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