@openclaw/feishu 2026.7.1 → 2026.7.2-beta.2
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/{accounts-Bs5uJ4h0.js → accounts-BDoGHJDk.js} +29 -54
- package/dist/api.js +351 -195
- package/dist/{app-registration-BwQ-aGTe.js → app-registration-BzkyrVZu.js} +11 -11
- package/dist/{channel-DRQRQQQ3.js → channel-X30GQVwc.js} +591 -398
- package/dist/channel-plugin-api.js +1 -1
- package/dist/{channel.runtime-pvr-Y5ji.js → channel.runtime-By2uqa3Q.js} +272 -107
- package/dist/{client-B7EAV_Ss.js → client-87BmeMpj.js} +55 -29
- package/dist/contract-api.js +1 -1
- package/dist/{conversation-id-CdLdoot3.js → conversation-id-BeJL-wq7.js} +3 -0
- package/dist/doctor-contract-DXH5hux1.js +97 -0
- package/dist/doctor-contract-api.js +2 -0
- package/dist/{drive-D0lIhxqZ.js → drive-B4E8OXZ0.js} +181 -33
- package/dist/{monitor-CsbheK9J.js → monitor-CHl0bWzb.js} +3 -3
- package/dist/{monitor.account-Dr7do33p.js → monitor.account-BSRV2hIF.js} +529 -549
- package/dist/monitor.startup-Cy8NPGAX.js +43 -0
- package/dist/{probe-Dxyo9zlw.js → probe-BgboTHIn.js} +3 -6
- package/dist/{secret-contract-DLaBl9m4.js → secret-contract-DnlMcrn5.js} +14 -69
- package/dist/secret-contract-api.js +1 -1
- package/dist/{send-Be2GMA6Z.js → send-DrWM_Ilf.js} +67 -40
- package/dist/send-result-DsqTk27v.js +770 -0
- package/dist/{session-conversation-BYuoVJwl.js → session-conversation-BksWrfzm.js} +1 -1
- package/dist/session-key-api.js +1 -1
- package/dist/setup-api.js +1 -1
- package/dist/setup-entry.js +0 -5
- package/dist/{subagent-hooks-B2iWPYJ1.js → subagent-hooks-BKTOxB-T.js} +9 -5
- package/dist/subagent-hooks-api.js +1 -1
- package/node_modules/@types/debug/LICENSE +21 -0
- package/node_modules/@types/debug/README.md +69 -0
- package/node_modules/@types/debug/index.d.ts +50 -0
- package/node_modules/@types/debug/package.json +58 -0
- package/node_modules/@types/mdast/LICENSE +21 -0
- package/node_modules/@types/mdast/README.md +15 -0
- package/node_modules/@types/mdast/index.d.ts +1123 -0
- package/node_modules/@types/mdast/package.json +47 -0
- package/node_modules/@types/ms/LICENSE +21 -0
- package/node_modules/@types/ms/README.md +82 -0
- package/node_modules/@types/ms/index.d.ts +63 -0
- package/node_modules/@types/ms/package.json +26 -0
- package/node_modules/@types/unist/LICENSE +21 -0
- package/node_modules/@types/unist/README.md +15 -0
- package/node_modules/@types/unist/index.d.ts +119 -0
- package/node_modules/@types/unist/package.json +60 -0
- package/node_modules/character-entities/index.d.ts +6 -0
- package/node_modules/character-entities/index.js +2132 -0
- package/node_modules/character-entities/license +22 -0
- package/node_modules/character-entities/package.json +78 -0
- package/node_modules/character-entities/readme.md +152 -0
- package/node_modules/debug/LICENSE +20 -0
- package/node_modules/debug/README.md +481 -0
- package/node_modules/debug/package.json +64 -0
- package/node_modules/debug/src/browser.js +272 -0
- package/node_modules/debug/src/common.js +292 -0
- package/node_modules/debug/src/index.js +10 -0
- package/node_modules/debug/src/node.js +263 -0
- package/node_modules/decode-named-character-reference/index.d.ts +13 -0
- package/node_modules/decode-named-character-reference/index.d.ts.map +1 -0
- package/node_modules/decode-named-character-reference/index.dom.d.ts +6 -0
- package/node_modules/decode-named-character-reference/index.dom.d.ts.map +1 -0
- package/node_modules/decode-named-character-reference/index.dom.js +32 -0
- package/node_modules/decode-named-character-reference/index.js +19 -0
- package/node_modules/decode-named-character-reference/license +22 -0
- package/node_modules/decode-named-character-reference/package.json +90 -0
- package/node_modules/decode-named-character-reference/readme.md +136 -0
- package/node_modules/dequal/dist/index.js +86 -0
- package/node_modules/dequal/dist/index.min.js +1 -0
- package/node_modules/dequal/dist/index.mjs +84 -0
- package/node_modules/dequal/index.d.ts +1 -0
- package/node_modules/dequal/license +21 -0
- package/node_modules/dequal/lite/index.d.ts +1 -0
- package/node_modules/dequal/lite/index.js +31 -0
- package/node_modules/dequal/lite/index.min.js +1 -0
- package/node_modules/dequal/lite/index.mjs +29 -0
- package/node_modules/dequal/package.json +57 -0
- package/node_modules/dequal/readme.md +112 -0
- package/node_modules/devlop/lib/default.js +9 -0
- package/node_modules/devlop/lib/development.d.ts +84 -0
- package/node_modules/devlop/lib/development.js +238 -0
- package/node_modules/devlop/license +22 -0
- package/node_modules/devlop/package.json +80 -0
- package/node_modules/devlop/readme.md +360 -0
- package/node_modules/longest-streak/index.d.ts +11 -0
- package/node_modules/longest-streak/index.js +36 -0
- package/node_modules/longest-streak/license +22 -0
- package/node_modules/longest-streak/package.json +73 -0
- package/node_modules/longest-streak/readme.md +150 -0
- package/node_modules/markdown-table/index.d.ts +171 -0
- package/node_modules/markdown-table/index.d.ts.map +1 -0
- package/node_modules/markdown-table/index.js +393 -0
- package/node_modules/markdown-table/license +22 -0
- package/node_modules/markdown-table/package.json +77 -0
- package/node_modules/markdown-table/readme.md +344 -0
- package/node_modules/mdast-util-from-markdown/dev/index.d.ts +23 -0
- package/node_modules/mdast-util-from-markdown/dev/index.js +2 -0
- package/node_modules/mdast-util-from-markdown/dev/lib/index.d.ts +53 -0
- package/node_modules/mdast-util-from-markdown/dev/lib/index.d.ts.map +1 -0
- package/node_modules/mdast-util-from-markdown/dev/lib/index.js +1348 -0
- package/node_modules/mdast-util-from-markdown/dev/lib/types.d.ts +295 -0
- package/node_modules/mdast-util-from-markdown/dev/lib/types.js +2 -0
- package/node_modules/mdast-util-from-markdown/index.d.ts +23 -0
- package/node_modules/mdast-util-from-markdown/index.js +2 -0
- package/node_modules/mdast-util-from-markdown/lib/index.d.ts +53 -0
- package/node_modules/mdast-util-from-markdown/lib/index.d.ts.map +1 -0
- package/node_modules/mdast-util-from-markdown/lib/index.js +1177 -0
- package/node_modules/mdast-util-from-markdown/lib/types.d.ts +295 -0
- package/node_modules/mdast-util-from-markdown/lib/types.js +2 -0
- package/node_modules/mdast-util-from-markdown/license +22 -0
- package/node_modules/mdast-util-from-markdown/package.json +99 -0
- package/node_modules/mdast-util-from-markdown/readme.md +535 -0
- package/node_modules/mdast-util-gfm-table/index.d.ts +54 -0
- package/node_modules/mdast-util-gfm-table/index.js +2 -0
- package/node_modules/mdast-util-gfm-table/lib/index.d.ts +51 -0
- package/node_modules/mdast-util-gfm-table/lib/index.js +300 -0
- package/node_modules/mdast-util-gfm-table/license +22 -0
- package/node_modules/mdast-util-gfm-table/package.json +101 -0
- package/node_modules/mdast-util-gfm-table/readme.md +605 -0
- package/node_modules/mdast-util-phrasing/index.d.ts +1 -0
- package/node_modules/mdast-util-phrasing/index.js +1 -0
- package/node_modules/mdast-util-phrasing/lib/index.d.ts +3 -0
- package/node_modules/mdast-util-phrasing/lib/index.js +45 -0
- package/node_modules/mdast-util-phrasing/license +23 -0
- package/node_modules/mdast-util-phrasing/package.json +78 -0
- package/node_modules/mdast-util-phrasing/readme.md +200 -0
- package/node_modules/mdast-util-to-markdown/index.d.ts +16 -0
- package/node_modules/mdast-util-to-markdown/index.js +3 -0
- package/node_modules/mdast-util-to-markdown/lib/configure.d.ts +9 -0
- package/node_modules/mdast-util-to-markdown/lib/configure.d.ts.map +1 -0
- package/node_modules/mdast-util-to-markdown/lib/configure.js +79 -0
- package/node_modules/mdast-util-to-markdown/lib/handle/blockquote.d.ts +17 -0
- package/node_modules/mdast-util-to-markdown/lib/handle/blockquote.d.ts.map +1 -0
- package/node_modules/mdast-util-to-markdown/lib/handle/blockquote.js +29 -0
- package/node_modules/mdast-util-to-markdown/lib/handle/break.d.ts +13 -0
- package/node_modules/mdast-util-to-markdown/lib/handle/break.d.ts.map +1 -0
- package/node_modules/mdast-util-to-markdown/lib/handle/break.js +30 -0
- package/node_modules/mdast-util-to-markdown/lib/handle/code.d.ts +13 -0
- package/node_modules/mdast-util-to-markdown/lib/handle/code.d.ts.map +1 -0
- package/node_modules/mdast-util-to-markdown/lib/handle/code.js +75 -0
- package/node_modules/mdast-util-to-markdown/lib/handle/definition.d.ts +13 -0
- package/node_modules/mdast-util-to-markdown/lib/handle/definition.d.ts.map +1 -0
- package/node_modules/mdast-util-to-markdown/lib/handle/definition.js +76 -0
- package/node_modules/mdast-util-to-markdown/lib/handle/emphasis.d.ts +24 -0
- package/node_modules/mdast-util-to-markdown/lib/handle/emphasis.d.ts.map +1 -0
- package/node_modules/mdast-util-to-markdown/lib/handle/emphasis.js +69 -0
- package/node_modules/mdast-util-to-markdown/lib/handle/heading.d.ts +13 -0
- package/node_modules/mdast-util-to-markdown/lib/handle/heading.d.ts.map +1 -0
- package/node_modules/mdast-util-to-markdown/lib/handle/heading.js +75 -0
- package/node_modules/mdast-util-to-markdown/lib/handle/html.d.ts +15 -0
- package/node_modules/mdast-util-to-markdown/lib/handle/html.d.ts.map +1 -0
- package/node_modules/mdast-util-to-markdown/lib/handle/html.js +20 -0
- package/node_modules/mdast-util-to-markdown/lib/handle/image-reference.d.ts +21 -0
- package/node_modules/mdast-util-to-markdown/lib/handle/image-reference.d.ts.map +1 -0
- package/node_modules/mdast-util-to-markdown/lib/handle/image-reference.js +63 -0
- package/node_modules/mdast-util-to-markdown/lib/handle/image.d.ts +21 -0
- package/node_modules/mdast-util-to-markdown/lib/handle/image.d.ts.map +1 -0
- package/node_modules/mdast-util-to-markdown/lib/handle/image.js +82 -0
- package/node_modules/mdast-util-to-markdown/lib/handle/index.d.ts +42 -0
- package/node_modules/mdast-util-to-markdown/lib/handle/index.d.ts.map +1 -0
- package/node_modules/mdast-util-to-markdown/lib/handle/index.js +45 -0
- package/node_modules/mdast-util-to-markdown/lib/handle/inline-code.d.ts +19 -0
- package/node_modules/mdast-util-to-markdown/lib/handle/inline-code.d.ts.map +1 -0
- package/node_modules/mdast-util-to-markdown/lib/handle/inline-code.js +76 -0
- package/node_modules/mdast-util-to-markdown/lib/handle/link-reference.d.ts +21 -0
- package/node_modules/mdast-util-to-markdown/lib/handle/link-reference.d.ts.map +1 -0
- package/node_modules/mdast-util-to-markdown/lib/handle/link-reference.js +63 -0
- package/node_modules/mdast-util-to-markdown/lib/handle/link.d.ts +24 -0
- package/node_modules/mdast-util-to-markdown/lib/handle/link.d.ts.map +1 -0
- package/node_modules/mdast-util-to-markdown/lib/handle/link.js +114 -0
- package/node_modules/mdast-util-to-markdown/lib/handle/list-item.d.ts +13 -0
- package/node_modules/mdast-util-to-markdown/lib/handle/list-item.d.ts.map +1 -0
- package/node_modules/mdast-util-to-markdown/lib/handle/list-item.js +62 -0
- package/node_modules/mdast-util-to-markdown/lib/handle/list.d.ts +13 -0
- package/node_modules/mdast-util-to-markdown/lib/handle/list.d.ts.map +1 -0
- package/node_modules/mdast-util-to-markdown/lib/handle/list.js +100 -0
- package/node_modules/mdast-util-to-markdown/lib/handle/paragraph.d.ts +17 -0
- package/node_modules/mdast-util-to-markdown/lib/handle/paragraph.d.ts.map +1 -0
- package/node_modules/mdast-util-to-markdown/lib/handle/paragraph.js +20 -0
- package/node_modules/mdast-util-to-markdown/lib/handle/root.d.ts +13 -0
- package/node_modules/mdast-util-to-markdown/lib/handle/root.d.ts.map +1 -0
- package/node_modules/mdast-util-to-markdown/lib/handle/root.js +23 -0
- package/node_modules/mdast-util-to-markdown/lib/handle/strong.d.ts +24 -0
- package/node_modules/mdast-util-to-markdown/lib/handle/strong.d.ts.map +1 -0
- package/node_modules/mdast-util-to-markdown/lib/handle/strong.js +69 -0
- package/node_modules/mdast-util-to-markdown/lib/handle/text.d.ts +17 -0
- package/node_modules/mdast-util-to-markdown/lib/handle/text.d.ts.map +1 -0
- package/node_modules/mdast-util-to-markdown/lib/handle/text.js +15 -0
- package/node_modules/mdast-util-to-markdown/lib/handle/thematic-break.d.ts +11 -0
- package/node_modules/mdast-util-to-markdown/lib/handle/thematic-break.d.ts.map +1 -0
- package/node_modules/mdast-util-to-markdown/lib/handle/thematic-break.js +21 -0
- package/node_modules/mdast-util-to-markdown/lib/index.d.ts +14 -0
- package/node_modules/mdast-util-to-markdown/lib/index.d.ts.map +1 -0
- package/node_modules/mdast-util-to-markdown/lib/index.js +187 -0
- package/node_modules/mdast-util-to-markdown/lib/join.d.ts +4 -0
- package/node_modules/mdast-util-to-markdown/lib/join.d.ts.map +1 -0
- package/node_modules/mdast-util-to-markdown/lib/join.js +39 -0
- package/node_modules/mdast-util-to-markdown/lib/types.d.ts +965 -0
- package/node_modules/mdast-util-to-markdown/lib/types.js +2 -0
- package/node_modules/mdast-util-to-markdown/lib/unsafe.d.ts +4 -0
- package/node_modules/mdast-util-to-markdown/lib/unsafe.d.ts.map +1 -0
- package/node_modules/mdast-util-to-markdown/lib/unsafe.js +146 -0
- package/node_modules/mdast-util-to-markdown/lib/util/association.d.ts +2 -0
- package/node_modules/mdast-util-to-markdown/lib/util/association.d.ts.map +1 -0
- package/node_modules/mdast-util-to-markdown/lib/util/association.js +33 -0
- package/node_modules/mdast-util-to-markdown/lib/util/check-bullet-ordered.d.ts +11 -0
- package/node_modules/mdast-util-to-markdown/lib/util/check-bullet-ordered.d.ts.map +1 -0
- package/node_modules/mdast-util-to-markdown/lib/util/check-bullet-ordered.js +21 -0
- package/node_modules/mdast-util-to-markdown/lib/util/check-bullet-other.d.ts +8 -0
- package/node_modules/mdast-util-to-markdown/lib/util/check-bullet-other.d.ts.map +1 -0
- package/node_modules/mdast-util-to-markdown/lib/util/check-bullet-other.js +38 -0
- package/node_modules/mdast-util-to-markdown/lib/util/check-bullet.d.ts +11 -0
- package/node_modules/mdast-util-to-markdown/lib/util/check-bullet.d.ts.map +1 -0
- package/node_modules/mdast-util-to-markdown/lib/util/check-bullet.js +21 -0
- package/node_modules/mdast-util-to-markdown/lib/util/check-emphasis.d.ts +11 -0
- package/node_modules/mdast-util-to-markdown/lib/util/check-emphasis.d.ts.map +1 -0
- package/node_modules/mdast-util-to-markdown/lib/util/check-emphasis.js +21 -0
- package/node_modules/mdast-util-to-markdown/lib/util/check-fence.d.ts +11 -0
- package/node_modules/mdast-util-to-markdown/lib/util/check-fence.d.ts.map +1 -0
- package/node_modules/mdast-util-to-markdown/lib/util/check-fence.js +21 -0
- package/node_modules/mdast-util-to-markdown/lib/util/check-list-item-indent.d.ts +11 -0
- package/node_modules/mdast-util-to-markdown/lib/util/check-list-item-indent.d.ts.map +1 -0
- package/node_modules/mdast-util-to-markdown/lib/util/check-list-item-indent.js +21 -0
- package/node_modules/mdast-util-to-markdown/lib/util/check-quote.d.ts +11 -0
- package/node_modules/mdast-util-to-markdown/lib/util/check-quote.d.ts.map +1 -0
- package/node_modules/mdast-util-to-markdown/lib/util/check-quote.js +21 -0
- package/node_modules/mdast-util-to-markdown/lib/util/check-rule-repetition.d.ts +11 -0
- package/node_modules/mdast-util-to-markdown/lib/util/check-rule-repetition.d.ts.map +1 -0
- package/node_modules/mdast-util-to-markdown/lib/util/check-rule-repetition.js +21 -0
- package/node_modules/mdast-util-to-markdown/lib/util/check-rule.d.ts +11 -0
- package/node_modules/mdast-util-to-markdown/lib/util/check-rule.d.ts.map +1 -0
- package/node_modules/mdast-util-to-markdown/lib/util/check-rule.js +21 -0
- package/node_modules/mdast-util-to-markdown/lib/util/check-strong.d.ts +11 -0
- package/node_modules/mdast-util-to-markdown/lib/util/check-strong.d.ts.map +1 -0
- package/node_modules/mdast-util-to-markdown/lib/util/check-strong.js +21 -0
- package/node_modules/mdast-util-to-markdown/lib/util/compile-pattern.d.ts +2 -0
- package/node_modules/mdast-util-to-markdown/lib/util/compile-pattern.d.ts.map +1 -0
- package/node_modules/mdast-util-to-markdown/lib/util/compile-pattern.js +24 -0
- package/node_modules/mdast-util-to-markdown/lib/util/container-flow.d.ts +19 -0
- package/node_modules/mdast-util-to-markdown/lib/util/container-flow.d.ts.map +1 -0
- package/node_modules/mdast-util-to-markdown/lib/util/container-flow.js +84 -0
- package/node_modules/mdast-util-to-markdown/lib/util/container-phrasing.d.ts +19 -0
- package/node_modules/mdast-util-to-markdown/lib/util/container-phrasing.d.ts.map +1 -0
- package/node_modules/mdast-util-to-markdown/lib/util/container-phrasing.js +125 -0
- package/node_modules/mdast-util-to-markdown/lib/util/emphasis-strong-marker.d.ts +7 -0
- package/node_modules/mdast-util-to-markdown/lib/util/emphasis-strong-marker.d.ts.map +1 -0
- package/node_modules/mdast-util-to-markdown/lib/util/encode-character-reference.d.ts +10 -0
- package/node_modules/mdast-util-to-markdown/lib/util/encode-character-reference.d.ts.map +1 -0
- package/node_modules/mdast-util-to-markdown/lib/util/encode-character-reference.js +11 -0
- package/node_modules/mdast-util-to-markdown/lib/util/encode-info.d.ts +33 -0
- package/node_modules/mdast-util-to-markdown/lib/util/encode-info.d.ts.map +1 -0
- package/node_modules/mdast-util-to-markdown/lib/util/encode-info.js +82 -0
- package/node_modules/mdast-util-to-markdown/lib/util/format-code-as-indented.d.ts +13 -0
- package/node_modules/mdast-util-to-markdown/lib/util/format-code-as-indented.d.ts.map +1 -0
- package/node_modules/mdast-util-to-markdown/lib/util/format-code-as-indented.js +22 -0
- package/node_modules/mdast-util-to-markdown/lib/util/format-heading-as-setext.d.ts +9 -0
- package/node_modules/mdast-util-to-markdown/lib/util/format-heading-as-setext.d.ts.map +1 -0
- package/node_modules/mdast-util-to-markdown/lib/util/format-heading-as-setext.js +34 -0
- package/node_modules/mdast-util-to-markdown/lib/util/format-link-as-autolink.d.ts +9 -0
- package/node_modules/mdast-util-to-markdown/lib/util/format-link-as-autolink.d.ts.map +1 -0
- package/node_modules/mdast-util-to-markdown/lib/util/format-link-as-autolink.js +34 -0
- package/node_modules/mdast-util-to-markdown/lib/util/indent-lines.d.ts +2 -0
- package/node_modules/mdast-util-to-markdown/lib/util/indent-lines.d.ts.map +1 -0
- package/node_modules/mdast-util-to-markdown/lib/util/indent-lines.js +35 -0
- package/node_modules/mdast-util-to-markdown/lib/util/pattern-in-scope.d.ts +12 -0
- package/node_modules/mdast-util-to-markdown/lib/util/pattern-in-scope.d.ts.map +1 -0
- package/node_modules/mdast-util-to-markdown/lib/util/pattern-in-scope.js +41 -0
- package/node_modules/mdast-util-to-markdown/lib/util/safe.d.ts +29 -0
- package/node_modules/mdast-util-to-markdown/lib/util/safe.d.ts.map +1 -0
- package/node_modules/mdast-util-to-markdown/lib/util/safe.js +174 -0
- package/node_modules/mdast-util-to-markdown/lib/util/track.d.ts +2 -0
- package/node_modules/mdast-util-to-markdown/lib/util/track.d.ts.map +1 -0
- package/node_modules/mdast-util-to-markdown/lib/util/track.js +55 -0
- package/node_modules/mdast-util-to-markdown/license +22 -0
- package/node_modules/mdast-util-to-markdown/package.json +132 -0
- package/node_modules/mdast-util-to-markdown/readme.md +750 -0
- package/node_modules/mdast-util-to-string/index.d.ts +2 -0
- package/node_modules/mdast-util-to-string/index.js +5 -0
- package/node_modules/mdast-util-to-string/lib/index.d.ts +31 -0
- package/node_modules/mdast-util-to-string/lib/index.js +108 -0
- package/node_modules/mdast-util-to-string/license +22 -0
- package/node_modules/mdast-util-to-string/package.json +78 -0
- package/node_modules/mdast-util-to-string/readme.md +218 -0
- package/node_modules/micromark/dev/index.d.ts +82 -0
- package/node_modules/micromark/dev/index.d.ts.map +1 -0
- package/node_modules/micromark/dev/index.js +68 -0
- package/node_modules/micromark/dev/lib/compile.d.ts +16 -0
- package/node_modules/micromark/dev/lib/compile.d.ts.map +1 -0
- package/node_modules/micromark/dev/lib/compile.js +1152 -0
- package/node_modules/micromark/dev/lib/constructs.d.ts +73 -0
- package/node_modules/micromark/dev/lib/constructs.d.ts.map +1 -0
- package/node_modules/micromark/dev/lib/constructs.js +101 -0
- package/node_modules/micromark/dev/lib/create-tokenizer.d.ts +46 -0
- package/node_modules/micromark/dev/lib/create-tokenizer.d.ts.map +1 -0
- package/node_modules/micromark/dev/lib/create-tokenizer.js +717 -0
- package/node_modules/micromark/dev/lib/initialize/content.d.ts +4 -0
- package/node_modules/micromark/dev/lib/initialize/content.d.ts.map +1 -0
- package/node_modules/micromark/dev/lib/initialize/content.js +99 -0
- package/node_modules/micromark/dev/lib/initialize/document.d.ts +10 -0
- package/node_modules/micromark/dev/lib/initialize/document.d.ts.map +1 -0
- package/node_modules/micromark/dev/lib/initialize/document.js +445 -0
- package/node_modules/micromark/dev/lib/initialize/flow.d.ts +4 -0
- package/node_modules/micromark/dev/lib/initialize/flow.d.ts.map +1 -0
- package/node_modules/micromark/dev/lib/initialize/flow.js +86 -0
- package/node_modules/micromark/dev/lib/initialize/text.d.ts +8 -0
- package/node_modules/micromark/dev/lib/initialize/text.d.ts.map +1 -0
- package/node_modules/micromark/dev/lib/initialize/text.js +244 -0
- package/node_modules/micromark/dev/lib/parse.d.ts +10 -0
- package/node_modules/micromark/dev/lib/parse.d.ts.map +1 -0
- package/node_modules/micromark/dev/lib/parse.js +58 -0
- package/node_modules/micromark/dev/lib/postprocess.d.ts +9 -0
- package/node_modules/micromark/dev/lib/postprocess.d.ts.map +1 -0
- package/node_modules/micromark/dev/lib/postprocess.js +19 -0
- package/node_modules/micromark/dev/lib/preprocess.d.ts +13 -0
- package/node_modules/micromark/dev/lib/preprocess.d.ts.map +1 -0
- package/node_modules/micromark/dev/lib/preprocess.js +141 -0
- package/node_modules/micromark/dev/stream.d.ts +35 -0
- package/node_modules/micromark/dev/stream.d.ts.map +1 -0
- package/node_modules/micromark/dev/stream.js +270 -0
- package/node_modules/micromark/index.d.ts +82 -0
- package/node_modules/micromark/index.d.ts.map +1 -0
- package/node_modules/micromark/index.js +60 -0
- package/node_modules/micromark/lib/compile.d.ts +16 -0
- package/node_modules/micromark/lib/compile.d.ts.map +1 -0
- package/node_modules/micromark/lib/compile.js +1060 -0
- package/node_modules/micromark/lib/constructs.d.ts +73 -0
- package/node_modules/micromark/lib/constructs.d.ts.map +1 -0
- package/node_modules/micromark/lib/constructs.js +85 -0
- package/node_modules/micromark/lib/create-tokenizer.d.ts +46 -0
- package/node_modules/micromark/lib/create-tokenizer.d.ts.map +1 -0
- package/node_modules/micromark/lib/create-tokenizer.js +611 -0
- package/node_modules/micromark/lib/initialize/content.d.ts +4 -0
- package/node_modules/micromark/lib/initialize/content.d.ts.map +1 -0
- package/node_modules/micromark/lib/initialize/content.js +79 -0
- package/node_modules/micromark/lib/initialize/document.d.ts +10 -0
- package/node_modules/micromark/lib/initialize/document.d.ts.map +1 -0
- package/node_modules/micromark/lib/initialize/document.js +362 -0
- package/node_modules/micromark/lib/initialize/flow.d.ts +4 -0
- package/node_modules/micromark/lib/initialize/flow.d.ts.map +1 -0
- package/node_modules/micromark/lib/initialize/flow.js +58 -0
- package/node_modules/micromark/lib/initialize/text.d.ts +8 -0
- package/node_modules/micromark/lib/initialize/text.d.ts.map +1 -0
- package/node_modules/micromark/lib/initialize/text.js +212 -0
- package/node_modules/micromark/lib/parse.d.ts +10 -0
- package/node_modules/micromark/lib/parse.d.ts.map +1 -0
- package/node_modules/micromark/lib/parse.js +56 -0
- package/node_modules/micromark/lib/postprocess.d.ts +9 -0
- package/node_modules/micromark/lib/postprocess.d.ts.map +1 -0
- package/node_modules/micromark/lib/postprocess.js +18 -0
- package/node_modules/micromark/lib/preprocess.d.ts +13 -0
- package/node_modules/micromark/lib/preprocess.d.ts.map +1 -0
- package/node_modules/micromark/lib/preprocess.js +115 -0
- package/node_modules/micromark/license +22 -0
- package/node_modules/micromark/package.json +100 -0
- package/node_modules/micromark/readme.md +488 -0
- package/node_modules/micromark/stream.d.ts +35 -0
- package/node_modules/micromark/stream.d.ts.map +1 -0
- package/node_modules/micromark/stream.js +256 -0
- package/node_modules/micromark-core-commonmark/dev/index.d.ts +23 -0
- package/node_modules/micromark-core-commonmark/dev/index.d.ts.map +1 -0
- package/node_modules/micromark-core-commonmark/dev/index.js +22 -0
- package/node_modules/micromark-core-commonmark/dev/lib/attention.d.ts +4 -0
- package/node_modules/micromark-core-commonmark/dev/lib/attention.d.ts.map +1 -0
- package/node_modules/micromark-core-commonmark/dev/lib/attention.js +300 -0
- package/node_modules/micromark-core-commonmark/dev/lib/autolink.d.ts +4 -0
- package/node_modules/micromark-core-commonmark/dev/lib/autolink.d.ts.map +1 -0
- package/node_modules/micromark-core-commonmark/dev/lib/autolink.js +269 -0
- package/node_modules/micromark-core-commonmark/dev/lib/blank-line.d.ts +4 -0
- package/node_modules/micromark-core-commonmark/dev/lib/blank-line.d.ts.map +1 -0
- package/node_modules/micromark-core-commonmark/dev/lib/blank-line.js +62 -0
- package/node_modules/micromark-core-commonmark/dev/lib/block-quote.d.ts +4 -0
- package/node_modules/micromark-core-commonmark/dev/lib/block-quote.d.ts.map +1 -0
- package/node_modules/micromark-core-commonmark/dev/lib/block-quote.js +162 -0
- package/node_modules/micromark-core-commonmark/dev/lib/character-escape.d.ts +4 -0
- package/node_modules/micromark-core-commonmark/dev/lib/character-escape.d.ts.map +1 -0
- package/node_modules/micromark-core-commonmark/dev/lib/character-escape.js +69 -0
- package/node_modules/micromark-core-commonmark/dev/lib/character-reference.d.ts +4 -0
- package/node_modules/micromark-core-commonmark/dev/lib/character-reference.d.ts.map +1 -0
- package/node_modules/micromark-core-commonmark/dev/lib/character-reference.js +166 -0
- package/node_modules/micromark-core-commonmark/dev/lib/code-fenced.d.ts +4 -0
- package/node_modules/micromark-core-commonmark/dev/lib/code-fenced.d.ts.map +1 -0
- package/node_modules/micromark-core-commonmark/dev/lib/code-fenced.js +514 -0
- package/node_modules/micromark-core-commonmark/dev/lib/code-indented.d.ts +4 -0
- package/node_modules/micromark-core-commonmark/dev/lib/code-indented.d.ts.map +1 -0
- package/node_modules/micromark-core-commonmark/dev/lib/code-indented.js +202 -0
- package/node_modules/micromark-core-commonmark/dev/lib/code-text.d.ts +4 -0
- package/node_modules/micromark-core-commonmark/dev/lib/code-text.d.ts.map +1 -0
- package/node_modules/micromark-core-commonmark/dev/lib/code-text.js +257 -0
- package/node_modules/micromark-core-commonmark/dev/lib/content.d.ts +7 -0
- package/node_modules/micromark-core-commonmark/dev/lib/content.d.ts.map +1 -0
- package/node_modules/micromark-core-commonmark/dev/lib/content.js +185 -0
- package/node_modules/micromark-core-commonmark/dev/lib/definition.d.ts +4 -0
- package/node_modules/micromark-core-commonmark/dev/lib/definition.d.ts.map +1 -0
- package/node_modules/micromark-core-commonmark/dev/lib/definition.js +295 -0
- package/node_modules/micromark-core-commonmark/dev/lib/hard-break-escape.d.ts +4 -0
- package/node_modules/micromark-core-commonmark/dev/lib/hard-break-escape.d.ts.map +1 -0
- package/node_modules/micromark-core-commonmark/dev/lib/hard-break-escape.js +65 -0
- package/node_modules/micromark-core-commonmark/dev/lib/heading-atx.d.ts +4 -0
- package/node_modules/micromark-core-commonmark/dev/lib/heading-atx.d.ts.map +1 -0
- package/node_modules/micromark-core-commonmark/dev/lib/heading-atx.js +233 -0
- package/node_modules/micromark-core-commonmark/dev/lib/html-flow.d.ts +4 -0
- package/node_modules/micromark-core-commonmark/dev/lib/html-flow.d.ts.map +1 -0
- package/node_modules/micromark-core-commonmark/dev/lib/html-flow.js +989 -0
- package/node_modules/micromark-core-commonmark/dev/lib/html-text.d.ts +4 -0
- package/node_modules/micromark-core-commonmark/dev/lib/html-text.d.ts.map +1 -0
- package/node_modules/micromark-core-commonmark/dev/lib/html-text.js +783 -0
- package/node_modules/micromark-core-commonmark/dev/lib/label-end.d.ts +4 -0
- package/node_modules/micromark-core-commonmark/dev/lib/label-end.d.ts.map +1 -0
- package/node_modules/micromark-core-commonmark/dev/lib/label-end.js +656 -0
- package/node_modules/micromark-core-commonmark/dev/lib/label-start-image.d.ts +4 -0
- package/node_modules/micromark-core-commonmark/dev/lib/label-start-image.d.ts.map +1 -0
- package/node_modules/micromark-core-commonmark/dev/lib/label-start-image.js +110 -0
- package/node_modules/micromark-core-commonmark/dev/lib/label-start-link.d.ts +4 -0
- package/node_modules/micromark-core-commonmark/dev/lib/label-start-link.d.ts.map +1 -0
- package/node_modules/micromark-core-commonmark/dev/lib/label-start-link.js +62 -0
- package/node_modules/micromark-core-commonmark/dev/lib/line-ending.d.ts +4 -0
- package/node_modules/micromark-core-commonmark/dev/lib/line-ending.d.ts.map +1 -0
- package/node_modules/micromark-core-commonmark/dev/lib/line-ending.js +34 -0
- package/node_modules/micromark-core-commonmark/dev/lib/list.d.ts +4 -0
- package/node_modules/micromark-core-commonmark/dev/lib/list.d.ts.map +1 -0
- package/node_modules/micromark-core-commonmark/dev/lib/list.js +306 -0
- package/node_modules/micromark-core-commonmark/dev/lib/setext-underline.d.ts +4 -0
- package/node_modules/micromark-core-commonmark/dev/lib/setext-underline.d.ts.map +1 -0
- package/node_modules/micromark-core-commonmark/dev/lib/setext-underline.js +210 -0
- package/node_modules/micromark-core-commonmark/dev/lib/thematic-break.d.ts +4 -0
- package/node_modules/micromark-core-commonmark/dev/lib/thematic-break.d.ts.map +1 -0
- package/node_modules/micromark-core-commonmark/dev/lib/thematic-break.js +120 -0
- package/node_modules/micromark-core-commonmark/index.d.ts +23 -0
- package/node_modules/micromark-core-commonmark/index.d.ts.map +1 -0
- package/node_modules/micromark-core-commonmark/index.js +22 -0
- package/node_modules/micromark-core-commonmark/lib/attention.d.ts +4 -0
- package/node_modules/micromark-core-commonmark/lib/attention.d.ts.map +1 -0
- package/node_modules/micromark-core-commonmark/lib/attention.js +241 -0
- package/node_modules/micromark-core-commonmark/lib/autolink.d.ts +4 -0
- package/node_modules/micromark-core-commonmark/lib/autolink.d.ts.map +1 -0
- package/node_modules/micromark-core-commonmark/lib/autolink.js +233 -0
- package/node_modules/micromark-core-commonmark/lib/blank-line.d.ts +4 -0
- package/node_modules/micromark-core-commonmark/lib/blank-line.d.ts.map +1 -0
- package/node_modules/micromark-core-commonmark/lib/blank-line.js +61 -0
- package/node_modules/micromark-core-commonmark/lib/block-quote.d.ts +4 -0
- package/node_modules/micromark-core-commonmark/lib/block-quote.d.ts.map +1 -0
- package/node_modules/micromark-core-commonmark/lib/block-quote.js +143 -0
- package/node_modules/micromark-core-commonmark/lib/character-escape.d.ts +4 -0
- package/node_modules/micromark-core-commonmark/lib/character-escape.d.ts.map +1 -0
- package/node_modules/micromark-core-commonmark/lib/character-escape.js +64 -0
- package/node_modules/micromark-core-commonmark/lib/character-reference.d.ts +4 -0
- package/node_modules/micromark-core-commonmark/lib/character-reference.d.ts.map +1 -0
- package/node_modules/micromark-core-commonmark/lib/character-reference.js +149 -0
- package/node_modules/micromark-core-commonmark/lib/code-fenced.d.ts +4 -0
- package/node_modules/micromark-core-commonmark/lib/code-fenced.d.ts.map +1 -0
- package/node_modules/micromark-core-commonmark/lib/code-fenced.js +460 -0
- package/node_modules/micromark-core-commonmark/lib/code-indented.d.ts +4 -0
- package/node_modules/micromark-core-commonmark/lib/code-indented.d.ts.map +1 -0
- package/node_modules/micromark-core-commonmark/lib/code-indented.js +177 -0
- package/node_modules/micromark-core-commonmark/lib/code-text.d.ts +4 -0
- package/node_modules/micromark-core-commonmark/lib/code-text.d.ts.map +1 -0
- package/node_modules/micromark-core-commonmark/lib/code-text.js +225 -0
- package/node_modules/micromark-core-commonmark/lib/content.d.ts +7 -0
- package/node_modules/micromark-core-commonmark/lib/content.d.ts.map +1 -0
- package/node_modules/micromark-core-commonmark/lib/content.js +163 -0
- package/node_modules/micromark-core-commonmark/lib/definition.d.ts +4 -0
- package/node_modules/micromark-core-commonmark/lib/definition.d.ts.map +1 -0
- package/node_modules/micromark-core-commonmark/lib/definition.js +254 -0
- package/node_modules/micromark-core-commonmark/lib/hard-break-escape.d.ts +4 -0
- package/node_modules/micromark-core-commonmark/lib/hard-break-escape.d.ts.map +1 -0
- package/node_modules/micromark-core-commonmark/lib/hard-break-escape.js +60 -0
- package/node_modules/micromark-core-commonmark/lib/heading-atx.d.ts +4 -0
- package/node_modules/micromark-core-commonmark/lib/heading-atx.d.ts.map +1 -0
- package/node_modules/micromark-core-commonmark/lib/heading-atx.js +195 -0
- package/node_modules/micromark-core-commonmark/lib/html-flow.d.ts +4 -0
- package/node_modules/micromark-core-commonmark/lib/html-flow.d.ts.map +1 -0
- package/node_modules/micromark-core-commonmark/lib/html-flow.js +876 -0
- package/node_modules/micromark-core-commonmark/lib/html-text.d.ts +4 -0
- package/node_modules/micromark-core-commonmark/lib/html-text.d.ts.map +1 -0
- package/node_modules/micromark-core-commonmark/lib/html-text.js +678 -0
- package/node_modules/micromark-core-commonmark/lib/label-end.d.ts +4 -0
- package/node_modules/micromark-core-commonmark/lib/label-end.d.ts.map +1 -0
- package/node_modules/micromark-core-commonmark/lib/label-end.js +560 -0
- package/node_modules/micromark-core-commonmark/lib/label-start-image.d.ts +4 -0
- package/node_modules/micromark-core-commonmark/lib/label-start-image.d.ts.map +1 -0
- package/node_modules/micromark-core-commonmark/lib/label-start-image.js +102 -0
- package/node_modules/micromark-core-commonmark/lib/label-start-link.d.ts +4 -0
- package/node_modules/micromark-core-commonmark/lib/label-start-link.d.ts.map +1 -0
- package/node_modules/micromark-core-commonmark/lib/label-start-link.js +55 -0
- package/node_modules/micromark-core-commonmark/lib/line-ending.d.ts +4 -0
- package/node_modules/micromark-core-commonmark/lib/line-ending.d.ts.map +1 -0
- package/node_modules/micromark-core-commonmark/lib/line-ending.js +33 -0
- package/node_modules/micromark-core-commonmark/lib/list.d.ts +4 -0
- package/node_modules/micromark-core-commonmark/lib/list.d.ts.map +1 -0
- package/node_modules/micromark-core-commonmark/lib/list.js +213 -0
- package/node_modules/micromark-core-commonmark/lib/setext-underline.d.ts +4 -0
- package/node_modules/micromark-core-commonmark/lib/setext-underline.d.ts.map +1 -0
- package/node_modules/micromark-core-commonmark/lib/setext-underline.js +185 -0
- package/node_modules/micromark-core-commonmark/lib/thematic-break.d.ts +4 -0
- package/node_modules/micromark-core-commonmark/lib/thematic-break.d.ts.map +1 -0
- package/node_modules/micromark-core-commonmark/lib/thematic-break.js +102 -0
- package/node_modules/micromark-core-commonmark/license +22 -0
- package/node_modules/micromark-core-commonmark/package.json +74 -0
- package/node_modules/micromark-core-commonmark/readme.md +171 -0
- package/node_modules/micromark-extension-gfm-table/dev/index.d.ts +55 -0
- package/node_modules/micromark-extension-gfm-table/dev/index.js +2 -0
- package/node_modules/micromark-extension-gfm-table/dev/lib/edit-map.d.ts +38 -0
- package/node_modules/micromark-extension-gfm-table/dev/lib/edit-map.d.ts.map +1 -0
- package/node_modules/micromark-extension-gfm-table/dev/lib/edit-map.js +212 -0
- package/node_modules/micromark-extension-gfm-table/dev/lib/html.d.ts +11 -0
- package/node_modules/micromark-extension-gfm-table/dev/lib/html.d.ts.map +1 -0
- package/node_modules/micromark-extension-gfm-table/dev/lib/html.js +148 -0
- package/node_modules/micromark-extension-gfm-table/dev/lib/infer.d.ts +14 -0
- package/node_modules/micromark-extension-gfm-table/dev/lib/infer.d.ts.map +1 -0
- package/node_modules/micromark-extension-gfm-table/dev/lib/infer.js +64 -0
- package/node_modules/micromark-extension-gfm-table/dev/lib/syntax.d.ts +18 -0
- package/node_modules/micromark-extension-gfm-table/dev/lib/syntax.d.ts.map +1 -0
- package/node_modules/micromark-extension-gfm-table/dev/lib/syntax.js +941 -0
- package/node_modules/micromark-extension-gfm-table/index.d.ts +55 -0
- package/node_modules/micromark-extension-gfm-table/index.js +2 -0
- package/node_modules/micromark-extension-gfm-table/lib/edit-map.d.ts +38 -0
- package/node_modules/micromark-extension-gfm-table/lib/edit-map.d.ts.map +1 -0
- package/node_modules/micromark-extension-gfm-table/lib/edit-map.js +202 -0
- package/node_modules/micromark-extension-gfm-table/lib/html.d.ts +11 -0
- package/node_modules/micromark-extension-gfm-table/lib/html.d.ts.map +1 -0
- package/node_modules/micromark-extension-gfm-table/lib/html.js +130 -0
- package/node_modules/micromark-extension-gfm-table/lib/infer.d.ts +14 -0
- package/node_modules/micromark-extension-gfm-table/lib/infer.d.ts.map +1 -0
- package/node_modules/micromark-extension-gfm-table/lib/infer.js +52 -0
- package/node_modules/micromark-extension-gfm-table/lib/syntax.d.ts +18 -0
- package/node_modules/micromark-extension-gfm-table/lib/syntax.d.ts.map +1 -0
- package/node_modules/micromark-extension-gfm-table/lib/syntax.js +819 -0
- package/node_modules/micromark-extension-gfm-table/license +22 -0
- package/node_modules/micromark-extension-gfm-table/package.json +128 -0
- package/node_modules/micromark-extension-gfm-table/readme.md +515 -0
- package/node_modules/micromark-factory-destination/dev/index.d.ts +42 -0
- package/node_modules/micromark-factory-destination/dev/index.d.ts.map +1 -0
- package/node_modules/micromark-factory-destination/dev/index.js +255 -0
- package/node_modules/micromark-factory-destination/index.d.ts +42 -0
- package/node_modules/micromark-factory-destination/index.d.ts.map +1 -0
- package/node_modules/micromark-factory-destination/index.js +206 -0
- package/node_modules/micromark-factory-destination/license +22 -0
- package/node_modules/micromark-factory-destination/package.json +57 -0
- package/node_modules/micromark-factory-destination/readme.md +234 -0
- package/node_modules/micromark-factory-label/dev/index.d.ts +37 -0
- package/node_modules/micromark-factory-label/dev/index.d.ts.map +1 -0
- package/node_modules/micromark-factory-label/dev/index.js +172 -0
- package/node_modules/micromark-factory-label/index.d.ts +37 -0
- package/node_modules/micromark-factory-label/index.d.ts.map +1 -0
- package/node_modules/micromark-factory-label/index.js +148 -0
- package/node_modules/micromark-factory-label/license +22 -0
- package/node_modules/micromark-factory-label/package.json +60 -0
- package/node_modules/micromark-factory-label/readme.md +224 -0
- package/node_modules/micromark-factory-space/dev/index.d.ts +37 -0
- package/node_modules/micromark-factory-space/dev/index.d.ts.map +1 -0
- package/node_modules/micromark-factory-space/dev/index.js +67 -0
- package/node_modules/micromark-factory-space/index.d.ts +37 -0
- package/node_modules/micromark-factory-space/index.d.ts.map +1 -0
- package/node_modules/micromark-factory-space/index.js +64 -0
- package/node_modules/micromark-factory-space/license +22 -0
- package/node_modules/micromark-factory-space/package.json +55 -0
- package/node_modules/micromark-factory-space/readme.md +225 -0
- package/node_modules/micromark-factory-title/dev/index.d.ts +36 -0
- package/node_modules/micromark-factory-title/dev/index.d.ts.map +1 -0
- package/node_modules/micromark-factory-title/dev/index.js +169 -0
- package/node_modules/micromark-factory-title/index.d.ts +36 -0
- package/node_modules/micromark-factory-title/index.d.ts.map +1 -0
- package/node_modules/micromark-factory-title/index.js +158 -0
- package/node_modules/micromark-factory-title/license +22 -0
- package/node_modules/micromark-factory-title/package.json +58 -0
- package/node_modules/micromark-factory-title/readme.md +229 -0
- package/node_modules/micromark-factory-whitespace/dev/index.d.ts +22 -0
- package/node_modules/micromark-factory-whitespace/dev/index.d.ts.map +1 -0
- package/node_modules/micromark-factory-whitespace/dev/index.js +53 -0
- package/node_modules/micromark-factory-whitespace/index.d.ts +22 -0
- package/node_modules/micromark-factory-whitespace/index.d.ts.map +1 -0
- package/node_modules/micromark-factory-whitespace/index.js +44 -0
- package/node_modules/micromark-factory-whitespace/license +22 -0
- package/node_modules/micromark-factory-whitespace/package.json +57 -0
- package/node_modules/micromark-factory-whitespace/readme.md +205 -0
- package/node_modules/micromark-util-character/dev/index.d.ts +195 -0
- package/node_modules/micromark-util-character/dev/index.d.ts.map +1 -0
- package/node_modules/micromark-util-character/dev/index.js +252 -0
- package/node_modules/micromark-util-character/index.d.ts +195 -0
- package/node_modules/micromark-util-character/index.d.ts.map +1 -0
- package/node_modules/micromark-util-character/index.js +246 -0
- package/node_modules/micromark-util-character/license +22 -0
- package/node_modules/micromark-util-character/package.json +57 -0
- package/node_modules/micromark-util-character/readme.md +446 -0
- package/node_modules/micromark-util-chunked/dev/index.d.ts +41 -0
- package/node_modules/micromark-util-chunked/dev/index.d.ts.map +1 -0
- package/node_modules/micromark-util-chunked/dev/index.js +89 -0
- package/node_modules/micromark-util-chunked/index.d.ts +41 -0
- package/node_modules/micromark-util-chunked/index.d.ts.map +1 -0
- package/node_modules/micromark-util-chunked/index.js +81 -0
- package/node_modules/micromark-util-chunked/license +22 -0
- package/node_modules/micromark-util-chunked/package.json +57 -0
- package/node_modules/micromark-util-chunked/readme.md +219 -0
- package/node_modules/micromark-util-classify-character/dev/index.d.ts +18 -0
- package/node_modules/micromark-util-classify-character/dev/index.d.ts.map +1 -0
- package/node_modules/micromark-util-classify-character/dev/index.js +38 -0
- package/node_modules/micromark-util-classify-character/index.d.ts +18 -0
- package/node_modules/micromark-util-classify-character/index.d.ts.map +1 -0
- package/node_modules/micromark-util-classify-character/index.js +27 -0
- package/node_modules/micromark-util-classify-character/license +22 -0
- package/node_modules/micromark-util-classify-character/package.json +59 -0
- package/node_modules/micromark-util-classify-character/readme.md +205 -0
- package/node_modules/micromark-util-combine-extensions/index.d.ts +22 -0
- package/node_modules/micromark-util-combine-extensions/index.d.ts.map +1 -0
- package/node_modules/micromark-util-combine-extensions/index.js +143 -0
- package/node_modules/micromark-util-combine-extensions/license +22 -0
- package/node_modules/micromark-util-combine-extensions/package.json +52 -0
- package/node_modules/micromark-util-combine-extensions/readme.md +201 -0
- package/node_modules/micromark-util-decode-numeric-character-reference/dev/index.d.ts +16 -0
- package/node_modules/micromark-util-decode-numeric-character-reference/dev/index.d.ts.map +1 -0
- package/node_modules/micromark-util-decode-numeric-character-reference/dev/index.js +42 -0
- package/node_modules/micromark-util-decode-numeric-character-reference/index.d.ts +16 -0
- package/node_modules/micromark-util-decode-numeric-character-reference/index.d.ts.map +1 -0
- package/node_modules/micromark-util-decode-numeric-character-reference/index.js +32 -0
- package/node_modules/micromark-util-decode-numeric-character-reference/license +22 -0
- package/node_modules/micromark-util-decode-numeric-character-reference/package.json +59 -0
- package/node_modules/micromark-util-decode-numeric-character-reference/readme.md +184 -0
- package/node_modules/micromark-util-decode-string/dev/index.d.ts +14 -0
- package/node_modules/micromark-util-decode-string/dev/index.d.ts.map +1 -0
- package/node_modules/micromark-util-decode-string/dev/index.js +53 -0
- package/node_modules/micromark-util-decode-string/index.d.ts +14 -0
- package/node_modules/micromark-util-decode-string/index.d.ts.map +1 -0
- package/node_modules/micromark-util-decode-string/index.js +45 -0
- package/node_modules/micromark-util-decode-string/license +22 -0
- package/node_modules/micromark-util-decode-string/package.json +63 -0
- package/node_modules/micromark-util-decode-string/readme.md +179 -0
- package/node_modules/micromark-util-encode/index.d.ts +14 -0
- package/node_modules/micromark-util-encode/index.d.ts.map +1 -0
- package/node_modules/micromark-util-encode/index.js +33 -0
- package/node_modules/micromark-util-encode/license +22 -0
- package/node_modules/micromark-util-encode/package.json +47 -0
- package/node_modules/micromark-util-encode/readme.md +176 -0
- package/node_modules/micromark-util-html-tag-name/index.d.ts +30 -0
- package/node_modules/micromark-util-html-tag-name/index.d.ts.map +1 -0
- package/node_modules/micromark-util-html-tag-name/index.js +93 -0
- package/node_modules/micromark-util-html-tag-name/license +22 -0
- package/node_modules/micromark-util-html-tag-name/package.json +47 -0
- package/node_modules/micromark-util-html-tag-name/readme.md +193 -0
- package/node_modules/micromark-util-normalize-identifier/dev/index.d.ts +21 -0
- package/node_modules/micromark-util-normalize-identifier/dev/index.d.ts.map +1 -0
- package/node_modules/micromark-util-normalize-identifier/dev/index.js +38 -0
- package/node_modules/micromark-util-normalize-identifier/index.d.ts +21 -0
- package/node_modules/micromark-util-normalize-identifier/index.d.ts.map +1 -0
- package/node_modules/micromark-util-normalize-identifier/index.js +33 -0
- package/node_modules/micromark-util-normalize-identifier/license +22 -0
- package/node_modules/micromark-util-normalize-identifier/package.json +58 -0
- package/node_modules/micromark-util-normalize-identifier/readme.md +187 -0
- package/node_modules/micromark-util-resolve-all/index.d.ts +22 -0
- package/node_modules/micromark-util-resolve-all/index.d.ts.map +1 -0
- package/node_modules/micromark-util-resolve-all/index.js +32 -0
- package/node_modules/micromark-util-resolve-all/license +22 -0
- package/node_modules/micromark-util-resolve-all/package.json +48 -0
- package/node_modules/micromark-util-resolve-all/readme.md +238 -0
- package/node_modules/micromark-util-sanitize-uri/dev/index.d.ts +36 -0
- package/node_modules/micromark-util-sanitize-uri/dev/index.d.ts.map +1 -0
- package/node_modules/micromark-util-sanitize-uri/dev/index.js +124 -0
- package/node_modules/micromark-util-sanitize-uri/index.d.ts +36 -0
- package/node_modules/micromark-util-sanitize-uri/index.d.ts.map +1 -0
- package/node_modules/micromark-util-sanitize-uri/index.js +107 -0
- package/node_modules/micromark-util-sanitize-uri/license +22 -0
- package/node_modules/micromark-util-sanitize-uri/package.json +59 -0
- package/node_modules/micromark-util-sanitize-uri/readme.md +214 -0
- package/node_modules/micromark-util-subtokenize/dev/index.d.ts +12 -0
- package/node_modules/micromark-util-subtokenize/dev/index.d.ts.map +1 -0
- package/node_modules/micromark-util-subtokenize/dev/index.js +284 -0
- package/node_modules/micromark-util-subtokenize/dev/lib/splice-buffer.d.ts +161 -0
- package/node_modules/micromark-util-subtokenize/dev/lib/splice-buffer.d.ts.map +1 -0
- package/node_modules/micromark-util-subtokenize/dev/lib/splice-buffer.js +288 -0
- package/node_modules/micromark-util-subtokenize/index.d.ts +12 -0
- package/node_modules/micromark-util-subtokenize/index.d.ts.map +1 -0
- package/node_modules/micromark-util-subtokenize/index.js +228 -0
- package/node_modules/micromark-util-subtokenize/lib/splice-buffer.d.ts +161 -0
- package/node_modules/micromark-util-subtokenize/lib/splice-buffer.d.ts.map +1 -0
- package/node_modules/micromark-util-subtokenize/lib/splice-buffer.js +251 -0
- package/node_modules/micromark-util-subtokenize/license +22 -0
- package/node_modules/micromark-util-subtokenize/package.json +60 -0
- package/node_modules/micromark-util-subtokenize/readme.md +181 -0
- package/node_modules/micromark-util-symbol/lib/codes.d.ts +139 -0
- package/node_modules/micromark-util-symbol/lib/codes.d.ts.map +1 -0
- package/node_modules/micromark-util-symbol/lib/codes.js +158 -0
- package/node_modules/micromark-util-symbol/lib/constants.d.ts +37 -0
- package/node_modules/micromark-util-symbol/lib/constants.d.ts.map +1 -0
- package/node_modules/micromark-util-symbol/lib/constants.js +44 -0
- package/node_modules/micromark-util-symbol/lib/default.d.ts +5 -0
- package/node_modules/micromark-util-symbol/lib/default.d.ts.map +1 -0
- package/node_modules/micromark-util-symbol/lib/default.js +4 -0
- package/node_modules/micromark-util-symbol/lib/types.d.ts +106 -0
- package/node_modules/micromark-util-symbol/lib/types.d.ts.map +1 -0
- package/node_modules/micromark-util-symbol/lib/types.js +453 -0
- package/node_modules/micromark-util-symbol/lib/values.d.ts +102 -0
- package/node_modules/micromark-util-symbol/lib/values.d.ts.map +1 -0
- package/node_modules/micromark-util-symbol/lib/values.js +109 -0
- package/node_modules/micromark-util-symbol/license +22 -0
- package/node_modules/micromark-util-symbol/package.json +43 -0
- package/node_modules/micromark-util-symbol/readme.md +168 -0
- package/node_modules/micromark-util-types/index.d.ts +1312 -0
- package/node_modules/micromark-util-types/index.js +2 -0
- package/node_modules/micromark-util-types/license +22 -0
- package/node_modules/micromark-util-types/package.json +71 -0
- package/node_modules/micromark-util-types/readme.md +151 -0
- package/node_modules/ms/index.js +162 -0
- package/node_modules/ms/license.md +21 -0
- package/node_modules/ms/package.json +38 -0
- package/node_modules/ms/readme.md +59 -0
- package/node_modules/unist-util-is/index.d.ts +5 -0
- package/node_modules/unist-util-is/index.d.ts.map +1 -0
- package/node_modules/unist-util-is/index.js +7 -0
- package/node_modules/unist-util-is/lib/index.d.ts +111 -0
- package/node_modules/unist-util-is/lib/index.d.ts.map +1 -0
- package/node_modules/unist-util-is/lib/index.js +296 -0
- package/node_modules/unist-util-is/license +22 -0
- package/node_modules/unist-util-is/package.json +103 -0
- package/node_modules/unist-util-is/readme.md +351 -0
- package/node_modules/unist-util-stringify-position/index.d.ts +1 -0
- package/node_modules/unist-util-stringify-position/index.js +1 -0
- package/node_modules/unist-util-stringify-position/lib/index.d.ts +61 -0
- package/node_modules/unist-util-stringify-position/lib/index.js +84 -0
- package/node_modules/unist-util-stringify-position/license +22 -0
- package/node_modules/unist-util-stringify-position/package.json +80 -0
- package/node_modules/unist-util-stringify-position/readme.md +206 -0
- package/node_modules/unist-util-visit/index.d.ts +9 -0
- package/node_modules/unist-util-visit/index.js +2 -0
- package/node_modules/unist-util-visit/lib/index.d.ts +195 -0
- package/node_modules/unist-util-visit/lib/index.d.ts.map +1 -0
- package/node_modules/unist-util-visit/lib/index.js +312 -0
- package/node_modules/unist-util-visit/license +22 -0
- package/node_modules/unist-util-visit/package.json +108 -0
- package/node_modules/unist-util-visit/readme.md +313 -0
- package/node_modules/unist-util-visit-parents/index.d.ts +14 -0
- package/node_modules/unist-util-visit-parents/index.js +2 -0
- package/node_modules/unist-util-visit-parents/lib/color.d.ts +6 -0
- package/node_modules/unist-util-visit-parents/lib/color.d.ts.map +1 -0
- package/node_modules/unist-util-visit-parents/lib/color.js +7 -0
- package/node_modules/unist-util-visit-parents/lib/color.node.d.ts +6 -0
- package/node_modules/unist-util-visit-parents/lib/color.node.d.ts.map +1 -0
- package/node_modules/unist-util-visit-parents/lib/color.node.js +7 -0
- package/node_modules/unist-util-visit-parents/lib/index.d.ts +219 -0
- package/node_modules/unist-util-visit-parents/lib/index.d.ts.map +1 -0
- package/node_modules/unist-util-visit-parents/lib/index.js +399 -0
- package/node_modules/unist-util-visit-parents/license +22 -0
- package/node_modules/unist-util-visit-parents/package.json +106 -0
- package/node_modules/unist-util-visit-parents/readme.md +388 -0
- package/node_modules/zwitch/index.d.ts +67 -0
- package/node_modules/zwitch/index.js +118 -0
- package/node_modules/zwitch/license +22 -0
- package/node_modules/zwitch/package.json +72 -0
- package/node_modules/zwitch/readme.md +226 -0
- package/npm-shrinkwrap.json +737 -3
- package/openclaw.plugin.json +164 -89
- package/package.json +10 -7
- package/skills/feishu-drive/SKILL.md +5 -2
- package/dist/legacy-state-migrations-api.js +0 -73
- package/dist/monitor.state-DAHbcR2N.js +0 -173
- package/dist/send-result-BMQw-YhV.js +0 -287
|
@@ -1,45 +1,88 @@
|
|
|
1
|
-
import { _ as normalizeCommentFileType, c as encodeQuery, d as isRecord$1, f as normalizeString, g as buildFeishuCommentTarget, h as requestFeishuApi, l as extractReplyText, m as readString, o as resolveFeishuAccount, p as parseCommentContentElements, s as resolveFeishuRuntimeAccount } from "./accounts-
|
|
1
|
+
import { _ as normalizeCommentFileType, c as encodeQuery, d as isRecord$1, f as normalizeString, g as buildFeishuCommentTarget, h as requestFeishuApi, l as extractReplyText, m as readString, o as resolveFeishuAccount, p as parseCommentContentElements, s as resolveFeishuRuntimeAccount } from "./accounts-BDoGHJDk.js";
|
|
2
2
|
import { i as resolveReceiveIdType } from "./targets-BUjQ1TcA.js";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
3
|
+
import { A as resolveFeishuChatType, C as resolveFeishuDmIngressAccess, E as resolveFeishuGroupSenderActivationIngressAccess, M as buildFeishuCardActionTextFallback, N as createFeishuCardInteractionEnvelope, O as resolveFeishuReplyPolicy, P as decodeFeishuCardAction, S as normalizeFeishuAllowEntry, T as resolveFeishuGroupConversationIngressAccess, d as chunkFeishuPostMarkdown, f as materializeFeishuPostMarkdownSoftBreaks, k as normalizeFeishuChatType$2, o as resolveFeishuCardTemplate, w as resolveFeishuGroupConfig, x as hasExplicitFeishuGroupConfig } from "./send-result-DsqTk27v.js";
|
|
4
|
+
import { o as resolveConfiguredFeishuGroupSessionScope, t as buildFeishuConversationId } from "./conversation-id-BeJL-wq7.js";
|
|
5
|
+
import { a as getFeishuUserAgent, i as createFeishuWSClient, n as createEventDispatcher, r as createFeishuClient, s as resolveConfiguredHttpTimeoutMs } from "./client-87BmeMpj.js";
|
|
6
6
|
import { t as getFeishuRuntime } from "./runtime-C5JxBWZp.js";
|
|
7
|
-
import {
|
|
8
|
-
import { i as createCommentTypingReactionLifecycle, s as getChatInfo, t as deliverCommentThreadText } from "./drive-D0lIhxqZ.js";
|
|
7
|
+
import { i as createCommentTypingReactionLifecycle, l as getChatInfo, t as deliverCommentThreadText } from "./drive-B4E8OXZ0.js";
|
|
9
8
|
import { t as createFeishuThreadBindingManager } from "./thread-bindings-V0bwk0A1.js";
|
|
10
9
|
import { createReplyPrefixContext, evaluateSupplementalContextVisibility, getSessionEntry, normalizeAgentId as normalizeAgentId$2, resolveChannelContextVisibilityMode } from "./runtime-api.js";
|
|
11
10
|
import { t as readFeishuJsonResponse } from "./json-response-CheljwGr.js";
|
|
12
|
-
import { _ as resolveFeishuIdentityEmoji, c as parsePostContent, d as isMentionForwardRequest, f as isFeishuGroupChatType, g as normalizeFeishuExternalKey, h as shouldSuppressFeishuTextForVoiceMedia, i as sendCardFeishu, l as extractMentionTargets, m as sendMediaFeishu, n as getMessageFeishu, o as sendMessageFeishu, p as saveMessageResourceFeishu, r as listFeishuThreadMessages, s as sendStructuredCardFeishu, u as isFeishuBroadcastMention } from "./send-
|
|
13
|
-
import { i as waitForAbortableDelay, r as raceWithTimeoutAndAbort } from "./probe-
|
|
14
|
-
import {
|
|
15
|
-
import { createChannelMessageReplyPipeline, formatChannelProgressDraftLineForEntry, isChannelProgressDraftWorkToolName, resolveAgentOutboundIdentity } from "openclaw/plugin-sdk/channel-outbound";
|
|
11
|
+
import { _ as resolveFeishuIdentityEmoji, c as parsePostContent, d as isMentionForwardRequest, f as isFeishuGroupChatType, g as normalizeFeishuExternalKey, h as shouldSuppressFeishuTextForVoiceMedia, i as sendCardFeishu, l as extractMentionTargets, m as sendMediaFeishu, n as getMessageFeishu, o as sendMessageFeishu, p as saveMessageResourceFeishu, r as listFeishuThreadMessages, s as sendStructuredCardFeishu, u as isFeishuBroadcastMention } from "./send-DrWM_Ilf.js";
|
|
12
|
+
import { i as waitForAbortableDelay, r as raceWithTimeoutAndAbort } from "./probe-BgboTHIn.js";
|
|
13
|
+
import { t as fetchBotIdentityForMonitor } from "./monitor.startup-Cy8NPGAX.js";
|
|
14
|
+
import { createChannelMessageReplyPipeline, formatChannelProgressDraftLineForEntry, isChannelProgressDraftWorkToolName, resolveAgentOutboundIdentity, resolveChannelPreviewStreamMode, resolveChannelStreamingBlockEnabled } from "openclaw/plugin-sdk/channel-outbound";
|
|
16
15
|
import { createChannelPairingController, createChannelPairingController as createChannelPairingController$1 } from "openclaw/plugin-sdk/channel-pairing";
|
|
17
16
|
import { ensureConfiguredBindingRouteReady, resolveConfiguredBindingRoute, resolveRuntimeConversationBindingRoute } from "openclaw/plugin-sdk/conversation-runtime";
|
|
18
17
|
import { asDateTimestampMs, isFutureDateTimestampMs, parseStrictNonNegativeInteger, resolveDateTimestampMs, resolveExpiresAtMsFromDurationMs, resolveExpiresAtMsFromDurationSeconds, resolveTimerTimeoutMs } from "openclaw/plugin-sdk/number-runtime";
|
|
19
18
|
import { asBoolean, asNullableRecord, isRecord, normalizeLowercaseStringOrEmpty, normalizeOptionalLowercaseString, normalizeOptionalString, readStringValue, uniqueStrings } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
20
19
|
import { stripReasoningTagsFromText } from "openclaw/plugin-sdk/text-chunking";
|
|
20
|
+
import { resolveDefaultGroupPolicy, resolveOpenProviderRuntimeGroupPolicy, warnMissingProviderGroupPolicyFallbackOnce } from "openclaw/plugin-sdk/runtime-group-policy";
|
|
21
21
|
import fs from "node:fs";
|
|
22
22
|
import os from "node:os";
|
|
23
23
|
import path from "node:path";
|
|
24
24
|
import { normalizeAccountId, resolveAgentRoute, resolveInboundLastRouteSessionKey } from "openclaw/plugin-sdk/routing";
|
|
25
25
|
import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
|
|
26
26
|
import * as Lark from "@larksuiteoapi/node-sdk";
|
|
27
|
-
import
|
|
28
|
-
import crypto, { createHash } from "node:crypto";
|
|
29
|
-
import { applyBasicWebhookRequestGuards, resolveRequestClientIp } from "openclaw/plugin-sdk/webhook-ingress";
|
|
27
|
+
import { WEBHOOK_ANOMALY_COUNTER_DEFAULTS, WEBHOOK_RATE_LIMIT_DEFAULTS, applyBasicWebhookRequestGuards, createFixedWindowRateLimiter, createWebhookAnomalyTracker, resolveRequestClientIp } from "openclaw/plugin-sdk/webhook-ingress";
|
|
30
28
|
import { fetchWithSsrFGuard } from "openclaw/plugin-sdk/ssrf-runtime";
|
|
31
29
|
import { resolveSendableOutboundReplyParts, resolveTextChunksWithFallback, sendMediaWithLeadingCaption } from "openclaw/plugin-sdk/reply-payload";
|
|
32
30
|
import { resolvePinnedMainDmOwnerFromAllowlist, safeEqualSecret } from "openclaw/plugin-sdk/security-runtime";
|
|
31
|
+
import * as crypto$1 from "node:crypto";
|
|
32
|
+
import crypto, { createHash } from "node:crypto";
|
|
33
33
|
import { buildChannelInboundEventContext, formatInboundMediaUnavailableText, toInboundMediaFacts } from "openclaw/plugin-sdk/channel-inbound";
|
|
34
34
|
import { DEFAULT_GROUP_HISTORY_LIMIT, createChannelHistoryWindow } from "openclaw/plugin-sdk/reply-history";
|
|
35
|
-
import { resolveDefaultGroupPolicy, resolveOpenProviderRuntimeGroupPolicy, warnMissingProviderGroupPolicyFallbackOnce } from "openclaw/plugin-sdk/runtime-group-policy";
|
|
36
35
|
import { sliceUtf16Safe, truncateUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime";
|
|
36
|
+
import { createChannelReplayGuard } from "openclaw/plugin-sdk/persistent-dedupe";
|
|
37
37
|
import { resolveChannelConfigWrites } from "openclaw/plugin-sdk/channel-config-writes";
|
|
38
38
|
import { formatReasoningMessage } from "openclaw/plugin-sdk/agent-runtime";
|
|
39
39
|
import { logTypingFailure } from "openclaw/plugin-sdk/channel-feedback";
|
|
40
40
|
import * as http from "node:http";
|
|
41
41
|
import { installRequestBodyLimitGuard, readWebhookBodyOrReject } from "openclaw/plugin-sdk/webhook-request-guards";
|
|
42
42
|
import { isAbortRequestText, isBtwRequestText } from "openclaw/plugin-sdk/command-primitives-runtime";
|
|
43
|
+
//#region extensions/feishu/src/bot-agent-body.ts
|
|
44
|
+
const MAX_MENTION_CONTEXT_NAME_LENGTH = 80;
|
|
45
|
+
function formatMentionNameForAgentContext(name) {
|
|
46
|
+
const normalized = Array.from(name, (char) => {
|
|
47
|
+
return char.charCodeAt(0) < 32 || char === "[" || char === "]" ? " " : char;
|
|
48
|
+
}).join("").replace(/\s+/g, " ").trim();
|
|
49
|
+
const bounded = normalized.length > MAX_MENTION_CONTEXT_NAME_LENGTH ? `${truncateUtf16Safe(normalized, MAX_MENTION_CONTEXT_NAME_LENGTH - 3)}...` : normalized;
|
|
50
|
+
return JSON.stringify(bounded || "unknown");
|
|
51
|
+
}
|
|
52
|
+
function buildFeishuAgentBody(params) {
|
|
53
|
+
const { ctx, quotedContent, permissionErrorForAgent, botOpenId } = params;
|
|
54
|
+
let messageBody = ctx.content;
|
|
55
|
+
if (quotedContent) messageBody = `[Replying to: "${quotedContent}"]\n\n${ctx.content}`;
|
|
56
|
+
messageBody = `${ctx.senderName ?? ctx.senderOpenId}: ${messageBody}`;
|
|
57
|
+
if (ctx.hasAnyMention) {
|
|
58
|
+
const botIdHint = botOpenId?.trim();
|
|
59
|
+
messageBody += "\n\n[System: The content may include mention tags in the form <at user_id=\"...\">name</at>. Treat these as real mentions of Feishu entities (users or bots).]";
|
|
60
|
+
if (botIdHint) messageBody += `\n[System: If user_id is "${botIdHint}", that mention refers to you.]`;
|
|
61
|
+
}
|
|
62
|
+
if (ctx.mentionTargets && ctx.mentionTargets.length > 0) {
|
|
63
|
+
const targetNames = ctx.mentionTargets.map((target) => formatMentionNameForAgentContext(target.name)).join(", ");
|
|
64
|
+
messageBody += `\n\n[System: Feishu users mentioned in the incoming message, for context only: ${targetNames}. Do not notify or mention these users solely because they are listed here.]`;
|
|
65
|
+
}
|
|
66
|
+
messageBody = `[message_id: ${ctx.messageId}]\n${messageBody}`;
|
|
67
|
+
if (permissionErrorForAgent) {
|
|
68
|
+
const grantUrl = permissionErrorForAgent.grantUrl ?? "";
|
|
69
|
+
messageBody += `\n\n[System: The bot encountered a Feishu API permission error. Please inform the user about this issue and provide the permission grant URL for the admin to authorize. Permission grant URL: ${grantUrl}]`;
|
|
70
|
+
}
|
|
71
|
+
return messageBody;
|
|
72
|
+
}
|
|
73
|
+
//#endregion
|
|
74
|
+
//#region extensions/feishu/src/bot-broadcast.ts
|
|
75
|
+
function resolveBroadcastAgents(cfg, peerId) {
|
|
76
|
+
const broadcast = cfg.broadcast;
|
|
77
|
+
if (!broadcast || typeof broadcast !== "object") return null;
|
|
78
|
+
const agents = broadcast[peerId];
|
|
79
|
+
return Array.isArray(agents) && agents.length > 0 ? agents : null;
|
|
80
|
+
}
|
|
81
|
+
function buildBroadcastSessionKey(baseSessionKey, originalAgentId, targetAgentId) {
|
|
82
|
+
const prefix = `agent:${originalAgentId}:`;
|
|
83
|
+
return baseSessionKey.startsWith(prefix) ? `agent:${targetAgentId}:${baseSessionKey.slice(prefix.length)}` : baseSessionKey;
|
|
84
|
+
}
|
|
85
|
+
//#endregion
|
|
43
86
|
//#region extensions/feishu/src/bot-content.ts
|
|
44
87
|
function resolveFeishuGroupSession(params) {
|
|
45
88
|
const { chatId, senderOpenId, messageId, rootId, threadId, chatType, groupConfig, feishuCfg } = params;
|
|
@@ -376,6 +419,65 @@ async function resolveFeishuMediaList(params) {
|
|
|
376
419
|
};
|
|
377
420
|
}
|
|
378
421
|
//#endregion
|
|
422
|
+
//#region extensions/feishu/src/bot-group-name-state.ts
|
|
423
|
+
const feishuGroupNameCache = /* @__PURE__ */ new Map();
|
|
424
|
+
//#endregion
|
|
425
|
+
//#region extensions/feishu/src/bot-group-name.ts
|
|
426
|
+
const GROUP_NAME_CACHE_TTL_MS = 1800 * 1e3;
|
|
427
|
+
const GROUP_NAME_CACHE_MAX_SIZE = 500;
|
|
428
|
+
function evictGroupNameCache() {
|
|
429
|
+
const now = asDateTimestampMs(Date.now());
|
|
430
|
+
if (now === void 0) {
|
|
431
|
+
feishuGroupNameCache.clear();
|
|
432
|
+
return;
|
|
433
|
+
}
|
|
434
|
+
for (const [key, value] of feishuGroupNameCache) {
|
|
435
|
+
const expiresAt = asDateTimestampMs(value.expiresAt);
|
|
436
|
+
if (expiresAt === void 0 || expiresAt <= now) feishuGroupNameCache.delete(key);
|
|
437
|
+
}
|
|
438
|
+
const excess = feishuGroupNameCache.size - GROUP_NAME_CACHE_MAX_SIZE;
|
|
439
|
+
if (excess <= 0) return;
|
|
440
|
+
let removed = 0;
|
|
441
|
+
for (const key of feishuGroupNameCache.keys()) {
|
|
442
|
+
if (removed >= excess) break;
|
|
443
|
+
feishuGroupNameCache.delete(key);
|
|
444
|
+
removed++;
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
function setCacheEntry(key, name) {
|
|
448
|
+
const expiresAt = resolveExpiresAtMsFromDurationMs(GROUP_NAME_CACHE_TTL_MS);
|
|
449
|
+
feishuGroupNameCache.delete(key);
|
|
450
|
+
if (expiresAt !== void 0) feishuGroupNameCache.set(key, {
|
|
451
|
+
name,
|
|
452
|
+
expiresAt
|
|
453
|
+
});
|
|
454
|
+
}
|
|
455
|
+
async function resolveGroupName(params) {
|
|
456
|
+
const { account, chatId, log } = params;
|
|
457
|
+
if (!account.configured) return;
|
|
458
|
+
const cacheKey = `${account.accountId}:${chatId}`;
|
|
459
|
+
const cached = feishuGroupNameCache.get(cacheKey);
|
|
460
|
+
if (cached) {
|
|
461
|
+
const now = asDateTimestampMs(Date.now());
|
|
462
|
+
const expiresAt = asDateTimestampMs(cached.expiresAt);
|
|
463
|
+
if (now !== void 0 && expiresAt !== void 0 && expiresAt > now) return cached.name || void 0;
|
|
464
|
+
feishuGroupNameCache.delete(cacheKey);
|
|
465
|
+
}
|
|
466
|
+
let resolvedName;
|
|
467
|
+
try {
|
|
468
|
+
const name = (await getChatInfo(createFeishuClient(account), chatId))?.name?.trim();
|
|
469
|
+
if (name) {
|
|
470
|
+
setCacheEntry(cacheKey, name);
|
|
471
|
+
resolvedName = name;
|
|
472
|
+
} else setCacheEntry(cacheKey, "");
|
|
473
|
+
} catch (err) {
|
|
474
|
+
log(`feishu[${account.accountId}]: getChatInfo failed for ${chatId}: ${String(err)}`);
|
|
475
|
+
setCacheEntry(cacheKey, "");
|
|
476
|
+
}
|
|
477
|
+
evictGroupNameCache();
|
|
478
|
+
return resolvedName;
|
|
479
|
+
}
|
|
480
|
+
//#endregion
|
|
379
481
|
//#region extensions/feishu/src/bot-sender-name.ts
|
|
380
482
|
const IGNORED_PERMISSION_SCOPE_TOKENS = ["contact:contact.base:readonly"];
|
|
381
483
|
const FEISHU_SCOPE_CORRECTIONS = { "contact:contact.base:readonly": "contact:user.base:readonly" };
|
|
@@ -455,207 +557,79 @@ async function resolveFeishuSenderName(params) {
|
|
|
455
557
|
}
|
|
456
558
|
}
|
|
457
559
|
//#endregion
|
|
458
|
-
//#region extensions/feishu/src/
|
|
459
|
-
const
|
|
460
|
-
const EVENT_MEMORY_MAX_SIZE = 2e3;
|
|
461
|
-
const processingClaims = /* @__PURE__ */ new Map();
|
|
462
|
-
function resolveEventDedupeKey(namespace, messageId) {
|
|
463
|
-
const trimmed = messageId?.trim();
|
|
464
|
-
return trimmed ? `${namespace}:${trimmed}` : null;
|
|
465
|
-
}
|
|
466
|
-
function pruneProcessingClaims(now) {
|
|
467
|
-
const cutoff = now - EVENT_DEDUP_TTL_MS;
|
|
468
|
-
for (const [key, seenAt] of processingClaims) if (seenAt < cutoff) processingClaims.delete(key);
|
|
469
|
-
while (processingClaims.size > EVENT_MEMORY_MAX_SIZE) {
|
|
470
|
-
const oldestKey = processingClaims.keys().next().value;
|
|
471
|
-
if (!oldestKey) return;
|
|
472
|
-
processingClaims.delete(oldestKey);
|
|
473
|
-
}
|
|
474
|
-
}
|
|
475
|
-
function tryBeginFeishuMessageProcessing(messageId, namespace = "global") {
|
|
476
|
-
const key = resolveEventDedupeKey(namespace, messageId);
|
|
477
|
-
if (!key) return true;
|
|
478
|
-
const now = Date.now();
|
|
479
|
-
pruneProcessingClaims(now);
|
|
480
|
-
if (processingClaims.has(key)) {
|
|
481
|
-
processingClaims.delete(key);
|
|
482
|
-
processingClaims.set(key, now);
|
|
483
|
-
pruneProcessingClaims(now);
|
|
484
|
-
return false;
|
|
485
|
-
}
|
|
486
|
-
processingClaims.set(key, now);
|
|
487
|
-
pruneProcessingClaims(now);
|
|
488
|
-
return true;
|
|
489
|
-
}
|
|
490
|
-
function releaseFeishuMessageProcessing(messageId, namespace = "global") {
|
|
491
|
-
const key = resolveEventDedupeKey(namespace, messageId);
|
|
492
|
-
if (key) processingClaims.delete(key);
|
|
493
|
-
}
|
|
494
|
-
//#endregion
|
|
495
|
-
//#region extensions/feishu/src/dedup.ts
|
|
560
|
+
//#region extensions/feishu/src/dedup-state.ts
|
|
561
|
+
const DEDUPE_NAMESPACE_PREFIX = "feishu.dedup";
|
|
496
562
|
const DEDUP_TTL_MS = 1440 * 60 * 1e3;
|
|
497
563
|
const MEMORY_MAX_SIZE = 1e3;
|
|
498
564
|
const STORE_MAX_ENTRIES = 1e4;
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
}
|
|
508
|
-
|
|
509
|
-
return `dedup.${namespace.replace(/[^a-zA-Z0-9_-]/g, "_")}`;
|
|
510
|
-
}
|
|
511
|
-
function openDedupStore(namespace) {
|
|
512
|
-
const stateNamespace = pluginStateNamespace(namespace);
|
|
513
|
-
const cached = cachedDedupStores.get(stateNamespace);
|
|
514
|
-
if (cached) return cached;
|
|
515
|
-
const store = getFeishuRuntime().state.openSyncKeyedStore({
|
|
516
|
-
namespace: stateNamespace,
|
|
517
|
-
maxEntries: STORE_MAX_ENTRIES,
|
|
518
|
-
defaultTtlMs: DEDUP_TTL_MS
|
|
565
|
+
function createFeishuDedupeGuard() {
|
|
566
|
+
return createChannelReplayGuard({
|
|
567
|
+
dedupe: {
|
|
568
|
+
pluginId: "feishu",
|
|
569
|
+
namespacePrefix: DEDUPE_NAMESPACE_PREFIX,
|
|
570
|
+
ttlMs: DEDUP_TTL_MS,
|
|
571
|
+
memoryMaxSize: MEMORY_MAX_SIZE,
|
|
572
|
+
stateMaxEntries: STORE_MAX_ENTRIES
|
|
573
|
+
},
|
|
574
|
+
buildReplayKey: (messageId) => messageId
|
|
519
575
|
});
|
|
520
|
-
cachedDedupStores.set(stateNamespace, store);
|
|
521
|
-
return store;
|
|
522
|
-
}
|
|
523
|
-
function dedupeStoreKey(namespace, messageId) {
|
|
524
|
-
return createHash("sha256").update(`${namespace}\0${messageId}`, "utf8").digest("hex").slice(0, 32);
|
|
525
|
-
}
|
|
526
|
-
function memoryKey(namespace, messageId) {
|
|
527
|
-
return `${namespace}\0${messageId}`;
|
|
528
|
-
}
|
|
529
|
-
function isRecent(seenAt, now = Date.now()) {
|
|
530
|
-
return typeof seenAt === "number" && Number.isFinite(seenAt) && now - seenAt < DEDUP_TTL_MS;
|
|
531
|
-
}
|
|
532
|
-
function pruneMemory(now = Date.now()) {
|
|
533
|
-
for (const [key, seenAt] of memory) if (!isRecent(seenAt, now)) memory.delete(key);
|
|
534
|
-
if (memory.size <= MEMORY_MAX_SIZE) return;
|
|
535
|
-
const toRemove = Array.from(memory.entries()).toSorted(([, left], [, right]) => left - right).slice(0, memory.size - MEMORY_MAX_SIZE);
|
|
536
|
-
for (const [key] of toRemove) memory.delete(key);
|
|
537
576
|
}
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
577
|
+
const feishuDedupeState = {
|
|
578
|
+
guard: createFeishuDedupeGuard(),
|
|
579
|
+
reset() {
|
|
580
|
+
this.guard = createFeishuDedupeGuard();
|
|
581
|
+
}
|
|
582
|
+
};
|
|
583
|
+
//#endregion
|
|
584
|
+
//#region extensions/feishu/src/dedup.ts
|
|
585
|
+
function dedupeKey(messageId) {
|
|
586
|
+
return messageId?.trim() ?? "";
|
|
541
587
|
}
|
|
542
|
-
function
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
588
|
+
function dedupeOptions(namespace, log) {
|
|
589
|
+
return {
|
|
590
|
+
...namespace ? { namespace } : {},
|
|
591
|
+
...log ? { onDiskError: (error) => log(`feishu-dedup: persistent state error: ${String(error)}`) } : {}
|
|
592
|
+
};
|
|
547
593
|
}
|
|
594
|
+
/**
|
|
595
|
+
* Claims a dedupe key for exclusive handling. Duplicate (already committed)
|
|
596
|
+
* and in-flight keys are reported; blank keys fail open as invalid so an
|
|
597
|
+
* unidentifiable event is never suppressed.
|
|
598
|
+
*/
|
|
548
599
|
async function claimUnprocessedFeishuMessage(params) {
|
|
549
|
-
const
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
if (await hasProcessedFeishuMessage(normalizedMessageId, namespace, log)) return "duplicate";
|
|
553
|
-
if (!tryBeginFeishuMessageProcessing(normalizedMessageId, namespace)) return "inflight";
|
|
554
|
-
return "claimed";
|
|
600
|
+
const claim = await feishuDedupeState.guard.claim(params.messageId, dedupeOptions(params.namespace, params.log));
|
|
601
|
+
if (claim.kind === "inflight") return { kind: "inflight" };
|
|
602
|
+
return claim;
|
|
555
603
|
}
|
|
604
|
+
/**
|
|
605
|
+
* Claims (unless the caller already holds the claim) and commits a message.
|
|
606
|
+
* False means another handler owns it, it was already handled, or the key is
|
|
607
|
+
* blank; handlers must skip dispatch then.
|
|
608
|
+
*/
|
|
556
609
|
async function finalizeFeishuMessageProcessing(params) {
|
|
557
|
-
const
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
if (
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
return true;
|
|
566
|
-
}
|
|
610
|
+
const key = dedupeKey(params.messageId);
|
|
611
|
+
if (!key) return false;
|
|
612
|
+
const options = dedupeOptions(params.namespace, params.log);
|
|
613
|
+
const claim = params.processingClaim ?? await feishuDedupeState.guard.claim(key, options);
|
|
614
|
+
if ("kind" in claim && claim.kind !== "claimed") return false;
|
|
615
|
+
return await ("kind" in claim ? claim.handle : claim).commit();
|
|
616
|
+
}
|
|
617
|
+
/** Records a handled message so restart/replay cannot dispatch it again; false when already recorded. */
|
|
567
618
|
async function recordProcessedFeishuMessage(messageId, namespace = "global", log) {
|
|
568
|
-
const
|
|
569
|
-
|
|
570
|
-
return await tryRecordMessagePersistent(normalizedMessageId, namespace, log);
|
|
619
|
+
const claim = await feishuDedupeState.guard.claim(messageId, dedupeOptions(namespace, log));
|
|
620
|
+
return claim.kind === "claimed" ? await claim.handle.commit() : false;
|
|
571
621
|
}
|
|
622
|
+
/** Forgets a recorded message so a retryable synthetic event can be handled on redelivery. */
|
|
572
623
|
async function forgetProcessedFeishuMessage(messageId, namespace = "global", log) {
|
|
573
|
-
|
|
574
|
-
const normalizedMessageId = normalizeMessageId(messageId);
|
|
575
|
-
if (!normalizedMessageId) return false;
|
|
576
|
-
memory.delete(memoryKey(normalizedNamespace, normalizedMessageId));
|
|
577
|
-
const key = dedupeStoreKey(normalizedNamespace, normalizedMessageId);
|
|
578
|
-
try {
|
|
579
|
-
return openDedupStore(normalizedNamespace).delete(key);
|
|
580
|
-
} catch (error) {
|
|
581
|
-
log?.(`feishu-dedup: persistent delete failed: ${String(error)}`);
|
|
582
|
-
return false;
|
|
583
|
-
}
|
|
624
|
+
return await feishuDedupeState.guard.forget(messageId, dedupeOptions(namespace, log));
|
|
584
625
|
}
|
|
626
|
+
/** Checks recency without claiming or recording. */
|
|
585
627
|
async function hasProcessedFeishuMessage(messageId, namespace = "global", log) {
|
|
586
|
-
|
|
587
|
-
if (!normalizedMessageId) return false;
|
|
588
|
-
return hasRecordedMessagePersistent(normalizedMessageId, namespace, log);
|
|
589
|
-
}
|
|
590
|
-
async function tryRecordMessagePersistent(messageId, namespace = "global", log) {
|
|
591
|
-
const normalizedNamespace = normalizeNamespace(namespace);
|
|
592
|
-
const normalizedMessageId = normalizeMessageId(messageId);
|
|
593
|
-
if (!normalizedMessageId) return true;
|
|
594
|
-
const now = Date.now();
|
|
595
|
-
if (hasMemory(normalizedNamespace, normalizedMessageId, now)) return false;
|
|
596
|
-
const key = dedupeStoreKey(normalizedNamespace, normalizedMessageId);
|
|
597
|
-
try {
|
|
598
|
-
const store = openDedupStore(normalizedNamespace);
|
|
599
|
-
const existingSeenAt = store.lookup(key)?.seenAt;
|
|
600
|
-
if (isRecent(existingSeenAt, now)) {
|
|
601
|
-
remember(normalizedNamespace, normalizedMessageId, existingSeenAt);
|
|
602
|
-
return false;
|
|
603
|
-
}
|
|
604
|
-
if (!store.registerIfAbsent(key, {
|
|
605
|
-
namespace: normalizedNamespace,
|
|
606
|
-
messageId: normalizedMessageId,
|
|
607
|
-
seenAt: now
|
|
608
|
-
}, { ttlMs: DEDUP_TTL_MS })) {
|
|
609
|
-
const currentSeenAt = store.lookup(key)?.seenAt;
|
|
610
|
-
if (isRecent(currentSeenAt, now)) {
|
|
611
|
-
remember(normalizedNamespace, normalizedMessageId, currentSeenAt);
|
|
612
|
-
return false;
|
|
613
|
-
}
|
|
614
|
-
store.register(key, {
|
|
615
|
-
namespace: normalizedNamespace,
|
|
616
|
-
messageId: normalizedMessageId,
|
|
617
|
-
seenAt: now
|
|
618
|
-
}, { ttlMs: DEDUP_TTL_MS });
|
|
619
|
-
}
|
|
620
|
-
remember(normalizedNamespace, normalizedMessageId, now);
|
|
621
|
-
return true;
|
|
622
|
-
} catch (error) {
|
|
623
|
-
log?.(`feishu-dedup: persistent state error, falling back to memory: ${String(error)}`);
|
|
624
|
-
remember(normalizedNamespace, normalizedMessageId, now);
|
|
625
|
-
return true;
|
|
626
|
-
}
|
|
627
|
-
}
|
|
628
|
-
async function hasRecordedMessagePersistent(messageId, namespace = "global", log) {
|
|
629
|
-
const normalizedNamespace = normalizeNamespace(namespace);
|
|
630
|
-
const normalizedMessageId = normalizeMessageId(messageId);
|
|
631
|
-
if (!normalizedMessageId) return false;
|
|
632
|
-
const now = Date.now();
|
|
633
|
-
if (hasMemory(normalizedNamespace, normalizedMessageId, now)) return true;
|
|
634
|
-
try {
|
|
635
|
-
const existingSeenAt = openDedupStore(normalizedNamespace).lookup(dedupeStoreKey(normalizedNamespace, normalizedMessageId))?.seenAt;
|
|
636
|
-
if (!isRecent(existingSeenAt, now)) return false;
|
|
637
|
-
remember(normalizedNamespace, normalizedMessageId, existingSeenAt);
|
|
638
|
-
return true;
|
|
639
|
-
} catch (error) {
|
|
640
|
-
log?.(`feishu-dedup: persistent peek failed: ${String(error)}`);
|
|
641
|
-
return hasMemory(normalizedNamespace, normalizedMessageId, now);
|
|
642
|
-
}
|
|
628
|
+
return await feishuDedupeState.guard.hasRecent(messageId, dedupeOptions(namespace, log));
|
|
643
629
|
}
|
|
630
|
+
/** Loads recent persisted entries into memory at account start; returns the loaded count. */
|
|
644
631
|
async function warmupDedupFromPluginState(namespace, log) {
|
|
645
|
-
|
|
646
|
-
try {
|
|
647
|
-
let loaded = 0;
|
|
648
|
-
const now = Date.now();
|
|
649
|
-
for (const entry of openDedupStore(normalizedNamespace).entries()) {
|
|
650
|
-
if (entry.value.namespace !== normalizedNamespace || !isRecent(entry.value.seenAt, now)) continue;
|
|
651
|
-
remember(normalizedNamespace, entry.value.messageId, entry.value.seenAt);
|
|
652
|
-
loaded++;
|
|
653
|
-
}
|
|
654
|
-
return loaded;
|
|
655
|
-
} catch (error) {
|
|
656
|
-
log?.(`feishu-dedup: warmup persistent state error: ${String(error)}`);
|
|
657
|
-
return 0;
|
|
658
|
-
}
|
|
632
|
+
return await feishuDedupeState.guard.warmup(namespace, (error) => log?.(`feishu-dedup: warmup persistent state error: ${String(error)}`));
|
|
659
633
|
}
|
|
660
634
|
//#endregion
|
|
661
635
|
//#region extensions/feishu/src/dedupe-key.ts
|
|
@@ -902,6 +876,16 @@ function resolveFeishuReasoningPreviewEnabled(params) {
|
|
|
902
876
|
return configDefault === "stream";
|
|
903
877
|
}
|
|
904
878
|
//#endregion
|
|
879
|
+
//#region extensions/feishu/src/reply-dispatcher-state.ts
|
|
880
|
+
const streamingStartBackoffUntilByAccount = /* @__PURE__ */ new Map();
|
|
881
|
+
//#endregion
|
|
882
|
+
//#region extensions/feishu/src/streaming-card-send-mode.ts
|
|
883
|
+
function resolveStreamingCardSendMode(options) {
|
|
884
|
+
if (options?.replyToMessageId) return "reply";
|
|
885
|
+
if (options?.rootId) return "root_create";
|
|
886
|
+
return "create";
|
|
887
|
+
}
|
|
888
|
+
//#endregion
|
|
905
889
|
//#region extensions/feishu/src/streaming-card.ts
|
|
906
890
|
const STREAMING_UPDATE_THROTTLE_MS = 160;
|
|
907
891
|
const STREAMING_SIGNIFICANT_DELTA_CHARS = 18;
|
|
@@ -926,6 +910,11 @@ function resolveAllowedHostnames(domain) {
|
|
|
926
910
|
}
|
|
927
911
|
return ["open.feishu.cn"];
|
|
928
912
|
}
|
|
913
|
+
async function assertSuccessfulCardKitResponse(response, auditContext, action) {
|
|
914
|
+
if (!response.ok) throw new Error(`${action} failed with HTTP ${response.status}`);
|
|
915
|
+
const data = await readFeishuJsonResponse(response, auditContext);
|
|
916
|
+
if (data.code !== 0) throw new Error(`${action} failed: ${data.msg ?? "unknown error"} (code=${String(data.code)})`);
|
|
917
|
+
}
|
|
929
918
|
async function getToken(creds, deps) {
|
|
930
919
|
const key = `${creds.domain ?? "feishu"}|${creds.appId}`;
|
|
931
920
|
const cached = tokenCache.get(key);
|
|
@@ -993,11 +982,6 @@ function mergeStreamingText(previousText, nextText) {
|
|
|
993
982
|
for (let overlap = maxOverlap; overlap > 0; overlap -= 1) if (previous.slice(-overlap) === next.slice(0, overlap)) return `${previous}${next.slice(overlap)}`;
|
|
994
983
|
return `${previous}${next}`;
|
|
995
984
|
}
|
|
996
|
-
function resolveStreamingCardSendMode(options) {
|
|
997
|
-
if (options?.replyToMessageId) return "reply";
|
|
998
|
-
if (options?.rootId) return "root_create";
|
|
999
|
-
return "create";
|
|
1000
|
-
}
|
|
1001
985
|
/** Streaming card session manager */
|
|
1002
986
|
var FeishuStreamingSession = class {
|
|
1003
987
|
constructor(client, creds, log, deps) {
|
|
@@ -1152,10 +1136,10 @@ var FeishuStreamingSession = class {
|
|
|
1152
1136
|
auditContext: "feishu.streaming-card.update",
|
|
1153
1137
|
timeoutMs: this.creds.httpTimeoutMs ?? 3e4
|
|
1154
1138
|
});
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1139
|
+
try {
|
|
1140
|
+
await assertSuccessfulCardKitResponse(response, "feishu.streaming-card.update", "Update card content");
|
|
1141
|
+
} finally {
|
|
1142
|
+
await release();
|
|
1159
1143
|
}
|
|
1160
1144
|
return true;
|
|
1161
1145
|
} catch (error) {
|
|
@@ -1196,10 +1180,10 @@ var FeishuStreamingSession = class {
|
|
|
1196
1180
|
auditContext: "feishu.streaming-card.replace",
|
|
1197
1181
|
timeoutMs: this.creds.httpTimeoutMs ?? 3e4
|
|
1198
1182
|
});
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1183
|
+
try {
|
|
1184
|
+
await assertSuccessfulCardKitResponse(response, "feishu.streaming-card.replace", "Replace card content");
|
|
1185
|
+
} finally {
|
|
1186
|
+
await release();
|
|
1203
1187
|
}
|
|
1204
1188
|
return true;
|
|
1205
1189
|
} catch (error) {
|
|
@@ -1218,35 +1202,35 @@ var FeishuStreamingSession = class {
|
|
|
1218
1202
|
const delayMs = Math.max(0, this.updateThrottleMs - (Date.now() - this.lastUpdateTime));
|
|
1219
1203
|
this.flushTimer = setTimeout(() => {
|
|
1220
1204
|
this.flushTimer = null;
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
this.
|
|
1205
|
+
if (!this.pendingText || this.closed) return;
|
|
1206
|
+
this.lastUpdateTime = Date.now();
|
|
1207
|
+
this.flushPendingUpdate().catch((error) => this.log?.(`Scheduled flush update failed: ${String(error)}`));
|
|
1224
1208
|
}, delayMs);
|
|
1225
1209
|
}
|
|
1210
|
+
async flushPendingUpdate() {
|
|
1211
|
+
this.queue = this.queue.then(async () => {
|
|
1212
|
+
if (!this.state || this.closed) return;
|
|
1213
|
+
const nextText = this.pendingText;
|
|
1214
|
+
if (!nextText) return;
|
|
1215
|
+
this.pendingText = null;
|
|
1216
|
+
if (nextText === this.state.sentText) return;
|
|
1217
|
+
if (await this.updateCardContent(nextText, (e) => this.log?.(`Update failed: ${String(e)}`)) && this.state) this.state.sentText = nextText;
|
|
1218
|
+
});
|
|
1219
|
+
await this.queue;
|
|
1220
|
+
}
|
|
1226
1221
|
async update(text) {
|
|
1227
|
-
if (!this.state || this.closed) return;
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
this.pendingText = mergedInput;
|
|
1222
|
+
if (!this.state || this.closed || !text) return;
|
|
1223
|
+
this.state.currentText = text;
|
|
1224
|
+
this.pendingText = text;
|
|
1231
1225
|
this.clearFlushTimer();
|
|
1232
|
-
const shouldForceUpdate = shouldPushStreamingUpdate(this.state.
|
|
1226
|
+
const shouldForceUpdate = shouldPushStreamingUpdate(this.state.sentText, text);
|
|
1233
1227
|
const now = Date.now();
|
|
1234
1228
|
if (!shouldForceUpdate && now - this.lastUpdateTime < this.updateThrottleMs) {
|
|
1235
1229
|
this.schedulePendingFlush();
|
|
1236
1230
|
return;
|
|
1237
1231
|
}
|
|
1238
1232
|
this.lastUpdateTime = now;
|
|
1239
|
-
|
|
1240
|
-
if (!this.state || this.closed) return;
|
|
1241
|
-
const nextText = this.pendingText ?? mergedInput;
|
|
1242
|
-
const mergedText = mergeStreamingText(this.state.currentText, nextText);
|
|
1243
|
-
if (!mergedText || mergedText === this.state.currentText) return;
|
|
1244
|
-
if (mergedText === this.state.sentText) return;
|
|
1245
|
-
this.pendingText = null;
|
|
1246
|
-
this.state.currentText = mergedText;
|
|
1247
|
-
if (await this.updateCardContent(mergedText, (e) => this.log?.(`Update failed: ${String(e)}`)) && this.state) this.state.sentText = mergedText;
|
|
1248
|
-
});
|
|
1249
|
-
await this.queue;
|
|
1233
|
+
await this.flushPendingUpdate();
|
|
1250
1234
|
}
|
|
1251
1235
|
async updateNoteContent(note) {
|
|
1252
1236
|
if (!this.state || !this.state.hasNote) return;
|
|
@@ -1275,8 +1259,12 @@ var FeishuStreamingSession = class {
|
|
|
1275
1259
|
policy: { allowedHostnames: resolveAllowedHostnames(this.creds.domain) },
|
|
1276
1260
|
auditContext: "feishu.streaming-card.note-update",
|
|
1277
1261
|
timeoutMs: this.creds.httpTimeoutMs ?? 3e4
|
|
1278
|
-
}).then(async ({ release }) => {
|
|
1279
|
-
|
|
1262
|
+
}).then(async ({ response, release }) => {
|
|
1263
|
+
try {
|
|
1264
|
+
await assertSuccessfulCardKitResponse(response, "feishu.streaming-card.note-update", "Update card note");
|
|
1265
|
+
} finally {
|
|
1266
|
+
await release();
|
|
1267
|
+
}
|
|
1280
1268
|
}).catch((e) => this.log?.(`Note update failed: ${String(e)}`));
|
|
1281
1269
|
}
|
|
1282
1270
|
async close(finalText, options) {
|
|
@@ -1284,8 +1272,7 @@ var FeishuStreamingSession = class {
|
|
|
1284
1272
|
this.closed = true;
|
|
1285
1273
|
this.clearFlushTimer();
|
|
1286
1274
|
await this.queue;
|
|
1287
|
-
const
|
|
1288
|
-
const text = finalText ?? pendingMerged;
|
|
1275
|
+
const text = finalText ?? this.pendingText ?? this.state.currentText;
|
|
1289
1276
|
const apiBase = resolveApiBase(this.creds.domain);
|
|
1290
1277
|
let visibleContentSent = Boolean(this.state.sentText.trim());
|
|
1291
1278
|
if ((text || finalText !== void 0) && text !== this.state.sentText) {
|
|
@@ -1297,6 +1284,7 @@ var FeishuStreamingSession = class {
|
|
|
1297
1284
|
}
|
|
1298
1285
|
}
|
|
1299
1286
|
if (options?.note) await this.updateNoteContent(options.note);
|
|
1287
|
+
const acceptedText = this.state.sentText;
|
|
1300
1288
|
this.state.sequence += 1;
|
|
1301
1289
|
await fetchWithSsrFGuard({
|
|
1302
1290
|
url: `${apiBase}/cardkit/v1/cards/${this.state.cardId}/settings`,
|
|
@@ -1313,7 +1301,7 @@ var FeishuStreamingSession = class {
|
|
|
1313
1301
|
body: JSON.stringify({
|
|
1314
1302
|
settings: JSON.stringify({ config: {
|
|
1315
1303
|
streaming_mode: false,
|
|
1316
|
-
summary: { content: truncateSummary(
|
|
1304
|
+
summary: { content: truncateSummary(acceptedText) }
|
|
1317
1305
|
} }),
|
|
1318
1306
|
sequence: this.state.sequence,
|
|
1319
1307
|
uuid: `c_${this.state.cardId}_${this.state.sequence}`
|
|
@@ -1324,8 +1312,12 @@ var FeishuStreamingSession = class {
|
|
|
1324
1312
|
policy: { allowedHostnames: resolveAllowedHostnames(this.creds.domain) },
|
|
1325
1313
|
auditContext: "feishu.streaming-card.close",
|
|
1326
1314
|
timeoutMs: this.creds.httpTimeoutMs ?? 3e4
|
|
1327
|
-
}).then(async ({ release }) => {
|
|
1328
|
-
|
|
1315
|
+
}).then(async ({ response, release }) => {
|
|
1316
|
+
try {
|
|
1317
|
+
await assertSuccessfulCardKitResponse(response, "feishu.streaming-card.close", "Close streaming card");
|
|
1318
|
+
} finally {
|
|
1319
|
+
await release();
|
|
1320
|
+
}
|
|
1329
1321
|
}).catch((e) => this.log?.(`Close failed: ${String(e)}`));
|
|
1330
1322
|
const finalState = this.state;
|
|
1331
1323
|
this.state = null;
|
|
@@ -1356,29 +1348,13 @@ var FeishuStreamingSession = class {
|
|
|
1356
1348
|
}
|
|
1357
1349
|
};
|
|
1358
1350
|
//#endregion
|
|
1359
|
-
//#region extensions/feishu/src/typing.ts
|
|
1360
|
-
|
|
1361
|
-
/**
|
|
1362
|
-
* Feishu API error codes that indicate the caller should back off.
|
|
1363
|
-
* These must propagate to the typing circuit breaker so the keepalive loop
|
|
1364
|
-
* can trip and stop retrying.
|
|
1365
|
-
*
|
|
1366
|
-
* - 99991400: Rate limit (too many requests per second)
|
|
1367
|
-
* - 99991403: Monthly API call quota exceeded
|
|
1368
|
-
* - 429: Standard HTTP 429 returned as a Feishu SDK error code
|
|
1369
|
-
*
|
|
1370
|
-
* @see https://open.feishu.cn/document/server-docs/api-call-guide/generic-error-code
|
|
1371
|
-
*/
|
|
1351
|
+
//#region extensions/feishu/src/typing-backoff.ts
|
|
1352
|
+
/** Feishu API codes that should trip the typing circuit breaker. */
|
|
1372
1353
|
const FEISHU_BACKOFF_CODES = /* @__PURE__ */ new Set([
|
|
1373
1354
|
99991400,
|
|
1374
1355
|
99991403,
|
|
1375
1356
|
429
|
|
1376
1357
|
]);
|
|
1377
|
-
/**
|
|
1378
|
-
* Custom error class for Feishu backoff conditions detected from non-throwing
|
|
1379
|
-
* SDK responses. Carries a numeric `.code` so that `isFeishuBackoffError()`
|
|
1380
|
-
* recognises it when the error is caught downstream.
|
|
1381
|
-
*/
|
|
1382
1358
|
var FeishuBackoffError = class extends Error {
|
|
1383
1359
|
constructor(code) {
|
|
1384
1360
|
super(`Feishu API backoff: code ${code}`);
|
|
@@ -1386,14 +1362,6 @@ var FeishuBackoffError = class extends Error {
|
|
|
1386
1362
|
this.code = code;
|
|
1387
1363
|
}
|
|
1388
1364
|
};
|
|
1389
|
-
/**
|
|
1390
|
-
* Check whether an error represents a rate-limit or quota-exceeded condition
|
|
1391
|
-
* from the Feishu API that should stop the typing keepalive loop.
|
|
1392
|
-
*
|
|
1393
|
-
* Handles two shapes:
|
|
1394
|
-
* 1. AxiosError with `response.status` and `response.data.code`
|
|
1395
|
-
* 2. Feishu SDK error with a top-level `code` property
|
|
1396
|
-
*/
|
|
1397
1365
|
function isFeishuBackoffError(err) {
|
|
1398
1366
|
if (typeof err !== "object" || err === null) return false;
|
|
1399
1367
|
const response = err.response;
|
|
@@ -1402,21 +1370,16 @@ function isFeishuBackoffError(err) {
|
|
|
1402
1370
|
if (typeof response.data?.code === "number" && FEISHU_BACKOFF_CODES.has(response.data.code)) return true;
|
|
1403
1371
|
}
|
|
1404
1372
|
const code = err.code;
|
|
1405
|
-
|
|
1406
|
-
return false;
|
|
1373
|
+
return typeof code === "number" && FEISHU_BACKOFF_CODES.has(code);
|
|
1407
1374
|
}
|
|
1408
|
-
/**
|
|
1409
|
-
* Check whether a Feishu SDK response object contains a backoff error code.
|
|
1410
|
-
*
|
|
1411
|
-
* The Feishu SDK sometimes returns a normal response (no throw) with an
|
|
1412
|
-
* API-level error code in the response body. This must be detected so the
|
|
1413
|
-
* circuit breaker can trip. See codex review on #28157.
|
|
1414
|
-
*/
|
|
1415
1375
|
function getBackoffCodeFromResponse(response) {
|
|
1416
1376
|
if (typeof response !== "object" || response === null) return;
|
|
1417
1377
|
const code = response.code;
|
|
1418
|
-
|
|
1378
|
+
return typeof code === "number" && FEISHU_BACKOFF_CODES.has(code) ? code : void 0;
|
|
1419
1379
|
}
|
|
1380
|
+
//#endregion
|
|
1381
|
+
//#region extensions/feishu/src/typing.ts
|
|
1382
|
+
const TYPING_EMOJI = "Typing";
|
|
1420
1383
|
/**
|
|
1421
1384
|
* Add a typing indicator (reaction) to a message.
|
|
1422
1385
|
*
|
|
@@ -1512,7 +1475,6 @@ const TYPING_INDICATOR_MAX_AGE_MS = 2 * 6e4;
|
|
|
1512
1475
|
const MS_EPOCH_MIN = 0xe8d4a51000;
|
|
1513
1476
|
const STREAMING_START_FAILURE_BACKOFF_MS = 6e4;
|
|
1514
1477
|
const NO_VISIBLE_REPLY_FALLBACK_TEXT = "⚠️ This reply completed without visible content. The turn may have been interrupted; please retry or ask me to recover from recent context.";
|
|
1515
|
-
const streamingStartBackoffUntilByAccount = /* @__PURE__ */ new Map();
|
|
1516
1478
|
function isStreamingStartBackedOff(accountId, now = Date.now()) {
|
|
1517
1479
|
const backoffUntil = streamingStartBackoffUntilByAccount.get(accountId);
|
|
1518
1480
|
if (backoffUntil === void 0) return false;
|
|
@@ -1615,14 +1577,15 @@ function createFeishuReplyDispatcher(params) {
|
|
|
1615
1577
|
}
|
|
1616
1578
|
});
|
|
1617
1579
|
const textChunkLimit = core.channel.text.resolveTextChunkLimit(cfg, "feishu", accountId, { fallbackLimit: 4e3 });
|
|
1618
|
-
const chunkMode = core.channel.text.resolveChunkMode(cfg, "feishu");
|
|
1580
|
+
const chunkMode = core.channel.text.resolveChunkMode(cfg, "feishu", accountId);
|
|
1619
1581
|
const tableMode = core.channel.text.resolveMarkdownTableMode({
|
|
1620
1582
|
cfg,
|
|
1621
1583
|
channel: "feishu"
|
|
1622
1584
|
});
|
|
1623
1585
|
const renderMode = account.config?.renderMode ?? "auto";
|
|
1624
|
-
const streamingEnabled = account.config
|
|
1625
|
-
const
|
|
1586
|
+
const streamingEnabled = resolveChannelPreviewStreamMode(account.config, "partial") !== "off" && renderMode !== "raw";
|
|
1587
|
+
const blockStreamingEnabled = resolveChannelStreamingBlockEnabled(account.config);
|
|
1588
|
+
const coreBlockStreamingEnabled = blockStreamingEnabled === true;
|
|
1626
1589
|
const reasoningPreviewEnabled = streamingEnabled && params.allowReasoningPreview === true;
|
|
1627
1590
|
let streaming = null;
|
|
1628
1591
|
let streamText = "";
|
|
@@ -1761,8 +1724,15 @@ function createFeishuReplyDispatcher(params) {
|
|
|
1761
1724
|
flushStreamingCardUpdate(buildCombinedStreamText(reasoningText, streamText));
|
|
1762
1725
|
};
|
|
1763
1726
|
const sendChunkedTextReply = async (paramsLocal) => {
|
|
1764
|
-
const chunkSource = paramsLocal.useCard ? paramsLocal.text : core.channel.text.convertMarkdownTables(paramsLocal.text, tableMode);
|
|
1765
|
-
const
|
|
1727
|
+
const chunkSource = paramsLocal.useCard ? paramsLocal.text : materializeFeishuPostMarkdownSoftBreaks(core.channel.text.convertMarkdownTables(paramsLocal.text, tableMode));
|
|
1728
|
+
const initialChunks = core.channel.text.chunkMarkdownTextWithMode(chunkSource, textChunkLimit, chunkMode);
|
|
1729
|
+
const chunks = resolveTextChunksWithFallback(chunkSource, paramsLocal.useCard ? initialChunks : chunkFeishuPostMarkdown({
|
|
1730
|
+
text: chunkSource,
|
|
1731
|
+
limit: textChunkLimit,
|
|
1732
|
+
mode: chunkMode,
|
|
1733
|
+
firstChunkMentions: paramsLocal.firstChunkMentions,
|
|
1734
|
+
initialChunks
|
|
1735
|
+
}));
|
|
1766
1736
|
for (const [index, chunk] of chunks.entries()) {
|
|
1767
1737
|
await paramsLocal.sendChunk({
|
|
1768
1738
|
chunk,
|
|
@@ -1914,11 +1884,12 @@ function createFeishuReplyDispatcher(params) {
|
|
|
1914
1884
|
if (info?.kind === "block") {
|
|
1915
1885
|
if (!useStreamingCard) {
|
|
1916
1886
|
if (coreBlockStreamingEnabled) {
|
|
1917
|
-
const
|
|
1887
|
+
const firstChunkMentions = !sentIndependentBlockText && mentionTargets?.length ? mentionTargets : void 0;
|
|
1918
1888
|
await sendChunkedTextReply({
|
|
1919
1889
|
text,
|
|
1920
1890
|
useCard: false,
|
|
1921
1891
|
infoKind: "block",
|
|
1892
|
+
firstChunkMentions,
|
|
1922
1893
|
sendChunk: async ({ chunk, isFirst }) => {
|
|
1923
1894
|
await sendMessageFeishu({
|
|
1924
1895
|
cfg,
|
|
@@ -1928,7 +1899,7 @@ function createFeishuReplyDispatcher(params) {
|
|
|
1928
1899
|
replyInThread: effectiveReplyInThread,
|
|
1929
1900
|
allowTopLevelReplyFallback,
|
|
1930
1901
|
accountId,
|
|
1931
|
-
...
|
|
1902
|
+
...isFirst && firstChunkMentions ? { mentions: firstChunkMentions } : {}
|
|
1932
1903
|
});
|
|
1933
1904
|
}
|
|
1934
1905
|
});
|
|
@@ -1981,23 +1952,27 @@ function createFeishuReplyDispatcher(params) {
|
|
|
1981
1952
|
});
|
|
1982
1953
|
}
|
|
1983
1954
|
});
|
|
1984
|
-
} else
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
1955
|
+
} else {
|
|
1956
|
+
const firstChunkMentions = info?.kind === "final" && mentionTargets?.length ? mentionTargets : void 0;
|
|
1957
|
+
await sendChunkedTextReply({
|
|
1958
|
+
text,
|
|
1959
|
+
useCard: false,
|
|
1960
|
+
infoKind: info?.kind,
|
|
1961
|
+
firstChunkMentions,
|
|
1962
|
+
sendChunk: async ({ chunk, isFirst }) => {
|
|
1963
|
+
await sendMessageFeishu({
|
|
1964
|
+
cfg,
|
|
1965
|
+
to: sendTarget,
|
|
1966
|
+
text: chunk,
|
|
1967
|
+
replyToMessageId: sendReplyToMessageId,
|
|
1968
|
+
replyInThread: effectiveReplyInThread,
|
|
1969
|
+
allowTopLevelReplyFallback,
|
|
1970
|
+
accountId,
|
|
1971
|
+
...isFirst && firstChunkMentions ? { mentions: firstChunkMentions } : {}
|
|
1972
|
+
});
|
|
1973
|
+
}
|
|
1974
|
+
});
|
|
1975
|
+
}
|
|
2001
1976
|
}
|
|
2002
1977
|
if (hasMedia) await sendMediaReplies(payload, hasVoiceMedia && hasText ? { fallbackText: text } : void 0);
|
|
2003
1978
|
},
|
|
@@ -2017,7 +1992,7 @@ function createFeishuReplyDispatcher(params) {
|
|
|
2017
1992
|
replyOptions: {
|
|
2018
1993
|
...replyOptions,
|
|
2019
1994
|
onModelSelected: prefixContext.onModelSelected,
|
|
2020
|
-
disableBlockStreaming: typeof
|
|
1995
|
+
disableBlockStreaming: typeof blockStreamingEnabled === "boolean" ? !blockStreamingEnabled : true,
|
|
2021
1996
|
onPartialReply: streamingEnabled ? (payload) => {
|
|
2022
1997
|
if (!payload.text) return;
|
|
2023
1998
|
const cleaned = stripReasoningTagsFromText(payload.text, {
|
|
@@ -2069,9 +2044,6 @@ function createFeishuReplyDispatcher(params) {
|
|
|
2069
2044
|
//#region extensions/feishu/src/bot.ts
|
|
2070
2045
|
const permissionErrorNotifiedAt = /* @__PURE__ */ new Map();
|
|
2071
2046
|
const PERMISSION_ERROR_COOLDOWN_MS = 300 * 1e3;
|
|
2072
|
-
const groupNameCache = /* @__PURE__ */ new Map();
|
|
2073
|
-
const GROUP_NAME_CACHE_TTL_MS = 1800 * 1e3;
|
|
2074
|
-
const GROUP_NAME_CACHE_MAX_SIZE = 500;
|
|
2075
2047
|
function shouldSendNoVisibleReplyFallback(dispatchResult) {
|
|
2076
2048
|
const finalCount = dispatchResult.counts.final ?? 0;
|
|
2077
2049
|
const failedFinalCount = dispatchResult.failedCounts?.final ?? 0;
|
|
@@ -2082,59 +2054,6 @@ function shouldSendNoVisibleReplyFallback(dispatchResult) {
|
|
|
2082
2054
|
function isFeishuTopicSessionScope(scope) {
|
|
2083
2055
|
return scope === "group_topic" || scope === "group_topic_sender";
|
|
2084
2056
|
}
|
|
2085
|
-
function evictGroupNameCache() {
|
|
2086
|
-
const now = asDateTimestampMs(Date.now());
|
|
2087
|
-
if (now === void 0) {
|
|
2088
|
-
groupNameCache.clear();
|
|
2089
|
-
return;
|
|
2090
|
-
}
|
|
2091
|
-
for (const [key, val] of groupNameCache) {
|
|
2092
|
-
const expiresAt = asDateTimestampMs(val.expiresAt);
|
|
2093
|
-
if (expiresAt === void 0 || expiresAt <= now) groupNameCache.delete(key);
|
|
2094
|
-
}
|
|
2095
|
-
if (groupNameCache.size > GROUP_NAME_CACHE_MAX_SIZE) {
|
|
2096
|
-
const excess = groupNameCache.size - GROUP_NAME_CACHE_MAX_SIZE;
|
|
2097
|
-
let removed = 0;
|
|
2098
|
-
for (const key of groupNameCache.keys()) {
|
|
2099
|
-
if (removed >= excess) break;
|
|
2100
|
-
groupNameCache.delete(key);
|
|
2101
|
-
removed++;
|
|
2102
|
-
}
|
|
2103
|
-
}
|
|
2104
|
-
}
|
|
2105
|
-
function setCacheEntry(key, name) {
|
|
2106
|
-
const expiresAt = resolveExpiresAtMsFromDurationMs(GROUP_NAME_CACHE_TTL_MS);
|
|
2107
|
-
groupNameCache.delete(key);
|
|
2108
|
-
if (expiresAt !== void 0) groupNameCache.set(key, {
|
|
2109
|
-
name,
|
|
2110
|
-
expiresAt
|
|
2111
|
-
});
|
|
2112
|
-
}
|
|
2113
|
-
async function resolveGroupName(params) {
|
|
2114
|
-
const { account, chatId, log } = params;
|
|
2115
|
-
if (!account.configured) return;
|
|
2116
|
-
const cacheKey = `${account.accountId}:${chatId}`;
|
|
2117
|
-
const cached = groupNameCache.get(cacheKey);
|
|
2118
|
-
if (cached) {
|
|
2119
|
-
const now = asDateTimestampMs(Date.now());
|
|
2120
|
-
const expiresAt = asDateTimestampMs(cached.expiresAt);
|
|
2121
|
-
if (now !== void 0 && expiresAt !== void 0 && expiresAt > now) return cached.name || void 0;
|
|
2122
|
-
groupNameCache.delete(cacheKey);
|
|
2123
|
-
}
|
|
2124
|
-
let resolvedName;
|
|
2125
|
-
try {
|
|
2126
|
-
const name = (await getChatInfo(createFeishuClient(account), chatId))?.name?.trim();
|
|
2127
|
-
if (name) {
|
|
2128
|
-
setCacheEntry(cacheKey, name);
|
|
2129
|
-
resolvedName = name;
|
|
2130
|
-
} else setCacheEntry(cacheKey, "");
|
|
2131
|
-
} catch (err) {
|
|
2132
|
-
log(`feishu[${account.accountId}]: getChatInfo failed for ${chatId}: ${String(err)}`);
|
|
2133
|
-
setCacheEntry(cacheKey, "");
|
|
2134
|
-
}
|
|
2135
|
-
evictGroupNameCache();
|
|
2136
|
-
return resolvedName;
|
|
2137
|
-
}
|
|
2138
2057
|
async function resolveFeishuAudioPreflightTranscript(params) {
|
|
2139
2058
|
if (params.content.trim() !== "<media:audio>") return;
|
|
2140
2059
|
const audioMedia = params.mediaList.filter((media) => media.contentType?.startsWith("audio/"));
|
|
@@ -2154,18 +2073,6 @@ async function resolveFeishuAudioPreflightTranscript(params) {
|
|
|
2154
2073
|
return;
|
|
2155
2074
|
}
|
|
2156
2075
|
}
|
|
2157
|
-
function resolveBroadcastAgents(cfg, peerId) {
|
|
2158
|
-
const broadcast = cfg.broadcast;
|
|
2159
|
-
if (!broadcast || typeof broadcast !== "object") return null;
|
|
2160
|
-
const agents = broadcast[peerId];
|
|
2161
|
-
if (!Array.isArray(agents) || agents.length === 0) return null;
|
|
2162
|
-
return agents;
|
|
2163
|
-
}
|
|
2164
|
-
function buildBroadcastSessionKey(baseSessionKey, originalAgentId, targetAgentId) {
|
|
2165
|
-
const prefix = `agent:${originalAgentId}:`;
|
|
2166
|
-
if (baseSessionKey.startsWith(prefix)) return `agent:${targetAgentId}:${baseSessionKey.slice(prefix.length)}`;
|
|
2167
|
-
return baseSessionKey;
|
|
2168
|
-
}
|
|
2169
2076
|
/**
|
|
2170
2077
|
* Build media payload for inbound context.
|
|
2171
2078
|
* Similar to Discord's buildDiscordMediaPayload().
|
|
@@ -2202,35 +2109,6 @@ function parseFeishuMessageEvent(event, botOpenId, _botName) {
|
|
|
2202
2109
|
}
|
|
2203
2110
|
return ctx;
|
|
2204
2111
|
}
|
|
2205
|
-
const MAX_MENTION_CONTEXT_NAME_LENGTH = 80;
|
|
2206
|
-
function formatMentionNameForAgentContext(name) {
|
|
2207
|
-
const normalized = Array.from(name, (char) => {
|
|
2208
|
-
return char.charCodeAt(0) < 32 || char === "[" || char === "]" ? " " : char;
|
|
2209
|
-
}).join("").replace(/\s+/g, " ").trim();
|
|
2210
|
-
const bounded = normalized.length > MAX_MENTION_CONTEXT_NAME_LENGTH ? `${truncateUtf16Safe(normalized, MAX_MENTION_CONTEXT_NAME_LENGTH - 3)}...` : normalized;
|
|
2211
|
-
return JSON.stringify(bounded || "unknown");
|
|
2212
|
-
}
|
|
2213
|
-
function buildFeishuAgentBody(params) {
|
|
2214
|
-
const { ctx, quotedContent, permissionErrorForAgent, botOpenId } = params;
|
|
2215
|
-
let messageBody = ctx.content;
|
|
2216
|
-
if (quotedContent) messageBody = `[Replying to: "${quotedContent}"]\n\n${ctx.content}`;
|
|
2217
|
-
messageBody = `${ctx.senderName ?? ctx.senderOpenId}: ${messageBody}`;
|
|
2218
|
-
if (ctx.hasAnyMention) {
|
|
2219
|
-
const botIdHint = botOpenId?.trim();
|
|
2220
|
-
messageBody += "\n\n[System: The content may include mention tags in the form <at user_id=\"...\">name</at>. Treat these as real mentions of Feishu entities (users or bots).]";
|
|
2221
|
-
if (botIdHint) messageBody += `\n[System: If user_id is "${botIdHint}", that mention refers to you.]`;
|
|
2222
|
-
}
|
|
2223
|
-
if (ctx.mentionTargets && ctx.mentionTargets.length > 0) {
|
|
2224
|
-
const targetNames = ctx.mentionTargets.map((t) => formatMentionNameForAgentContext(t.name)).join(", ");
|
|
2225
|
-
messageBody += `\n\n[System: Feishu users mentioned in the incoming message, for context only: ${targetNames}. Do not notify or mention these users solely because they are listed here.]`;
|
|
2226
|
-
}
|
|
2227
|
-
messageBody = `[message_id: ${ctx.messageId}]\n${messageBody}`;
|
|
2228
|
-
if (permissionErrorForAgent) {
|
|
2229
|
-
const grantUrl = permissionErrorForAgent.grantUrl ?? "";
|
|
2230
|
-
messageBody += `\n\n[System: The bot encountered a Feishu API permission error. Please inform the user about this issue and provide the permission grant URL for the admin to authorize. Permission grant URL: ${grantUrl}]`;
|
|
2231
|
-
}
|
|
2232
|
-
return messageBody;
|
|
2233
|
-
}
|
|
2234
2112
|
async function shouldIncludeFetchedGroupContextMessage(params) {
|
|
2235
2113
|
let senderAllowed = !params.isGroup || params.allowFrom.length === 0 || params.senderType === "app";
|
|
2236
2114
|
const senderId = params.senderId?.trim();
|
|
@@ -2264,7 +2142,7 @@ async function filterFetchedGroupContextMessages(messages, params) {
|
|
|
2264
2142
|
}) ? message : void 0))).filter((message) => message !== void 0);
|
|
2265
2143
|
}
|
|
2266
2144
|
async function handleFeishuMessage(params) {
|
|
2267
|
-
const { cfg, event, botOpenId, botName, runtime, channelRuntime, chatHistories, accountId,
|
|
2145
|
+
const { cfg, event, botOpenId, botName, runtime, channelRuntime, chatHistories, accountId, processingClaim, messageDedupeKey: messageDedupeKeyOverride } = params;
|
|
2268
2146
|
const account = resolveFeishuRuntimeAccount({
|
|
2269
2147
|
cfg,
|
|
2270
2148
|
accountId
|
|
@@ -2278,7 +2156,7 @@ async function handleFeishuMessage(params) {
|
|
|
2278
2156
|
messageId: messageDedupeKey,
|
|
2279
2157
|
namespace: account.accountId,
|
|
2280
2158
|
log,
|
|
2281
|
-
|
|
2159
|
+
processingClaim
|
|
2282
2160
|
})) {
|
|
2283
2161
|
log(`feishu: skipping duplicate message ${messageId}`);
|
|
2284
2162
|
return;
|
|
@@ -2916,6 +2794,7 @@ async function handleFeishuMessage(params) {
|
|
|
2916
2794
|
conversation: {
|
|
2917
2795
|
kind: isGroup ? "group" : "direct",
|
|
2918
2796
|
id: ctx.chatId,
|
|
2797
|
+
nativeChannelId: ctx.chatId,
|
|
2919
2798
|
label: isGroup && groupName && !isTopicSessionForThread ? groupName : void 0,
|
|
2920
2799
|
threadId: ctx.rootId && isTopicSessionForThread ? ctx.rootId : void 0
|
|
2921
2800
|
},
|
|
@@ -2942,7 +2821,7 @@ async function handleFeishuMessage(params) {
|
|
|
2942
2821
|
wasMentioned,
|
|
2943
2822
|
requireMention
|
|
2944
2823
|
},
|
|
2945
|
-
commands: { authorized: commandAuthorized }
|
|
2824
|
+
commands: { authorized: commandAuthorized === true }
|
|
2946
2825
|
},
|
|
2947
2826
|
extra: {
|
|
2948
2827
|
RootMessageId: ctx.rootId,
|
|
@@ -2985,7 +2864,7 @@ async function handleFeishuMessage(params) {
|
|
|
2985
2864
|
};
|
|
2986
2865
|
};
|
|
2987
2866
|
if (broadcastAgents) {
|
|
2988
|
-
if (!await
|
|
2867
|
+
if (!await recordProcessedFeishuMessage(messageDedupeKey ?? ctx.messageId, "broadcast", log)) {
|
|
2989
2868
|
log(`feishu[${account.accountId}]: broadcast already claimed by another account for message ${ctx.messageId}; skipping`);
|
|
2990
2869
|
return;
|
|
2991
2870
|
}
|
|
@@ -3146,7 +3025,11 @@ async function handleFeishuMessage(params) {
|
|
|
3146
3025
|
}
|
|
3147
3026
|
else {
|
|
3148
3027
|
const results = await Promise.allSettled(broadcastAgents.map(dispatchForAgent));
|
|
3149
|
-
for (
|
|
3028
|
+
for (const [i, result] of results.entries()) if (result.status === "rejected") {
|
|
3029
|
+
const agentId = broadcastAgents.at(i);
|
|
3030
|
+
if (agentId === void 0) continue;
|
|
3031
|
+
log(`feishu[${account.accountId}]: broadcast dispatch failed for agent=${agentId}: ${String(result.reason)}`);
|
|
3032
|
+
}
|
|
3150
3033
|
}
|
|
3151
3034
|
if (isGroup && historyKey && chatHistories) createChannelHistoryWindow({ historyMap: chatHistories }).clear({
|
|
3152
3035
|
historyKey,
|
|
@@ -3255,6 +3138,10 @@ async function handleFeishuMessage(params) {
|
|
|
3255
3138
|
}
|
|
3256
3139
|
}
|
|
3257
3140
|
//#endregion
|
|
3141
|
+
//#region extensions/feishu/src/card-action-state.ts
|
|
3142
|
+
const processedCardActions = /* @__PURE__ */ new Map();
|
|
3143
|
+
const resolvedCardActionChatTypes = /* @__PURE__ */ new Map();
|
|
3144
|
+
//#endregion
|
|
3258
3145
|
//#region extensions/feishu/src/card-ux-shared.ts
|
|
3259
3146
|
function buildFeishuCardButton(params) {
|
|
3260
3147
|
return {
|
|
@@ -3322,20 +3209,13 @@ function createApprovalCard(params) {
|
|
|
3322
3209
|
//#region extensions/feishu/src/card-action.ts
|
|
3323
3210
|
const FEISHU_APPROVAL_CARD_TTL_MS = 5 * 6e4;
|
|
3324
3211
|
const FEISHU_CARD_ACTION_TOKEN_TTL_MS = 15 * 6e4;
|
|
3325
|
-
const processedCardActionTokens = /* @__PURE__ */ new Map();
|
|
3326
|
-
var FeishuRetryableCardActionError = class extends Error {
|
|
3327
|
-
constructor(message, options) {
|
|
3328
|
-
super(message, options);
|
|
3329
|
-
this.name = "FeishuRetryableCardActionError";
|
|
3330
|
-
}
|
|
3331
|
-
};
|
|
3332
3212
|
function pruneProcessedCardActionTokens(now) {
|
|
3333
3213
|
const validNow = asDateTimestampMs(now);
|
|
3334
3214
|
if (validNow === void 0) {
|
|
3335
|
-
|
|
3215
|
+
processedCardActions.clear();
|
|
3336
3216
|
return;
|
|
3337
3217
|
}
|
|
3338
|
-
for (const [key, entry] of
|
|
3218
|
+
for (const [key, entry] of processedCardActions.entries()) if (!isFutureDateTimestampMs(entry.expiresAt, { nowMs: validNow })) processedCardActions.delete(key);
|
|
3339
3219
|
}
|
|
3340
3220
|
function resolveProcessedCardActionTokenExpiresAt(now) {
|
|
3341
3221
|
return resolveExpiresAtMsFromDurationMs(FEISHU_CARD_ACTION_TOKEN_TTL_MS, { nowMs: now });
|
|
@@ -3346,36 +3226,30 @@ function beginFeishuCardActionToken(params) {
|
|
|
3346
3226
|
const normalizedToken = params.token.trim();
|
|
3347
3227
|
if (!normalizedToken) return false;
|
|
3348
3228
|
const key = `${params.accountId}:${normalizedToken}`;
|
|
3349
|
-
const existing =
|
|
3229
|
+
const existing = processedCardActions.get(key);
|
|
3350
3230
|
if (existing && isFutureDateTimestampMs(existing.expiresAt, { nowMs: now })) return false;
|
|
3351
|
-
|
|
3231
|
+
processedCardActions.delete(key);
|
|
3352
3232
|
const expiresAt = resolveProcessedCardActionTokenExpiresAt(now);
|
|
3353
|
-
if (expiresAt !== void 0)
|
|
3233
|
+
if (expiresAt !== void 0) processedCardActions.set(key, {
|
|
3354
3234
|
status: "inflight",
|
|
3355
3235
|
expiresAt
|
|
3356
3236
|
});
|
|
3357
3237
|
return true;
|
|
3358
3238
|
}
|
|
3359
|
-
function
|
|
3360
|
-
const
|
|
3361
|
-
|
|
3362
|
-
|
|
3363
|
-
const key = `${params.accountId}:${normalizedToken}`;
|
|
3239
|
+
function completeFeishuCardAction(actionId, accountId, now = Date.now()) {
|
|
3240
|
+
const normalizedActionId = actionId.trim();
|
|
3241
|
+
if (!normalizedActionId) return;
|
|
3242
|
+
const key = `${accountId}:${normalizedActionId}`;
|
|
3364
3243
|
const expiresAt = resolveProcessedCardActionTokenExpiresAt(now);
|
|
3365
3244
|
if (expiresAt === void 0) {
|
|
3366
|
-
|
|
3245
|
+
processedCardActions.delete(key);
|
|
3367
3246
|
return;
|
|
3368
3247
|
}
|
|
3369
|
-
|
|
3248
|
+
processedCardActions.set(key, {
|
|
3370
3249
|
status: "completed",
|
|
3371
3250
|
expiresAt
|
|
3372
3251
|
});
|
|
3373
3252
|
}
|
|
3374
|
-
function releaseFeishuCardActionToken(params) {
|
|
3375
|
-
const normalizedToken = params.token.trim();
|
|
3376
|
-
if (!normalizedToken) return;
|
|
3377
|
-
processedCardActionTokens.delete(`${params.accountId}:${normalizedToken}`);
|
|
3378
|
-
}
|
|
3379
3253
|
function buildSyntheticMessageEvent(event, content, chatType) {
|
|
3380
3254
|
const replyTargetMessageId = event.context.open_message_id ?? event.open_message_id;
|
|
3381
3255
|
const isTemporaryCardActionId = replyTargetMessageId?.startsWith("card-action-c-");
|
|
@@ -3419,11 +3293,7 @@ async function dispatchSyntheticCommand(params) {
|
|
|
3419
3293
|
accountId: params.accountId
|
|
3420
3294
|
});
|
|
3421
3295
|
}
|
|
3422
|
-
|
|
3423
|
-
if (value === "group" || value === "topic" || value === "public") return "group";
|
|
3424
|
-
if (value === "p2p" || value === "private") return "p2p";
|
|
3425
|
-
}
|
|
3426
|
-
const resolvedChatTypeCache = /* @__PURE__ */ new Map();
|
|
3296
|
+
const resolvedChatTypeCache = resolvedCardActionChatTypes;
|
|
3427
3297
|
const CHAT_TYPE_CACHE_TTL_MS = 30 * 6e4;
|
|
3428
3298
|
const CHAT_TYPE_CACHE_MAX_SIZE = 5e3;
|
|
3429
3299
|
function pruneChatTypeCache(now) {
|
|
@@ -3461,7 +3331,7 @@ function cacheResolvedCardActionChatType(cacheKey, value, now) {
|
|
|
3461
3331
|
});
|
|
3462
3332
|
}
|
|
3463
3333
|
async function resolveCardActionChatType(params) {
|
|
3464
|
-
const explicitChatType =
|
|
3334
|
+
const explicitChatType = normalizeFeishuChatType$2(params.chatType);
|
|
3465
3335
|
if (explicitChatType) return explicitChatType;
|
|
3466
3336
|
const chatId = params.event.context.chat_id?.trim();
|
|
3467
3337
|
if (!chatId) return "p2p";
|
|
@@ -3475,7 +3345,7 @@ async function resolveCardActionChatType(params) {
|
|
|
3475
3345
|
try {
|
|
3476
3346
|
const response = await createFeishuClient(params.account).im.chat.get({ path: { chat_id: chatId } });
|
|
3477
3347
|
if (response.code === 0) {
|
|
3478
|
-
const resolvedChatType =
|
|
3348
|
+
const resolvedChatType = resolveFeishuChatType(response.data ?? {});
|
|
3479
3349
|
if (resolvedChatType) {
|
|
3480
3350
|
cacheResolvedCardActionChatType(cacheKey, resolvedChatType, now);
|
|
3481
3351
|
return resolvedChatType;
|
|
@@ -3513,7 +3383,7 @@ async function handleFeishuCardAction(params) {
|
|
|
3513
3383
|
token: event.token,
|
|
3514
3384
|
accountId: account.accountId
|
|
3515
3385
|
})) {
|
|
3516
|
-
log(`feishu[${account.accountId}]: skipping duplicate card action token
|
|
3386
|
+
log(`feishu[${account.accountId}]: skipping duplicate card action token`);
|
|
3517
3387
|
return;
|
|
3518
3388
|
}
|
|
3519
3389
|
try {
|
|
@@ -3525,10 +3395,7 @@ async function handleFeishuCardAction(params) {
|
|
|
3525
3395
|
reason: decoded.reason,
|
|
3526
3396
|
accountId
|
|
3527
3397
|
});
|
|
3528
|
-
|
|
3529
|
-
token: event.token,
|
|
3530
|
-
accountId: account.accountId
|
|
3531
|
-
});
|
|
3398
|
+
completeFeishuCardAction(event.token, account.accountId);
|
|
3532
3399
|
return;
|
|
3533
3400
|
}
|
|
3534
3401
|
if (decoded.kind === "structured") {
|
|
@@ -3543,10 +3410,7 @@ async function handleFeishuCardAction(params) {
|
|
|
3543
3410
|
reason: "malformed",
|
|
3544
3411
|
accountId
|
|
3545
3412
|
});
|
|
3546
|
-
|
|
3547
|
-
token: event.token,
|
|
3548
|
-
accountId: account.accountId
|
|
3549
|
-
});
|
|
3413
|
+
completeFeishuCardAction(event.token, account.accountId);
|
|
3550
3414
|
return;
|
|
3551
3415
|
}
|
|
3552
3416
|
const prompt = typeof envelope.m?.prompt === "string" && envelope.m.prompt.trim() ? envelope.m.prompt : `Run \`${command}\` in this Feishu conversation?`;
|
|
@@ -3558,10 +3422,7 @@ async function handleFeishuCardAction(params) {
|
|
|
3558
3422
|
reason: "malformed",
|
|
3559
3423
|
accountId
|
|
3560
3424
|
});
|
|
3561
|
-
|
|
3562
|
-
token: event.token,
|
|
3563
|
-
accountId: account.accountId
|
|
3564
|
-
});
|
|
3425
|
+
completeFeishuCardAction(event.token, account.accountId);
|
|
3565
3426
|
return;
|
|
3566
3427
|
}
|
|
3567
3428
|
await sendCardFeishu({
|
|
@@ -3584,10 +3445,7 @@ async function handleFeishuCardAction(params) {
|
|
|
3584
3445
|
}),
|
|
3585
3446
|
accountId
|
|
3586
3447
|
});
|
|
3587
|
-
|
|
3588
|
-
token: event.token,
|
|
3589
|
-
accountId: account.accountId
|
|
3590
|
-
});
|
|
3448
|
+
completeFeishuCardAction(event.token, account.accountId);
|
|
3591
3449
|
return;
|
|
3592
3450
|
}
|
|
3593
3451
|
if (envelope.a === "feishu.approval.cancel") {
|
|
@@ -3597,10 +3455,7 @@ async function handleFeishuCardAction(params) {
|
|
|
3597
3455
|
text: "Cancelled.",
|
|
3598
3456
|
accountId
|
|
3599
3457
|
});
|
|
3600
|
-
|
|
3601
|
-
token: event.token,
|
|
3602
|
-
accountId: account.accountId
|
|
3603
|
-
});
|
|
3458
|
+
completeFeishuCardAction(event.token, account.accountId);
|
|
3604
3459
|
return;
|
|
3605
3460
|
}
|
|
3606
3461
|
if (envelope.a === "feishu.approval.confirm" || envelope.k === "quick") {
|
|
@@ -3612,10 +3467,7 @@ async function handleFeishuCardAction(params) {
|
|
|
3612
3467
|
reason: "malformed",
|
|
3613
3468
|
accountId
|
|
3614
3469
|
});
|
|
3615
|
-
|
|
3616
|
-
token: event.token,
|
|
3617
|
-
accountId: account.accountId
|
|
3618
|
-
});
|
|
3470
|
+
completeFeishuCardAction(event.token, account.accountId);
|
|
3619
3471
|
return;
|
|
3620
3472
|
}
|
|
3621
3473
|
await dispatchSyntheticCommand({
|
|
@@ -3629,10 +3481,7 @@ async function handleFeishuCardAction(params) {
|
|
|
3629
3481
|
accountId,
|
|
3630
3482
|
chatType: envelope.c?.t
|
|
3631
3483
|
});
|
|
3632
|
-
|
|
3633
|
-
token: event.token,
|
|
3634
|
-
accountId: account.accountId
|
|
3635
|
-
});
|
|
3484
|
+
completeFeishuCardAction(event.token, account.accountId);
|
|
3636
3485
|
return;
|
|
3637
3486
|
}
|
|
3638
3487
|
await sendInvalidInteractionNotice({
|
|
@@ -3641,10 +3490,7 @@ async function handleFeishuCardAction(params) {
|
|
|
3641
3490
|
reason: "malformed",
|
|
3642
3491
|
accountId
|
|
3643
3492
|
});
|
|
3644
|
-
|
|
3645
|
-
token: event.token,
|
|
3646
|
-
accountId: account.accountId
|
|
3647
|
-
});
|
|
3493
|
+
completeFeishuCardAction(event.token, account.accountId);
|
|
3648
3494
|
return;
|
|
3649
3495
|
}
|
|
3650
3496
|
const content = buildFeishuCardActionTextFallback(event);
|
|
@@ -3659,23 +3505,146 @@ async function handleFeishuCardAction(params) {
|
|
|
3659
3505
|
channelRuntime: params.channelRuntime,
|
|
3660
3506
|
accountId
|
|
3661
3507
|
});
|
|
3662
|
-
|
|
3663
|
-
token: event.token,
|
|
3664
|
-
accountId: account.accountId
|
|
3665
|
-
});
|
|
3508
|
+
completeFeishuCardAction(event.token, account.accountId);
|
|
3666
3509
|
} catch (err) {
|
|
3667
|
-
|
|
3668
|
-
token: event.token,
|
|
3669
|
-
accountId: account.accountId
|
|
3670
|
-
});
|
|
3671
|
-
else completeFeishuCardActionToken({
|
|
3672
|
-
token: event.token,
|
|
3673
|
-
accountId: account.accountId
|
|
3674
|
-
});
|
|
3510
|
+
completeFeishuCardAction(event.token, account.accountId);
|
|
3675
3511
|
throw err;
|
|
3676
3512
|
}
|
|
3677
3513
|
}
|
|
3678
3514
|
//#endregion
|
|
3515
|
+
//#region extensions/feishu/src/monitor-defaults.ts
|
|
3516
|
+
const FEISHU_WEBHOOK_RATE_LIMIT_FALLBACK_DEFAULTS = {
|
|
3517
|
+
windowMs: 6e4,
|
|
3518
|
+
maxRequests: 120,
|
|
3519
|
+
maxTrackedKeys: 4096
|
|
3520
|
+
};
|
|
3521
|
+
const FEISHU_WEBHOOK_ANOMALY_FALLBACK_DEFAULTS = {
|
|
3522
|
+
maxTrackedKeys: 4096,
|
|
3523
|
+
ttlMs: 360 * 6e4,
|
|
3524
|
+
logEvery: 25
|
|
3525
|
+
};
|
|
3526
|
+
function coercePositiveInt(value, fallback) {
|
|
3527
|
+
if (typeof value !== "number" || !Number.isFinite(value)) return fallback;
|
|
3528
|
+
const normalized = Math.floor(value);
|
|
3529
|
+
return normalized > 0 ? normalized : fallback;
|
|
3530
|
+
}
|
|
3531
|
+
function resolveFeishuWebhookRateLimitDefaults(defaults) {
|
|
3532
|
+
const resolved = defaults;
|
|
3533
|
+
return {
|
|
3534
|
+
windowMs: coercePositiveInt(resolved?.windowMs, FEISHU_WEBHOOK_RATE_LIMIT_FALLBACK_DEFAULTS.windowMs),
|
|
3535
|
+
maxRequests: coercePositiveInt(resolved?.maxRequests, FEISHU_WEBHOOK_RATE_LIMIT_FALLBACK_DEFAULTS.maxRequests),
|
|
3536
|
+
maxTrackedKeys: coercePositiveInt(resolved?.maxTrackedKeys, FEISHU_WEBHOOK_RATE_LIMIT_FALLBACK_DEFAULTS.maxTrackedKeys)
|
|
3537
|
+
};
|
|
3538
|
+
}
|
|
3539
|
+
function resolveFeishuWebhookAnomalyDefaults(defaults) {
|
|
3540
|
+
const resolved = defaults;
|
|
3541
|
+
return {
|
|
3542
|
+
maxTrackedKeys: coercePositiveInt(resolved?.maxTrackedKeys, FEISHU_WEBHOOK_ANOMALY_FALLBACK_DEFAULTS.maxTrackedKeys),
|
|
3543
|
+
ttlMs: coercePositiveInt(resolved?.ttlMs, FEISHU_WEBHOOK_ANOMALY_FALLBACK_DEFAULTS.ttlMs),
|
|
3544
|
+
logEvery: coercePositiveInt(resolved?.logEvery, FEISHU_WEBHOOK_ANOMALY_FALLBACK_DEFAULTS.logEvery)
|
|
3545
|
+
};
|
|
3546
|
+
}
|
|
3547
|
+
//#endregion
|
|
3548
|
+
//#region extensions/feishu/src/monitor.state.ts
|
|
3549
|
+
const wsClients = /* @__PURE__ */ new Map();
|
|
3550
|
+
const httpServers = /* @__PURE__ */ new Map();
|
|
3551
|
+
const botOpenIds = /* @__PURE__ */ new Map();
|
|
3552
|
+
const botNames = /* @__PURE__ */ new Map();
|
|
3553
|
+
const botIdentityRevisions = /* @__PURE__ */ new Map();
|
|
3554
|
+
const FEISHU_WEBHOOK_MAX_BODY_BYTES = 64 * 1024;
|
|
3555
|
+
const FEISHU_WEBHOOK_BODY_TIMEOUT_MS = 5e3;
|
|
3556
|
+
const FEISHU_HTTP_SERVER_CLOSE_TIMEOUT_MS = 5e3;
|
|
3557
|
+
const feishuWebhookRateLimitDefaults = resolveFeishuWebhookRateLimitDefaults(WEBHOOK_RATE_LIMIT_DEFAULTS);
|
|
3558
|
+
const feishuWebhookAnomalyDefaults = resolveFeishuWebhookAnomalyDefaults(WEBHOOK_ANOMALY_COUNTER_DEFAULTS);
|
|
3559
|
+
const feishuWebhookRateLimiter = createFixedWindowRateLimiter({
|
|
3560
|
+
windowMs: feishuWebhookRateLimitDefaults.windowMs,
|
|
3561
|
+
maxRequests: feishuWebhookRateLimitDefaults.maxRequests,
|
|
3562
|
+
maxTrackedKeys: feishuWebhookRateLimitDefaults.maxTrackedKeys
|
|
3563
|
+
});
|
|
3564
|
+
const feishuWebhookAnomalyTracker = createWebhookAnomalyTracker({
|
|
3565
|
+
maxTrackedKeys: feishuWebhookAnomalyDefaults.maxTrackedKeys,
|
|
3566
|
+
ttlMs: feishuWebhookAnomalyDefaults.ttlMs,
|
|
3567
|
+
logEvery: feishuWebhookAnomalyDefaults.logEvery
|
|
3568
|
+
});
|
|
3569
|
+
function readBotIdentityRevision(accountId) {
|
|
3570
|
+
return botIdentityRevisions.get(accountId) ?? 0;
|
|
3571
|
+
}
|
|
3572
|
+
function bumpBotIdentityRevision(accountId) {
|
|
3573
|
+
botIdentityRevisions.set(accountId, readBotIdentityRevision(accountId) + 1);
|
|
3574
|
+
}
|
|
3575
|
+
function captureBotIdentitySnapshot(accountId) {
|
|
3576
|
+
return { revision: readBotIdentityRevision(accountId) };
|
|
3577
|
+
}
|
|
3578
|
+
function clearFeishuBotIdentityStateIfUnchanged(accountId, snapshot) {
|
|
3579
|
+
if (readBotIdentityRevision(accountId) !== snapshot.revision) return;
|
|
3580
|
+
botOpenIds.delete(accountId);
|
|
3581
|
+
botNames.delete(accountId);
|
|
3582
|
+
bumpBotIdentityRevision(accountId);
|
|
3583
|
+
}
|
|
3584
|
+
function setFeishuBotIdentityState(accountId, identity) {
|
|
3585
|
+
botOpenIds.set(accountId, identity.botOpenId);
|
|
3586
|
+
if (identity.botName) botNames.set(accountId, identity.botName);
|
|
3587
|
+
else botNames.delete(accountId);
|
|
3588
|
+
bumpBotIdentityRevision(accountId);
|
|
3589
|
+
}
|
|
3590
|
+
function clearFeishuBotIdentityState(accountId) {
|
|
3591
|
+
botOpenIds.delete(accountId);
|
|
3592
|
+
botNames.delete(accountId);
|
|
3593
|
+
bumpBotIdentityRevision(accountId);
|
|
3594
|
+
}
|
|
3595
|
+
function isServerNotRunningError(error) {
|
|
3596
|
+
return error.code === "ERR_SERVER_NOT_RUNNING";
|
|
3597
|
+
}
|
|
3598
|
+
async function closeFeishuHttpServer(server) {
|
|
3599
|
+
await new Promise((resolve, reject) => {
|
|
3600
|
+
let settled = false;
|
|
3601
|
+
const settle = (err) => {
|
|
3602
|
+
if (settled) return;
|
|
3603
|
+
settled = true;
|
|
3604
|
+
clearTimeout(fallbackTimer);
|
|
3605
|
+
if (!err || isServerNotRunningError(err)) {
|
|
3606
|
+
resolve();
|
|
3607
|
+
return;
|
|
3608
|
+
}
|
|
3609
|
+
reject(err);
|
|
3610
|
+
};
|
|
3611
|
+
const fallbackTimer = setTimeout(() => {
|
|
3612
|
+
try {
|
|
3613
|
+
server.closeAllConnections();
|
|
3614
|
+
settle();
|
|
3615
|
+
} catch (err) {
|
|
3616
|
+
settle(err instanceof Error ? err : new Error(String(err)));
|
|
3617
|
+
}
|
|
3618
|
+
}, FEISHU_HTTP_SERVER_CLOSE_TIMEOUT_MS);
|
|
3619
|
+
try {
|
|
3620
|
+
server.close((err) => {
|
|
3621
|
+
settle(err);
|
|
3622
|
+
});
|
|
3623
|
+
} catch (err) {
|
|
3624
|
+
settle(err instanceof Error ? err : new Error(String(err)));
|
|
3625
|
+
}
|
|
3626
|
+
});
|
|
3627
|
+
}
|
|
3628
|
+
async function closeTrackedFeishuHttpServer(accountId, server) {
|
|
3629
|
+
const identitySnapshot = captureBotIdentitySnapshot(accountId);
|
|
3630
|
+
try {
|
|
3631
|
+
await closeFeishuHttpServer(server);
|
|
3632
|
+
} finally {
|
|
3633
|
+
if (httpServers.get(accountId) === server) {
|
|
3634
|
+
httpServers.delete(accountId);
|
|
3635
|
+
clearFeishuBotIdentityStateIfUnchanged(accountId, identitySnapshot);
|
|
3636
|
+
}
|
|
3637
|
+
}
|
|
3638
|
+
}
|
|
3639
|
+
function recordWebhookStatus(runtime, accountId, path, statusCode) {
|
|
3640
|
+
feishuWebhookAnomalyTracker.record({
|
|
3641
|
+
key: `${accountId}:${path}:${statusCode}`,
|
|
3642
|
+
statusCode,
|
|
3643
|
+
log: runtime?.log ?? console.log,
|
|
3644
|
+
message: (count) => `feishu[${accountId}]: webhook anomaly path=${path} status=${statusCode} count=${count}`
|
|
3645
|
+
});
|
|
3646
|
+
}
|
|
3647
|
+
//#endregion
|
|
3679
3648
|
//#region extensions/feishu/src/monitor.bot-identity.ts
|
|
3680
3649
|
const BOT_IDENTITY_RETRY_DELAYS_MS = [
|
|
3681
3650
|
6e4,
|
|
@@ -3699,9 +3668,10 @@ function applyBotIdentityState(accountId, identity) {
|
|
|
3699
3668
|
async function retryBotIdentityProbe(account, accountId, runtime, abortSignal) {
|
|
3700
3669
|
const log = runtime?.log ?? console.log;
|
|
3701
3670
|
const error = runtime?.error ?? console.error;
|
|
3702
|
-
|
|
3671
|
+
const nextDelays = BOT_IDENTITY_RETRY_DELAYS_MS.slice(1)[Symbol.iterator]();
|
|
3672
|
+
for (const [i, delayMs] of BOT_IDENTITY_RETRY_DELAYS_MS.entries()) {
|
|
3703
3673
|
if (abortSignal?.aborted) return;
|
|
3704
|
-
if (!await waitForAbortableDelay(
|
|
3674
|
+
if (!await waitForAbortableDelay(delayMs, abortSignal)) return;
|
|
3705
3675
|
const resolved = applyBotIdentityState(accountId, await fetchBotIdentityForMonitor(account, {
|
|
3706
3676
|
runtime,
|
|
3707
3677
|
abortSignal
|
|
@@ -3710,7 +3680,8 @@ async function retryBotIdentityProbe(account, accountId, runtime, abortSignal) {
|
|
|
3710
3680
|
log(`feishu[${accountId}]: bot open_id recovered via background retry: ${resolved.botOpenId}`);
|
|
3711
3681
|
return;
|
|
3712
3682
|
}
|
|
3713
|
-
const
|
|
3683
|
+
const nextDelayResult = nextDelays.next();
|
|
3684
|
+
const nextDelay = nextDelayResult.done ? void 0 : nextDelayResult.value;
|
|
3714
3685
|
error(`feishu[${accountId}]: bot identity background retry ${i + 1}/${BOT_IDENTITY_RETRY_DELAYS_MS.length} failed` + (nextDelay ? `; next attempt in ${nextDelay / 1e3}s` : ""));
|
|
3715
3686
|
}
|
|
3716
3687
|
error(`feishu[${accountId}]: bot identity background retry exhausted; requireMention group messages may be skipped until restart`);
|
|
@@ -3886,11 +3857,11 @@ function createFeishuBotMenuHandler(params) {
|
|
|
3886
3857
|
namespace: accountId,
|
|
3887
3858
|
log
|
|
3888
3859
|
});
|
|
3889
|
-
if (claim === "duplicate") {
|
|
3860
|
+
if (claim.kind === "duplicate") {
|
|
3890
3861
|
log(`feishu[${accountId}]: dropping duplicate bot-menu event for ${syntheticMessageId}`);
|
|
3891
3862
|
return;
|
|
3892
3863
|
}
|
|
3893
|
-
if (claim === "inflight") {
|
|
3864
|
+
if (claim.kind === "inflight") {
|
|
3894
3865
|
log(`feishu[${accountId}]: dropping in-flight bot-menu event for ${syntheticMessageId}`);
|
|
3895
3866
|
return;
|
|
3896
3867
|
}
|
|
@@ -3903,7 +3874,7 @@ function createFeishuBotMenuHandler(params) {
|
|
|
3903
3874
|
channelRuntime: params.channelRuntime,
|
|
3904
3875
|
chatHistories,
|
|
3905
3876
|
accountId,
|
|
3906
|
-
|
|
3877
|
+
processingClaim: claim.kind === "claimed" ? claim.handle : void 0
|
|
3907
3878
|
});
|
|
3908
3879
|
const promise = maybeHandleFeishuQuickActionMenu({
|
|
3909
3880
|
cfg,
|
|
@@ -3913,16 +3884,16 @@ function createFeishuBotMenuHandler(params) {
|
|
|
3913
3884
|
accountId
|
|
3914
3885
|
}).then(async (handledMenu) => {
|
|
3915
3886
|
if (handledMenu) {
|
|
3916
|
-
|
|
3887
|
+
if (claim.kind === "claimed") await claim.handle.commit();
|
|
3917
3888
|
return;
|
|
3918
3889
|
}
|
|
3919
3890
|
return await handleLegacyMenu();
|
|
3920
3891
|
}).catch(async (err) => {
|
|
3921
|
-
if (isFeishuRetryableSyntheticEventError(err))
|
|
3922
|
-
|
|
3892
|
+
if (isFeishuRetryableSyntheticEventError(err)) {
|
|
3893
|
+
await forgetProcessedFeishuMessage(syntheticMessageId, accountId, log);
|
|
3894
|
+
if (claim.kind === "claimed") claim.handle.release({ error: err });
|
|
3895
|
+
} else if (claim.kind === "claimed") await claim.handle.commit();
|
|
3923
3896
|
throw err;
|
|
3924
|
-
}).finally(() => {
|
|
3925
|
-
releaseFeishuMessageProcessing(syntheticMessageId, accountId);
|
|
3926
3897
|
});
|
|
3927
3898
|
if (fireAndForget) {
|
|
3928
3899
|
promise.catch((err) => {
|
|
@@ -3951,7 +3922,7 @@ function createFeishuCommentReplyDispatcher(params) {
|
|
|
3951
3922
|
accountId: params.accountId
|
|
3952
3923
|
}));
|
|
3953
3924
|
const textChunkLimit = core.channel.text.resolveTextChunkLimit(params.cfg, "feishu", params.accountId, { fallbackLimit: 4e3 });
|
|
3954
|
-
const chunkMode = core.channel.text.resolveChunkMode(params.cfg, "feishu");
|
|
3925
|
+
const chunkMode = core.channel.text.resolveChunkMode(params.cfg, "feishu", params.accountId);
|
|
3955
3926
|
const typingReaction = createCommentTypingReactionLifecycle({
|
|
3956
3927
|
cfg: params.cfg,
|
|
3957
3928
|
fileToken: params.fileToken,
|
|
@@ -4111,11 +4082,6 @@ async function resolveParsedCommentContent(params) {
|
|
|
4111
4082
|
linkedDocuments: resolvedLinkedDocuments
|
|
4112
4083
|
};
|
|
4113
4084
|
}
|
|
4114
|
-
async function delayMs(ms) {
|
|
4115
|
-
await new Promise((resolve) => {
|
|
4116
|
-
setTimeout(resolve, ms);
|
|
4117
|
-
});
|
|
4118
|
-
}
|
|
4119
4085
|
function buildDriveCommentTargetUrl(params) {
|
|
4120
4086
|
return `/open-apis/drive/v1/files/${encodeURIComponent(params.fileToken)}/comments/batch_query` + encodeQuery({
|
|
4121
4087
|
file_type: params.fileType,
|
|
@@ -4338,8 +4304,9 @@ async function fetchDriveCommentContext(params) {
|
|
|
4338
4304
|
fetchedMatchedReply = params.replyId ? replies.find((reply) => reply.reply_id?.trim() === params.replyId?.trim()) : void 0;
|
|
4339
4305
|
}
|
|
4340
4306
|
if (params.replyId && !embeddedTargetReply && !fetchedMatchedReply) for (let attempt = 1; attempt <= FEISHU_COMMENT_REPLY_MISS_RETRY_LIMIT; attempt += 1) {
|
|
4307
|
+
if (params.abortSignal?.aborted) break;
|
|
4341
4308
|
params.logger?.(`feishu[${params.accountId}]: retrying comment reply lookup comment=${params.commentId} requested_reply=${params.replyId} attempt=${attempt}/${FEISHU_COMMENT_REPLY_MISS_RETRY_LIMIT} delay_ms=${FEISHU_COMMENT_REPLY_MISS_RETRY_DELAY_MS}`);
|
|
4342
|
-
await params.
|
|
4309
|
+
if (!await waitForAbortableDelay(FEISHU_COMMENT_REPLY_MISS_RETRY_DELAY_MS, params.abortSignal)) break;
|
|
4343
4310
|
const retried = await fetchDriveCommentReplies(params);
|
|
4344
4311
|
if (retried.replies.length > 0) {
|
|
4345
4312
|
params.logger?.(`feishu[${params.accountId}]: fetched retried comment replies comment=${params.commentId} attempt=${attempt} count=${retried.replies.length} log_ids=${safeJsonStringify(retried.logIds)} summary=${summarizeCommentRepliesForLog(retried.replies)}`);
|
|
@@ -4487,7 +4454,7 @@ function buildDriveCommentSurfacePrompt(params) {
|
|
|
4487
4454
|
return lines.join("\n");
|
|
4488
4455
|
}
|
|
4489
4456
|
async function resolveDriveCommentEventCore(params) {
|
|
4490
|
-
const { cfg, accountId, event, account, botOpenId, createClient, verificationTimeoutMs = FEISHU_COMMENT_VERIFY_TIMEOUT_MS, logger,
|
|
4457
|
+
const { cfg, accountId, event, account, botOpenId, createClient, verificationTimeoutMs = FEISHU_COMMENT_VERIFY_TIMEOUT_MS, logger, abortSignal } = params;
|
|
4491
4458
|
const eventId = event.event_id?.trim();
|
|
4492
4459
|
const commentId = event.comment_id?.trim();
|
|
4493
4460
|
const replyId = event.reply_id?.trim();
|
|
@@ -4513,7 +4480,7 @@ async function resolveDriveCommentEventCore(params) {
|
|
|
4513
4480
|
return null;
|
|
4514
4481
|
}
|
|
4515
4482
|
const context = await fetchDriveCommentContext({
|
|
4516
|
-
client: createClient ? createClient(account ?? { accountId }) : createFeishuClient((await import("./accounts-
|
|
4483
|
+
client: createClient ? createClient(account ?? { accountId }) : createFeishuClient((await import("./accounts-BDoGHJDk.js").then((n) => n.t)).resolveFeishuAccount({
|
|
4517
4484
|
cfg,
|
|
4518
4485
|
accountId
|
|
4519
4486
|
})),
|
|
@@ -4525,7 +4492,7 @@ async function resolveDriveCommentEventCore(params) {
|
|
|
4525
4492
|
timeoutMs: verificationTimeoutMs,
|
|
4526
4493
|
logger,
|
|
4527
4494
|
accountId,
|
|
4528
|
-
|
|
4495
|
+
abortSignal
|
|
4529
4496
|
});
|
|
4530
4497
|
return {
|
|
4531
4498
|
eventId,
|
|
@@ -4651,7 +4618,8 @@ async function handleFeishuCommentEvent(params) {
|
|
|
4651
4618
|
accountId: account.accountId,
|
|
4652
4619
|
event: params.event,
|
|
4653
4620
|
botOpenId: params.botOpenId,
|
|
4654
|
-
logger: log
|
|
4621
|
+
logger: log,
|
|
4622
|
+
abortSignal: params.abortSignal
|
|
4655
4623
|
});
|
|
4656
4624
|
if (!turn) {
|
|
4657
4625
|
log(`feishu[${account.accountId}]: drive comment notice skipped event=${params.event.event_id ?? "unknown"} comment=${params.event.comment_id ?? "unknown"}`);
|
|
@@ -4935,7 +4903,7 @@ function buildCommentNoticeQueueKey(event) {
|
|
|
4935
4903
|
return `comment-doc:${event.notice_meta?.file_type?.trim() || "unknown"}:${event.notice_meta?.file_token?.trim() || "unknown"}`;
|
|
4936
4904
|
}
|
|
4937
4905
|
function createFeishuDriveCommentNoticeHandler(params) {
|
|
4938
|
-
const { cfg, accountId, runtime, fireAndForget } = params;
|
|
4906
|
+
const { cfg, accountId, runtime, fireAndForget, abortSignal } = params;
|
|
4939
4907
|
const log = runtime?.log ?? console.log;
|
|
4940
4908
|
const error = runtime?.error ?? console.error;
|
|
4941
4909
|
const enqueue = createSequentialQueue();
|
|
@@ -4955,20 +4923,22 @@ function createFeishuDriveCommentNoticeHandler(params) {
|
|
|
4955
4923
|
}
|
|
4956
4924
|
const eventId = event.event_id?.trim();
|
|
4957
4925
|
const syntheticMessageId = eventId ? `drive-comment:${eventId}` : void 0;
|
|
4926
|
+
let processingClaim;
|
|
4958
4927
|
if (syntheticMessageId) {
|
|
4959
4928
|
const claim = await claimUnprocessedFeishuMessage({
|
|
4960
4929
|
messageId: syntheticMessageId,
|
|
4961
4930
|
namespace: accountId,
|
|
4962
4931
|
log
|
|
4963
4932
|
});
|
|
4964
|
-
if (claim === "duplicate") {
|
|
4933
|
+
if (claim.kind === "duplicate") {
|
|
4965
4934
|
log(`feishu[${accountId}]: dropping duplicate comment event ${syntheticMessageId}`);
|
|
4966
4935
|
return;
|
|
4967
4936
|
}
|
|
4968
|
-
if (claim === "inflight") {
|
|
4937
|
+
if (claim.kind === "inflight") {
|
|
4969
4938
|
log(`feishu[${accountId}]: dropping in-flight comment event ${syntheticMessageId}`);
|
|
4970
4939
|
return;
|
|
4971
4940
|
}
|
|
4941
|
+
processingClaim = claim.kind === "claimed" ? claim.handle : void 0;
|
|
4972
4942
|
}
|
|
4973
4943
|
log(`feishu[${accountId}]: received drive comment notice event=${event.event_id ?? "unknown"} type=${event.notice_meta?.notice_type ?? "unknown"} file=${event.notice_meta?.file_type ?? "unknown"}:${event.notice_meta?.file_token ?? "unknown"} comment=${event.comment_id ?? "unknown"} reply=${event.reply_id ?? "none"} from=${event.notice_meta?.from_user_id?.open_id ?? "unknown"} mentioned=${event.is_mentioned === true ? "yes" : "no"}`);
|
|
4974
4944
|
try {
|
|
@@ -4978,15 +4948,15 @@ function createFeishuDriveCommentNoticeHandler(params) {
|
|
|
4978
4948
|
accountId,
|
|
4979
4949
|
event,
|
|
4980
4950
|
botOpenId: getBotOpenId(accountId),
|
|
4981
|
-
runtime
|
|
4951
|
+
runtime,
|
|
4952
|
+
abortSignal
|
|
4982
4953
|
});
|
|
4983
4954
|
});
|
|
4984
|
-
|
|
4955
|
+
await processingClaim?.commit();
|
|
4985
4956
|
} catch (err) {
|
|
4986
|
-
if (
|
|
4957
|
+
if (isFeishuRetryableSyntheticEventError(err)) processingClaim?.release({ error: err });
|
|
4958
|
+
else await processingClaim?.commit();
|
|
4987
4959
|
throw err;
|
|
4988
|
-
} finally {
|
|
4989
|
-
if (syntheticMessageId) releaseFeishuMessageProcessing(syntheticMessageId, accountId);
|
|
4990
4960
|
}
|
|
4991
4961
|
});
|
|
4992
4962
|
};
|
|
@@ -5028,7 +4998,7 @@ function dedupeFeishuDebounceEntriesByDedupeKey(entries) {
|
|
|
5028
4998
|
const seen = /* @__PURE__ */ new Set();
|
|
5029
4999
|
const deduped = [];
|
|
5030
5000
|
for (const entry of entries) {
|
|
5031
|
-
const dedupeKey = resolveFeishuMessageDedupeKey(entry);
|
|
5001
|
+
const dedupeKey = resolveFeishuMessageDedupeKey(entry.event);
|
|
5032
5002
|
if (!dedupeKey) {
|
|
5033
5003
|
deduped.push(entry);
|
|
5034
5004
|
continue;
|
|
@@ -5042,10 +5012,7 @@ function dedupeFeishuDebounceEntriesByDedupeKey(entries) {
|
|
|
5042
5012
|
function resolveFeishuDebounceMentions(params) {
|
|
5043
5013
|
const { entries, botOpenId } = params;
|
|
5044
5014
|
if (entries.length === 0) return;
|
|
5045
|
-
for (
|
|
5046
|
-
const entry = entries[index];
|
|
5047
|
-
if (isMentionForwardRequest(entry, botOpenId)) return mergeFeishuDebounceMentions([entry]);
|
|
5048
|
-
}
|
|
5015
|
+
for (const entry of entries.toReversed()) if (isMentionForwardRequest(entry, botOpenId)) return mergeFeishuDebounceMentions([entry]);
|
|
5049
5016
|
const merged = mergeFeishuDebounceMentions(entries);
|
|
5050
5017
|
if (!merged) return;
|
|
5051
5018
|
const normalizedBotOpenId = botOpenId?.trim();
|
|
@@ -5053,7 +5020,7 @@ function resolveFeishuDebounceMentions(params) {
|
|
|
5053
5020
|
const botMentions = merged.filter((mention) => mention.id.open_id?.trim() === normalizedBotOpenId);
|
|
5054
5021
|
return botMentions.length > 0 ? botMentions : void 0;
|
|
5055
5022
|
}
|
|
5056
|
-
function createFeishuMessageReceiveHandler({ cfg, channelRuntime, accountId, runtime, chatHistories, fireAndForget, handleMessage, resolveDebounceText: resolveText, hasProcessedMessage,
|
|
5023
|
+
function createFeishuMessageReceiveHandler({ cfg, channelRuntime, accountId, runtime, chatHistories, fireAndForget, handleMessage, resolveDebounceText: resolveText, hasProcessedMessage, getBotOpenId = () => void 0, getBotName = () => void 0, resolveSequentialKey = ({ accountId: accountIdLocal, event }) => `feishu:${accountIdLocal}:${event.message.chat_id?.trim() || "unknown"}`, statusSink }) {
|
|
5057
5024
|
const inboundDebounceMs = channelRuntime.debounce.resolveInboundDebounceMs({
|
|
5058
5025
|
cfg,
|
|
5059
5026
|
channel: "feishu"
|
|
@@ -5063,7 +5030,7 @@ function createFeishuMessageReceiveHandler({ cfg, channelRuntime, accountId, run
|
|
|
5063
5030
|
const enqueue = createSequentialQueue({ onTaskTimeout: (key, timeoutMs) => {
|
|
5064
5031
|
log(`feishu[${accountId}]: per-chat task exceeded ${timeoutMs}ms cap (key=${key}); evicting from queue so later same-key messages can proceed (#70133)`);
|
|
5065
5032
|
} });
|
|
5066
|
-
const dispatchFeishuMessage = async (event, messageDedupeKey) => {
|
|
5033
|
+
const dispatchFeishuMessage = async (event, messageDedupeKey, processingClaim) => {
|
|
5067
5034
|
const sequentialKey = resolveSequentialKey({
|
|
5068
5035
|
accountId,
|
|
5069
5036
|
event,
|
|
@@ -5079,7 +5046,7 @@ function createFeishuMessageReceiveHandler({ cfg, channelRuntime, accountId, run
|
|
|
5079
5046
|
channelRuntime,
|
|
5080
5047
|
chatHistories,
|
|
5081
5048
|
accountId,
|
|
5082
|
-
|
|
5049
|
+
processingClaim,
|
|
5083
5050
|
messageDedupeKey
|
|
5084
5051
|
});
|
|
5085
5052
|
await enqueue(sequentialKey, task);
|
|
@@ -5096,23 +5063,26 @@ function createFeishuMessageReceiveHandler({ cfg, channelRuntime, accountId, run
|
|
|
5096
5063
|
};
|
|
5097
5064
|
const recordSuppressedMessageIds = async (entries, dispatchDedupeKey) => {
|
|
5098
5065
|
const keepDedupeKey = dispatchDedupeKey?.trim();
|
|
5099
|
-
const suppressedIds = new Set(entries.map((entry) =>
|
|
5100
|
-
|
|
5101
|
-
|
|
5066
|
+
const suppressedIds = new Set(entries.map((entry) => ({
|
|
5067
|
+
id: resolveFeishuMessageDedupeKey(entry.event),
|
|
5068
|
+
claim: entry.processingClaim
|
|
5069
|
+
})).filter(({ id }) => Boolean(id) && (!keepDedupeKey || id !== keepDedupeKey)));
|
|
5070
|
+
for (const suppressed of suppressedIds) try {
|
|
5071
|
+
await suppressed.claim?.commit();
|
|
5102
5072
|
} catch (err) {
|
|
5103
|
-
error(`feishu[${accountId}]: failed to record merged dedupe id ${
|
|
5073
|
+
error(`feishu[${accountId}]: failed to record merged dedupe id ${suppressed.id}: ${String(err)}`);
|
|
5104
5074
|
}
|
|
5105
5075
|
};
|
|
5106
5076
|
const inboundDebouncer = channelRuntime.debounce.createInboundDebouncer({
|
|
5107
5077
|
debounceMs: inboundDebounceMs,
|
|
5108
|
-
buildKey: (event) => {
|
|
5078
|
+
buildKey: ({ event }) => {
|
|
5109
5079
|
const chatId = event.message.chat_id?.trim();
|
|
5110
5080
|
const senderId = resolveSenderDebounceId(event);
|
|
5111
5081
|
if (!chatId || !senderId) return null;
|
|
5112
5082
|
const rootId = event.message.root_id?.trim();
|
|
5113
5083
|
return `feishu:${accountId}:${chatId}:${rootId ? `thread:${rootId}` : "chat"}:${senderId}`;
|
|
5114
5084
|
},
|
|
5115
|
-
shouldDebounce: (event) => {
|
|
5085
|
+
shouldDebounce: ({ event }) => {
|
|
5116
5086
|
if (event.message.message_type !== "text") return false;
|
|
5117
5087
|
const text = resolveDebounceText(event);
|
|
5118
5088
|
return Boolean(text) && !channelRuntime.commands.isControlCommandMessage(text, cfg);
|
|
@@ -5121,35 +5091,35 @@ function createFeishuMessageReceiveHandler({ cfg, channelRuntime, accountId, run
|
|
|
5121
5091
|
const last = entries.at(-1);
|
|
5122
5092
|
if (!last) return;
|
|
5123
5093
|
if (entries.length === 1) {
|
|
5124
|
-
await dispatchFeishuMessage(last, resolveFeishuMessageDedupeKey(last));
|
|
5094
|
+
await dispatchFeishuMessage(last.event, resolveFeishuMessageDedupeKey(last.event), last.processingClaim);
|
|
5125
5095
|
return;
|
|
5126
5096
|
}
|
|
5127
5097
|
const dedupedEntries = dedupeFeishuDebounceEntriesByDedupeKey(entries);
|
|
5128
5098
|
const freshEntries = [];
|
|
5129
|
-
for (const entry of dedupedEntries) if (!await hasProcessedMessage(resolveFeishuMessageDedupeKey(entry), accountId, log)) freshEntries.push(entry);
|
|
5099
|
+
for (const entry of dedupedEntries) if (!await hasProcessedMessage(resolveFeishuMessageDedupeKey(entry.event), accountId, log)) freshEntries.push(entry);
|
|
5130
5100
|
const dispatchEntry = freshEntries.at(-1);
|
|
5131
5101
|
if (!dispatchEntry) return;
|
|
5132
|
-
const dispatchDedupeKey = resolveFeishuMessageDedupeKey(dispatchEntry);
|
|
5102
|
+
const dispatchDedupeKey = resolveFeishuMessageDedupeKey(dispatchEntry.event);
|
|
5133
5103
|
await recordSuppressedMessageIds(dedupedEntries, dispatchDedupeKey);
|
|
5134
|
-
const combinedText = freshEntries.map((entry) => resolveDebounceText(entry)).filter(Boolean).join("\n");
|
|
5104
|
+
const combinedText = freshEntries.map((entry) => resolveDebounceText(entry.event)).filter(Boolean).join("\n");
|
|
5135
5105
|
const mergedMentions = resolveFeishuDebounceMentions({
|
|
5136
|
-
entries: freshEntries,
|
|
5106
|
+
entries: freshEntries.map((entry) => entry.event),
|
|
5137
5107
|
botOpenId: getBotOpenId(accountId)
|
|
5138
5108
|
});
|
|
5139
5109
|
await dispatchFeishuMessage({
|
|
5140
|
-
...dispatchEntry,
|
|
5110
|
+
...dispatchEntry.event,
|
|
5141
5111
|
message: {
|
|
5142
|
-
...dispatchEntry.message,
|
|
5112
|
+
...dispatchEntry.event.message,
|
|
5143
5113
|
...combinedText.trim() ? {
|
|
5144
5114
|
message_type: "text",
|
|
5145
5115
|
content: JSON.stringify({ text: combinedText })
|
|
5146
5116
|
} : {},
|
|
5147
|
-
mentions: mergedMentions ?? dispatchEntry.message.mentions
|
|
5117
|
+
mentions: mergedMentions ?? dispatchEntry.event.message.mentions
|
|
5148
5118
|
}
|
|
5149
|
-
}, dispatchDedupeKey);
|
|
5119
|
+
}, dispatchDedupeKey, dispatchEntry.processingClaim);
|
|
5150
5120
|
},
|
|
5151
5121
|
onError: (err, entries) => {
|
|
5152
|
-
for (const entry of entries)
|
|
5122
|
+
for (const entry of entries) entry.processingClaim?.release({ error: err });
|
|
5153
5123
|
error(`feishu[${accountId}]: inbound debounce flush failed: ${String(err)}`);
|
|
5154
5124
|
}
|
|
5155
5125
|
});
|
|
@@ -5167,17 +5137,24 @@ function createFeishuMessageReceiveHandler({ cfg, channelRuntime, accountId, run
|
|
|
5167
5137
|
log(`feishu[${accountId}]: dropping self-authored message ${messageId ?? "unknown"}`);
|
|
5168
5138
|
return;
|
|
5169
5139
|
}
|
|
5170
|
-
const
|
|
5171
|
-
|
|
5172
|
-
|
|
5140
|
+
const claim = await claimUnprocessedFeishuMessage({
|
|
5141
|
+
messageId: resolveFeishuMessageDedupeKey(event),
|
|
5142
|
+
namespace: accountId,
|
|
5143
|
+
log
|
|
5144
|
+
});
|
|
5145
|
+
if (claim.kind === "duplicate" || claim.kind === "inflight") {
|
|
5146
|
+
log(`feishu[${accountId}]: dropping ${claim.kind} event for message ${messageId}`);
|
|
5173
5147
|
return;
|
|
5174
5148
|
}
|
|
5175
5149
|
const processMessage = async () => {
|
|
5176
|
-
await inboundDebouncer.enqueue(
|
|
5150
|
+
await inboundDebouncer.enqueue({
|
|
5151
|
+
event,
|
|
5152
|
+
...claim.kind === "claimed" ? { processingClaim: claim.handle } : {}
|
|
5153
|
+
});
|
|
5177
5154
|
};
|
|
5178
5155
|
if (fireAndForget) {
|
|
5179
5156
|
processMessage().catch((err) => {
|
|
5180
|
-
|
|
5157
|
+
if (claim.kind === "claimed") claim.handle.release({ error: err });
|
|
5181
5158
|
error(`feishu[${accountId}]: error handling message: ${String(err)}`);
|
|
5182
5159
|
});
|
|
5183
5160
|
return;
|
|
@@ -5185,12 +5162,22 @@ function createFeishuMessageReceiveHandler({ cfg, channelRuntime, accountId, run
|
|
|
5185
5162
|
try {
|
|
5186
5163
|
await processMessage();
|
|
5187
5164
|
} catch (err) {
|
|
5188
|
-
|
|
5165
|
+
if (claim.kind === "claimed") claim.handle.release({ error: err });
|
|
5189
5166
|
error(`feishu[${accountId}]: error handling message: ${String(err)}`);
|
|
5190
5167
|
}
|
|
5191
5168
|
};
|
|
5192
5169
|
}
|
|
5193
5170
|
//#endregion
|
|
5171
|
+
//#region extensions/feishu/src/monitor-rate-limit-key.ts
|
|
5172
|
+
function normalizeFeishuWebhookRateLimitClient(clientIp) {
|
|
5173
|
+
if (!clientIp) return "unknown";
|
|
5174
|
+
if (clientIp === "::1" || clientIp.startsWith("127.")) return "loopback";
|
|
5175
|
+
return clientIp;
|
|
5176
|
+
}
|
|
5177
|
+
function buildFeishuWebhookRateLimitKey(params) {
|
|
5178
|
+
return `${params.accountId}:${params.path}:${normalizeFeishuWebhookRateLimitClient(params.clientIp)}`;
|
|
5179
|
+
}
|
|
5180
|
+
//#endregion
|
|
5194
5181
|
//#region extensions/feishu/src/monitor.transport.ts
|
|
5195
5182
|
const FEISHU_WS_RECONNECT_INITIAL_DELAY_MS = 1e3;
|
|
5196
5183
|
const FEISHU_WS_RECONNECT_MAX_DELAY_MS = 3e4;
|
|
@@ -5228,14 +5215,6 @@ function respondText(res, statusCode, body) {
|
|
|
5228
5215
|
res.setHeader("Content-Type", "text/plain; charset=utf-8");
|
|
5229
5216
|
res.end(body);
|
|
5230
5217
|
}
|
|
5231
|
-
function normalizeFeishuWebhookRateLimitClient(clientIp) {
|
|
5232
|
-
if (!clientIp) return "unknown";
|
|
5233
|
-
if (clientIp === "::1" || clientIp.startsWith("127.")) return "loopback";
|
|
5234
|
-
return clientIp;
|
|
5235
|
-
}
|
|
5236
|
-
function buildFeishuWebhookRateLimitKey(params) {
|
|
5237
|
-
return `${params.accountId}:${params.path}:${normalizeFeishuWebhookRateLimitClient(params.clientIp)}`;
|
|
5238
|
-
}
|
|
5239
5218
|
function getFeishuWsReconnectDelayMs(attempt) {
|
|
5240
5219
|
return Math.min(FEISHU_WS_RECONNECT_INITIAL_DELAY_MS * 2 ** Math.max(0, attempt - 1), FEISHU_WS_RECONNECT_MAX_DELAY_MS);
|
|
5241
5220
|
}
|
|
@@ -5529,7 +5508,7 @@ async function resolveReactionSyntheticEvent(params) {
|
|
|
5529
5508
|
const senderId = event.user_id?.open_id;
|
|
5530
5509
|
const senderUserId = event.user_id?.user_id;
|
|
5531
5510
|
if (!emoji || !messageId || !senderId) return null;
|
|
5532
|
-
const { resolveFeishuAccount } = await import("./accounts-
|
|
5511
|
+
const { resolveFeishuAccount } = await import("./accounts-BDoGHJDk.js").then((n) => n.t);
|
|
5533
5512
|
const reactionNotifications = resolveFeishuAccount({
|
|
5534
5513
|
cfg,
|
|
5535
5514
|
accountId
|
|
@@ -5638,7 +5617,7 @@ function parseFeishuCardActionEventPayload(value) {
|
|
|
5638
5617
|
};
|
|
5639
5618
|
}
|
|
5640
5619
|
function registerEventHandlers(eventDispatcher, context) {
|
|
5641
|
-
const { cfg, accountId, channelRuntime, runtime, chatHistories, fireAndForget } = context;
|
|
5620
|
+
const { cfg, accountId, channelRuntime, runtime, chatHistories, fireAndForget, abortSignal } = context;
|
|
5642
5621
|
const log = runtime?.log ?? console.log;
|
|
5643
5622
|
const error = runtime?.error ?? console.error;
|
|
5644
5623
|
const runFeishuHandler = async (params) => {
|
|
@@ -5665,7 +5644,6 @@ function registerEventHandlers(eventDispatcher, context) {
|
|
|
5665
5644
|
handleMessage: handleFeishuMessage,
|
|
5666
5645
|
resolveDebounceText: ({ event, botOpenId, botName }) => parseFeishuMessageEvent(event, botOpenId, botName).content,
|
|
5667
5646
|
hasProcessedMessage: hasProcessedFeishuMessage,
|
|
5668
|
-
recordProcessedMessage: recordProcessedFeishuMessage,
|
|
5669
5647
|
getBotOpenId: (id) => botOpenIds.get(id),
|
|
5670
5648
|
getBotName: (id) => botNames.get(id),
|
|
5671
5649
|
resolveSequentialKey: getFeishuSequentialKey,
|
|
@@ -5695,7 +5673,8 @@ function registerEventHandlers(eventDispatcher, context) {
|
|
|
5695
5673
|
cfg,
|
|
5696
5674
|
accountId,
|
|
5697
5675
|
runtime,
|
|
5698
|
-
fireAndForget
|
|
5676
|
+
fireAndForget,
|
|
5677
|
+
abortSignal
|
|
5699
5678
|
}),
|
|
5700
5679
|
"im.message.reaction.created_v1": async (data) => {
|
|
5701
5680
|
await runFeishuHandler({
|
|
@@ -5824,6 +5803,7 @@ async function monitorSingleAccount(params) {
|
|
|
5824
5803
|
runtime,
|
|
5825
5804
|
chatHistories,
|
|
5826
5805
|
fireAndForget: params.fireAndForget ?? true,
|
|
5806
|
+
abortSignal,
|
|
5827
5807
|
...params.statusSink ? { statusSink: params.statusSink } : {}
|
|
5828
5808
|
});
|
|
5829
5809
|
if (connectionMode === "webhook") return await monitorWebhook({
|