@openclaw/line 2026.9.5 → 2026.9.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/icon.png +0 -0
- package/dist/.setup/{accounts-BBEFMYbY.mjs → accounts-DOiM8-y3.mjs} +1 -4
- package/dist/.setup/api-4RgpQmHW.mjs +3 -0
- package/dist/.setup/{api-W3zy11mj.mjs → api-w4QdlCCB.mjs} +2 -2
- package/dist/.setup/{card-command-PSnrhetp.mjs → card-command-DYf4gnmI.mjs} +25 -33
- package/dist/.setup/{channel-CAFu4vuW.mjs → channel-DN6Za8Vm.mjs} +789 -26
- package/dist/.setup/channel.runtime-bd5vGeSo.mjs +4 -0
- package/dist/.setup/{monitor-1JaX1WOU.mjs → monitor-C01hAm3f.mjs} +268 -340
- package/dist/.setup/monitor.runtime-DwH2zK48.mjs +2 -0
- package/dist/.setup/outbound.runtime-D_Gs99Dm.mjs +3 -0
- package/dist/.setup/probe.runtime-Cj08-BZ1.mjs +2 -0
- package/dist/.setup/runtime-V7yh9OeC.mjs +8 -0
- package/dist/.setup/{send-E6GiL_tr.mjs → send-DOY1WTxv.mjs} +7 -26
- package/dist/.setup/{send-retry-DaGwYlBO.mjs → send-retry-DV6I0muq.mjs} +105 -209
- package/dist/.setup/{setup-surface-CcfKJKtr.mjs → setup-surface-CbfkmkIS.mjs} +15 -4
- package/dist/.setup/{markdown-to-line-Dvyr_6HD.mjs → template-messages-CxCnYsWN.mjs} +168 -189
- package/dist/api.js +2 -2
- package/dist/channel-plugin-api.js +1 -1
- package/dist/contract-api.js +1 -1
- package/dist/index.js +1 -1
- package/dist/runtime-api.js +2 -260
- package/dist/setup-api.js +1 -1
- package/dist/setup-entry.js +1 -1
- package/node_modules/@line/bot-sdk/node_modules/@types/node/README.md +1 -1
- package/node_modules/@line/bot-sdk/node_modules/@types/node/child_process.d.ts +1 -1
- package/node_modules/@line/bot-sdk/node_modules/@types/node/package.json +2 -2
- package/node_modules/@line/bot-sdk/node_modules/@types/node/stream/web.d.ts +4 -0
- package/node_modules/typebox/build/compile/code.mjs +1 -2
- package/node_modules/typebox/build/compile/validator.mjs +5 -1
- package/node_modules/typebox/build/format/iri.mjs +16 -9
- package/node_modules/typebox/build/guard/emit.mjs +2 -2
- package/node_modules/typebox/build/guard/guard.d.mts +7 -5
- package/node_modules/typebox/build/guard/guard.mjs +14 -9
- package/node_modules/typebox/build/guard/index.mjs +6 -0
- package/node_modules/typebox/build/guard/unicode/unicode.d.mts +6 -0
- package/node_modules/typebox/build/guard/unicode/unicode.mjs +35 -0
- package/node_modules/typebox/build/guard/{string.mjs → unicode/unicode_segment.mjs} +16 -19
- package/node_modules/typebox/build/schema/build.mjs +2 -3
- package/node_modules/typebox/build/schema/engine/_pathing.d.mts +1 -0
- package/node_modules/typebox/build/schema/engine/_pathing.mjs +11 -0
- package/node_modules/typebox/build/schema/engine/_refine.mjs +13 -5
- package/node_modules/typebox/build/schema/engine/additionalProperties.mjs +2 -1
- package/node_modules/typebox/build/schema/engine/dependencies.mjs +2 -1
- package/node_modules/typebox/build/schema/engine/dependentSchemas.mjs +2 -1
- package/node_modules/typebox/build/schema/engine/dynamicRef.d.mts +1 -1
- package/node_modules/typebox/build/schema/engine/dynamicRef.mjs +2 -2
- package/node_modules/typebox/build/schema/engine/format.mjs +9 -2
- package/node_modules/typebox/build/schema/engine/patternProperties.mjs +3 -2
- package/node_modules/typebox/build/schema/engine/properties.mjs +3 -2
- package/node_modules/typebox/build/schema/engine/propertyNames.mjs +2 -1
- package/node_modules/typebox/build/schema/engine/recursiveRef.d.mts +1 -1
- package/node_modules/typebox/build/schema/engine/recursiveRef.mjs +2 -2
- package/node_modules/typebox/build/schema/engine/ref.d.mts +1 -1
- package/node_modules/typebox/build/schema/engine/ref.mjs +2 -2
- package/node_modules/typebox/build/schema/engine/schema.mjs +24 -24
- package/node_modules/typebox/build/schema/parse.mjs +3 -0
- package/node_modules/typebox/build/schema/pointer/pointer.d.mts +1 -6
- package/node_modules/typebox/build/schema/pointer/pointer.mjs +47 -64
- package/node_modules/typebox/build/system/settings/internal.d.mts +2 -0
- package/node_modules/typebox/build/system/settings/internal.mjs +20 -0
- package/node_modules/typebox/build/system/settings/settings.d.mts +11 -0
- package/node_modules/typebox/build/system/settings/settings.mjs +14 -0
- package/node_modules/typebox/build/type/extends/inference.d.mts +1 -1
- package/node_modules/typebox/build/type/extends/inference.mjs +15 -2
- package/node_modules/typebox/build/type/extends/tuple.d.mts +2 -1
- package/node_modules/typebox/build/type/extends/tuple.mjs +21 -1
- package/node_modules/typebox/build/value/parse/parse.mjs +10 -4
- package/node_modules/typebox/package.json +1 -1
- package/node_modules/typebox/readme.md +3 -1
- 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 +6 -6
- package/dist/.setup/account-helpers-BSUyZwLm.mjs +0 -12
- package/dist/.setup/api-BePkCTWu.mjs +0 -3
- package/dist/.setup/channel.runtime-CgI6K6p-.mjs +0 -4
- package/dist/.setup/monitor.runtime-D2vNVJRD.mjs +0 -2
- package/dist/.setup/outbound.runtime-CyrwiL69.mjs +0 -3
- package/dist/.setup/probe.runtime-kp-FIW5_.mjs +0 -2
- package/dist/.setup/rich-messages-Cp77q9NY.mjs +0 -872
- /package/node_modules/typebox/build/guard/{string.d.mts → unicode/unicode_segment.d.mts} +0 -0
|
@@ -1,12 +1,15 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import { n as resolveDefaultLineAccountId, r as resolveLineAccount } from "./accounts-DOiM8-y3.mjs";
|
|
2
|
+
import { a as resolveLineQuestionPostback, c as normalizeLineAllowEntry, i as parseLineQuestionPostbackData, n as createLineQuickReply, o as buildLineQuickReplyFallbackText, r as prepareLineReplyPayload, s as resolveLineGroupConfigEntry } from "./channel-DN6Za8Vm.mjs";
|
|
3
|
+
import { t as getLineRuntime } from "./runtime-V7yh9OeC.mjs";
|
|
4
|
+
import { D as recordLineQuoteToken, E as readLineQuoteToken, O as reportLineQuoteCarrierMissing, T as canCarryLineQuoteToken, j as buildLineMediaMessage, k as resolveLineQuoteToken, n as findLineHttpError, r as resolveLineNonDispatchRetryable, t as explainLineRefusal, w as applyLineQuoteToken } from "./send-retry-DV6I0muq.mjs";
|
|
4
5
|
import { a as eventIdFor, n as LINE_WEBHOOK_SPOOL_INVALID_PAYLOAD_MESSAGE, o as laneKeyFor, r as LineWebhookPayloadError, t as LINE_WEBHOOK_SPOOL_INVALID_EVENT_REASON } from "./webhook-spool-contract-1rY8OJw8.mjs";
|
|
5
|
-
import { a as
|
|
6
|
-
import {
|
|
6
|
+
import { a as getUserDisplayName, g as quotesLineBotMessage, h as showLoadingAnimation, i as getLineGroupName, l as pushMessageLine, n as createLocationMessage, o as getUserProfile, p as replyMessageLine, t as createFlexMessage, u as pushMessagesLine } from "./send-DOY1WTxv.mjs";
|
|
7
|
+
import { n as processLineMessage, t as buildTemplateMessageFromPayload } from "./template-messages-CxCnYsWN.mjs";
|
|
7
8
|
import { createChannelPairingChallengeIssuer } from "openclaw/plugin-sdk/channel-pairing";
|
|
8
9
|
import { resolveChannelGroupsConfigPath } from "openclaw/plugin-sdk/channel-policy";
|
|
9
10
|
import { normalizeOptionalString, normalizeStringEntries, readNonEmptyStringPreservingWhitespace } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
11
|
+
import { createDeferred } from "openclaw/plugin-sdk/extension-shared";
|
|
12
|
+
import { firstDefined } from "openclaw/plugin-sdk/allow-from";
|
|
10
13
|
import { DEFAULT_INGRESS_ADOPTION_STALL_MS, DEFAULT_INGRESS_RETRY_MAX_ATTEMPTS, bindIngressLifecycleToReplyOptions, createChannelIngressMonitor, resolveChannelStreamingBlockEnabled } from "openclaw/plugin-sdk/channel-outbound";
|
|
11
14
|
import { buildChannelInboundEventContext, buildMentionRegexes, formatInboundEnvelope, formatInboundMediaUnavailableText, formatLocationText, hasFinalInboundReplyDispatch, implicitMentionKindWhen, isChannelPartialDeliveryError, logInboundDrop, matchesMentionPatterns, resolveInboundSessionEnvelopeContext, toInboundMediaFactsWithMetadata, toLocationContext } from "openclaw/plugin-sdk/channel-inbound";
|
|
12
15
|
import { collectErrorGraphCandidates, extractErrorCode, formatErrorMessage, readErrorName, toErrorObject } from "openclaw/plugin-sdk/error-runtime";
|
|
@@ -16,132 +19,29 @@ import { createNonExitingRuntime, danger, logVerbose, shouldLogVerbose, waitForA
|
|
|
16
19
|
import { truncateUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime";
|
|
17
20
|
import { classifyTransientNetworkErrorCode } from "openclaw/plugin-sdk/retry-runtime";
|
|
18
21
|
import { fetchWithRuntimeDispatcherOrMockedGlobal } from "openclaw/plugin-sdk/runtime-fetch";
|
|
19
|
-
import {
|
|
20
|
-
import { MediaFetchError } from "openclaw/plugin-sdk/media-runtime";
|
|
21
|
-
import { saveMediaStream } from "openclaw/plugin-sdk/media-store";
|
|
22
|
+
import { expectDefined } from "openclaw/plugin-sdk/expect-runtime";
|
|
22
23
|
import crypto from "node:crypto";
|
|
23
24
|
import { recordChannelActivity } from "openclaw/plugin-sdk/channel-activity-runtime";
|
|
24
25
|
import { resolveHumanDelayConfig } from "openclaw/plugin-sdk/agent-runtime";
|
|
25
26
|
import { channelReadyPatch, channelStoppedPatch } from "openclaw/plugin-sdk/gateway-runtime";
|
|
26
27
|
import { canonicalizeWebhookRouteKey, registerWebhookTargetWithPluginRoute, resolveSingleWebhookTarget, resolveWebhookPath } from "openclaw/plugin-sdk/webhook-ingress";
|
|
27
28
|
import { beginWebhookRequestPipelineOrReject, createWebhookInFlightLimiter, isRequestBodyLimitError, readRequestBodyWithLimit, requestBodyErrorToText, runDetachedWebhookWork, sendHttpRequestRejection } from "openclaw/plugin-sdk/webhook-request-guards";
|
|
28
|
-
import { expectDefined } from "openclaw/plugin-sdk/expect-runtime";
|
|
29
29
|
import { chunkMarkdownText } from "openclaw/plugin-sdk/reply-runtime";
|
|
30
|
-
import {
|
|
30
|
+
import { resolvePromptHistoryLimit } from "openclaw/plugin-sdk/number-runtime";
|
|
31
31
|
import { getRuntimeConfig, getRuntimeConfigSnapshot, getRuntimeConfigSourceSnapshot, selectApplicableRuntimeConfig } from "openclaw/plugin-sdk/runtime-config-snapshot";
|
|
32
|
-
import { fanInChannelIngressLifecycles, resolveChannelImplicitMentions
|
|
32
|
+
import { fanInChannelIngressLifecycles, resolveChannelImplicitMentions } from "openclaw/plugin-sdk/channel-ingress-runtime";
|
|
33
33
|
import { reportChannelRoomJoin } from "openclaw/plugin-sdk/channel-join-intro-runtime";
|
|
34
34
|
import { hasControlCommand } from "openclaw/plugin-sdk/command-auth-native";
|
|
35
|
-
import { ensureConfiguredBindingRouteReady, readChannelAllowFromStore, resolveConfiguredBindingRoute, resolvePairingIdLabel, resolvePinnedMainDmOwnerFromAllowlist,
|
|
36
|
-
import {
|
|
35
|
+
import { ensureConfiguredBindingRouteReady, readChannelAllowFromStore, resolveConfiguredBindingRoute, resolvePairingIdLabel, resolvePinnedMainDmOwnerFromAllowlist, upsertChannelPairingRequest } from "openclaw/plugin-sdk/conversation-runtime";
|
|
36
|
+
import { DEFAULT_GROUP_HISTORY_LIMIT, createChannelHistoryWindow } from "openclaw/plugin-sdk/reply-history";
|
|
37
|
+
import { parseAgentSessionKey, resolveAgentRoute, resolveInboundLastRouteSessionKey } from "openclaw/plugin-sdk/routing";
|
|
37
38
|
import { resolveAllowlistProviderRuntimeGroupPolicy, resolveDefaultGroupPolicy, warnMissingProviderGroupPolicyFallbackOnce } from "openclaw/plugin-sdk/runtime-group-policy";
|
|
39
|
+
import { getSessionBindingService, inspectRuntimeConversationBindingRoute } from "openclaw/plugin-sdk/conversation-binding-runtime";
|
|
40
|
+
import { setTimeout as setTimeout$1 } from "node:timers/promises";
|
|
41
|
+
import { MediaFetchError } from "openclaw/plugin-sdk/media-runtime";
|
|
42
|
+
import { saveMediaStream } from "openclaw/plugin-sdk/media-store";
|
|
38
43
|
import { enqueueKeyedTask } from "openclaw/plugin-sdk/keyed-async-queue";
|
|
39
44
|
import { safeEqualSecret } from "openclaw/plugin-sdk/security-runtime";
|
|
40
|
-
//#region extensions/line/src/download.ts
|
|
41
|
-
const CONTENT_READY_MAX_ATTEMPTS = 6;
|
|
42
|
-
const CONTENT_READY_BASE_DELAY_MS = 500;
|
|
43
|
-
const CONTENT_READY_MAX_DELAY_MS = 4e3;
|
|
44
|
-
const CONTENT_DOWNLOAD_TIMEOUT_MS = 15e3;
|
|
45
|
-
const LINE_CONTENT_BASE_URL = "https://api-data.line.me/v2/bot/message";
|
|
46
|
-
var RetryableLineMediaFetchError = class extends MediaFetchError {
|
|
47
|
-
constructor(message, options) {
|
|
48
|
-
super("fetch_failed", message, options);
|
|
49
|
-
this.name = "RetryableLineMediaFetchError";
|
|
50
|
-
}
|
|
51
|
-
};
|
|
52
|
-
function contentBackoffDelayMs(attempt) {
|
|
53
|
-
return Math.min(CONTENT_READY_BASE_DELAY_MS * 2 ** attempt, CONTENT_READY_MAX_DELAY_MS);
|
|
54
|
-
}
|
|
55
|
-
function lineContentUrl(messageId) {
|
|
56
|
-
return `${LINE_CONTENT_BASE_URL}/${encodeURIComponent(messageId)}/content`;
|
|
57
|
-
}
|
|
58
|
-
async function* lineResponseBodyChunks(response, messageId, signal, onComplete) {
|
|
59
|
-
const body = response.body;
|
|
60
|
-
if (!body) throw new RetryableLineMediaFetchError(`LINE media response for message ${messageId} had no body`);
|
|
61
|
-
const reader = body.getReader();
|
|
62
|
-
let completed = false;
|
|
63
|
-
try {
|
|
64
|
-
while (true) {
|
|
65
|
-
let chunk;
|
|
66
|
-
try {
|
|
67
|
-
chunk = await reader.read();
|
|
68
|
-
} catch (err) {
|
|
69
|
-
if (signal.aborted) throw signal.reason;
|
|
70
|
-
throw new RetryableLineMediaFetchError(`LINE media response stream failed for message ${messageId}`, { cause: err });
|
|
71
|
-
}
|
|
72
|
-
if (chunk.done) {
|
|
73
|
-
completed = true;
|
|
74
|
-
onComplete();
|
|
75
|
-
return;
|
|
76
|
-
}
|
|
77
|
-
if (chunk.value.byteLength > 0) yield chunk.value;
|
|
78
|
-
}
|
|
79
|
-
} finally {
|
|
80
|
-
if (!completed) await reader.cancel(signal.aborted ? signal.reason : void 0).catch(() => void 0);
|
|
81
|
-
try {
|
|
82
|
-
reader.releaseLock();
|
|
83
|
-
} catch {}
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
async function fetchLineContentWhenReady(messageId, channelAccessToken, signal) {
|
|
87
|
-
try {
|
|
88
|
-
for (let attempt = 0; attempt < CONTENT_READY_MAX_ATTEMPTS; attempt++) {
|
|
89
|
-
const response = await fetchWithRuntimeDispatcherOrMockedGlobal(lineContentUrl(messageId), {
|
|
90
|
-
headers: { Authorization: `Bearer ${channelAccessToken}` },
|
|
91
|
-
redirect: "error",
|
|
92
|
-
signal
|
|
93
|
-
});
|
|
94
|
-
if (response.status === 200) {
|
|
95
|
-
if (!response.body) throw new RetryableLineMediaFetchError(`LINE media response for message ${messageId} had no body`);
|
|
96
|
-
return response;
|
|
97
|
-
}
|
|
98
|
-
await response.body?.cancel().catch(() => void 0);
|
|
99
|
-
if (response.status !== 202) throw new MediaFetchError("http_error", `LINE media download failed for message ${messageId} (HTTP ${response.status})`, { status: response.status });
|
|
100
|
-
if (attempt < 5) await setTimeout$1(contentBackoffDelayMs(attempt), void 0, { signal });
|
|
101
|
-
}
|
|
102
|
-
} catch (err) {
|
|
103
|
-
if (signal.aborted) throw signal.reason;
|
|
104
|
-
if (err instanceof MediaFetchError) throw err;
|
|
105
|
-
throw new RetryableLineMediaFetchError(`LINE media download failed for message ${messageId}`, { cause: err });
|
|
106
|
-
}
|
|
107
|
-
throw new MediaFetchError("http_error", `LINE media for message ${messageId} was still preparing (HTTP 202) after ${CONTENT_READY_MAX_ATTEMPTS} attempts`, { status: 202 });
|
|
108
|
-
}
|
|
109
|
-
function isRetryableLineInboundMediaError(err) {
|
|
110
|
-
if (err instanceof RetryableLineMediaFetchError) return true;
|
|
111
|
-
if (!(err instanceof MediaFetchError)) return false;
|
|
112
|
-
if (err.code === "http_error") return err.status === 202 || err.status === 408 || err.status === 429 || typeof err.status === "number" && err.status >= 500;
|
|
113
|
-
return false;
|
|
114
|
-
}
|
|
115
|
-
async function downloadLineMedia(messageId, channelAccessToken, maxBytes = 10485760, options) {
|
|
116
|
-
options?.signal?.throwIfAborted();
|
|
117
|
-
const deadlineAbort = new AbortController();
|
|
118
|
-
const signal = options?.signal ? AbortSignal.any([options.signal, deadlineAbort.signal]) : deadlineAbort.signal;
|
|
119
|
-
const deadline = setTimeout(() => {
|
|
120
|
-
deadlineAbort.abort(new RetryableLineMediaFetchError(`LINE media for message ${messageId} did not download within ${CONTENT_DOWNLOAD_TIMEOUT_MS / 1e3} seconds`));
|
|
121
|
-
}, CONTENT_DOWNLOAD_TIMEOUT_MS);
|
|
122
|
-
deadline.unref();
|
|
123
|
-
try {
|
|
124
|
-
const response = await fetchLineContentWhenReady(messageId, channelAccessToken, signal);
|
|
125
|
-
let saved;
|
|
126
|
-
try {
|
|
127
|
-
saved = await saveMediaStream(lineResponseBodyChunks(response, messageId, signal, () => clearTimeout(deadline)), response.headers.get("content-type") ?? void 0, "inbound", maxBytes, options?.originalFilename);
|
|
128
|
-
} catch (err) {
|
|
129
|
-
await response.body?.cancel(signal.aborted ? signal.reason : err).catch(() => void 0);
|
|
130
|
-
if (signal.aborted) throw signal.reason;
|
|
131
|
-
throw err;
|
|
132
|
-
}
|
|
133
|
-
options?.signal?.throwIfAborted();
|
|
134
|
-
logVerbose(`line: persisted media ${messageId} to ${saved.path} (${saved.size} bytes)`);
|
|
135
|
-
return {
|
|
136
|
-
path: saved.path,
|
|
137
|
-
contentType: saved.contentType,
|
|
138
|
-
size: saved.size
|
|
139
|
-
};
|
|
140
|
-
} finally {
|
|
141
|
-
clearTimeout(deadline);
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
//#endregion
|
|
145
45
|
//#region extensions/line/src/auto-reply-delivery.ts
|
|
146
46
|
function toLineDeliveryError(error) {
|
|
147
47
|
return error instanceof Error ? error : new Error("LINE message send failed", { cause: error });
|
|
@@ -409,46 +309,73 @@ function buildPeerId(source) {
|
|
|
409
309
|
if (source.type === "user" && source.userId) return source.userId;
|
|
410
310
|
return "unknown";
|
|
411
311
|
}
|
|
412
|
-
async function
|
|
413
|
-
recordChannelActivity({
|
|
414
|
-
channel: "line",
|
|
415
|
-
accountId: params.account.accountId,
|
|
416
|
-
direction: "inbound"
|
|
417
|
-
});
|
|
312
|
+
async function prepareLineInboundRoute(params) {
|
|
418
313
|
const { userId, groupId, roomId, isGroup } = getLineSourceInfo(params.source);
|
|
419
314
|
const peerId = buildPeerId(params.source);
|
|
420
|
-
|
|
421
|
-
cfg: params.cfg,
|
|
315
|
+
const routeInput = {
|
|
422
316
|
channel: "line",
|
|
423
317
|
accountId: params.account.accountId,
|
|
424
318
|
peer: {
|
|
425
319
|
kind: isGroup ? "group" : "direct",
|
|
426
320
|
id: peerId
|
|
427
321
|
}
|
|
322
|
+
};
|
|
323
|
+
const conversation = {
|
|
324
|
+
channel: "line",
|
|
325
|
+
accountId: params.account.accountId,
|
|
326
|
+
conversationId: peerId
|
|
327
|
+
};
|
|
328
|
+
const inspection = await getSessionBindingService().inspectByConversationAsync(conversation);
|
|
329
|
+
if (inspection.status === "unavailable") throw new Error("LINE conversation binding owner is temporarily unavailable; retry the message.");
|
|
330
|
+
const resolveScopeRoute = (agentId) => resolveAgentRoute({
|
|
331
|
+
...routeInput,
|
|
332
|
+
cfg: { session: params.cfg.session },
|
|
333
|
+
defaultAgentId: agentId
|
|
334
|
+
});
|
|
335
|
+
const selection = inspectRuntimeConversationBindingRoute({
|
|
336
|
+
route: resolveScopeRoute(),
|
|
337
|
+
inspection
|
|
338
|
+
});
|
|
339
|
+
const metadataAgentId = selection.bindingRecord?.metadata?.agentId;
|
|
340
|
+
const hasBoundAgent = selection.boundSessionKey && (parseAgentSessionKey(selection.boundSessionKey) || typeof metadataAgentId === "string" && metadataAgentId.trim());
|
|
341
|
+
const baseRoute = hasBoundAgent ? resolveScopeRoute(selection.boundAgentId) : resolveAgentRoute({
|
|
342
|
+
...routeInput,
|
|
343
|
+
cfg: params.cfg
|
|
428
344
|
});
|
|
429
|
-
const configuredRoute =
|
|
345
|
+
const configuredRoute = hasBoundAgent ? {
|
|
346
|
+
route: baseRoute,
|
|
347
|
+
bindingResolution: null
|
|
348
|
+
} : resolveConfiguredBindingRoute({
|
|
430
349
|
cfg: params.cfg,
|
|
431
|
-
route,
|
|
432
|
-
conversation
|
|
433
|
-
channel: "line",
|
|
434
|
-
accountId: params.account.accountId,
|
|
435
|
-
conversationId: peerId
|
|
436
|
-
}
|
|
350
|
+
route: baseRoute,
|
|
351
|
+
conversation
|
|
437
352
|
});
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
353
|
+
const runtimeRoute = inspectRuntimeConversationBindingRoute({
|
|
354
|
+
route: configuredRoute.route,
|
|
355
|
+
inspection
|
|
356
|
+
});
|
|
357
|
+
return {
|
|
358
|
+
userId,
|
|
359
|
+
groupId,
|
|
360
|
+
roomId,
|
|
361
|
+
isGroup,
|
|
362
|
+
peerId,
|
|
363
|
+
route: runtimeRoute.route,
|
|
364
|
+
mentionAgentId: baseRoute.agentId,
|
|
365
|
+
runtimeRoute,
|
|
366
|
+
configuredBinding: runtimeRoute.bindingRecord ? null : configuredRoute.bindingResolution,
|
|
367
|
+
configuredBindingSessionKey: configuredRoute.boundSessionKey ?? ""
|
|
368
|
+
};
|
|
369
|
+
}
|
|
370
|
+
async function resolveLineInboundRoute(params) {
|
|
371
|
+
recordChannelActivity({
|
|
372
|
+
channel: "line",
|
|
373
|
+
accountId: params.account.accountId,
|
|
374
|
+
direction: "inbound"
|
|
448
375
|
});
|
|
449
|
-
route =
|
|
376
|
+
const { userId, groupId, roomId, isGroup, peerId, route, runtimeRoute, configuredBinding, configuredBindingSessionKey } = params.preparedRoute ?? await prepareLineInboundRoute(params);
|
|
450
377
|
if (runtimeRoute.bindingRecord) {
|
|
451
|
-
|
|
378
|
+
await getSessionBindingService().touchAsync(runtimeRoute.bindingRecord.bindingId, void 0, runtimeRoute.bindingRecord.conversation);
|
|
452
379
|
logVerbose(runtimeRoute.boundSessionKey ? `line: routed via bound conversation ${peerId} -> ${runtimeRoute.boundSessionKey}` : `line: plugin-bound conversation ${peerId}`);
|
|
453
380
|
}
|
|
454
381
|
if (configuredBinding) {
|
|
@@ -538,7 +465,7 @@ async function finalizeLineInboundContext(params) {
|
|
|
538
465
|
const body = formatInboundEnvelope({
|
|
539
466
|
channel: "LINE",
|
|
540
467
|
from: conversationLabel,
|
|
541
|
-
timestamp: params.timestamp,
|
|
468
|
+
timestamp: params.event.timestamp,
|
|
542
469
|
body: agentBody,
|
|
543
470
|
chatType: params.source.isGroup ? "group" : "direct",
|
|
544
471
|
sender: {
|
|
@@ -553,7 +480,7 @@ async function finalizeLineInboundContext(params) {
|
|
|
553
480
|
channel: "line",
|
|
554
481
|
accountId: params.route.accountId,
|
|
555
482
|
messageId: params.messageSid,
|
|
556
|
-
timestamp: params.timestamp,
|
|
483
|
+
timestamp: params.event.timestamp,
|
|
557
484
|
from: address,
|
|
558
485
|
sender: {
|
|
559
486
|
id: senderId,
|
|
@@ -565,9 +492,7 @@ async function finalizeLineInboundContext(params) {
|
|
|
565
492
|
label: conversationLabel
|
|
566
493
|
},
|
|
567
494
|
route: {
|
|
568
|
-
|
|
569
|
-
dmScope: params.route.dmScope,
|
|
570
|
-
accountId: params.route.accountId,
|
|
495
|
+
...params.route,
|
|
571
496
|
routeSessionKey: params.route.sessionKey
|
|
572
497
|
},
|
|
573
498
|
reply: {
|
|
@@ -595,7 +520,7 @@ async function finalizeLineInboundContext(params) {
|
|
|
595
520
|
const pinnedMainDmOwner = !params.source.isGroup ? resolvePinnedMainDmOwnerFromAllowlist({
|
|
596
521
|
dmScope: params.cfg.session?.dmScope,
|
|
597
522
|
allowFrom: params.account.config.allowFrom,
|
|
598
|
-
normalizeEntry: (entry) =>
|
|
523
|
+
normalizeEntry: (entry) => normalizeLineAllowEntry(entry) || void 0
|
|
599
524
|
}) : null;
|
|
600
525
|
const inboundLastRouteSessionKey = resolveInboundLastRouteSessionKey({
|
|
601
526
|
route: params.route,
|
|
@@ -609,7 +534,14 @@ async function finalizeLineInboundContext(params) {
|
|
|
609
534
|
}
|
|
610
535
|
return {
|
|
611
536
|
ctxPayload,
|
|
537
|
+
event: params.event,
|
|
538
|
+
userId: params.source.userId,
|
|
539
|
+
groupId: params.source.groupId,
|
|
540
|
+
roomId: params.source.roomId,
|
|
541
|
+
isGroup: params.source.isGroup,
|
|
542
|
+
route: params.route,
|
|
612
543
|
replyToken: params.event.replyToken,
|
|
544
|
+
accountId: params.account.accountId,
|
|
613
545
|
skillFilter: groupConfig?.skills,
|
|
614
546
|
turn: {
|
|
615
547
|
storePath,
|
|
@@ -640,11 +572,11 @@ async function buildLineMessageContext(params) {
|
|
|
640
572
|
const { userId, groupId, roomId, isGroup, peerId, route } = await resolveLineInboundRoute({
|
|
641
573
|
source,
|
|
642
574
|
cfg,
|
|
643
|
-
account
|
|
575
|
+
account,
|
|
576
|
+
preparedRoute: params.preparedRoute
|
|
644
577
|
});
|
|
645
578
|
const message = event.message;
|
|
646
579
|
const messageId = message.id;
|
|
647
|
-
const timestamp = event.timestamp;
|
|
648
580
|
const textContent = extractMessageText(message);
|
|
649
581
|
const nativeMediaKind = extractNativeMediaKind(message);
|
|
650
582
|
const mediaFacts = allMedia.length > 0 ? allMedia.map((media) => ({
|
|
@@ -678,7 +610,7 @@ async function buildLineMessageContext(params) {
|
|
|
678
610
|
address: loc.address
|
|
679
611
|
});
|
|
680
612
|
}
|
|
681
|
-
|
|
613
|
+
return finalizeLineInboundContext({
|
|
682
614
|
cfg,
|
|
683
615
|
account,
|
|
684
616
|
event,
|
|
@@ -694,7 +626,6 @@ async function buildLineMessageContext(params) {
|
|
|
694
626
|
agentBody,
|
|
695
627
|
commandBody: resolveLineMentionStrippedText(message) || rawBody,
|
|
696
628
|
mentions: params.mentions,
|
|
697
|
-
timestamp,
|
|
698
629
|
messageSid: messageId,
|
|
699
630
|
commandAuthorized,
|
|
700
631
|
channelIngress: await params.resolveChannelIngress?.({
|
|
@@ -712,19 +643,6 @@ async function buildLineMessageContext(params) {
|
|
|
712
643
|
},
|
|
713
644
|
inboundHistory
|
|
714
645
|
});
|
|
715
|
-
return {
|
|
716
|
-
ctxPayload: finalized.ctxPayload,
|
|
717
|
-
turn: finalized.turn,
|
|
718
|
-
skillFilter: finalized.skillFilter,
|
|
719
|
-
event,
|
|
720
|
-
userId,
|
|
721
|
-
groupId,
|
|
722
|
-
roomId,
|
|
723
|
-
isGroup,
|
|
724
|
-
route,
|
|
725
|
-
replyToken: event.replyToken,
|
|
726
|
-
accountId: account.accountId
|
|
727
|
-
};
|
|
728
646
|
}
|
|
729
647
|
async function buildLinePostbackContext(params) {
|
|
730
648
|
const { event, cfg, account, commandAuthorized } = params;
|
|
@@ -749,7 +667,7 @@ async function buildLinePostbackContext(params) {
|
|
|
749
667
|
if (picked) agentBody += ` ${key}=${picked}`;
|
|
750
668
|
}
|
|
751
669
|
const messageSid = event.replyToken ? `postback:${event.replyToken}` : `postback:${timestamp}`;
|
|
752
|
-
|
|
670
|
+
return finalizeLineInboundContext({
|
|
753
671
|
cfg,
|
|
754
672
|
account,
|
|
755
673
|
event,
|
|
@@ -763,7 +681,6 @@ async function buildLinePostbackContext(params) {
|
|
|
763
681
|
},
|
|
764
682
|
rawBody,
|
|
765
683
|
agentBody,
|
|
766
|
-
timestamp,
|
|
767
684
|
messageSid,
|
|
768
685
|
commandAuthorized,
|
|
769
686
|
channelIngress: await params.resolveChannelIngress?.({
|
|
@@ -776,19 +693,111 @@ async function buildLinePostbackContext(params) {
|
|
|
776
693
|
media: [],
|
|
777
694
|
verboseLog: { kind: "postback" }
|
|
778
695
|
});
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
}
|
|
696
|
+
}
|
|
697
|
+
//#endregion
|
|
698
|
+
//#region extensions/line/src/download.ts
|
|
699
|
+
const CONTENT_READY_MAX_ATTEMPTS = 6;
|
|
700
|
+
const CONTENT_READY_BASE_DELAY_MS = 500;
|
|
701
|
+
const CONTENT_READY_MAX_DELAY_MS = 4e3;
|
|
702
|
+
const CONTENT_DOWNLOAD_TIMEOUT_MS = 15e3;
|
|
703
|
+
const LINE_CONTENT_BASE_URL = "https://api-data.line.me/v2/bot/message";
|
|
704
|
+
var RetryableLineMediaFetchError = class extends MediaFetchError {
|
|
705
|
+
constructor(message, options) {
|
|
706
|
+
super("fetch_failed", message, options);
|
|
707
|
+
this.name = "RetryableLineMediaFetchError";
|
|
708
|
+
}
|
|
709
|
+
};
|
|
710
|
+
function contentBackoffDelayMs(attempt) {
|
|
711
|
+
return Math.min(CONTENT_READY_BASE_DELAY_MS * 2 ** attempt, CONTENT_READY_MAX_DELAY_MS);
|
|
712
|
+
}
|
|
713
|
+
function lineContentUrl(messageId) {
|
|
714
|
+
return `${LINE_CONTENT_BASE_URL}/${encodeURIComponent(messageId)}/content`;
|
|
715
|
+
}
|
|
716
|
+
async function* lineResponseBodyChunks(response, messageId, signal, onComplete) {
|
|
717
|
+
const body = response.body;
|
|
718
|
+
if (!body) throw new RetryableLineMediaFetchError(`LINE media response for message ${messageId} had no body`);
|
|
719
|
+
const reader = body.getReader();
|
|
720
|
+
let completed = false;
|
|
721
|
+
try {
|
|
722
|
+
while (true) {
|
|
723
|
+
let chunk;
|
|
724
|
+
try {
|
|
725
|
+
chunk = await reader.read();
|
|
726
|
+
} catch (err) {
|
|
727
|
+
if (signal.aborted) throw signal.reason;
|
|
728
|
+
throw new RetryableLineMediaFetchError(`LINE media response stream failed for message ${messageId}`, { cause: err });
|
|
729
|
+
}
|
|
730
|
+
if (chunk.done) {
|
|
731
|
+
completed = true;
|
|
732
|
+
onComplete();
|
|
733
|
+
return;
|
|
734
|
+
}
|
|
735
|
+
if (chunk.value.byteLength > 0) yield chunk.value;
|
|
736
|
+
}
|
|
737
|
+
} finally {
|
|
738
|
+
if (!completed) await reader.cancel(signal.aborted ? signal.reason : void 0).catch(() => void 0);
|
|
739
|
+
try {
|
|
740
|
+
reader.releaseLock();
|
|
741
|
+
} catch {}
|
|
742
|
+
}
|
|
743
|
+
}
|
|
744
|
+
async function fetchLineContentWhenReady(messageId, channelAccessToken, signal) {
|
|
745
|
+
try {
|
|
746
|
+
for (let attempt = 0; attempt < CONTENT_READY_MAX_ATTEMPTS; attempt++) {
|
|
747
|
+
const response = await fetchWithRuntimeDispatcherOrMockedGlobal(lineContentUrl(messageId), {
|
|
748
|
+
headers: { Authorization: `Bearer ${channelAccessToken}` },
|
|
749
|
+
redirect: "error",
|
|
750
|
+
signal
|
|
751
|
+
});
|
|
752
|
+
if (response.status === 200) {
|
|
753
|
+
if (!response.body) throw new RetryableLineMediaFetchError(`LINE media response for message ${messageId} had no body`);
|
|
754
|
+
return response;
|
|
755
|
+
}
|
|
756
|
+
await response.body?.cancel().catch(() => void 0);
|
|
757
|
+
if (response.status !== 202) throw new MediaFetchError("http_error", `LINE media download failed for message ${messageId} (HTTP ${response.status})`, { status: response.status });
|
|
758
|
+
if (attempt < 5) await setTimeout$1(contentBackoffDelayMs(attempt), void 0, { signal });
|
|
759
|
+
}
|
|
760
|
+
} catch (err) {
|
|
761
|
+
if (signal.aborted) throw signal.reason;
|
|
762
|
+
if (err instanceof MediaFetchError) throw err;
|
|
763
|
+
throw new RetryableLineMediaFetchError(`LINE media download failed for message ${messageId}`, { cause: err });
|
|
764
|
+
}
|
|
765
|
+
throw new MediaFetchError("http_error", `LINE media for message ${messageId} was still preparing (HTTP 202) after ${CONTENT_READY_MAX_ATTEMPTS} attempts`, { status: 202 });
|
|
766
|
+
}
|
|
767
|
+
function isRetryableLineInboundMediaError(err) {
|
|
768
|
+
if (err instanceof RetryableLineMediaFetchError) return true;
|
|
769
|
+
if (!(err instanceof MediaFetchError)) return false;
|
|
770
|
+
if (err.code === "http_error") return err.status === 202 || err.status === 408 || err.status === 429 || typeof err.status === "number" && err.status >= 500;
|
|
771
|
+
return false;
|
|
772
|
+
}
|
|
773
|
+
async function downloadLineMedia(messageId, channelAccessToken, maxBytes = 10485760, options) {
|
|
774
|
+
options?.signal?.throwIfAborted();
|
|
775
|
+
const deadlineAbort = new AbortController();
|
|
776
|
+
const signal = options?.signal ? AbortSignal.any([options.signal, deadlineAbort.signal]) : deadlineAbort.signal;
|
|
777
|
+
const deadline = setTimeout(() => {
|
|
778
|
+
deadlineAbort.abort(new RetryableLineMediaFetchError(`LINE media for message ${messageId} did not download within ${CONTENT_DOWNLOAD_TIMEOUT_MS / 1e3} seconds`));
|
|
779
|
+
}, CONTENT_DOWNLOAD_TIMEOUT_MS);
|
|
780
|
+
deadline.unref();
|
|
781
|
+
try {
|
|
782
|
+
const response = await fetchLineContentWhenReady(messageId, channelAccessToken, signal);
|
|
783
|
+
let saved;
|
|
784
|
+
try {
|
|
785
|
+
saved = await saveMediaStream(lineResponseBodyChunks(response, messageId, signal, () => clearTimeout(deadline)), response.headers.get("content-type") ?? void 0, "inbound", maxBytes, options?.originalFilename);
|
|
786
|
+
} catch (err) {
|
|
787
|
+
await response.body?.cancel(signal.aborted ? signal.reason : err).catch(() => void 0);
|
|
788
|
+
if (signal.aborted) throw signal.reason;
|
|
789
|
+
throw err;
|
|
790
|
+
}
|
|
791
|
+
options?.signal?.throwIfAborted();
|
|
792
|
+
logVerbose(`line: persisted media ${messageId} to ${saved.path} (${saved.size} bytes)`);
|
|
793
|
+
return {
|
|
794
|
+
path: saved.path,
|
|
795
|
+
contentType: saved.contentType,
|
|
796
|
+
size: saved.size
|
|
797
|
+
};
|
|
798
|
+
} finally {
|
|
799
|
+
clearTimeout(deadline);
|
|
800
|
+
}
|
|
792
801
|
}
|
|
793
802
|
//#endregion
|
|
794
803
|
//#region extensions/line/src/group-history.ts
|
|
@@ -916,6 +925,10 @@ async function resolveLineEventAdmission(event, context) {
|
|
|
916
925
|
groupId,
|
|
917
926
|
roomId
|
|
918
927
|
});
|
|
928
|
+
if (isGroup && groupConfig?.enabled === false) {
|
|
929
|
+
logVerbose(`Blocked line group ${groupId ?? roomId ?? "unknown"} (group disabled)`);
|
|
930
|
+
return null;
|
|
931
|
+
}
|
|
919
932
|
const rawText = resolveEventRawText(event);
|
|
920
933
|
const requireMention = isGroup ? groupConfig?.requireMention !== false : false;
|
|
921
934
|
const dmPolicy = account.config.dmPolicy ?? "pairing";
|
|
@@ -926,30 +939,9 @@ async function resolveLineEventAdmission(event, context) {
|
|
|
926
939
|
});
|
|
927
940
|
const groupPolicy = runtimeGroupPolicy === "disabled" ? "disabled" : groupConfig?.allowFrom !== void 0 ? "allowlist" : runtimeGroupPolicy;
|
|
928
941
|
const groupAllowFrom = normalizeStringEntries(firstDefined(groupConfig?.allowFrom, account.config.groupAllowFrom));
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
const { agentId } = resolveAgentRoute({
|
|
933
|
-
cfg,
|
|
934
|
-
channel: "line",
|
|
935
|
-
accountId: account.accountId,
|
|
936
|
-
peer: {
|
|
937
|
-
kind: "group",
|
|
938
|
-
id: peerId
|
|
939
|
-
}
|
|
940
|
-
});
|
|
941
|
-
const mentionRegexes = buildMentionRegexes(cfg, agentId);
|
|
942
|
-
const wasMentionedByNative = isLineBotMentioned(event.message);
|
|
943
|
-
const wasMentionedByPattern = event.message.type === "text" ? matchesMentionPatterns(rawText, mentionRegexes) : false;
|
|
944
|
-
return {
|
|
945
|
-
canDetectMention: event.message.type === "text",
|
|
946
|
-
wasMentioned: wasMentionedByNative || wasMentionedByPattern,
|
|
947
|
-
explicitlyMentionedBot: wasMentionedByNative,
|
|
948
|
-
hasAnyMention: hasAnyLineMention(event.message),
|
|
949
|
-
implicitMentionKinds: implicitMentionKindWhen("quoted_bot", quotesLineBotMessage(account.accountId, resolveLineQuotedMessageId(event.message)))
|
|
950
|
-
};
|
|
951
|
-
})();
|
|
952
|
-
const resolveAccess = async (contextBinding) => await resolveStableChannelMessageIngress({
|
|
942
|
+
let preparedRoute;
|
|
943
|
+
let mentionFacts;
|
|
944
|
+
const resolveAccess = async (contextBinding) => await getLineRuntime().channel.inbound.ingress.resolveStable({
|
|
953
945
|
channelId: "line",
|
|
954
946
|
accountId: account.accountId,
|
|
955
947
|
identity: {
|
|
@@ -966,10 +958,6 @@ async function resolveLineEventAdmission(event, context) {
|
|
|
966
958
|
id: (groupId ?? roomId ?? senderId) || "unknown"
|
|
967
959
|
},
|
|
968
960
|
...contextBinding ? { contextBinding } : {},
|
|
969
|
-
...isGroup && groupConfig?.enabled === false ? { route: {
|
|
970
|
-
id: "line:group-config",
|
|
971
|
-
enabled: false
|
|
972
|
-
} } : {},
|
|
973
961
|
mentionFacts,
|
|
974
962
|
event: { kind: event.type === "join" ? "system" : event.type },
|
|
975
963
|
dmPolicy,
|
|
@@ -993,35 +981,53 @@ async function resolveLineEventAdmission(event, context) {
|
|
|
993
981
|
groupOwnerAllowFrom: "none"
|
|
994
982
|
}
|
|
995
983
|
});
|
|
996
|
-
|
|
984
|
+
let access = await resolveAccess();
|
|
985
|
+
if (isGroup && event.type === "message" && isLineEventAdmitted(access)) {
|
|
986
|
+
preparedRoute = await prepareLineInboundRoute({
|
|
987
|
+
source: event.source,
|
|
988
|
+
cfg,
|
|
989
|
+
account
|
|
990
|
+
});
|
|
991
|
+
const mentionRegexes = buildMentionRegexes(cfg, preparedRoute.mentionAgentId);
|
|
992
|
+
const wasMentionedByNative = isLineBotMentioned(event.message);
|
|
993
|
+
const wasMentionedByPattern = event.message.type === "text" ? matchesMentionPatterns(rawText, mentionRegexes) : false;
|
|
994
|
+
mentionFacts = {
|
|
995
|
+
canDetectMention: event.message.type === "text",
|
|
996
|
+
wasMentioned: wasMentionedByNative || wasMentionedByPattern,
|
|
997
|
+
explicitlyMentionedBot: wasMentionedByNative,
|
|
998
|
+
hasAnyMention: hasAnyLineMention(event.message),
|
|
999
|
+
implicitMentionKinds: implicitMentionKindWhen("quoted_bot", quotesLineBotMessage(account.accountId, resolveLineQuotedMessageId(event.message)))
|
|
1000
|
+
};
|
|
1001
|
+
access = await resolveAccess();
|
|
1002
|
+
}
|
|
997
1003
|
warnMissingProviderGroupPolicyFallbackOnce({
|
|
998
1004
|
providerMissingFallbackApplied,
|
|
999
1005
|
providerKey: "line",
|
|
1000
1006
|
accountId: account.accountId,
|
|
1001
1007
|
log: (message) => logVerbose(message)
|
|
1002
1008
|
});
|
|
1003
|
-
if (event.type === "join") return
|
|
1009
|
+
if (event.type === "join") return groupPolicy !== "disabled" && (groupPolicy !== "allowlist" || access.state.allowlists.group.hasMatchableEntries) ? {
|
|
1004
1010
|
access,
|
|
1005
1011
|
resolveBoundAccess: resolveAccess
|
|
1006
1012
|
} : null;
|
|
1007
|
-
if (isLineEventAdmitted(access))
|
|
1008
|
-
|
|
1009
|
-
resolveBoundAccess: resolveAccess,
|
|
1010
|
-
mentions: mentionFacts ? {
|
|
1013
|
+
if (isLineEventAdmitted(access)) {
|
|
1014
|
+
const mentions = mentionFacts ? {
|
|
1011
1015
|
...mentionFacts,
|
|
1012
1016
|
wasMentioned: access.activationAccess.effectiveWasMentioned ?? mentionFacts.wasMentioned,
|
|
1013
1017
|
requireMention
|
|
1014
|
-
} : void 0
|
|
1015
|
-
|
|
1018
|
+
} : void 0;
|
|
1019
|
+
return {
|
|
1020
|
+
access,
|
|
1021
|
+
resolveBoundAccess: resolveAccess,
|
|
1022
|
+
mentions,
|
|
1023
|
+
preparedRoute
|
|
1024
|
+
};
|
|
1025
|
+
}
|
|
1016
1026
|
if (access.senderAccess.decision === "allow") {
|
|
1017
1027
|
logVerbose(`Blocked line event (${access.ingress.reasonCode})`);
|
|
1018
1028
|
return null;
|
|
1019
1029
|
}
|
|
1020
1030
|
if (isGroup) {
|
|
1021
|
-
if (groupConfig?.enabled === false) {
|
|
1022
|
-
logVerbose(`Blocked line group ${groupId ?? roomId ?? "unknown"} (group disabled)`);
|
|
1023
|
-
return null;
|
|
1024
|
-
}
|
|
1025
1031
|
if (groupConfig?.allowFrom !== void 0) {
|
|
1026
1032
|
if (!senderId) {
|
|
1027
1033
|
logVerbose("Blocked line group message (group allowFrom override, no sender ID)");
|
|
@@ -1150,6 +1156,7 @@ async function handleMessageEvent(event, context, setParts) {
|
|
|
1150
1156
|
...context.missingParts === void 0 ? {} : { missingParts: context.missingParts },
|
|
1151
1157
|
cfg,
|
|
1152
1158
|
account,
|
|
1159
|
+
preparedRoute: decision.preparedRoute,
|
|
1153
1160
|
commandAuthorized: decision.access.commandAccess.authorized,
|
|
1154
1161
|
resolveChannelIngress: decision.resolveBoundAccess,
|
|
1155
1162
|
inboundHistory: historyReservation.inboundHistory,
|
|
@@ -1168,14 +1175,6 @@ async function handleMessageEvent(event, context, setParts) {
|
|
|
1168
1175
|
historyReservation.release();
|
|
1169
1176
|
}
|
|
1170
1177
|
}
|
|
1171
|
-
async function handleFollowEvent(event, _context) {
|
|
1172
|
-
const { userId } = getLineSourceInfo(event.source);
|
|
1173
|
-
logVerbose(`line: user ${userId ?? "unknown"} followed`);
|
|
1174
|
-
}
|
|
1175
|
-
async function handleUnfollowEvent(event, _context) {
|
|
1176
|
-
const { userId } = getLineSourceInfo(event.source);
|
|
1177
|
-
logVerbose(`line: user ${userId ?? "unknown"} unfollowed`);
|
|
1178
|
-
}
|
|
1179
1178
|
async function handleJoinEvent(event, context) {
|
|
1180
1179
|
const { groupId, roomId, isGroup } = getLineSourceInfo(event.source);
|
|
1181
1180
|
const conversationId = groupId ?? roomId;
|
|
@@ -1213,10 +1212,6 @@ async function handleJoinEvent(event, context) {
|
|
|
1213
1212
|
}
|
|
1214
1213
|
});
|
|
1215
1214
|
}
|
|
1216
|
-
async function handleLeaveEvent(event, _context) {
|
|
1217
|
-
const { groupId, roomId } = getLineSourceInfo(event.source);
|
|
1218
|
-
logVerbose(`line: bot left ${groupId ? `group ${groupId}` : `room ${roomId}`}`);
|
|
1219
|
-
}
|
|
1220
1215
|
/** What a tap that did not answer the question has to tell the person who tapped. */
|
|
1221
1216
|
function lineQuestionOutcomeNotice(status) {
|
|
1222
1217
|
if (status === "already-terminal") return "That question is no longer waiting for an answer.";
|
|
@@ -1291,17 +1286,19 @@ async function handleLineWebhookEvent(event, context, setParts = []) {
|
|
|
1291
1286
|
await handleMessageEvent(event, context, setParts.filter((part) => part.type === "message"));
|
|
1292
1287
|
break;
|
|
1293
1288
|
case "follow":
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
await handleUnfollowEvent(event, context);
|
|
1289
|
+
case "unfollow": {
|
|
1290
|
+
const { userId } = getLineSourceInfo(event.source);
|
|
1291
|
+
logVerbose(`line: user ${userId ?? "unknown"} ${event.type}ed`);
|
|
1298
1292
|
break;
|
|
1293
|
+
}
|
|
1299
1294
|
case "join":
|
|
1300
1295
|
await handleJoinEvent(event, context);
|
|
1301
1296
|
break;
|
|
1302
|
-
case "leave":
|
|
1303
|
-
|
|
1297
|
+
case "leave": {
|
|
1298
|
+
const { groupId, roomId } = getLineSourceInfo(event.source);
|
|
1299
|
+
logVerbose(`line: bot left ${groupId ? `group ${groupId}` : `room ${roomId}`}`);
|
|
1304
1300
|
break;
|
|
1301
|
+
}
|
|
1305
1302
|
case "postback":
|
|
1306
1303
|
await handlePostbackEvent(event, context);
|
|
1307
1304
|
break;
|
|
@@ -1311,40 +1308,17 @@ async function handleLineWebhookEvent(event, context, setParts = []) {
|
|
|
1311
1308
|
//#endregion
|
|
1312
1309
|
//#region extensions/line/src/inbound-image-set.ts
|
|
1313
1310
|
const IMAGE_SET_FLUSH_DELAY_MS = 4e3;
|
|
1314
|
-
/**
|
|
1315
|
-
* Ordered by the index the sender picked, falling back to arrival.
|
|
1316
|
-
*
|
|
1317
|
-
* `index` is optional per part in LINE's contract, so a set can arrive partly
|
|
1318
|
-
* indexed. Choosing the key per pair would make the comparator intransitive and
|
|
1319
|
-
* the resulting order depend on insertion; ranking unindexed parts last keeps
|
|
1320
|
-
* one total order for every mix.
|
|
1321
|
-
*/
|
|
1322
1311
|
function orderedParts(pending) {
|
|
1323
1312
|
return [...pending.parts.values()].toSorted((left, right) => (left.index ?? Number.MAX_SAFE_INTEGER) - (right.index ?? Number.MAX_SAFE_INTEGER) || left.arrivedAt - right.arrivedAt);
|
|
1324
1313
|
}
|
|
1325
|
-
/**
|
|
1326
|
-
* Buffers the parts of a LINE image set until the set is whole.
|
|
1327
|
-
*
|
|
1328
|
-
* The first part becomes the set's holder: its call does not resolve until the
|
|
1329
|
-
* set completes or its wait expires, and it is the one that delivers. Keeping
|
|
1330
|
-
* that call open is what keeps the combined turn inside a live ingress
|
|
1331
|
-
* adoption - a turn dispatched after every part had returned is refused by
|
|
1332
|
-
* admission, so a set that never completes would never be delivered at all.
|
|
1333
|
-
*/
|
|
1334
1314
|
function createLineImageSetIngressBuffer() {
|
|
1335
1315
|
const pendingBySet = /* @__PURE__ */ new Map();
|
|
1336
1316
|
const deliveredBySet = /* @__PURE__ */ new Map();
|
|
1337
1317
|
const pendingKey = (laneKey, senderKey, setId) => `${laneKey}\u0000${senderKey}\u0000${setId}`;
|
|
1338
1318
|
const laneChain = /* @__PURE__ */ new Map();
|
|
1339
1319
|
const enterLane = async (laneKey) => {
|
|
1340
|
-
|
|
1341
|
-
const
|
|
1342
|
-
release = resolve;
|
|
1343
|
-
});
|
|
1344
|
-
let entered = () => {};
|
|
1345
|
-
const turn = new Promise((resolve) => {
|
|
1346
|
-
entered = resolve;
|
|
1347
|
-
});
|
|
1320
|
+
const { promise: held, resolve: release } = createDeferred();
|
|
1321
|
+
const { promise: turn, resolve: entered } = createDeferred();
|
|
1348
1322
|
enqueueKeyedTask({
|
|
1349
1323
|
tails: laneChain,
|
|
1350
1324
|
key: laneKey,
|
|
@@ -1379,10 +1353,7 @@ function createLineImageSetIngressBuffer() {
|
|
|
1379
1353
|
}
|
|
1380
1354
|
return null;
|
|
1381
1355
|
}
|
|
1382
|
-
|
|
1383
|
-
const whole = new Promise((resolve) => {
|
|
1384
|
-
release = resolve;
|
|
1385
|
-
});
|
|
1356
|
+
const { promise: whole, resolve: release } = createDeferred();
|
|
1386
1357
|
const pending = {
|
|
1387
1358
|
parts: /* @__PURE__ */ new Map([[input.messageId, part]]),
|
|
1388
1359
|
total: input.total,
|
|
@@ -1718,7 +1689,7 @@ function createLineBot(opts) {
|
|
|
1718
1689
|
...control.turnAdoptionLifecycle ? { turnAdoptionLifecycle: control.turnAdoptionLifecycle } : {},
|
|
1719
1690
|
...control.missingParts === void 0 ? {} : { missingParts: control.missingParts },
|
|
1720
1691
|
groupHistories,
|
|
1721
|
-
historyLimit: account.config.historyLimit ?? cfg.messages?.groupChat?.historyLimit
|
|
1692
|
+
historyLimit: resolvePromptHistoryLimit(account.config.historyLimit ?? cfg.messages?.groupChat?.historyLimit)
|
|
1722
1693
|
});
|
|
1723
1694
|
}
|
|
1724
1695
|
});
|
|
@@ -1773,9 +1744,9 @@ function parseLineWebhookBody(rawBody) {
|
|
|
1773
1744
|
//#endregion
|
|
1774
1745
|
//#region extensions/line/src/webhook-node.ts
|
|
1775
1746
|
const LINE_WEBHOOK_MAX_BODY_BYTES = 1048576;
|
|
1776
|
-
const LINE_WEBHOOK_PREAUTH_MAX_BODY_BYTES
|
|
1777
|
-
const LINE_WEBHOOK_PREAUTH_BODY_TIMEOUT_MS
|
|
1778
|
-
async function readLineWebhookRequestBody(req, maxBytes = LINE_WEBHOOK_MAX_BODY_BYTES, timeoutMs = LINE_WEBHOOK_PREAUTH_BODY_TIMEOUT_MS
|
|
1747
|
+
const LINE_WEBHOOK_PREAUTH_MAX_BODY_BYTES = 65536;
|
|
1748
|
+
const LINE_WEBHOOK_PREAUTH_BODY_TIMEOUT_MS = 5e3;
|
|
1749
|
+
async function readLineWebhookRequestBody(req, maxBytes = LINE_WEBHOOK_MAX_BODY_BYTES, timeoutMs = LINE_WEBHOOK_PREAUTH_BODY_TIMEOUT_MS) {
|
|
1779
1750
|
return await readRequestBodyWithLimit(req, {
|
|
1780
1751
|
maxBytes,
|
|
1781
1752
|
timeoutMs,
|
|
@@ -1798,6 +1769,12 @@ function createLineNodeWebhookHandler(params) {
|
|
|
1798
1769
|
const maxBodyBytes = params.maxBodyBytes ?? LINE_WEBHOOK_MAX_BODY_BYTES;
|
|
1799
1770
|
const readBody = params.readBody ?? readLineWebhookRequestBody;
|
|
1800
1771
|
return async (req, res) => {
|
|
1772
|
+
const targets = params.getTargets();
|
|
1773
|
+
if (req.method !== "POST" && targets.length === 0) {
|
|
1774
|
+
res.statusCode = 404;
|
|
1775
|
+
res.end("Not Found");
|
|
1776
|
+
return;
|
|
1777
|
+
}
|
|
1801
1778
|
if (req.method === "GET" || req.method === "HEAD") {
|
|
1802
1779
|
if (req.method === "HEAD") {
|
|
1803
1780
|
res.statusCode = 204;
|
|
@@ -1826,14 +1803,22 @@ function createLineNodeWebhookHandler(params) {
|
|
|
1826
1803
|
res.end(JSON.stringify({ error: "Missing X-Line-Signature header" }));
|
|
1827
1804
|
return;
|
|
1828
1805
|
}
|
|
1829
|
-
const rawBody = await readBody(req, Math.min(maxBodyBytes, LINE_WEBHOOK_PREAUTH_MAX_BODY_BYTES
|
|
1830
|
-
|
|
1806
|
+
const rawBody = await readBody(req, Math.min(maxBodyBytes, LINE_WEBHOOK_PREAUTH_MAX_BODY_BYTES), LINE_WEBHOOK_PREAUTH_BODY_TIMEOUT_MS);
|
|
1807
|
+
const match = resolveSingleWebhookTarget(targets, (target) => validateLineSignature(rawBody, signature, target.channelSecret));
|
|
1808
|
+
if (match.kind === "none") {
|
|
1831
1809
|
logVerbose("line: webhook signature validation failed");
|
|
1832
1810
|
res.statusCode = 401;
|
|
1833
1811
|
res.setHeader("Content-Type", "application/json");
|
|
1834
1812
|
res.end(JSON.stringify({ error: "Invalid signature" }));
|
|
1835
1813
|
return;
|
|
1836
1814
|
}
|
|
1815
|
+
if (match.kind === "ambiguous") {
|
|
1816
|
+
logVerbose("line: webhook signature matched multiple accounts");
|
|
1817
|
+
res.statusCode = 401;
|
|
1818
|
+
res.setHeader("Content-Type", "application/json");
|
|
1819
|
+
res.end(JSON.stringify({ error: "Ambiguous webhook target" }));
|
|
1820
|
+
return;
|
|
1821
|
+
}
|
|
1837
1822
|
const body = parseLineWebhookBody(rawBody);
|
|
1838
1823
|
if (!body) {
|
|
1839
1824
|
res.statusCode = 400;
|
|
@@ -1841,10 +1826,9 @@ function createLineNodeWebhookHandler(params) {
|
|
|
1841
1826
|
res.end(JSON.stringify({ error: "Invalid webhook payload" }));
|
|
1842
1827
|
return;
|
|
1843
1828
|
}
|
|
1844
|
-
params.onRequestAuthenticated?.();
|
|
1845
1829
|
if (body.events && body.events.length > 0) {
|
|
1846
1830
|
logVerbose(`line: received ${body.events.length} webhook events`);
|
|
1847
|
-
await
|
|
1831
|
+
if (await match.target.bot.handleWebhook(body) === "durable") res.setHeader("x-openclaw-delivery-accepted", "durable");
|
|
1848
1832
|
}
|
|
1849
1833
|
res.statusCode = 200;
|
|
1850
1834
|
res.setHeader("Content-Type", "application/json");
|
|
@@ -1863,8 +1847,6 @@ function createLineNodeWebhookHandler(params) {
|
|
|
1863
1847
|
//#endregion
|
|
1864
1848
|
//#region extensions/line/src/monitor.ts
|
|
1865
1849
|
const lineWebhookInFlightLimiter = createWebhookInFlightLimiter();
|
|
1866
|
-
const LINE_WEBHOOK_PREAUTH_MAX_BODY_BYTES = 65536;
|
|
1867
|
-
const LINE_WEBHOOK_PREAUTH_BODY_TIMEOUT_MS = 5e3;
|
|
1868
1850
|
async function registerLineWebhookTarget(params, bot) {
|
|
1869
1851
|
try {
|
|
1870
1852
|
return registerWebhookTargetWithPluginRoute(params);
|
|
@@ -2017,10 +1999,9 @@ async function monitorLineProvider(opts) {
|
|
|
2017
1999
|
});
|
|
2018
2000
|
const normalizedPath = resolveLineWebhookPath(webhookPath);
|
|
2019
2001
|
const webhookRouteKey = canonicalizeWebhookRouteKey(normalizedPath);
|
|
2020
|
-
const
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
runtime: target.runtime
|
|
2002
|
+
const handleWebhook = createLineNodeWebhookHandler({
|
|
2003
|
+
getTargets: () => lineWebhookTargets.get(webhookRouteKey) ?? [],
|
|
2004
|
+
runtime
|
|
2024
2005
|
});
|
|
2025
2006
|
const { unregister: unregisterHttp } = await registerLineWebhookTarget({
|
|
2026
2007
|
targetsByPath: lineWebhookTargets,
|
|
@@ -2039,15 +2020,8 @@ async function monitorLineProvider(opts) {
|
|
|
2039
2020
|
log: (msg) => logVerbose(msg),
|
|
2040
2021
|
throwOnFailure: true,
|
|
2041
2022
|
handler: async (req, res) => {
|
|
2042
|
-
const targets = lineWebhookTargets.get(webhookRouteKey) ?? [];
|
|
2043
|
-
const firstTarget = targets[0];
|
|
2044
2023
|
if (req.method !== "POST") {
|
|
2045
|
-
|
|
2046
|
-
res.statusCode = 404;
|
|
2047
|
-
res.end("Not Found");
|
|
2048
|
-
return;
|
|
2049
|
-
}
|
|
2050
|
-
await createScopedLineWebhookHandler(firstTarget)(req, res);
|
|
2024
|
+
await handleWebhook(req, res);
|
|
2051
2025
|
return;
|
|
2052
2026
|
}
|
|
2053
2027
|
const requestLifecycle = beginWebhookRequestPipelineOrReject({
|
|
@@ -2058,53 +2032,7 @@ async function monitorLineProvider(opts) {
|
|
|
2058
2032
|
});
|
|
2059
2033
|
if (!requestLifecycle.ok) return;
|
|
2060
2034
|
try {
|
|
2061
|
-
|
|
2062
|
-
const signature = typeof signatureHeader === "string" ? signatureHeader.trim() : Array.isArray(signatureHeader) ? (signatureHeader[0] ?? "").trim() : "";
|
|
2063
|
-
if (!signature) {
|
|
2064
|
-
logVerbose("line: webhook missing X-Line-Signature header");
|
|
2065
|
-
res.statusCode = 400;
|
|
2066
|
-
res.setHeader("Content-Type", "application/json");
|
|
2067
|
-
res.end(JSON.stringify({ error: "Missing X-Line-Signature header" }));
|
|
2068
|
-
return;
|
|
2069
|
-
}
|
|
2070
|
-
const rawBody = await readLineWebhookRequestBody(req, LINE_WEBHOOK_PREAUTH_MAX_BODY_BYTES, LINE_WEBHOOK_PREAUTH_BODY_TIMEOUT_MS);
|
|
2071
|
-
const match = resolveSingleWebhookTarget(targets, (target) => validateLineSignature(rawBody, signature, target.channelSecret));
|
|
2072
|
-
if (match.kind === "none") {
|
|
2073
|
-
logVerbose("line: webhook signature validation failed");
|
|
2074
|
-
res.statusCode = 401;
|
|
2075
|
-
res.setHeader("Content-Type", "application/json");
|
|
2076
|
-
res.end(JSON.stringify({ error: "Invalid signature" }));
|
|
2077
|
-
return;
|
|
2078
|
-
}
|
|
2079
|
-
if (match.kind === "ambiguous") {
|
|
2080
|
-
logVerbose("line: webhook signature matched multiple accounts");
|
|
2081
|
-
res.statusCode = 401;
|
|
2082
|
-
res.setHeader("Content-Type", "application/json");
|
|
2083
|
-
res.end(JSON.stringify({ error: "Ambiguous webhook target" }));
|
|
2084
|
-
return;
|
|
2085
|
-
}
|
|
2086
|
-
const body = parseLineWebhookBody(rawBody);
|
|
2087
|
-
if (!body) {
|
|
2088
|
-
res.statusCode = 400;
|
|
2089
|
-
res.setHeader("Content-Type", "application/json");
|
|
2090
|
-
res.end(JSON.stringify({ error: "Invalid webhook payload" }));
|
|
2091
|
-
return;
|
|
2092
|
-
}
|
|
2093
|
-
if (body.events && body.events.length > 0) {
|
|
2094
|
-
logVerbose(`line: received ${body.events.length} webhook events`);
|
|
2095
|
-
if (await match.target.bot.handleWebhook(body) === "durable") res.setHeader("x-openclaw-delivery-accepted", "durable");
|
|
2096
|
-
}
|
|
2097
|
-
res.statusCode = 200;
|
|
2098
|
-
res.setHeader("Content-Type", "application/json");
|
|
2099
|
-
res.end(JSON.stringify({ status: "ok" }));
|
|
2100
|
-
} catch (err) {
|
|
2101
|
-
if (await rejectLineWebhookRequest(req, res, err)) return;
|
|
2102
|
-
runtime.error?.(danger(`line webhook error: ${formatErrorMessage(err)}`));
|
|
2103
|
-
if (!res.headersSent) {
|
|
2104
|
-
res.statusCode = 500;
|
|
2105
|
-
res.setHeader("Content-Type", "application/json");
|
|
2106
|
-
res.end(JSON.stringify({ error: "Internal server error" }));
|
|
2107
|
-
}
|
|
2035
|
+
await handleWebhook(req, res);
|
|
2108
2036
|
} finally {
|
|
2109
2037
|
requestLifecycle.release();
|
|
2110
2038
|
}
|
|
@@ -2143,4 +2071,4 @@ async function monitorLineProvider(opts) {
|
|
|
2143
2071
|
};
|
|
2144
2072
|
}
|
|
2145
2073
|
//#endregion
|
|
2146
|
-
export {
|
|
2074
|
+
export { monitorLineProvider as t };
|