@openclaw/voice-call 2026.9.4 → 2026.9.5
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/assets/activity.svg +3 -0
- package/assets/icon.png +0 -0
- package/dist/{cli-BGdihqyA.js → .setup/cli-z1onSLj4.mjs} +7 -7
- package/dist/{config-DQwvsxeV.js → .setup/config-72FnMWHb.mjs} +3 -3
- package/dist/{guarded-json-api-3Jy2k-eX.js → .setup/guarded-json-api-CuLkeTrl.mjs} +17 -39
- package/dist/{mock-C57qj18W.js → .setup/mock-CcYEAUhV.mjs} +1 -1
- package/dist/{plivo-BsdFT1gS.js → .setup/plivo-DWYNkAQ3.mjs} +2 -2
- package/dist/{realtime-handler-C7N4qzvf.js → .setup/realtime-handler-CaoetLrM.mjs} +284 -135
- package/dist/{response-generator-DsdC88Xg.js → .setup/response-generator-DB1nElLO.mjs} +2 -2
- package/dist/{runtime-entry-Ln4SWaYK.js → .setup/runtime-entry-YWSSnAsH.mjs} +457 -291
- package/dist/{store-path-M0GXxUfv.js → .setup/store-path-B1j1up4_.mjs} +91 -55
- package/dist/{telnyx-eCxGOUfA.js → .setup/telnyx-BY3ef4Cc.mjs} +1 -1
- package/dist/{twilio-DQKhnXXE.js → .setup/twilio-DWZ4HVmF.mjs} +9 -23
- package/dist/doctor-contract-api.js +14 -33
- package/dist/index.js +3 -3
- package/dist/runtime-entry.js +1 -1
- package/node_modules/typebox/build/compile/validator.d.mts +1 -1
- package/node_modules/typebox/build/compile/validator.mjs +1 -1
- package/node_modules/typebox/build/format/idna/idn-hostname.mjs +7 -5
- package/node_modules/typebox/build/format/iri.mjs +5 -1
- package/node_modules/typebox/build/guard/emit.mjs +2 -4
- package/node_modules/typebox/build/guard/guard.mjs +6 -18
- package/node_modules/typebox/build/guard/string.mjs +16 -24
- package/node_modules/typebox/build/schema/build.mjs +2 -2
- package/node_modules/typebox/build/schema/check.mjs +1 -1
- package/node_modules/typebox/build/schema/compile.d.mts +3 -2
- package/node_modules/typebox/build/schema/compile.mjs +8 -8
- package/node_modules/typebox/build/schema/engine/_context.d.mts +6 -7
- package/node_modules/typebox/build/schema/engine/_context.mjs +23 -15
- package/node_modules/typebox/build/schema/engine/_functions.d.mts +2 -2
- package/node_modules/typebox/build/schema/engine/_functions.mjs +1 -1
- package/node_modules/typebox/build/schema/engine/_reducer.d.mts +3 -3
- package/node_modules/typebox/build/schema/engine/_refine.d.mts +5 -5
- package/node_modules/typebox/build/schema/engine/_refine.mjs +4 -7
- package/node_modules/typebox/build/schema/engine/_stack.d.mts +34 -16
- package/node_modules/typebox/build/schema/engine/_stack.mjs +148 -104
- package/node_modules/typebox/build/schema/engine/additionalItems.d.mts +4 -4
- package/node_modules/typebox/build/schema/engine/additionalProperties.d.mts +8 -8
- package/node_modules/typebox/build/schema/engine/additionalProperties.mjs +26 -18
- package/node_modules/typebox/build/schema/engine/allOf.d.mts +4 -4
- package/node_modules/typebox/build/schema/engine/allOf.mjs +3 -3
- package/node_modules/typebox/build/schema/engine/anyOf.d.mts +4 -4
- package/node_modules/typebox/build/schema/engine/anyOf.mjs +5 -10
- package/node_modules/typebox/build/schema/engine/boolean.d.mts +4 -4
- package/node_modules/typebox/build/schema/engine/boolean.mjs +2 -6
- package/node_modules/typebox/build/schema/engine/const.d.mts +4 -4
- package/node_modules/typebox/build/schema/engine/const.mjs +2 -6
- package/node_modules/typebox/build/schema/engine/contains.d.mts +4 -4
- package/node_modules/typebox/build/schema/engine/contains.mjs +2 -6
- package/node_modules/typebox/build/schema/engine/dependencies.d.mts +4 -4
- package/node_modules/typebox/build/schema/engine/dependencies.mjs +3 -6
- package/node_modules/typebox/build/schema/engine/dependentRequired.d.mts +4 -4
- package/node_modules/typebox/build/schema/engine/dependentRequired.mjs +2 -6
- package/node_modules/typebox/build/schema/engine/dependentSchemas.d.mts +4 -4
- package/node_modules/typebox/build/schema/engine/dynamicRef.d.mts +4 -4
- package/node_modules/typebox/build/schema/engine/dynamicRef.mjs +11 -7
- package/node_modules/typebox/build/schema/engine/enum.d.mts +4 -4
- package/node_modules/typebox/build/schema/engine/enum.mjs +2 -6
- package/node_modules/typebox/build/schema/engine/exclusiveMaximum.d.mts +4 -4
- package/node_modules/typebox/build/schema/engine/exclusiveMaximum.mjs +2 -6
- package/node_modules/typebox/build/schema/engine/exclusiveMinimum.d.mts +4 -4
- package/node_modules/typebox/build/schema/engine/exclusiveMinimum.mjs +2 -6
- package/node_modules/typebox/build/schema/engine/format.d.mts +4 -4
- package/node_modules/typebox/build/schema/engine/format.mjs +2 -6
- package/node_modules/typebox/build/schema/engine/if.d.mts +4 -4
- package/node_modules/typebox/build/schema/engine/if.mjs +7 -15
- package/node_modules/typebox/build/schema/engine/items.d.mts +4 -4
- package/node_modules/typebox/build/schema/engine/items.mjs +1 -1
- package/node_modules/typebox/build/schema/engine/maxContains.d.mts +4 -4
- package/node_modules/typebox/build/schema/engine/maxContains.mjs +2 -6
- package/node_modules/typebox/build/schema/engine/maxItems.d.mts +4 -4
- package/node_modules/typebox/build/schema/engine/maxItems.mjs +2 -6
- package/node_modules/typebox/build/schema/engine/maxLength.d.mts +4 -4
- package/node_modules/typebox/build/schema/engine/maxLength.mjs +2 -6
- package/node_modules/typebox/build/schema/engine/maxProperties.d.mts +4 -4
- package/node_modules/typebox/build/schema/engine/maxProperties.mjs +2 -6
- package/node_modules/typebox/build/schema/engine/maximum.d.mts +4 -4
- package/node_modules/typebox/build/schema/engine/maximum.mjs +2 -6
- package/node_modules/typebox/build/schema/engine/minContains.d.mts +4 -4
- package/node_modules/typebox/build/schema/engine/minContains.mjs +2 -6
- package/node_modules/typebox/build/schema/engine/minItems.d.mts +5 -5
- package/node_modules/typebox/build/schema/engine/minItems.mjs +2 -6
- package/node_modules/typebox/build/schema/engine/minLength.d.mts +4 -4
- package/node_modules/typebox/build/schema/engine/minLength.mjs +2 -6
- package/node_modules/typebox/build/schema/engine/minProperties.d.mts +4 -4
- package/node_modules/typebox/build/schema/engine/minProperties.mjs +2 -6
- package/node_modules/typebox/build/schema/engine/minimum.d.mts +4 -4
- package/node_modules/typebox/build/schema/engine/minimum.mjs +2 -6
- package/node_modules/typebox/build/schema/engine/multipleOf.d.mts +4 -4
- package/node_modules/typebox/build/schema/engine/multipleOf.mjs +2 -6
- package/node_modules/typebox/build/schema/engine/not.d.mts +4 -4
- package/node_modules/typebox/build/schema/engine/not.mjs +4 -8
- package/node_modules/typebox/build/schema/engine/oneOf.d.mts +4 -4
- package/node_modules/typebox/build/schema/engine/oneOf.mjs +6 -11
- package/node_modules/typebox/build/schema/engine/pattern.d.mts +4 -4
- package/node_modules/typebox/build/schema/engine/pattern.mjs +3 -7
- package/node_modules/typebox/build/schema/engine/patternProperties.d.mts +4 -4
- package/node_modules/typebox/build/schema/engine/patternProperties.mjs +1 -1
- package/node_modules/typebox/build/schema/engine/prefixItems.d.mts +4 -4
- package/node_modules/typebox/build/schema/engine/prefixItems.mjs +1 -1
- package/node_modules/typebox/build/schema/engine/properties.d.mts +4 -4
- package/node_modules/typebox/build/schema/engine/properties.mjs +1 -1
- package/node_modules/typebox/build/schema/engine/propertyNames.d.mts +4 -4
- package/node_modules/typebox/build/schema/engine/propertyNames.mjs +4 -10
- package/node_modules/typebox/build/schema/engine/recursiveRef.d.mts +4 -4
- package/node_modules/typebox/build/schema/engine/recursiveRef.mjs +11 -7
- package/node_modules/typebox/build/schema/engine/ref.d.mts +4 -4
- package/node_modules/typebox/build/schema/engine/ref.mjs +19 -15
- package/node_modules/typebox/build/schema/engine/required.d.mts +4 -4
- package/node_modules/typebox/build/schema/engine/required.mjs +2 -6
- package/node_modules/typebox/build/schema/engine/schema.d.mts +7 -7
- package/node_modules/typebox/build/schema/engine/schema.mjs +137 -133
- package/node_modules/typebox/build/schema/engine/type.d.mts +4 -4
- package/node_modules/typebox/build/schema/engine/type.mjs +2 -6
- package/node_modules/typebox/build/schema/engine/unevaluatedItems.d.mts +4 -4
- package/node_modules/typebox/build/schema/engine/unevaluatedItems.mjs +5 -9
- package/node_modules/typebox/build/schema/engine/unevaluatedProperties.d.mts +4 -4
- package/node_modules/typebox/build/schema/engine/unevaluatedProperties.mjs +5 -9
- package/node_modules/typebox/build/schema/engine/uniqueItems.d.mts +4 -4
- package/node_modules/typebox/build/schema/engine/uniqueItems.mjs +2 -6
- package/node_modules/typebox/build/schema/errors.d.mts +2 -2
- package/node_modules/typebox/build/schema/errors.mjs +8 -14
- package/node_modules/typebox/build/schema/intern/index.d.mts +1 -0
- package/node_modules/typebox/build/schema/intern/index.mjs +1 -0
- package/node_modules/typebox/build/schema/intern/intern.d.mts +11 -0
- package/node_modules/typebox/build/schema/intern/intern.mjs +293 -0
- package/node_modules/typebox/build/schema/meta/draft_2019_09.d.mts +2 -0
- package/node_modules/typebox/build/schema/meta/draft_2019_09.mjs +288 -0
- package/node_modules/typebox/build/schema/meta/draft_2020_12.d.mts +2 -0
- package/node_modules/typebox/build/schema/meta/draft_2020_12.mjs +300 -0
- package/node_modules/typebox/build/schema/meta/draft_3.d.mts +2 -0
- package/node_modules/typebox/build/schema/meta/draft_3.mjs +143 -0
- package/node_modules/typebox/build/schema/meta/draft_4.d.mts +2 -0
- package/node_modules/typebox/build/schema/meta/draft_4.mjs +149 -0
- package/node_modules/typebox/build/schema/meta/draft_6.d.mts +2 -0
- package/node_modules/typebox/build/schema/meta/draft_6.mjs +155 -0
- package/node_modules/typebox/build/schema/meta/draft_7.d.mts +2 -0
- package/node_modules/typebox/build/schema/meta/draft_7.mjs +172 -0
- package/node_modules/typebox/build/schema/meta/index.d.mts +2 -0
- package/node_modules/typebox/build/schema/meta/index.mjs +2 -0
- package/node_modules/typebox/build/schema/meta/meta.d.mts +9 -0
- package/node_modules/typebox/build/schema/meta/meta.mjs +15 -0
- package/node_modules/typebox/build/schema/meta/schema.d.mts +6 -0
- package/node_modules/typebox/build/schema/meta/schema.mjs +1 -0
- package/node_modules/typebox/build/schema/parse.d.mts +1 -0
- package/node_modules/typebox/build/schema/parse.mjs +10 -5
- package/node_modules/typebox/build/schema/resolve/resolve.d.mts +8 -3
- package/node_modules/typebox/build/schema/resolve/resolve.mjs +268 -139
- package/node_modules/typebox/build/schema/schema.d.mts +2 -0
- package/node_modules/typebox/build/schema/schema.mjs +2 -0
- package/node_modules/typebox/build/value/errors/errors.d.mts +2 -12
- package/node_modules/typebox/build/value/errors/errors.mjs +2 -7
- package/node_modules/typebox/package.json +1 -1
- package/node_modules/typebox/readme.md +59 -89
- package/node_modules/zod/README.md +27 -0
- package/node_modules/zod/compile.cjs +77 -0
- package/node_modules/zod/compile.d.cts +1 -0
- package/node_modules/zod/compile.d.ts +1 -0
- package/node_modules/zod/compile.js +52 -0
- package/node_modules/zod/index.cjs +2 -2
- package/node_modules/zod/index.d.cts +1 -2
- package/node_modules/zod/index.d.ts +1 -2
- package/node_modules/zod/index.js +5 -2
- package/node_modules/zod/package.json +13 -2
- package/node_modules/zod/src/compile.ts +56 -0
- package/node_modules/zod/src/index.ts +5 -2
- package/node_modules/zod/src/v3/ZodError.ts +22 -12
- package/node_modules/zod/src/v3/tests/error.test.ts +35 -0
- package/node_modules/zod/src/v3/tests/intersection.test.ts +18 -0
- package/node_modules/zod/src/v3/tests/language-server.test.ts +1 -2
- package/node_modules/zod/src/v3/tests/object.test.ts +3 -6
- package/node_modules/zod/src/v3/tests/readonly.test.ts +0 -80
- package/node_modules/zod/src/v3/tests/string.test.ts +6 -0
- package/node_modules/zod/src/v3/types.ts +5 -5
- package/node_modules/zod/src/v4/classic/checks.ts +1 -0
- package/node_modules/zod/src/v4/classic/compat.ts +26 -18
- package/node_modules/zod/src/v4/classic/deep-partial.ts +76 -0
- package/node_modules/zod/src/v4/classic/errors.ts +59 -44
- package/node_modules/zod/src/v4/classic/external.ts +12 -9
- package/node_modules/zod/src/v4/classic/from-json-schema.ts +140 -78
- package/node_modules/zod/src/v4/classic/in-out.ts +45 -0
- package/node_modules/zod/src/v4/classic/index.ts +2 -2
- package/node_modules/zod/src/v4/classic/iso.ts +2 -72
- package/node_modules/zod/src/v4/classic/parse.ts +10 -4
- package/node_modules/zod/src/v4/classic/schemas.ts +452 -262
- package/node_modules/zod/src/v4/classic/tests/apply.test.ts +27 -0
- package/node_modules/zod/src/v4/classic/tests/array.test.ts +2 -2
- package/node_modules/zod/src/v4/classic/tests/assignability.test.ts +135 -0
- package/node_modules/zod/src/v4/classic/tests/bigint.test.ts +30 -1
- package/node_modules/zod/src/v4/classic/tests/catch.test.ts +278 -0
- package/node_modules/zod/src/v4/classic/tests/codec-examples.test.ts +1 -2
- package/node_modules/zod/src/v4/classic/tests/codec.test.ts +2 -1
- package/node_modules/zod/src/v4/classic/tests/continuability.test.ts +2 -2
- package/node_modules/zod/src/v4/classic/tests/credit-card.test.ts +76 -0
- package/node_modules/zod/src/v4/classic/tests/cyclic-data.test.ts +720 -0
- package/node_modules/zod/src/v4/classic/tests/date.test.ts +30 -0
- package/node_modules/zod/src/v4/classic/tests/datetime.test.ts +32 -18
- package/node_modules/zod/src/v4/classic/tests/deep-partial.test.ts +380 -0
- package/node_modules/zod/src/v4/classic/tests/default-locale.test.ts +32 -0
- package/node_modules/zod/src/v4/classic/tests/default.test.ts +46 -0
- package/node_modules/zod/src/v4/classic/tests/detached-methods.test.ts +31 -7
- package/node_modules/zod/src/v4/classic/tests/discriminated-unions.test.ts +155 -13
- package/node_modules/zod/src/v4/classic/tests/enum.test.ts +11 -0
- package/node_modules/zod/src/v4/classic/tests/error-utils.test.ts +112 -2
- package/node_modules/zod/src/v4/classic/tests/error.test.ts +274 -6
- package/node_modules/zod/src/v4/classic/tests/from-json-schema.test.ts +425 -10
- package/node_modules/zod/src/v4/classic/tests/function.test.ts +31 -0
- package/node_modules/zod/src/v4/classic/tests/global-config.test.ts +2 -9
- package/node_modules/zod/src/v4/classic/tests/hash.test.ts +1 -2
- package/node_modules/zod/src/v4/classic/tests/in-out.test.ts +159 -0
- package/node_modules/zod/src/v4/classic/tests/index.test.ts +21 -2
- package/node_modules/zod/src/v4/classic/tests/instance-footprint.test.ts +281 -0
- package/node_modules/zod/src/v4/classic/tests/instanceof.test.ts +47 -0
- package/node_modules/zod/src/v4/classic/tests/intersection.test.ts +136 -0
- package/node_modules/zod/src/v4/classic/tests/issue-schema.test.ts +183 -0
- package/node_modules/zod/src/v4/classic/tests/jitless-allows-eval.test.ts +3 -10
- package/node_modules/zod/src/v4/classic/tests/lazy.test.ts +36 -1
- package/node_modules/zod/src/v4/classic/tests/literal.test.ts +12 -1
- package/node_modules/zod/src/v4/classic/tests/map.test.ts +12 -0
- package/node_modules/zod/src/v4/classic/tests/number.test.ts +46 -9
- package/node_modules/zod/src/v4/classic/tests/object.test.ts +245 -12
- package/node_modules/zod/src/v4/classic/tests/optin-ladder.test.ts +234 -0
- package/node_modules/zod/src/v4/classic/tests/optional.test.ts +49 -16
- package/node_modules/zod/src/v4/classic/tests/partial.test.ts +51 -4
- package/node_modules/zod/src/v4/classic/tests/preprocess-types.test.ts +20 -2
- package/node_modules/zod/src/v4/classic/tests/readonly.test.ts +0 -68
- package/node_modules/zod/src/v4/classic/tests/record.test.ts +186 -18
- package/node_modules/zod/src/v4/classic/tests/recursive-types.test.ts +33 -2
- package/node_modules/zod/src/v4/classic/tests/redos.test.ts +68 -0
- package/node_modules/zod/src/v4/classic/tests/refine.test.ts +60 -0
- package/node_modules/zod/src/v4/classic/tests/set.test.ts +9 -0
- package/node_modules/zod/src/v4/classic/tests/string.test.ts +127 -5
- package/node_modules/zod/src/v4/classic/tests/stringbool.test.ts +18 -0
- package/node_modules/zod/src/v4/classic/tests/template-literal.test.ts +11 -2
- package/node_modules/zod/src/v4/classic/tests/to-json-schema.test.ts +1585 -173
- package/node_modules/zod/src/v4/classic/tests/tuple.test.ts +45 -30
- package/node_modules/zod/src/v4/classic/tests/union.test.ts +39 -2
- package/node_modules/zod/src/v4/classic/tests/validate.test.ts +76 -0
- package/node_modules/zod/src/v4/classic/tests/validations.test.ts +2 -2
- package/node_modules/zod/src/v4/core/api.ts +48 -12
- package/node_modules/zod/src/v4/core/checks.ts +57 -44
- package/node_modules/zod/src/v4/core/compile.ts +2188 -0
- package/node_modules/zod/src/v4/core/core.ts +98 -19
- package/node_modules/zod/src/v4/core/doc.ts +11 -7
- package/node_modules/zod/src/v4/core/errors.ts +115 -24
- package/node_modules/zod/src/v4/core/index.ts +3 -0
- package/node_modules/zod/src/v4/core/json-schema-generator.ts +6 -1
- package/node_modules/zod/src/v4/core/json-schema-processors.ts +257 -93
- package/node_modules/zod/src/v4/core/json-schema.ts +2 -1
- package/node_modules/zod/src/v4/core/memoizer.ts +284 -0
- package/node_modules/zod/src/v4/core/parse.ts +131 -38
- package/node_modules/zod/src/v4/core/regexes.ts +30 -13
- package/node_modules/zod/src/v4/core/registries.ts +2 -2
- package/node_modules/zod/src/v4/core/schemas.ts +759 -461
- package/node_modules/zod/src/v4/core/tests/compile-differential.test.ts +969 -0
- package/node_modules/zod/src/v4/core/tests/compile-global.test.ts +89 -0
- package/node_modules/zod/src/v4/core/tests/compile-off-by-default.test.ts +26 -0
- package/node_modules/zod/src/v4/core/tests/compile-stats.test.ts +34 -0
- package/node_modules/zod/src/v4/core/tests/compile.test.ts +1639 -0
- package/node_modules/zod/src/v4/core/tests/locales/el.test.ts +1 -2
- package/node_modules/zod/src/v4/core/tests/locales/es.test.ts +1 -2
- package/node_modules/zod/src/v4/core/tests/locales/fr.test.ts +3 -3
- package/node_modules/zod/src/v4/core/tests/locales/parity.test.ts +42 -0
- package/node_modules/zod/src/v4/core/tests/locales/tk.test.ts +69 -0
- package/node_modules/zod/src/v4/core/tests/treeshake.test.ts +51 -0
- package/node_modules/zod/src/v4/core/tests/url-no-canparse.test.ts +31 -0
- package/node_modules/zod/src/v4/core/to-json-schema.ts +275 -42
- package/node_modules/zod/src/v4/core/util.ts +268 -42
- package/node_modules/zod/src/v4/core/versions.ts +2 -2
- package/node_modules/zod/src/v4/core/visit.ts +193 -0
- package/node_modules/zod/src/v4/index.ts +3 -3
- package/node_modules/zod/src/v4/locales/ar.ts +3 -0
- package/node_modules/zod/src/v4/locales/az.ts +3 -0
- package/node_modules/zod/src/v4/locales/be.ts +10 -0
- package/node_modules/zod/src/v4/locales/bg.ts +3 -0
- package/node_modules/zod/src/v4/locales/bn.ts +121 -0
- package/node_modules/zod/src/v4/locales/ca.ts +3 -0
- package/node_modules/zod/src/v4/locales/ckb.ts +138 -0
- package/node_modules/zod/src/v4/locales/cs.ts +3 -0
- package/node_modules/zod/src/v4/locales/da.ts +5 -2
- package/node_modules/zod/src/v4/locales/de.ts +3 -0
- package/node_modules/zod/src/v4/locales/el.ts +1 -0
- package/node_modules/zod/src/v4/locales/en.ts +15 -4
- package/node_modules/zod/src/v4/locales/eo.ts +3 -0
- package/node_modules/zod/src/v4/locales/es.ts +2 -0
- package/node_modules/zod/src/v4/locales/fa.ts +3 -0
- package/node_modules/zod/src/v4/locales/fi.ts +3 -0
- package/node_modules/zod/src/v4/locales/fr-CA.ts +3 -0
- package/node_modules/zod/src/v4/locales/fr.ts +19 -14
- package/node_modules/zod/src/v4/locales/gu.ts +121 -0
- package/node_modules/zod/src/v4/locales/he.ts +6 -1
- package/node_modules/zod/src/v4/locales/hi.ts +124 -0
- package/node_modules/zod/src/v4/locales/hr.ts +2 -0
- package/node_modules/zod/src/v4/locales/hu.ts +3 -0
- package/node_modules/zod/src/v4/locales/hy.ts +9 -0
- package/node_modules/zod/src/v4/locales/id.ts +3 -0
- package/node_modules/zod/src/v4/locales/index.ts +10 -0
- package/node_modules/zod/src/v4/locales/is.ts +3 -0
- package/node_modules/zod/src/v4/locales/it.ts +3 -0
- package/node_modules/zod/src/v4/locales/ja.ts +3 -0
- package/node_modules/zod/src/v4/locales/ka.ts +3 -0
- package/node_modules/zod/src/v4/locales/km.ts +3 -0
- package/node_modules/zod/src/v4/locales/kn.ts +124 -0
- package/node_modules/zod/src/v4/locales/ko.ts +3 -0
- package/node_modules/zod/src/v4/locales/lt.ts +2 -0
- package/node_modules/zod/src/v4/locales/mk.ts +3 -0
- package/node_modules/zod/src/v4/locales/ms.ts +3 -0
- package/node_modules/zod/src/v4/locales/ne.ts +126 -0
- package/node_modules/zod/src/v4/locales/nl.ts +3 -0
- package/node_modules/zod/src/v4/locales/nn.ts +119 -0
- package/node_modules/zod/src/v4/locales/no.ts +5 -2
- package/node_modules/zod/src/v4/locales/ota.ts +3 -0
- package/node_modules/zod/src/v4/locales/pl.ts +3 -0
- package/node_modules/zod/src/v4/locales/ps.ts +3 -0
- package/node_modules/zod/src/v4/locales/pt-BR.ts +159 -0
- package/node_modules/zod/src/v4/locales/pt.ts +99 -58
- package/node_modules/zod/src/v4/locales/ro.ts +1 -0
- package/node_modules/zod/src/v4/locales/ru.ts +10 -0
- package/node_modules/zod/src/v4/locales/sk.ts +121 -0
- package/node_modules/zod/src/v4/locales/sl.ts +3 -0
- package/node_modules/zod/src/v4/locales/sv.ts +5 -2
- package/node_modules/zod/src/v4/locales/ta.ts +3 -0
- package/node_modules/zod/src/v4/locales/th.ts +3 -0
- package/node_modules/zod/src/v4/locales/tk.ts +111 -0
- package/node_modules/zod/src/v4/locales/tr.ts +3 -0
- package/node_modules/zod/src/v4/locales/uk.ts +3 -0
- package/node_modules/zod/src/v4/locales/ur.ts +3 -0
- package/node_modules/zod/src/v4/locales/uz.ts +1 -0
- package/node_modules/zod/src/v4/locales/vi.ts +3 -0
- package/node_modules/zod/src/v4/locales/yo.ts +3 -0
- package/node_modules/zod/src/v4/locales/zh-CN.ts +3 -0
- package/node_modules/zod/src/v4/locales/zh-TW.ts +3 -0
- package/node_modules/zod/src/v4/mini/checks.ts +1 -0
- package/node_modules/zod/src/v4/mini/deep-partial.ts +73 -0
- package/node_modules/zod/src/v4/mini/external.ts +10 -1
- package/node_modules/zod/src/v4/mini/in-out.ts +45 -0
- package/node_modules/zod/src/v4/mini/parse.ts +2 -0
- package/node_modules/zod/src/v4/mini/schemas.ts +135 -56
- package/node_modules/zod/src/v4/mini/tests/apply.test.ts +33 -0
- package/node_modules/zod/src/v4/mini/tests/assignability.test.ts +62 -1
- package/node_modules/zod/src/v4/mini/tests/checks.test.ts +14 -0
- package/node_modules/zod/src/v4/mini/tests/codec.test.ts +35 -1
- package/node_modules/zod/src/v4/mini/tests/cyclic-data.test.ts +84 -0
- package/node_modules/zod/src/v4/mini/tests/deep-partial.test.ts +54 -0
- package/node_modules/zod/src/v4/mini/tests/error.test.ts +23 -4
- package/node_modules/zod/src/v4/mini/tests/functions.test.ts +9 -0
- package/node_modules/zod/src/v4/mini/tests/index.test.ts +72 -5
- package/node_modules/zod/src/v4/mini/tests/number.test.ts +14 -0
- package/node_modules/zod/src/v4/mini/tests/object.test.ts +65 -0
- package/node_modules/zod/src/v4/mini/tests/string.test.ts +21 -0
- package/node_modules/zod/v3/ZodError.cjs +22 -12
- package/node_modules/zod/v3/ZodError.d.cts +1 -1
- package/node_modules/zod/v3/ZodError.d.ts +1 -1
- package/node_modules/zod/v3/ZodError.js +22 -12
- package/node_modules/zod/v3/types.cjs +7 -5
- package/node_modules/zod/v3/types.js +7 -5
- package/node_modules/zod/v4/classic/checks.cjs +2 -1
- package/node_modules/zod/v4/classic/checks.d.cts +1 -1
- package/node_modules/zod/v4/classic/checks.d.ts +1 -1
- package/node_modules/zod/v4/classic/checks.js +1 -1
- package/node_modules/zod/v4/classic/compat.d.cts +9 -11
- package/node_modules/zod/v4/classic/compat.d.ts +9 -11
- package/node_modules/zod/v4/classic/deep-partial.cjs +39 -0
- package/node_modules/zod/v4/classic/deep-partial.d.cts +14 -0
- package/node_modules/zod/v4/classic/deep-partial.d.ts +14 -0
- package/node_modules/zod/v4/classic/deep-partial.js +13 -0
- package/node_modules/zod/v4/classic/errors.cjs +43 -34
- package/node_modules/zod/v4/classic/errors.d.cts +3 -4
- package/node_modules/zod/v4/classic/errors.d.ts +3 -4
- package/node_modules/zod/v4/classic/errors.js +43 -34
- package/node_modules/zod/v4/classic/external.cjs +30 -27
- package/node_modules/zod/v4/classic/external.d.cts +5 -2
- package/node_modules/zod/v4/classic/external.d.ts +5 -2
- package/node_modules/zod/v4/classic/external.js +5 -8
- package/node_modules/zod/v4/classic/from-json-schema.cjs +136 -75
- package/node_modules/zod/v4/classic/from-json-schema.js +136 -75
- package/node_modules/zod/v4/classic/in-out.cjs +63 -0
- package/node_modules/zod/v4/classic/in-out.d.cts +8 -0
- package/node_modules/zod/v4/classic/in-out.d.ts +8 -0
- package/node_modules/zod/v4/classic/in-out.js +36 -0
- package/node_modules/zod/v4/classic/index.cjs +2 -2
- package/node_modules/zod/v4/classic/index.d.cts +1 -2
- package/node_modules/zod/v4/classic/index.d.ts +1 -2
- package/node_modules/zod/v4/classic/index.js +2 -2
- package/node_modules/zod/v4/classic/iso.cjs +11 -22
- package/node_modules/zod/v4/classic/iso.d.cts +2 -17
- package/node_modules/zod/v4/classic/iso.d.ts +2 -17
- package/node_modules/zod/v4/classic/iso.js +2 -17
- package/node_modules/zod/v4/classic/parse.cjs +4 -1
- package/node_modules/zod/v4/classic/parse.d.cts +17 -4
- package/node_modules/zod/v4/classic/parse.d.ts +17 -4
- package/node_modules/zod/v4/classic/parse.js +1 -0
- package/node_modules/zod/v4/classic/schemas.cjs +498 -398
- package/node_modules/zod/v4/classic/schemas.d.cts +53 -18
- package/node_modules/zod/v4/classic/schemas.d.ts +53 -18
- package/node_modules/zod/v4/classic/schemas.js +492 -396
- package/node_modules/zod/v4/core/api.cjs +23 -4
- package/node_modules/zod/v4/core/api.d.cts +13 -9
- package/node_modules/zod/v4/core/api.d.ts +13 -9
- package/node_modules/zod/v4/core/api.js +21 -4
- package/node_modules/zod/v4/core/checks.cjs +37 -31
- package/node_modules/zod/v4/core/checks.d.cts +13 -13
- package/node_modules/zod/v4/core/checks.d.ts +13 -13
- package/node_modules/zod/v4/core/checks.js +37 -31
- package/node_modules/zod/v4/core/compile.cjs +1813 -0
- package/node_modules/zod/v4/core/compile.d.cts +51 -0
- package/node_modules/zod/v4/core/compile.d.ts +51 -0
- package/node_modules/zod/v4/core/compile.js +1783 -0
- package/node_modules/zod/v4/core/core.cjs +81 -18
- package/node_modules/zod/v4/core/core.d.cts +16 -4
- package/node_modules/zod/v4/core/core.d.ts +16 -4
- package/node_modules/zod/v4/core/core.js +82 -19
- package/node_modules/zod/v4/core/doc.cjs +5 -7
- package/node_modules/zod/v4/core/doc.d.cts +3 -1
- package/node_modules/zod/v4/core/doc.d.ts +3 -1
- package/node_modules/zod/v4/core/doc.js +5 -7
- package/node_modules/zod/v4/core/errors.cjs +110 -25
- package/node_modules/zod/v4/core/errors.d.cts +4 -0
- package/node_modules/zod/v4/core/errors.d.ts +4 -0
- package/node_modules/zod/v4/core/errors.js +110 -25
- package/node_modules/zod/v4/core/index.cjs +5 -1
- package/node_modules/zod/v4/core/index.d.cts +3 -0
- package/node_modules/zod/v4/core/index.d.ts +3 -0
- package/node_modules/zod/v4/core/index.js +3 -0
- package/node_modules/zod/v4/core/json-schema-generator.cjs +4 -0
- package/node_modules/zod/v4/core/json-schema-generator.d.cts +2 -2
- package/node_modules/zod/v4/core/json-schema-generator.d.ts +2 -2
- package/node_modules/zod/v4/core/json-schema-generator.js +4 -0
- package/node_modules/zod/v4/core/json-schema-processors.cjs +264 -95
- package/node_modules/zod/v4/core/json-schema-processors.js +243 -97
- package/node_modules/zod/v4/core/json-schema.d.cts +2 -1
- package/node_modules/zod/v4/core/json-schema.d.ts +2 -1
- package/node_modules/zod/v4/core/memoizer.cjs +272 -0
- package/node_modules/zod/v4/core/memoizer.d.cts +15 -0
- package/node_modules/zod/v4/core/memoizer.d.ts +15 -0
- package/node_modules/zod/v4/core/memoizer.js +265 -0
- package/node_modules/zod/v4/core/parse.cjs +96 -34
- package/node_modules/zod/v4/core/parse.d.cts +14 -11
- package/node_modules/zod/v4/core/parse.d.ts +14 -11
- package/node_modules/zod/v4/core/parse.js +94 -33
- package/node_modules/zod/v4/core/regexes.cjs +27 -15
- package/node_modules/zod/v4/core/regexes.d.cts +2 -0
- package/node_modules/zod/v4/core/regexes.d.ts +2 -0
- package/node_modules/zod/v4/core/regexes.js +24 -13
- package/node_modules/zod/v4/core/registries.js +2 -2
- package/node_modules/zod/v4/core/schemas.cjs +537 -326
- package/node_modules/zod/v4/core/schemas.d.cts +100 -31
- package/node_modules/zod/v4/core/schemas.d.ts +100 -31
- package/node_modules/zod/v4/core/schemas.js +526 -325
- package/node_modules/zod/v4/core/to-json-schema.cjs +242 -39
- package/node_modules/zod/v4/core/to-json-schema.d.cts +42 -3
- package/node_modules/zod/v4/core/to-json-schema.d.ts +42 -3
- package/node_modules/zod/v4/core/to-json-schema.js +241 -39
- package/node_modules/zod/v4/core/util.cjs +212 -31
- package/node_modules/zod/v4/core/util.d.cts +58 -1
- package/node_modules/zod/v4/core/util.d.ts +58 -1
- package/node_modules/zod/v4/core/util.js +202 -30
- package/node_modules/zod/v4/core/versions.cjs +2 -2
- package/node_modules/zod/v4/core/versions.d.cts +1 -1
- package/node_modules/zod/v4/core/versions.d.ts +1 -1
- package/node_modules/zod/v4/core/versions.js +2 -2
- package/node_modules/zod/v4/core/visit.cjs +195 -0
- package/node_modules/zod/v4/core/visit.d.cts +30 -0
- package/node_modules/zod/v4/core/visit.d.ts +30 -0
- package/node_modules/zod/v4/core/visit.js +169 -0
- package/node_modules/zod/v4/index.cjs +15 -5
- package/node_modules/zod/v4/index.d.cts +2 -2
- package/node_modules/zod/v4/index.d.ts +2 -2
- package/node_modules/zod/v4/index.js +3 -2
- package/node_modules/zod/v4/locales/ar.cjs +3 -0
- package/node_modules/zod/v4/locales/ar.js +3 -0
- package/node_modules/zod/v4/locales/az.cjs +3 -0
- package/node_modules/zod/v4/locales/az.js +3 -0
- package/node_modules/zod/v4/locales/be.cjs +10 -0
- package/node_modules/zod/v4/locales/be.js +10 -0
- package/node_modules/zod/v4/locales/bg.cjs +3 -0
- package/node_modules/zod/v4/locales/bg.js +3 -0
- package/node_modules/zod/v4/locales/bn.cjs +138 -0
- package/node_modules/zod/v4/locales/bn.d.cts +5 -0
- package/node_modules/zod/v4/locales/bn.d.ts +4 -0
- package/node_modules/zod/v4/locales/bn.js +111 -0
- package/node_modules/zod/v4/locales/ca.cjs +3 -0
- package/node_modules/zod/v4/locales/ca.js +3 -0
- package/node_modules/zod/v4/locales/ckb.cjs +158 -0
- package/node_modules/zod/v4/locales/ckb.d.cts +5 -0
- package/node_modules/zod/v4/locales/ckb.d.ts +4 -0
- package/node_modules/zod/v4/locales/ckb.js +131 -0
- package/node_modules/zod/v4/locales/cs.cjs +3 -0
- package/node_modules/zod/v4/locales/cs.js +3 -0
- package/node_modules/zod/v4/locales/da.cjs +5 -2
- package/node_modules/zod/v4/locales/da.js +5 -2
- package/node_modules/zod/v4/locales/de.cjs +3 -0
- package/node_modules/zod/v4/locales/de.js +3 -0
- package/node_modules/zod/v4/locales/el.cjs +1 -0
- package/node_modules/zod/v4/locales/el.js +1 -0
- package/node_modules/zod/v4/locales/en.cjs +14 -4
- package/node_modules/zod/v4/locales/en.js +14 -4
- package/node_modules/zod/v4/locales/eo.cjs +3 -0
- package/node_modules/zod/v4/locales/eo.js +3 -0
- package/node_modules/zod/v4/locales/es.cjs +2 -0
- package/node_modules/zod/v4/locales/es.js +2 -0
- package/node_modules/zod/v4/locales/fa.cjs +3 -0
- package/node_modules/zod/v4/locales/fa.js +3 -0
- package/node_modules/zod/v4/locales/fi.cjs +3 -0
- package/node_modules/zod/v4/locales/fi.js +3 -0
- package/node_modules/zod/v4/locales/fr-CA.cjs +3 -0
- package/node_modules/zod/v4/locales/fr-CA.js +3 -0
- package/node_modules/zod/v4/locales/fr.cjs +16 -14
- package/node_modules/zod/v4/locales/fr.js +16 -14
- package/node_modules/zod/v4/locales/gu.cjs +138 -0
- package/node_modules/zod/v4/locales/gu.d.cts +5 -0
- package/node_modules/zod/v4/locales/gu.d.ts +4 -0
- package/node_modules/zod/v4/locales/gu.js +111 -0
- package/node_modules/zod/v4/locales/he.cjs +5 -0
- package/node_modules/zod/v4/locales/he.js +5 -0
- package/node_modules/zod/v4/locales/hi.cjs +136 -0
- package/node_modules/zod/v4/locales/hi.d.cts +5 -0
- package/node_modules/zod/v4/locales/hi.d.ts +4 -0
- package/node_modules/zod/v4/locales/hi.js +109 -0
- package/node_modules/zod/v4/locales/hr.cjs +2 -0
- package/node_modules/zod/v4/locales/hr.js +2 -0
- package/node_modules/zod/v4/locales/hu.cjs +3 -0
- package/node_modules/zod/v4/locales/hu.js +3 -0
- package/node_modules/zod/v4/locales/hy.cjs +9 -0
- package/node_modules/zod/v4/locales/hy.js +9 -0
- package/node_modules/zod/v4/locales/id.cjs +3 -0
- package/node_modules/zod/v4/locales/id.js +3 -0
- package/node_modules/zod/v4/locales/index.cjs +22 -2
- package/node_modules/zod/v4/locales/index.d.cts +10 -0
- package/node_modules/zod/v4/locales/index.d.ts +10 -0
- package/node_modules/zod/v4/locales/index.js +10 -0
- package/node_modules/zod/v4/locales/is.cjs +3 -0
- package/node_modules/zod/v4/locales/is.js +3 -0
- package/node_modules/zod/v4/locales/it.cjs +3 -0
- package/node_modules/zod/v4/locales/it.js +3 -0
- package/node_modules/zod/v4/locales/ja.cjs +3 -0
- package/node_modules/zod/v4/locales/ja.js +3 -0
- package/node_modules/zod/v4/locales/ka.cjs +3 -0
- package/node_modules/zod/v4/locales/ka.js +3 -0
- package/node_modules/zod/v4/locales/km.cjs +3 -0
- package/node_modules/zod/v4/locales/km.js +3 -0
- package/node_modules/zod/v4/locales/kn.cjs +141 -0
- package/node_modules/zod/v4/locales/kn.d.cts +5 -0
- package/node_modules/zod/v4/locales/kn.d.ts +4 -0
- package/node_modules/zod/v4/locales/kn.js +114 -0
- package/node_modules/zod/v4/locales/ko.cjs +3 -0
- package/node_modules/zod/v4/locales/ko.js +3 -0
- package/node_modules/zod/v4/locales/lt.cjs +2 -0
- package/node_modules/zod/v4/locales/lt.js +2 -0
- package/node_modules/zod/v4/locales/mk.cjs +3 -0
- package/node_modules/zod/v4/locales/mk.js +3 -0
- package/node_modules/zod/v4/locales/ms.cjs +3 -0
- package/node_modules/zod/v4/locales/ms.js +3 -0
- package/node_modules/zod/v4/locales/ne.cjs +136 -0
- package/node_modules/zod/v4/locales/ne.d.cts +5 -0
- package/node_modules/zod/v4/locales/ne.d.ts +4 -0
- package/node_modules/zod/v4/locales/ne.js +109 -0
- package/node_modules/zod/v4/locales/nl.cjs +3 -0
- package/node_modules/zod/v4/locales/nl.js +3 -0
- package/node_modules/zod/v4/locales/nn.cjs +138 -0
- package/node_modules/zod/v4/locales/nn.d.cts +5 -0
- package/node_modules/zod/v4/locales/nn.d.ts +4 -0
- package/node_modules/zod/v4/locales/nn.js +111 -0
- package/node_modules/zod/v4/locales/no.cjs +5 -2
- package/node_modules/zod/v4/locales/no.js +5 -2
- package/node_modules/zod/v4/locales/ota.cjs +3 -0
- package/node_modules/zod/v4/locales/ota.js +3 -0
- package/node_modules/zod/v4/locales/pl.cjs +3 -0
- package/node_modules/zod/v4/locales/pl.js +3 -0
- package/node_modules/zod/v4/locales/ps.cjs +3 -0
- package/node_modules/zod/v4/locales/ps.js +3 -0
- package/node_modules/zod/v4/locales/pt-BR.cjs +168 -0
- package/node_modules/zod/v4/locales/pt-BR.d.cts +5 -0
- package/node_modules/zod/v4/locales/pt-BR.d.ts +4 -0
- package/node_modules/zod/v4/locales/pt-BR.js +141 -0
- package/node_modules/zod/v4/locales/pt.cjs +87 -55
- package/node_modules/zod/v4/locales/pt.js +87 -55
- package/node_modules/zod/v4/locales/ro.cjs +1 -0
- package/node_modules/zod/v4/locales/ro.js +1 -0
- package/node_modules/zod/v4/locales/ru.cjs +10 -0
- package/node_modules/zod/v4/locales/ru.js +10 -0
- package/node_modules/zod/v4/locales/sk.cjs +141 -0
- package/node_modules/zod/v4/locales/sk.d.cts +5 -0
- package/node_modules/zod/v4/locales/sk.d.ts +4 -0
- package/node_modules/zod/v4/locales/sk.js +114 -0
- package/node_modules/zod/v4/locales/sl.cjs +3 -0
- package/node_modules/zod/v4/locales/sl.js +3 -0
- package/node_modules/zod/v4/locales/sv.cjs +5 -2
- package/node_modules/zod/v4/locales/sv.js +5 -2
- package/node_modules/zod/v4/locales/ta.cjs +3 -0
- package/node_modules/zod/v4/locales/ta.js +3 -0
- package/node_modules/zod/v4/locales/th.cjs +3 -0
- package/node_modules/zod/v4/locales/th.js +3 -0
- package/node_modules/zod/v4/locales/tk.cjs +132 -0
- package/node_modules/zod/v4/locales/tk.d.cts +5 -0
- package/node_modules/zod/v4/locales/tk.d.ts +4 -0
- package/node_modules/zod/v4/locales/tk.js +105 -0
- package/node_modules/zod/v4/locales/tr.cjs +3 -0
- package/node_modules/zod/v4/locales/tr.js +3 -0
- package/node_modules/zod/v4/locales/uk.cjs +3 -0
- package/node_modules/zod/v4/locales/uk.js +3 -0
- package/node_modules/zod/v4/locales/ur.cjs +3 -0
- package/node_modules/zod/v4/locales/ur.js +3 -0
- package/node_modules/zod/v4/locales/uz.cjs +1 -0
- package/node_modules/zod/v4/locales/uz.js +1 -0
- package/node_modules/zod/v4/locales/vi.cjs +3 -0
- package/node_modules/zod/v4/locales/vi.js +3 -0
- package/node_modules/zod/v4/locales/yo.cjs +3 -0
- package/node_modules/zod/v4/locales/yo.js +3 -0
- package/node_modules/zod/v4/locales/zh-CN.cjs +3 -0
- package/node_modules/zod/v4/locales/zh-CN.js +3 -0
- package/node_modules/zod/v4/locales/zh-TW.cjs +3 -0
- package/node_modules/zod/v4/locales/zh-TW.js +3 -0
- package/node_modules/zod/v4/mini/checks.cjs +2 -1
- package/node_modules/zod/v4/mini/checks.d.cts +1 -1
- package/node_modules/zod/v4/mini/checks.d.ts +1 -1
- package/node_modules/zod/v4/mini/checks.js +1 -1
- package/node_modules/zod/v4/mini/deep-partial.cjs +39 -0
- package/node_modules/zod/v4/mini/deep-partial.d.cts +14 -0
- package/node_modules/zod/v4/mini/deep-partial.d.ts +14 -0
- package/node_modules/zod/v4/mini/deep-partial.js +13 -0
- package/node_modules/zod/v4/mini/external.cjs +12 -1
- package/node_modules/zod/v4/mini/external.d.cts +5 -2
- package/node_modules/zod/v4/mini/external.d.ts +5 -2
- package/node_modules/zod/v4/mini/external.js +3 -1
- package/node_modules/zod/v4/mini/in-out.cjs +63 -0
- package/node_modules/zod/v4/mini/in-out.d.cts +8 -0
- package/node_modules/zod/v4/mini/in-out.d.ts +8 -0
- package/node_modules/zod/v4/mini/in-out.js +36 -0
- package/node_modules/zod/v4/mini/parse.cjs +3 -1
- package/node_modules/zod/v4/mini/parse.d.cts +1 -1
- package/node_modules/zod/v4/mini/parse.d.ts +1 -1
- package/node_modules/zod/v4/mini/parse.js +1 -1
- package/node_modules/zod/v4/mini/schemas.cjs +75 -47
- package/node_modules/zod/v4/mini/schemas.d.cts +43 -13
- package/node_modules/zod/v4/mini/schemas.d.ts +43 -13
- package/node_modules/zod/v4/mini/schemas.js +71 -45
- package/openclaw.plugin.json +70 -1
- package/package.json +9 -6
- package/node_modules/zod/src/v4/core/config.ts +0 -15
- /package/dist/{realtime-transcription.runtime-CbJAs5t_.js → .setup/realtime-transcription.runtime-CbJAs5t_.mjs} +0 -0
- /package/dist/{realtime-voice.runtime-vtdCOWg-.js → .setup/realtime-voice.runtime-vtdCOWg-.mjs} +0 -0
- /package/dist/{twilio-region-4fkgz3UG.js → .setup/twilio-region-4fkgz3UG.mjs} +0 -0
- /package/dist/{webhook-replay-CCQSoBNF.js → .setup/webhook-replay-CCQSoBNF.mjs} +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { isBlockedHostnameOrIp, isRequestBodyLimitError, readRequestBodyWithLimit, requestBodyErrorToText, sendHttpRequestRejection } from "
|
|
2
|
-
import "
|
|
3
|
-
import { a as resolveVoiceCallEffectiveConfig, c as resolveVoiceCallSessionKey, f as resolveVoiceCallRealtimeTools, i as resolveVoiceCallConfig, l as resolveVoiceCallStreamExposurePaths, n as normalizeVoiceCallConfig, o as resolveVoiceCallNumberRouteKeyForCall, r as resolveTwilioAuthToken, u as validateProviderConfig } from "./config-
|
|
4
|
-
import { _ as releaseRejectedProviderCall, b as setVoiceCallStateRuntime, d as
|
|
1
|
+
import { isBlockedHostnameOrIp, isRequestBodyLimitError, readRequestBodyWithLimit, requestBodyErrorToText, sendHttpRequestRejection } from "../runtime-api.js";
|
|
2
|
+
import "../api.js";
|
|
3
|
+
import { a as resolveVoiceCallEffectiveConfig, c as resolveVoiceCallSessionKey, f as resolveVoiceCallRealtimeTools, i as resolveVoiceCallConfig, l as resolveVoiceCallStreamExposurePaths, n as normalizeVoiceCallConfig, o as resolveVoiceCallNumberRouteKeyForCall, r as resolveTwilioAuthToken, u as validateProviderConfig } from "./config-72FnMWHb.mjs";
|
|
4
|
+
import { _ as releaseRejectedProviderCall, b as setVoiceCallStateRuntime, d as getCallHistoryFromStore, f as loadActiveCallsFromStore, g as appendCallReplayKey, m as persistCallRecord, t as resolveDefaultVoiceCallStoreDir, u as findCallInStore, v as rememberManagerReplayKey, x as TerminalStates, y as reserveRejectedProviderCall } from "./store-path-B1j1up4_.mjs";
|
|
5
5
|
import { createRequire } from "node:module";
|
|
6
6
|
import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
|
|
7
7
|
import { isLoopbackHost } from "openclaw/plugin-sdk/gateway-runtime";
|
|
@@ -14,6 +14,7 @@ import { REALTIME_VOICE_AGENT_CONSULT_TOOL_NAME, assertRealtimeVoiceAgentConsult
|
|
|
14
14
|
import { WEBHOOK_BODY_READ_DEFAULTS, createWebhookInFlightLimiter, normalizeWebhookPath } from "openclaw/plugin-sdk/webhook-ingress";
|
|
15
15
|
import { MAX_TIMER_TIMEOUT_MS, asDateTimestampMs, resolveExpiresAtMsFromDurationMs, resolveTimerTimeoutMs } from "openclaw/plugin-sdk/number-runtime";
|
|
16
16
|
import fs from "node:fs";
|
|
17
|
+
import { KeyedAsyncQueue } from "openclaw/plugin-sdk/keyed-async-queue";
|
|
17
18
|
import crypto from "node:crypto";
|
|
18
19
|
import { redactIdentifier } from "openclaw/plugin-sdk/logging-core";
|
|
19
20
|
import path from "node:path";
|
|
@@ -74,6 +75,15 @@ function addTranscriptEntry(call, speaker, text) {
|
|
|
74
75
|
};
|
|
75
76
|
call.transcript.push(entry);
|
|
76
77
|
}
|
|
78
|
+
/** Stage persisted changes without exposing uncommitted state through active-call getters. */
|
|
79
|
+
function copyCallRecord(call) {
|
|
80
|
+
return {
|
|
81
|
+
...call,
|
|
82
|
+
transcript: [...call.transcript],
|
|
83
|
+
processedEventIds: [...call.processedEventIds],
|
|
84
|
+
...call.metadata ? { metadata: { ...call.metadata } } : {}
|
|
85
|
+
};
|
|
86
|
+
}
|
|
77
87
|
//#endregion
|
|
78
88
|
//#region extensions/voice-call/src/manager/timer-delays.ts
|
|
79
89
|
/** Convert seconds to a safe timeout delay in milliseconds. */
|
|
@@ -102,10 +112,10 @@ function startMaxDurationTimer(params) {
|
|
|
102
112
|
const maxDurationMs = params.timeoutMs === void 0 ? resolveVoiceCallSecondsTimerDelayMs(params.ctx.config.maxDurationSeconds) : resolveVoiceCallTimerDelayMs(params.timeoutMs);
|
|
103
113
|
console.log(`[voice-call] Starting max duration timer (${Math.ceil(maxDurationMs / 1e3)}s) for call ${params.callId}`);
|
|
104
114
|
const timer = setTimeout(() => {
|
|
105
|
-
(async () => {
|
|
115
|
+
const work = (async () => {
|
|
106
116
|
params.ctx.maxDurationTimers.delete(params.callId);
|
|
107
117
|
const call = params.ctx.activeCalls.get(params.callId);
|
|
108
|
-
if (call && !TerminalStates.has(call.state)) {
|
|
118
|
+
if (!params.ctx.isStopping() && call && !TerminalStates.has(call.state)) {
|
|
109
119
|
console.log(`[voice-call] Max duration reached (${Math.ceil(maxDurationMs / 1e3)}s), ending call ${params.callId}`);
|
|
110
120
|
try {
|
|
111
121
|
const result = await params.onTimeout(params.callId);
|
|
@@ -115,19 +125,10 @@ function startMaxDurationTimer(params) {
|
|
|
115
125
|
}
|
|
116
126
|
}
|
|
117
127
|
})();
|
|
128
|
+
params.ctx.trackCallWork(work);
|
|
118
129
|
}, maxDurationMs);
|
|
119
130
|
params.ctx.maxDurationTimers.set(params.callId, timer);
|
|
120
131
|
}
|
|
121
|
-
/** Backfill max-duration enforcement from the first live conversation signal. */
|
|
122
|
-
function ensureMaxDurationTimerForLiveCall(params) {
|
|
123
|
-
if (params.call.answeredAt) return;
|
|
124
|
-
params.call.answeredAt = params.liveAt;
|
|
125
|
-
startMaxDurationTimer({
|
|
126
|
-
ctx: params.ctx,
|
|
127
|
-
callId: params.call.callId,
|
|
128
|
-
onTimeout: params.onTimeout
|
|
129
|
-
});
|
|
130
|
-
}
|
|
131
132
|
/** Clear and forget a pending final-transcript waiter. */
|
|
132
133
|
function clearTranscriptWaiter(ctx, callId) {
|
|
133
134
|
const waiter = ctx.transcriptWaiters.get(callId);
|
|
@@ -176,18 +177,26 @@ function removeProviderCallMapping(providerCallIdMap, call) {
|
|
|
176
177
|
if (!call.providerCallId) return;
|
|
177
178
|
if (providerCallIdMap.get(call.providerCallId) === call.callId) providerCallIdMap.delete(call.providerCallId);
|
|
178
179
|
}
|
|
179
|
-
/**
|
|
180
|
-
function finalizeCall(params) {
|
|
180
|
+
/** Finalize under the manager mutation queue, publishing cleanup only after persistence. */
|
|
181
|
+
async function finalizeCall(params) {
|
|
181
182
|
const { ctx, call, endReason } = params;
|
|
183
|
+
if (ctx.activeCalls.get(call.callId) !== call) return;
|
|
182
184
|
const previousState = call.state;
|
|
183
185
|
if (!TerminalStates.has(previousState)) {
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
186
|
+
const next = copyCallRecord(params.preparedCall ?? call);
|
|
187
|
+
next.endedAt = params.endedAt ?? Date.now();
|
|
188
|
+
next.endReason = endReason;
|
|
189
|
+
transitionState(next, endReason);
|
|
190
|
+
await persistCallRecord(ctx.storePath, next, ctx.stateRuntime);
|
|
191
|
+
Object.assign(call, next);
|
|
188
192
|
log$1.info(`[voice-call] Call finalized callId=${call.callId} providerCallId=${call.providerCallId ?? "unknown"} endReason=${endReason}`);
|
|
189
193
|
}
|
|
190
194
|
if (ctx.maxDurationTimers) clearMaxDurationTimer({ maxDurationTimers: ctx.maxDurationTimers }, call.callId);
|
|
195
|
+
const notifyTimer = ctx.notifyHangupTimers?.get(call.callId);
|
|
196
|
+
if (notifyTimer) {
|
|
197
|
+
clearTimeout(notifyTimer);
|
|
198
|
+
ctx.notifyHangupTimers?.delete(call.callId);
|
|
199
|
+
}
|
|
191
200
|
if (ctx.transcriptWaiters) rejectTranscriptWaiter({ transcriptWaiters: ctx.transcriptWaiters }, call.callId, params.transcriptRejectReason ?? `Call ended: ${endReason}`);
|
|
192
201
|
ctx.activeCalls.delete(call.callId);
|
|
193
202
|
removeProviderCallMapping(ctx.providerCallIdMap, call);
|
|
@@ -260,6 +269,19 @@ function mapVoiceToPolly(voice) {
|
|
|
260
269
|
return OPENAI_TO_POLLY_MAP.get(normalizeLowercaseStringOrEmpty(voice)) ?? DEFAULT_POLLY_VOICE;
|
|
261
270
|
}
|
|
262
271
|
//#endregion
|
|
272
|
+
//#region extensions/voice-call/src/manager/mutations.ts
|
|
273
|
+
/** Commit one live call update while preserving the call identity held by its callbacks. */
|
|
274
|
+
function updateCall(ctx, call, update, isCurrent) {
|
|
275
|
+
return ctx.mutationQueue.enqueue("state", async () => {
|
|
276
|
+
if (ctx.activeCalls.get(call.callId) !== call || TerminalStates.has(call.state) || isCurrent && !isCurrent()) return false;
|
|
277
|
+
const next = copyCallRecord(call);
|
|
278
|
+
update(next);
|
|
279
|
+
await persistCallRecord(ctx.storePath, next, ctx.stateRuntime);
|
|
280
|
+
Object.assign(call, next);
|
|
281
|
+
return true;
|
|
282
|
+
});
|
|
283
|
+
}
|
|
284
|
+
//#endregion
|
|
263
285
|
//#region extensions/voice-call/src/manager/twiml.ts
|
|
264
286
|
/** Generate TwiML that speaks one notification and hangs up. */
|
|
265
287
|
function generateNotifyTwiml(message, voice) {
|
|
@@ -317,6 +339,9 @@ function requireConnectedCall(ctx, callId) {
|
|
|
317
339
|
provider: lookup.provider
|
|
318
340
|
};
|
|
319
341
|
}
|
|
342
|
+
function isCurrentCall(ctx, call) {
|
|
343
|
+
return ctx.activeCalls.get(call.callId) === call && !TerminalStates.has(call.state);
|
|
344
|
+
}
|
|
320
345
|
function validateDtmfDigits(digits) {
|
|
321
346
|
return /^[0-9*#wWpP,]+$/.test(digits) ? null : "digits may only contain digits, *, #, comma, w, p";
|
|
322
347
|
}
|
|
@@ -350,7 +375,7 @@ async function initiateCall(ctx, to, sessionKey, options) {
|
|
|
350
375
|
success: false,
|
|
351
376
|
error: "Webhook URL not configured"
|
|
352
377
|
};
|
|
353
|
-
if (ctx.activeCalls.size >= ctx.config.maxConcurrentCalls) return {
|
|
378
|
+
if (ctx.activeCalls.size + ctx.pendingCallAdmissions.size >= ctx.config.maxConcurrentCalls) return {
|
|
354
379
|
callId: "",
|
|
355
380
|
success: false,
|
|
356
381
|
error: `Maximum concurrent calls (${ctx.config.maxConcurrentCalls}) reached`
|
|
@@ -389,9 +414,18 @@ async function initiateCall(ctx, to, sessionKey, options) {
|
|
|
389
414
|
...requesterSessionKey ? { requesterSessionKey } : {}
|
|
390
415
|
}
|
|
391
416
|
};
|
|
392
|
-
|
|
393
|
-
|
|
417
|
+
ctx.pendingCallAdmissions.add(callId);
|
|
418
|
+
try {
|
|
419
|
+
await ctx.mutationQueue.enqueue("state", async () => {
|
|
420
|
+
await persistCallRecord(ctx.storePath, callRecord, ctx.stateRuntime);
|
|
421
|
+
ctx.activeCalls.set(callId, callRecord);
|
|
422
|
+
ctx.pendingCallAdmissions.delete(callId);
|
|
423
|
+
});
|
|
424
|
+
} finally {
|
|
425
|
+
ctx.pendingCallAdmissions.delete(callId);
|
|
426
|
+
}
|
|
394
427
|
try {
|
|
428
|
+
if (ctx.isStopping()) throw new Error("Voice Call manager is stopping");
|
|
395
429
|
let inlineTwiml;
|
|
396
430
|
let preConnectTwiml;
|
|
397
431
|
if (mode === "notify" && initialMessage) {
|
|
@@ -421,22 +455,25 @@ async function initiateCall(ctx, to, sessionKey, options) {
|
|
|
421
455
|
streamAuthToken: streamSession.token
|
|
422
456
|
} : {}
|
|
423
457
|
});
|
|
424
|
-
|
|
425
|
-
callRecord
|
|
458
|
+
await ctx.mutationQueue.enqueue("state", async () => {
|
|
459
|
+
if (!isCurrentCall(ctx, callRecord) || callRecord.providerCallId) return;
|
|
460
|
+
const next = copyCallRecord(callRecord);
|
|
461
|
+
next.providerCallId = result.providerCallId;
|
|
462
|
+
await persistCallRecord(ctx.storePath, next, ctx.stateRuntime);
|
|
463
|
+
Object.assign(callRecord, next);
|
|
426
464
|
ctx.providerCallIdMap.set(result.providerCallId, callId);
|
|
427
|
-
|
|
428
|
-
}
|
|
465
|
+
});
|
|
429
466
|
console.log(`[voice-call] Outbound call initiated: callId=${callId} providerCallId=${callRecord.providerCallId ?? result.providerCallId} mode=${mode} preConnectDtmf=${preConnectTwiml ? "yes" : "no"} initialMessage=${initialMessage ? "yes" : "no"}`);
|
|
430
467
|
return {
|
|
431
468
|
callId,
|
|
432
469
|
success: true
|
|
433
470
|
};
|
|
434
471
|
} catch (err) {
|
|
435
|
-
finalizeCall({
|
|
472
|
+
await ctx.mutationQueue.enqueue("state", () => finalizeCall({
|
|
436
473
|
ctx,
|
|
437
474
|
call: callRecord,
|
|
438
475
|
endReason: "failed"
|
|
439
|
-
});
|
|
476
|
+
}));
|
|
440
477
|
return {
|
|
441
478
|
callId,
|
|
442
479
|
success: false,
|
|
@@ -451,31 +488,49 @@ async function speak(ctx, callId, text, options) {
|
|
|
451
488
|
error: connected.error
|
|
452
489
|
};
|
|
453
490
|
const { call, providerCallId, provider } = connected;
|
|
491
|
+
let speakingCommitted = false;
|
|
454
492
|
try {
|
|
455
|
-
|
|
493
|
+
let startTimer = false;
|
|
494
|
+
speakingCommitted = await updateCall(ctx, call, (next) => {
|
|
495
|
+
if (!next.answeredAt) {
|
|
496
|
+
next.answeredAt = Date.now();
|
|
497
|
+
startTimer = true;
|
|
498
|
+
}
|
|
499
|
+
transitionState(next, "speaking");
|
|
500
|
+
}, options?.isCurrent);
|
|
501
|
+
if (options?.isCurrent) {
|
|
502
|
+
await ctx.mutationQueue.enqueue("state", async () => void 0);
|
|
503
|
+
if (!options.isCurrent()) throw new Error("Automatic reply superseded");
|
|
504
|
+
}
|
|
505
|
+
if (!speakingCommitted || !isCurrentCall(ctx, call)) return {
|
|
506
|
+
success: false,
|
|
507
|
+
error: "Call has ended"
|
|
508
|
+
};
|
|
509
|
+
if (ctx.isStopping()) throw new Error("Voice Call manager is stopping");
|
|
510
|
+
if (startTimer) startMaxDurationTimer({
|
|
456
511
|
ctx,
|
|
457
|
-
|
|
458
|
-
liveAt: Date.now(),
|
|
512
|
+
callId,
|
|
459
513
|
onTimeout: (id) => endCall(ctx, id, { reason: "timeout" })
|
|
460
514
|
});
|
|
461
|
-
transitionState(call, "speaking");
|
|
462
|
-
persistCallRecord(ctx.storePath, call);
|
|
463
515
|
const numberRouteKey = resolveVoiceCallNumberRouteKeyForCall(call);
|
|
464
516
|
const voice = resolvePreferredTtsVoice(resolveVoiceCallEffectiveConfig(ctx.config, numberRouteKey).config);
|
|
465
517
|
const playbackOptions = options?.listenAfterPlayback ? { listenAfterPlayback: true } : {};
|
|
466
518
|
await provider.playTts({
|
|
467
519
|
callId,
|
|
468
|
-
providerCallId,
|
|
520
|
+
providerCallId: call.providerCallId ?? providerCallId,
|
|
469
521
|
text,
|
|
470
522
|
voice,
|
|
471
523
|
...playbackOptions
|
|
472
524
|
});
|
|
473
|
-
|
|
474
|
-
|
|
525
|
+
if (!await updateCall(ctx, call, (next) => addTranscriptEntry(next, "bot", text))) return {
|
|
526
|
+
success: false,
|
|
527
|
+
error: "Call has ended"
|
|
528
|
+
};
|
|
475
529
|
return { success: true };
|
|
476
530
|
} catch (err) {
|
|
477
|
-
|
|
478
|
-
|
|
531
|
+
if (speakingCommitted) await updateCall(ctx, call, (next) => {
|
|
532
|
+
if (next.state === "speaking") transitionState(next, "listening");
|
|
533
|
+
});
|
|
479
534
|
return {
|
|
480
535
|
success: false,
|
|
481
536
|
error: formatErrorMessage(err)
|
|
@@ -544,30 +599,39 @@ async function speakInitialMessage(ctx, providerCallId) {
|
|
|
544
599
|
console.warn(`[voice-call] Failed to speak initial message: ${result.error}`);
|
|
545
600
|
return;
|
|
546
601
|
}
|
|
547
|
-
if (call
|
|
548
|
-
delete
|
|
549
|
-
|
|
550
|
-
|
|
602
|
+
if (!await updateCall(ctx, call, (next) => {
|
|
603
|
+
if (next.metadata?.initialMessage === initialMessage) delete next.metadata.initialMessage;
|
|
604
|
+
}) || !isCurrentCall(ctx, call)) return;
|
|
605
|
+
if (ctx.isStopping()) throw new Error("Voice Call manager is stopping");
|
|
551
606
|
if (mode === "notify") {
|
|
552
607
|
const delaySec = ctx.config.outbound.notifyHangupDelaySec;
|
|
553
608
|
const delayMs = resolveVoiceCallSecondsTimerDelayMs(delaySec, 0);
|
|
554
609
|
console.log(`[voice-call] Notify mode: auto-hangup in ${delaySec}s for call ${call.callId}`);
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
610
|
+
const previousTimer = ctx.notifyHangupTimers.get(call.callId);
|
|
611
|
+
if (previousTimer) clearTimeout(previousTimer);
|
|
612
|
+
const timer = setTimeout(() => {
|
|
613
|
+
if (ctx.notifyHangupTimers.get(call.callId) !== timer) return;
|
|
614
|
+
ctx.notifyHangupTimers.delete(call.callId);
|
|
615
|
+
const work = (async () => {
|
|
616
|
+
if (!ctx.isStopping() && isCurrentCall(ctx, call)) {
|
|
559
617
|
console.log(`[voice-call] Notify mode: hanging up call ${call.callId}`);
|
|
560
|
-
|
|
561
|
-
|
|
618
|
+
try {
|
|
619
|
+
const endResult = await endCall(ctx, call.callId);
|
|
620
|
+
if (!endResult.success) console.warn(`[voice-call] Notify mode failed to hang up call ${call.callId}: ${endResult.error ?? "unknown error"}`);
|
|
621
|
+
} catch (error) {
|
|
622
|
+
console.warn(`[voice-call] Notify mode failed to hang up call ${call.callId}: ${formatErrorMessage(error)}`);
|
|
623
|
+
}
|
|
562
624
|
}
|
|
563
625
|
})();
|
|
626
|
+
ctx.trackCallWork(work);
|
|
564
627
|
}, delayMs);
|
|
628
|
+
ctx.notifyHangupTimers.set(call.callId, timer);
|
|
565
629
|
} else if (mode === "conversation" && ctx.provider && shouldStartListeningAfterInitialMessage(ctx)) {
|
|
566
|
-
|
|
567
|
-
|
|
630
|
+
if (!await updateCall(ctx, call, (next) => transitionState(next, "listening")) || !isCurrentCall(ctx, call)) return;
|
|
631
|
+
if (ctx.isStopping()) throw new Error("Voice Call manager is stopping");
|
|
568
632
|
await ctx.provider.startListening({
|
|
569
633
|
callId: call.callId,
|
|
570
|
-
providerCallId
|
|
634
|
+
providerCallId: call.providerCallId ?? providerCallId
|
|
571
635
|
});
|
|
572
636
|
}
|
|
573
637
|
} finally {
|
|
@@ -591,14 +655,22 @@ async function continueCall(ctx, callId, prompt) {
|
|
|
591
655
|
try {
|
|
592
656
|
const speakResult = await speak(ctx, callId, prompt);
|
|
593
657
|
if (!speakResult.success) return speakResult;
|
|
594
|
-
|
|
595
|
-
|
|
658
|
+
if (!await updateCall(ctx, call, (next) => transitionState(next, "listening")) || !isCurrentCall(ctx, call)) return {
|
|
659
|
+
success: false,
|
|
660
|
+
error: "Call has ended"
|
|
661
|
+
};
|
|
662
|
+
if (ctx.isStopping()) throw new Error("Voice Call manager is stopping");
|
|
596
663
|
const listenStartedAt = Date.now();
|
|
597
664
|
await provider.startListening({
|
|
598
665
|
callId,
|
|
599
|
-
providerCallId,
|
|
666
|
+
providerCallId: call.providerCallId ?? providerCallId,
|
|
600
667
|
turnToken
|
|
601
668
|
});
|
|
669
|
+
if (ctx.isStopping()) throw new Error("Voice Call manager is stopping");
|
|
670
|
+
if (!isCurrentCall(ctx, call)) return {
|
|
671
|
+
success: false,
|
|
672
|
+
error: "Call has ended"
|
|
673
|
+
};
|
|
602
674
|
const transcript = await waitForFinalTranscript(ctx, callId, turnToken);
|
|
603
675
|
const transcriptReceivedAt = Date.now();
|
|
604
676
|
await provider.stopListening({
|
|
@@ -607,15 +679,19 @@ async function continueCall(ctx, callId, prompt) {
|
|
|
607
679
|
});
|
|
608
680
|
const lastTurnLatencyMs = transcriptReceivedAt - turnStartedAt;
|
|
609
681
|
const lastTurnListenWaitMs = transcriptReceivedAt - listenStartedAt;
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
682
|
+
if (!await updateCall(ctx, call, (next) => {
|
|
683
|
+
const turnCount = typeof next.metadata?.turnCount === "number" ? next.metadata.turnCount + 1 : 1;
|
|
684
|
+
next.metadata = {
|
|
685
|
+
...next.metadata,
|
|
686
|
+
turnCount,
|
|
687
|
+
lastTurnLatencyMs,
|
|
688
|
+
lastTurnListenWaitMs,
|
|
689
|
+
lastTurnCompletedAt: transcriptReceivedAt
|
|
690
|
+
};
|
|
691
|
+
})) return {
|
|
692
|
+
success: false,
|
|
693
|
+
error: "Call has ended"
|
|
617
694
|
};
|
|
618
|
-
persistCallRecord(ctx.storePath, call);
|
|
619
695
|
console.log("[voice-call] continueCall latency call=" + call.callId + " totalMs=" + String(lastTurnLatencyMs) + " listenWaitMs=" + String(lastTurnListenWaitMs));
|
|
620
696
|
return {
|
|
621
697
|
success: true,
|
|
@@ -649,11 +725,11 @@ function endCall(ctx, callId, options) {
|
|
|
649
725
|
providerCallId,
|
|
650
726
|
reason
|
|
651
727
|
});
|
|
652
|
-
finalizeCall({
|
|
728
|
+
await ctx.mutationQueue.enqueue("state", () => finalizeCall({
|
|
653
729
|
ctx,
|
|
654
730
|
call,
|
|
655
731
|
endReason: reason
|
|
656
|
-
});
|
|
732
|
+
}));
|
|
657
733
|
return { success: true };
|
|
658
734
|
} catch (err) {
|
|
659
735
|
return {
|
|
@@ -695,7 +771,7 @@ function shouldAcceptInbound(config, from) {
|
|
|
695
771
|
default: return false;
|
|
696
772
|
}
|
|
697
773
|
}
|
|
698
|
-
function createWebhookCall(params) {
|
|
774
|
+
async function createWebhookCall(params) {
|
|
699
775
|
const callId = crypto.randomUUID();
|
|
700
776
|
const effective = resolveVoiceCallEffectiveConfig(params.ctx.config, params.direction === "inbound" ? params.to : void 0);
|
|
701
777
|
const effectiveConfig = effective.config;
|
|
@@ -722,13 +798,13 @@ function createWebhookCall(params) {
|
|
|
722
798
|
...effective.numberRouteKey ? { numberRouteKey: effective.numberRouteKey } : {}
|
|
723
799
|
}
|
|
724
800
|
};
|
|
725
|
-
persistCallRecord(params.ctx.storePath, callRecord);
|
|
801
|
+
await persistCallRecord(params.ctx.storePath, callRecord, params.ctx.stateRuntime);
|
|
726
802
|
params.ctx.activeCalls.set(callId, callRecord);
|
|
727
803
|
params.ctx.providerCallIdMap.set(params.providerCallId, callId);
|
|
728
804
|
log.info(`Created ${params.direction} call record: ${callId} caller=${redactIdentifier(params.from)}`);
|
|
729
805
|
return callRecord;
|
|
730
806
|
}
|
|
731
|
-
function persistRejectedInboundCall(params) {
|
|
807
|
+
async function persistRejectedInboundCall(params) {
|
|
732
808
|
const callId = params.event.callId || params.providerCallId;
|
|
733
809
|
const now = Date.now();
|
|
734
810
|
const rejectedCall = {
|
|
@@ -746,9 +822,12 @@ function persistRejectedInboundCall(params) {
|
|
|
746
822
|
processedEventIds: [params.dedupeKey],
|
|
747
823
|
metadata: { rejectionReason: "inbound-policy" }
|
|
748
824
|
};
|
|
749
|
-
persistCallRecord(params.ctx.storePath, rejectedCall);
|
|
825
|
+
await persistCallRecord(params.ctx.storePath, rejectedCall, params.ctx.stateRuntime);
|
|
750
826
|
}
|
|
751
827
|
function processEvent(ctx, event) {
|
|
828
|
+
return ctx.mutationQueue.enqueue("state", () => processEventInQueue(ctx, event));
|
|
829
|
+
}
|
|
830
|
+
async function processEventInQueue(ctx, event) {
|
|
752
831
|
const dedupeKey = event.dedupeKey || event.id;
|
|
753
832
|
if (ctx.processedEventIds.has(dedupeKey)) return { kind: "ignored" };
|
|
754
833
|
let call = findCall({
|
|
@@ -759,8 +838,8 @@ function processEvent(ctx, event) {
|
|
|
759
838
|
let providerCallId = event.providerCallId;
|
|
760
839
|
let retained;
|
|
761
840
|
if (!call) {
|
|
762
|
-
retained = findCallInStore(ctx.storePath, event.callId);
|
|
763
|
-
if (!retained && providerCallId && providerCallId !== event.callId) retained = findCallInStore(ctx.storePath, providerCallId);
|
|
841
|
+
retained = await findCallInStore(ctx.storePath, event.callId, ctx.stateRuntime);
|
|
842
|
+
if (!retained && providerCallId && providerCallId !== event.callId) retained = await findCallInStore(ctx.storePath, providerCallId, ctx.stateRuntime);
|
|
764
843
|
if (retained && retained.metadata?.rejectionReason !== "inbound-policy") {
|
|
765
844
|
call = ctx.activeCalls.get(retained.callId);
|
|
766
845
|
if (!call) return TerminalStates.has(retained.state) ? { kind: "ignored" } : {
|
|
@@ -770,7 +849,7 @@ function processEvent(ctx, event) {
|
|
|
770
849
|
}
|
|
771
850
|
}
|
|
772
851
|
if (call && providerCallId && providerCallId !== call.providerCallId) {
|
|
773
|
-
if ((providerCallId === event.callId && retained ? retained : findCallInStore(ctx.storePath, providerCallId))?.callId === call.callId) providerCallId = call.providerCallId;
|
|
852
|
+
if ((providerCallId === event.callId && retained ? retained : await findCallInStore(ctx.storePath, providerCallId, ctx.stateRuntime))?.callId === call.callId) providerCallId = call.providerCallId;
|
|
774
853
|
}
|
|
775
854
|
const eventDirection = event.direction === "inbound" || event.direction === "outbound" ? event.direction : void 0;
|
|
776
855
|
if (!call && providerCallId && eventDirection) {
|
|
@@ -782,17 +861,18 @@ function processEvent(ctx, event) {
|
|
|
782
861
|
}
|
|
783
862
|
if (ctx.rejectedProviderCallIds.has(pid)) return { kind: "ignored" };
|
|
784
863
|
const callId = event.callId ?? pid;
|
|
785
|
-
persistRejectedInboundCall({
|
|
864
|
+
await persistRejectedInboundCall({
|
|
786
865
|
ctx,
|
|
787
866
|
event,
|
|
788
867
|
dedupeKey,
|
|
789
868
|
providerCallId: pid
|
|
790
869
|
});
|
|
870
|
+
if (ctx.isStopping()) return { kind: "processed" };
|
|
791
871
|
const rejectionReservation = reserveRejectedProviderCall(ctx.rejectedProviderCallIds, pid);
|
|
792
872
|
if (rejectionReservation === void 0) return { kind: "ignored" };
|
|
793
873
|
rememberManagerReplayKey(ctx.processedEventIds, dedupeKey);
|
|
794
874
|
log.info(`Rejecting inbound call by policy: ${pid}`);
|
|
795
|
-
ctx.provider.hangupCall({
|
|
875
|
+
ctx.trackCallWork(ctx.provider.hangupCall({
|
|
796
876
|
callId,
|
|
797
877
|
providerCallId: pid,
|
|
798
878
|
reason: "hangup-bot"
|
|
@@ -800,10 +880,10 @@ function processEvent(ctx, event) {
|
|
|
800
880
|
releaseRejectedProviderCall(ctx.rejectedProviderCallIds, pid, rejectionReservation);
|
|
801
881
|
const message = formatErrorMessage(err);
|
|
802
882
|
log.warn(`Failed to reject inbound call ${pid}: ${message}`);
|
|
803
|
-
});
|
|
883
|
+
}));
|
|
804
884
|
return { kind: "processed" };
|
|
805
885
|
}
|
|
806
|
-
call = createWebhookCall({
|
|
886
|
+
call = await createWebhookCall({
|
|
807
887
|
ctx,
|
|
808
888
|
providerCallId,
|
|
809
889
|
direction: eventDirection === "outbound" ? "outbound" : "inbound",
|
|
@@ -816,16 +896,8 @@ function processEvent(ctx, event) {
|
|
|
816
896
|
kind: "ignored",
|
|
817
897
|
replayable: true
|
|
818
898
|
};
|
|
819
|
-
const activeCall = call;
|
|
820
|
-
const previousCall = {
|
|
821
|
-
state: activeCall.state,
|
|
822
|
-
providerCallId: activeCall.providerCallId,
|
|
823
|
-
answeredAt: activeCall.answeredAt,
|
|
824
|
-
endedAt: activeCall.endedAt,
|
|
825
|
-
endReason: activeCall.endReason,
|
|
826
|
-
transcriptLength: activeCall.transcript.length,
|
|
827
|
-
processedEventIds: [...activeCall.processedEventIds]
|
|
828
|
-
};
|
|
899
|
+
const activeCall = copyCallRecord(call);
|
|
900
|
+
const previousCall = { providerCallId: call.providerCallId };
|
|
829
901
|
const shouldCommitReplayKey = !(event.type === "call.error" && event.retryable);
|
|
830
902
|
const effects = [];
|
|
831
903
|
let result = { kind: "processed" };
|
|
@@ -849,123 +921,114 @@ function processEvent(ctx, event) {
|
|
|
849
921
|
if (ctx.providerCallIdMap.get(previousCall.providerCallId) === activeCall.callId) ctx.providerCallIdMap.delete(previousCall.providerCallId);
|
|
850
922
|
}
|
|
851
923
|
};
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
924
|
+
if (providerCallId && providerCallId !== activeCall.providerCallId) activeCall.providerCallId = providerCallId;
|
|
925
|
+
if (shouldCommitReplayKey) appendCallReplayKey(activeCall.processedEventIds, dedupeKey);
|
|
926
|
+
switch (event.type) {
|
|
927
|
+
case "call.initiated": {
|
|
928
|
+
transitionState(activeCall, "initiated");
|
|
929
|
+
const inboundProvider = ctx.provider;
|
|
930
|
+
const inboundProviderCallId = activeCall.providerCallId;
|
|
931
|
+
const answerInboundCall = inboundProvider?.answerCall?.bind(inboundProvider);
|
|
932
|
+
if (activeCall.direction === "inbound" && inboundProviderCallId && answerInboundCall) effects.push(() => {
|
|
933
|
+
const inboundStreamSession = ctx.config.realtime?.enabled && inboundProvider?.name === "telnyx" && ctx.streamSessionIssuer ? ctx.streamSessionIssuer({
|
|
934
|
+
providerName: "telnyx",
|
|
935
|
+
callId: activeCall.callId,
|
|
936
|
+
from: activeCall.from,
|
|
937
|
+
to: activeCall.to,
|
|
938
|
+
direction: "inbound"
|
|
939
|
+
}) : void 0;
|
|
940
|
+
ctx.trackCallWork(answerInboundCall({
|
|
941
|
+
callId: activeCall.callId,
|
|
942
|
+
providerCallId: inboundProviderCallId,
|
|
943
|
+
...inboundStreamSession ? {
|
|
944
|
+
streamUrl: inboundStreamSession.streamUrl,
|
|
945
|
+
streamAuthToken: inboundStreamSession.token
|
|
946
|
+
} : {}
|
|
947
|
+
}).catch((err) => {
|
|
948
|
+
const message = formatErrorMessage(err);
|
|
949
|
+
log.warn(`Failed to answer inbound call ${activeCall.providerCallId}: ${message}`);
|
|
950
|
+
}));
|
|
951
|
+
});
|
|
952
|
+
break;
|
|
953
|
+
}
|
|
954
|
+
case "call.ringing":
|
|
955
|
+
transitionState(activeCall, "ringing");
|
|
956
|
+
break;
|
|
957
|
+
case "call.answered":
|
|
958
|
+
activeCall.answeredAt = event.timestamp;
|
|
959
|
+
transitionState(activeCall, "answered");
|
|
960
|
+
effects.push(startDurationTimer, () => ctx.onCallAnswered?.(call));
|
|
961
|
+
break;
|
|
962
|
+
case "call.active":
|
|
963
|
+
transitionState(activeCall, "active");
|
|
964
|
+
break;
|
|
965
|
+
case "call.speaking":
|
|
966
|
+
case "call.assistant-speech":
|
|
967
|
+
prepareLiveDurationTimer();
|
|
968
|
+
transitionState(activeCall, "speaking");
|
|
969
|
+
if (event.type === "call.assistant-speech" && event.transcript.trim()) addTranscriptEntry(activeCall, "bot", event.transcript);
|
|
970
|
+
break;
|
|
971
|
+
case "call.speech":
|
|
972
|
+
if (event.isFinal && event.transcript.trim()) {
|
|
973
|
+
const waiter = ctx.transcriptWaiters.get(activeCall.callId);
|
|
974
|
+
if (waiter?.turnToken && waiter.turnToken !== event.turnToken) {
|
|
975
|
+
log.warn(`Ignoring speech event with mismatched turn token for ${activeCall.callId}`);
|
|
976
|
+
result = { kind: "ignored" };
|
|
977
|
+
break;
|
|
978
|
+
}
|
|
979
|
+
addTranscriptEntry(activeCall, "user", event.transcript);
|
|
980
|
+
const speechResult = {
|
|
981
|
+
kind: "final-speech",
|
|
982
|
+
call,
|
|
983
|
+
transcript: event.transcript,
|
|
984
|
+
waiterResolved: false
|
|
985
|
+
};
|
|
986
|
+
result = speechResult;
|
|
987
|
+
if (waiter) effects.push(() => {
|
|
988
|
+
if (ctx.transcriptWaiters.get(activeCall.callId) === waiter) speechResult.waiterResolved = resolveTranscriptWaiter(ctx, activeCall.callId, event.transcript, event.turnToken);
|
|
880
989
|
});
|
|
881
|
-
break;
|
|
882
990
|
}
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
if (waiter?.turnToken && waiter.turnToken !== event.turnToken) {
|
|
904
|
-
log.warn(`Ignoring speech event with mismatched turn token for ${activeCall.callId}`);
|
|
905
|
-
result = { kind: "ignored" };
|
|
906
|
-
break;
|
|
907
|
-
}
|
|
908
|
-
addTranscriptEntry(activeCall, "user", event.transcript);
|
|
909
|
-
result = {
|
|
910
|
-
kind: "final-speech",
|
|
911
|
-
call: activeCall,
|
|
912
|
-
transcript: event.transcript,
|
|
913
|
-
waiterResolved: Boolean(waiter)
|
|
914
|
-
};
|
|
915
|
-
if (waiter) effects.push(() => {
|
|
916
|
-
resolveTranscriptWaiter(ctx, activeCall.callId, event.transcript, event.turnToken);
|
|
917
|
-
});
|
|
918
|
-
}
|
|
919
|
-
if (event.transcript.trim()) effects.push(() => ctx.onCallerSpeech?.(activeCall));
|
|
920
|
-
prepareLiveDurationTimer();
|
|
921
|
-
transitionState(activeCall, "listening");
|
|
922
|
-
break;
|
|
923
|
-
case "call.silence":
|
|
924
|
-
case "call.dtmf": break;
|
|
925
|
-
case "call.ended":
|
|
926
|
-
finalizeCall({
|
|
991
|
+
if (event.transcript.trim()) effects.push(() => ctx.onCallerSpeech?.(call));
|
|
992
|
+
prepareLiveDurationTimer();
|
|
993
|
+
transitionState(activeCall, "listening");
|
|
994
|
+
break;
|
|
995
|
+
case "call.silence":
|
|
996
|
+
case "call.dtmf": break;
|
|
997
|
+
case "call.ended":
|
|
998
|
+
await finalizeCall({
|
|
999
|
+
ctx,
|
|
1000
|
+
call,
|
|
1001
|
+
preparedCall: activeCall,
|
|
1002
|
+
endReason: event.reason,
|
|
1003
|
+
endedAt: event.timestamp
|
|
1004
|
+
});
|
|
1005
|
+
publishProviderCallId(true);
|
|
1006
|
+
rememberManagerReplayKey(ctx.processedEventIds, dedupeKey);
|
|
1007
|
+
return { kind: "processed" };
|
|
1008
|
+
case "call.error":
|
|
1009
|
+
if (!event.retryable) {
|
|
1010
|
+
await finalizeCall({
|
|
927
1011
|
ctx,
|
|
928
|
-
call
|
|
929
|
-
|
|
930
|
-
|
|
1012
|
+
call,
|
|
1013
|
+
preparedCall: activeCall,
|
|
1014
|
+
endReason: "error",
|
|
1015
|
+
endedAt: event.timestamp,
|
|
1016
|
+
transcriptRejectReason: `Call error: ${event.error}`
|
|
931
1017
|
});
|
|
932
1018
|
publishProviderCallId(true);
|
|
933
1019
|
rememberManagerReplayKey(ctx.processedEventIds, dedupeKey);
|
|
934
1020
|
return { kind: "processed" };
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
endReason: "error",
|
|
941
|
-
endedAt: event.timestamp,
|
|
942
|
-
transcriptRejectReason: `Call error: ${event.error}`
|
|
943
|
-
});
|
|
944
|
-
publishProviderCallId(true);
|
|
945
|
-
rememberManagerReplayKey(ctx.processedEventIds, dedupeKey);
|
|
946
|
-
return { kind: "processed" };
|
|
947
|
-
}
|
|
948
|
-
result = {
|
|
949
|
-
kind: "processed",
|
|
950
|
-
replayable: true
|
|
951
|
-
};
|
|
952
|
-
}
|
|
953
|
-
persistCallRecord(ctx.storePath, activeCall);
|
|
954
|
-
publishProviderCallId();
|
|
955
|
-
if (shouldCommitReplayKey) rememberManagerReplayKey(ctx.processedEventIds, dedupeKey);
|
|
956
|
-
} catch (err) {
|
|
957
|
-
Object.assign(activeCall, {
|
|
958
|
-
state: previousCall.state,
|
|
959
|
-
providerCallId: previousCall.providerCallId,
|
|
960
|
-
answeredAt: previousCall.answeredAt,
|
|
961
|
-
endedAt: previousCall.endedAt,
|
|
962
|
-
endReason: previousCall.endReason
|
|
963
|
-
});
|
|
964
|
-
activeCall.transcript.length = previousCall.transcriptLength;
|
|
965
|
-
activeCall.processedEventIds.splice(0, activeCall.processedEventIds.length, ...previousCall.processedEventIds);
|
|
966
|
-
throw err;
|
|
1021
|
+
}
|
|
1022
|
+
result = {
|
|
1023
|
+
kind: "processed",
|
|
1024
|
+
replayable: true
|
|
1025
|
+
};
|
|
967
1026
|
}
|
|
968
|
-
|
|
1027
|
+
await persistCallRecord(ctx.storePath, activeCall, ctx.stateRuntime);
|
|
1028
|
+
Object.assign(call, activeCall);
|
|
1029
|
+
publishProviderCallId();
|
|
1030
|
+
if (shouldCommitReplayKey) rememberManagerReplayKey(ctx.processedEventIds, dedupeKey);
|
|
1031
|
+
if (!ctx.isStopping()) for (const effect of effects) effect();
|
|
969
1032
|
return result;
|
|
970
1033
|
}
|
|
971
1034
|
//#endregion
|
|
@@ -1003,7 +1066,49 @@ function resolveDefaultStoreBase(config, storePath) {
|
|
|
1003
1066
|
* Manages voice calls: state ownership and delegation to manager helper modules.
|
|
1004
1067
|
*/
|
|
1005
1068
|
var CallManager = class {
|
|
1006
|
-
|
|
1069
|
+
runOperation(operation) {
|
|
1070
|
+
if (this.closing) return Promise.reject(/* @__PURE__ */ new Error("Voice Call manager is stopping"));
|
|
1071
|
+
const pending = this.initialization ? this.initialization.then(() => {
|
|
1072
|
+
if (this.closing) throw new Error("Voice Call manager is stopping");
|
|
1073
|
+
return operation();
|
|
1074
|
+
}) : operation();
|
|
1075
|
+
this.trackCallWork(pending);
|
|
1076
|
+
return pending;
|
|
1077
|
+
}
|
|
1078
|
+
/** Stop is owned by runtime shutdown, after webhook and stream producers have closed. */
|
|
1079
|
+
stop() {
|
|
1080
|
+
if (this.stopPromise) return this.stopPromise;
|
|
1081
|
+
this.closing = true;
|
|
1082
|
+
for (const timers of [this.maxDurationTimers, this.notifyHangupTimers]) {
|
|
1083
|
+
for (const timer of timers.values()) clearTimeout(timer);
|
|
1084
|
+
timers.clear();
|
|
1085
|
+
}
|
|
1086
|
+
for (const waiter of this.transcriptWaiters.values()) {
|
|
1087
|
+
clearTimeout(waiter.timeout);
|
|
1088
|
+
waiter.reject(/* @__PURE__ */ new Error("Voice Call runtime stopped"));
|
|
1089
|
+
}
|
|
1090
|
+
this.transcriptWaiters.clear();
|
|
1091
|
+
this.stopPromise = (async () => {
|
|
1092
|
+
const failures = [];
|
|
1093
|
+
while (this.pendingWork.size > 0) {
|
|
1094
|
+
const results = await Promise.allSettled(this.pendingWork);
|
|
1095
|
+
for (const result of results) if (result.status === "rejected") failures.push(result.reason);
|
|
1096
|
+
}
|
|
1097
|
+
for (const timers of [this.maxDurationTimers, this.notifyHangupTimers]) {
|
|
1098
|
+
for (const timer of timers.values()) clearTimeout(timer);
|
|
1099
|
+
timers.clear();
|
|
1100
|
+
}
|
|
1101
|
+
if (failures.length > 0) throw new AggregateError(failures, "Voice Call work failed during shutdown");
|
|
1102
|
+
})();
|
|
1103
|
+
return this.stopPromise;
|
|
1104
|
+
}
|
|
1105
|
+
/** Serialize transient metadata with persisted updates without adding event-store writes. */
|
|
1106
|
+
updateCallMetadata(call, update) {
|
|
1107
|
+
return this.runOperation(() => this.mutationQueue.enqueue("state", async () => {
|
|
1108
|
+
if (this.activeCalls.get(call.callId) === call && !TerminalStates.has(call.state)) call.metadata = update(call.metadata ? { ...call.metadata } : void 0);
|
|
1109
|
+
}));
|
|
1110
|
+
}
|
|
1111
|
+
constructor(config, storePath, coreSession, stateRuntime) {
|
|
1007
1112
|
this.activeCalls = /* @__PURE__ */ new Map();
|
|
1008
1113
|
this.providerCallIdMap = /* @__PURE__ */ new Map();
|
|
1009
1114
|
this.processedEventIds = /* @__PURE__ */ new Set();
|
|
@@ -1016,25 +1121,48 @@ var CallManager = class {
|
|
|
1016
1121
|
this.maxDurationTimers = /* @__PURE__ */ new Map();
|
|
1017
1122
|
this.initialMessageInFlight = /* @__PURE__ */ new Set();
|
|
1018
1123
|
this.autoResponseOwners = /* @__PURE__ */ new WeakMap();
|
|
1124
|
+
this.mutationQueue = new KeyedAsyncQueue();
|
|
1125
|
+
this.pendingCallAdmissions = /* @__PURE__ */ new Set();
|
|
1126
|
+
this.pendingWork = /* @__PURE__ */ new Set();
|
|
1127
|
+
this.notifyHangupTimers = /* @__PURE__ */ new Map();
|
|
1128
|
+
this.initialization = null;
|
|
1129
|
+
this.closing = false;
|
|
1130
|
+
this.stopPromise = null;
|
|
1131
|
+
this.trackCallWork = (work) => {
|
|
1132
|
+
this.pendingWork.add(work);
|
|
1133
|
+
const settled = () => this.pendingWork.delete(work);
|
|
1134
|
+
work.then(settled, settled);
|
|
1135
|
+
};
|
|
1019
1136
|
this.config = config;
|
|
1020
1137
|
this.coreSession = coreSession;
|
|
1021
1138
|
this.storePath = resolveDefaultStoreBase(config, storePath);
|
|
1139
|
+
this.stateRuntime = stateRuntime;
|
|
1022
1140
|
}
|
|
1023
1141
|
/**
|
|
1024
1142
|
* Initialize the call manager with a provider.
|
|
1025
1143
|
* Verifies persisted calls with the provider and restarts timers.
|
|
1026
1144
|
*/
|
|
1027
|
-
|
|
1145
|
+
initialize(provider, webhookUrl) {
|
|
1146
|
+
if (this.closing) return Promise.reject(/* @__PURE__ */ new Error("Voice Call manager is stopping"));
|
|
1147
|
+
const pending = this.initializeFromStore(provider, webhookUrl);
|
|
1148
|
+
this.initialization = pending;
|
|
1149
|
+
this.trackCallWork(pending);
|
|
1150
|
+
pending.then(() => {
|
|
1151
|
+
if (this.initialization === pending) this.initialization = null;
|
|
1152
|
+
}, () => {});
|
|
1153
|
+
return pending;
|
|
1154
|
+
}
|
|
1155
|
+
async initializeFromStore(provider, webhookUrl) {
|
|
1028
1156
|
this.provider = provider;
|
|
1029
1157
|
this.webhookUrl = webhookUrl;
|
|
1030
1158
|
fs.mkdirSync(this.storePath, { recursive: true });
|
|
1031
|
-
const persisted = loadActiveCallsFromStore(this.storePath);
|
|
1159
|
+
const persisted = await loadActiveCallsFromStore(this.storePath, this.stateRuntime);
|
|
1160
|
+
if (this.closing) return;
|
|
1032
1161
|
this.processedEventIds = persisted.processedEventIds;
|
|
1033
1162
|
this.rejectedProviderCallIds = /* @__PURE__ */ new Map();
|
|
1034
1163
|
const verified = await this.verifyRestoredCalls(provider, persisted.activeCalls);
|
|
1035
|
-
this.
|
|
1036
|
-
|
|
1037
|
-
for (const [callId, call] of verified) if (call.providerCallId) this.providerCallIdMap.set(call.providerCallId, callId);
|
|
1164
|
+
if (this.closing) return;
|
|
1165
|
+
const timers = [];
|
|
1038
1166
|
let skippedAlreadyElapsedTimers = 0;
|
|
1039
1167
|
for (const [callId, call] of verified) {
|
|
1040
1168
|
const maxDurationAnchor = resolveRestoredMaxDurationAnchor(call);
|
|
@@ -1043,23 +1171,32 @@ var CallManager = class {
|
|
|
1043
1171
|
const maxDurationMs = resolveVoiceCallSecondsTimerDelayMs(this.config.maxDurationSeconds);
|
|
1044
1172
|
if (elapsed >= maxDurationMs) {
|
|
1045
1173
|
verified.delete(callId);
|
|
1046
|
-
if (call.providerCallId) this.providerCallIdMap.delete(call.providerCallId);
|
|
1047
1174
|
skippedAlreadyElapsedTimers += 1;
|
|
1048
1175
|
continue;
|
|
1049
1176
|
}
|
|
1050
1177
|
if (call.answeredAt === void 0) {
|
|
1051
1178
|
call.answeredAt = maxDurationAnchor;
|
|
1052
|
-
persistCallRecord(this.storePath, call);
|
|
1179
|
+
await persistCallRecord(this.storePath, call, this.stateRuntime);
|
|
1053
1180
|
}
|
|
1054
|
-
|
|
1055
|
-
|
|
1181
|
+
if (this.closing) return;
|
|
1182
|
+
timers.push({
|
|
1056
1183
|
callId,
|
|
1057
|
-
|
|
1058
|
-
onTimeout: (id) => this.endCall(id, { reason: "timeout" })
|
|
1184
|
+
deadline: maxDurationAnchor + maxDurationMs
|
|
1059
1185
|
});
|
|
1060
|
-
console.log(`[voice-call] Restarted max-duration timer for restored call ${callId}`);
|
|
1061
1186
|
}
|
|
1062
1187
|
}
|
|
1188
|
+
this.activeCalls = verified;
|
|
1189
|
+
this.providerCallIdMap = /* @__PURE__ */ new Map();
|
|
1190
|
+
for (const [callId, call] of verified) if (call.providerCallId) this.providerCallIdMap.set(call.providerCallId, callId);
|
|
1191
|
+
for (const { callId, deadline } of timers) {
|
|
1192
|
+
startMaxDurationTimer({
|
|
1193
|
+
ctx: this.getContext(),
|
|
1194
|
+
callId,
|
|
1195
|
+
timeoutMs: Math.max(0, deadline - Date.now()),
|
|
1196
|
+
onTimeout: (id) => this.endCall(id, { reason: "timeout" })
|
|
1197
|
+
});
|
|
1198
|
+
console.log(`[voice-call] Restarted max-duration timer for restored call ${callId}`);
|
|
1199
|
+
}
|
|
1063
1200
|
if (skippedAlreadyElapsedTimers > 0) console.log(`[voice-call] Skipped ${skippedAlreadyElapsedTimers} restored call(s) whose max-duration timer already elapsed`);
|
|
1064
1201
|
if (verified.size > 0) console.log(`[voice-call] Restored ${verified.size} active call(s) from store`);
|
|
1065
1202
|
}
|
|
@@ -1080,32 +1217,33 @@ var CallManager = class {
|
|
|
1080
1217
|
let keptVerifiedActive = 0;
|
|
1081
1218
|
let keptUnknownProviderStatus = 0;
|
|
1082
1219
|
let keptVerificationFailures = 0;
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1220
|
+
let admissionFailure;
|
|
1221
|
+
try {
|
|
1222
|
+
for (const [callId, call] of candidates) {
|
|
1223
|
+
if (this.closing) break;
|
|
1224
|
+
if (!call.providerCallId) {
|
|
1225
|
+
skippedNoProviderCallId += 1;
|
|
1226
|
+
continue;
|
|
1227
|
+
}
|
|
1228
|
+
if (now - call.startedAt > maxAgeMs) {
|
|
1229
|
+
skippedOlderThanMaxDuration += 1;
|
|
1230
|
+
markRestoredCallSkipped(call, "timeout");
|
|
1231
|
+
await persistCallRecord(this.storePath, call, this.stateRuntime);
|
|
1232
|
+
if (this.closing) break;
|
|
1233
|
+
await provider.hangupCall({
|
|
1234
|
+
callId,
|
|
1235
|
+
providerCallId: call.providerCallId,
|
|
1236
|
+
reason: "timeout"
|
|
1237
|
+
}).catch((err) => {
|
|
1238
|
+
console.warn(`[voice-call] Failed to hang up expired restored call ${callId}:`, err instanceof Error ? err.message : String(err));
|
|
1239
|
+
});
|
|
1240
|
+
continue;
|
|
1241
|
+
}
|
|
1242
|
+
const task = provider.getCallStatus({ providerCallId: call.providerCallId }).then(async (result) => {
|
|
1105
1243
|
if (result.isTerminal) {
|
|
1106
1244
|
incrementRestoreStatusCount(skippedTerminalStatuses, result.status);
|
|
1107
1245
|
markRestoredCallSkipped(call, "completed");
|
|
1108
|
-
persistCallRecord(this.storePath, call);
|
|
1246
|
+
await persistCallRecord(this.storePath, call, this.stateRuntime);
|
|
1109
1247
|
} else if (result.isUnknown) {
|
|
1110
1248
|
keptUnknownProviderStatus += 1;
|
|
1111
1249
|
verified.set(callId, call);
|
|
@@ -1113,14 +1251,19 @@ var CallManager = class {
|
|
|
1113
1251
|
keptVerifiedActive += 1;
|
|
1114
1252
|
verified.set(callId, call);
|
|
1115
1253
|
}
|
|
1116
|
-
}
|
|
1254
|
+
}, () => {
|
|
1117
1255
|
keptVerificationFailures += 1;
|
|
1118
1256
|
verified.set(callId, call);
|
|
1119
|
-
})
|
|
1120
|
-
|
|
1121
|
-
|
|
1257
|
+
});
|
|
1258
|
+
task.catch(() => {});
|
|
1259
|
+
verifyTasks.push(task);
|
|
1260
|
+
}
|
|
1261
|
+
} catch (error) {
|
|
1262
|
+
admissionFailure = { error };
|
|
1122
1263
|
}
|
|
1123
|
-
await Promise.allSettled(verifyTasks
|
|
1264
|
+
const outcomes = await Promise.allSettled(verifyTasks);
|
|
1265
|
+
if (admissionFailure) throw admissionFailure.error;
|
|
1266
|
+
for (const outcome of outcomes) if (outcome.status === "rejected") throw outcome.reason;
|
|
1124
1267
|
if (skippedNoProviderCallId > 0) console.log(`[voice-call] Skipped ${skippedNoProviderCallId} restored call(s) with no providerCallId`);
|
|
1125
1268
|
if (skippedOlderThanMaxDuration > 0) console.log(`[voice-call] Skipped ${skippedOlderThanMaxDuration} restored call(s) older than maxDurationSeconds`);
|
|
1126
1269
|
for (const [status, count] of [...skippedTerminalStatuses].toSorted(([a], [b]) => a.localeCompare(b))) console.log(`[voice-call] Skipped ${count} restored call(s) with provider status: ${status}`);
|
|
@@ -1139,40 +1282,45 @@ var CallManager = class {
|
|
|
1139
1282
|
* Initiate an outbound call.
|
|
1140
1283
|
*/
|
|
1141
1284
|
async initiateCall(to, sessionKey, options) {
|
|
1142
|
-
return initiateCall(this.getContext(), to, sessionKey, options);
|
|
1285
|
+
return this.runOperation(() => initiateCall(this.getContext(), to, sessionKey, options));
|
|
1143
1286
|
}
|
|
1144
1287
|
/**
|
|
1145
1288
|
* Speak to user in an active call.
|
|
1146
1289
|
*/
|
|
1147
1290
|
async speak(callId, text, options) {
|
|
1148
|
-
return speak(this.getContext(), callId, text, options);
|
|
1291
|
+
return this.runOperation(() => speak(this.getContext(), callId, text, options));
|
|
1149
1292
|
}
|
|
1150
1293
|
/**
|
|
1151
1294
|
* Send DTMF digits to an active call.
|
|
1152
1295
|
*/
|
|
1153
1296
|
async sendDtmf(callId, digits) {
|
|
1154
|
-
return sendDtmf(this.getContext(), callId, digits);
|
|
1297
|
+
return this.runOperation(() => sendDtmf(this.getContext(), callId, digits));
|
|
1155
1298
|
}
|
|
1156
1299
|
/**
|
|
1157
1300
|
* Speak the initial message for a call (called when media stream connects).
|
|
1158
1301
|
*/
|
|
1159
1302
|
async speakInitialMessage(providerCallId) {
|
|
1160
|
-
return speakInitialMessage(this.getContext(), providerCallId);
|
|
1303
|
+
return this.runOperation(() => speakInitialMessage(this.getContext(), providerCallId));
|
|
1161
1304
|
}
|
|
1162
1305
|
/**
|
|
1163
1306
|
* Continue call: speak prompt, then wait for user's final transcript.
|
|
1164
1307
|
*/
|
|
1165
1308
|
async continueCall(callId, prompt) {
|
|
1166
|
-
return continueCall(this.getContext(), callId, prompt);
|
|
1309
|
+
return this.runOperation(() => continueCall(this.getContext(), callId, prompt));
|
|
1167
1310
|
}
|
|
1168
1311
|
/**
|
|
1169
1312
|
* End an active call.
|
|
1170
1313
|
*/
|
|
1171
1314
|
endCall(callId, options) {
|
|
1172
|
-
return endCall(this.getContext(), callId, options);
|
|
1315
|
+
return this.runOperation(() => endCall(this.getContext(), callId, options));
|
|
1173
1316
|
}
|
|
1174
1317
|
getContext() {
|
|
1175
1318
|
return {
|
|
1319
|
+
mutationQueue: this.mutationQueue,
|
|
1320
|
+
pendingCallAdmissions: this.pendingCallAdmissions,
|
|
1321
|
+
trackCallWork: this.trackCallWork,
|
|
1322
|
+
isStopping: () => this.closing,
|
|
1323
|
+
notifyHangupTimers: this.notifyHangupTimers,
|
|
1176
1324
|
activeCalls: this.activeCalls,
|
|
1177
1325
|
providerCallIdMap: this.providerCallIdMap,
|
|
1178
1326
|
processedEventIds: this.processedEventIds,
|
|
@@ -1181,6 +1329,7 @@ var CallManager = class {
|
|
|
1181
1329
|
config: this.config,
|
|
1182
1330
|
coreSession: this.coreSession,
|
|
1183
1331
|
storePath: this.storePath,
|
|
1332
|
+
stateRuntime: this.stateRuntime,
|
|
1184
1333
|
webhookUrl: this.webhookUrl,
|
|
1185
1334
|
activeTurnCalls: this.activeTurnCalls,
|
|
1186
1335
|
endCallOperations: this.endCallOperations,
|
|
@@ -1198,13 +1347,13 @@ var CallManager = class {
|
|
|
1198
1347
|
* Process a webhook event.
|
|
1199
1348
|
*/
|
|
1200
1349
|
processEvent(event) {
|
|
1201
|
-
return processEvent(this.getContext(), event);
|
|
1350
|
+
return this.runOperation(() => processEvent(this.getContext(), event));
|
|
1202
1351
|
}
|
|
1203
1352
|
createAutoResponseGuard(call) {
|
|
1204
1353
|
const owner = Symbol("automatic response");
|
|
1205
1354
|
this.autoResponseOwners.set(call, owner);
|
|
1206
1355
|
return {
|
|
1207
|
-
isCurrent: () => this.activeCalls.get(call.callId) === call && !TerminalStates.has(call.state) && this.autoResponseOwners.get(call) === owner,
|
|
1356
|
+
isCurrent: () => !this.closing && this.activeCalls.get(call.callId) === call && !TerminalStates.has(call.state) && this.autoResponseOwners.get(call) === owner,
|
|
1208
1357
|
release: () => {
|
|
1209
1358
|
if (this.autoResponseOwners.get(call) === owner) this.autoResponseOwners.delete(call);
|
|
1210
1359
|
}
|
|
@@ -1237,6 +1386,10 @@ var CallManager = class {
|
|
|
1237
1386
|
getCall(callId) {
|
|
1238
1387
|
return this.activeCalls.get(callId);
|
|
1239
1388
|
}
|
|
1389
|
+
/** Await admitted identity updates before resolving a token-bound stream's active call. */
|
|
1390
|
+
getCallForStream(callId) {
|
|
1391
|
+
return this.runOperation(() => this.mutationQueue.enqueue("state", async () => this.closing ? void 0 : this.activeCalls.get(callId)));
|
|
1392
|
+
}
|
|
1240
1393
|
/**
|
|
1241
1394
|
* Get an active call by provider call ID (e.g., Twilio CallSid).
|
|
1242
1395
|
*/
|
|
@@ -1257,13 +1410,13 @@ var CallManager = class {
|
|
|
1257
1410
|
async getCallFromMemoryOrStore(callId) {
|
|
1258
1411
|
const active = this.getCall(callId) ?? this.getCallByProviderCallId(callId);
|
|
1259
1412
|
if (active) return active;
|
|
1260
|
-
return findCallInStore(this.storePath, callId);
|
|
1413
|
+
return this.runOperation(() => findCallInStore(this.storePath, callId, this.stateRuntime));
|
|
1261
1414
|
}
|
|
1262
1415
|
/**
|
|
1263
1416
|
* Get call history (from persisted logs).
|
|
1264
1417
|
*/
|
|
1265
1418
|
async getCallHistory(limit = 50) {
|
|
1266
|
-
return getCallHistoryFromStore(this.storePath, limit);
|
|
1419
|
+
return this.runOperation(() => getCallHistoryFromStore(this.storePath, limit, this.stateRuntime));
|
|
1267
1420
|
}
|
|
1268
1421
|
};
|
|
1269
1422
|
//#endregion
|
|
@@ -2691,19 +2844,19 @@ var StreamDisconnectGrace = class {
|
|
|
2691
2844
|
const MAX_WEBHOOK_BODY_BYTES = WEBHOOK_BODY_READ_DEFAULTS.preAuth.maxBytes;
|
|
2692
2845
|
const WEBHOOK_BODY_TIMEOUT_MS = WEBHOOK_BODY_READ_DEFAULTS.preAuth.timeoutMs;
|
|
2693
2846
|
const MISSING_REMOTE_ADDRESS_IN_FLIGHT_KEY = "__voice_call_no_remote__";
|
|
2694
|
-
const loadRealtimeTranscriptionRuntime = createLazyRuntimeModule(() => import("./realtime-transcription.runtime-CbJAs5t_.
|
|
2695
|
-
const loadResponseGeneratorModule = createLazyRuntimeModule(() => import("./response-generator-
|
|
2696
|
-
function appendRecentTalkEventMetadata(
|
|
2697
|
-
const
|
|
2698
|
-
const recent = Array.isArray(
|
|
2847
|
+
const loadRealtimeTranscriptionRuntime = createLazyRuntimeModule(() => import("./realtime-transcription.runtime-CbJAs5t_.mjs"));
|
|
2848
|
+
const loadResponseGeneratorModule = createLazyRuntimeModule(() => import("./response-generator-DB1nElLO.mjs"));
|
|
2849
|
+
function appendRecentTalkEventMetadata(metadata, event) {
|
|
2850
|
+
const previous = metadata ?? {};
|
|
2851
|
+
const recent = Array.isArray(previous.recentTalkEvents) ? previous.recentTalkEvents.filter((entry) => Boolean(entry) && typeof entry === "object" && !Array.isArray(entry)) : [];
|
|
2699
2852
|
recent.push({
|
|
2700
2853
|
at: event.timestamp,
|
|
2701
2854
|
type: event.type,
|
|
2702
2855
|
sessionId: event.sessionId,
|
|
2703
2856
|
turnId: event.turnId
|
|
2704
2857
|
});
|
|
2705
|
-
|
|
2706
|
-
...
|
|
2858
|
+
return {
|
|
2859
|
+
...previous,
|
|
2707
2860
|
lastTalkEventAt: event.timestamp,
|
|
2708
2861
|
lastTalkEventType: event.type,
|
|
2709
2862
|
recentTalkEvents: recent.slice(-10)
|
|
@@ -2772,6 +2925,7 @@ var VoiceCallWebhookServer = class {
|
|
|
2772
2925
|
this.stopStaleCallReaper = null;
|
|
2773
2926
|
this.webhookInFlightLimiter = createWebhookInFlightLimiter();
|
|
2774
2927
|
this.mediaStreamHandler = null;
|
|
2928
|
+
this.streamSpeechGenerations = /* @__PURE__ */ new WeakMap();
|
|
2775
2929
|
this.realtimeHandler = null;
|
|
2776
2930
|
this.replayResponses = /* @__PURE__ */ new Map();
|
|
2777
2931
|
this.replayResponseCacheCalls = 0;
|
|
@@ -2858,8 +3012,11 @@ var VoiceCallWebhookServer = class {
|
|
|
2858
3012
|
interruptStreamReply(providerCallId, streamSid) {
|
|
2859
3013
|
const current = this.getCurrentStream(providerCallId, streamSid);
|
|
2860
3014
|
if (!current || this.shouldSuppressBargeInForInitialMessage(current.call)) return;
|
|
3015
|
+
const generation = Symbol("stream speech");
|
|
3016
|
+
this.streamSpeechGenerations.set(current.call, generation);
|
|
2861
3017
|
this.manager.invalidateAutoResponse(current.call);
|
|
2862
3018
|
current.provider.clearTtsQueue(providerCallId);
|
|
3019
|
+
return generation;
|
|
2863
3020
|
}
|
|
2864
3021
|
/**
|
|
2865
3022
|
* Initialize media streaming with the selected realtime transcription provider.
|
|
@@ -2924,12 +3081,12 @@ var VoiceCallWebhookServer = class {
|
|
|
2924
3081
|
this.logger.info(`Ignoring transcript from inactive stream ${streamSid} (${providerCallId})`);
|
|
2925
3082
|
return;
|
|
2926
3083
|
}
|
|
2927
|
-
const { call
|
|
3084
|
+
const { call } = current;
|
|
2928
3085
|
if (this.shouldSuppressBargeInForInitialMessage(call)) {
|
|
2929
3086
|
this.logger.info(`Ignoring barge transcript while initial message is still playing (${providerCallId})`);
|
|
2930
3087
|
return;
|
|
2931
3088
|
}
|
|
2932
|
-
|
|
3089
|
+
const generation = this.interruptStreamReply(providerCallId, streamSid);
|
|
2933
3090
|
const event = {
|
|
2934
3091
|
id: `stream-transcript-${Date.now()}`,
|
|
2935
3092
|
type: "call.speech",
|
|
@@ -2939,7 +3096,9 @@ var VoiceCallWebhookServer = class {
|
|
|
2939
3096
|
transcript,
|
|
2940
3097
|
isFinal: true
|
|
2941
3098
|
};
|
|
2942
|
-
this.processEventWithAutoResponse(event)
|
|
3099
|
+
this.processEventWithAutoResponse(event, () => this.streamSpeechGenerations.get(call) === generation && this.getCurrentStream(providerCallId, streamSid)?.call === call).catch((err) => {
|
|
3100
|
+
this.logger.error(`Error processing stream transcript: ${String(err)}`);
|
|
3101
|
+
});
|
|
2943
3102
|
},
|
|
2944
3103
|
onSpeechStart: (providerCallId, streamSid) => this.interruptStreamReply(providerCallId, streamSid),
|
|
2945
3104
|
onPartialTranscript: (callId, partial, streamSid) => {
|
|
@@ -2948,7 +3107,9 @@ var VoiceCallWebhookServer = class {
|
|
|
2948
3107
|
},
|
|
2949
3108
|
onTalkEvent: (providerCallId, streamSid, event) => {
|
|
2950
3109
|
const current = this.getCurrentStream(providerCallId, streamSid);
|
|
2951
|
-
if (current)
|
|
3110
|
+
if (current) this.manager.updateCallMetadata(current.call, (metadata) => this.getCurrentStream(providerCallId, streamSid) ? appendRecentTalkEventMetadata(metadata, event) : metadata).catch((error) => {
|
|
3111
|
+
this.logger.warn(`Failed to update stream call metadata: ${String(error)}`);
|
|
3112
|
+
});
|
|
2952
3113
|
},
|
|
2953
3114
|
onConnect: (callId, streamSid) => {
|
|
2954
3115
|
this.logger.info(`Media stream connected: ${callId} -> ${streamSid}`);
|
|
@@ -3203,7 +3364,7 @@ var VoiceCallWebhookServer = class {
|
|
|
3203
3364
|
return this.realtimeHandler.buildTwiMLPayload(req, realtimeParams);
|
|
3204
3365
|
}
|
|
3205
3366
|
const parsed = this.provider.parseWebhookEvent(ctx, { verifiedRequestKey: verification.verifiedRequestKey });
|
|
3206
|
-
if (!isReplay && this.processParsedEvents(parsed.events)) verification.releaseReplay?.();
|
|
3367
|
+
if (!isReplay && await this.processParsedEvents(parsed.events)) verification.releaseReplay?.();
|
|
3207
3368
|
return normalizeWebhookResponse(parsed);
|
|
3208
3369
|
};
|
|
3209
3370
|
if (isReplay) return await buildResponse();
|
|
@@ -3317,20 +3478,20 @@ var VoiceCallWebhookServer = class {
|
|
|
3317
3478
|
default: return false;
|
|
3318
3479
|
}
|
|
3319
3480
|
}
|
|
3320
|
-
processParsedEvents(events) {
|
|
3481
|
+
async processParsedEvents(events) {
|
|
3321
3482
|
let replayable = false;
|
|
3322
3483
|
for (const event of events) try {
|
|
3323
|
-
replayable = this.processEventWithAutoResponse(event) || replayable;
|
|
3484
|
+
replayable = await this.processEventWithAutoResponse(event) || replayable;
|
|
3324
3485
|
} catch (err) {
|
|
3325
3486
|
this.logger.error(`Error processing event ${event.type}: ${String(err)}`);
|
|
3326
3487
|
throw err;
|
|
3327
3488
|
}
|
|
3328
3489
|
return replayable;
|
|
3329
3490
|
}
|
|
3330
|
-
processEventWithAutoResponse(event) {
|
|
3331
|
-
const result = this.manager.processEvent(event);
|
|
3491
|
+
async processEventWithAutoResponse(event, isCurrent) {
|
|
3492
|
+
const result = await this.manager.processEvent(event);
|
|
3332
3493
|
if (result.kind !== "final-speech") return result.replayable === true;
|
|
3333
|
-
if (result.waiterResolved) return false;
|
|
3494
|
+
if (result.waiterResolved || isCurrent && !isCurrent()) return false;
|
|
3334
3495
|
const callMode = result.call.metadata?.mode;
|
|
3335
3496
|
if (result.call.direction !== "inbound" && callMode !== "conversation") return false;
|
|
3336
3497
|
this.handleInboundResponse(result.call.callId, result.transcript).catch((err) => {
|
|
@@ -3379,7 +3540,10 @@ var VoiceCallWebhookServer = class {
|
|
|
3379
3540
|
return false;
|
|
3380
3541
|
}
|
|
3381
3542
|
this.logger.info(`AI response queued ${callId} chars=${text.length}`);
|
|
3382
|
-
return (await this.manager.speak(callId, text, {
|
|
3543
|
+
return (await this.manager.speak(callId, text, {
|
|
3544
|
+
listenAfterPlayback: true,
|
|
3545
|
+
isCurrent: response.isCurrent
|
|
3546
|
+
})).success;
|
|
3383
3547
|
};
|
|
3384
3548
|
try {
|
|
3385
3549
|
const { generateVoiceResponse } = await loadResponseGeneratorModule();
|
|
@@ -3421,12 +3585,12 @@ const REALTIME_VOICE_CONSULT_SYSTEM_PROMPT = [
|
|
|
3421
3585
|
"Do not print secret values or dump environment variables; only check whether required configuration is present.",
|
|
3422
3586
|
"Be accurate, brief, and speakable."
|
|
3423
3587
|
].join(" ");
|
|
3424
|
-
const loadTelnyxProvider = createLazyRuntimeModule(() => import("./telnyx-
|
|
3425
|
-
const loadTwilioProvider = createLazyRuntimeModule(() => import("./twilio-
|
|
3426
|
-
const loadPlivoProvider = createLazyRuntimeModule(() => import("./plivo-
|
|
3427
|
-
const loadMockProvider = createLazyRuntimeModule(() => import("./mock-
|
|
3428
|
-
const loadRealtimeVoiceRuntime = createLazyRuntimeModule(() => import("./realtime-voice.runtime-vtdCOWg-.
|
|
3429
|
-
const loadRealtimeHandler = createLazyRuntimeModule(() => import("./realtime-handler-
|
|
3588
|
+
const loadTelnyxProvider = createLazyRuntimeModule(() => import("./telnyx-BY3ef4Cc.mjs"));
|
|
3589
|
+
const loadTwilioProvider = createLazyRuntimeModule(() => import("./twilio-DWZ4HVmF.mjs"));
|
|
3590
|
+
const loadPlivoProvider = createLazyRuntimeModule(() => import("./plivo-DWYNkAQ3.mjs"));
|
|
3591
|
+
const loadMockProvider = createLazyRuntimeModule(() => import("./mock-CcYEAUhV.mjs"));
|
|
3592
|
+
const loadRealtimeVoiceRuntime = createLazyRuntimeModule(() => import("./realtime-voice.runtime-vtdCOWg-.mjs"));
|
|
3593
|
+
const loadRealtimeHandler = createLazyRuntimeModule(() => import("./realtime-handler-CaoetLrM.mjs"));
|
|
3430
3594
|
function resolveVoiceCallConsultSessionKey(call) {
|
|
3431
3595
|
return resolveVoiceCallSessionKey({
|
|
3432
3596
|
config: call.config,
|
|
@@ -3451,13 +3615,6 @@ function mapVoiceCallConsultTranscript(call, context) {
|
|
|
3451
3615
|
function createRuntimeResourceLifecycle(params) {
|
|
3452
3616
|
let tunnelResult = null;
|
|
3453
3617
|
let stopPromise = null;
|
|
3454
|
-
const runStep = async (step, suppressErrors) => {
|
|
3455
|
-
if (suppressErrors) {
|
|
3456
|
-
await step().catch(() => {});
|
|
3457
|
-
return;
|
|
3458
|
-
}
|
|
3459
|
-
await step();
|
|
3460
|
-
};
|
|
3461
3618
|
return {
|
|
3462
3619
|
setTunnelResult: (result) => {
|
|
3463
3620
|
tunnelResult = result;
|
|
@@ -3466,15 +3623,20 @@ function createRuntimeResourceLifecycle(params) {
|
|
|
3466
3623
|
if (stopPromise) return stopPromise;
|
|
3467
3624
|
const suppressErrors = opts?.suppressErrors ?? false;
|
|
3468
3625
|
stopPromise = (async () => {
|
|
3469
|
-
|
|
3470
|
-
|
|
3471
|
-
|
|
3472
|
-
|
|
3473
|
-
|
|
3474
|
-
|
|
3475
|
-
|
|
3476
|
-
|
|
3477
|
-
|
|
3626
|
+
let failure;
|
|
3627
|
+
for (const step of [
|
|
3628
|
+
async () => {
|
|
3629
|
+
await tunnelResult?.stop();
|
|
3630
|
+
},
|
|
3631
|
+
() => cleanupTailscaleExposure(params.config),
|
|
3632
|
+
() => params.webhookServer.stop(),
|
|
3633
|
+
() => params.manager.stop()
|
|
3634
|
+
]) try {
|
|
3635
|
+
await step();
|
|
3636
|
+
} catch (error) {
|
|
3637
|
+
failure ??= { error };
|
|
3638
|
+
}
|
|
3639
|
+
if (failure && !suppressErrors) throw failure.error;
|
|
3478
3640
|
})();
|
|
3479
3641
|
return stopPromise;
|
|
3480
3642
|
}
|
|
@@ -3587,7 +3749,7 @@ async function createVoiceCallRuntime(params) {
|
|
|
3587
3749
|
if (!validation.valid) throw new Error(`Invalid voice-call config: ${validation.errors.join("; ")}`);
|
|
3588
3750
|
const provider = await resolveProvider(config);
|
|
3589
3751
|
if (stateRuntime) setVoiceCallStateRuntime({ state: stateRuntime });
|
|
3590
|
-
const manager = new CallManager(config, void 0, cfg.session);
|
|
3752
|
+
const manager = new CallManager(config, void 0, cfg.session, stateRuntime);
|
|
3591
3753
|
const realtimeVoiceRuntime = config.realtime.enabled ? await loadRealtimeVoiceRuntime() : null;
|
|
3592
3754
|
const webhookServer = new VoiceCallWebhookServer(config, manager, provider, coreConfig, fullConfig ?? coreConfig, agentRuntime, log);
|
|
3593
3755
|
if (realtimeVoiceRuntime) {
|
|
@@ -3609,12 +3771,15 @@ async function createVoiceCallRuntime(params) {
|
|
|
3609
3771
|
configuredProviderId: effectiveConfig.realtime.provider,
|
|
3610
3772
|
providerConfigs: effectiveConfig.realtime.providers,
|
|
3611
3773
|
cfg,
|
|
3612
|
-
agentId
|
|
3774
|
+
agentId,
|
|
3775
|
+
surface: "gateway-relay",
|
|
3776
|
+
useProviderDefaultModel: true
|
|
3613
3777
|
});
|
|
3614
3778
|
return {
|
|
3615
3779
|
agentId,
|
|
3616
3780
|
provider: resolved.provider,
|
|
3617
3781
|
providerConfig: resolved.providerConfig,
|
|
3782
|
+
capabilities: resolved.capabilities,
|
|
3618
3783
|
instructions: resolveRealtimeInstructions(call)
|
|
3619
3784
|
};
|
|
3620
3785
|
};
|
|
@@ -3696,7 +3861,8 @@ async function createVoiceCallRuntime(params) {
|
|
|
3696
3861
|
}
|
|
3697
3862
|
const lifecycle = createRuntimeResourceLifecycle({
|
|
3698
3863
|
config,
|
|
3699
|
-
webhookServer
|
|
3864
|
+
webhookServer,
|
|
3865
|
+
manager
|
|
3700
3866
|
});
|
|
3701
3867
|
const localUrl = await webhookServer.start();
|
|
3702
3868
|
try {
|