@openclaw/voice-call 2026.7.1-beta.2 → 2026.7.1-beta.4
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/README.md +1 -0
- package/dist/{config-DNtTB7Iw.js → config-CgigQDrF.js} +31 -13
- package/dist/{config-compat-CCEjHjAJ.js → config-compat-DAFd5tVH.js} +3 -2
- package/dist/doctor-contract-api.js +4 -22
- package/dist/{guarded-json-api-7ITxTL6G.js → guarded-json-api-BrBbW_RJ.js} +19 -57
- package/dist/index.js +46 -33
- package/dist/{mock-YAo3QDri.js → mock-YsvBTX-7.js} +18 -2
- package/dist/{plivo-wmeT9r_t.js → plivo-BnCuAGwj.js} +25 -6
- package/dist/{realtime-handler-DdViwdCW.js → realtime-handler-Bz-MNWtD.js} +103 -43
- package/dist/response-generator-PXuisI3L.js +272 -0
- package/dist/{runtime-entry-DN7HllXj.js → runtime-entry-kCq5Xjph.js} +234 -96
- package/dist/runtime-entry.js +1 -1
- package/dist/setup-api.js +1 -1
- package/dist/{store-8M2m4Isq.js → store-DtewuuOb.js} +23 -6
- package/dist/{telnyx-DuUBsPW2.js → telnyx-DTHQGeaW.js} +1 -1
- package/dist/{twilio-CsJBvC3a.js → twilio-xNIXGJ-M.js} +16 -8
- package/dist/webhook-replay-aaP79dI8.js +32 -0
- package/node_modules/commander/Readme.md +11 -15
- package/node_modules/commander/index.js +14 -17
- package/node_modules/commander/lib/argument.js +3 -6
- package/node_modules/commander/lib/command.js +46 -33
- package/node_modules/commander/lib/error.js +2 -5
- package/node_modules/commander/lib/help.js +4 -20
- package/node_modules/commander/lib/option.js +3 -6
- package/node_modules/commander/lib/suggestSimilar.js +2 -4
- package/node_modules/commander/package.json +10 -28
- package/node_modules/commander/typings/index.d.ts +3 -3
- package/node_modules/typebox/build/compile/validator.d.mts +2 -7
- package/node_modules/typebox/build/compile/validator.mjs +6 -36
- package/node_modules/typebox/build/error/errors.d.mts +1 -7
- package/node_modules/typebox/build/format/_idna.mjs +36 -6
- package/node_modules/typebox/build/format/_puny.mjs +4 -1
- package/node_modules/typebox/build/format/uuid.d.mts +2 -2
- package/node_modules/typebox/build/format/uuid.mjs +3 -3
- package/node_modules/typebox/build/guard/emit.d.mts +0 -4
- package/node_modules/typebox/build/guard/emit.mjs +0 -8
- package/node_modules/typebox/build/guard/guard.d.mts +4 -8
- package/node_modules/typebox/build/guard/guard.mjs +5 -13
- package/node_modules/typebox/build/schema/engine/boolean.d.mts +3 -3
- package/node_modules/typebox/build/schema/engine/boolean.mjs +4 -4
- package/node_modules/typebox/build/schema/engine/index.d.mts +0 -1
- package/node_modules/typebox/build/schema/engine/index.mjs +0 -1
- package/node_modules/typebox/build/schema/engine/schema.mjs +5 -10
- package/node_modules/typebox/build/schema/engine/type.mjs +14 -18
- package/node_modules/typebox/build/schema/types/dependencies.mjs +1 -1
- package/node_modules/typebox/build/schema/types/index.d.mts +0 -1
- package/node_modules/typebox/build/schema/types/index.mjs +0 -1
- package/node_modules/typebox/build/schema/types/schema.d.mts +1 -1
- package/node_modules/typebox/build/schema/types/schema.mjs +2 -2
- package/node_modules/typebox/build/system/locale/ar_001.mjs +0 -1
- package/node_modules/typebox/build/system/locale/bn_BD.mjs +0 -1
- package/node_modules/typebox/build/system/locale/cs_CZ.mjs +0 -1
- package/node_modules/typebox/build/system/locale/de_DE.mjs +0 -1
- package/node_modules/typebox/build/system/locale/el_GR.mjs +0 -1
- package/node_modules/typebox/build/system/locale/en_US.mjs +0 -1
- package/node_modules/typebox/build/system/locale/es_419.mjs +0 -1
- package/node_modules/typebox/build/system/locale/es_AR.mjs +0 -1
- package/node_modules/typebox/build/system/locale/es_ES.mjs +0 -1
- package/node_modules/typebox/build/system/locale/es_MX.mjs +0 -1
- package/node_modules/typebox/build/system/locale/fa_IR.mjs +0 -1
- package/node_modules/typebox/build/system/locale/fil_PH.mjs +0 -1
- package/node_modules/typebox/build/system/locale/fr_CA.mjs +0 -1
- package/node_modules/typebox/build/system/locale/fr_FR.mjs +0 -1
- package/node_modules/typebox/build/system/locale/ha_NG.mjs +0 -1
- package/node_modules/typebox/build/system/locale/hi_IN.mjs +0 -1
- package/node_modules/typebox/build/system/locale/hu_HU.mjs +0 -1
- package/node_modules/typebox/build/system/locale/id_ID.mjs +0 -1
- package/node_modules/typebox/build/system/locale/it_IT.mjs +0 -1
- package/node_modules/typebox/build/system/locale/ja_JP.mjs +0 -1
- package/node_modules/typebox/build/system/locale/ko_KR.mjs +0 -1
- package/node_modules/typebox/build/system/locale/ms_MY.mjs +0 -1
- package/node_modules/typebox/build/system/locale/nl_NL.mjs +0 -1
- package/node_modules/typebox/build/system/locale/pl_PL.mjs +0 -1
- package/node_modules/typebox/build/system/locale/pt_BR.mjs +0 -1
- package/node_modules/typebox/build/system/locale/pt_PT.mjs +0 -1
- package/node_modules/typebox/build/system/locale/ro_RO.mjs +0 -1
- package/node_modules/typebox/build/system/locale/ru_RU.mjs +0 -1
- package/node_modules/typebox/build/system/locale/sv_SE.mjs +0 -1
- package/node_modules/typebox/build/system/locale/sw_TZ.mjs +0 -1
- package/node_modules/typebox/build/system/locale/th_TH.mjs +0 -1
- package/node_modules/typebox/build/system/locale/tr_TR.mjs +0 -1
- package/node_modules/typebox/build/system/locale/uk_UA.mjs +0 -1
- package/node_modules/typebox/build/system/locale/ur_PK.mjs +0 -1
- package/node_modules/typebox/build/system/locale/vi_VN.mjs +0 -1
- package/node_modules/typebox/build/system/locale/yo_NG.mjs +0 -1
- package/node_modules/typebox/build/system/locale/zh_Hans.mjs +0 -1
- package/node_modules/typebox/build/system/locale/zh_Hant.mjs +0 -1
- package/node_modules/typebox/build/system/memory/clone.d.mts +2 -3
- package/node_modules/typebox/build/system/memory/clone.mjs +73 -26
- package/node_modules/typebox/build/system/settings/settings.d.mts +15 -0
- package/node_modules/typebox/build/system/settings/settings.mjs +3 -1
- package/node_modules/typebox/build/type/action/_add_immutable.d.mts +11 -0
- package/node_modules/typebox/build/type/action/_add_immutable.mjs +11 -0
- package/node_modules/typebox/build/type/action/_add_optional.d.mts +11 -0
- package/node_modules/typebox/build/type/action/_add_optional.mjs +11 -0
- package/node_modules/typebox/build/type/action/_add_readonly.d.mts +11 -0
- package/node_modules/typebox/build/type/action/_add_readonly.mjs +11 -0
- package/node_modules/typebox/build/type/action/_remove_immutable.d.mts +11 -0
- package/node_modules/typebox/build/type/action/_remove_immutable.mjs +11 -0
- package/node_modules/typebox/build/type/action/_remove_optional.d.mts +11 -0
- package/node_modules/typebox/build/type/action/_remove_optional.mjs +11 -0
- package/node_modules/typebox/build/type/action/_remove_readonly.d.mts +11 -0
- package/node_modules/typebox/build/type/action/_remove_readonly.mjs +11 -0
- package/node_modules/typebox/build/type/action/conditional.d.mts +2 -3
- package/node_modules/typebox/build/type/action/conditional.mjs +2 -1
- package/node_modules/typebox/build/type/action/index.d.mts +7 -4
- package/node_modules/typebox/build/type/action/index.mjs +7 -4
- package/node_modules/typebox/build/type/action/mapped.d.mts +2 -3
- package/node_modules/typebox/build/type/action/mapped.mjs +2 -1
- package/node_modules/typebox/build/type/action/module.d.mts +8 -7
- package/node_modules/typebox/build/type/action/module.mjs +7 -6
- package/node_modules/typebox/build/type/action/readonly_object.d.mts +0 -5
- package/node_modules/typebox/build/type/action/readonly_object.mjs +0 -5
- package/node_modules/typebox/build/type/action/with.d.mts +11 -0
- package/node_modules/typebox/build/type/action/with.mjs +11 -0
- package/node_modules/typebox/build/type/engine/call/distribute_arguments.mjs +1 -1
- package/node_modules/typebox/build/type/engine/call/instantiate.d.mts +1 -3
- package/node_modules/typebox/build/type/engine/call/instantiate.mjs +3 -2
- package/node_modules/typebox/build/type/engine/call/resolve_arguments.mjs +2 -2
- package/node_modules/typebox/build/type/engine/constructor_parameters/instantiate.d.mts +3 -4
- package/node_modules/typebox/build/type/engine/constructor_parameters/instantiate.mjs +2 -1
- package/node_modules/typebox/build/type/engine/cyclic/candidates.d.mts +2 -3
- package/node_modules/typebox/build/type/engine/cyclic/candidates.mjs +3 -6
- package/node_modules/typebox/build/type/engine/cyclic/check.d.mts +6 -9
- package/node_modules/typebox/build/type/engine/cyclic/check.mjs +10 -16
- package/node_modules/typebox/build/type/engine/cyclic/dependencies.d.mts +1 -4
- package/node_modules/typebox/build/type/engine/cyclic/dependencies.mjs +9 -15
- package/node_modules/typebox/build/type/engine/cyclic/extends.d.mts +1 -4
- package/node_modules/typebox/build/type/engine/cyclic/extends.mjs +8 -14
- package/node_modules/typebox/build/type/engine/cyclic/instantiate.d.mts +2 -5
- package/node_modules/typebox/build/type/engine/cyclic/instantiate.mjs +3 -2
- package/node_modules/typebox/build/type/engine/enum/index.d.mts +0 -1
- package/node_modules/typebox/build/type/engine/enum/index.mjs +0 -1
- package/node_modules/typebox/build/type/engine/evaluate/broaden.d.mts +1 -2
- package/node_modules/typebox/build/type/engine/evaluate/broaden.mjs +2 -6
- package/node_modules/typebox/build/type/engine/evaluate/composite.d.mts +10 -6
- package/node_modules/typebox/build/type/engine/evaluate/composite.mjs +10 -6
- package/node_modules/typebox/build/type/engine/evaluate/distribute.d.mts +2 -1
- package/node_modules/typebox/build/type/engine/evaluate/distribute.mjs +3 -3
- package/node_modules/typebox/build/type/engine/evaluate/evaluate.d.mts +17 -5
- package/node_modules/typebox/build/type/engine/evaluate/evaluate.mjs +34 -8
- package/node_modules/typebox/build/type/engine/exclude/operation.d.mts +5 -6
- package/node_modules/typebox/build/type/engine/exclude/operation.mjs +11 -12
- package/node_modules/typebox/build/type/engine/extract/operation.d.mts +5 -6
- package/node_modules/typebox/build/type/engine/extract/operation.mjs +11 -12
- package/node_modules/typebox/build/type/engine/immutable/instantiate_add.d.mts +10 -0
- package/node_modules/typebox/build/type/engine/immutable/instantiate_add.mjs +14 -0
- package/node_modules/typebox/build/type/engine/immutable/instantiate_remove.d.mts +10 -0
- package/node_modules/typebox/build/type/engine/immutable/instantiate_remove.mjs +14 -0
- package/node_modules/typebox/build/type/engine/index.d.mts +2 -2
- package/node_modules/typebox/build/type/engine/index.mjs +2 -2
- package/node_modules/typebox/build/type/engine/indexable/from_dependent.d.mts +5 -0
- package/node_modules/typebox/build/type/engine/indexable/from_dependent.mjs +8 -0
- package/node_modules/typebox/build/type/engine/indexable/from_enum.d.mts +3 -3
- package/node_modules/typebox/build/type/engine/indexable/from_enum.mjs +4 -4
- package/node_modules/typebox/build/type/engine/indexable/from_template_literal.d.mts +2 -2
- package/node_modules/typebox/build/type/engine/indexable/from_template_literal.mjs +3 -3
- package/node_modules/typebox/build/type/engine/indexable/from_type.d.mts +3 -1
- package/node_modules/typebox/build/type/engine/indexable/from_type.mjs +9 -6
- package/node_modules/typebox/build/type/engine/indexed/instantiate.d.mts +2 -1
- package/node_modules/typebox/build/type/engine/indexed/instantiate.mjs +5 -2
- package/node_modules/typebox/build/type/engine/instantiate.d.mts +44 -31
- package/node_modules/typebox/build/type/engine/instantiate.mjs +82 -83
- package/node_modules/typebox/build/type/engine/interface/instantiate.d.mts +3 -6
- package/node_modules/typebox/build/type/engine/intrinsics/from_template_literal.d.mts +2 -2
- package/node_modules/typebox/build/type/engine/intrinsics/from_template_literal.mjs +3 -3
- package/node_modules/typebox/build/type/engine/keyof/instantiate.d.mts +2 -1
- package/node_modules/typebox/build/type/engine/keyof/instantiate.mjs +5 -1
- package/node_modules/typebox/build/type/engine/mapped/mapped_operation.d.mts +4 -4
- package/node_modules/typebox/build/type/engine/mapped/mapped_operation.mjs +3 -3
- package/node_modules/typebox/build/type/engine/mapped/mapped_variants.d.mts +5 -4
- package/node_modules/typebox/build/type/engine/mapped/mapped_variants.mjs +10 -5
- package/node_modules/typebox/build/type/engine/module/instantiate.d.mts +7 -9
- package/node_modules/typebox/build/type/engine/module/instantiate.mjs +17 -15
- package/node_modules/typebox/build/type/engine/object/from_dependent.d.mts +5 -0
- package/node_modules/typebox/build/type/engine/object/from_dependent.mjs +8 -0
- package/node_modules/typebox/build/type/engine/object/from_type.d.mts +3 -1
- package/node_modules/typebox/build/type/engine/object/from_type.mjs +8 -5
- package/node_modules/typebox/build/type/engine/object/from_union.mjs +2 -2
- package/node_modules/typebox/build/type/engine/optional/instantiate_add.d.mts +10 -0
- package/node_modules/typebox/build/type/engine/optional/instantiate_add.mjs +14 -0
- package/node_modules/typebox/build/type/engine/optional/instantiate_remove.d.mts +10 -0
- package/node_modules/typebox/build/type/engine/optional/instantiate_remove.mjs +14 -0
- package/node_modules/typebox/build/type/engine/parameters/instantiate.d.mts +3 -4
- package/node_modules/typebox/build/type/engine/parameters/instantiate.mjs +2 -1
- package/node_modules/typebox/build/type/engine/partial/from_dependent.d.mts +5 -0
- package/node_modules/typebox/build/type/engine/partial/from_dependent.mjs +8 -0
- package/node_modules/typebox/build/type/engine/partial/from_intersect.d.mts +1 -1
- package/node_modules/typebox/build/type/engine/partial/from_intersect.mjs +3 -2
- package/node_modules/typebox/build/type/engine/partial/from_object.d.mts +2 -2
- package/node_modules/typebox/build/type/engine/partial/from_object.mjs +2 -2
- package/node_modules/typebox/build/type/engine/partial/from_type.d.mts +3 -1
- package/node_modules/typebox/build/type/engine/partial/from_type.mjs +7 -4
- package/node_modules/typebox/build/type/engine/priority/index.d.mts +1 -0
- package/node_modules/typebox/build/type/engine/priority/index.mjs +1 -0
- package/node_modules/typebox/build/type/engine/priority/priority.d.mts +20 -0
- package/node_modules/typebox/build/type/engine/priority/priority.mjs +28 -0
- package/node_modules/typebox/build/type/engine/readonly/instantiate_add.d.mts +10 -0
- package/node_modules/typebox/build/type/engine/readonly/instantiate_add.mjs +14 -0
- package/node_modules/typebox/build/type/engine/readonly/instantiate_remove.d.mts +10 -0
- package/node_modules/typebox/build/type/engine/readonly/instantiate_remove.mjs +14 -0
- package/node_modules/typebox/build/type/engine/readonly_object/from_array.d.mts +2 -2
- package/node_modules/typebox/build/type/engine/readonly_object/from_array.mjs +2 -2
- package/node_modules/typebox/build/type/engine/readonly_object/from_dependent.d.mts +5 -0
- package/node_modules/typebox/build/type/engine/readonly_object/from_dependent.mjs +8 -0
- package/node_modules/typebox/build/type/engine/readonly_object/from_intersect.d.mts +1 -1
- package/node_modules/typebox/build/type/engine/readonly_object/from_intersect.mjs +3 -2
- package/node_modules/typebox/build/type/engine/readonly_object/from_object.d.mts +2 -2
- package/node_modules/typebox/build/type/engine/readonly_object/from_object.mjs +2 -2
- package/node_modules/typebox/build/type/engine/readonly_object/from_tuple.d.mts +2 -2
- package/node_modules/typebox/build/type/engine/readonly_object/from_tuple.mjs +2 -2
- package/node_modules/typebox/build/type/engine/readonly_object/from_type.d.mts +3 -1
- package/node_modules/typebox/build/type/engine/readonly_object/from_type.mjs +8 -5
- package/node_modules/typebox/build/type/engine/record/from_key_enum.d.mts +2 -2
- package/node_modules/typebox/build/type/engine/record/from_key_enum.mjs +2 -2
- package/node_modules/typebox/build/type/engine/record/from_key_template_literal.d.mts +2 -2
- package/node_modules/typebox/build/type/engine/record/from_key_template_literal.mjs +2 -2
- package/node_modules/typebox/build/type/engine/ref/instantiate.d.mts +3 -3
- package/node_modules/typebox/build/type/engine/ref/instantiate.mjs +6 -6
- package/node_modules/typebox/build/type/engine/required/from_dependent.d.mts +5 -0
- package/node_modules/typebox/build/type/engine/required/from_dependent.mjs +8 -0
- package/node_modules/typebox/build/type/engine/required/from_intersect.d.mts +1 -1
- package/node_modules/typebox/build/type/engine/required/from_intersect.mjs +3 -2
- package/node_modules/typebox/build/type/engine/required/from_object.d.mts +2 -2
- package/node_modules/typebox/build/type/engine/required/from_object.mjs +2 -2
- package/node_modules/typebox/build/type/engine/required/from_type.d.mts +3 -1
- package/node_modules/typebox/build/type/engine/required/from_type.mjs +7 -4
- package/node_modules/typebox/build/type/engine/template_literal/decode.mjs +3 -3
- package/node_modules/typebox/build/type/engine/template_literal/encode.d.mts +2 -2
- package/node_modules/typebox/build/type/engine/template_literal/encode.mjs +6 -6
- package/node_modules/typebox/build/type/engine/template_literal/is_finite.mjs +1 -1
- package/node_modules/typebox/build/type/engine/template_literal/is_pattern.mjs +1 -0
- package/node_modules/typebox/build/type/engine/this/expand_this.d.mts +1 -4
- package/node_modules/typebox/build/type/engine/this/expand_this.mjs +7 -13
- package/node_modules/typebox/build/type/engine/with/instantiate.d.mts +8 -0
- package/node_modules/typebox/build/type/engine/{options → with}/instantiate.mjs +5 -5
- package/node_modules/typebox/build/type/extends/dependent.d.mts +6 -0
- package/node_modules/typebox/build/type/extends/dependent.mjs +6 -0
- package/node_modules/typebox/build/type/extends/enum.d.mts +4 -4
- package/node_modules/typebox/build/type/extends/enum.mjs +3 -2
- package/node_modules/typebox/build/type/extends/extends_left.d.mts +5 -7
- package/node_modules/typebox/build/type/extends/extends_left.mjs +24 -27
- package/node_modules/typebox/build/type/extends/extends_right.d.mts +7 -5
- package/node_modules/typebox/build/type/extends/extends_right.mjs +20 -15
- package/node_modules/typebox/build/type/extends/inference.mjs +1 -1
- package/node_modules/typebox/build/type/extends/object.d.mts +8 -1
- package/node_modules/typebox/build/type/extends/object.mjs +25 -3
- package/node_modules/typebox/build/type/extends/parameters.mjs +2 -2
- package/node_modules/typebox/build/type/extends/record.d.mts +13 -0
- package/node_modules/typebox/build/type/extends/record.mjs +23 -0
- package/node_modules/typebox/build/type/extends/template_literal.d.mts +3 -3
- package/node_modules/typebox/build/type/extends/template_literal.mjs +3 -3
- package/node_modules/typebox/build/type/extends/tuple.d.mts +3 -6
- package/node_modules/typebox/build/type/extends/tuple.mjs +6 -5
- package/node_modules/typebox/build/type/extends/union.mjs +2 -2
- package/node_modules/typebox/build/type/script/mapping.d.mts +84 -99
- package/node_modules/typebox/build/type/script/mapping.mjs +81 -85
- package/node_modules/typebox/build/type/script/parser.d.mts +40 -40
- package/node_modules/typebox/build/type/script/parser.mjs +22 -22
- package/node_modules/typebox/build/type/script/script.d.mts +3 -4
- package/node_modules/typebox/build/type/script/script.mjs +3 -2
- package/node_modules/typebox/build/type/script/token/internal/guard.d.mts +1 -1
- package/node_modules/typebox/build/type/script/token/internal/guard.mjs +1 -1
- package/node_modules/typebox/build/type/script/token/internal/take.mjs +1 -1
- package/node_modules/typebox/build/type/script/token/until.mjs +2 -2
- package/node_modules/typebox/build/type/types/_codec.d.mts +12 -12
- package/node_modules/typebox/build/type/types/_codec.mjs +0 -1
- package/node_modules/typebox/build/type/types/_immutable.d.mts +2 -9
- package/node_modules/typebox/build/type/types/_immutable.mjs +2 -10
- package/node_modules/typebox/build/type/types/_optional.d.mts +2 -9
- package/node_modules/typebox/build/type/types/_optional.mjs +2 -11
- package/node_modules/typebox/build/type/types/_readonly.d.mts +2 -9
- package/node_modules/typebox/build/type/types/_readonly.mjs +2 -10
- package/node_modules/typebox/build/type/types/_refine.d.mts +8 -10
- package/node_modules/typebox/build/type/types/_refine.mjs +1 -2
- package/node_modules/typebox/build/type/types/call.d.mts +3 -3
- package/node_modules/typebox/build/type/types/call.mjs +3 -2
- package/node_modules/typebox/build/type/types/deferred.d.mts +1 -0
- package/node_modules/typebox/build/type/types/deferred.mjs +1 -1
- package/node_modules/typebox/build/type/types/dependent.d.mts +17 -0
- package/node_modules/typebox/build/type/types/dependent.mjs +24 -0
- package/node_modules/typebox/build/type/types/enum.d.mts +3 -1
- package/node_modules/typebox/build/type/types/enum.mjs +5 -0
- package/node_modules/typebox/build/type/types/index.d.mts +1 -4
- package/node_modules/typebox/build/type/types/index.mjs +1 -4
- package/node_modules/typebox/build/type/types/number.d.mts +1 -1
- package/node_modules/typebox/build/type/types/number.mjs +1 -1
- package/node_modules/typebox/build/type/types/record.d.mts +13 -7
- package/node_modules/typebox/build/type/types/record.mjs +15 -9
- package/node_modules/typebox/build/type/types/static.d.mts +2 -5
- package/node_modules/typebox/build/typebox.d.mts +4 -8
- package/node_modules/typebox/build/typebox.mjs +4 -8
- package/node_modules/typebox/build/value/clean/clean.mjs +4 -2
- package/node_modules/typebox/build/value/clean/from_intersect.mjs +2 -2
- package/node_modules/typebox/build/value/clean/from_type.mjs +8 -10
- package/node_modules/typebox/build/value/clean/from_union.d.mts +1 -1
- package/node_modules/typebox/build/value/clean/from_union.mjs +1 -2
- package/node_modules/typebox/build/value/clone/clone.mjs +2 -73
- package/node_modules/typebox/build/value/codec/decode.mjs +4 -2
- package/node_modules/typebox/build/value/codec/encode.mjs +4 -2
- package/node_modules/typebox/build/value/codec/from_array.mjs +1 -4
- package/node_modules/typebox/build/value/codec/from_object.mjs +1 -4
- package/node_modules/typebox/build/value/codec/from_record.mjs +2 -7
- package/node_modules/typebox/build/value/codec/from_tuple.mjs +1 -4
- package/node_modules/typebox/build/value/codec/from_union.mjs +2 -3
- package/node_modules/typebox/build/value/convert/from_enum.mjs +3 -4
- package/node_modules/typebox/build/value/convert/from_template_literal.d.mts +1 -1
- package/node_modules/typebox/build/value/convert/from_template_literal.mjs +2 -3
- package/node_modules/typebox/build/value/convert/from_type.mjs +19 -21
- package/node_modules/typebox/build/value/create/from_enum.mjs +2 -2
- package/node_modules/typebox/build/value/create/from_type.mjs +23 -31
- package/node_modules/typebox/build/value/default/from_object.mjs +1 -1
- package/node_modules/typebox/build/value/default/from_type.mjs +8 -10
- package/node_modules/typebox/build/value/index.d.mts +0 -1
- package/node_modules/typebox/build/value/index.mjs +0 -1
- package/node_modules/typebox/build/value/repair/from_enum.mjs +2 -3
- package/node_modules/typebox/build/value/repair/from_type.mjs +24 -22
- package/node_modules/typebox/build/value/shared/union_priority_sort.d.mts +6 -2
- package/node_modules/typebox/build/value/shared/union_priority_sort.mjs +62 -26
- package/node_modules/typebox/build/value/value.d.mts +0 -1
- package/node_modules/typebox/build/value/value.mjs +0 -1
- package/node_modules/typebox/package.json +25 -25
- package/node_modules/typebox/readme.md +97 -80
- package/npm-shrinkwrap.json +12 -12
- package/openclaw.plugin.json +8 -0
- package/package.json +6 -6
- package/dist/response-generator-CXBGKbAp.js +0 -212
- package/node_modules/commander/esm.mjs +0 -16
- package/node_modules/commander/typings/esm.d.mts +0 -3
- package/node_modules/typebox/build/schema/engine/_guard.d.mts +0 -6
- package/node_modules/typebox/build/schema/engine/_guard.mjs +0 -26
- package/node_modules/typebox/build/schema/types/_guard.d.mts +0 -10
- package/node_modules/typebox/build/schema/types/_guard.mjs +0 -16
- package/node_modules/typebox/build/type/action/_optional.d.mts +0 -19
- package/node_modules/typebox/build/type/action/_optional.mjs +0 -40
- package/node_modules/typebox/build/type/action/_readonly.d.mts +0 -19
- package/node_modules/typebox/build/type/action/_readonly.mjs +0 -40
- package/node_modules/typebox/build/type/action/awaited.d.mts +0 -15
- package/node_modules/typebox/build/type/action/awaited.mjs +0 -15
- package/node_modules/typebox/build/type/action/options.d.mts +0 -11
- package/node_modules/typebox/build/type/action/options.mjs +0 -11
- package/node_modules/typebox/build/type/engine/awaited/instantiate.d.mts +0 -11
- package/node_modules/typebox/build/type/engine/awaited/instantiate.mjs +0 -20
- package/node_modules/typebox/build/type/engine/enum/enum_to_union.d.mts +0 -14
- package/node_modules/typebox/build/type/engine/enum/enum_to_union.mjs +0 -24
- package/node_modules/typebox/build/type/engine/options/index.d.mts +0 -1
- package/node_modules/typebox/build/type/engine/options/index.mjs +0 -1
- package/node_modules/typebox/build/type/engine/options/instantiate.d.mts +0 -8
- package/node_modules/typebox/build/type/extends/async_iterator.d.mts +0 -7
- package/node_modules/typebox/build/type/extends/async_iterator.mjs +0 -9
- package/node_modules/typebox/build/type/extends/iterator.d.mts +0 -7
- package/node_modules/typebox/build/type/extends/iterator.mjs +0 -9
- package/node_modules/typebox/build/type/extends/promise.d.mts +0 -7
- package/node_modules/typebox/build/type/extends/promise.mjs +0 -9
- package/node_modules/typebox/build/type/types/async_iterator.d.mts +0 -20
- package/node_modules/typebox/build/type/types/async_iterator.mjs +0 -28
- package/node_modules/typebox/build/type/types/base.d.mts +0 -50
- package/node_modules/typebox/build/type/types/base.mjs +0 -84
- package/node_modules/typebox/build/type/types/iterator.d.mts +0 -20
- package/node_modules/typebox/build/type/types/iterator.mjs +0 -28
- package/node_modules/typebox/build/type/types/promise.d.mts +0 -21
- package/node_modules/typebox/build/type/types/promise.mjs +0 -29
- package/node_modules/typebox/build/value/clean/from_base.d.mts +0 -2
- package/node_modules/typebox/build/value/clean/from_base.mjs +0 -4
- package/node_modules/typebox/build/value/convert/from_base.d.mts +0 -2
- package/node_modules/typebox/build/value/convert/from_base.mjs +0 -4
- package/node_modules/typebox/build/value/create/from_async_iterator.d.mts +0 -2
- package/node_modules/typebox/build/value/create/from_async_iterator.mjs +0 -5
- package/node_modules/typebox/build/value/create/from_base.d.mts +0 -2
- package/node_modules/typebox/build/value/create/from_base.mjs +0 -4
- package/node_modules/typebox/build/value/create/from_iterator.d.mts +0 -2
- package/node_modules/typebox/build/value/create/from_iterator.mjs +0 -5
- package/node_modules/typebox/build/value/create/from_promise.d.mts +0 -2
- package/node_modules/typebox/build/value/create/from_promise.mjs +0 -5
- package/node_modules/typebox/build/value/default/from_base.d.mts +0 -2
- package/node_modules/typebox/build/value/default/from_base.mjs +0 -5
- package/node_modules/typebox/build/value/mutate/error.d.mts +0 -3
- package/node_modules/typebox/build/value/mutate/error.mjs +0 -6
- package/node_modules/typebox/build/value/mutate/from_array.d.mts +0 -2
- package/node_modules/typebox/build/value/mutate/from_array.mjs +0 -16
- package/node_modules/typebox/build/value/mutate/from_object.d.mts +0 -2
- package/node_modules/typebox/build/value/mutate/from_object.mjs +0 -40
- package/node_modules/typebox/build/value/mutate/from_unknown.d.mts +0 -2
- package/node_modules/typebox/build/value/mutate/from_unknown.mjs +0 -7
- package/node_modules/typebox/build/value/mutate/from_value.d.mts +0 -2
- package/node_modules/typebox/build/value/mutate/from_value.mjs +0 -12
- package/node_modules/typebox/build/value/mutate/index.d.mts +0 -1
- package/node_modules/typebox/build/value/mutate/index.mjs +0 -1
- package/node_modules/typebox/build/value/mutate/mutate.d.mts +0 -11
- package/node_modules/typebox/build/value/mutate/mutate.mjs +0 -41
- package/node_modules/typebox/build/value/repair/from_base.d.mts +0 -2
- package/node_modules/typebox/build/value/repair/from_base.mjs +0 -8
- /package/node_modules/typebox/build/type/engine/{awaited → with}/index.d.mts +0 -0
- /package/node_modules/typebox/build/type/engine/{awaited → with}/index.mjs +0 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { a as reconstructWebhookUrl, o as verifyPlivoWebhook, t as guardedJsonApiRequest } from "./guarded-json-api-
|
|
1
|
+
import { g as escapeXml, o as getHeader } from "./runtime-entry-kCq5Xjph.js";
|
|
2
|
+
import { a as reconstructWebhookUrl, o as verifyPlivoWebhook, t as guardedJsonApiRequest } from "./guarded-json-api-BrBbW_RJ.js";
|
|
3
3
|
import { normalizeLowercaseStringOrEmpty, normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
4
4
|
import crypto from "node:crypto";
|
|
5
5
|
//#region extensions/voice-call/src/providers/plivo.ts
|
|
@@ -75,9 +75,17 @@ var PlivoProvider = class PlivoProvider {
|
|
|
75
75
|
const callId = this.getCallIdFromQuery(ctx);
|
|
76
76
|
const pending = callId ? this.pendingSpeakByCallId.get(callId) : void 0;
|
|
77
77
|
if (callId) this.pendingSpeakByCallId.delete(callId);
|
|
78
|
+
const actionUrl = pending?.listenAfterPlayback && callId ? this.buildActionUrl(ctx, {
|
|
79
|
+
flow: "getinput",
|
|
80
|
+
callId
|
|
81
|
+
}) : null;
|
|
78
82
|
return {
|
|
79
83
|
events: [],
|
|
80
|
-
providerResponseBody: pending ?
|
|
84
|
+
providerResponseBody: pending ? actionUrl ? PlivoProvider.xmlSpeakAndListen({
|
|
85
|
+
text: pending.text,
|
|
86
|
+
language: pending.locale,
|
|
87
|
+
actionUrl
|
|
88
|
+
}) : PlivoProvider.xmlSpeak(pending.text, pending.locale) : PlivoProvider.xmlKeepAlive(),
|
|
81
89
|
providerResponseHeaders: { "Content-Type": "text/xml" },
|
|
82
90
|
statusCode: 200
|
|
83
91
|
};
|
|
@@ -244,7 +252,8 @@ var PlivoProvider = class PlivoProvider {
|
|
|
244
252
|
});
|
|
245
253
|
this.pendingSpeakByCallId.set(input.callId, {
|
|
246
254
|
text: input.text,
|
|
247
|
-
locale: input.locale
|
|
255
|
+
locale: input.locale,
|
|
256
|
+
listenAfterPlayback: input.listenAfterPlayback
|
|
248
257
|
});
|
|
249
258
|
await this.transferCallLeg({
|
|
250
259
|
callUuid,
|
|
@@ -269,7 +278,7 @@ var PlivoProvider = class PlivoProvider {
|
|
|
269
278
|
}
|
|
270
279
|
async stopListening(_input) {}
|
|
271
280
|
async getCallStatus(input) {
|
|
272
|
-
const terminalStatuses = new Set([
|
|
281
|
+
const terminalStatuses = /* @__PURE__ */ new Set([
|
|
273
282
|
"completed",
|
|
274
283
|
"busy",
|
|
275
284
|
"failed",
|
|
@@ -331,7 +340,17 @@ var PlivoProvider = class PlivoProvider {
|
|
|
331
340
|
const language = params.language || "en-US";
|
|
332
341
|
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
333
342
|
<Response>
|
|
334
|
-
<GetInput inputType="speech" method="POST" action="${escapeXml(params.actionUrl)}" language="${escapeXml(language)}" executionTimeout="30" speechEndTimeout="
|
|
343
|
+
<GetInput inputType="speech" method="POST" action="${escapeXml(params.actionUrl)}" language="${escapeXml(language)}" executionTimeout="30" speechEndTimeout="2" redirect="false">
|
|
344
|
+
</GetInput>
|
|
345
|
+
<Wait length="300" />
|
|
346
|
+
</Response>`;
|
|
347
|
+
}
|
|
348
|
+
static xmlSpeakAndListen(params) {
|
|
349
|
+
const language = params.language || "en-US";
|
|
350
|
+
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
351
|
+
<Response>
|
|
352
|
+
<GetInput inputType="speech" method="POST" action="${escapeXml(params.actionUrl)}" language="${escapeXml(language)}" executionTimeout="30" speechEndTimeout="2" redirect="false">
|
|
353
|
+
<Speak language="${escapeXml(language)}">${escapeXml(params.text)}</Speak>
|
|
335
354
|
</GetInput>
|
|
336
355
|
<Wait length="300" />
|
|
337
356
|
</Response>`;
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import { l as normalizePath } from "./config-DNtTB7Iw.js";
|
|
2
1
|
import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
|
|
3
2
|
import { isFutureDateTimestampMs, resolveExpiresAtMsFromDurationMs } from "openclaw/plugin-sdk/number-runtime";
|
|
4
3
|
import { createSubsystemLogger } from "openclaw/plugin-sdk/runtime-env";
|
|
5
4
|
import { REALTIME_VOICE_AGENT_CONSULT_TOOL_NAME, buildRealtimeVoiceAgentConsultWorkingResponse, createRealtimeVoiceBridgeSession, createRealtimeVoiceForcedConsultCoordinator, createTalkSessionController, readRealtimeVoiceConsultQuestion, readSpeakableRealtimeVoiceToolResult, recordTalkObservabilityEvent } from "openclaw/plugin-sdk/realtime-voice";
|
|
5
|
+
import { normalizeWebhookPath } from "openclaw/plugin-sdk/webhook-ingress";
|
|
6
6
|
import { randomUUID } from "node:crypto";
|
|
7
|
-
import "node:http";
|
|
8
|
-
import WebSocket, { WebSocketServer } from "ws";
|
|
9
7
|
import { sliceUtf16Safe, truncateUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime";
|
|
8
|
+
import "node:http";
|
|
9
|
+
import WebSocket$1, { WebSocketServer } from "ws";
|
|
10
10
|
//#region extensions/voice-call/src/webhook/realtime-audio-pacer.ts
|
|
11
11
|
const TELEPHONY_SAMPLE_RATE = 8e3;
|
|
12
12
|
const TELEPHONY_CHUNK_BYTES = 160;
|
|
@@ -16,7 +16,7 @@ const DEFAULT_REQUIRED_LOUD_CHUNKS = 4;
|
|
|
16
16
|
const DEFAULT_REQUIRED_QUIET_CHUNKS = 12;
|
|
17
17
|
const DEFAULT_MAX_QUEUED_AUDIO_BYTES = TELEPHONY_SAMPLE_RATE * 120;
|
|
18
18
|
const PCM16_MAX_AMPLITUDE = 32768;
|
|
19
|
-
const MULAW_LINEAR_SAMPLES = new Int16Array(256);
|
|
19
|
+
const MULAW_LINEAR_SAMPLES = /* @__PURE__ */ new Int16Array(256);
|
|
20
20
|
for (let i = 0; i < MULAW_LINEAR_SAMPLES.length; i += 1) MULAW_LINEAR_SAMPLES[i] = decodeMulawSample(i);
|
|
21
21
|
/** Paces outgoing mulaw audio frames at telephony cadence. */
|
|
22
22
|
var RealtimeAudioPacer = class {
|
|
@@ -65,6 +65,10 @@ var RealtimeAudioPacer = class {
|
|
|
65
65
|
this.params.send(this.params.serializer.clear());
|
|
66
66
|
return clearedAudioBytes;
|
|
67
67
|
}
|
|
68
|
+
/** True while queued audio or a paced send timer can still reach the telephony stream. */
|
|
69
|
+
hasPendingAudio() {
|
|
70
|
+
return !this.closed && (this.queuedAudioBytes > 0 || this.timer !== null);
|
|
71
|
+
}
|
|
68
72
|
/** Stop sending and discard queued frames. */
|
|
69
73
|
close() {
|
|
70
74
|
this.closed = true;
|
|
@@ -378,6 +382,21 @@ function appendTranscriptText(base, fragment) {
|
|
|
378
382
|
if (overlap >= 6 || overlap >= 3 && next.length <= 12) return `${current}${next.slice(overlap)}`.trim();
|
|
379
383
|
return `${current}${shouldInsertTranscriptSpace(current, next) ? " " : ""}${next}`.trim();
|
|
380
384
|
}
|
|
385
|
+
function resolveFinalTranscriptText(params) {
|
|
386
|
+
const final = normalizeTranscriptText(params.final);
|
|
387
|
+
const rawPartial = params.rawPartial ?? "";
|
|
388
|
+
const partial = normalizeTranscriptText(params.partial ?? rawPartial);
|
|
389
|
+
if (!partial) return final;
|
|
390
|
+
if (!final) return partial;
|
|
391
|
+
const compact = (value) => value.toLowerCase().replaceAll(/\s/g, "");
|
|
392
|
+
const compactFinal = compact(final);
|
|
393
|
+
const compactRaw = compact(rawPartial);
|
|
394
|
+
const compactPartial = compact(partial);
|
|
395
|
+
if (compactFinal.startsWith(compactPartial) || compactFinal.endsWith(compactPartial)) return final;
|
|
396
|
+
if (compactPartial.endsWith(compactFinal)) return partial;
|
|
397
|
+
if (compactRaw !== compactPartial) return appendTranscriptText(partial, params.final);
|
|
398
|
+
return normalizeTranscriptText(`${rawPartial}${params.final}`);
|
|
399
|
+
}
|
|
381
400
|
function limitPartialUserTranscript(text) {
|
|
382
401
|
if (text.length <= MAX_PARTIAL_USER_TRANSCRIPT_CHARS) return text;
|
|
383
402
|
const tail = sliceUtf16Safe(text, -1200);
|
|
@@ -438,7 +457,7 @@ function appendRecentTalkEventMetadata(call, event) {
|
|
|
438
457
|
call.metadata = metadata;
|
|
439
458
|
}
|
|
440
459
|
var RealtimeCallHandler = class {
|
|
441
|
-
constructor(config, manager, provider, realtimeProvider, providerConfig, servePath, coreConfig) {
|
|
460
|
+
constructor(config, manager, provider, realtimeProvider, providerConfig, servePath, coreConfig, resolveInstructions) {
|
|
442
461
|
this.config = config;
|
|
443
462
|
this.manager = manager;
|
|
444
463
|
this.provider = provider;
|
|
@@ -446,11 +465,13 @@ var RealtimeCallHandler = class {
|
|
|
446
465
|
this.providerConfig = providerConfig;
|
|
447
466
|
this.servePath = servePath;
|
|
448
467
|
this.coreConfig = coreConfig;
|
|
468
|
+
this.resolveInstructions = resolveInstructions;
|
|
449
469
|
this.toolHandlers = /* @__PURE__ */ new Map();
|
|
450
470
|
this.pendingStreamTokens = /* @__PURE__ */ new Map();
|
|
451
471
|
this.activeBridgesByCallId = /* @__PURE__ */ new Map();
|
|
452
472
|
this.activeTelephonyClosersByCallId = /* @__PURE__ */ new Map();
|
|
453
473
|
this.partialUserTranscriptsByCallId = /* @__PURE__ */ new Map();
|
|
474
|
+
this.rawPartialUserTranscriptsByCallId = /* @__PURE__ */ new Map();
|
|
454
475
|
this.partialUserTranscriptUpdatedAtByCallId = /* @__PURE__ */ new Map();
|
|
455
476
|
this.recentFinalUserTranscriptsByCallId = /* @__PURE__ */ new Map();
|
|
456
477
|
this.recentFinalUserTranscriptTimersByCallId = /* @__PURE__ */ new Map();
|
|
@@ -464,8 +485,8 @@ var RealtimeCallHandler = class {
|
|
|
464
485
|
try {
|
|
465
486
|
const parsed = new URL(url);
|
|
466
487
|
this.publicOrigin = parsed.host;
|
|
467
|
-
const normalizedServePath =
|
|
468
|
-
const normalizedPublicPath =
|
|
488
|
+
const normalizedServePath = normalizeWebhookPath(this.servePath);
|
|
489
|
+
const normalizedPublicPath = normalizeWebhookPath(parsed.pathname);
|
|
469
490
|
const idx = normalizedPublicPath.indexOf(normalizedServePath);
|
|
470
491
|
this.publicPathPrefix = idx > 0 ? normalizedPublicPath.slice(0, idx) : "";
|
|
471
492
|
} catch {
|
|
@@ -474,7 +495,7 @@ var RealtimeCallHandler = class {
|
|
|
474
495
|
}
|
|
475
496
|
}
|
|
476
497
|
getStreamPathPattern() {
|
|
477
|
-
return `${this.publicPathPrefix}${
|
|
498
|
+
return `${this.publicPathPrefix}${normalizeWebhookPath(this.config.streamPath ?? "/voice/stream/realtime")}`;
|
|
478
499
|
}
|
|
479
500
|
buildTwiMLPayload(req, params) {
|
|
480
501
|
const rawDirection = params?.get("Direction");
|
|
@@ -638,7 +659,7 @@ var RealtimeCallHandler = class {
|
|
|
638
659
|
ws.close(1008, "Caller rejected by policy");
|
|
639
660
|
return null;
|
|
640
661
|
}
|
|
641
|
-
const { callId, initialGreetingInstructions } = registration;
|
|
662
|
+
const { callId, instructions, initialGreetingInstructions } = registration;
|
|
642
663
|
const callRecord = this.manager.getCallByProviderCallId(callSid);
|
|
643
664
|
const talk = createTalkSessionController({
|
|
644
665
|
sessionId: `voice-call:${callId}:realtime`,
|
|
@@ -677,6 +698,28 @@ var RealtimeCallHandler = class {
|
|
|
677
698
|
reason
|
|
678
699
|
} }));
|
|
679
700
|
};
|
|
701
|
+
const providerHandlesInputAudioBargeIn = this.realtimeProvider.capabilities?.handlesInputAudioBargeIn === true;
|
|
702
|
+
const cancelOutputAudioForBargeIn = (source, interruptProvider, clearedAudioBytes = 0) => {
|
|
703
|
+
const outputAudioActive = talk.outputAudioActive;
|
|
704
|
+
const pendingTelephonyAudio = audioPacer.hasPendingAudio();
|
|
705
|
+
if (source === "provider" && !outputAudioActive && !pendingTelephonyAudio && clearedAudioBytes === 0) return;
|
|
706
|
+
const interruptedTurnId = talk.activeTurnId;
|
|
707
|
+
interruptProvider?.(outputAudioActive || pendingTelephonyAudio);
|
|
708
|
+
const clearedBytes = clearedAudioBytes + (source === "local" || pendingTelephonyAudio ? audioPacer.clearAudio() : 0);
|
|
709
|
+
console.log(`[voice-call] realtime outbound audio cleared by ${source} barge-in callId=${callId} providerCallId=${callSid} queuedBytes=${clearedBytes}`);
|
|
710
|
+
if (!outputAudioActive || !interruptedTurnId) return;
|
|
711
|
+
const reason = `${source}-barge-in`;
|
|
712
|
+
finishOutputAudio(reason);
|
|
713
|
+
const cancelled = talk.cancelTurn({
|
|
714
|
+
turnId: interruptedTurnId,
|
|
715
|
+
payload: {
|
|
716
|
+
callId,
|
|
717
|
+
providerCallId: callSid,
|
|
718
|
+
reason
|
|
719
|
+
}
|
|
720
|
+
});
|
|
721
|
+
if (cancelled.ok) rememberTalkEvent(cancelled.event);
|
|
722
|
+
};
|
|
680
723
|
emitTalkEvent({
|
|
681
724
|
type: "session.started",
|
|
682
725
|
payload: {
|
|
@@ -693,7 +736,7 @@ var RealtimeCallHandler = class {
|
|
|
693
736
|
this.endCallInManager(callSid, callId, reason);
|
|
694
737
|
};
|
|
695
738
|
const sendString = (message) => {
|
|
696
|
-
if (ws.readyState !== WebSocket.OPEN) return false;
|
|
739
|
+
if (ws.readyState !== WebSocket$1.OPEN) return false;
|
|
697
740
|
if (ws.bufferedAmount > MAX_REALTIME_WS_BUFFERED_BYTES) {
|
|
698
741
|
console.warn(`[voice-call] realtime outbound websocket backpressure before send callId=${callId} providerCallId=${callSid} bufferedBytes=${ws.bufferedAmount}`);
|
|
699
742
|
ws.close(1013, "Backpressure: send buffer exceeded");
|
|
@@ -716,20 +759,22 @@ var RealtimeCallHandler = class {
|
|
|
716
759
|
},
|
|
717
760
|
onBackpressure: () => {
|
|
718
761
|
console.warn(`[voice-call] realtime paced audio backpressure callId=${callId} providerCallId=${callSid}`);
|
|
719
|
-
if (ws.readyState === WebSocket.OPEN) ws.close(1013, "Backpressure: paced audio queue exceeded");
|
|
762
|
+
if (ws.readyState === WebSocket$1.OPEN) ws.close(1013, "Backpressure: paced audio queue exceeded");
|
|
720
763
|
}
|
|
721
764
|
});
|
|
722
765
|
const speechDetector = new RealtimeMulawSpeechStartDetector({ requiredLoudChunks: BARGE_IN_REQUIRED_LOUD_CHUNKS });
|
|
766
|
+
const interruptResponseOnInputAudio = typeof this.providerConfig.interruptResponseOnInputAudio === "boolean" ? this.providerConfig.interruptResponseOnInputAudio : void 0;
|
|
723
767
|
const session = createRealtimeVoiceBridgeSession({
|
|
724
768
|
provider: this.realtimeProvider,
|
|
725
769
|
cfg: this.coreConfig,
|
|
726
770
|
providerConfig: this.providerConfig,
|
|
727
|
-
|
|
771
|
+
interruptResponseOnInputAudio,
|
|
772
|
+
instructions,
|
|
728
773
|
tools: this.config.tools,
|
|
729
774
|
initialGreetingInstructions,
|
|
730
775
|
triggerGreetingOnReady: Boolean(initialGreetingInstructions),
|
|
731
776
|
audioSink: {
|
|
732
|
-
isOpen: () => ws.readyState === WebSocket.OPEN,
|
|
777
|
+
isOpen: () => ws.readyState === WebSocket$1.OPEN,
|
|
733
778
|
sendAudio: (muLaw) => {
|
|
734
779
|
const turnId = ensureTalkTurn();
|
|
735
780
|
rememberTalkEvent(talk.startOutputAudio({
|
|
@@ -746,8 +791,12 @@ var RealtimeCallHandler = class {
|
|
|
746
791
|
});
|
|
747
792
|
audioPacer.sendAudio(muLaw);
|
|
748
793
|
},
|
|
749
|
-
clearAudio: () => {
|
|
794
|
+
clearAudio: (reason) => {
|
|
750
795
|
const clearedBytes = audioPacer.clearAudio();
|
|
796
|
+
if (reason === "barge-in") {
|
|
797
|
+
cancelOutputAudioForBargeIn("provider", void 0, clearedBytes);
|
|
798
|
+
return;
|
|
799
|
+
}
|
|
751
800
|
console.log(`[voice-call] realtime outbound audio clear requested callId=${callId} providerCallId=${callSid} queuedBytes=${clearedBytes}`);
|
|
752
801
|
finishOutputAudio("clear");
|
|
753
802
|
},
|
|
@@ -783,7 +832,11 @@ var RealtimeCallHandler = class {
|
|
|
783
832
|
return;
|
|
784
833
|
}
|
|
785
834
|
if (role === "user") {
|
|
786
|
-
const transcript =
|
|
835
|
+
const transcript = resolveFinalTranscriptText({
|
|
836
|
+
partial: this.partialUserTranscriptsByCallId.get(callId),
|
|
837
|
+
rawPartial: this.rawPartialUserTranscriptsByCallId.get(callId),
|
|
838
|
+
final: text
|
|
839
|
+
});
|
|
787
840
|
this.clearPartialUserTranscript(callId);
|
|
788
841
|
this.setRecentFinalUserTranscript(callId, transcript);
|
|
789
842
|
console.log(`[voice-call] realtime input transcript callId=${callId} providerCallId=${callSid} final=true chars=${text.trim().length} aggregateChars=${transcript.length}`);
|
|
@@ -811,11 +864,11 @@ var RealtimeCallHandler = class {
|
|
|
811
864
|
}
|
|
812
865
|
this.manager.processEvent({
|
|
813
866
|
id: `realtime-bot-${callSid}-${Date.now()}`,
|
|
814
|
-
type: "call.
|
|
867
|
+
type: "call.assistant-speech",
|
|
815
868
|
callId,
|
|
816
869
|
providerCallId: callSid,
|
|
817
870
|
timestamp: Date.now(),
|
|
818
|
-
text
|
|
871
|
+
transcript: text
|
|
819
872
|
});
|
|
820
873
|
},
|
|
821
874
|
onToolCall: (toolEvent, sessionLocal) => {
|
|
@@ -895,7 +948,7 @@ var RealtimeCallHandler = class {
|
|
|
895
948
|
});
|
|
896
949
|
if (reason !== "error") return;
|
|
897
950
|
emitCallEnd("error");
|
|
898
|
-
if (ws.readyState === WebSocket.OPEN) ws.close(1011, "Bridge disconnected");
|
|
951
|
+
if (ws.readyState === WebSocket$1.OPEN) ws.close(1011, "Bridge disconnected");
|
|
899
952
|
this.provider.hangupCall({
|
|
900
953
|
callId,
|
|
901
954
|
providerCallId: callSid,
|
|
@@ -906,8 +959,11 @@ var RealtimeCallHandler = class {
|
|
|
906
959
|
}
|
|
907
960
|
});
|
|
908
961
|
const closeTelephony = (reason) => {
|
|
909
|
-
|
|
910
|
-
|
|
962
|
+
try {
|
|
963
|
+
session.close();
|
|
964
|
+
} finally {
|
|
965
|
+
emitCallEnd(reason);
|
|
966
|
+
}
|
|
911
967
|
};
|
|
912
968
|
this.activeBridgesByCallId.set(callId, session);
|
|
913
969
|
this.activeBridgesByCallId.set(callSid, session);
|
|
@@ -916,19 +972,10 @@ var RealtimeCallHandler = class {
|
|
|
916
972
|
const sendAudioToSession = session.sendAudio.bind(session);
|
|
917
973
|
session.sendAudio = (audio) => {
|
|
918
974
|
if (speechDetector.accept(audio)) {
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
finishOutputAudio("barge-in");
|
|
923
|
-
const cancelled = talk.cancelTurn({
|
|
924
|
-
turnId: interruptedTurnId,
|
|
925
|
-
payload: {
|
|
926
|
-
callId,
|
|
927
|
-
providerCallId: callSid,
|
|
928
|
-
reason: "barge-in"
|
|
929
|
-
}
|
|
975
|
+
console.log(`[voice-call] realtime local speech detected callId=${callId} providerCallId=${callSid}`);
|
|
976
|
+
if (!providerHandlesInputAudioBargeIn) cancelOutputAudioForBargeIn("local", (audioPlaybackActive) => {
|
|
977
|
+
session.handleBargeIn({ audioPlaybackActive });
|
|
930
978
|
});
|
|
931
|
-
if (cancelled.ok) rememberTalkEvent(cancelled.event);
|
|
932
979
|
}
|
|
933
980
|
emitTalkEvent({
|
|
934
981
|
type: "input.audio.delta",
|
|
@@ -938,15 +985,21 @@ var RealtimeCallHandler = class {
|
|
|
938
985
|
sendAudioToSession(audio);
|
|
939
986
|
};
|
|
940
987
|
const closeSession = session.close.bind(session);
|
|
988
|
+
let sessionClosed = false;
|
|
941
989
|
session.close = () => {
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
990
|
+
if (sessionClosed) return;
|
|
991
|
+
sessionClosed = true;
|
|
992
|
+
try {
|
|
993
|
+
closeSession();
|
|
994
|
+
} finally {
|
|
995
|
+
this.activeBridgesByCallId.delete(callId);
|
|
996
|
+
this.activeBridgesByCallId.delete(callSid);
|
|
997
|
+
this.activeTelephonyClosersByCallId.delete(callId);
|
|
998
|
+
this.activeTelephonyClosersByCallId.delete(callSid);
|
|
999
|
+
this.clearUserTranscriptState(callId);
|
|
1000
|
+
this.clearForcedConsultState(callId);
|
|
1001
|
+
audioPacer.close();
|
|
1002
|
+
}
|
|
950
1003
|
};
|
|
951
1004
|
session.connect().catch((error) => {
|
|
952
1005
|
console.error("[voice-call] Failed to connect realtime bridge:", error);
|
|
@@ -958,12 +1011,15 @@ var RealtimeCallHandler = class {
|
|
|
958
1011
|
}
|
|
959
1012
|
recordPartialUserTranscript(callId, text) {
|
|
960
1013
|
const next = limitPartialUserTranscript(appendTranscriptText(this.partialUserTranscriptsByCallId.get(callId), text));
|
|
1014
|
+
const raw = limitPartialUserTranscript(`${this.rawPartialUserTranscriptsByCallId.get(callId) ?? ""}${text}`);
|
|
961
1015
|
this.partialUserTranscriptsByCallId.set(callId, next);
|
|
1016
|
+
this.rawPartialUserTranscriptsByCallId.set(callId, raw);
|
|
962
1017
|
this.partialUserTranscriptUpdatedAtByCallId.set(callId, Date.now());
|
|
963
1018
|
return next;
|
|
964
1019
|
}
|
|
965
1020
|
clearPartialUserTranscript(callId) {
|
|
966
1021
|
this.partialUserTranscriptsByCallId.delete(callId);
|
|
1022
|
+
this.rawPartialUserTranscriptsByCallId.delete(callId);
|
|
967
1023
|
this.partialUserTranscriptUpdatedAtByCallId.delete(callId);
|
|
968
1024
|
}
|
|
969
1025
|
setRecentFinalUserTranscript(callId, text) {
|
|
@@ -1002,8 +1058,10 @@ var RealtimeCallHandler = class {
|
|
|
1002
1058
|
}
|
|
1003
1059
|
if (current.toLowerCase().startsWith(text.toLowerCase())) {
|
|
1004
1060
|
const remaining = current.slice(text.length).trimStart();
|
|
1005
|
-
if (remaining)
|
|
1006
|
-
|
|
1061
|
+
if (remaining) {
|
|
1062
|
+
this.partialUserTranscriptsByCallId.set(callId, remaining);
|
|
1063
|
+
this.rawPartialUserTranscriptsByCallId.set(callId, remaining);
|
|
1064
|
+
} else this.clearPartialUserTranscript(callId);
|
|
1007
1065
|
}
|
|
1008
1066
|
const recent = this.recentFinalUserTranscriptsByCallId.get(callId);
|
|
1009
1067
|
if (!recent) return;
|
|
@@ -1125,9 +1183,11 @@ var RealtimeCallHandler = class {
|
|
|
1125
1183
|
type: "call.answered",
|
|
1126
1184
|
...baseFields
|
|
1127
1185
|
});
|
|
1186
|
+
const instructions = this.resolveInstructions?.(callRecord) ?? this.config.instructions;
|
|
1128
1187
|
return {
|
|
1129
1188
|
callId: callRecord.callId,
|
|
1130
|
-
|
|
1189
|
+
instructions,
|
|
1190
|
+
initialGreetingInstructions: buildGreetingInstructions(instructions, initialGreeting)
|
|
1131
1191
|
};
|
|
1132
1192
|
}
|
|
1133
1193
|
resolveRealtimeCall(callSid, callerMeta, baseFields) {
|
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
import { s as resolveVoiceCallSessionKey } from "./config-CgigQDrF.js";
|
|
2
|
+
import { m as resolveCallAgentId, p as resolveVoiceResponseModel } from "./runtime-entry-kCq5Xjph.js";
|
|
3
|
+
import { isRecord, normalizeLowercaseStringOrEmpty, normalizeStringEntries } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
4
|
+
import crypto from "node:crypto";
|
|
5
|
+
import { applyModelOverrideToSessionEntry } from "openclaw/plugin-sdk/model-session-runtime";
|
|
6
|
+
//#region extensions/voice-call/src/response-generator.ts
|
|
7
|
+
/**
|
|
8
|
+
* Voice call response generator - uses the embedded OpenClaw agent for tool support.
|
|
9
|
+
* Routes voice responses through the same agent infrastructure as messaging.
|
|
10
|
+
*/
|
|
11
|
+
function readExplicitToolsAllow(value) {
|
|
12
|
+
if (!isRecord(value)) return;
|
|
13
|
+
const allow = value.allow;
|
|
14
|
+
if (!Array.isArray(allow)) return;
|
|
15
|
+
return allow.filter((entry) => typeof entry === "string");
|
|
16
|
+
}
|
|
17
|
+
function resolveVoiceAgentToolsAllow(config, agentId) {
|
|
18
|
+
const agents = isRecord(config.agents) ? config.agents : void 0;
|
|
19
|
+
const agent = (Array.isArray(agents?.list) ? agents.list : []).find((entry) => isRecord(entry) && entry.id === agentId);
|
|
20
|
+
if (!isRecord(agent)) return;
|
|
21
|
+
return readExplicitToolsAllow(isRecord(agent.tools) ? agent.tools : void 0);
|
|
22
|
+
}
|
|
23
|
+
const VOICE_SPOKEN_OUTPUT_CONTRACT = [
|
|
24
|
+
"Output format requirements:",
|
|
25
|
+
"- Return only valid JSON in this exact shape: {\"spoken\":\"...\"}",
|
|
26
|
+
"- Do not include markdown, code fences, planning text, or extra keys.",
|
|
27
|
+
"- Put exactly what should be spoken to the caller into \"spoken\".",
|
|
28
|
+
"- If there is nothing to say, return {\"spoken\":\"\"}."
|
|
29
|
+
].join("\n");
|
|
30
|
+
function normalizeSpokenText(value) {
|
|
31
|
+
const normalized = value.replace(/\s+/g, " ").trim();
|
|
32
|
+
return normalized.length > 0 ? normalized : null;
|
|
33
|
+
}
|
|
34
|
+
function tryParseSpokenJson(text) {
|
|
35
|
+
const candidates = [];
|
|
36
|
+
const trimmed = text.trim();
|
|
37
|
+
if (!trimmed) return null;
|
|
38
|
+
candidates.push(trimmed);
|
|
39
|
+
const fenced = trimmed.match(/^```(?:json)?\s*([\s\S]*?)\s*```$/i);
|
|
40
|
+
if (fenced?.[1]) candidates.push(fenced[1]);
|
|
41
|
+
const firstBrace = trimmed.indexOf("{");
|
|
42
|
+
const lastBrace = trimmed.lastIndexOf("}");
|
|
43
|
+
if (firstBrace >= 0 && lastBrace > firstBrace) candidates.push(trimmed.slice(firstBrace, lastBrace + 1));
|
|
44
|
+
for (const candidate of candidates) try {
|
|
45
|
+
const parsed = JSON.parse(candidate);
|
|
46
|
+
if (typeof parsed?.spoken !== "string") continue;
|
|
47
|
+
return normalizeSpokenText(parsed.spoken) ?? "";
|
|
48
|
+
} catch {}
|
|
49
|
+
const inlineSpokenMatch = trimmed.match(/"spoken"\s*:\s*"((?:[^"\\]|\\.)*)"/i);
|
|
50
|
+
if (!inlineSpokenMatch) return null;
|
|
51
|
+
try {
|
|
52
|
+
return normalizeSpokenText(JSON.parse(`"${inlineSpokenMatch[1] ?? ""}"`)) ?? "";
|
|
53
|
+
} catch {
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
function isLikelyMetaReasoningParagraph(paragraph) {
|
|
58
|
+
const lower = normalizeLowercaseStringOrEmpty(paragraph);
|
|
59
|
+
if (!lower) return false;
|
|
60
|
+
if (lower.startsWith("thinking process")) return true;
|
|
61
|
+
if (lower.startsWith("reasoning:") || lower.startsWith("analysis:")) return true;
|
|
62
|
+
if (lower.startsWith("the user ") && (lower.includes("i should") || lower.includes("i need to") || lower.includes("i will"))) return true;
|
|
63
|
+
if (lower.includes("this is a natural continuation of the conversation") || lower.includes("keep the conversation flowing")) return true;
|
|
64
|
+
return false;
|
|
65
|
+
}
|
|
66
|
+
function sanitizePlainSpokenText(text) {
|
|
67
|
+
const withoutCodeFences = text.replace(/```[\s\S]*?```/g, " ").trim();
|
|
68
|
+
if (!withoutCodeFences) return null;
|
|
69
|
+
const paragraphs = normalizeStringEntries(withoutCodeFences.split(/\n\s*\n+/));
|
|
70
|
+
while (paragraphs.length > 1 && isLikelyMetaReasoningParagraph(paragraphs[0])) paragraphs.shift();
|
|
71
|
+
return normalizeSpokenText(paragraphs.join(" "));
|
|
72
|
+
}
|
|
73
|
+
function extractSpokenTextFromPayloads(payloads) {
|
|
74
|
+
const spokenSegments = [];
|
|
75
|
+
for (const payload of payloads) {
|
|
76
|
+
if (payload.isError || payload.isReasoning) continue;
|
|
77
|
+
const rawText = payload.text?.trim() ?? "";
|
|
78
|
+
if (!rawText) continue;
|
|
79
|
+
const structured = tryParseSpokenJson(rawText);
|
|
80
|
+
if (structured !== null) {
|
|
81
|
+
if (structured.length > 0) spokenSegments.push(structured);
|
|
82
|
+
continue;
|
|
83
|
+
}
|
|
84
|
+
const plain = sanitizePlainSpokenText(rawText);
|
|
85
|
+
if (plain) spokenSegments.push(plain);
|
|
86
|
+
}
|
|
87
|
+
return spokenSegments.length > 0 ? spokenSegments.join(" ").trim() : null;
|
|
88
|
+
}
|
|
89
|
+
async function deliverEarlyText(callback, text) {
|
|
90
|
+
try {
|
|
91
|
+
return await callback(text);
|
|
92
|
+
} catch (error) {
|
|
93
|
+
console.error("[voice-call] Early TTS delivery failed:", error);
|
|
94
|
+
return false;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
function resolveVoiceSandboxSessionKey(agentId, sessionKey) {
|
|
98
|
+
const trimmed = sessionKey.trim();
|
|
99
|
+
if (trimmed.toLowerCase().startsWith("agent:")) return trimmed;
|
|
100
|
+
return `agent:${agentId}:${trimmed}`;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Generate a voice response using the embedded OpenClaw agent with full tool support.
|
|
104
|
+
* Uses the same agent infrastructure as messaging for consistent behavior.
|
|
105
|
+
*/
|
|
106
|
+
async function generateVoiceResponse(params) {
|
|
107
|
+
const { voiceConfig, callId, sessionKey, from, transcript, userMessage, coreConfig, agentRuntime, onEarlyText } = params;
|
|
108
|
+
if (!coreConfig) return {
|
|
109
|
+
text: null,
|
|
110
|
+
deliveredEarly: false,
|
|
111
|
+
error: "Core config unavailable for voice response"
|
|
112
|
+
};
|
|
113
|
+
const cfg = coreConfig;
|
|
114
|
+
const agentId = resolveCallAgentId({ agentId: params.agentId }, voiceConfig);
|
|
115
|
+
const resolvedSessionKey = resolveVoiceCallSessionKey({
|
|
116
|
+
config: {
|
|
117
|
+
...voiceConfig,
|
|
118
|
+
agentId
|
|
119
|
+
},
|
|
120
|
+
callId,
|
|
121
|
+
phone: from,
|
|
122
|
+
explicitSessionKey: sessionKey,
|
|
123
|
+
coreSession: coreConfig.session
|
|
124
|
+
});
|
|
125
|
+
const toolsAllow = resolveVoiceAgentToolsAllow(cfg, agentId);
|
|
126
|
+
const storePath = agentRuntime.session.resolveStorePath(cfg.session?.store, { agentId });
|
|
127
|
+
try {
|
|
128
|
+
return await agentRuntime.session.runWithWorkAdmission({
|
|
129
|
+
storePath,
|
|
130
|
+
sessionKey: resolvedSessionKey
|
|
131
|
+
}, async (abortSignal) => {
|
|
132
|
+
const agentDir = agentRuntime.resolveAgentDir(cfg, agentId);
|
|
133
|
+
const workspaceDir = agentRuntime.resolveAgentWorkspaceDir(cfg, agentId);
|
|
134
|
+
await agentRuntime.ensureAgentWorkspace({ dir: workspaceDir });
|
|
135
|
+
const now = Date.now();
|
|
136
|
+
const existingSessionEntry = agentRuntime.session.getSessionEntry({
|
|
137
|
+
storePath,
|
|
138
|
+
sessionKey: resolvedSessionKey
|
|
139
|
+
});
|
|
140
|
+
const { provider, model } = resolveVoiceResponseModel({
|
|
141
|
+
voiceConfig,
|
|
142
|
+
agentRuntime
|
|
143
|
+
});
|
|
144
|
+
let sessionEntry = existingSessionEntry;
|
|
145
|
+
if (!sessionEntry?.sessionId || voiceConfig.responseModel) sessionEntry = await agentRuntime.session.patchSessionEntry({
|
|
146
|
+
storePath,
|
|
147
|
+
sessionKey: resolvedSessionKey,
|
|
148
|
+
replaceEntry: true,
|
|
149
|
+
fallbackEntry: sessionEntry ?? {
|
|
150
|
+
sessionId: crypto.randomUUID(),
|
|
151
|
+
updatedAt: now
|
|
152
|
+
},
|
|
153
|
+
update: (entry) => {
|
|
154
|
+
const next = entry.sessionId ? { ...entry } : {
|
|
155
|
+
...entry,
|
|
156
|
+
sessionId: crypto.randomUUID(),
|
|
157
|
+
updatedAt: now
|
|
158
|
+
};
|
|
159
|
+
if (voiceConfig.responseModel) applyModelOverrideToSessionEntry({
|
|
160
|
+
entry: next,
|
|
161
|
+
selection: {
|
|
162
|
+
provider,
|
|
163
|
+
model
|
|
164
|
+
},
|
|
165
|
+
selectionSource: "auto"
|
|
166
|
+
});
|
|
167
|
+
return next;
|
|
168
|
+
}
|
|
169
|
+
}) ?? void 0;
|
|
170
|
+
if (!sessionEntry?.sessionId) return {
|
|
171
|
+
text: null,
|
|
172
|
+
deliveredEarly: false,
|
|
173
|
+
error: "Voice response session could not be initialized"
|
|
174
|
+
};
|
|
175
|
+
const sessionId = sessionEntry.sessionId;
|
|
176
|
+
const thinkLevel = agentRuntime.resolveThinkingDefault({
|
|
177
|
+
cfg,
|
|
178
|
+
provider,
|
|
179
|
+
model
|
|
180
|
+
});
|
|
181
|
+
const agentName = agentRuntime.resolveAgentIdentity(cfg, agentId)?.name?.trim() || "assistant";
|
|
182
|
+
const basePrompt = voiceConfig.responseSystemPrompt ?? `You are ${agentName}, a helpful voice assistant on a phone call. Keep responses brief and conversational (1-2 sentences max). Be natural and friendly. The caller's phone number is ${from}. You have access to tools - use them when helpful.`;
|
|
183
|
+
let extraSystemPrompt = basePrompt;
|
|
184
|
+
if (transcript.length > 0) extraSystemPrompt = `${basePrompt}\n\nConversation so far:\n${transcript.map((entry) => `${entry.speaker === "bot" ? "You" : "Caller"}: ${entry.text}`).join("\n")}`;
|
|
185
|
+
extraSystemPrompt = `${extraSystemPrompt}\n\n${VOICE_SPOKEN_OUTPUT_CONTRACT}`;
|
|
186
|
+
const timeoutMs = voiceConfig.responseTimeoutMs ?? agentRuntime.resolveAgentTimeoutMs({ cfg });
|
|
187
|
+
const runId = `voice:${callId}:${Date.now()}`;
|
|
188
|
+
const blockReplyPayloads = [];
|
|
189
|
+
let latestToolBoundaryMessageIndex;
|
|
190
|
+
let blockReplyBoundariesReliable = true;
|
|
191
|
+
let deliveredEarly = false;
|
|
192
|
+
let lastFlushedText = null;
|
|
193
|
+
const result = await agentRuntime.runEmbeddedAgent({
|
|
194
|
+
sessionId,
|
|
195
|
+
sessionKey: resolvedSessionKey,
|
|
196
|
+
sessionTarget: {
|
|
197
|
+
agentId,
|
|
198
|
+
sessionId,
|
|
199
|
+
sessionKey: resolvedSessionKey,
|
|
200
|
+
storePath
|
|
201
|
+
},
|
|
202
|
+
sandboxSessionKey: resolveVoiceSandboxSessionKey(agentId, resolvedSessionKey),
|
|
203
|
+
agentId,
|
|
204
|
+
messageProvider: "voice",
|
|
205
|
+
workspaceDir,
|
|
206
|
+
config: cfg,
|
|
207
|
+
prompt: userMessage,
|
|
208
|
+
provider,
|
|
209
|
+
model,
|
|
210
|
+
thinkLevel,
|
|
211
|
+
verboseLevel: "off",
|
|
212
|
+
timeoutMs,
|
|
213
|
+
runId,
|
|
214
|
+
lane: "voice",
|
|
215
|
+
extraSystemPrompt,
|
|
216
|
+
agentDir,
|
|
217
|
+
toolsAllow,
|
|
218
|
+
abortSignal,
|
|
219
|
+
blockReplyBreak: "text_end",
|
|
220
|
+
onBlockReply: (payload, context) => {
|
|
221
|
+
if (latestToolBoundaryMessageIndex !== void 0) {
|
|
222
|
+
const messageIndex = context?.assistantMessageIndex;
|
|
223
|
+
if (messageIndex === void 0) {
|
|
224
|
+
blockReplyBoundariesReliable = false;
|
|
225
|
+
return;
|
|
226
|
+
}
|
|
227
|
+
if (messageIndex <= latestToolBoundaryMessageIndex) return;
|
|
228
|
+
}
|
|
229
|
+
blockReplyPayloads.push(payload);
|
|
230
|
+
},
|
|
231
|
+
onBlockReplyFlush: async (context) => {
|
|
232
|
+
if (context.reason === "tool_start") {
|
|
233
|
+
blockReplyPayloads.length = 0;
|
|
234
|
+
latestToolBoundaryMessageIndex = context.assistantMessageIndex;
|
|
235
|
+
blockReplyBoundariesReliable = true;
|
|
236
|
+
return;
|
|
237
|
+
}
|
|
238
|
+
if (context.reason !== "pre_compaction") return;
|
|
239
|
+
const pendingPayloads = blockReplyPayloads.splice(0);
|
|
240
|
+
const boundariesReliable = blockReplyBoundariesReliable;
|
|
241
|
+
latestToolBoundaryMessageIndex = void 0;
|
|
242
|
+
blockReplyBoundariesReliable = true;
|
|
243
|
+
if (!context.attemptAccepted) return;
|
|
244
|
+
if (deliveredEarly || !onEarlyText || !boundariesReliable) return;
|
|
245
|
+
const text = extractSpokenTextFromPayloads(pendingPayloads);
|
|
246
|
+
if (!text) return;
|
|
247
|
+
lastFlushedText = text;
|
|
248
|
+
deliveredEarly = await deliverEarlyText(onEarlyText, text);
|
|
249
|
+
}
|
|
250
|
+
});
|
|
251
|
+
const text = extractSpokenTextFromPayloads(result.payloads ?? []) ?? lastFlushedText ?? extractSpokenTextFromPayloads(blockReplyPayloads);
|
|
252
|
+
if (!text && result.meta?.aborted) return {
|
|
253
|
+
text: null,
|
|
254
|
+
deliveredEarly: false,
|
|
255
|
+
error: "Response generation was aborted"
|
|
256
|
+
};
|
|
257
|
+
return {
|
|
258
|
+
text,
|
|
259
|
+
deliveredEarly
|
|
260
|
+
};
|
|
261
|
+
});
|
|
262
|
+
} catch (err) {
|
|
263
|
+
console.error(`[voice-call] Response generation failed:`, err);
|
|
264
|
+
return {
|
|
265
|
+
text: null,
|
|
266
|
+
deliveredEarly: false,
|
|
267
|
+
error: String(err)
|
|
268
|
+
};
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
//#endregion
|
|
272
|
+
export { generateVoiceResponse };
|