@openclaw/discord 2026.9.5 → 2026.9.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/.setup/{activities-api-DBwRt5ES.mjs → activities-api-COU4-0nR.mjs} +4 -4
- package/dist/.setup/{approval-handler.runtime-Du3n5ypX.mjs → approval-handler.runtime-CbBktBb4.mjs} +5 -5
- package/dist/.setup/{approval-message-updates-BN7JtScm.mjs → approval-message-updates-jf9zMaIC.mjs} +1 -1
- package/dist/.setup/{audit-C8uaKoa9.mjs → audit-vKbh-LFR.mjs} +3 -3
- package/dist/.setup/{channel-ChKdlBgH.mjs → channel-Dv4e3Jpc.mjs} +19 -16
- package/dist/.setup/{channel-actions.runtime-CJmiFfps.mjs → channel-actions.runtime-leZuw01r.mjs} +13 -7
- package/dist/.setup/{channel.setup-BlC3-Kzz.mjs → channel.setup-0NX6FFwi.mjs} +1 -1
- package/dist/.setup/{components-MqMWUWnE.mjs → components-yBEb75bB.mjs} +1 -2
- package/dist/.setup/{conversation-binding-route-_rz33QHO.mjs → conversation-binding-route-B7qImK_b.mjs} +6 -3
- package/dist/.setup/{doctor-DxcdkXzz.mjs → doctor-D1R-uFIu.mjs} +2 -2
- package/dist/.setup/{handle-action.guild-admin-DAFyh_yV.mjs → handle-action.guild-admin-DcFa8NwA.mjs} +3 -3
- package/dist/.setup/{message-handler-DnUrDpaU.mjs → message-handler-X6ejmbtY.mjs} +6 -5
- package/dist/.setup/{message-handler.preflight-CtqaF_fb.mjs → message-handler.preflight-DE_POxFc.mjs} +14 -117
- package/dist/.setup/message-handler.preflight-pluralkit-8Xji34AF.mjs +143 -0
- package/dist/.setup/{message-handler.process-Dz1xvuQU.mjs → message-handler.process-CCmIVnxy.mjs} +387 -317
- package/dist/.setup/{outbound-adapter-C8v79z9Z.mjs → outbound-adapter-ClIgmu4F.mjs} +5 -5
- package/dist/.setup/{outbound-session-route-CqWbuMOm.mjs → outbound-session-route-VulUE0yV.mjs} +7 -6
- package/dist/.setup/{preflight-audio-DrnqFA8U.mjs → preflight-audio-DHGIHEpv.mjs} +2 -1
- package/dist/.setup/{provider-72zIvN-i.mjs → provider-iOf73HW-.mjs} +425 -286
- package/dist/.setup/{provider-session.runtime-BW7QrF5C.mjs → provider-session.runtime-DrGAYnZv.mjs} +3 -3
- package/dist/.setup/provider.runtime-BmjW_pIw.mjs +2 -0
- package/dist/.setup/{realtime-session.runtime-DTccTgTM.mjs → realtime-session.runtime-Dz8uVutq.mjs} +338 -297
- package/dist/.setup/receive-recovery-DHst8WRx.mjs +517 -0
- package/dist/.setup/{retry-DBfcEgmO.mjs → retry-BEYkDy0P.mjs} +78 -13
- package/dist/.setup/{runtime-SchNfUsQ.mjs → runtime-B8lJfyrA.mjs} +30 -11
- package/dist/.setup/{runtime-BVoa7hhx.mjs → runtime-DisDbixd.mjs} +1 -1
- package/dist/.setup/{send-CKDczUNL.mjs → send-CIBzvXjS.mjs} +23 -9
- package/dist/.setup/{send.components-DWQjXhPV.mjs → send.components-ChY21qr-.mjs} +4 -4
- package/dist/.setup/{send.outbound-D0hQ7s50.mjs → send.outbound-QTyuFupn.mjs} +15 -16
- package/dist/.setup/{send.shared-Zwx6BxQ5.mjs → send.shared-VNvWfX2T.mjs} +2 -2
- package/dist/.setup/setup-plugin-api-Dvr41dyx.mjs +3 -0
- package/dist/.setup/{shared-CaA3Vv4n.mjs → shared-DHPDaMSx.mjs} +1 -1
- package/dist/.setup/{subagent-hooks-Bired9q6.mjs → subagent-hooks-CjW7r8Pe.mjs} +1 -1
- package/dist/.setup/{target-resolver-B6MrxbYv.mjs → target-resolver-BXpy6VT8.mjs} +1 -1
- package/dist/.setup/targets-CvemhN3i.mjs +3 -0
- package/dist/.setup/{thread-bindings-CK5272V3.mjs → thread-bindings-CEh2dhqP.mjs} +3 -3
- package/dist/.setup/{thread-bindings.manager-eexkKyrG.mjs → thread-bindings.manager-ve-i6oqt.mjs} +94 -45
- package/dist/.setup/{transcripts-source-CuWYgayu.mjs → transcripts-source-DVegW0WI.mjs} +61 -7
- package/dist/.setup/{voice-runtime-DHVQ2mFz.mjs → voice-runtime-elTtjEIG.mjs} +553 -901
- package/dist/action-runtime-api.js +1 -1
- package/dist/activities-api.js +1 -1
- package/dist/api.js +10 -10
- package/dist/channel-plugin-api.js +1 -1
- package/dist/index.js +1 -1
- package/dist/runtime-api.js +12 -12
- package/dist/setup-entry.js +1 -1
- package/dist/setup-plugin-api.js +1 -1
- package/dist/src/voice/audio-worker.runtime.js +1065 -0
- package/dist/subagent-hooks-api.js +1 -1
- package/dist/transcripts-source-api.js +1 -1
- package/node_modules/@napi-rs/wasm-runtime/dist/emnapi-plugins.cjs +8 -4
- package/node_modules/@napi-rs/wasm-runtime/dist/emnapi-plugins.js +8 -4
- package/node_modules/@napi-rs/wasm-runtime/dist/fs-proxy.cjs +1 -1
- package/node_modules/@napi-rs/wasm-runtime/dist/fs.js +770 -695
- package/node_modules/@napi-rs/wasm-runtime/fs-proxy.js +3 -2
- package/node_modules/@napi-rs/wasm-runtime/package.json +1 -1
- package/node_modules/@tybys/wasm-util/LICENSE +21 -0
- package/node_modules/@tybys/wasm-util/package.json +1 -1
- package/node_modules/@types/node/README.md +1 -1
- package/node_modules/@types/node/package.json +2 -2
- package/node_modules/@types/node/web-globals/streams.d.ts +4 -0
- package/node_modules/zod/README.md +2 -2
- package/node_modules/zod/compile.cjs +19 -0
- package/node_modules/zod/index.cjs +19 -0
- package/node_modules/zod/locales/index.cjs +19 -0
- package/node_modules/zod/mini/index.cjs +19 -0
- package/node_modules/zod/package.json +8 -7
- package/node_modules/zod/src/v3/helpers/errorUtil.ts +1 -1
- package/node_modules/zod/src/v4/classic/external.ts +2 -0
- package/node_modules/zod/src/v4/classic/from-json-schema.ts +248 -25
- package/node_modules/zod/src/v4/classic/schemas.ts +243 -168
- package/node_modules/zod/src/v4/classic/tests/assignability.test.ts +60 -9
- package/node_modules/zod/src/v4/classic/tests/bigint.test.ts +6 -0
- package/node_modules/zod/src/v4/classic/tests/continuability.test.ts +2 -2
- package/node_modules/zod/src/v4/classic/tests/cyclic-data.test.ts +265 -0
- package/node_modules/zod/src/v4/classic/tests/discriminated-unions.test.ts +112 -6
- package/node_modules/zod/src/v4/classic/tests/enum.test.ts +9 -0
- package/node_modules/zod/src/v4/classic/tests/error.test.ts +130 -1
- package/node_modules/zod/src/v4/classic/tests/from-json-schema.test.ts +157 -0
- package/node_modules/zod/src/v4/classic/tests/iban.test.ts +81 -0
- package/node_modules/zod/src/v4/classic/tests/instance-footprint.test.ts +40 -2
- package/node_modules/zod/src/v4/classic/tests/instanceof.test.ts +27 -7
- package/node_modules/zod/src/v4/classic/tests/issue-schema.test.ts +88 -56
- package/node_modules/zod/src/v4/classic/tests/number.test.ts +39 -0
- package/node_modules/zod/src/v4/classic/tests/object.test.ts +56 -0
- package/node_modules/zod/src/v4/classic/tests/optin-ladder.test.ts +3 -2
- package/node_modules/zod/src/v4/classic/tests/prefault.test.ts +70 -0
- package/node_modules/zod/src/v4/classic/tests/properties.test.ts +141 -0
- package/node_modules/zod/src/v4/classic/tests/recursive-types.test.ts +46 -1
- package/node_modules/zod/src/v4/classic/tests/standard-schema.test.ts +19 -0
- package/node_modules/zod/src/v4/classic/tests/string.test.ts +95 -1
- package/node_modules/zod/src/v4/classic/tests/template-literal.test.ts +33 -1
- package/node_modules/zod/src/v4/classic/tests/to-json-schema.test.ts +234 -38
- package/node_modules/zod/src/v4/classic/tests/validate.test.ts +569 -0
- package/node_modules/zod/src/v4/core/api.ts +44 -28
- package/node_modules/zod/src/v4/core/checks.ts +62 -102
- package/node_modules/zod/src/v4/core/compile.ts +218 -93
- package/node_modules/zod/src/v4/core/core.ts +1 -3
- package/node_modules/zod/src/v4/core/doc.ts +6 -2
- package/node_modules/zod/src/v4/core/errors.ts +3 -6
- package/node_modules/zod/src/v4/core/json-schema-generator.ts +2 -2
- package/node_modules/zod/src/v4/core/json-schema-processors.ts +185 -81
- package/node_modules/zod/src/v4/core/memoizer.ts +75 -28
- package/node_modules/zod/src/v4/core/parse.ts +37 -16
- package/node_modules/zod/src/v4/core/regexes.ts +14 -4
- package/node_modules/zod/src/v4/core/schemas.ts +296 -132
- package/node_modules/zod/src/v4/core/tests/cached.test.ts +54 -0
- package/node_modules/zod/src/v4/core/tests/compile-differential.test.ts +35 -0
- package/node_modules/zod/src/v4/core/tests/compile-generative.test.ts +445 -0
- package/node_modules/zod/src/v4/core/tests/compile.test.ts +399 -2
- package/node_modules/zod/src/v4/core/tests/email-regex.test.ts +140 -0
- package/node_modules/zod/src/v4/core/tests/locales/tg.test.ts +85 -0
- package/node_modules/zod/src/v4/core/tests/polyfill-collision.test.ts +46 -0
- package/node_modules/zod/src/v4/core/tests/url-no-canparse.test.ts +118 -16
- package/node_modules/zod/src/v4/core/to-json-schema.ts +9 -7
- package/node_modules/zod/src/v4/core/util.ts +218 -147
- package/node_modules/zod/src/v4/core/versions.ts +2 -2
- package/node_modules/zod/src/v4/locales/ar.ts +2 -0
- package/node_modules/zod/src/v4/locales/az.ts +2 -0
- package/node_modules/zod/src/v4/locales/be.ts +2 -0
- package/node_modules/zod/src/v4/locales/bg.ts +2 -0
- package/node_modules/zod/src/v4/locales/bn.ts +2 -0
- package/node_modules/zod/src/v4/locales/ca.ts +2 -0
- package/node_modules/zod/src/v4/locales/ckb.ts +2 -0
- package/node_modules/zod/src/v4/locales/cs.ts +2 -0
- package/node_modules/zod/src/v4/locales/da.ts +2 -0
- package/node_modules/zod/src/v4/locales/de.ts +2 -0
- package/node_modules/zod/src/v4/locales/el.ts +2 -0
- package/node_modules/zod/src/v4/locales/en.ts +2 -0
- package/node_modules/zod/src/v4/locales/eo.ts +2 -0
- package/node_modules/zod/src/v4/locales/es.ts +2 -0
- package/node_modules/zod/src/v4/locales/fa.ts +2 -0
- package/node_modules/zod/src/v4/locales/fi.ts +2 -0
- package/node_modules/zod/src/v4/locales/fr-CA.ts +2 -0
- package/node_modules/zod/src/v4/locales/fr.ts +2 -0
- package/node_modules/zod/src/v4/locales/gu.ts +2 -0
- package/node_modules/zod/src/v4/locales/he.ts +2 -0
- package/node_modules/zod/src/v4/locales/hi.ts +2 -0
- package/node_modules/zod/src/v4/locales/hr.ts +2 -0
- package/node_modules/zod/src/v4/locales/hu.ts +2 -0
- package/node_modules/zod/src/v4/locales/hy.ts +2 -0
- package/node_modules/zod/src/v4/locales/id.ts +2 -0
- package/node_modules/zod/src/v4/locales/index.ts +1 -0
- package/node_modules/zod/src/v4/locales/is.ts +2 -0
- package/node_modules/zod/src/v4/locales/it.ts +2 -0
- package/node_modules/zod/src/v4/locales/ja.ts +2 -0
- package/node_modules/zod/src/v4/locales/ka.ts +2 -0
- package/node_modules/zod/src/v4/locales/km.ts +2 -0
- package/node_modules/zod/src/v4/locales/kn.ts +2 -0
- package/node_modules/zod/src/v4/locales/ko.ts +2 -0
- package/node_modules/zod/src/v4/locales/lt.ts +2 -0
- package/node_modules/zod/src/v4/locales/mk.ts +2 -0
- package/node_modules/zod/src/v4/locales/ms.ts +2 -0
- package/node_modules/zod/src/v4/locales/ne.ts +2 -0
- package/node_modules/zod/src/v4/locales/nl.ts +2 -0
- package/node_modules/zod/src/v4/locales/nn.ts +2 -0
- package/node_modules/zod/src/v4/locales/no.ts +2 -0
- package/node_modules/zod/src/v4/locales/ota.ts +2 -0
- package/node_modules/zod/src/v4/locales/pl.ts +2 -0
- package/node_modules/zod/src/v4/locales/ps.ts +2 -0
- package/node_modules/zod/src/v4/locales/pt-BR.ts +2 -0
- package/node_modules/zod/src/v4/locales/pt.ts +2 -0
- package/node_modules/zod/src/v4/locales/ro.ts +2 -0
- package/node_modules/zod/src/v4/locales/ru.ts +2 -0
- package/node_modules/zod/src/v4/locales/sk.ts +2 -0
- package/node_modules/zod/src/v4/locales/sl.ts +2 -0
- package/node_modules/zod/src/v4/locales/sv.ts +2 -0
- package/node_modules/zod/src/v4/locales/ta.ts +2 -0
- package/node_modules/zod/src/v4/locales/tg.ts +135 -0
- package/node_modules/zod/src/v4/locales/th.ts +2 -0
- package/node_modules/zod/src/v4/locales/tk.ts +2 -0
- package/node_modules/zod/src/v4/locales/tr.ts +2 -0
- package/node_modules/zod/src/v4/locales/uk.ts +2 -0
- package/node_modules/zod/src/v4/locales/ur.ts +2 -0
- package/node_modules/zod/src/v4/locales/uz.ts +2 -0
- package/node_modules/zod/src/v4/locales/vi.ts +2 -0
- package/node_modules/zod/src/v4/locales/yo.ts +2 -0
- package/node_modules/zod/src/v4/locales/zh-CN.ts +2 -0
- package/node_modules/zod/src/v4/locales/zh-TW.ts +2 -0
- package/node_modules/zod/src/v4/mini/external.ts +2 -0
- package/node_modules/zod/src/v4/mini/schemas.ts +32 -7
- package/node_modules/zod/src/v4/mini/tests/checks.test.ts +1 -1
- package/node_modules/zod/src/v4/mini/tests/computed.test.ts +11 -17
- package/node_modules/zod/src/v4/mini/tests/index.test.ts +86 -0
- package/node_modules/zod/src/v4/mini/tests/recursive-types.test.ts +16 -0
- package/node_modules/zod/src/v4/mini/tests/string.test.ts +23 -0
- package/node_modules/zod/v3/ZodError.cjs +19 -0
- package/node_modules/zod/v3/errors.cjs +19 -0
- package/node_modules/zod/v3/external.cjs +19 -0
- package/node_modules/zod/v3/helpers/enumUtil.cjs +19 -0
- package/node_modules/zod/v3/helpers/errorUtil.cjs +20 -1
- package/node_modules/zod/v3/helpers/errorUtil.js +1 -1
- package/node_modules/zod/v3/helpers/parseUtil.cjs +19 -0
- package/node_modules/zod/v3/helpers/partialUtil.cjs +19 -0
- package/node_modules/zod/v3/helpers/typeAliases.cjs +19 -0
- package/node_modules/zod/v3/helpers/util.cjs +19 -0
- package/node_modules/zod/v3/index.cjs +19 -0
- package/node_modules/zod/v3/standard-schema.cjs +19 -0
- package/node_modules/zod/v3/types.cjs +19 -0
- package/node_modules/zod/v4/classic/checks.cjs +19 -0
- package/node_modules/zod/v4/classic/coerce.cjs +19 -0
- package/node_modules/zod/v4/classic/compat.cjs +19 -0
- package/node_modules/zod/v4/classic/deep-partial.cjs +19 -0
- package/node_modules/zod/v4/classic/errors.cjs +19 -0
- package/node_modules/zod/v4/classic/external.cjs +22 -1
- package/node_modules/zod/v4/classic/external.d.cts +1 -1
- package/node_modules/zod/v4/classic/external.d.ts +1 -1
- package/node_modules/zod/v4/classic/external.js +1 -1
- package/node_modules/zod/v4/classic/from-json-schema.cjs +264 -24
- package/node_modules/zod/v4/classic/from-json-schema.js +245 -24
- package/node_modules/zod/v4/classic/in-out.cjs +19 -0
- package/node_modules/zod/v4/classic/index.cjs +19 -0
- package/node_modules/zod/v4/classic/iso.cjs +19 -0
- package/node_modules/zod/v4/classic/parse.cjs +19 -0
- package/node_modules/zod/v4/classic/schemas.cjs +100 -35
- package/node_modules/zod/v4/classic/schemas.d.cts +15 -1
- package/node_modules/zod/v4/classic/schemas.d.ts +15 -1
- package/node_modules/zod/v4/classic/schemas.js +77 -33
- package/node_modules/zod/v4/core/api.cjs +45 -22
- package/node_modules/zod/v4/core/api.d.cts +12 -6
- package/node_modules/zod/v4/core/api.d.ts +12 -6
- package/node_modules/zod/v4/core/api.js +25 -22
- package/node_modules/zod/v4/core/checks.cjs +51 -97
- package/node_modules/zod/v4/core/checks.d.cts +17 -1
- package/node_modules/zod/v4/core/checks.d.ts +17 -1
- package/node_modules/zod/v4/core/checks.js +31 -96
- package/node_modules/zod/v4/core/compile.cjs +173 -78
- package/node_modules/zod/v4/core/compile.d.cts +18 -4
- package/node_modules/zod/v4/core/compile.d.ts +18 -4
- package/node_modules/zod/v4/core/compile.js +154 -79
- package/node_modules/zod/v4/core/core.cjs +20 -1
- package/node_modules/zod/v4/core/core.js +1 -1
- package/node_modules/zod/v4/core/doc.cjs +26 -2
- package/node_modules/zod/v4/core/doc.js +7 -2
- package/node_modules/zod/v4/core/errors.cjs +21 -5
- package/node_modules/zod/v4/core/errors.js +2 -5
- package/node_modules/zod/v4/core/index.cjs +19 -0
- package/node_modules/zod/v4/core/json-schema-generator.cjs +20 -1
- package/node_modules/zod/v4/core/json-schema-generator.js +2 -2
- package/node_modules/zod/v4/core/json-schema-processors.cjs +188 -72
- package/node_modules/zod/v4/core/json-schema-processors.d.cts +16 -0
- package/node_modules/zod/v4/core/json-schema-processors.d.ts +16 -0
- package/node_modules/zod/v4/core/json-schema-processors.js +170 -74
- package/node_modules/zod/v4/core/json-schema.cjs +19 -0
- package/node_modules/zod/v4/core/memoizer.cjs +111 -23
- package/node_modules/zod/v4/core/memoizer.js +69 -23
- package/node_modules/zod/v4/core/parse.cjs +56 -16
- package/node_modules/zod/v4/core/parse.js +37 -16
- package/node_modules/zod/v4/core/regexes.cjs +31 -6
- package/node_modules/zod/v4/core/regexes.d.cts +3 -0
- package/node_modules/zod/v4/core/regexes.d.ts +3 -0
- package/node_modules/zod/v4/core/regexes.js +10 -4
- package/node_modules/zod/v4/core/registries.cjs +19 -0
- package/node_modules/zod/v4/core/schemas.cjs +302 -114
- package/node_modules/zod/v4/core/schemas.d.cts +28 -8
- package/node_modules/zod/v4/core/schemas.d.ts +28 -8
- package/node_modules/zod/v4/core/schemas.js +279 -113
- package/node_modules/zod/v4/core/standard-schema.cjs +19 -0
- package/node_modules/zod/v4/core/to-json-schema.cjs +28 -7
- package/node_modules/zod/v4/core/to-json-schema.d.cts +4 -3
- package/node_modules/zod/v4/core/to-json-schema.d.ts +4 -3
- package/node_modules/zod/v4/core/to-json-schema.js +7 -6
- package/node_modules/zod/v4/core/util.cjs +177 -143
- package/node_modules/zod/v4/core/util.d.cts +25 -4
- package/node_modules/zod/v4/core/util.d.ts +25 -4
- package/node_modules/zod/v4/core/util.js +156 -143
- package/node_modules/zod/v4/core/versions.cjs +21 -2
- package/node_modules/zod/v4/core/versions.d.cts +1 -1
- package/node_modules/zod/v4/core/versions.d.ts +1 -1
- package/node_modules/zod/v4/core/versions.js +2 -2
- package/node_modules/zod/v4/core/visit.cjs +19 -0
- package/node_modules/zod/v4/index.cjs +19 -0
- package/node_modules/zod/v4/locales/ar.cjs +2 -0
- package/node_modules/zod/v4/locales/ar.js +2 -0
- package/node_modules/zod/v4/locales/az.cjs +2 -0
- package/node_modules/zod/v4/locales/az.js +2 -0
- package/node_modules/zod/v4/locales/be.cjs +2 -0
- package/node_modules/zod/v4/locales/be.js +2 -0
- package/node_modules/zod/v4/locales/bg.cjs +2 -0
- package/node_modules/zod/v4/locales/bg.js +2 -0
- package/node_modules/zod/v4/locales/bn.cjs +2 -0
- package/node_modules/zod/v4/locales/bn.js +2 -0
- package/node_modules/zod/v4/locales/ca.cjs +2 -0
- package/node_modules/zod/v4/locales/ca.js +2 -0
- package/node_modules/zod/v4/locales/ckb.cjs +2 -0
- package/node_modules/zod/v4/locales/ckb.js +2 -0
- package/node_modules/zod/v4/locales/cs.cjs +2 -0
- package/node_modules/zod/v4/locales/cs.js +2 -0
- package/node_modules/zod/v4/locales/da.cjs +2 -0
- package/node_modules/zod/v4/locales/da.js +2 -0
- package/node_modules/zod/v4/locales/de.cjs +2 -0
- package/node_modules/zod/v4/locales/de.js +2 -0
- package/node_modules/zod/v4/locales/el.cjs +2 -0
- package/node_modules/zod/v4/locales/el.js +2 -0
- package/node_modules/zod/v4/locales/en.cjs +2 -0
- package/node_modules/zod/v4/locales/en.js +2 -0
- package/node_modules/zod/v4/locales/eo.cjs +2 -0
- package/node_modules/zod/v4/locales/eo.js +2 -0
- package/node_modules/zod/v4/locales/es.cjs +2 -0
- package/node_modules/zod/v4/locales/es.js +2 -0
- package/node_modules/zod/v4/locales/fa.cjs +2 -0
- package/node_modules/zod/v4/locales/fa.js +2 -0
- package/node_modules/zod/v4/locales/fi.cjs +2 -0
- package/node_modules/zod/v4/locales/fi.js +2 -0
- package/node_modules/zod/v4/locales/fr-CA.cjs +2 -0
- package/node_modules/zod/v4/locales/fr-CA.js +2 -0
- package/node_modules/zod/v4/locales/fr.cjs +2 -0
- package/node_modules/zod/v4/locales/fr.js +2 -0
- package/node_modules/zod/v4/locales/gu.cjs +2 -0
- package/node_modules/zod/v4/locales/gu.js +2 -0
- package/node_modules/zod/v4/locales/he.cjs +2 -0
- package/node_modules/zod/v4/locales/he.js +2 -0
- package/node_modules/zod/v4/locales/hi.cjs +2 -0
- package/node_modules/zod/v4/locales/hi.js +2 -0
- package/node_modules/zod/v4/locales/hr.cjs +2 -0
- package/node_modules/zod/v4/locales/hr.js +2 -0
- package/node_modules/zod/v4/locales/hu.cjs +2 -0
- package/node_modules/zod/v4/locales/hu.js +2 -0
- package/node_modules/zod/v4/locales/hy.cjs +2 -0
- package/node_modules/zod/v4/locales/hy.js +2 -0
- package/node_modules/zod/v4/locales/id.cjs +2 -0
- package/node_modules/zod/v4/locales/id.js +2 -0
- package/node_modules/zod/v4/locales/index.cjs +22 -1
- package/node_modules/zod/v4/locales/index.d.cts +1 -0
- package/node_modules/zod/v4/locales/index.d.ts +1 -0
- package/node_modules/zod/v4/locales/index.js +1 -0
- package/node_modules/zod/v4/locales/is.cjs +2 -0
- package/node_modules/zod/v4/locales/is.js +2 -0
- package/node_modules/zod/v4/locales/it.cjs +2 -0
- package/node_modules/zod/v4/locales/it.js +2 -0
- package/node_modules/zod/v4/locales/ja.cjs +2 -0
- package/node_modules/zod/v4/locales/ja.js +2 -0
- package/node_modules/zod/v4/locales/ka.cjs +2 -0
- package/node_modules/zod/v4/locales/ka.js +2 -0
- package/node_modules/zod/v4/locales/km.cjs +2 -0
- package/node_modules/zod/v4/locales/km.js +2 -0
- package/node_modules/zod/v4/locales/kn.cjs +2 -0
- package/node_modules/zod/v4/locales/kn.js +2 -0
- package/node_modules/zod/v4/locales/ko.cjs +2 -0
- package/node_modules/zod/v4/locales/ko.js +2 -0
- package/node_modules/zod/v4/locales/lt.cjs +2 -0
- package/node_modules/zod/v4/locales/lt.js +2 -0
- package/node_modules/zod/v4/locales/mk.cjs +2 -0
- package/node_modules/zod/v4/locales/mk.js +2 -0
- package/node_modules/zod/v4/locales/ms.cjs +2 -0
- package/node_modules/zod/v4/locales/ms.js +2 -0
- package/node_modules/zod/v4/locales/ne.cjs +2 -0
- package/node_modules/zod/v4/locales/ne.js +2 -0
- package/node_modules/zod/v4/locales/nl.cjs +2 -0
- package/node_modules/zod/v4/locales/nl.js +2 -0
- package/node_modules/zod/v4/locales/nn.cjs +2 -0
- package/node_modules/zod/v4/locales/nn.js +2 -0
- package/node_modules/zod/v4/locales/no.cjs +2 -0
- package/node_modules/zod/v4/locales/no.js +2 -0
- package/node_modules/zod/v4/locales/ota.cjs +2 -0
- package/node_modules/zod/v4/locales/ota.js +2 -0
- package/node_modules/zod/v4/locales/pl.cjs +2 -0
- package/node_modules/zod/v4/locales/pl.js +2 -0
- package/node_modules/zod/v4/locales/ps.cjs +2 -0
- package/node_modules/zod/v4/locales/ps.js +2 -0
- package/node_modules/zod/v4/locales/pt-BR.cjs +2 -0
- package/node_modules/zod/v4/locales/pt-BR.js +2 -0
- package/node_modules/zod/v4/locales/pt.cjs +2 -0
- package/node_modules/zod/v4/locales/pt.js +2 -0
- package/node_modules/zod/v4/locales/ro.cjs +2 -0
- package/node_modules/zod/v4/locales/ro.js +2 -0
- package/node_modules/zod/v4/locales/ru.cjs +2 -0
- package/node_modules/zod/v4/locales/ru.js +2 -0
- package/node_modules/zod/v4/locales/sk.cjs +2 -0
- package/node_modules/zod/v4/locales/sk.js +2 -0
- package/node_modules/zod/v4/locales/sl.cjs +2 -0
- package/node_modules/zod/v4/locales/sl.js +2 -0
- package/node_modules/zod/v4/locales/sv.cjs +2 -0
- package/node_modules/zod/v4/locales/sv.js +2 -0
- package/node_modules/zod/v4/locales/ta.cjs +2 -0
- package/node_modules/zod/v4/locales/ta.js +2 -0
- package/node_modules/zod/v4/locales/tg.cjs +144 -0
- package/node_modules/zod/v4/locales/tg.d.cts +5 -0
- package/node_modules/zod/v4/locales/tg.d.ts +4 -0
- package/node_modules/zod/v4/locales/tg.js +117 -0
- package/node_modules/zod/v4/locales/th.cjs +2 -0
- package/node_modules/zod/v4/locales/th.js +2 -0
- package/node_modules/zod/v4/locales/tk.cjs +2 -0
- package/node_modules/zod/v4/locales/tk.js +2 -0
- package/node_modules/zod/v4/locales/tr.cjs +2 -0
- package/node_modules/zod/v4/locales/tr.js +2 -0
- package/node_modules/zod/v4/locales/uk.cjs +2 -0
- package/node_modules/zod/v4/locales/uk.js +2 -0
- package/node_modules/zod/v4/locales/ur.cjs +2 -0
- package/node_modules/zod/v4/locales/ur.js +2 -0
- package/node_modules/zod/v4/locales/uz.cjs +2 -0
- package/node_modules/zod/v4/locales/uz.js +2 -0
- package/node_modules/zod/v4/locales/vi.cjs +2 -0
- package/node_modules/zod/v4/locales/vi.js +2 -0
- package/node_modules/zod/v4/locales/yo.cjs +2 -0
- package/node_modules/zod/v4/locales/yo.js +2 -0
- package/node_modules/zod/v4/locales/zh-CN.cjs +2 -0
- package/node_modules/zod/v4/locales/zh-CN.js +2 -0
- package/node_modules/zod/v4/locales/zh-TW.cjs +2 -0
- package/node_modules/zod/v4/locales/zh-TW.js +2 -0
- package/node_modules/zod/v4/mini/checks.cjs +19 -0
- package/node_modules/zod/v4/mini/coerce.cjs +19 -0
- package/node_modules/zod/v4/mini/deep-partial.cjs +19 -0
- package/node_modules/zod/v4/mini/external.cjs +22 -1
- package/node_modules/zod/v4/mini/external.d.cts +1 -1
- package/node_modules/zod/v4/mini/external.d.ts +1 -1
- package/node_modules/zod/v4/mini/external.js +1 -1
- package/node_modules/zod/v4/mini/in-out.cjs +19 -0
- package/node_modules/zod/v4/mini/index.cjs +19 -0
- package/node_modules/zod/v4/mini/iso.cjs +19 -0
- package/node_modules/zod/v4/mini/parse.cjs +19 -0
- package/node_modules/zod/v4/mini/schemas.cjs +44 -8
- package/node_modules/zod/v4/mini/schemas.d.cts +6 -1
- package/node_modules/zod/v4/mini/schemas.d.ts +6 -1
- package/node_modules/zod/v4/mini/schemas.js +21 -6
- package/node_modules/zod/v4-mini/index.cjs +19 -0
- package/package.json +8 -5
- package/dist/.setup/message-handler.history-CJOsN9w5.mjs +0 -28
- package/dist/.setup/provider.runtime-DuhmKdDU.mjs +0 -2
- package/dist/.setup/setup-plugin-api-CINIEBLa.mjs +0 -3
- package/dist/.setup/targets-D1mAB5yO.mjs +0 -3
|
@@ -0,0 +1,517 @@
|
|
|
1
|
+
import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
|
|
2
|
+
import { logVerbose, shouldLogVerbose } from "openclaw/plugin-sdk/runtime-env";
|
|
3
|
+
import { Duplex } from "node:stream";
|
|
4
|
+
import { spawn } from "node:child_process";
|
|
5
|
+
import { StringDecoder } from "node:string_decoder";
|
|
6
|
+
import { Application, OpusError, createDecoder, createEncoder } from "libopus-wasm";
|
|
7
|
+
import { resolveFfmpegBin } from "openclaw/plugin-sdk/media-runtime";
|
|
8
|
+
import { createStreamingPcmResampler } from "openclaw/plugin-sdk/realtime-voice-provider";
|
|
9
|
+
import { resolvePreferredOpenClawTmpDir, tempWorkspace } from "openclaw/plugin-sdk/temp-path";
|
|
10
|
+
//#region extensions/discord/src/voice/audio-worker-protocol.ts
|
|
11
|
+
const DISCORD_AUDIO_OUTPUT_STATUS = 1;
|
|
12
|
+
const DiscordAudioOutputStatus = {
|
|
13
|
+
Buffering: 0n,
|
|
14
|
+
Playing: 1n,
|
|
15
|
+
Retiring: 2n,
|
|
16
|
+
Closed: 3n
|
|
17
|
+
};
|
|
18
|
+
const OUTPUT_STATUS_MASK = 3n;
|
|
19
|
+
const OUTPUT_INPUT_RESERVATION = 4n;
|
|
20
|
+
function getDiscordAudioOutputStatus(clock) {
|
|
21
|
+
return Atomics.load(clock, DISCORD_AUDIO_OUTPUT_STATUS) & OUTPUT_STATUS_MASK;
|
|
22
|
+
}
|
|
23
|
+
function setDiscordAudioOutputStatus(clock, status) {
|
|
24
|
+
for (;;) {
|
|
25
|
+
const current = Atomics.load(clock, DISCORD_AUDIO_OUTPUT_STATUS);
|
|
26
|
+
if ((current & OUTPUT_STATUS_MASK) >= status) return;
|
|
27
|
+
const next = current & -4n | status;
|
|
28
|
+
if (Atomics.compareExchange(clock, DISCORD_AUDIO_OUTPUT_STATUS, current, next) === current) return;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
function admitDiscordAudioInput(clock) {
|
|
32
|
+
for (;;) {
|
|
33
|
+
const current = Atomics.load(clock, DISCORD_AUDIO_OUTPUT_STATUS);
|
|
34
|
+
if ((current & OUTPUT_STATUS_MASK) >= DiscordAudioOutputStatus.Retiring) return false;
|
|
35
|
+
if (Atomics.compareExchange(clock, DISCORD_AUDIO_OUTPUT_STATUS, current, current + OUTPUT_INPUT_RESERVATION) === current) return true;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
function releaseDiscordAudioInput(clock) {
|
|
39
|
+
Atomics.sub(clock, DISCORD_AUDIO_OUTPUT_STATUS, OUTPUT_INPUT_RESERVATION);
|
|
40
|
+
}
|
|
41
|
+
function retireDiscordAudioOutput(clock) {
|
|
42
|
+
for (;;) {
|
|
43
|
+
const current = Atomics.load(clock, DISCORD_AUDIO_OUTPUT_STATUS);
|
|
44
|
+
if ((current & OUTPUT_STATUS_MASK) >= DiscordAudioOutputStatus.Retiring) return true;
|
|
45
|
+
if (current >= OUTPUT_INPUT_RESERVATION) return false;
|
|
46
|
+
if (Atomics.compareExchange(clock, DISCORD_AUDIO_OUTPUT_STATUS, current, DiscordAudioOutputStatus.Retiring) === current) return true;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
function serializeDiscordAudioError(error) {
|
|
50
|
+
if (!(error instanceof Error)) return {
|
|
51
|
+
name: "Error",
|
|
52
|
+
message: String(error)
|
|
53
|
+
};
|
|
54
|
+
return {
|
|
55
|
+
name: error.name,
|
|
56
|
+
message: error.message,
|
|
57
|
+
..."code" in error && typeof error.code === "number" ? { code: error.code } : {},
|
|
58
|
+
..."codeName" in error && typeof error.codeName === "string" ? { codeName: error.codeName } : {},
|
|
59
|
+
..."operation" in error && typeof error.operation === "string" ? { operation: error.operation } : {}
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
function restoreDiscordAudioError(error) {
|
|
63
|
+
return Object.assign(new Error(error.message), error);
|
|
64
|
+
}
|
|
65
|
+
//#endregion
|
|
66
|
+
//#region extensions/discord/src/voice/audio.ts
|
|
67
|
+
const SAMPLE_RATE = 48e3;
|
|
68
|
+
const CHANNELS = 2;
|
|
69
|
+
const BIT_DEPTH = 16;
|
|
70
|
+
const FFMPEG_ERROR_OUTPUT_BYTES = 8192;
|
|
71
|
+
const DISCORD_OPUS_FRAME_SIZE = 960;
|
|
72
|
+
const DISCORD_OPUS_MAX_DECODE_FRAME_SIZE = SAMPLE_RATE * 120 / 1e3;
|
|
73
|
+
const DISCORD_OPUS_ENCODE_BATCH_FRAMES = 8;
|
|
74
|
+
const DISCORD_OPUS_FRAME_BYTES = DISCORD_OPUS_FRAME_SIZE * CHANNELS * (BIT_DEPTH / 8);
|
|
75
|
+
const FFMPEG_PCM_ARGUMENTS = [
|
|
76
|
+
"-analyzeduration",
|
|
77
|
+
"0",
|
|
78
|
+
"-loglevel",
|
|
79
|
+
"error",
|
|
80
|
+
"-vn",
|
|
81
|
+
"-sn",
|
|
82
|
+
"-dn",
|
|
83
|
+
"-f",
|
|
84
|
+
"s16le",
|
|
85
|
+
"-ar",
|
|
86
|
+
String(SAMPLE_RATE),
|
|
87
|
+
"-ac",
|
|
88
|
+
String(CHANNELS)
|
|
89
|
+
];
|
|
90
|
+
let warnedOpusMissing = false;
|
|
91
|
+
function buildWavBuffer(chunks) {
|
|
92
|
+
const pcmBytes = chunks.reduce((total, chunk) => total + chunk.length, 0);
|
|
93
|
+
const blockAlign = 4;
|
|
94
|
+
const byteRate = SAMPLE_RATE * blockAlign;
|
|
95
|
+
const wav = Buffer.allocUnsafe(44 + pcmBytes);
|
|
96
|
+
const header = wav.subarray(0, 44);
|
|
97
|
+
header.write("RIFF", 0);
|
|
98
|
+
header.writeUInt32LE(36 + pcmBytes, 4);
|
|
99
|
+
header.write("WAVE", 8);
|
|
100
|
+
header.write("fmt ", 12);
|
|
101
|
+
header.writeUInt32LE(16, 16);
|
|
102
|
+
header.writeUInt16LE(1, 20);
|
|
103
|
+
header.writeUInt16LE(CHANNELS, 22);
|
|
104
|
+
header.writeUInt32LE(SAMPLE_RATE, 24);
|
|
105
|
+
header.writeUInt32LE(byteRate, 28);
|
|
106
|
+
header.writeUInt16LE(blockAlign, 32);
|
|
107
|
+
header.writeUInt16LE(BIT_DEPTH, 34);
|
|
108
|
+
header.write("data", 36);
|
|
109
|
+
header.writeUInt32LE(pcmBytes, 40);
|
|
110
|
+
let offset = 44;
|
|
111
|
+
for (const chunk of chunks) offset += chunk.copy(wav, offset);
|
|
112
|
+
return wav;
|
|
113
|
+
}
|
|
114
|
+
function createDiscordOpusEncodeStream() {
|
|
115
|
+
return new DiscordOpusEncodeStream();
|
|
116
|
+
}
|
|
117
|
+
function createDiscordOpusPlaybackStream(input) {
|
|
118
|
+
const inputSource = typeof input === "string" ? input : "pipe:0";
|
|
119
|
+
const ffmpeg = spawn(resolveFfmpegBin(), [
|
|
120
|
+
"-i",
|
|
121
|
+
inputSource,
|
|
122
|
+
...FFMPEG_PCM_ARGUMENTS,
|
|
123
|
+
"pipe:1"
|
|
124
|
+
], {
|
|
125
|
+
stdio: [
|
|
126
|
+
"pipe",
|
|
127
|
+
"pipe",
|
|
128
|
+
"pipe"
|
|
129
|
+
],
|
|
130
|
+
windowsHide: true
|
|
131
|
+
});
|
|
132
|
+
const opusStream = createDiscordOpusEncodeStream();
|
|
133
|
+
const stderr = Buffer.alloc(FFMPEG_ERROR_OUTPUT_BYTES);
|
|
134
|
+
let stderrBytes = 0;
|
|
135
|
+
let ffmpegClosed = false;
|
|
136
|
+
const killFfmpeg = (signal = "SIGTERM") => {
|
|
137
|
+
if (!ffmpegClosed && !ffmpeg.killed) ffmpeg.kill(signal);
|
|
138
|
+
};
|
|
139
|
+
ffmpeg.stderr.on("data", (chunk) => {
|
|
140
|
+
if (stderrBytes < FFMPEG_ERROR_OUTPUT_BYTES) stderrBytes += chunk.copy(stderr, stderrBytes, 0, FFMPEG_ERROR_OUTPUT_BYTES - stderrBytes);
|
|
141
|
+
});
|
|
142
|
+
ffmpeg.once("error", (err) => {
|
|
143
|
+
opusStream.destroy(err);
|
|
144
|
+
});
|
|
145
|
+
ffmpeg.once("close", (code, signal) => {
|
|
146
|
+
ffmpegClosed = true;
|
|
147
|
+
if (code && code !== 0) {
|
|
148
|
+
const stderrText = new StringDecoder("utf8").write(stderr.subarray(0, stderrBytes)).trim();
|
|
149
|
+
const suffix = stderrText ? `: ${stderrText}` : "";
|
|
150
|
+
opusStream.destroy(/* @__PURE__ */ new Error(`ffmpeg exited with code ${code}${suffix}`));
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
if (signal) opusStream.destroy(/* @__PURE__ */ new Error(`ffmpeg exited with signal ${signal}`));
|
|
154
|
+
});
|
|
155
|
+
for (const readable of [ffmpeg.stdout, ffmpeg.stderr]) readable.on("error", (err) => {
|
|
156
|
+
killFfmpeg("SIGKILL");
|
|
157
|
+
opusStream.destroy(err);
|
|
158
|
+
});
|
|
159
|
+
ffmpeg.stdin.on("error", (err) => {
|
|
160
|
+
if (err.code !== "EPIPE") opusStream.destroy(err);
|
|
161
|
+
});
|
|
162
|
+
ffmpeg.stdout.pipe(opusStream);
|
|
163
|
+
opusStream.once("close", () => {
|
|
164
|
+
if (!opusStream.readableEnded) killFfmpeg();
|
|
165
|
+
});
|
|
166
|
+
if (typeof input !== "string") {
|
|
167
|
+
input.on("error", (err) => {
|
|
168
|
+
ffmpeg.stdin.destroy(err);
|
|
169
|
+
opusStream.destroy(err);
|
|
170
|
+
});
|
|
171
|
+
input.pipe(ffmpeg.stdin);
|
|
172
|
+
} else ffmpeg.stdin.end();
|
|
173
|
+
return opusStream;
|
|
174
|
+
}
|
|
175
|
+
var DiscordOpusEncodeStream = class extends Duplex {
|
|
176
|
+
#partialFrame = Buffer.alloc(DISCORD_OPUS_FRAME_BYTES);
|
|
177
|
+
#partialBytes = 0;
|
|
178
|
+
#pending;
|
|
179
|
+
#scheduled;
|
|
180
|
+
#readBlocked = false;
|
|
181
|
+
#partialFlushRequested = false;
|
|
182
|
+
#encoder;
|
|
183
|
+
#packetPcmBytes = /* @__PURE__ */ new WeakMap();
|
|
184
|
+
constructor() {
|
|
185
|
+
super({ readableObjectMode: true });
|
|
186
|
+
}
|
|
187
|
+
_construct(done) {
|
|
188
|
+
createEncoder({
|
|
189
|
+
application: Application.Audio,
|
|
190
|
+
channels: CHANNELS,
|
|
191
|
+
sampleRate: SAMPLE_RATE
|
|
192
|
+
}).then((encoder) => {
|
|
193
|
+
this.#encoder = encoder;
|
|
194
|
+
done();
|
|
195
|
+
}, (err) => done(err instanceof Error ? err : new Error(formatErrorMessage(err))));
|
|
196
|
+
}
|
|
197
|
+
_write(chunk, _encoding, done) {
|
|
198
|
+
this.#pending = {
|
|
199
|
+
chunk,
|
|
200
|
+
offset: 0,
|
|
201
|
+
done
|
|
202
|
+
};
|
|
203
|
+
this.#schedule();
|
|
204
|
+
}
|
|
205
|
+
_read() {
|
|
206
|
+
this.#readBlocked = false;
|
|
207
|
+
this.#schedule();
|
|
208
|
+
}
|
|
209
|
+
#schedule() {
|
|
210
|
+
if (this.destroyed || this.#scheduled || this.#readBlocked || !this.#pending) return;
|
|
211
|
+
this.#scheduled = setImmediate(() => {
|
|
212
|
+
this.#scheduled = void 0;
|
|
213
|
+
this.#encodeBatch();
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
#encodeBatch() {
|
|
217
|
+
const pending = this.#pending;
|
|
218
|
+
if (!pending || this.destroyed) return;
|
|
219
|
+
try {
|
|
220
|
+
for (let count = 0; count < DISCORD_OPUS_ENCODE_BATCH_FRAMES; count += 1) {
|
|
221
|
+
const remainingBytes = pending.chunk.length - pending.offset;
|
|
222
|
+
if (this.#partialBytes > 0 || remainingBytes < DISCORD_OPUS_FRAME_BYTES) {
|
|
223
|
+
const copied = pending.chunk.copy(this.#partialFrame, this.#partialBytes, pending.offset, pending.offset + DISCORD_OPUS_FRAME_BYTES - this.#partialBytes);
|
|
224
|
+
pending.offset += copied;
|
|
225
|
+
this.#partialBytes += copied;
|
|
226
|
+
if (this.#partialBytes < DISCORD_OPUS_FRAME_BYTES) {
|
|
227
|
+
this.#pending = void 0;
|
|
228
|
+
pending.done();
|
|
229
|
+
this.#flushRequestedPartialFrame();
|
|
230
|
+
return;
|
|
231
|
+
}
|
|
232
|
+
this.#partialBytes = 0;
|
|
233
|
+
this.#readBlocked = !this.#encodeFrame(this.#partialFrame);
|
|
234
|
+
} else {
|
|
235
|
+
const frame = pending.chunk.subarray(pending.offset, pending.offset + DISCORD_OPUS_FRAME_BYTES);
|
|
236
|
+
pending.offset += DISCORD_OPUS_FRAME_BYTES;
|
|
237
|
+
this.#readBlocked = !this.#encodeFrame(frame);
|
|
238
|
+
}
|
|
239
|
+
if (this.destroyed || this.#readBlocked) return;
|
|
240
|
+
}
|
|
241
|
+
this.#schedule();
|
|
242
|
+
} catch (err) {
|
|
243
|
+
this.#pending = void 0;
|
|
244
|
+
pending.done(err instanceof Error ? err : new Error(formatErrorMessage(err)));
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
_final(done) {
|
|
248
|
+
try {
|
|
249
|
+
this.flushPartialFrame();
|
|
250
|
+
this.push(null);
|
|
251
|
+
done();
|
|
252
|
+
} catch (err) {
|
|
253
|
+
done(err instanceof Error ? err : new Error(formatErrorMessage(err)));
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
flushPartialFrameWhenReady() {
|
|
257
|
+
this.#partialFlushRequested = true;
|
|
258
|
+
if (this.#partialBytes > 0) this.#flushRequestedPartialFrame();
|
|
259
|
+
}
|
|
260
|
+
#flushRequestedPartialFrame() {
|
|
261
|
+
if (!this.#partialFlushRequested || this.#pending || this.writableLength > 0) return;
|
|
262
|
+
this.#partialFlushRequested = false;
|
|
263
|
+
try {
|
|
264
|
+
this.flushPartialFrame();
|
|
265
|
+
} catch (error) {
|
|
266
|
+
this.destroy(error instanceof Error ? error : new Error(formatErrorMessage(error)));
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
flushPartialFrame() {
|
|
270
|
+
if (this.destroyed || this.#pending || this.#partialBytes === 0) return false;
|
|
271
|
+
const pcmBytes = this.#partialBytes;
|
|
272
|
+
this.#partialFrame.fill(0, pcmBytes);
|
|
273
|
+
this.#partialBytes = 0;
|
|
274
|
+
this.#readBlocked = !this.#encodeFrame(this.#partialFrame, pcmBytes);
|
|
275
|
+
return true;
|
|
276
|
+
}
|
|
277
|
+
takePcmBytes(packet) {
|
|
278
|
+
const bytes = this.#packetPcmBytes.get(packet) ?? 0;
|
|
279
|
+
this.#packetPcmBytes.delete(packet);
|
|
280
|
+
return bytes;
|
|
281
|
+
}
|
|
282
|
+
_destroy(err, done) {
|
|
283
|
+
this.#encoder?.free();
|
|
284
|
+
clearImmediate(this.#scheduled);
|
|
285
|
+
this.#scheduled = void 0;
|
|
286
|
+
this.#partialFlushRequested = false;
|
|
287
|
+
const pending = this.#pending;
|
|
288
|
+
this.#pending = void 0;
|
|
289
|
+
pending?.done(err ?? /* @__PURE__ */ new Error("Discord Opus encoder was destroyed"));
|
|
290
|
+
this.#partialBytes = 0;
|
|
291
|
+
this.#partialFrame = Buffer.alloc(0);
|
|
292
|
+
done(err);
|
|
293
|
+
}
|
|
294
|
+
#encodeFrame(frame, pcmBytes = frame.length) {
|
|
295
|
+
const packet = Buffer.from(this.#encoder.encode(frame, { frameSize: DISCORD_OPUS_FRAME_SIZE }));
|
|
296
|
+
this.#packetPcmBytes.set(packet, pcmBytes);
|
|
297
|
+
return this.push(packet);
|
|
298
|
+
}
|
|
299
|
+
};
|
|
300
|
+
function pcmInt16ToBuffer(pcm) {
|
|
301
|
+
return Buffer.from(pcm.buffer, pcm.byteOffset, pcm.byteLength);
|
|
302
|
+
}
|
|
303
|
+
async function decodeOpusStreamChunks(stream, params) {
|
|
304
|
+
try {
|
|
305
|
+
for await (const { pcm, packet } of decodeOpusFrames(stream, params)) await params.onChunk(pcm, packet);
|
|
306
|
+
} catch (err) {
|
|
307
|
+
params.onError?.(err);
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
async function* decodeOpusFrames(stream, params) {
|
|
311
|
+
let decoder;
|
|
312
|
+
try {
|
|
313
|
+
decoder = await createDecoder({
|
|
314
|
+
channels: CHANNELS,
|
|
315
|
+
sampleRate: SAMPLE_RATE
|
|
316
|
+
});
|
|
317
|
+
} catch (err) {
|
|
318
|
+
params.onError?.(err);
|
|
319
|
+
if (!warnedOpusMissing) {
|
|
320
|
+
warnedOpusMissing = true;
|
|
321
|
+
params.onWarn(`discord voice: no usable opus decoder available (libopus-wasm: ${formatErrorMessage(err)}); cannot decode voice audio`);
|
|
322
|
+
}
|
|
323
|
+
return;
|
|
324
|
+
}
|
|
325
|
+
params.onVerbose("opus decoder: libopus-wasm");
|
|
326
|
+
try {
|
|
327
|
+
for await (const chunk of stream) {
|
|
328
|
+
if (!chunk || !(chunk instanceof Buffer) || chunk.length === 0) continue;
|
|
329
|
+
const decoded = decoder.decode(chunk, { maxFrameSize: DISCORD_OPUS_MAX_DECODE_FRAME_SIZE });
|
|
330
|
+
if (decoded.length > 0) yield {
|
|
331
|
+
pcm: pcmInt16ToBuffer(decoded),
|
|
332
|
+
packet: chunk
|
|
333
|
+
};
|
|
334
|
+
}
|
|
335
|
+
} catch (err) {
|
|
336
|
+
params.onError?.(err);
|
|
337
|
+
if (shouldLogVerbose()) logVerbose(`discord voice: opus decode failed: ${formatErrorMessage(err)}`);
|
|
338
|
+
} finally {
|
|
339
|
+
decoder.free();
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
function createDiscordPcmToRealtimeConverter() {
|
|
343
|
+
const resampler = createStreamingPcmResampler(SAMPLE_RATE, 24e3);
|
|
344
|
+
let trailingFrame = Buffer.alloc(0);
|
|
345
|
+
return {
|
|
346
|
+
process(pcm) {
|
|
347
|
+
const input = trailingFrame.length > 0 ? Buffer.concat([trailingFrame, pcm]) : pcm;
|
|
348
|
+
const completeBytes = input.length - input.length % 4;
|
|
349
|
+
trailingFrame = Buffer.from(input.subarray(completeBytes));
|
|
350
|
+
const mono = Buffer.alloc(completeBytes / 2);
|
|
351
|
+
for (let offset = 0; offset < completeBytes; offset += 4) mono.writeInt16LE(Math.round((input.readInt16LE(offset) + input.readInt16LE(offset + 2)) / 2), offset / 2);
|
|
352
|
+
return resampler.process(mono);
|
|
353
|
+
},
|
|
354
|
+
flush() {
|
|
355
|
+
trailingFrame = Buffer.alloc(0);
|
|
356
|
+
return resampler.flush();
|
|
357
|
+
}
|
|
358
|
+
};
|
|
359
|
+
}
|
|
360
|
+
function duplicateMonoChannels(mono) {
|
|
361
|
+
const stereo = Buffer.alloc(mono.length * 2);
|
|
362
|
+
for (let offset = 0; offset < mono.length; offset += 2) {
|
|
363
|
+
const sample = mono.readInt16LE(offset);
|
|
364
|
+
stereo.writeInt16LE(sample, offset * 2);
|
|
365
|
+
stereo.writeInt16LE(sample, offset * 2 + 2);
|
|
366
|
+
}
|
|
367
|
+
return stereo;
|
|
368
|
+
}
|
|
369
|
+
function createRealtimePcmToDiscordConverter() {
|
|
370
|
+
let resampler = createStreamingPcmResampler(24e3, SAMPLE_RATE);
|
|
371
|
+
let history = Buffer.alloc(0);
|
|
372
|
+
let trailingByte = Buffer.alloc(0);
|
|
373
|
+
let replayBytes = 0;
|
|
374
|
+
let flushed = false;
|
|
375
|
+
const takeOutput = (pcm) => {
|
|
376
|
+
const skippedBytes = Math.min(replayBytes, pcm.length);
|
|
377
|
+
replayBytes -= skippedBytes;
|
|
378
|
+
return duplicateMonoChannels(pcm.subarray(skippedBytes));
|
|
379
|
+
};
|
|
380
|
+
return {
|
|
381
|
+
process(pcm) {
|
|
382
|
+
const input = trailingByte.length > 0 ? Buffer.concat([trailingByte, pcm]) : pcm;
|
|
383
|
+
const completeBytes = input.length - input.length % 2;
|
|
384
|
+
const completePcm = input.subarray(0, completeBytes);
|
|
385
|
+
trailingByte = Buffer.from(input.subarray(completeBytes));
|
|
386
|
+
history = Buffer.concat([history, completePcm.subarray(-64)]).subarray(-64);
|
|
387
|
+
return takeOutput(resampler.process(completePcm));
|
|
388
|
+
},
|
|
389
|
+
drain() {
|
|
390
|
+
if (flushed) return Buffer.alloc(0);
|
|
391
|
+
const output = takeOutput(resampler.flush());
|
|
392
|
+
resampler = createStreamingPcmResampler(24e3, SAMPLE_RATE);
|
|
393
|
+
replayBytes = history.length * 2 - resampler.process(history).length;
|
|
394
|
+
return output;
|
|
395
|
+
},
|
|
396
|
+
flush() {
|
|
397
|
+
flushed = true;
|
|
398
|
+
trailingByte = Buffer.alloc(0);
|
|
399
|
+
history = Buffer.alloc(0);
|
|
400
|
+
return takeOutput(resampler.flush());
|
|
401
|
+
}
|
|
402
|
+
};
|
|
403
|
+
}
|
|
404
|
+
async function writeVoiceWavFile(chunks) {
|
|
405
|
+
const wav = buildWavBuffer(chunks);
|
|
406
|
+
const workspace = await tempWorkspace({
|
|
407
|
+
rootDir: resolvePreferredOpenClawTmpDir(),
|
|
408
|
+
prefix: "discord-voice-"
|
|
409
|
+
});
|
|
410
|
+
try {
|
|
411
|
+
return {
|
|
412
|
+
path: await workspace.write("segment.wav", wav),
|
|
413
|
+
durationSeconds: (wav.length - 44) / (BIT_DEPTH / 8 * CHANNELS * SAMPLE_RATE),
|
|
414
|
+
cleanup: () => workspace[Symbol.asyncDispose]()
|
|
415
|
+
};
|
|
416
|
+
} catch (error) {
|
|
417
|
+
await workspace.cleanup();
|
|
418
|
+
throw error;
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
//#endregion
|
|
422
|
+
//#region extensions/discord/src/voice/receive-recovery.ts
|
|
423
|
+
const DECRYPT_FAILURE_WINDOW_MS = 3e4;
|
|
424
|
+
const DECRYPT_FAILURE_RECONNECT_THRESHOLD = 3;
|
|
425
|
+
const DECRYPT_FAILURE_MARKER = "DecryptionFailed(";
|
|
426
|
+
const DAVE_PASSTHROUGH_DISABLED_MARKER = "UnencryptedWhenPassthroughDisabled";
|
|
427
|
+
const WASM_MEMORY_ACCESS_MARKER = "memory access out of bounds";
|
|
428
|
+
const OPUS_INVALID_PACKET_CODE = -4;
|
|
429
|
+
function createVoiceReceiveRecoveryState() {
|
|
430
|
+
return {
|
|
431
|
+
decryptFailureCount: 0,
|
|
432
|
+
lastDecryptFailureAt: 0,
|
|
433
|
+
decryptRecoveryInFlight: false
|
|
434
|
+
};
|
|
435
|
+
}
|
|
436
|
+
function isAbortLikeReceiveError(err) {
|
|
437
|
+
if (!err || typeof err !== "object") return false;
|
|
438
|
+
const name = "name" in err && typeof err.name === "string" ? err.name : "";
|
|
439
|
+
const message = "message" in err && typeof err.message === "string" ? err.message : "";
|
|
440
|
+
return name === "AbortError" || message === "Premature close" || message.includes("The operation was aborted") || message.includes("aborted");
|
|
441
|
+
}
|
|
442
|
+
function isOpusDecodeInvalidPacketError(err) {
|
|
443
|
+
if (!err || typeof err !== "object") return false;
|
|
444
|
+
const maybeOpusError = err;
|
|
445
|
+
const isDecodeOperation = maybeOpusError.operation === "decode" || maybeOpusError.operation === "decodeFloat";
|
|
446
|
+
const isInvalidPacket = maybeOpusError.code === OPUS_INVALID_PACKET_CODE || maybeOpusError.codeName === "InvalidPacket";
|
|
447
|
+
return isDecodeOperation && isInvalidPacket && (err instanceof OpusError || maybeOpusError.name === "OpusError");
|
|
448
|
+
}
|
|
449
|
+
function analyzeVoiceReceiveError(err) {
|
|
450
|
+
const message = formatErrorMessage(err);
|
|
451
|
+
const normalizedMessage = message.toLowerCase();
|
|
452
|
+
const shouldAttemptPassthrough = message.includes(DAVE_PASSTHROUGH_DISABLED_MARKER);
|
|
453
|
+
const isWasmMemoryAccessFailure = normalizedMessage.includes(WASM_MEMORY_ACCESS_MARKER);
|
|
454
|
+
return {
|
|
455
|
+
message,
|
|
456
|
+
isAbortLike: isAbortLikeReceiveError(err),
|
|
457
|
+
isDecodeCorruption: isOpusDecodeInvalidPacketError(err),
|
|
458
|
+
shouldAttemptPassthrough,
|
|
459
|
+
countsAsDecryptFailure: message.includes(DECRYPT_FAILURE_MARKER) || shouldAttemptPassthrough || isWasmMemoryAccessFailure
|
|
460
|
+
};
|
|
461
|
+
}
|
|
462
|
+
function noteVoiceDecryptFailure(state, now = Date.now()) {
|
|
463
|
+
if (now - state.lastDecryptFailureAt > 3e4) state.decryptFailureCount = 0;
|
|
464
|
+
state.lastDecryptFailureAt = now;
|
|
465
|
+
state.decryptFailureCount += 1;
|
|
466
|
+
const firstFailure = state.decryptFailureCount === 1;
|
|
467
|
+
if (state.decryptFailureCount < DECRYPT_FAILURE_RECONNECT_THRESHOLD || state.decryptRecoveryInFlight) return {
|
|
468
|
+
firstFailure,
|
|
469
|
+
shouldRecover: false
|
|
470
|
+
};
|
|
471
|
+
state.decryptRecoveryInFlight = true;
|
|
472
|
+
resetVoiceReceiveRecoveryState(state);
|
|
473
|
+
return {
|
|
474
|
+
firstFailure,
|
|
475
|
+
shouldRecover: true
|
|
476
|
+
};
|
|
477
|
+
}
|
|
478
|
+
function resetVoiceReceiveRecoveryState(state) {
|
|
479
|
+
state.decryptFailureCount = 0;
|
|
480
|
+
state.lastDecryptFailureAt = 0;
|
|
481
|
+
}
|
|
482
|
+
function finishVoiceDecryptRecovery(state) {
|
|
483
|
+
state.decryptRecoveryInFlight = false;
|
|
484
|
+
}
|
|
485
|
+
function isDaveReinitializing(session) {
|
|
486
|
+
return session.reinitializing === true;
|
|
487
|
+
}
|
|
488
|
+
function recoverDaveZeroTransition(params) {
|
|
489
|
+
const { target, sdk, onWarn } = params;
|
|
490
|
+
const networkingState = target.connection.state.networking?.state;
|
|
491
|
+
const daveSession = networkingState?.dave;
|
|
492
|
+
if (target.connection.state.status !== sdk.VoiceConnectionStatus.Ready || networkingState?.code !== sdk.NetworkingStatusCode.Ready || daveSession?.lastTransitionId !== 0 || daveSession.reinitializing !== false || typeof daveSession.recoverFromInvalidTransition !== "function") return "not-attempted";
|
|
493
|
+
try {
|
|
494
|
+
daveSession.recoverFromInvalidTransition(0);
|
|
495
|
+
return "recovered";
|
|
496
|
+
} catch (err) {
|
|
497
|
+
onWarn(`discord voice: failed to recover DAVE transition 0 guild=${target.guildId} channel=${target.channelId}: ${formatErrorMessage(err)}`);
|
|
498
|
+
return isDaveReinitializing(daveSession) ? "failed" : "not-attempted";
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
function enableDaveReceivePassthrough(params) {
|
|
502
|
+
const { target, sdk, reason, expirySeconds, onVerbose, onWarn } = params;
|
|
503
|
+
const networkingState = target.connection.state.networking?.state;
|
|
504
|
+
if (target.connection.state.status !== sdk.VoiceConnectionStatus.Ready || !networkingState || networkingState.code !== sdk.NetworkingStatusCode.Ready && networkingState.code !== sdk.NetworkingStatusCode.Resuming) return false;
|
|
505
|
+
const daveSession = networkingState.dave?.session;
|
|
506
|
+
if (!daveSession) return false;
|
|
507
|
+
try {
|
|
508
|
+
daveSession.setPassthroughMode(true, expirySeconds);
|
|
509
|
+
onVerbose(`enabled DAVE receive passthrough: guild ${target.guildId} channel ${target.channelId} expiry=${expirySeconds}s reason=${reason}`);
|
|
510
|
+
return true;
|
|
511
|
+
} catch (err) {
|
|
512
|
+
onWarn(`discord voice: failed to enable DAVE passthrough guild=${target.guildId} channel=${target.channelId} reason=${reason}: ${formatErrorMessage(err)}`);
|
|
513
|
+
return false;
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
//#endregion
|
|
517
|
+
export { setDiscordAudioOutputStatus as S, getDiscordAudioOutputStatus as _, finishVoiceDecryptRecovery as a, retireDiscordAudioOutput as b, resetVoiceReceiveRecoveryState as c, createDiscordPcmToRealtimeConverter as d, createRealtimePcmToDiscordConverter as f, admitDiscordAudioInput as g, DiscordAudioOutputStatus as h, enableDaveReceivePassthrough as i, createDiscordOpusEncodeStream as l, writeVoiceWavFile as m, analyzeVoiceReceiveError as n, noteVoiceDecryptFailure as o, decodeOpusStreamChunks as p, createVoiceReceiveRecoveryState as r, recoverDaveZeroTransition as s, DECRYPT_FAILURE_WINDOW_MS as t, createDiscordOpusPlaybackStream as u, releaseDiscordAudioInput as v, serializeDiscordAudioError as x, restoreDiscordAudioError as y };
|
|
@@ -7,7 +7,7 @@ import { buildMessagingTarget, parseMentionPrefixOrAtUserTarget, requireTargetKi
|
|
|
7
7
|
import { sleepWithAbort } from "openclaw/plugin-sdk/runtime-env";
|
|
8
8
|
import { resolveAllowlistMatchByCandidates } from "openclaw/plugin-sdk/allow-from";
|
|
9
9
|
import { chunkByParagraph } from "openclaw/plugin-sdk/reply-chunking";
|
|
10
|
-
import {
|
|
10
|
+
import { chunkTextForOutbound, findCodeRegions } from "openclaw/plugin-sdk/text-chunking";
|
|
11
11
|
import { isSingleUseReplyToMode } from "openclaw/plugin-sdk/reply-reference";
|
|
12
12
|
import { createMessageReceiptFromOutboundResults } from "openclaw/plugin-sdk/channel-outbound";
|
|
13
13
|
import { attachChannelToResults } from "openclaw/plugin-sdk/channel-send-result";
|
|
@@ -222,6 +222,42 @@ function createDiscordSendResult(params) {
|
|
|
222
222
|
};
|
|
223
223
|
}
|
|
224
224
|
//#endregion
|
|
225
|
+
//#region packages/normalization-core/src/utf16-slice.ts
|
|
226
|
+
function isHighSurrogate(codeUnit) {
|
|
227
|
+
return codeUnit >= 55296 && codeUnit <= 56319;
|
|
228
|
+
}
|
|
229
|
+
function isLowSurrogate(codeUnit) {
|
|
230
|
+
return codeUnit >= 56320 && codeUnit <= 57343;
|
|
231
|
+
}
|
|
232
|
+
/** Moves a chunk boundary away from the middle of a UTF-16 surrogate pair. */
|
|
233
|
+
function avoidTrailingHighSurrogateBreak(text, start, end) {
|
|
234
|
+
if (end <= start || end >= text.length || !isHighSurrogate(text.charCodeAt(end - 1)) || !isLowSurrogate(text.charCodeAt(end))) return end;
|
|
235
|
+
const adjusted = end - 1;
|
|
236
|
+
return adjusted > start ? adjusted : end + 1;
|
|
237
|
+
}
|
|
238
|
+
//#endregion
|
|
239
|
+
//#region packages/normalization-core/src/grapheme.ts
|
|
240
|
+
let graphemeSegmenter;
|
|
241
|
+
function getGraphemeSegmenter() {
|
|
242
|
+
graphemeSegmenter ??= new Intl.Segmenter(void 0, { granularity: "grapheme" });
|
|
243
|
+
return graphemeSegmenter;
|
|
244
|
+
}
|
|
245
|
+
/**
|
|
246
|
+
* Chooses a whole-grapheme cut within the hard budget, honoring a usable preference.
|
|
247
|
+
* If no whole grapheme fits, allowPartial permits a surrogate-safe progress cut;
|
|
248
|
+
* a leading surrogate pair can exceed maxEnd by one code unit.
|
|
249
|
+
*/
|
|
250
|
+
function findGraphemeChunkEnd(text, start, maxEnd, preferredEnd = maxEnd, allowPartial = true) {
|
|
251
|
+
const hardEnd = Math.min(maxEnd, text.length);
|
|
252
|
+
if (hardEnd <= start) return start;
|
|
253
|
+
const preferred = Number.isInteger(preferredEnd) && preferredEnd > start && preferredEnd <= hardEnd ? preferredEnd : hardEnd;
|
|
254
|
+
if (preferred === text.length) return preferred;
|
|
255
|
+
const segments = getGraphemeSegmenter().segment(text);
|
|
256
|
+
let end = segments.containing(preferred)?.index ?? preferred;
|
|
257
|
+
if (end <= start && preferred < hardEnd) end = hardEnd === text.length ? hardEnd : segments.containing(hardEnd)?.index ?? hardEnd;
|
|
258
|
+
return end > start ? end : allowPartial ? avoidTrailingHighSurrogateBreak(text, start, hardEnd) : start;
|
|
259
|
+
}
|
|
260
|
+
//#endregion
|
|
225
261
|
//#region extensions/discord/src/chunk.ts
|
|
226
262
|
const DEFAULT_MAX_CHARS = 2e3;
|
|
227
263
|
const DEFAULT_MAX_LINES = 17;
|
|
@@ -453,24 +489,53 @@ function createDiscordRanges(source, maxChars, maxLines) {
|
|
|
453
489
|
offset += line.length + 1;
|
|
454
490
|
}
|
|
455
491
|
if (!fence) collect(source.length);
|
|
456
|
-
const
|
|
457
|
-
|
|
492
|
+
const firstSpanEndingAfter = (position) => {
|
|
493
|
+
let low = 0;
|
|
494
|
+
let high = spans.length;
|
|
495
|
+
while (low < high) {
|
|
496
|
+
const middle = low + Math.floor((high - low) / 2);
|
|
497
|
+
if (expectDefined(spans[middle], "Discord inline span").end <= position) low = middle + 1;
|
|
498
|
+
else high = middle;
|
|
499
|
+
}
|
|
500
|
+
return low;
|
|
501
|
+
};
|
|
502
|
+
const firstPrefixEndingAfter = (position) => {
|
|
503
|
+
let low = 0;
|
|
504
|
+
let high = spans.length;
|
|
505
|
+
while (low < high) {
|
|
506
|
+
const middle = low + Math.floor((high - low) / 2);
|
|
507
|
+
const span = expectDefined(spans[middle], "Discord inline span");
|
|
508
|
+
if (span.base + span.code.prefix.end <= position) low = middle + 1;
|
|
509
|
+
else high = middle;
|
|
510
|
+
}
|
|
511
|
+
return spans[low];
|
|
512
|
+
};
|
|
513
|
+
const overlaps = (start, end) => {
|
|
514
|
+
const span = spans[firstSpanEndingAfter(start)];
|
|
515
|
+
return Boolean(span && span.start < end);
|
|
516
|
+
};
|
|
517
|
+
const joins = (end, start) => {
|
|
518
|
+
if (end > start) return false;
|
|
519
|
+
const span = spans[firstSpanEndingAfter(end)];
|
|
520
|
+
return Boolean(span && span.start < end && start < span.end);
|
|
521
|
+
};
|
|
458
522
|
const boundary = (start, end) => {
|
|
459
|
-
let safe =
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
523
|
+
let safe = findGraphemeChunkEnd(source, start, end);
|
|
524
|
+
if (safe === end - 1 && source[end - 1] === "\r" && source[end] === "\n") safe = end;
|
|
525
|
+
const prefixSpan = firstPrefixEndingAfter(safe);
|
|
526
|
+
if (prefixSpan && prefixSpan.base + prefixSpan.code.prefix.start < safe) return prefixSpan.base + prefixSpan.code.prefix.start;
|
|
527
|
+
const span = spans[firstSpanEndingAfter(safe)];
|
|
528
|
+
if (span && span.start < safe) {
|
|
529
|
+
if (source[safe - 1] === "\r" && source[safe] === "\n") safe -= 1;
|
|
530
|
+
if (span.atomicTicks) while (source[safe - 1] === "`" && source[safe] === "`") safe -= 1;
|
|
467
531
|
}
|
|
468
532
|
return safe;
|
|
469
533
|
};
|
|
470
534
|
const render = (start, end) => {
|
|
471
535
|
let cursor = start, text = "";
|
|
472
|
-
for (
|
|
473
|
-
|
|
536
|
+
for (let index = firstSpanEndingAfter(start); index < spans.length; index += 1) {
|
|
537
|
+
const span = expectDefined(spans[index], "Discord inline span");
|
|
538
|
+
if (span.start >= end) break;
|
|
474
539
|
const prefix = span.code.prefix;
|
|
475
540
|
const prefixStart = span.base + prefix.start;
|
|
476
541
|
if (start > span.base + prefix.ownerStart && cursor <= prefixStart) {
|