@openclaw/voice-call 2026.9.3 → 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-D7qQRwUE.js → .setup/cli-z1onSLj4.mjs} +7 -7
- package/dist/{config-DQwvsxeV.js → .setup/config-72FnMWHb.mjs} +3 -3
- package/dist/{guarded-json-api-Z9SuGiD_.js → .setup/guarded-json-api-CuLkeTrl.mjs} +17 -39
- package/dist/{mock-C57qj18W.js → .setup/mock-CcYEAUhV.mjs} +1 -1
- package/dist/{plivo-qSdVTUcE.js → .setup/plivo-DWYNkAQ3.mjs} +2 -2
- package/dist/{realtime-handler-BSW48gqM.js → .setup/realtime-handler-CaoetLrM.mjs} +411 -144
- package/dist/{response-generator-IX26g0hi.js → .setup/response-generator-DB1nElLO.mjs} +2 -2
- package/dist/{runtime-entry-B8SNb2qD.js → .setup/runtime-entry-YWSSnAsH.mjs} +472 -302
- package/dist/{store-path-M0GXxUfv.js → .setup/store-path-B1j1up4_.mjs} +91 -55
- package/dist/{telnyx-B8shXuBM.js → .setup/telnyx-BY3ef4Cc.mjs} +1 -1
- package/dist/{twilio-DhsTO8-E.js → .setup/twilio-DWZ4HVmF.mjs} +9 -23
- package/dist/doctor-contract-api.js +15 -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 -0
- 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,9 +1,9 @@
|
|
|
1
|
-
import { d as REALTIME_VOICE_END_CALL_TOOL_NAME, s as resolveVoiceCallPublicPathPrefix } from "./config-
|
|
2
|
-
import { c as canonicalizeVoiceCallMediaBase64, o as WebSocket, s as WebSocketServer } from "./runtime-entry-
|
|
1
|
+
import { d as REALTIME_VOICE_END_CALL_TOOL_NAME, s as resolveVoiceCallPublicPathPrefix } from "./config-72FnMWHb.mjs";
|
|
2
|
+
import { c as canonicalizeVoiceCallMediaBase64, o as WebSocket, s as WebSocketServer } from "./runtime-entry-YWSSnAsH.mjs";
|
|
3
3
|
import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
|
|
4
4
|
import { asNullableRecord, asOptionalObjectRecord } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
5
5
|
import { createSubsystemLogger } from "openclaw/plugin-sdk/runtime-env";
|
|
6
|
-
import { REALTIME_VOICE_AGENT_CONSULT_TOOL_NAME, REALTIME_VOICE_AUDIO_FORMAT_G711_ULAW_8KHZ, buildRealtimeVoiceAgentConsultWorkingResponse, buildRealtimeVoiceAgentErrorProviderResult, calculateMulawRms, createRealtimeVoiceSessionHarness, createSpeechThresholdGate, readRealtimeVoiceConsultQuestion, readSpeakableRealtimeVoiceToolResult } from "openclaw/plugin-sdk/realtime-voice";
|
|
6
|
+
import { REALTIME_VOICE_AGENT_CONSULT_TOOL_NAME, REALTIME_VOICE_AUDIO_FORMAT_G711_ULAW_8KHZ, buildRealtimeVoiceAgentConsultWorkingResponse, buildRealtimeVoiceAgentErrorProviderResult, calculateMulawRms, createRealtimeVoiceSessionHarness, createSpeechThresholdGate, readRealtimeVoiceConsultQuestion, readSpeakableRealtimeVoiceToolResult, resolveRealtimeVoiceBargeIn, resolveRealtimeVoiceSessionPolicy } from "openclaw/plugin-sdk/realtime-voice";
|
|
7
7
|
import { normalizeWebhookPath } from "openclaw/plugin-sdk/webhook-ingress";
|
|
8
8
|
import { isFutureDateTimestampMs, resolveExpiresAtMsFromDurationMs } from "openclaw/plugin-sdk/number-runtime";
|
|
9
9
|
import { randomUUID } from "node:crypto";
|
|
@@ -15,6 +15,8 @@ const TELEPHONY_CHUNK_BYTES = 160;
|
|
|
15
15
|
const LEAD_MS = 160;
|
|
16
16
|
const DEFAULT_MAX_QUEUED_AUDIO_BYTES = TELEPHONY_SAMPLE_RATE * 120;
|
|
17
17
|
const QUEUE_COMPACT_HEAD_THRESHOLD = 256;
|
|
18
|
+
const MAX_PLAYBACK_SEGMENTS = 128;
|
|
19
|
+
const MAX_PENDING_MARK_BOUNDARIES = 64;
|
|
18
20
|
/** Paces outgoing mulaw audio frames at telephony cadence. */
|
|
19
21
|
var RealtimeAudioPacer = class {
|
|
20
22
|
constructor(params) {
|
|
@@ -25,9 +27,18 @@ var RealtimeAudioPacer = class {
|
|
|
25
27
|
this.queuedAudioBytes = 0;
|
|
26
28
|
this.closed = false;
|
|
27
29
|
this.streamClockMs = null;
|
|
30
|
+
this.playbackSegments = [];
|
|
31
|
+
this.sentAudioMs = 0;
|
|
32
|
+
this.retiredAudioMs = 0;
|
|
33
|
+
this.confirmedPlayedMs = 0;
|
|
34
|
+
this.playbackMarkPrefix = `openclaw-playout-${randomUUID()}`;
|
|
35
|
+
this.playbackMarkSequence = 0;
|
|
36
|
+
this.lastPlaybackMarkMs = 0;
|
|
37
|
+
this.markBoundaries = [];
|
|
38
|
+
this.retiredItemOffsets = /* @__PURE__ */ new Map();
|
|
28
39
|
}
|
|
29
40
|
/** Queue mulaw audio and split it into 20ms-ish telephony chunks. */
|
|
30
|
-
sendAudio(muLaw) {
|
|
41
|
+
sendAudio(muLaw, metadata) {
|
|
31
42
|
if (this.closed || muLaw.length === 0) return;
|
|
32
43
|
const maxQueuedAudioBytes = this.params.maxQueuedAudioBytes ?? DEFAULT_MAX_QUEUED_AUDIO_BYTES;
|
|
33
44
|
for (let offset = 0; offset < muLaw.length; offset += TELEPHONY_CHUNK_BYTES) {
|
|
@@ -36,15 +47,42 @@ var RealtimeAudioPacer = class {
|
|
|
36
47
|
this.failBackpressure();
|
|
37
48
|
return;
|
|
38
49
|
}
|
|
50
|
+
const durationMs = chunk.length / 8;
|
|
51
|
+
const segment = this.extendPlaybackSegment(metadata?.itemId, durationMs);
|
|
52
|
+
if (!segment) {
|
|
53
|
+
this.failBackpressure();
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
39
56
|
this.queue.push({
|
|
40
57
|
type: "audio",
|
|
41
58
|
chunk,
|
|
42
|
-
durationMs
|
|
59
|
+
durationMs,
|
|
60
|
+
segment
|
|
43
61
|
});
|
|
44
62
|
this.queuedAudioBytes += chunk.length;
|
|
45
63
|
}
|
|
46
64
|
this.ensurePump();
|
|
47
65
|
}
|
|
66
|
+
/**
|
|
67
|
+
* Retained provider items in playback order with consumed playout duration.
|
|
68
|
+
* Queued audio has not reached the telephony line, so unplayed items report zero.
|
|
69
|
+
*/
|
|
70
|
+
getPlaybackState() {
|
|
71
|
+
let remaining = Math.max(0, this.confirmedPlayedMs - this.retiredAudioMs);
|
|
72
|
+
const playedByItem = /* @__PURE__ */ new Map();
|
|
73
|
+
for (const segment of this.playbackSegments) {
|
|
74
|
+
const consumed = Math.min(remaining, segment.sentMs);
|
|
75
|
+
remaining -= consumed;
|
|
76
|
+
if (segment.itemId !== void 0) {
|
|
77
|
+
const previousMs = playedByItem.get(segment.itemId) ?? this.retiredItemOffsets.get(segment.itemId) ?? 0;
|
|
78
|
+
playedByItem.set(segment.itemId, previousMs + consumed);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
return Array.from(playedByItem, ([itemId, audioEndMs]) => ({
|
|
82
|
+
itemId,
|
|
83
|
+
audioEndMs: Math.floor(audioEndMs)
|
|
84
|
+
}));
|
|
85
|
+
}
|
|
48
86
|
/** Queue a provider mark frame after prior audio frames. */
|
|
49
87
|
sendMark(name) {
|
|
50
88
|
if (this.closed || !name) return;
|
|
@@ -54,14 +92,32 @@ var RealtimeAudioPacer = class {
|
|
|
54
92
|
});
|
|
55
93
|
this.ensurePump();
|
|
56
94
|
}
|
|
95
|
+
/** Retire the playback prefix once the carrier confirms playout reached the mark. */
|
|
96
|
+
acknowledgeMark(name) {
|
|
97
|
+
if (this.closed || !name) return;
|
|
98
|
+
const boundaryIndex = this.markBoundaries.findIndex((boundary) => boundary.name === name);
|
|
99
|
+
if (boundaryIndex < 0) return;
|
|
100
|
+
const boundary = this.markBoundaries[boundaryIndex];
|
|
101
|
+
this.markBoundaries.splice(0, boundaryIndex + 1);
|
|
102
|
+
if (!boundary) return;
|
|
103
|
+
while (this.playbackSegments.length > 0) {
|
|
104
|
+
const head = this.playbackSegments[0];
|
|
105
|
+
if (!head || head.sentMs < head.totalMs || head.lastSentEndMs === void 0 || head.lastSentEndMs > boundary.sentMs) break;
|
|
106
|
+
const retired = this.playbackSegments.shift();
|
|
107
|
+
if (retired) {
|
|
108
|
+
this.retiredAudioMs += retired.sentMs;
|
|
109
|
+
if (retired.itemId !== void 0) this.retiredItemOffsets.set(retired.itemId, (this.retiredItemOffsets.get(retired.itemId) ?? 0) + retired.sentMs);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
this.confirmedPlayedMs = Math.max(this.confirmedPlayedMs, Math.min(boundary.sentMs, this.sentAudioMs));
|
|
113
|
+
}
|
|
57
114
|
/** Clear queued audio and notify the provider stream. */
|
|
58
115
|
clearAudio() {
|
|
59
116
|
if (this.closed) return 0;
|
|
60
117
|
const clearedAudioBytes = this.queuedAudioBytes;
|
|
61
118
|
this.clearTimer();
|
|
62
119
|
this.resetQueue();
|
|
63
|
-
this.
|
|
64
|
-
this.streamClockMs = null;
|
|
120
|
+
this.resetPlaybackState();
|
|
65
121
|
this.params.send(this.params.serializer.clear());
|
|
66
122
|
return clearedAudioBytes;
|
|
67
123
|
}
|
|
@@ -74,8 +130,33 @@ var RealtimeAudioPacer = class {
|
|
|
74
130
|
this.closed = true;
|
|
75
131
|
this.clearTimer();
|
|
76
132
|
this.resetQueue();
|
|
133
|
+
this.resetPlaybackState();
|
|
134
|
+
}
|
|
135
|
+
extendPlaybackSegment(itemId, durationMs) {
|
|
136
|
+
let segment = this.playbackSegments.at(-1);
|
|
137
|
+
if (!segment || segment.itemId !== itemId) {
|
|
138
|
+
if (this.playbackSegments.length >= MAX_PLAYBACK_SEGMENTS) return null;
|
|
139
|
+
segment = {
|
|
140
|
+
itemId,
|
|
141
|
+
totalMs: 0,
|
|
142
|
+
sentMs: 0
|
|
143
|
+
};
|
|
144
|
+
this.playbackSegments.push(segment);
|
|
145
|
+
}
|
|
146
|
+
segment.totalMs += durationMs;
|
|
147
|
+
return segment;
|
|
148
|
+
}
|
|
149
|
+
resetPlaybackState() {
|
|
150
|
+
this.playbackSegments = [];
|
|
77
151
|
this.queuedAudioBytes = 0;
|
|
152
|
+
this.sentAudioMs = 0;
|
|
153
|
+
this.retiredAudioMs = 0;
|
|
154
|
+
this.confirmedPlayedMs = 0;
|
|
155
|
+
this.lastPlaybackMarkMs = 0;
|
|
156
|
+
this.markBoundaries = [];
|
|
157
|
+
this.retiredItemOffsets.clear();
|
|
78
158
|
this.streamClockMs = null;
|
|
159
|
+
this.params.onPlaybackReset?.();
|
|
79
160
|
}
|
|
80
161
|
/** Clear the scheduled pump timer. */
|
|
81
162
|
clearTimer() {
|
|
@@ -123,7 +204,7 @@ var RealtimeAudioPacer = class {
|
|
|
123
204
|
while (this.pendingQueueSize > 0 && this.streamClockMs < now + LEAD_MS) {
|
|
124
205
|
const item = this.takeNextItem();
|
|
125
206
|
if (!item) break;
|
|
126
|
-
if (!(item.type === "audio" ? this.sendAudioItem(item) : this.
|
|
207
|
+
if (!(item.type === "audio" ? this.sendAudioItem(item) : this.sendMarkItem(item))) {
|
|
127
208
|
this.resetQueue();
|
|
128
209
|
this.queuedAudioBytes = 0;
|
|
129
210
|
this.streamClockMs = null;
|
|
@@ -140,7 +221,30 @@ var RealtimeAudioPacer = class {
|
|
|
140
221
|
sendAudioItem(item) {
|
|
141
222
|
this.queuedAudioBytes = Math.max(0, this.queuedAudioBytes - item.chunk.length);
|
|
142
223
|
const sent = this.params.send(this.params.serializer.media(item.chunk.toString("base64")));
|
|
224
|
+
if (sent) {
|
|
225
|
+
item.segment.sentMs += item.durationMs;
|
|
226
|
+
this.sentAudioMs += item.durationMs;
|
|
227
|
+
item.segment.lastSentEndMs = this.sentAudioMs;
|
|
228
|
+
}
|
|
143
229
|
this.streamClockMs = (this.streamClockMs ?? performance.now()) + item.durationMs;
|
|
230
|
+
if (!sent || item.segment.itemId === void 0 || this.sentAudioMs - this.lastPlaybackMarkMs < LEAD_MS) return sent;
|
|
231
|
+
this.lastPlaybackMarkMs = this.sentAudioMs;
|
|
232
|
+
this.playbackMarkSequence += 1;
|
|
233
|
+
return this.sendMarkItem({
|
|
234
|
+
type: "mark",
|
|
235
|
+
name: `${this.playbackMarkPrefix}-${this.playbackMarkSequence}`
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
/** Send a queued mark frame and bind it to the playback prefix before it. */
|
|
239
|
+
sendMarkItem(item) {
|
|
240
|
+
const sent = this.params.send(this.params.serializer.mark(item.name));
|
|
241
|
+
if (sent) {
|
|
242
|
+
this.markBoundaries.push({
|
|
243
|
+
name: item.name,
|
|
244
|
+
sentMs: this.sentAudioMs
|
|
245
|
+
});
|
|
246
|
+
if (this.markBoundaries.length > MAX_PENDING_MARK_BOUNDARIES) this.markBoundaries.shift();
|
|
247
|
+
}
|
|
144
248
|
return sent;
|
|
145
249
|
}
|
|
146
250
|
};
|
|
@@ -421,26 +525,27 @@ async function waitForNativeConsult(state) {
|
|
|
421
525
|
result
|
|
422
526
|
})), state.cancellation.then(() => ({ kind: "cancelled" }))]);
|
|
423
527
|
}
|
|
424
|
-
function appendRecentTalkEventMetadata(
|
|
425
|
-
|
|
426
|
-
const
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
528
|
+
function appendRecentTalkEventMetadata(metadata, event) {
|
|
529
|
+
const previous = metadata ?? {};
|
|
530
|
+
const recent = Array.isArray(previous.recentTalkEvents) ? previous.recentTalkEvents : [];
|
|
531
|
+
return {
|
|
532
|
+
...previous,
|
|
533
|
+
lastTalkEventAt: event.timestamp,
|
|
534
|
+
lastTalkEventType: event.type,
|
|
535
|
+
recentTalkEvents: [...recent, {
|
|
536
|
+
id: event.id,
|
|
537
|
+
brain: event.brain,
|
|
538
|
+
mode: event.mode,
|
|
539
|
+
provider: event.provider,
|
|
540
|
+
seq: event.seq,
|
|
541
|
+
sessionId: event.sessionId,
|
|
542
|
+
timestamp: event.timestamp,
|
|
543
|
+
transport: event.transport,
|
|
544
|
+
type: event.type,
|
|
545
|
+
...event.turnId ? { turnId: event.turnId } : {},
|
|
546
|
+
...event.final !== void 0 ? { final: event.final } : {}
|
|
547
|
+
}].slice(-12)
|
|
548
|
+
};
|
|
444
549
|
}
|
|
445
550
|
function rejectRealtimeUpgrade(socket, status) {
|
|
446
551
|
const reason = status === 401 ? "Unauthorized" : "Service Unavailable";
|
|
@@ -470,6 +575,7 @@ var RealtimeCallHandler = class {
|
|
|
470
575
|
this.consultSessionsByCallId = /* @__PURE__ */ new Map();
|
|
471
576
|
this.nativeConsultsInFlightByCallId = /* @__PURE__ */ new Map();
|
|
472
577
|
this.terminationAttempts = /* @__PURE__ */ new Set();
|
|
578
|
+
this.admissions = /* @__PURE__ */ new Set();
|
|
473
579
|
this.closePromise = null;
|
|
474
580
|
this.closing = false;
|
|
475
581
|
this.publicOrigin = null;
|
|
@@ -537,7 +643,19 @@ var RealtimeCallHandler = class {
|
|
|
537
643
|
let activeStreamSid = "unknown";
|
|
538
644
|
let lastMediaTimestamp;
|
|
539
645
|
let lastMediaGapWarnAt = 0;
|
|
540
|
-
|
|
646
|
+
let admitting = false;
|
|
647
|
+
const pendingFrames = [];
|
|
648
|
+
let pendingBytes = 0;
|
|
649
|
+
const handleMessage = (data) => {
|
|
650
|
+
if (admitting) {
|
|
651
|
+
pendingBytes += Math.max(1, data.byteLength);
|
|
652
|
+
if (pendingBytes > MAX_REALTIME_WS_BUFFERED_BYTES) {
|
|
653
|
+
ws.terminate();
|
|
654
|
+
return;
|
|
655
|
+
}
|
|
656
|
+
pendingFrames.push(data);
|
|
657
|
+
return;
|
|
658
|
+
}
|
|
541
659
|
try {
|
|
542
660
|
const frame = adapter.parseInbound(data.toString());
|
|
543
661
|
if (frame.kind === "ignored") return;
|
|
@@ -546,10 +664,27 @@ var RealtimeCallHandler = class {
|
|
|
546
664
|
initialized = true;
|
|
547
665
|
activeCallSid = frame.providerCallId;
|
|
548
666
|
activeStreamSid = frame.streamId;
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
667
|
+
admitting = true;
|
|
668
|
+
ws.pause();
|
|
669
|
+
const admission = this.handleCall(frame.streamId, frame.providerCallId, ws, callerMeta, adapter).then(async (nextBinding) => {
|
|
670
|
+
telephonyBinding = nextBinding;
|
|
671
|
+
if (!nextBinding) return;
|
|
672
|
+
if (this.closing || ws.readyState !== WebSocket.OPEN) {
|
|
673
|
+
await nextBinding.close(this.serverClosingSockets.has(ws) ? "shutdown" : "disconnect");
|
|
674
|
+
return;
|
|
675
|
+
}
|
|
676
|
+
this.streamDisconnectLifecycle.connect(activeCallSid, activeStreamSid);
|
|
677
|
+
}).catch((error) => {
|
|
678
|
+
console.error("[voice-call] realtime admission failed:", error);
|
|
679
|
+
ws.close(1011, "Failed to persist call");
|
|
680
|
+
}).finally(() => {
|
|
681
|
+
admitting = false;
|
|
682
|
+
if (ws.readyState === WebSocket.OPEN && !this.closing) for (const pending of pendingFrames) handleMessage(pending);
|
|
683
|
+
ws.resume();
|
|
684
|
+
pendingFrames.length = 0;
|
|
685
|
+
pendingBytes = 0;
|
|
686
|
+
});
|
|
687
|
+
this.trackShutdownWork(admission, this.admissions);
|
|
553
688
|
return;
|
|
554
689
|
}
|
|
555
690
|
if (!telephonyBinding) return;
|
|
@@ -572,7 +707,8 @@ var RealtimeCallHandler = class {
|
|
|
572
707
|
return;
|
|
573
708
|
}
|
|
574
709
|
if (frame.kind === "mark") {
|
|
575
|
-
telephonyBinding.
|
|
710
|
+
telephonyBinding.acknowledgeCarrierMark(frame.name);
|
|
711
|
+
telephonyBinding.bridge.acknowledgeMark(frame.name);
|
|
576
712
|
return;
|
|
577
713
|
}
|
|
578
714
|
if (frame.kind === "error") {
|
|
@@ -583,7 +719,8 @@ var RealtimeCallHandler = class {
|
|
|
583
719
|
} catch (error) {
|
|
584
720
|
console.error("[voice-call] realtime WS parse failed:", error);
|
|
585
721
|
}
|
|
586
|
-
}
|
|
722
|
+
};
|
|
723
|
+
ws.on("message", handleMessage);
|
|
587
724
|
ws.on("close", () => {
|
|
588
725
|
this.activeSockets.delete(ws);
|
|
589
726
|
const reason = this.serverClosingSockets.has(ws) ? "shutdown" : "disconnect";
|
|
@@ -604,7 +741,7 @@ var RealtimeCallHandler = class {
|
|
|
604
741
|
this.closing = true;
|
|
605
742
|
this.pendingStreamTokens.clear();
|
|
606
743
|
const sockets = [...this.activeSockets];
|
|
607
|
-
this.closePromise = Promise.
|
|
744
|
+
this.closePromise = Promise.allSettled([shutdownBarrier, ...sockets.map((ws) => new Promise((resolve) => {
|
|
608
745
|
if (ws.readyState === WebSocket.CLOSED) {
|
|
609
746
|
resolve();
|
|
610
747
|
return;
|
|
@@ -612,15 +749,29 @@ var RealtimeCallHandler = class {
|
|
|
612
749
|
this.serverClosingSockets.add(ws);
|
|
613
750
|
ws.once("close", () => resolve());
|
|
614
751
|
ws.terminate();
|
|
615
|
-
}))]).then(async () => {
|
|
616
|
-
await Promise.
|
|
752
|
+
}))]).then(async (results) => {
|
|
753
|
+
results.push(...await Promise.allSettled(this.admissions));
|
|
754
|
+
results.push(...await Promise.allSettled(this.terminationAttempts));
|
|
617
755
|
this.pendingStreamTokens.clear();
|
|
756
|
+
const failure = results.find((result) => result.status === "rejected");
|
|
757
|
+
if (failure?.status === "rejected") throw failure.reason;
|
|
758
|
+
if (this.shutdownFailure) throw this.shutdownFailure.error;
|
|
618
759
|
}).finally(() => {
|
|
619
760
|
this.closing = false;
|
|
620
761
|
this.closePromise = null;
|
|
762
|
+
this.shutdownFailure = void 0;
|
|
621
763
|
});
|
|
622
764
|
return this.closePromise;
|
|
623
765
|
}
|
|
766
|
+
trackShutdownWork(work, pending) {
|
|
767
|
+
pending.add(work);
|
|
768
|
+
work.then(() => {
|
|
769
|
+
pending.delete(work);
|
|
770
|
+
}, (error) => {
|
|
771
|
+
pending.delete(work);
|
|
772
|
+
if (this.closing) this.shutdownFailure ??= { error };
|
|
773
|
+
});
|
|
774
|
+
}
|
|
624
775
|
registerToolHandler(name, fn) {
|
|
625
776
|
this.toolHandlers.set(name, fn);
|
|
626
777
|
}
|
|
@@ -688,16 +839,14 @@ var RealtimeCallHandler = class {
|
|
|
688
839
|
callId: entry.callId
|
|
689
840
|
};
|
|
690
841
|
}
|
|
691
|
-
handleCall(streamSid, callSid, ws, callerMeta, adapter) {
|
|
692
|
-
const preparedCall = this.prepareCallInManager(callSid, callerMeta);
|
|
842
|
+
async handleCall(streamSid, callSid, ws, callerMeta, adapter) {
|
|
843
|
+
const preparedCall = await this.prepareCallInManager(callSid, callerMeta);
|
|
693
844
|
if (!preparedCall) {
|
|
694
845
|
ws.close(1008, "Caller rejected by policy");
|
|
695
846
|
return null;
|
|
696
847
|
}
|
|
697
848
|
const { callRecord } = preparedCall;
|
|
698
849
|
const callId = callRecord.callId;
|
|
699
|
-
const hadPredecessorOnAdmission = this.activeBridgesByCallId.has(callId);
|
|
700
|
-
const previousTelephonyBinding = this.activeTelephonyBindingsByCallId.get(callId);
|
|
701
850
|
let callEndPromise;
|
|
702
851
|
const emitCallEnd = (cause) => {
|
|
703
852
|
if (callEndPromise) return callEndPromise;
|
|
@@ -710,29 +859,70 @@ var RealtimeCallHandler = class {
|
|
|
710
859
|
console.log(`[voice-call] Realtime call ended callId=${callId} providerCallId=${callSid} reason=${cause}`);
|
|
711
860
|
});
|
|
712
861
|
callEndPromise = attempt;
|
|
713
|
-
this.
|
|
714
|
-
const release = () => this.terminationAttempts.delete(attempt);
|
|
715
|
-
attempt.then(release, release);
|
|
862
|
+
this.trackShutdownWork(attempt, this.terminationAttempts);
|
|
716
863
|
return attempt;
|
|
717
864
|
};
|
|
865
|
+
const admissionAbandoned = () => this.closing || ws.readyState !== WebSocket.OPEN;
|
|
866
|
+
const abandonAdmission = async () => {
|
|
867
|
+
if (!this.activeBridgesByCallId.has(callId)) {
|
|
868
|
+
if (this.closing || this.serverClosingSockets.has(ws)) await emitCallEnd("shutdown");
|
|
869
|
+
else {
|
|
870
|
+
this.streamDisconnectLifecycle.connect(callSid, streamSid);
|
|
871
|
+
this.streamDisconnectLifecycle.disconnect(callSid, streamSid);
|
|
872
|
+
}
|
|
873
|
+
}
|
|
874
|
+
};
|
|
875
|
+
if (admissionAbandoned()) {
|
|
876
|
+
await abandonAdmission();
|
|
877
|
+
return null;
|
|
878
|
+
}
|
|
718
879
|
let registration;
|
|
880
|
+
let sessionPolicy;
|
|
719
881
|
try {
|
|
720
882
|
registration = this.resolveCallRegistration(callRecord);
|
|
883
|
+
sessionPolicy = resolveRealtimeVoiceSessionPolicy({
|
|
884
|
+
isAgentProxy: false,
|
|
885
|
+
capabilities: registration.capabilities,
|
|
886
|
+
configuredToolPolicy: this.config.toolPolicy,
|
|
887
|
+
configuredConsultPolicy: this.config.consultPolicy === "always" ? "always" : "auto",
|
|
888
|
+
requireWakeName: void 0,
|
|
889
|
+
configuredWakeNames: void 0,
|
|
890
|
+
cfg: this.coreConfig ?? {},
|
|
891
|
+
agentId: registration.agentId
|
|
892
|
+
});
|
|
721
893
|
} catch (error) {
|
|
722
894
|
console.error(`[voice-call] Failed to resolve realtime call registration callId=${callId} providerCallId=${callSid}: ${formatErrorMessage(error)}`);
|
|
723
|
-
if (!
|
|
895
|
+
if (!this.activeBridgesByCallId.has(callId)) emitCallEnd("error");
|
|
724
896
|
ws.close(1011, "Check realtime configuration for routed agent");
|
|
725
897
|
return null;
|
|
726
898
|
}
|
|
727
|
-
const { baseFields
|
|
728
|
-
|
|
729
|
-
this.manager.
|
|
899
|
+
const { baseFields } = preparedCall;
|
|
900
|
+
let initialGreeting;
|
|
901
|
+
await this.manager.updateCallMetadata(callRecord, (metadata) => {
|
|
902
|
+
if (metadata) {
|
|
903
|
+
initialGreeting = typeof metadata.initialMessage === "string" ? metadata.initialMessage : void 0;
|
|
904
|
+
delete metadata.initialMessage;
|
|
905
|
+
}
|
|
906
|
+
return metadata;
|
|
907
|
+
});
|
|
908
|
+
await this.manager.processEvent({
|
|
730
909
|
id: `realtime-answered-${callSid}`,
|
|
731
910
|
callId,
|
|
732
911
|
type: "call.answered",
|
|
733
912
|
...baseFields
|
|
734
913
|
});
|
|
735
|
-
|
|
914
|
+
if (admissionAbandoned()) {
|
|
915
|
+
await abandonAdmission();
|
|
916
|
+
return null;
|
|
917
|
+
}
|
|
918
|
+
if (this.manager.getCallByProviderCallId(callSid) !== callRecord) {
|
|
919
|
+
ws.close(1008, "Call is no longer active");
|
|
920
|
+
return null;
|
|
921
|
+
}
|
|
922
|
+
const previousTelephonyBinding = this.activeTelephonyBindingsByCallId.get(callId);
|
|
923
|
+
const { agentId, instructions, provider: realtimeProvider, providerConfig, capabilities } = registration;
|
|
924
|
+
const { handlesAgentConsult, toolPolicy } = sessionPolicy;
|
|
925
|
+
if (handlesAgentConsult) console.warn("[voice-call] This realtime model uses native agent delegation; the end-call and custom realtime function tools are unavailable.");
|
|
736
926
|
const initialGreetingInstructions = buildGreetingInstructions(instructions, initialGreeting);
|
|
737
927
|
const harness = createRealtimeVoiceSessionHarness({
|
|
738
928
|
talk: {
|
|
@@ -764,9 +954,13 @@ var RealtimeCallHandler = class {
|
|
|
764
954
|
reason
|
|
765
955
|
})
|
|
766
956
|
},
|
|
767
|
-
onTalkEvent: (event) =>
|
|
957
|
+
onTalkEvent: (event) => {
|
|
958
|
+
this.manager.updateCallMetadata(callRecord, (metadata) => appendRecentTalkEventMetadata(metadata, event)).catch((error) => {
|
|
959
|
+
console.warn("[voice-call] Failed to update realtime call metadata:", error);
|
|
960
|
+
});
|
|
961
|
+
}
|
|
768
962
|
});
|
|
769
|
-
|
|
963
|
+
const providerHandlesInputAudioBargeIn = (capabilities ?? realtimeProvider.capabilities)?.handlesInputAudioBargeIn === true;
|
|
770
964
|
const cancelOutputAudioForBargeIn = (source, interruptProvider, clearedAudioBytes = 0) => {
|
|
771
965
|
const outputAudioActive = harness.talk.outputAudioActive;
|
|
772
966
|
const pendingTelephonyAudio = audioPacer.hasPendingAudio();
|
|
@@ -811,7 +1005,9 @@ var RealtimeCallHandler = class {
|
|
|
811
1005
|
}
|
|
812
1006
|
return true;
|
|
813
1007
|
};
|
|
1008
|
+
const pendingMarkAcks = /* @__PURE__ */ new Map();
|
|
814
1009
|
const audioPacer = new RealtimeAudioPacer({
|
|
1010
|
+
onPlaybackReset: () => pendingMarkAcks.clear(),
|
|
815
1011
|
send: sendString,
|
|
816
1012
|
serializer: {
|
|
817
1013
|
media: (payload) => adapter.serializeMedia(payload),
|
|
@@ -834,23 +1030,63 @@ var RealtimeCallHandler = class {
|
|
|
834
1030
|
let sessionClosed = false;
|
|
835
1031
|
const userTranscriptAdoption = this.beginUserTranscriptOwnerAdoption(callId);
|
|
836
1032
|
const userTranscriptOwner = userTranscriptAdoption.owner;
|
|
1033
|
+
let transcriptPersistence = Promise.resolve();
|
|
1034
|
+
let transcriptFailure;
|
|
1035
|
+
const reportTranscriptFailure = (error) => {
|
|
1036
|
+
transcriptFailure ??= { error };
|
|
1037
|
+
console.error("[voice-call] Failed to persist realtime transcript:", error);
|
|
1038
|
+
};
|
|
1039
|
+
const drainProviderClose = async (closeProvider) => {
|
|
1040
|
+
const failures = [];
|
|
1041
|
+
try {
|
|
1042
|
+
await closeProvider();
|
|
1043
|
+
} catch (error) {
|
|
1044
|
+
failures.push(error);
|
|
1045
|
+
}
|
|
1046
|
+
await transcriptPersistence.catch((error) => {
|
|
1047
|
+
transcriptFailure ??= { error };
|
|
1048
|
+
});
|
|
1049
|
+
if (transcriptFailure) failures.push(transcriptFailure.error);
|
|
1050
|
+
if (failures.length === 1) throw failures[0];
|
|
1051
|
+
if (failures.length > 1) throw new AggregateError(failures, "Realtime provider and transcript cleanup failed");
|
|
1052
|
+
};
|
|
1053
|
+
let continuityGeneration = 0;
|
|
837
1054
|
const bridgeParams = {
|
|
838
1055
|
provider: realtimeProvider,
|
|
839
1056
|
cfg: this.coreConfig,
|
|
840
1057
|
agentId,
|
|
841
1058
|
providerConfig,
|
|
1059
|
+
capabilities,
|
|
842
1060
|
audioFormat: REALTIME_VOICE_AUDIO_FORMAT_G711_ULAW_8KHZ,
|
|
843
1061
|
interruptResponseOnInputAudio,
|
|
844
|
-
instructions,
|
|
845
|
-
tools: this.config.tools,
|
|
1062
|
+
instructions: handlesAgentConsult ? `${instructions}\n\nUse native agent delegation for OpenClaw work. End-call and custom realtime function tools are unavailable in this session; the caller can hang up to end the call.` : instructions,
|
|
1063
|
+
tools: handlesAgentConsult ? [] : this.config.tools,
|
|
1064
|
+
...handlesAgentConsult ? { runAgentConsult: async (request) => {
|
|
1065
|
+
const owner = nativeConsultOwner.current;
|
|
1066
|
+
const generation = continuityGeneration;
|
|
1067
|
+
request.signal?.throwIfAborted();
|
|
1068
|
+
await transcriptPersistence;
|
|
1069
|
+
if (!owner || sessionClosed || generation !== continuityGeneration || !this.isActiveBridgeOwner(callId, owner)) throw new Error("Realtime call delegation owner is no longer active");
|
|
1070
|
+
if (toolPolicy === "none") throw new Error("Agent consultation is disabled for this call");
|
|
1071
|
+
const result = await this.executeToolCall(owner, callId, randomUUID(), REALTIME_VOICE_AGENT_CONSULT_TOOL_NAME, { question: request.prompt }, harness.ensureTurn(), harness, userTranscriptOwner, { signal: request.signal });
|
|
1072
|
+
request.signal?.throwIfAborted();
|
|
1073
|
+
if (sessionClosed || generation !== continuityGeneration || !this.isActiveBridgeOwner(callId, owner)) throw new Error("Realtime call delegation owner is no longer active");
|
|
1074
|
+
const text = readSpeakableRealtimeVoiceToolResult(result, {
|
|
1075
|
+
keys: ["text", "output"],
|
|
1076
|
+
maxChars: FORCED_CONSULT_RESULT_MAX_CHARS
|
|
1077
|
+
});
|
|
1078
|
+
if (!text) throw new Error("Agent consultation returned no spoken answer");
|
|
1079
|
+
return { text };
|
|
1080
|
+
} } : {},
|
|
846
1081
|
initialGreetingInstructions,
|
|
847
1082
|
triggerGreetingOnReady: Boolean(initialGreetingInstructions),
|
|
848
1083
|
audioSink: {
|
|
849
|
-
isOpen: () => ws.readyState === WebSocket.OPEN,
|
|
850
|
-
sendAudio: (muLaw) => {
|
|
1084
|
+
isOpen: () => !sessionClosed && ws.readyState === WebSocket.OPEN,
|
|
1085
|
+
sendAudio: (muLaw, metadata) => {
|
|
851
1086
|
harness.recordOutputAudio(muLaw);
|
|
852
|
-
audioPacer.sendAudio(muLaw);
|
|
1087
|
+
audioPacer.sendAudio(muLaw, metadata);
|
|
853
1088
|
},
|
|
1089
|
+
getPlaybackState: () => audioPacer.getPlaybackState(),
|
|
854
1090
|
clearAudio: (reason) => {
|
|
855
1091
|
harness.flushOutput(() => {
|
|
856
1092
|
const clearedBytes = audioPacer.clearAudio();
|
|
@@ -862,13 +1098,14 @@ var RealtimeCallHandler = class {
|
|
|
862
1098
|
harness.finishOutputAudio("clear");
|
|
863
1099
|
});
|
|
864
1100
|
},
|
|
865
|
-
sendMark: (markName) => {
|
|
1101
|
+
sendMark: (markName, acknowledge) => {
|
|
866
1102
|
audioPacer.sendMark(markName);
|
|
1103
|
+
if (markName && acknowledge) pendingMarkAcks.set(markName, acknowledge);
|
|
867
1104
|
}
|
|
868
1105
|
},
|
|
869
1106
|
onTranscript: (role, text, isFinal) => {
|
|
870
1107
|
const owner = nativeConsultOwner.current;
|
|
871
|
-
if (provisionalCloseReason || !this.getUserTranscriptState(callId, userTranscriptOwner) || owner && !this.isActiveBridgeOwner(callId, owner)) return;
|
|
1108
|
+
if (provisionalCloseReason || sessionClosed && !isFinal || !this.getUserTranscriptState(callId, userTranscriptOwner) || owner && !this.isActiveBridgeOwner(callId, owner)) return;
|
|
872
1109
|
const turnId = harness.ensureTurn();
|
|
873
1110
|
const eventType = role === "assistant" ? isFinal ? "output.text.done" : "output.text.delta" : isFinal ? "transcript.done" : "transcript.delta";
|
|
874
1111
|
const payload = role === "assistant" ? { text } : {
|
|
@@ -910,7 +1147,7 @@ var RealtimeCallHandler = class {
|
|
|
910
1147
|
this.setRecentFinalUserTranscript(callId, userTranscriptOwner, transcript);
|
|
911
1148
|
console.log(`[voice-call] realtime input transcript callId=${callId} providerCallId=${callSid} final=true chars=${text.trim().length} aggregateChars=${transcript.length}`);
|
|
912
1149
|
const event = {
|
|
913
|
-
id: `realtime-speech-${callSid}-${
|
|
1150
|
+
id: `realtime-speech-${callSid}-${randomUUID()}`,
|
|
914
1151
|
type: "call.speech",
|
|
915
1152
|
callId,
|
|
916
1153
|
providerCallId: callSid,
|
|
@@ -918,31 +1155,39 @@ var RealtimeCallHandler = class {
|
|
|
918
1155
|
transcript,
|
|
919
1156
|
isFinal: true
|
|
920
1157
|
};
|
|
921
|
-
|
|
922
|
-
this.
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
1158
|
+
const generation = continuityGeneration;
|
|
1159
|
+
transcriptPersistence = this.manager.processEvent(event).then(() => {
|
|
1160
|
+
if (handlesAgentConsult || sessionClosed || generation !== continuityGeneration || !this.getUserTranscriptState(callId, userTranscriptOwner) || !this.isActiveBridgeOwner(callId, session)) return;
|
|
1161
|
+
this.scheduleForcedAgentConsult({
|
|
1162
|
+
harness,
|
|
1163
|
+
session,
|
|
1164
|
+
callId,
|
|
1165
|
+
callSid,
|
|
1166
|
+
transcript,
|
|
1167
|
+
userTranscriptOwner,
|
|
1168
|
+
clearAudio: () => {
|
|
1169
|
+
const clearedBytes = audioPacer.clearAudio();
|
|
1170
|
+
console.log(`[voice-call] realtime forced consult cleared outbound audio callId=${callId} providerCallId=${callSid} queuedBytes=${clearedBytes}`);
|
|
1171
|
+
}
|
|
1172
|
+
});
|
|
933
1173
|
});
|
|
1174
|
+
transcriptPersistence.catch(reportTranscriptFailure);
|
|
934
1175
|
return;
|
|
935
1176
|
}
|
|
936
|
-
this.manager.processEvent({
|
|
937
|
-
id: `realtime-bot-${callSid}-${
|
|
1177
|
+
transcriptPersistence = this.manager.processEvent({
|
|
1178
|
+
id: `realtime-bot-${callSid}-${randomUUID()}`,
|
|
938
1179
|
type: "call.assistant-speech",
|
|
939
1180
|
callId,
|
|
940
1181
|
providerCallId: callSid,
|
|
941
1182
|
timestamp: Date.now(),
|
|
942
1183
|
transcript: text
|
|
943
|
-
});
|
|
1184
|
+
}).then(() => {});
|
|
1185
|
+
transcriptPersistence.catch(reportTranscriptFailure);
|
|
944
1186
|
},
|
|
945
|
-
onToolCall: (toolEvent, sessionLocal) => {
|
|
1187
|
+
onToolCall: async (toolEvent, sessionLocal) => {
|
|
1188
|
+
const generation = continuityGeneration;
|
|
1189
|
+
await transcriptPersistence;
|
|
1190
|
+
if (sessionClosed || generation !== continuityGeneration || !this.isActiveBridgeOwner(callId, sessionLocal)) return;
|
|
946
1191
|
const turnId = harness.ensureTurn();
|
|
947
1192
|
harness.emit({
|
|
948
1193
|
type: "tool.call",
|
|
@@ -955,10 +1200,11 @@ var RealtimeCallHandler = class {
|
|
|
955
1200
|
}
|
|
956
1201
|
});
|
|
957
1202
|
console.log(`[voice-call] realtime tool call received callId=${callId} providerCallId=${callSid} tool=${toolEvent.name}`);
|
|
958
|
-
|
|
1203
|
+
await this.executeToolCall(sessionLocal, callId, toolEvent.callId || toolEvent.itemId, toolEvent.name, toolEvent.args, turnId, harness, userTranscriptOwner);
|
|
959
1204
|
},
|
|
960
1205
|
onEvent: (event) => {
|
|
961
1206
|
if (event.direction === "client" && event.type === "session.continuity.reset") {
|
|
1207
|
+
continuityGeneration += 1;
|
|
962
1208
|
const turnId = harness.talk.activeTurnId;
|
|
963
1209
|
const owner = nativeConsultOwner.current;
|
|
964
1210
|
if (owner && this.isActiveBridgeOwner(callId, owner)) {
|
|
@@ -1036,14 +1282,18 @@ var RealtimeCallHandler = class {
|
|
|
1036
1282
|
provisionalCloseReason ??= reason;
|
|
1037
1283
|
return;
|
|
1038
1284
|
}
|
|
1285
|
+
if (sessionClosed) {
|
|
1286
|
+
if (reason === "error") {
|
|
1287
|
+
this.streamDisconnectLifecycle.retire(callSid, streamSid);
|
|
1288
|
+
if (ws.readyState === WebSocket.OPEN) ws.close(1011, "Bridge disconnected");
|
|
1289
|
+
}
|
|
1290
|
+
return;
|
|
1291
|
+
}
|
|
1039
1292
|
const ownsCallState = this.isActiveBridgeOwner(callId, owner);
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
if (ownsCallState) this.clearUserTranscriptState(callId, userTranscriptOwner);
|
|
1043
|
-
if (reason === "completed" && (!ownsCallState || sessionClosed)) return;
|
|
1293
|
+
if (reason === "completed" && !ownsCallState) return;
|
|
1294
|
+
if (ownsCallState) closeBinding(telephonyBinding, reason);
|
|
1044
1295
|
this.streamDisconnectLifecycle.retire(callSid, streamSid);
|
|
1045
1296
|
if (ws.readyState === WebSocket.OPEN) ws.close(reason === "error" ? 1011 : 1e3, "Bridge disconnected");
|
|
1046
|
-
if (ownsCallState) emitCallEnd(reason);
|
|
1047
1297
|
}
|
|
1048
1298
|
};
|
|
1049
1299
|
let candidate;
|
|
@@ -1055,21 +1305,26 @@ var RealtimeCallHandler = class {
|
|
|
1055
1305
|
if (!candidate || provisionalCloseReason) {
|
|
1056
1306
|
this.rollbackUserTranscriptOwnerAdoption(callId, userTranscriptAdoption);
|
|
1057
1307
|
try {
|
|
1058
|
-
candidate?.close();
|
|
1308
|
+
await drainProviderClose(() => candidate?.close());
|
|
1059
1309
|
} catch (error) {
|
|
1060
1310
|
console.warn(`[voice-call] Failed to close realtime bridge ${callSid}: ${formatErrorMessage(error)}`);
|
|
1061
1311
|
}
|
|
1062
1312
|
harness.close();
|
|
1063
1313
|
audioPacer.close();
|
|
1064
1314
|
const reason = provisionalCloseReason ?? "error";
|
|
1065
|
-
if (!
|
|
1315
|
+
if (!this.activeBridgesByCallId.has(callId)) emitCallEnd(reason);
|
|
1066
1316
|
if (ws.readyState === WebSocket.OPEN) ws.close(reason === "error" ? 1011 : 1e3, "Failed to create realtime bridge");
|
|
1067
1317
|
return null;
|
|
1068
1318
|
}
|
|
1069
1319
|
const session = candidate;
|
|
1070
1320
|
this.commitUserTranscriptOwnerAdoption(callId, userTranscriptAdoption);
|
|
1071
1321
|
nativeConsultOwner.current = session;
|
|
1072
|
-
|
|
1322
|
+
const localBargeIn = !(session.bridge.handlesInputAudioBargeIn ?? providerHandlesInputAudioBargeIn) && resolveRealtimeVoiceBargeIn({
|
|
1323
|
+
configuredBargeIn: void 0,
|
|
1324
|
+
interruptResponseOnInputAudio,
|
|
1325
|
+
capabilities,
|
|
1326
|
+
outputAudioMode: session.bridge.outputAudioMode
|
|
1327
|
+
});
|
|
1073
1328
|
const previousConsultSession = this.consultSessionsByCallId.get(callId);
|
|
1074
1329
|
if (previousConsultSession && previousConsultSession.owner !== session) this.cancelConsultSession(callId, previousConsultSession.owner);
|
|
1075
1330
|
this.consultSessionsByCallId.set(callId, {
|
|
@@ -1078,12 +1333,13 @@ var RealtimeCallHandler = class {
|
|
|
1078
1333
|
});
|
|
1079
1334
|
const sendAudioToSession = session.sendAudio.bind(session);
|
|
1080
1335
|
session.sendAudio = (audio) => {
|
|
1336
|
+
if (sessionClosed) return;
|
|
1081
1337
|
if (speechDetector.accept({
|
|
1082
1338
|
rms: calculateMulawRms(audio),
|
|
1083
1339
|
peak: 0
|
|
1084
1340
|
})) {
|
|
1085
1341
|
console.log(`[voice-call] realtime local speech detected callId=${callId} providerCallId=${callSid}`);
|
|
1086
|
-
if (
|
|
1342
|
+
if (localBargeIn) cancelOutputAudioForBargeIn("local", (audioPlaybackActive) => {
|
|
1087
1343
|
session.handleBargeIn({ audioPlaybackActive });
|
|
1088
1344
|
});
|
|
1089
1345
|
}
|
|
@@ -1091,18 +1347,18 @@ var RealtimeCallHandler = class {
|
|
|
1091
1347
|
sendAudioToSession(audio);
|
|
1092
1348
|
};
|
|
1093
1349
|
const closeSession = session.close.bind(session);
|
|
1350
|
+
let sessionClosePromise;
|
|
1094
1351
|
session.close = () => {
|
|
1095
|
-
if (sessionClosed) return;
|
|
1352
|
+
if (sessionClosed) return sessionClosePromise ?? Promise.resolve();
|
|
1096
1353
|
sessionClosed = true;
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1354
|
+
this.cancelConsultSession(callId, session);
|
|
1355
|
+
audioPacer.close();
|
|
1356
|
+
sessionClosePromise = drainProviderClose(closeSession).finally(() => {
|
|
1100
1357
|
this.clearActiveBridgeMappings(callId, callSid, session);
|
|
1101
|
-
this.cancelConsultSession(callId, session);
|
|
1102
1358
|
this.clearUserTranscriptState(callId, userTranscriptOwner);
|
|
1103
1359
|
harness.close();
|
|
1104
|
-
|
|
1105
|
-
|
|
1360
|
+
});
|
|
1361
|
+
return sessionClosePromise;
|
|
1106
1362
|
};
|
|
1107
1363
|
let livenessTimer;
|
|
1108
1364
|
const clearLivenessTimer = () => {
|
|
@@ -1112,26 +1368,49 @@ var RealtimeCallHandler = class {
|
|
|
1112
1368
|
}
|
|
1113
1369
|
};
|
|
1114
1370
|
let bindingClosed = false;
|
|
1371
|
+
let bindingClosePromise;
|
|
1115
1372
|
const closeBinding = (binding, cause) => {
|
|
1116
|
-
if (bindingClosed) return callEndPromise ?? Promise.resolve();
|
|
1373
|
+
if (bindingClosed) return bindingClosePromise ?? callEndPromise ?? Promise.resolve();
|
|
1117
1374
|
bindingClosed = true;
|
|
1118
1375
|
clearLivenessTimer();
|
|
1119
1376
|
const ownsCall = this.activeTelephonyBindingsByCallId.get(callId) === binding;
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
session.close();
|
|
1123
|
-
} catch (error) {
|
|
1124
|
-
console.warn(`[voice-call] Failed to close realtime bridge ${callSid}: ${formatErrorMessage(error)}`);
|
|
1125
|
-
} finally {
|
|
1377
|
+
const finishClose = () => {
|
|
1378
|
+
const stillOwnsCall = this.activeTelephonyBindingsByCallId.get(callId) === binding;
|
|
1126
1379
|
this.clearActiveTelephonyBinding(callId, binding);
|
|
1127
1380
|
if (cause === "disconnect") this.streamDisconnectLifecycle.disconnect(callSid, streamSid);
|
|
1128
1381
|
else this.streamDisconnectLifecycle.retire(callSid, streamSid);
|
|
1129
|
-
if (ownsCall && cause && cause !== "disconnect")
|
|
1382
|
+
if (ownsCall && stillOwnsCall && cause && cause !== "disconnect") return emitCallEnd(cause);
|
|
1383
|
+
return Promise.resolve();
|
|
1384
|
+
};
|
|
1385
|
+
let pending;
|
|
1386
|
+
try {
|
|
1387
|
+
pending = Promise.resolve(session.close());
|
|
1388
|
+
} catch (error) {
|
|
1389
|
+
pending = Promise.reject(error instanceof Error ? error : new Error("Realtime provider close failed", { cause: error }));
|
|
1130
1390
|
}
|
|
1131
|
-
|
|
1391
|
+
bindingClosePromise = pending.then(finishClose, async (error) => {
|
|
1392
|
+
console.warn(`[voice-call] Failed to close realtime bridge ${callSid}: ${formatErrorMessage(error)}`);
|
|
1393
|
+
try {
|
|
1394
|
+
await finishClose();
|
|
1395
|
+
} catch (terminationError) {
|
|
1396
|
+
throw new AggregateError([error, terminationError], "Realtime call cleanup failed", { cause: terminationError });
|
|
1397
|
+
}
|
|
1398
|
+
throw error;
|
|
1399
|
+
});
|
|
1400
|
+
this.trackShutdownWork(bindingClosePromise, this.terminationAttempts);
|
|
1401
|
+
return bindingClosePromise;
|
|
1132
1402
|
};
|
|
1133
1403
|
const telephonyBinding = {
|
|
1134
1404
|
bridge: session,
|
|
1405
|
+
acknowledgeCarrierMark: (markName) => {
|
|
1406
|
+
audioPacer.acknowledgeMark(markName);
|
|
1407
|
+
if (!markName) return;
|
|
1408
|
+
const acknowledge = pendingMarkAcks.get(markName);
|
|
1409
|
+
if (acknowledge) {
|
|
1410
|
+
pendingMarkAcks.delete(markName);
|
|
1411
|
+
acknowledge();
|
|
1412
|
+
}
|
|
1413
|
+
},
|
|
1135
1414
|
close: (cause) => closeBinding(telephonyBinding, cause),
|
|
1136
1415
|
endCall: () => {
|
|
1137
1416
|
closeBinding(telephonyBinding);
|
|
@@ -1159,16 +1438,11 @@ var RealtimeCallHandler = class {
|
|
|
1159
1438
|
this.activeTelephonyBindingsByCallId.set(callId, telephonyBinding);
|
|
1160
1439
|
telephonyBinding.noteMediaActivity();
|
|
1161
1440
|
if (previousTelephonyBinding && previousTelephonyBinding !== telephonyBinding) previousTelephonyBinding.retire();
|
|
1162
|
-
session.connect().catch((error) => {
|
|
1441
|
+
session.connect().catch(async (error) => {
|
|
1163
1442
|
console.error("[voice-call] Failed to connect realtime bridge:", error);
|
|
1164
|
-
const ownsCallState = this.isActiveBridgeOwner(callId, session);
|
|
1165
|
-
this.streamDisconnectLifecycle.retire(callSid, streamSid);
|
|
1166
1443
|
try {
|
|
1167
|
-
|
|
1168
|
-
} catch
|
|
1169
|
-
console.warn(`[voice-call] Failed to close realtime bridge ${callSid}: ${formatErrorMessage(closeError)}`);
|
|
1170
|
-
} finally {
|
|
1171
|
-
if (ownsCallState) emitCallEnd("error");
|
|
1444
|
+
await closeBinding(telephonyBinding, "error");
|
|
1445
|
+
} catch {} finally {
|
|
1172
1446
|
ws.close(1011, "Failed to connect");
|
|
1173
1447
|
}
|
|
1174
1448
|
});
|
|
@@ -1257,7 +1531,6 @@ var RealtimeCallHandler = class {
|
|
|
1257
1531
|
cancelNativeConsult(callId, owner) {
|
|
1258
1532
|
const state = this.nativeConsultsInFlightByCallId.get(callId);
|
|
1259
1533
|
if (!state || state.owner !== owner) return;
|
|
1260
|
-
state.cancelled = true;
|
|
1261
1534
|
this.nativeConsultsInFlightByCallId.delete(callId);
|
|
1262
1535
|
state.cancel();
|
|
1263
1536
|
}
|
|
@@ -1421,7 +1694,7 @@ var RealtimeCallHandler = class {
|
|
|
1421
1694
|
}
|
|
1422
1695
|
}
|
|
1423
1696
|
}
|
|
1424
|
-
prepareCallInManager(callSid, callerMeta = {}) {
|
|
1697
|
+
async prepareCallInManager(callSid, callerMeta = {}) {
|
|
1425
1698
|
const baseFields = {
|
|
1426
1699
|
providerCallId: callSid,
|
|
1427
1700
|
timestamp: Date.now(),
|
|
@@ -1429,22 +1702,19 @@ var RealtimeCallHandler = class {
|
|
|
1429
1702
|
...callerMeta.from ? { from: callerMeta.from } : {},
|
|
1430
1703
|
...callerMeta.to ? { to: callerMeta.to } : {}
|
|
1431
1704
|
};
|
|
1432
|
-
const callRecord = this.resolveRealtimeCall(callSid, callerMeta, baseFields);
|
|
1705
|
+
const callRecord = await this.resolveRealtimeCall(callSid, callerMeta, baseFields);
|
|
1433
1706
|
if (!callRecord) return null;
|
|
1434
|
-
const initialGreeting = this.extractInitialGreeting(callRecord);
|
|
1435
|
-
console.log(`[voice-call] Realtime call ${callRecord.callId} initial greeting ${initialGreeting ? "queued" : "absent"}`);
|
|
1436
1707
|
return {
|
|
1437
1708
|
callRecord,
|
|
1438
|
-
baseFields
|
|
1439
|
-
initialGreeting
|
|
1709
|
+
baseFields
|
|
1440
1710
|
};
|
|
1441
1711
|
}
|
|
1442
|
-
resolveRealtimeCall(callSid, callerMeta, baseFields) {
|
|
1712
|
+
async resolveRealtimeCall(callSid, callerMeta, baseFields) {
|
|
1443
1713
|
if (callerMeta.callId) {
|
|
1444
|
-
const call = this.manager.
|
|
1714
|
+
const call = await this.manager.getCallForStream(callerMeta.callId);
|
|
1445
1715
|
return call?.providerCallId === callSid ? call : null;
|
|
1446
1716
|
}
|
|
1447
|
-
this.manager.processEvent({
|
|
1717
|
+
await this.manager.processEvent({
|
|
1448
1718
|
id: `realtime-initiated-${callSid}`,
|
|
1449
1719
|
callId: callSid,
|
|
1450
1720
|
type: "call.initiated",
|
|
@@ -1452,9 +1722,6 @@ var RealtimeCallHandler = class {
|
|
|
1452
1722
|
});
|
|
1453
1723
|
return this.manager.getCallByProviderCallId(callSid) ?? null;
|
|
1454
1724
|
}
|
|
1455
|
-
extractInitialGreeting(call) {
|
|
1456
|
-
return typeof call.metadata?.initialMessage === "string" ? call.metadata.initialMessage : void 0;
|
|
1457
|
-
}
|
|
1458
1725
|
async executeEndCallTool(params) {
|
|
1459
1726
|
const binding = this.activeTelephonyBindingsByCallId.get(params.callId);
|
|
1460
1727
|
if (!binding || binding.bridge !== params.bridge || !this.isActiveBridgeOwner(params.callId, params.bridge)) return;
|
|
@@ -1495,7 +1762,7 @@ var RealtimeCallHandler = class {
|
|
|
1495
1762
|
});
|
|
1496
1763
|
binding.endCall();
|
|
1497
1764
|
}
|
|
1498
|
-
async executeToolCall(bridge, callId, bridgeCallId, name, args, turnId, harness, userTranscriptOwner) {
|
|
1765
|
+
async executeToolCall(bridge, callId, bridgeCallId, name, args, turnId, harness, userTranscriptOwner, delegation) {
|
|
1499
1766
|
if (name === "openclaw_end_call") {
|
|
1500
1767
|
await this.executeEndCallTool({
|
|
1501
1768
|
bridge,
|
|
@@ -1524,11 +1791,12 @@ var RealtimeCallHandler = class {
|
|
|
1524
1791
|
});
|
|
1525
1792
|
};
|
|
1526
1793
|
const submitFinalToolResult = async (result) => {
|
|
1527
|
-
await bridge.submitToolResult(bridgeCallId, result);
|
|
1794
|
+
if (!delegation) await bridge.submitToolResult(bridgeCallId, result);
|
|
1528
1795
|
emitFinalToolEvent(result);
|
|
1796
|
+
return result;
|
|
1529
1797
|
};
|
|
1530
1798
|
const submitWorkingResponse = async () => {
|
|
1531
|
-
if (handler && name === REALTIME_VOICE_AGENT_CONSULT_TOOL_NAME && bridge.bridge.supportsToolResultContinuation && !this.config.fastContext.enabled) {
|
|
1799
|
+
if (!delegation && handler && name === REALTIME_VOICE_AGENT_CONSULT_TOOL_NAME && bridge.bridge.supportsToolResultContinuation && !this.config.fastContext.enabled) {
|
|
1532
1800
|
await bridge.submitToolResult(bridgeCallId, buildRealtimeVoiceAgentConsultWorkingResponse("caller"), { willContinue: true });
|
|
1533
1801
|
harness.emit({
|
|
1534
1802
|
type: "tool.progress",
|
|
@@ -1553,25 +1821,20 @@ var RealtimeCallHandler = class {
|
|
|
1553
1821
|
const forcedConsult = forcedConsultState?.owner === bridge && !forcedConsultState.cancelled ? forcedConsultState : void 0;
|
|
1554
1822
|
if (forcedMatch.kind === "already_delivered" && coordinator.isCancelled(forcedMatch.handle)) {
|
|
1555
1823
|
if (forcedConsult) forcedConsult.sendSpeechPrompt = false;
|
|
1556
|
-
await submitFinalToolResult({
|
|
1824
|
+
return await submitFinalToolResult({
|
|
1557
1825
|
status: "cancelled",
|
|
1558
1826
|
message: "OpenClaw cancelled this consult before completion. Do not restart it."
|
|
1559
1827
|
});
|
|
1560
|
-
return;
|
|
1561
1828
|
}
|
|
1562
1829
|
if (forcedConsult) {
|
|
1563
|
-
if (forcedConsult.completedAt || forcedMatch.kind === "already_delivered") {
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
});
|
|
1568
|
-
return;
|
|
1569
|
-
}
|
|
1830
|
+
if (forcedConsult.completedAt || forcedMatch.kind === "already_delivered") return await submitFinalToolResult({
|
|
1831
|
+
status: "already_delivered",
|
|
1832
|
+
message: "OpenClaw already delivered this consult result internally. Do not repeat it."
|
|
1833
|
+
});
|
|
1570
1834
|
forcedConsult.sendSpeechPrompt = false;
|
|
1571
1835
|
const result = await forcedConsult.promise.catch(buildRealtimeVoiceAgentErrorProviderResult);
|
|
1572
1836
|
if (forcedConsult.cancelled || forcedConsult.owner !== bridge || this.forcedConsultsByCallId.get(callId) !== forcedConsult) return;
|
|
1573
|
-
await submitFinalToolResult(result);
|
|
1574
|
-
return;
|
|
1837
|
+
return await submitFinalToolResult(result);
|
|
1575
1838
|
}
|
|
1576
1839
|
const existingNativeConsult = this.nativeConsultsInFlightByCallId.get(callId);
|
|
1577
1840
|
if (existingNativeConsult) {
|
|
@@ -1579,8 +1842,7 @@ var RealtimeCallHandler = class {
|
|
|
1579
1842
|
await submitWorkingResponse();
|
|
1580
1843
|
const outcome = await waitForNativeConsult(existingNativeConsult);
|
|
1581
1844
|
if (outcome.kind === "cancelled") return;
|
|
1582
|
-
await submitFinalToolResult(outcome.result);
|
|
1583
|
-
return;
|
|
1845
|
+
return await submitFinalToolResult(outcome.result);
|
|
1584
1846
|
}
|
|
1585
1847
|
const abortController = new AbortController();
|
|
1586
1848
|
let releaseCancellation = () => {};
|
|
@@ -1595,19 +1857,23 @@ var RealtimeCallHandler = class {
|
|
|
1595
1857
|
completeConsult = resolve;
|
|
1596
1858
|
}),
|
|
1597
1859
|
cancellation,
|
|
1598
|
-
cancelled
|
|
1860
|
+
get cancelled() {
|
|
1861
|
+
return abortController.signal.aborted;
|
|
1862
|
+
},
|
|
1599
1863
|
cancel: () => {
|
|
1600
1864
|
abortController.abort(/* @__PURE__ */ new Error("Realtime native consult owner was cancelled."));
|
|
1601
1865
|
releaseCancellation();
|
|
1602
1866
|
}
|
|
1603
1867
|
};
|
|
1868
|
+
if (delegation?.signal?.aborted) state.cancel();
|
|
1869
|
+
else delegation?.signal?.addEventListener("abort", state.cancel, { once: true });
|
|
1604
1870
|
this.nativeConsultsInFlightByCallId.set(callId, state);
|
|
1605
1871
|
(async () => {
|
|
1606
1872
|
try {
|
|
1607
1873
|
await submitWorkingResponse();
|
|
1608
|
-
if (state.cancelled) return;
|
|
1874
|
+
if (state.cancelled || !this.isActiveBridgeOwner(callId, bridge)) return;
|
|
1609
1875
|
await Promise.race([this.waitForConsultTranscriptSettle(callId, userTranscriptOwner, startedAt), state.cancellation]);
|
|
1610
|
-
if (state.cancelled) return;
|
|
1876
|
+
if (state.cancelled || !this.isActiveBridgeOwner(callId, bridge)) return;
|
|
1611
1877
|
const context = {
|
|
1612
1878
|
partialUserTranscript: this.resolveUserTranscriptContext(callId, userTranscriptOwner),
|
|
1613
1879
|
abortSignal: abortController.signal
|
|
@@ -1629,10 +1895,11 @@ var RealtimeCallHandler = class {
|
|
|
1629
1895
|
console.log(`[voice-call] realtime tool call completed callId=${callId} tool=${name} status=${failed ? "error" : "ok"} elapsedMs=${Date.now() - startedAt}${error ? ` error=${error}` : ""}`);
|
|
1630
1896
|
await submitFinalToolResult(result);
|
|
1631
1897
|
if (!failed) this.consumePartialUserTranscript(callId, userTranscriptOwner, state.partialUserTranscript);
|
|
1898
|
+
return result;
|
|
1632
1899
|
} finally {
|
|
1900
|
+
delegation?.signal?.removeEventListener("abort", state.cancel);
|
|
1633
1901
|
if (this.nativeConsultsInFlightByCallId.get(callId) === state) this.nativeConsultsInFlightByCallId.delete(callId);
|
|
1634
1902
|
}
|
|
1635
|
-
return;
|
|
1636
1903
|
}
|
|
1637
1904
|
console.log(`[voice-call] realtime tool call executing callId=${callId} tool=${name} hasHandler=${Boolean(handler)}`);
|
|
1638
1905
|
const context = { partialUserTranscript: this.resolveUserTranscriptContext(callId, userTranscriptOwner) };
|
|
@@ -1644,7 +1911,7 @@ var RealtimeCallHandler = class {
|
|
|
1644
1911
|
}
|
|
1645
1912
|
const error = hasResultError(result) ? formatErrorMessage(result.error ?? "unknown") : void 0;
|
|
1646
1913
|
console.log(`[voice-call] realtime tool call completed callId=${callId} tool=${name} status=${error === void 0 ? "ok" : "error"} elapsedMs=${Date.now() - startedAt}${error ? ` error=${error}` : ""}`);
|
|
1647
|
-
await submitFinalToolResult(result);
|
|
1914
|
+
return await submitFinalToolResult(result);
|
|
1648
1915
|
}
|
|
1649
1916
|
};
|
|
1650
1917
|
//#endregion
|