@openclaw/feishu 2026.9.8 → 2026.10.1-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/.setup/{channel-DV4hM2Uf.mjs → channel-CX62T71S.mjs} +146 -245
- package/dist/.setup/{channel.runtime-CXQcH5zZ.mjs → channel.runtime-COiaq-Rv.mjs} +6 -12
- package/dist/.setup/{chat-D8MlFAZi.mjs → chat-BdyvImsY.mjs} +6 -9
- package/dist/.setup/{client-BYG-_IZl.mjs → client-BsBVWJzN.mjs} +1 -1
- package/dist/.setup/{doctor-contract-3XC0vbIw.mjs → doctor-contract-B1B9ogdd.mjs} +212 -27
- package/dist/.setup/{monitor-D_rsHBZ6.mjs → monitor-7DvwUs4Y.mjs} +5 -6
- package/dist/.setup/{monitor.account-DvvY7i6k.mjs → monitor.account-7xVu7XWY.mjs} +190 -393
- package/dist/.setup/{probe-_ViqSi0j.mjs → probe-B9o7iey6.mjs} +13 -39
- package/dist/.setup/{reply-delivery-result-COAjaukc.mjs → reply-delivery-result-Bt-BWBEA.mjs} +151 -297
- package/dist/.setup/{setup-api-C4S5I3ac.mjs → setup-api-DmzX9S01.mjs} +1 -1
- package/dist/.setup/{subagent-hooks-BaFoMu8W.mjs → subagent-hooks-CUXg0pC-.mjs} +5 -11
- package/dist/.setup/{thread-bindings-EdLXPXzw.mjs → thread-bindings-jW2x5VuN.mjs} +23 -41
- package/dist/api.js +234 -297
- package/dist/channel-plugin-api.js +1 -1
- package/dist/doctor-contract-api.js +2 -2
- package/dist/session-binding-contract-api.js +1 -1
- package/dist/setup-api.js +1 -1
- package/dist/setup-entry.js +1 -1
- package/dist/subagent-hooks-api.js +1 -1
- package/node_modules/@openclaw/fs-safe/CHANGELOG.md +95 -0
- package/node_modules/@openclaw/fs-safe/README.md +70 -379
- package/node_modules/@openclaw/fs-safe/dist/absolute-path.js +35 -51
- package/node_modules/@openclaw/fs-safe/dist/advanced.d.ts +2 -0
- package/node_modules/@openclaw/fs-safe/dist/advanced.js +1 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-input.js +2 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-parser.wasm +0 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-staging.d.ts +1 -1
- package/node_modules/@openclaw/fs-safe/dist/archive-staging.js +9 -10
- package/node_modules/@openclaw/fs-safe/dist/archive.js +2 -5
- package/node_modules/@openclaw/fs-safe/dist/atomic-io.d.ts +51 -0
- package/node_modules/@openclaw/fs-safe/dist/atomic-io.js +242 -0
- package/node_modules/@openclaw/fs-safe/dist/config.d.ts +1 -1
- package/node_modules/@openclaw/fs-safe/dist/config.js +1 -1
- package/node_modules/@openclaw/fs-safe/dist/copy-file-input.d.ts +1 -1
- package/node_modules/@openclaw/fs-safe/dist/copy-file-input.js +2 -2
- package/node_modules/@openclaw/fs-safe/dist/copy-tree-portable.js +2 -0
- package/node_modules/@openclaw/fs-safe/dist/create.js +12 -5
- package/node_modules/@openclaw/fs-safe/dist/directory-guard.d.ts +11 -0
- package/node_modules/@openclaw/fs-safe/dist/directory-guard.js +4 -7
- package/node_modules/@openclaw/fs-safe/dist/entry-publication-types.d.ts +55 -0
- package/node_modules/@openclaw/fs-safe/dist/entry-publication-types.js +1 -0
- package/node_modules/@openclaw/fs-safe/dist/entry-publication.d.ts +8 -0
- package/node_modules/@openclaw/fs-safe/dist/entry-publication.js +262 -0
- package/node_modules/@openclaw/fs-safe/dist/exclusive-create.d.ts +3 -0
- package/node_modules/@openclaw/fs-safe/dist/exclusive-create.js +22 -0
- package/node_modules/@openclaw/fs-safe/dist/file-cleanup.d.ts +1 -6
- package/node_modules/@openclaw/fs-safe/dist/file-cleanup.js +3 -6
- package/node_modules/@openclaw/fs-safe/dist/file-identity.js +3 -6
- package/node_modules/@openclaw/fs-safe/dist/file-lock-sync-root-io.js +2 -2
- package/node_modules/@openclaw/fs-safe/dist/file-lock-sync-root-mutation.js +9 -0
- package/node_modules/@openclaw/fs-safe/dist/file-lock-sync-root.js +4 -6
- package/node_modules/@openclaw/fs-safe/dist/file-lock-sync-stale-admission.js +1 -1
- package/node_modules/@openclaw/fs-safe/dist/file-lock-sync.js +8 -0
- package/node_modules/@openclaw/fs-safe/dist/file-store-boundary.js +2 -0
- package/node_modules/@openclaw/fs-safe/dist/file-store-sync-write.js +20 -18
- package/node_modules/@openclaw/fs-safe/dist/file-store.js +4 -10
- package/node_modules/@openclaw/fs-safe/dist/fs.d.ts +2 -10
- package/node_modules/@openclaw/fs-safe/dist/fs.js +2 -10
- package/node_modules/@openclaw/fs-safe/dist/guarded-mkdir.d.ts +3 -4
- package/node_modules/@openclaw/fs-safe/dist/guarded-mkdir.js +6 -18
- package/node_modules/@openclaw/fs-safe/dist/guest-dispatch-python.js +1 -1
- package/node_modules/@openclaw/fs-safe/dist/guest-native-python.js +0 -2
- package/node_modules/@openclaw/fs-safe/dist/guest.js +3 -9
- package/node_modules/@openclaw/fs-safe/dist/index.d.ts +1 -1
- package/node_modules/@openclaw/fs-safe/dist/index.js +1 -1
- package/node_modules/@openclaw/fs-safe/dist/json-durable-queue-directory.js +1 -5
- package/node_modules/@openclaw/fs-safe/dist/json.js +19 -37
- package/node_modules/@openclaw/fs-safe/dist/move-path.js +2 -0
- package/node_modules/@openclaw/fs-safe/dist/mutation-authority.d.ts +1 -0
- package/node_modules/@openclaw/fs-safe/dist/mutation-authority.js +9 -1
- package/node_modules/@openclaw/fs-safe/dist/native-binding.d.ts +47 -2
- package/node_modules/@openclaw/fs-safe/dist/native-config.d.ts +1 -9
- package/node_modules/@openclaw/fs-safe/dist/native-config.js +6 -40
- package/node_modules/@openclaw/fs-safe/dist/native-parent-admission.d.ts +2 -0
- package/node_modules/@openclaw/fs-safe/dist/native-parent-admission.js +5 -2
- package/node_modules/@openclaw/fs-safe/dist/native-pinned-write.js +11 -316
- package/node_modules/@openclaw/fs-safe/dist/native-policy-parent-windows.d.ts +7 -7
- package/node_modules/@openclaw/fs-safe/dist/native-policy-parent-windows.js +28 -175
- package/node_modules/@openclaw/fs-safe/dist/native-policy-parent.d.ts +15 -0
- package/node_modules/@openclaw/fs-safe/dist/native-policy-parent.js +418 -0
- package/node_modules/@openclaw/fs-safe/dist/native-rename-outcome.js +9 -4
- package/node_modules/@openclaw/fs-safe/dist/native-staged-file.js +17 -13
- package/node_modules/@openclaw/fs-safe/dist/native-staged-symlink.js +6 -24
- package/node_modules/@openclaw/fs-safe/dist/native.js +5 -1
- package/node_modules/@openclaw/fs-safe/dist/path-case.js +10 -9
- package/node_modules/@openclaw/fs-safe/dist/path-scope-lexical.js +4 -1
- package/node_modules/@openclaw/fs-safe/dist/path-segment-route.d.ts +1 -0
- package/node_modules/@openclaw/fs-safe/dist/path-segment-route.js +3 -0
- package/node_modules/@openclaw/fs-safe/dist/path.js +4 -1
- package/node_modules/@openclaw/fs-safe/dist/permissions-windows.d.ts +0 -1
- package/node_modules/@openclaw/fs-safe/dist/pinned-mutation-admission.js +1 -3
- package/node_modules/@openclaw/fs-safe/dist/pinned-write-staged.js +2 -0
- package/node_modules/@openclaw/fs-safe/dist/pinned-write.js +9 -10
- package/node_modules/@openclaw/fs-safe/dist/private-producer-handoff.js +3 -6
- package/node_modules/@openclaw/fs-safe/dist/publish-copy-stage.js +2 -2
- package/node_modules/@openclaw/fs-safe/dist/publish-file.js +4 -3
- package/node_modules/@openclaw/fs-safe/dist/replace-file-buffer.d.ts +3 -4
- package/node_modules/@openclaw/fs-safe/dist/replace-file-buffer.js +18 -32
- package/node_modules/@openclaw/fs-safe/dist/replace-file-copy-fallback.d.ts +5 -17
- package/node_modules/@openclaw/fs-safe/dist/replace-file-copy-fallback.js +92 -230
- package/node_modules/@openclaw/fs-safe/dist/replace-file-copy-source.d.ts +4 -15
- package/node_modules/@openclaw/fs-safe/dist/replace-file-copy-source.js +22 -63
- package/node_modules/@openclaw/fs-safe/dist/replace-file-descriptor.d.ts +9 -34
- package/node_modules/@openclaw/fs-safe/dist/replace-file-descriptor.js +78 -83
- package/node_modules/@openclaw/fs-safe/dist/replace-file-destination.d.ts +18 -20
- package/node_modules/@openclaw/fs-safe/dist/replace-file-destination.js +64 -98
- package/node_modules/@openclaw/fs-safe/dist/replace-file-temp-owner.d.ts +16 -33
- package/node_modules/@openclaw/fs-safe/dist/replace-file-temp-owner.js +61 -200
- package/node_modules/@openclaw/fs-safe/dist/replace-file-types.d.ts +1 -6
- package/node_modules/@openclaw/fs-safe/dist/replace-file.js +76 -216
- package/node_modules/@openclaw/fs-safe/dist/root-boundary.js +14 -24
- package/node_modules/@openclaw/fs-safe/dist/root-context.d.ts +1 -4
- package/node_modules/@openclaw/fs-safe/dist/root-context.js +4 -19
- package/node_modules/@openclaw/fs-safe/dist/root-create-native.d.ts +52 -0
- package/node_modules/@openclaw/fs-safe/dist/root-create-native.js +350 -0
- package/node_modules/@openclaw/fs-safe/dist/root-directory-list-types.d.ts +35 -0
- package/node_modules/@openclaw/fs-safe/dist/root-directory-list-types.js +1 -0
- package/node_modules/@openclaw/fs-safe/dist/root-directory-list.d.ts +2 -27
- package/node_modules/@openclaw/fs-safe/dist/root-directory-list.js +31 -28
- package/node_modules/@openclaw/fs-safe/dist/root-directory.js +1 -4
- package/node_modules/@openclaw/fs-safe/dist/root-errors.js +34 -0
- package/node_modules/@openclaw/fs-safe/dist/root-file.js +9 -21
- package/node_modules/@openclaw/fs-safe/dist/root-impl.js +105 -37
- package/node_modules/@openclaw/fs-safe/dist/root-move-noreplace.d.ts +7 -2
- package/node_modules/@openclaw/fs-safe/dist/root-move-noreplace.js +67 -38
- package/node_modules/@openclaw/fs-safe/dist/root-observed-path.d.ts +1 -1
- package/node_modules/@openclaw/fs-safe/dist/root-observed-path.js +0 -2
- package/node_modules/@openclaw/fs-safe/dist/root-options.d.ts +2 -3
- package/node_modules/@openclaw/fs-safe/dist/root-path-existing.js +3 -1
- package/node_modules/@openclaw/fs-safe/dist/root-path-stat.js +68 -85
- package/node_modules/@openclaw/fs-safe/dist/root-path.js +6 -1
- package/node_modules/@openclaw/fs-safe/dist/root-paths-lexical.d.ts +4 -0
- package/node_modules/@openclaw/fs-safe/dist/root-paths-lexical.js +1 -1
- package/node_modules/@openclaw/fs-safe/dist/root-paths.js +4 -9
- package/node_modules/@openclaw/fs-safe/dist/root-remove-native.d.ts +4 -0
- package/node_modules/@openclaw/fs-safe/dist/root-remove-native.js +311 -0
- package/node_modules/@openclaw/fs-safe/dist/root-remove.d.ts +11 -0
- package/node_modules/@openclaw/fs-safe/dist/root-remove.js +3 -1
- package/node_modules/@openclaw/fs-safe/dist/root-walk.d.ts +2 -2
- package/node_modules/@openclaw/fs-safe/dist/root-walk.js +1 -3
- package/node_modules/@openclaw/fs-safe/dist/root-write-admission.d.ts +3 -3
- package/node_modules/@openclaw/fs-safe/dist/root-write-admission.js +8 -10
- package/node_modules/@openclaw/fs-safe/dist/safe-path-segment.d.ts +0 -1
- package/node_modules/@openclaw/fs-safe/dist/safe-path-segment.js +0 -4
- package/node_modules/@openclaw/fs-safe/dist/secret-file.js +12 -9
- package/node_modules/@openclaw/fs-safe/dist/secure-temp-dir.d.ts +0 -2
- package/node_modules/@openclaw/fs-safe/dist/sibling-staged-file.js +2 -0
- package/node_modules/@openclaw/fs-safe/dist/sibling-temp.js +7 -4
- package/node_modules/@openclaw/fs-safe/dist/sidecar-lock-acquire.js +13 -6
- package/node_modules/@openclaw/fs-safe/dist/sidecar-lock-reclaim.d.ts +0 -3
- package/node_modules/@openclaw/fs-safe/dist/sidecar-lock-reclaim.js +5 -23
- package/node_modules/@openclaw/fs-safe/dist/staged-file-settlement.d.ts +2 -1
- package/node_modules/@openclaw/fs-safe/dist/staged-file-settlement.js +11 -6
- package/node_modules/@openclaw/fs-safe/dist/temp-cleanup.js +1 -8
- package/node_modules/@openclaw/fs-safe/dist/temp-workspace-child-admission.d.ts +1 -1
- package/node_modules/@openclaw/fs-safe/dist/temp-workspace-child-admission.js +2 -9
- package/node_modules/@openclaw/fs-safe/dist/text-atomic.d.ts +1 -6
- package/node_modules/@openclaw/fs-safe/dist/trash.js +6 -2
- package/node_modules/@openclaw/fs-safe/dist/walk.js +100 -46
- package/node_modules/@openclaw/fs-safe/dist/watch-hints.d.ts +7 -0
- package/node_modules/@openclaw/fs-safe/dist/watch-hints.js +235 -19
- package/node_modules/@openclaw/fs-safe/dist/watch-native.d.ts +21 -2
- package/node_modules/@openclaw/fs-safe/dist/watch-native.js +21 -3
- package/node_modules/@openclaw/fs-safe/dist/watch-rescan.d.ts +6 -0
- package/node_modules/@openclaw/fs-safe/dist/watch-rescan.js +111 -0
- package/node_modules/@openclaw/fs-safe/dist/watch-scan.d.ts +13 -0
- package/node_modules/@openclaw/fs-safe/dist/watch-scan.js +27 -4
- package/node_modules/@openclaw/fs-safe/dist/watch-stream.js +2 -0
- package/node_modules/@openclaw/fs-safe/dist/watch.js +131 -40
- package/node_modules/@openclaw/fs-safe/dist/windows-path-alias.d.ts +8 -0
- package/node_modules/@openclaw/fs-safe/dist/windows-path-alias.js +24 -6
- package/node_modules/@openclaw/fs-safe/dist/windows-path-syntax.d.ts +13 -0
- package/node_modules/@openclaw/fs-safe/dist/windows-path-syntax.js +51 -0
- package/node_modules/@openclaw/fs-safe/docs/advanced.md +4 -0
- package/node_modules/@openclaw/fs-safe/docs/atomic.md +4 -1
- package/node_modules/@openclaw/fs-safe/docs/config.md +6 -14
- package/node_modules/@openclaw/fs-safe/docs/contributing.md +4 -14
- package/node_modules/@openclaw/fs-safe/docs/durability.md +6 -29
- package/node_modules/@openclaw/fs-safe/docs/entry-publication.md +146 -0
- package/node_modules/@openclaw/fs-safe/docs/errors.md +16 -0
- package/node_modules/@openclaw/fs-safe/docs/file-store.md +28 -5
- package/node_modules/@openclaw/fs-safe/docs/index.md +2 -31
- package/node_modules/@openclaw/fs-safe/docs/install.md +10 -31
- package/node_modules/@openclaw/fs-safe/docs/json.md +1 -1
- package/node_modules/@openclaw/fs-safe/docs/local-roots.md +0 -1
- package/node_modules/@openclaw/fs-safe/docs/migrating-to-0.5.md +12 -12
- package/node_modules/@openclaw/fs-safe/docs/native-helper.md +35 -96
- package/node_modules/@openclaw/fs-safe/docs/native.md +22 -20
- package/node_modules/@openclaw/fs-safe/docs/path.md +1 -1
- package/node_modules/@openclaw/fs-safe/docs/permissions.md +1 -2
- package/node_modules/@openclaw/fs-safe/docs/public-api.md +1 -2
- package/node_modules/@openclaw/fs-safe/docs/reading.md +1 -2
- package/node_modules/@openclaw/fs-safe/docs/root.md +26 -184
- package/node_modules/@openclaw/fs-safe/docs/secret-file.md +1 -1
- package/node_modules/@openclaw/fs-safe/docs/security-model.md +115 -3
- package/node_modules/@openclaw/fs-safe/docs/store.md +2 -2
- package/node_modules/@openclaw/fs-safe/docs/temp.md +29 -65
- package/node_modules/@openclaw/fs-safe/docs/testing.md +90 -58
- package/node_modules/@openclaw/fs-safe/docs/types.md +3 -16
- package/node_modules/@openclaw/fs-safe/docs/walk.md +33 -5
- package/node_modules/@openclaw/fs-safe/docs/watch.md +96 -14
- package/node_modules/@openclaw/fs-safe/docs/writing.md +172 -16
- package/node_modules/@openclaw/fs-safe/package.json +10 -10
- package/node_modules/@openclaw/fs-safe-darwin-arm64/fs-safe-native.node +0 -0
- package/node_modules/@openclaw/fs-safe-darwin-arm64/package.json +1 -1
- package/node_modules/@openclaw/fs-safe-darwin-x64/fs-safe-native.node +0 -0
- package/node_modules/@openclaw/fs-safe-darwin-x64/package.json +1 -1
- package/node_modules/@openclaw/fs-safe-linux-arm64-gnu/fs-safe-native.node +0 -0
- package/node_modules/@openclaw/fs-safe-linux-arm64-gnu/package.json +1 -1
- package/node_modules/@openclaw/fs-safe-linux-arm64-musl/fs-safe-native.node +0 -0
- package/node_modules/@openclaw/fs-safe-linux-arm64-musl/package.json +1 -1
- package/node_modules/@openclaw/fs-safe-linux-x64-gnu/fs-safe-native.node +0 -0
- package/node_modules/@openclaw/fs-safe-linux-x64-gnu/package.json +1 -1
- package/node_modules/@openclaw/fs-safe-linux-x64-musl/fs-safe-native.node +0 -0
- package/node_modules/@openclaw/fs-safe-linux-x64-musl/package.json +1 -1
- package/node_modules/@openclaw/fs-safe-win32-x64-msvc/fs-safe-native.node +0 -0
- package/node_modules/@openclaw/fs-safe-win32-x64-msvc/package.json +1 -1
- package/package.json +5 -5
- package/skills/feishu-wiki/SKILL.md +1 -1
- package/dist/.setup/accounts-wRqItHug.mjs +0 -206
- package/node_modules/@openclaw/fs-safe/dist/watch-alias.d.ts +0 -6
- package/node_modules/@openclaw/fs-safe/dist/watch-alias.js +0 -88
- package/node_modules/@openclaw/fs-safe/docs/mutation-policy-proof.md +0 -69
- package/node_modules/@openclaw/fs-safe/docs/private-file-store.md +0 -68
- package/node_modules/@openclaw/fs-safe/docs/test-hooks.md +0 -110
package/dist/.setup/{reply-delivery-result-COAjaukc.mjs → reply-delivery-result-Bt-BWBEA.mjs}
RENAMED
|
@@ -1,20 +1,20 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { c as resolveFeishuRuntimeAccount, i as listFeishuAccountIds, o as resolveDefaultFeishuAccountId, r as listEnabledFeishuAccounts, s as resolveFeishuAccount } from "./accounts-wRqItHug.mjs";
|
|
1
|
+
import { d as listFeishuAccountIds, h as resolveFeishuRuntimeAccount, m as resolveFeishuAccount, p as resolveDefaultFeishuAccountId, s as normalizeFeishuExternalKey, u as listEnabledFeishuAccounts } from "./doctor-contract-B1B9ogdd.mjs";
|
|
3
2
|
import { l as normalizeFeishuTarget, s as detectIdType, u as resolveReceiveIdType } from "./conversation-id-C1ofUfU8.mjs";
|
|
4
3
|
import { t as getFeishuRuntime } from "./runtime-C5JxBWZp.mjs";
|
|
5
|
-
import { c as withFeishuMessageDispatch, o as captureFeishuSendAuthority, r as createFeishuClient, s as runBeforeFeishuMessageDispatch } from "./client-
|
|
4
|
+
import { c as withFeishuMessageDispatch, o as captureFeishuSendAuthority, r as createFeishuClient, s as runBeforeFeishuMessageDispatch } from "./client-BsBVWJzN.mjs";
|
|
6
5
|
import { normalizeAccountId, normalizeOptionalAccountId, resolveMergedAccountConfig } from "openclaw/plugin-sdk/account-resolution";
|
|
7
6
|
import { compileAllowlist, resolveAllowlistMatchByCandidates } from "openclaw/plugin-sdk/allow-from";
|
|
8
7
|
import { ToolAuthorizationError } from "openclaw/plugin-sdk/channel-actions";
|
|
8
|
+
import { normalizeChannelDmPolicy } from "openclaw/plugin-sdk/channel-config-helpers";
|
|
9
9
|
import { createMessageReceiptFromOutboundResults } from "openclaw/plugin-sdk/channel-outbound";
|
|
10
10
|
import { PlatformMessageNotDispatchedError, formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
|
|
11
11
|
import { legacyInteractiveReplyToPresentation, normalizeLegacyInteractiveReply, normalizeMessagePresentation, renderMessagePresentationChartFallbackText, renderMessagePresentationFallbackText, renderMessagePresentationTableFallbackText, renderPresentationForDelivery, resolveLegacyInteractiveTextFallback } from "openclaw/plugin-sdk/interactive-runtime";
|
|
12
12
|
import { parseStrictNonNegativeInteger } from "openclaw/plugin-sdk/number-runtime";
|
|
13
13
|
import { isRecord, normalizeLowercaseStringOrEmpty, normalizeOptionalLowercaseString, normalizeOptionalString, normalizeStringEntries, normalizeTrimmedStringList, readStringValue } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
14
14
|
import { convertMarkdownTables, markdownToIRWithMeta } from "openclaw/plugin-sdk/text-chunking";
|
|
15
|
+
import { jsonResult } from "openclaw/plugin-sdk/tool-results";
|
|
15
16
|
import { resolveDefaultGroupPolicy, resolveOpenProviderRuntimeGroupPolicy } from "openclaw/plugin-sdk/runtime-group-policy";
|
|
16
17
|
import { defineStableChannelIngressIdentity } from "openclaw/plugin-sdk/channel-ingress-runtime";
|
|
17
|
-
import fs from "node:fs";
|
|
18
18
|
import path from "node:path";
|
|
19
19
|
import { fromMarkdown } from "mdast-util-from-markdown";
|
|
20
20
|
import { gfmTableFromMarkdown } from "mdast-util-gfm-table";
|
|
@@ -26,13 +26,11 @@ import { wrapExternalContent, writeExternalFileWithinRoot } from "openclaw/plugi
|
|
|
26
26
|
import { retryAsync } from "openclaw/plugin-sdk/retry-runtime";
|
|
27
27
|
import { readPositiveIntegerParam } from "openclaw/plugin-sdk/param-readers";
|
|
28
28
|
import { Type } from "typebox";
|
|
29
|
-
import { jsonResult } from "openclaw/plugin-sdk/tool-results";
|
|
30
29
|
import { isBlockedHostnameOrIp, resolvePinnedHostnameWithPolicy } from "openclaw/plugin-sdk/ssrf-runtime";
|
|
31
|
-
import { Readable } from "node:stream";
|
|
32
30
|
import { detectMime, mediaKindFromMime } from "openclaw/plugin-sdk/media-mime";
|
|
33
31
|
import { MEDIA_FFMPEG_MAX_AUDIO_DURATION_SECS, buildOutboundMediaLoadOptions, runFfmpeg, runFfprobe } from "openclaw/plugin-sdk/media-runtime";
|
|
34
|
-
import {
|
|
35
|
-
import {
|
|
32
|
+
import { resolvePreferredOpenClawTmpDir, withTempWorkspace } from "openclaw/plugin-sdk/temp-path";
|
|
33
|
+
import { saveMediaStream } from "openclaw/plugin-sdk/media-store";
|
|
36
34
|
import { logVerbose } from "openclaw/plugin-sdk/runtime-env";
|
|
37
35
|
import { escapeHtml, truncateUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime";
|
|
38
36
|
//#region extensions/feishu/src/card-interaction.ts
|
|
@@ -73,30 +71,16 @@ function decodeFeishuCardAction(params) {
|
|
|
73
71
|
kind: "invalid",
|
|
74
72
|
reason: "malformed"
|
|
75
73
|
};
|
|
76
|
-
if (actionValue.m !== void 0) {
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
};
|
|
81
|
-
for (const value of Object.values(actionValue.m)) if (!isMetadataValue(value)) return {
|
|
82
|
-
kind: "invalid",
|
|
83
|
-
reason: "malformed"
|
|
84
|
-
};
|
|
85
|
-
}
|
|
74
|
+
if (actionValue.m !== void 0 && (!isRecord(actionValue.m) || !Object.values(actionValue.m).every(isMetadataValue))) return {
|
|
75
|
+
kind: "invalid",
|
|
76
|
+
reason: "malformed"
|
|
77
|
+
};
|
|
86
78
|
if (actionValue.c !== void 0) {
|
|
87
79
|
if (!isRecord(actionValue.c)) return {
|
|
88
80
|
kind: "invalid",
|
|
89
81
|
reason: "malformed"
|
|
90
82
|
};
|
|
91
|
-
if (actionValue.c.u !== void 0 && typeof actionValue.c.u !== "string") return {
|
|
92
|
-
kind: "invalid",
|
|
93
|
-
reason: "malformed"
|
|
94
|
-
};
|
|
95
|
-
if (actionValue.c.h !== void 0 && typeof actionValue.c.h !== "string") return {
|
|
96
|
-
kind: "invalid",
|
|
97
|
-
reason: "malformed"
|
|
98
|
-
};
|
|
99
|
-
if (actionValue.c.s !== void 0 && typeof actionValue.c.s !== "string") return {
|
|
83
|
+
if (actionValue.c.u !== void 0 && typeof actionValue.c.u !== "string" || actionValue.c.h !== void 0 && typeof actionValue.c.h !== "string" || actionValue.c.s !== void 0 && typeof actionValue.c.s !== "string") return {
|
|
100
84
|
kind: "invalid",
|
|
101
85
|
reason: "malformed"
|
|
102
86
|
};
|
|
@@ -135,8 +119,7 @@ function normalizeFeishuChatType(value) {
|
|
|
135
119
|
if (value === "p2p") return "p2p";
|
|
136
120
|
}
|
|
137
121
|
function normalizeFeishuChatMode(value) {
|
|
138
|
-
|
|
139
|
-
return value === "p2p" ? "p2p" : void 0;
|
|
122
|
+
return value === "topic" ? "group" : normalizeFeishuChatType(value);
|
|
140
123
|
}
|
|
141
124
|
function resolveFeishuChatType(chat) {
|
|
142
125
|
return normalizeFeishuChatMode(chat.chat_mode) ?? normalizeFeishuChatType(chat.chat_type);
|
|
@@ -185,9 +168,6 @@ function normalizeFeishuAllowEntry(raw) {
|
|
|
185
168
|
if (detectedType === "open_id" || detectedType === "user_id") return `user:${withoutProviderPrefix}`;
|
|
186
169
|
return "";
|
|
187
170
|
}
|
|
188
|
-
function normalizeFeishuDmPolicy(policy) {
|
|
189
|
-
return policy === "open" || policy === "pairing" || policy === "allowlist" || policy === "disabled" ? policy : "pairing";
|
|
190
|
-
}
|
|
191
171
|
function normalizeFeishuGroupPolicy(policy) {
|
|
192
172
|
return policy === "allowall" ? "open" : policy;
|
|
193
173
|
}
|
|
@@ -219,7 +199,7 @@ async function resolveFeishuDmIngressAccess(params) {
|
|
|
219
199
|
},
|
|
220
200
|
...params.contextBinding ? { contextBinding: params.contextBinding } : {},
|
|
221
201
|
event: { mayPair: params.mayPair },
|
|
222
|
-
dmPolicy:
|
|
202
|
+
dmPolicy: normalizeChannelDmPolicy(params.dmPolicy ?? void 0) ?? "pairing",
|
|
223
203
|
groupPolicy: "disabled",
|
|
224
204
|
allowFrom: params.allowFrom ?? [],
|
|
225
205
|
...params.command ? { command: params.command } : {}
|
|
@@ -376,7 +356,7 @@ function isFeishuGroupReadEnabled(cfg, account, chatId) {
|
|
|
376
356
|
groupId: chatId
|
|
377
357
|
})?.enabled !== false;
|
|
378
358
|
}
|
|
379
|
-
function
|
|
359
|
+
function canEnumerateAllFeishuPeers(account) {
|
|
380
360
|
return compileAllowlist(normalizeFeishuAllowlist(account.config.allowFrom)).wildcard;
|
|
381
361
|
}
|
|
382
362
|
function assertFeishuChatReadAllowed(params) {
|
|
@@ -399,7 +379,7 @@ function resolveFeishuChatReadPreliminaryAuthorization(params) {
|
|
|
399
379
|
});
|
|
400
380
|
const directOperator = readContextFields(params.ctx).directOperator;
|
|
401
381
|
const groupAllowed = directOperator ? isFeishuGroupReadEnabled(params.cfg, params.account, chatId) : isFeishuGroupReadAllowed(params.cfg, params.account, chatId, current);
|
|
402
|
-
const dmAllowed = directOperator || current ||
|
|
382
|
+
const dmAllowed = directOperator || current || canEnumerateAllFeishuPeers(params.account);
|
|
403
383
|
if (knownGroup) return {
|
|
404
384
|
chatId,
|
|
405
385
|
decision: groupAllowed ? "allow" : "deny"
|
|
@@ -469,9 +449,6 @@ function canEnumerateAllFeishuGroups(cfg, account) {
|
|
|
469
449
|
const policy = resolveFeishuReadGroupPolicy(cfg, account);
|
|
470
450
|
return policy === "open" || policy === "allowlist" && compileAllowlist(normalizeFeishuAllowlist(account.config.groupAllowFrom)).wildcard;
|
|
471
451
|
}
|
|
472
|
-
function canEnumerateAllFeishuPeers(account) {
|
|
473
|
-
return isDmUniversallyAllowed(account);
|
|
474
|
-
}
|
|
475
452
|
//#endregion
|
|
476
453
|
//#region extensions/feishu/src/markdown.ts
|
|
477
454
|
const FEISHU_POST_MAX_BYTES = 30720;
|
|
@@ -485,6 +462,18 @@ function parseFeishuMarkdown(text) {
|
|
|
485
462
|
mdastExtensions: [gfmTableFromMarkdown()]
|
|
486
463
|
});
|
|
487
464
|
}
|
|
465
|
+
function visitFeishuMarkdown(root, visitor) {
|
|
466
|
+
const pending = [root];
|
|
467
|
+
while (pending.length > 0) {
|
|
468
|
+
const node = pending.pop();
|
|
469
|
+
if (!node) continue;
|
|
470
|
+
visitor(node);
|
|
471
|
+
for (let index = (node.children?.length ?? 0) - 1; index >= 0; index -= 1) {
|
|
472
|
+
const child = node.children?.[index];
|
|
473
|
+
if (child) pending.push(child);
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
}
|
|
488
477
|
function buildFeishuPostMentionElements(mentions) {
|
|
489
478
|
if (!mentions?.length) return [];
|
|
490
479
|
const elements = [];
|
|
@@ -513,15 +502,11 @@ function assertFeishuPostWithinEnvelope(content, label) {
|
|
|
513
502
|
function collectSoftBreakOffsets(text) {
|
|
514
503
|
const root = parseFeishuMarkdown(text);
|
|
515
504
|
const offsets = [];
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
const node = pending.pop();
|
|
519
|
-
if (!node) continue;
|
|
520
|
-
if (node.children) pending.push(...node.children);
|
|
521
|
-
if (node.type !== "text") continue;
|
|
505
|
+
visitFeishuMarkdown(root, (node) => {
|
|
506
|
+
if (node.type !== "text") return;
|
|
522
507
|
const start = node.position?.start.offset;
|
|
523
508
|
const end = node.position?.end.offset;
|
|
524
|
-
if (start === void 0 || end === void 0)
|
|
509
|
+
if (start === void 0 || end === void 0) return;
|
|
525
510
|
for (let offset = start; offset < end; offset += 1) {
|
|
526
511
|
const char = text[offset];
|
|
527
512
|
if (char === "\n") {
|
|
@@ -533,7 +518,7 @@ function collectSoftBreakOffsets(text) {
|
|
|
533
518
|
if (text[offset + 1] === "\n") offset += 1;
|
|
534
519
|
}
|
|
535
520
|
}
|
|
536
|
-
}
|
|
521
|
+
});
|
|
537
522
|
return offsets.toSorted((left, right) => left - right);
|
|
538
523
|
}
|
|
539
524
|
/**
|
|
@@ -628,14 +613,7 @@ function resolveFeishuCardTemplate(template) {
|
|
|
628
613
|
return normalized;
|
|
629
614
|
}
|
|
630
615
|
function escapeFeishuCardMarkdownText(text) {
|
|
631
|
-
return text.
|
|
632
|
-
switch (char) {
|
|
633
|
-
case "&": return "&";
|
|
634
|
-
case "<": return "<";
|
|
635
|
-
case ">": return ">";
|
|
636
|
-
default: return char;
|
|
637
|
-
}
|
|
638
|
-
});
|
|
616
|
+
return text.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">");
|
|
639
617
|
}
|
|
640
618
|
function escapeFeishuCardPlainText(text) {
|
|
641
619
|
return escapeFeishuCardMarkdownText(text).replace(/([\\`*_{}[\]()#+\-!|>~])/g, "\\$1");
|
|
@@ -664,11 +642,13 @@ function sanitizeNativeFeishuButtonBehavior(behavior) {
|
|
|
664
642
|
value: behavior.value
|
|
665
643
|
};
|
|
666
644
|
}
|
|
645
|
+
function resolveFeishuButtonType(style) {
|
|
646
|
+
return style === "primary" || style === "success" ? "primary" : style === "danger" ? "danger" : "default";
|
|
647
|
+
}
|
|
667
648
|
function sanitizeNativeFeishuCardButton(button) {
|
|
668
649
|
if (!isRecord(button)) return;
|
|
669
650
|
const text = isRecord(button.text) && typeof button.text.content === "string" ? button.text.content : void 0;
|
|
670
651
|
if (!text?.trim()) return;
|
|
671
|
-
const style = button.type === "danger" ? "danger" : button.type === "primary" || button.type === "success" ? "primary" : void 0;
|
|
672
652
|
const behaviors = Array.isArray(button.behaviors) ? button.behaviors.map(sanitizeNativeFeishuButtonBehavior).filter((behavior) => Boolean(behavior)) : [];
|
|
673
653
|
const rootSafeUrl = resolveSafeFeishuButtonUrl(button.url);
|
|
674
654
|
if (rootSafeUrl) behaviors.push({
|
|
@@ -686,7 +666,7 @@ function sanitizeNativeFeishuCardButton(button) {
|
|
|
686
666
|
tag: "plain_text",
|
|
687
667
|
content: text
|
|
688
668
|
},
|
|
689
|
-
type:
|
|
669
|
+
type: resolveFeishuButtonType(button.type),
|
|
690
670
|
behaviors
|
|
691
671
|
};
|
|
692
672
|
}
|
|
@@ -784,8 +764,7 @@ function getFeishuSendRateLimitCode(error) {
|
|
|
784
764
|
if (!isRecord(error)) return;
|
|
785
765
|
const response = isRecord(error.response) ? error.response : void 0;
|
|
786
766
|
if (response?.status === 429) return 429;
|
|
787
|
-
|
|
788
|
-
return typeof code === "number" && FEISHU_SEND_RATE_LIMIT_CODES.has(code) ? code : void 0;
|
|
767
|
+
return getFeishuSendRateLimitCodeFromResponse(response?.data);
|
|
789
768
|
}
|
|
790
769
|
function getFeishuSendRateLimitCodeFromResponse(response) {
|
|
791
770
|
if (!isRecord(response)) return;
|
|
@@ -1243,7 +1222,6 @@ const DEFAULT_TOOLS_CONFIG = {
|
|
|
1243
1222
|
scopes: true,
|
|
1244
1223
|
bitable: true
|
|
1245
1224
|
};
|
|
1246
|
-
/** Resolve tools config with defaults. */
|
|
1247
1225
|
function resolveToolsConfig(cfg) {
|
|
1248
1226
|
return {
|
|
1249
1227
|
...DEFAULT_TOOLS_CONFIG,
|
|
@@ -1369,11 +1347,8 @@ function registerFeishuTool(api, tool) {
|
|
|
1369
1347
|
//#endregion
|
|
1370
1348
|
//#region extensions/feishu/src/drive.ts
|
|
1371
1349
|
const FEISHU_DRIVE_REQUEST_TIMEOUT_MS = 3e4;
|
|
1372
|
-
function
|
|
1373
|
-
return client
|
|
1374
|
-
}
|
|
1375
|
-
async function requestDriveApi(params) {
|
|
1376
|
-
return await getDriveInternalClient(params.client).request({
|
|
1350
|
+
function requestDriveApi(params) {
|
|
1351
|
+
return params.client.request({
|
|
1377
1352
|
method: params.method,
|
|
1378
1353
|
url: params.url,
|
|
1379
1354
|
params: params.query ?? {},
|
|
@@ -1449,9 +1424,8 @@ function extractDriveApiErrorMeta(error) {
|
|
|
1449
1424
|
};
|
|
1450
1425
|
}
|
|
1451
1426
|
async function getRootFolderToken(client) {
|
|
1452
|
-
const
|
|
1453
|
-
const
|
|
1454
|
-
const res = await internalClient.httpInstance.get(`${domain}/open-apis/drive/explorer/v2/root_folder/meta`);
|
|
1427
|
+
const domain = client.domain ?? "https://open.feishu.cn";
|
|
1428
|
+
const res = await client.httpInstance.get(`${domain}/open-apis/drive/explorer/v2/root_folder/meta`);
|
|
1455
1429
|
if (res.code !== 0) throw new Error(res.msg ?? "Failed to get root folder");
|
|
1456
1430
|
const token = res.data?.token;
|
|
1457
1431
|
if (!token) throw new Error("Root folder token not found");
|
|
@@ -1652,35 +1626,24 @@ async function deliverCommentThreadText(client, params) {
|
|
|
1652
1626
|
if (isWholeComment) {
|
|
1653
1627
|
if (params.file_type !== "doc" && params.file_type !== "docx") throw new Error(`Whole-document comment follow-ups are only supported for doc/docx (got ${params.file_type})`);
|
|
1654
1628
|
console.info(`[feishu_drive] whole-comment compatibility path comment=${params.comment_id} file_type=${params.file_type} mode=add_comment`);
|
|
1655
|
-
|
|
1656
|
-
delivery_mode: "add_comment",
|
|
1657
|
-
...await addComment(client, {
|
|
1658
|
-
file_token: params.file_token,
|
|
1659
|
-
file_type: params.file_type,
|
|
1660
|
-
content: params.content
|
|
1661
|
-
})
|
|
1662
|
-
};
|
|
1663
|
-
}
|
|
1664
|
-
try {
|
|
1629
|
+
} else try {
|
|
1665
1630
|
return {
|
|
1666
1631
|
delivery_mode: "reply_comment",
|
|
1667
1632
|
...await replyComment(client, params)
|
|
1668
1633
|
};
|
|
1669
1634
|
} catch (error) {
|
|
1670
|
-
if (error instanceof FeishuReplyCommentError
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
return {
|
|
1674
|
-
delivery_mode: "add_comment",
|
|
1675
|
-
...await addComment(client, {
|
|
1676
|
-
file_token: params.file_token,
|
|
1677
|
-
file_type: params.file_type,
|
|
1678
|
-
content: params.content
|
|
1679
|
-
})
|
|
1680
|
-
};
|
|
1681
|
-
}
|
|
1682
|
-
throw error;
|
|
1635
|
+
if (!(error instanceof FeishuReplyCommentError) || error.feishuCode !== 1069302) throw error;
|
|
1636
|
+
if (params.file_type !== "doc" && params.file_type !== "docx") throw error;
|
|
1637
|
+
console.info(`[feishu_drive] reply-not-allowed compatibility path comment=${params.comment_id} file_type=${params.file_type} mode=add_comment log_id=${error.feishuLogId ?? "unknown"}`);
|
|
1683
1638
|
}
|
|
1639
|
+
return {
|
|
1640
|
+
delivery_mode: "add_comment",
|
|
1641
|
+
...await addComment(client, {
|
|
1642
|
+
file_token: params.file_token,
|
|
1643
|
+
file_type: params.file_type,
|
|
1644
|
+
content: params.content
|
|
1645
|
+
})
|
|
1646
|
+
};
|
|
1684
1647
|
}
|
|
1685
1648
|
function registerFeishuDriveTools(api) {
|
|
1686
1649
|
registerFeishuTool(api, {
|
|
@@ -1716,7 +1679,7 @@ function registerFeishuDriveTools(api) {
|
|
|
1716
1679
|
return feishuExternalToolResult(await (resolved.action === "add_comment" ? addComment(client, resolved) : deliverCommentThreadText(client, resolved)));
|
|
1717
1680
|
} finally {
|
|
1718
1681
|
cleanupAmbientCommentTypingReaction({
|
|
1719
|
-
client
|
|
1682
|
+
client,
|
|
1720
1683
|
deliveryContext: ctx.deliveryContext
|
|
1721
1684
|
});
|
|
1722
1685
|
}
|
|
@@ -1908,7 +1871,7 @@ function renderCodeBlockElement(element) {
|
|
|
1908
1871
|
}
|
|
1909
1872
|
function renderElement(element, attachments, mentionedOpenIds, renderMediaPlaceholders) {
|
|
1910
1873
|
if (!isRecord(element)) return escapeMarkdownText(toStringOrEmpty(element));
|
|
1911
|
-
switch (normalizeLowercaseStringOrEmpty(
|
|
1874
|
+
switch (normalizeLowercaseStringOrEmpty(element.tag)) {
|
|
1912
1875
|
case "text": return applyInlineStyles(escapeMarkdownText(toStringOrEmpty(element.text)), element.style);
|
|
1913
1876
|
case "a": return applyInlineStyles(renderLinkElement(element), element.style);
|
|
1914
1877
|
case "at":
|
|
@@ -1919,7 +1882,7 @@ function renderElement(element, attachments, mentionedOpenIds, renderMediaPlaceh
|
|
|
1919
1882
|
}
|
|
1920
1883
|
return applyInlineStyles(renderMentionElement(element), element.style);
|
|
1921
1884
|
case "img": {
|
|
1922
|
-
const imageKey = normalizeFeishuExternalKey(
|
|
1885
|
+
const imageKey = normalizeFeishuExternalKey(element.image_key);
|
|
1923
1886
|
if (imageKey) attachments.push({
|
|
1924
1887
|
kind: "image",
|
|
1925
1888
|
key: imageKey
|
|
@@ -1927,7 +1890,7 @@ function renderElement(element, attachments, mentionedOpenIds, renderMediaPlaceh
|
|
|
1927
1890
|
return renderMediaPlaceholders ? "![image]" : "";
|
|
1928
1891
|
}
|
|
1929
1892
|
case "media": {
|
|
1930
|
-
const fileKey = normalizeFeishuExternalKey(
|
|
1893
|
+
const fileKey = normalizeFeishuExternalKey(element.file_key);
|
|
1931
1894
|
if (fileKey) {
|
|
1932
1895
|
const fileName = toStringOrEmpty(element.file_name) || void 0;
|
|
1933
1896
|
attachments.push({
|
|
@@ -1952,11 +1915,29 @@ function renderElement(element, attachments, mentionedOpenIds, renderMediaPlaceh
|
|
|
1952
1915
|
default: return escapeMarkdownText(toStringOrEmpty(element.text));
|
|
1953
1916
|
}
|
|
1954
1917
|
}
|
|
1918
|
+
function appendTopLevelPostFiles(attachments, files) {
|
|
1919
|
+
if (!Array.isArray(files)) return;
|
|
1920
|
+
const seenFileKeys = new Set(attachments.filter((attachment) => attachment.kind === "file").map((attachment) => attachment.key));
|
|
1921
|
+
for (const entry of files) {
|
|
1922
|
+
if (!isRecord(entry) || entry.is_folder === true) continue;
|
|
1923
|
+
const fileKey = normalizeFeishuExternalKey(entry.file_key);
|
|
1924
|
+
if (!fileKey || seenFileKeys.has(fileKey)) continue;
|
|
1925
|
+
seenFileKeys.add(fileKey);
|
|
1926
|
+
const fileName = toStringOrEmpty(entry.file_name) || void 0;
|
|
1927
|
+
attachments.push({
|
|
1928
|
+
kind: "file",
|
|
1929
|
+
key: fileKey,
|
|
1930
|
+
origin: "top-level",
|
|
1931
|
+
...fileName ? { fileName } : {}
|
|
1932
|
+
});
|
|
1933
|
+
}
|
|
1934
|
+
}
|
|
1955
1935
|
function toPostPayload(candidate) {
|
|
1956
1936
|
if (!isRecord(candidate) || !Array.isArray(candidate.content)) return null;
|
|
1957
1937
|
return {
|
|
1958
1938
|
title: toStringOrEmpty(candidate.title),
|
|
1959
|
-
content: candidate.content
|
|
1939
|
+
content: candidate.content,
|
|
1940
|
+
...Array.isArray(candidate.files) ? { files: candidate.files } : {}
|
|
1960
1941
|
};
|
|
1961
1942
|
}
|
|
1962
1943
|
function resolveLocalePayload(candidate) {
|
|
@@ -1970,12 +1951,7 @@ function resolveLocalePayload(candidate) {
|
|
|
1970
1951
|
return null;
|
|
1971
1952
|
}
|
|
1972
1953
|
function resolvePostPayload(parsed) {
|
|
1973
|
-
|
|
1974
|
-
if (direct) return direct;
|
|
1975
|
-
if (!isRecord(parsed)) return null;
|
|
1976
|
-
const wrappedPost = resolveLocalePayload(parsed.post);
|
|
1977
|
-
if (wrappedPost) return wrappedPost;
|
|
1978
|
-
return resolveLocalePayload(parsed);
|
|
1954
|
+
return toPostPayload(parsed) ?? (isRecord(parsed) ? resolveLocalePayload(parsed.post) ?? resolveLocalePayload(parsed) : null);
|
|
1979
1955
|
}
|
|
1980
1956
|
function parsePostContent(content, options = {}) {
|
|
1981
1957
|
try {
|
|
@@ -2005,6 +1981,10 @@ function renderPostContent(parsed, options = {}) {
|
|
|
2005
1981
|
for (const element of paragraph) renderedParagraph += renderElement(element, attachments, mentionedOpenIds, options.renderMediaPlaceholders !== false);
|
|
2006
1982
|
paragraphs.push(renderedParagraph);
|
|
2007
1983
|
}
|
|
1984
|
+
if (options.includeTopLevelFiles !== false) {
|
|
1985
|
+
appendTopLevelPostFiles(attachments, payload.files);
|
|
1986
|
+
if (isRecord(parsed)) appendTopLevelPostFiles(attachments, parsed.files);
|
|
1987
|
+
}
|
|
2008
1988
|
return {
|
|
2009
1989
|
textContent: [escapeMarkdownText(payload.title.trim()), paragraphs.join("\n").trim()].filter(Boolean).join("\n\n").trim() || (options.emptyTextFallback ?? FALLBACK_POST_TEXT),
|
|
2010
1990
|
attachments,
|
|
@@ -2093,13 +2073,12 @@ function extractInteractiveElementText(element, variables) {
|
|
|
2093
2073
|
if (Array.isArray(element.fields)) parts.push(extractInteractiveElementsText(element.fields, variables));
|
|
2094
2074
|
return parts.filter(Boolean).join("\n") || void 0;
|
|
2095
2075
|
}
|
|
2096
|
-
if ((tag === "markdown" || tag === "lark_md") && typeof element.content === "string") return applyCardTemplateVariables(element.content, variables);
|
|
2076
|
+
if ((tag === "markdown" || tag === "lark_md" || tag === "plain_text") && typeof element.content === "string") return applyCardTemplateVariables(element.content, variables);
|
|
2097
2077
|
if ((tag === "text" || tag === "a" || tag === "button") && element.text !== void 0) return normalizeInteractiveValue(element.text, variables) || void 0;
|
|
2098
2078
|
if (tag === "at") {
|
|
2099
2079
|
const mention = normalizeInteractiveValue(element.user_name ?? element.user_id, variables);
|
|
2100
2080
|
return mention ? mention.startsWith("@") ? mention : `@${mention}` : void 0;
|
|
2101
2081
|
}
|
|
2102
|
-
if (tag === "plain_text" && typeof element.content === "string") return applyCardTemplateVariables(element.content, variables);
|
|
2103
2082
|
if (tag === "table") return extractInteractiveTableText(element, variables);
|
|
2104
2083
|
return [
|
|
2105
2084
|
element.elements,
|
|
@@ -2192,9 +2171,7 @@ function isMentionForwardRequest(event, botOpenId) {
|
|
|
2192
2171
|
if (!normalizedBotOpenId) return false;
|
|
2193
2172
|
const isDirectMessage = !isFeishuGroupChatType(event.message.chat_type);
|
|
2194
2173
|
const userMentions = mentions.filter((m) => !isFeishuBroadcastMention(m));
|
|
2195
|
-
|
|
2196
|
-
if (isDirectMessage) return hasOtherMention;
|
|
2197
|
-
return userMentions.some((m) => m.id.open_id === normalizedBotOpenId) && hasOtherMention;
|
|
2174
|
+
return userMentions.some((m) => m.id.open_id !== normalizedBotOpenId) && (isDirectMessage || userMentions.some((m) => m.id.open_id === normalizedBotOpenId));
|
|
2198
2175
|
}
|
|
2199
2176
|
function buildMentionedCardContent(targets, message) {
|
|
2200
2177
|
if (targets.length === 0) return message;
|
|
@@ -2320,21 +2297,21 @@ function isWithdrawnReplyError(err) {
|
|
|
2320
2297
|
if (cause && cause !== err) return isWithdrawnReplyError(cause);
|
|
2321
2298
|
return false;
|
|
2322
2299
|
}
|
|
2323
|
-
|
|
2324
|
-
|
|
2325
|
-
const
|
|
2326
|
-
|
|
2327
|
-
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
|
|
2331
|
-
|
|
2332
|
-
|
|
2333
|
-
|
|
2334
|
-
|
|
2335
|
-
|
|
2336
|
-
|
|
2337
|
-
if (!params.replyToMessageId) return
|
|
2300
|
+
async function sendReplyOrFallbackDirect(target, params) {
|
|
2301
|
+
const { client, receiveId, receiveIdType } = target;
|
|
2302
|
+
const sendDirect = async () => {
|
|
2303
|
+
const response = await requestFeishuApi(() => withFeishuMessageDispatch(() => client.im.message.create({
|
|
2304
|
+
params: { receive_id_type: receiveIdType },
|
|
2305
|
+
data: {
|
|
2306
|
+
receive_id: receiveId,
|
|
2307
|
+
content: params.content,
|
|
2308
|
+
msg_type: params.msgType
|
|
2309
|
+
}
|
|
2310
|
+
})), params.directErrorPrefix, { includeNestedErrorLogId: true });
|
|
2311
|
+
assertFeishuApiSuccess(response, params.directErrorPrefix);
|
|
2312
|
+
return toFeishuSendResult(response, receiveId, resolveFeishuReceiptKind(params.msgType), params.directErrorPrefix);
|
|
2313
|
+
};
|
|
2314
|
+
if (!params.replyToMessageId) return sendDirect();
|
|
2338
2315
|
const replyTargetFallbackError = params.replyInThread && params.allowTopLevelReplyFallback !== true ? /* @__PURE__ */ new Error("Feishu thread reply failed: reply target is unavailable and cannot safely fall back to a top-level send.") : null;
|
|
2339
2316
|
let response;
|
|
2340
2317
|
try {
|
|
@@ -2349,14 +2326,14 @@ async function sendReplyOrFallbackDirect(client, params) {
|
|
|
2349
2326
|
} catch (err) {
|
|
2350
2327
|
if (!isWithdrawnReplyError(err)) throw err;
|
|
2351
2328
|
if (replyTargetFallbackError) throw replyTargetFallbackError;
|
|
2352
|
-
return
|
|
2329
|
+
return sendDirect();
|
|
2353
2330
|
}
|
|
2354
2331
|
if (shouldFallbackFromReplyTarget(response)) {
|
|
2355
2332
|
if (replyTargetFallbackError) throw replyTargetFallbackError;
|
|
2356
|
-
return
|
|
2333
|
+
return sendDirect();
|
|
2357
2334
|
}
|
|
2358
2335
|
assertFeishuApiSuccess(response, params.replyErrorPrefix);
|
|
2359
|
-
return toFeishuSendResult(response,
|
|
2336
|
+
return toFeishuSendResult(response, receiveId, resolveFeishuReceiptKind(params.msgType), params.replyErrorPrefix, params.replyToMessageId);
|
|
2360
2337
|
}
|
|
2361
2338
|
function parseFeishuMessageContent(rawContent, msgType, messageId) {
|
|
2362
2339
|
if (!rawContent) return "";
|
|
@@ -2398,10 +2375,6 @@ function parseFeishuMessageItem(item, fallbackMessageId) {
|
|
|
2398
2375
|
threadId: item.thread_id || void 0
|
|
2399
2376
|
};
|
|
2400
2377
|
}
|
|
2401
|
-
/**
|
|
2402
|
-
* Get a message by its ID.
|
|
2403
|
-
* Useful for fetching quoted/replied message content.
|
|
2404
|
-
*/
|
|
2405
2378
|
async function getMessageFeishu(params) {
|
|
2406
2379
|
const { cfg, messageId, accountId } = params;
|
|
2407
2380
|
const client = createConfiguredFeishuClient({
|
|
@@ -2477,12 +2450,8 @@ async function listFeishuThreadMessages(params) {
|
|
|
2477
2450
|
return results;
|
|
2478
2451
|
}
|
|
2479
2452
|
async function sendMessageFeishu(params) {
|
|
2480
|
-
const { cfg,
|
|
2481
|
-
const
|
|
2482
|
-
cfg,
|
|
2483
|
-
to,
|
|
2484
|
-
accountId
|
|
2485
|
-
});
|
|
2453
|
+
const { cfg, text, preparedPostText, mentions } = params;
|
|
2454
|
+
const target = resolveFeishuSendTarget(params);
|
|
2486
2455
|
let messageText = text;
|
|
2487
2456
|
if (!preparedPostText) {
|
|
2488
2457
|
const tableMode = resolveMarkdownTableMode({
|
|
@@ -2495,44 +2464,20 @@ async function sendMessageFeishu(params) {
|
|
|
2495
2464
|
messageText,
|
|
2496
2465
|
mentions
|
|
2497
2466
|
});
|
|
2498
|
-
const msgType = "post";
|
|
2499
2467
|
assertFeishuPostWithinEnvelope(content, "Feishu post");
|
|
2500
|
-
return sendReplyOrFallbackDirect(
|
|
2501
|
-
|
|
2502
|
-
replyInThread,
|
|
2503
|
-
allowTopLevelReplyFallback,
|
|
2468
|
+
return sendReplyOrFallbackDirect(target, {
|
|
2469
|
+
...params,
|
|
2504
2470
|
content,
|
|
2505
|
-
msgType,
|
|
2506
|
-
directParams: {
|
|
2507
|
-
receiveId,
|
|
2508
|
-
receiveIdType,
|
|
2509
|
-
content,
|
|
2510
|
-
msgType
|
|
2511
|
-
},
|
|
2471
|
+
msgType: "post",
|
|
2512
2472
|
directErrorPrefix: "Feishu send failed",
|
|
2513
2473
|
replyErrorPrefix: "Feishu reply failed"
|
|
2514
2474
|
});
|
|
2515
2475
|
}
|
|
2516
2476
|
async function sendCardFeishu(params) {
|
|
2517
|
-
|
|
2518
|
-
|
|
2519
|
-
|
|
2520
|
-
to,
|
|
2521
|
-
accountId
|
|
2522
|
-
});
|
|
2523
|
-
const content = JSON.stringify(card);
|
|
2524
|
-
return sendReplyOrFallbackDirect(client, {
|
|
2525
|
-
replyToMessageId,
|
|
2526
|
-
replyInThread,
|
|
2527
|
-
allowTopLevelReplyFallback,
|
|
2528
|
-
content,
|
|
2477
|
+
return sendReplyOrFallbackDirect(resolveFeishuSendTarget(params), {
|
|
2478
|
+
...params,
|
|
2479
|
+
content: JSON.stringify(params.card),
|
|
2529
2480
|
msgType: "interactive",
|
|
2530
|
-
directParams: {
|
|
2531
|
-
receiveId,
|
|
2532
|
-
receiveIdType,
|
|
2533
|
-
content,
|
|
2534
|
-
msgType: "interactive"
|
|
2535
|
-
},
|
|
2536
2481
|
directErrorPrefix: "Feishu card send failed",
|
|
2537
2482
|
replyErrorPrefix: "Feishu card reply failed"
|
|
2538
2483
|
});
|
|
@@ -2575,9 +2520,6 @@ async function editMessageFeishu(params) {
|
|
|
2575
2520
|
contentType: "post"
|
|
2576
2521
|
};
|
|
2577
2522
|
}
|
|
2578
|
-
/**
|
|
2579
|
-
* Build a Feishu interactive card with optional header and note footer.
|
|
2580
|
-
*/
|
|
2581
2523
|
function buildStructuredCard(text, options) {
|
|
2582
2524
|
const elements = [{
|
|
2583
2525
|
tag: "markdown",
|
|
@@ -2614,9 +2556,6 @@ function chunkFeishuCardMarkdown(params) {
|
|
|
2614
2556
|
})), "utf8")
|
|
2615
2557
|
});
|
|
2616
2558
|
}
|
|
2617
|
-
/**
|
|
2618
|
-
* Send a message as a structured card with optional header and note.
|
|
2619
|
-
*/
|
|
2620
2559
|
async function sendStructuredCardFeishu(params) {
|
|
2621
2560
|
return sendCardFeishu({
|
|
2622
2561
|
...params,
|
|
@@ -2666,13 +2605,10 @@ function createConfiguredFeishuMediaClient(params) {
|
|
|
2666
2605
|
accountId: params.accountId
|
|
2667
2606
|
});
|
|
2668
2607
|
if (!account.configured) throw new Error(`Feishu account "${account.accountId}" not configured`);
|
|
2669
|
-
return {
|
|
2670
|
-
account,
|
|
2671
|
-
|
|
2672
|
-
|
|
2673
|
-
httpTimeoutMs: FEISHU_MEDIA_HTTP_TIMEOUT_MS
|
|
2674
|
-
})
|
|
2675
|
-
};
|
|
2608
|
+
return createFeishuClient({
|
|
2609
|
+
...account,
|
|
2610
|
+
httpTimeoutMs: FEISHU_MEDIA_HTTP_TIMEOUT_MS
|
|
2611
|
+
});
|
|
2676
2612
|
}
|
|
2677
2613
|
function asHeaderMap(value) {
|
|
2678
2614
|
if (!value) return;
|
|
@@ -2726,39 +2662,6 @@ function decodeDispositionFileName(value) {
|
|
|
2726
2662
|
const plainFileName = value.match(/filename="?([^";]+)"?/i)?.[1]?.trim();
|
|
2727
2663
|
return plainFileName ? recoverUtf8FileNameFromLatin1Header(plainFileName) : void 0;
|
|
2728
2664
|
}
|
|
2729
|
-
function extractFeishuDownloadMetadata(response) {
|
|
2730
|
-
const responseWithOptionalFields = response;
|
|
2731
|
-
const headers = asHeaderMap(responseWithOptionalFields.headers) ?? asHeaderMap(responseWithOptionalFields.header);
|
|
2732
|
-
const contentType = readHeaderValue(headers, "content-type") ?? responseWithOptionalFields.contentType ?? responseWithOptionalFields.mime_type ?? responseWithOptionalFields.data?.contentType ?? responseWithOptionalFields.data?.mime_type;
|
|
2733
|
-
const disposition = readHeaderValue(headers, "content-disposition");
|
|
2734
|
-
return {
|
|
2735
|
-
contentType,
|
|
2736
|
-
fileName: (disposition ? decodeDispositionFileName(disposition) : void 0) ?? responseWithOptionalFields.file_name ?? responseWithOptionalFields.fileName ?? responseWithOptionalFields.data?.file_name ?? responseWithOptionalFields.data?.fileName
|
|
2737
|
-
};
|
|
2738
|
-
}
|
|
2739
|
-
function mediaLimitError(maxBytes) {
|
|
2740
|
-
return /* @__PURE__ */ new Error(`Media exceeds ${Math.round(maxBytes / 1048576)}MB limit`);
|
|
2741
|
-
}
|
|
2742
|
-
async function saveFeishuResponseMedia(params) {
|
|
2743
|
-
const { response, maxBytes, contentType, fileName } = params;
|
|
2744
|
-
if (Buffer.isBuffer(response)) return saveMediaBuffer(response, contentType, "inbound", maxBytes, fileName);
|
|
2745
|
-
if (response instanceof ArrayBuffer) return saveMediaBuffer(Buffer.from(response), contentType, "inbound", maxBytes, fileName);
|
|
2746
|
-
const responseWithOptionalFields = response;
|
|
2747
|
-
if (responseWithOptionalFields.code !== void 0 && responseWithOptionalFields.code !== 0) throw new Error(`${params.errorPrefix}: ${responseWithOptionalFields.msg || `code ${responseWithOptionalFields.code}`}`);
|
|
2748
|
-
const data = responseWithOptionalFields.data;
|
|
2749
|
-
if (Buffer.isBuffer(data) || data instanceof ArrayBuffer) return saveMediaBuffer(Buffer.isBuffer(data) ? data : Buffer.from(data), contentType, "inbound", maxBytes, fileName);
|
|
2750
|
-
const save = (stream) => saveMediaStreamWithIdleTimeout(stream, contentType, maxBytes, fileName, FEISHU_MEDIA_HTTP_TIMEOUT_MS);
|
|
2751
|
-
if (typeof response.getReadableStream === "function") return save(response.getReadableStream());
|
|
2752
|
-
if (typeof response.writeFile === "function") return await withTempDownloadPath({ prefix: params.tmpDirPrefix }, async (tmpPath) => {
|
|
2753
|
-
await response.writeFile(tmpPath);
|
|
2754
|
-
if ((await fs.promises.stat(tmpPath)).size > maxBytes) throw mediaLimitError(maxBytes);
|
|
2755
|
-
return await save(fs.createReadStream(tmpPath));
|
|
2756
|
-
});
|
|
2757
|
-
if (responseWithOptionalFields[Symbol.asyncIterator]) return save(responseWithOptionalFields);
|
|
2758
|
-
if (response instanceof Readable) return save(response);
|
|
2759
|
-
const keys = Object.keys(response);
|
|
2760
|
-
throw new Error(`${params.errorPrefix}: unexpected response format. Keys: [${keys.join(", ")}]`);
|
|
2761
|
-
}
|
|
2762
2665
|
async function saveMessageResourceWithType(params) {
|
|
2763
2666
|
const response = await params.client.im.messageResource.get({
|
|
2764
2667
|
path: {
|
|
@@ -2767,29 +2670,25 @@ async function saveMessageResourceWithType(params) {
|
|
|
2767
2670
|
},
|
|
2768
2671
|
params: { type: params.type }
|
|
2769
2672
|
});
|
|
2770
|
-
const
|
|
2673
|
+
const headers = asHeaderMap(response.headers);
|
|
2674
|
+
const contentType = readHeaderValue(headers, "content-type");
|
|
2675
|
+
const disposition = readHeaderValue(headers, "content-disposition");
|
|
2676
|
+
const fileName = disposition ? decodeDispositionFileName(disposition) : void 0;
|
|
2771
2677
|
return {
|
|
2772
|
-
saved: await
|
|
2773
|
-
|
|
2774
|
-
|
|
2775
|
-
errorPrefix: "Feishu message resource download failed",
|
|
2776
|
-
maxBytes: params.maxBytes,
|
|
2777
|
-
contentType: meta.contentType,
|
|
2778
|
-
fileName: meta.fileName ?? (params.originalFilename ? recoverUtf8FileNameFromLatin1Header(params.originalFilename) : void 0)
|
|
2779
|
-
}),
|
|
2780
|
-
...meta
|
|
2678
|
+
saved: await saveMediaStreamWithIdleTimeout(response.getReadableStream(), contentType, params.maxBytes, fileName ?? (params.originalFilename ? recoverUtf8FileNameFromLatin1Header(params.originalFilename) : void 0), FEISHU_MEDIA_HTTP_TIMEOUT_MS),
|
|
2679
|
+
contentType,
|
|
2680
|
+
fileName
|
|
2781
2681
|
};
|
|
2782
2682
|
}
|
|
2783
2683
|
async function saveMessageResourceFeishu(params) {
|
|
2784
2684
|
const { cfg, messageId, fileKey, type, accountId, maxBytes, originalFilename } = params;
|
|
2785
2685
|
const normalizedFileKey = normalizeFeishuExternalKey(fileKey);
|
|
2786
2686
|
if (!normalizedFileKey) throw new Error("Feishu message resource download failed: invalid file_key");
|
|
2787
|
-
const { client } = createConfiguredFeishuMediaClient({
|
|
2788
|
-
cfg,
|
|
2789
|
-
accountId
|
|
2790
|
-
});
|
|
2791
2687
|
const request = {
|
|
2792
|
-
client
|
|
2688
|
+
client: createConfiguredFeishuMediaClient({
|
|
2689
|
+
cfg,
|
|
2690
|
+
accountId
|
|
2691
|
+
}),
|
|
2793
2692
|
messageId,
|
|
2794
2693
|
fileKey: normalizedFileKey,
|
|
2795
2694
|
type,
|
|
@@ -2810,20 +2709,6 @@ async function saveMessageResourceFeishu(params) {
|
|
|
2810
2709
|
}
|
|
2811
2710
|
}
|
|
2812
2711
|
}
|
|
2813
|
-
async function uploadImageFeishu(params) {
|
|
2814
|
-
const { cfg, image, accountId } = params;
|
|
2815
|
-
const { client } = createConfiguredFeishuMediaClient({
|
|
2816
|
-
cfg,
|
|
2817
|
-
accountId
|
|
2818
|
-
});
|
|
2819
|
-
return extractFeishuUploadKey(await requestFeishuApi(() => client.im.image.create({ data: {
|
|
2820
|
-
image_type: "message",
|
|
2821
|
-
image
|
|
2822
|
-
} }), "Feishu image upload failed", { includeNestedErrorLogId: true }), {
|
|
2823
|
-
key: "image_key",
|
|
2824
|
-
errorPrefix: "Feishu image upload failed"
|
|
2825
|
-
});
|
|
2826
|
-
}
|
|
2827
2712
|
/**
|
|
2828
2713
|
* Sanitize a filename for safe use in Feishu multipart/form-data uploads.
|
|
2829
2714
|
* Strips control characters and multipart-injection vectors (CWE-93) while
|
|
@@ -2837,39 +2722,13 @@ async function uploadImageFeishu(params) {
|
|
|
2837
2722
|
function sanitizeFileNameForUpload(fileName) {
|
|
2838
2723
|
return fileName.replace(/[\p{Cc}"\\]/gu, "_");
|
|
2839
2724
|
}
|
|
2840
|
-
async function uploadFileFeishu(params) {
|
|
2841
|
-
const { cfg, file, fileName, fileType, duration, accountId } = params;
|
|
2842
|
-
const { client } = createConfiguredFeishuMediaClient({
|
|
2843
|
-
cfg,
|
|
2844
|
-
accountId
|
|
2845
|
-
});
|
|
2846
|
-
const safeFileName = sanitizeFileNameForUpload(fileName);
|
|
2847
|
-
return extractFeishuUploadKey(await requestFeishuApi(() => client.im.file.create({ data: {
|
|
2848
|
-
file_type: fileType,
|
|
2849
|
-
file_name: safeFileName,
|
|
2850
|
-
file,
|
|
2851
|
-
...duration !== void 0 ? { duration } : {}
|
|
2852
|
-
} }), "Feishu file upload failed", { includeNestedErrorLogId: true }), {
|
|
2853
|
-
key: "file_key",
|
|
2854
|
-
errorPrefix: "Feishu file upload failed"
|
|
2855
|
-
});
|
|
2856
|
-
}
|
|
2857
2725
|
async function sendUploadedMediaFeishu(params, media, msgType) {
|
|
2858
|
-
const
|
|
2859
|
-
const content = JSON.stringify(media);
|
|
2726
|
+
const target = resolveFeishuSendTarget(params);
|
|
2860
2727
|
const label = msgType === "image" ? "image" : "file";
|
|
2861
|
-
return sendReplyOrFallbackDirect(
|
|
2862
|
-
|
|
2863
|
-
|
|
2864
|
-
allowTopLevelReplyFallback: params.allowTopLevelReplyFallback,
|
|
2865
|
-
content,
|
|
2728
|
+
return sendReplyOrFallbackDirect(target, {
|
|
2729
|
+
...params,
|
|
2730
|
+
content: JSON.stringify(media),
|
|
2866
2731
|
msgType,
|
|
2867
|
-
directParams: {
|
|
2868
|
-
receiveId,
|
|
2869
|
-
receiveIdType,
|
|
2870
|
-
content,
|
|
2871
|
-
msgType
|
|
2872
|
-
},
|
|
2873
2732
|
directErrorPrefix: `Feishu ${label} send failed`,
|
|
2874
2733
|
replyErrorPrefix: `Feishu ${label} reply failed`
|
|
2875
2734
|
});
|
|
@@ -2879,11 +2738,6 @@ function sendStickerFeishu(params) {
|
|
|
2879
2738
|
}
|
|
2880
2739
|
function detectFileType(fileName) {
|
|
2881
2740
|
switch (normalizeLowercaseStringOrEmpty(path.extname(fileName))) {
|
|
2882
|
-
case ".opus":
|
|
2883
|
-
case ".ogg": return "opus";
|
|
2884
|
-
case ".mp4":
|
|
2885
|
-
case ".mov":
|
|
2886
|
-
case ".avi": return "mp4";
|
|
2887
2741
|
case ".pdf": return "pdf";
|
|
2888
2742
|
case ".doc":
|
|
2889
2743
|
case ".docx": return "doc";
|
|
@@ -3098,28 +2952,33 @@ async function sendMediaFeishu(params) {
|
|
|
3098
2952
|
mediaMaxBytes,
|
|
3099
2953
|
msgType: routing.msgType
|
|
3100
2954
|
}));
|
|
3101
|
-
if (routing.msgType === "image") return {
|
|
3102
|
-
...await sendUploadedMediaFeishu(params, { image_key: await runBeforeFeishuMessageDispatch(() => uploadImageFeishu({
|
|
3103
|
-
cfg,
|
|
3104
|
-
image: buffer,
|
|
3105
|
-
accountId
|
|
3106
|
-
})) }, "image"),
|
|
3107
|
-
...voiceIntentDegradedToFile ? { voiceIntentDegradedToFile: true } : {}
|
|
3108
|
-
};
|
|
3109
2955
|
const durationMs = routing.msgType === "audio" || routing.msgType === "media" ? await probeMediaDurationMs({
|
|
3110
2956
|
buffer,
|
|
3111
2957
|
fileName: name,
|
|
3112
2958
|
contentType
|
|
3113
2959
|
}) : void 0;
|
|
3114
2960
|
return {
|
|
3115
|
-
...await sendUploadedMediaFeishu(params,
|
|
3116
|
-
|
|
3117
|
-
|
|
3118
|
-
|
|
3119
|
-
|
|
3120
|
-
|
|
3121
|
-
|
|
3122
|
-
|
|
2961
|
+
...await sendUploadedMediaFeishu(params, await runBeforeFeishuMessageDispatch(async () => {
|
|
2962
|
+
const client = createConfiguredFeishuMediaClient({
|
|
2963
|
+
cfg,
|
|
2964
|
+
accountId
|
|
2965
|
+
});
|
|
2966
|
+
const isImage = routing.msgType === "image";
|
|
2967
|
+
const errorPrefix = `Feishu ${isImage ? "image" : "file"} upload failed`;
|
|
2968
|
+
const key = extractFeishuUploadKey(await requestFeishuApi(() => isImage ? client.im.image.create({ data: {
|
|
2969
|
+
image_type: "message",
|
|
2970
|
+
image: buffer
|
|
2971
|
+
} }) : client.im.file.create({ data: {
|
|
2972
|
+
file_type: routing.fileType ?? "stream",
|
|
2973
|
+
file_name: sanitizeFileNameForUpload(name),
|
|
2974
|
+
file: buffer,
|
|
2975
|
+
...durationMs !== void 0 ? { duration: durationMs } : {}
|
|
2976
|
+
} }), errorPrefix, { includeNestedErrorLogId: true }), {
|
|
2977
|
+
key: isImage ? "image_key" : "file_key",
|
|
2978
|
+
errorPrefix
|
|
2979
|
+
});
|
|
2980
|
+
return isImage ? { image_key: key } : { file_key: key };
|
|
2981
|
+
}), routing.msgType),
|
|
3123
2982
|
...voiceIntentDegradedToFile ? { voiceIntentDegradedToFile: true } : {}
|
|
3124
2983
|
};
|
|
3125
2984
|
}
|
|
@@ -3236,11 +3095,6 @@ function renderFeishuPresentationFallbackText(params, textFormat = "plain") {
|
|
|
3236
3095
|
}
|
|
3237
3096
|
});
|
|
3238
3097
|
}
|
|
3239
|
-
function mapFeishuButtonType(style) {
|
|
3240
|
-
if (style === "primary" || style === "success") return "primary";
|
|
3241
|
-
if (style === "danger") return "danger";
|
|
3242
|
-
return "default";
|
|
3243
|
-
}
|
|
3244
3098
|
function buildFeishuPayloadButton(button) {
|
|
3245
3099
|
const url = resolveSafeFeishuButtonUrl(resolveFeishuButtonUrl(button));
|
|
3246
3100
|
const value = resolveFeishuCommandButtonValue(button);
|
|
@@ -3267,7 +3121,7 @@ function buildFeishuPayloadButton(button) {
|
|
|
3267
3121
|
tag: "plain_text",
|
|
3268
3122
|
content: button.label
|
|
3269
3123
|
},
|
|
3270
|
-
type:
|
|
3124
|
+
type: resolveFeishuButtonType(button.style),
|
|
3271
3125
|
behaviors
|
|
3272
3126
|
};
|
|
3273
3127
|
}
|
|
@@ -3487,4 +3341,4 @@ function createFeishuPartialReplyDeliveryError(cause, result) {
|
|
|
3487
3341
|
});
|
|
3488
3342
|
}
|
|
3489
3343
|
//#endregion
|
|
3490
|
-
export { cleanupAmbientCommentTypingReaction as $, sendMessageFeishu as A,
|
|
3344
|
+
export { cleanupAmbientCommentTypingReaction as $, sendMessageFeishu as A, resolveFeishuGroupSenderActivationIngressAccess as At, parsePostContent as B, sendStickerFeishu as C, readFeishuChatInfoWithAuthorization as Ct, getMessageFeishu as D, resolveFeishuDmIngressAccess as Dt, editMessageFeishu as E, normalizeFeishuAllowEntry as Et, isFeishuBroadcastMention as F, FEISHU_CARD_INTERACTION_VERSION as Ft, deliverCommentThreadText as G, buildFeishuMediaFallbackText as H, isMentionForwardRequest as I, createFeishuCardInteractionEnvelope as It, feishuExternalToolResult as J, registerFeishuDriveTools as K, isFeishuGroupChatType as L, decodeFeishuCardAction as Lt, toFeishuMessageSendResult as M, resolveFeishuReplyPolicy as Mt, formatFeishuMediaContent as N, normalizeFeishuChatType as Nt, listFeishuThreadMessages as O, resolveFeishuGroupConfig as Ot, extractMentionTargets as P, resolveFeishuChatType as Pt, assertFeishuApiSuccess as Q, normalizeFeishuEventChatType as R, sendMediaFeishu as S, isFeishuGroupReadEnabled as St, chunkFeishuCardMarkdown as T, hasExplicitFeishuGroupConfig as Tt, resolveFeishuIdentityEmoji as U, createConfiguredFeishuClient as V, resolveFeishuIdentityHeaderTitle as W, createFeishuToolClient as X, unknownToolActionResult as Y, resolveFeishuToolAccount as Z, renderFeishuPresentationPayload as _, assertFeishuChatReadAllowed as _t, shouldSendNoVisibleReplyFallback as a, requestFeishuApi as at, withinCardTableLimit as b, canEnumerateAllFeishuPeers as bt, buildFeishuPayloadCard as c, parseFeishuCommentTarget as ct, consumeFeishuPresentationFallbackMarker as d, chunkFeishuMarkdown as dt, createCommentTypingReactionLifecycle as et, feishuCardWithinTableLimit as f, chunkFeishuPostMarkdown as ft, renderFeishuPresentationFallbackText as g, visitFeishuMarkdown as gt, readNativeFeishuCard as h, shouldUseFeishuCard as ht, noVisibleFeishuReplyDelivery as i, parseCommentContentElements as it, sendStructuredCardFeishu as j, resolveFeishuGroupToolPolicy as jt, sendCardFeishu as k, resolveFeishuGroupConversationIngressAccess as kt, buildFeishuPresentationCard as l, readNativeFeishuCardJson as lt, markRenderedFeishuCard as m, parseFeishuMarkdown as mt, createFeishuReplyDeliveryResult as n, extractReplyText as nt, FEISHU_PRESENTATION_CAPABILITIES as o, buildFeishuCommentTarget as ot, isFeishuCardWithinEnvelope as p, materializeFeishuPostMarkdownSoftBreaks as pt, registerFeishuTool as q, mergeFeishuReplyDeliveryResults as r, formatFeishuApiError as rt, assertFeishuCardWithinEnvelope as s, normalizeCommentFileType as st, createFeishuPartialReplyDeliveryError as t, encodeQuery as tt, buildFeishuPresentationFallback as u, resolveFeishuCardTemplate as ut, renderFeishuReplyPayload as v, authorizeFeishuChatMemberRead as vt, shouldSuppressFeishuTextForVoiceMedia as w, resolveFeishuChatReadPreliminaryAuthorization as wt, saveMessageResourceFeishu as x, isFeishuGroupReadAllowed as xt, resolveFeishuRichReply as y, canEnumerateAllFeishuGroups as yt, parseInteractiveCardContent as z };
|