silentlake 2026.3.24
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/CHANGELOG.md +4587 -0
- package/LICENSE +21 -0
- package/README.md +248 -0
- package/assets/avatar-placeholder.svg +19 -0
- package/assets/chrome-extension/icons/icon128.png +0 -0
- package/assets/chrome-extension/icons/icon16.png +0 -0
- package/assets/chrome-extension/icons/icon32.png +0 -0
- package/assets/chrome-extension/icons/icon48.png +0 -0
- package/assets/dmg-background-small.png +0 -0
- package/assets/dmg-background.png +0 -0
- package/assets/silentlake-banner.png +0 -0
- package/dist/APEv2Parser-BZv_dP9t.js +269 -0
- package/dist/APEv2Parser-CPzxFNBB.js +5 -0
- package/dist/AbstractID3Parser-mvDFcjYV.js +47 -0
- package/dist/AiffParser-BXQ9SRZk.js +145 -0
- package/dist/AsfParser-CmBDUlZE.js +631 -0
- package/dist/BasicParser-DhmXREDo.js +853 -0
- package/dist/DsdiffParser-CTKKGyZg.js +150 -0
- package/dist/DsfParser-Ds-YQe4Z.js +101 -0
- package/dist/FlacParser-B1XVPgXF.js +5 -0
- package/dist/FlacParser-DMPyL1y4.js +367 -0
- package/dist/ID3v1Parser-BICWWVDG.js +289 -0
- package/dist/ID3v2Parser-BmZHSUqs.js +650 -0
- package/dist/ID3v2Token-DeJf4tYQ.js +145 -0
- package/dist/MP4Parser-Cjf-Zs8T.js +1061 -0
- package/dist/MatroskaParser-DgBzBe8t.js +909 -0
- package/dist/MpegParser-D5swTpA1.js +744 -0
- package/dist/MusepackParser-D8EQXnpK.js +285 -0
- package/dist/OggParser-BcIYPHwP.js +390 -0
- package/dist/Util-D_zGsr97.js +170 -0
- package/dist/WavPackParser-hosU8gfo.js +166 -0
- package/dist/WaveParser-CA00FZrC.js +273 -0
- package/dist/abort-cutoff-CERmtgZI.js +56 -0
- package/dist/abort-cutoff.runtime-DZkGKKzv.js +61 -0
- package/dist/abort-signal-CsrBEr94.js +13 -0
- package/dist/account-helpers-D3c_eI7c.js +37 -0
- package/dist/account-helpers-ru3jdZSV.js +12 -0
- package/dist/account-id-DZnNZg8x.js +1 -0
- package/dist/account-id-ZCrgXl7Z.js +44 -0
- package/dist/account-lookup-nkoa-foB.js +10 -0
- package/dist/account-snapshot-fields-Cvq7803C.js +116 -0
- package/dist/account-summary-B5Xzvntm.js +36 -0
- package/dist/accounts-43SvCDEA.js +212 -0
- package/dist/accounts-CYgFhv2o.js +105 -0
- package/dist/accounts-ChlyF7cx.js +112 -0
- package/dist/ack-reactions-CNVwfOBj.js +43 -0
- package/dist/acp-cli-B4Rv7-xU.js +2033 -0
- package/dist/acp-runtime-BdLdT-QY.js +1 -0
- package/dist/actions.runtime-CqnQssoB.js +217 -0
- package/dist/actions.runtime-FLmCvVRd.js +236 -0
- package/dist/agent-CBOdzEvR.js +1 -0
- package/dist/agent-scope-BLhzf-o0.js +17 -0
- package/dist/agent-scope-DPP4Z_UU.js +193 -0
- package/dist/agents-D8pBK0II.js +855 -0
- package/dist/agents-Dihz1Ihx.js +323 -0
- package/dist/agents.config-C_lrnc9J.js +18 -0
- package/dist/agents.config-D1VqC78r.js +121 -0
- package/dist/allow-from-BPSBITdd.js +9 -0
- package/dist/allow-from-BwTLpvhp.js +20 -0
- package/dist/allow-from-C4iBpqFI.js +62 -0
- package/dist/allowlist-config-edit-CKbnMmwS.js +279 -0
- package/dist/allowlist-match-CYmPgg1K.js +63 -0
- package/dist/ansi-BEJF8NKS.js +54 -0
- package/dist/anthropic-vertex-provider-Dd5agCN9.js +60 -0
- package/dist/apply.runtime-DhKxNSJE.js +370 -0
- package/dist/apply.runtime-ghlh-P6X.js +211 -0
- package/dist/archive-Tr0wIUO-.js +532 -0
- package/dist/arg-split-Dtda0YDl.js +38 -0
- package/dist/artifacts-C_4LekPC.js +39 -0
- package/dist/audit-BOPSQQtd.js +54 -0
- package/dist/audit-C5kdrCi_.js +788 -0
- package/dist/audit-channel.allow-from.runtime-B7BHNblL.js +17 -0
- package/dist/audit-channel.collect.runtime-CjAbXFBV.js +521 -0
- package/dist/audit-channel.discord.runtime-BBY6S9lg.js +5 -0
- package/dist/audit-channel.telegram.runtime-SJnxOJH2.js +8 -0
- package/dist/audit-channel.zalouser.runtime-SGRWvHxT.js +5 -0
- package/dist/audit-extra.async-DY8v7LXH.js +817 -0
- package/dist/audit-fs-oDMUa5N_.js +375 -0
- package/dist/audit-membership-runtime-BPjFryEx.js +261 -0
- package/dist/audit.deep.runtime-WFf-TpsD.js +31 -0
- package/dist/audit.nondeep.runtime-B4BaEaRU.js +842 -0
- package/dist/audit.runtime-rFjCrods.js +74 -0
- package/dist/auth-O6LQFLHJ.js +416 -0
- package/dist/auth-choice-DIBaxmAQ.js +219 -0
- package/dist/auth-choice-PrbpIjyg.js +610 -0
- package/dist/auth-choice-legacy-Clyw2lVc.js +17 -0
- package/dist/auth-choice-options-ohUw8QR-.js +127 -0
- package/dist/auth-choice-prompt-Cm0s-9Du.js +215 -0
- package/dist/auth-choice-prompt-DI-Xl1Nv.js +36 -0
- package/dist/auth-choice-rKBOd02a.js +64 -0
- package/dist/auth-choice.apply-helpers-BibBSEl9.js +66 -0
- package/dist/auth-choice.plugin-providers.runtime-gqF9NO7_.js +219 -0
- package/dist/auth-health-TWboMYA5.js +166 -0
- package/dist/auth-mode-policy-DywddkT-.js +18 -0
- package/dist/auth-profiles-CWEIQV77.js +1047 -0
- package/dist/auth-profiles.runtime-B98lwopF.js +48 -0
- package/dist/avatar-policy-Ds9e6uHI.js +67 -0
- package/dist/axios-xDDnM0KG.js +12831 -0
- package/dist/backup-create-B6JAR6jJ.js +461 -0
- package/dist/banner-bez5CpOK.js +351 -0
- package/dist/base-session-key-Cf2rkwag.js +14 -0
- package/dist/bindings-BV4AtNSY.js +21 -0
- package/dist/bindings-kjwuC11Q.js +69 -0
- package/dist/bluebubbles-C1M3Geg0.js +87 -0
- package/dist/bluebubbles-DRW3JdOY.js +603 -0
- package/dist/bluebubbles-dEl4QpYz.js +37 -0
- package/dist/bonjour-discovery-C2oY96BG.js +376 -0
- package/dist/boolean-DKtCJu_W.js +29 -0
- package/dist/boolean-param-xAGXUSSN.js +13 -0
- package/dist/boundary-file-read-BP6VMpqH.js +106 -0
- package/dist/boundary-path-B3FFLYNx.js +557 -0
- package/dist/brave-CkimJe4j.js +405 -0
- package/dist/brew-DSwWqzLd.js +44 -0
- package/dist/browser-cli-D3kBUBNc.js +1502 -0
- package/dist/bundled/boot-md/handler.js +381 -0
- package/dist/bundled/bootstrap-extra-files/handler.js +56 -0
- package/dist/bundled/command-logger/handler.js +62 -0
- package/dist/bundled/session-memory/handler.js +401 -0
- package/dist/call-BDvaXe4i.js +44 -0
- package/dist/call-BmLt3xO1.js +639 -0
- package/dist/catalog-BwAYUfL7.js +240 -0
- package/dist/channel-BBCuV5OT.js +4945 -0
- package/dist/channel-BDBXuqeg.js +321 -0
- package/dist/channel-C8h1Irxm.js +1284 -0
- package/dist/channel-CbGpFzo4.js +1602 -0
- package/dist/channel-Ci3K8fI9.js +1006 -0
- package/dist/channel-DGT5N1v7.js +1077 -0
- package/dist/channel-account-context-Bwa-YH_o.js +104 -0
- package/dist/channel-actions-DU2CR3xW.js +37 -0
- package/dist/channel-activity-B8aReQoE.js +35 -0
- package/dist/channel-config-3Uv6ve2_.js +115 -0
- package/dist/channel-config-helpers-CieQWILI.js +377 -0
- package/dist/channel-config-schema-DEVsCZpj.js +1 -0
- package/dist/channel-feedback-G6zh8efr.js +245 -0
- package/dist/channel-inbound-DwzVf2PK.js +395 -0
- package/dist/channel-lifecycle-CpU1dRbh.js +354 -0
- package/dist/channel-options-DJaIP4Dv.js +38 -0
- package/dist/channel-pairing-D54mn51y.js +66 -0
- package/dist/channel-plugin-common-BhTxCE5t.js +1 -0
- package/dist/channel-plugin-ids-CFeS3qir.js +26 -0
- package/dist/channel-plugin-resolution-DUngfdFj.js +112 -0
- package/dist/channel-policy-C4GKHvhz.js +1 -0
- package/dist/channel-reply-pipeline-CPTuaW8n.js +15 -0
- package/dist/channel-send-result-By8EpCPw.js +40 -0
- package/dist/channel-setup-Ck35g7zI.js +49 -0
- package/dist/channel-shared-LkXtTPXk.js +308 -0
- package/dist/channel-summary-CdYLGMVt.js +137 -0
- package/dist/channel-summary-D33z52ft.js +41 -0
- package/dist/channel-targets-DfnKGXez.js +87 -0
- package/dist/channel.runtime-DAyBR2A5.js +324 -0
- package/dist/channel.runtime-DVq5tC2D.js +35 -0
- package/dist/channel.runtime-DaLTDGtF.js +288 -0
- package/dist/channel.runtime-FKfTev2g.js +512 -0
- package/dist/channel.runtime-owqedh1t.js +268 -0
- package/dist/channel.runtime-wOTeiifp.js +230 -0
- package/dist/channels-CIHgkPea.js +408 -0
- package/dist/channels-ZXK6Jiuk.js +1393 -0
- package/dist/channels-cli-Bj6qSlkE.js +412 -0
- package/dist/channels-status-issues-C_U44M8Y.js +16 -0
- package/dist/chat-type-C-n03mQY.js +10 -0
- package/dist/clack-prompter-DuzDnaLi.js +112 -0
- package/dist/clawbot-cli-YNPuwmTB.js +218 -0
- package/dist/cli/daemon-cli.js +88 -0
- package/dist/cli-CW46WAZn.js +254 -0
- package/dist/cli-name-Daok7A7-.js +25 -0
- package/dist/cli-runtime-aAVwbEYy.js +7 -0
- package/dist/cli-utils-Np4NAAtt.js +39 -0
- package/dist/command-format-CYK9XiUC.js +16 -0
- package/dist/command-format-g8YUHNir.js +2 -0
- package/dist/command-gating-BQXGSqc9.js +40 -0
- package/dist/command-options-5coRiipK.js +25 -0
- package/dist/command-poll-backoff-CpkSns-6.js +56 -0
- package/dist/command-poll-backoff.runtime-YT6EGcLN.js +7 -0
- package/dist/command-registry-BI2MOs89.js +242 -0
- package/dist/command-registry-BMsxnuoC.js +14 -0
- package/dist/command-secret-gateway-ChXyZwos.js +211 -0
- package/dist/command-secret-targets-COcwhn-D.js +88 -0
- package/dist/command-secret-targets-CQJT3viO.js +3 -0
- package/dist/commands-Bb9xUwz9.js +42 -0
- package/dist/commands-core-C1usZXC2.js +4923 -0
- package/dist/commands-core.runtime-OTZivlO2.js +232 -0
- package/dist/commands-registry-ChCep1KJ.js +295 -0
- package/dist/commands-registry.data-XyUTELK9.js +904 -0
- package/dist/commands-registry.runtime-m5WTxFtv.js +25 -0
- package/dist/commands-status.runtime-C8_hpNgj.js +211 -0
- package/dist/commands.runtime-BZPnQKcW.js +232 -0
- package/dist/common-CUBlLRXB.js +457 -0
- package/dist/compact.runtime-Djmzpbn6.js +216 -0
- package/dist/completion-cli-D8tLgE5W.js +445 -0
- package/dist/completion-cli-Dz89naVA.js +17 -0
- package/dist/config-6sZwvXJD.js +88 -0
- package/dist/config-B7tPwoHZ.js +38 -0
- package/dist/config-DdDLrP_v.js +273 -0
- package/dist/config-cli-C10R8azD.js +945 -0
- package/dist/config-guard-B1c73BYQ.js +126 -0
- package/dist/config-helpers-3u5wfLBu.js +117 -0
- package/dist/config-pn7LKJdW.js +23 -0
- package/dist/config-presence-BmUF_5K9.js +79 -0
- package/dist/config-regex-CvZFnWkO.js +39 -0
- package/dist/config-runtime-CstET7fq.js +142 -0
- package/dist/config-schema-5YkIW1xw.js +270 -0
- package/dist/config-schema-B1UGMwZ8.js +31 -0
- package/dist/config-schema-DzlnsY3D.js +33 -0
- package/dist/config-state-CE0CGjey.js +288 -0
- package/dist/config-validation-CkVqgkHr.js +272 -0
- package/dist/config-value-DgJrpclm.js +25 -0
- package/dist/configure-DMkp7Sr4.js +1126 -0
- package/dist/configure-DOrQthLy.js +344 -0
- package/dist/connection-auth-BSQJeDOU.js +30 -0
- package/dist/constants-C_Scc680.js +71 -0
- package/dist/control-ui-assets-DjqeIg6A.js +232 -0
- package/dist/control-ui-shared-DP000Pxd.js +29 -0
- package/dist/conversation-runtime-1O0Aaolb.js +1458 -0
- package/dist/core-C7aHA4Aq.js +187 -0
- package/dist/core-command-descriptors-DCUYAEZd.js +96 -0
- package/dist/credentials-BPwBlm1X.js +265 -0
- package/dist/cron-cli-N2Hw_02d.js +579 -0
- package/dist/daemon-cli-DgfaF9xx.js +354 -0
- package/dist/daemon-install-CbclJo5M.js +134 -0
- package/dist/daemon-install-plan.shared-DK6BHlWI.js +222 -0
- package/dist/daemon-runtime-CbClrCwc.js +12 -0
- package/dist/dangerous-config-flags-BJtLWIk7.js +15 -0
- package/dist/dangerous-name-matching-DZa_t0RM.js +44 -0
- package/dist/dangerous-tools-yGPDFTHh.js +27 -0
- package/dist/date-time-DCAyaBop.js +118 -0
- package/dist/dedupe-Cgnk5BbX.js +55 -0
- package/dist/defaults-CEdZhIIb.js +6 -0
- package/dist/delegate-D4ql5N70.js +43 -0
- package/dist/deliver-B004w1Mv.js +212 -0
- package/dist/deliver-runtime-IYvc0giI.js +211 -0
- package/dist/delivery-queue-B19wDCjT.js +3 -0
- package/dist/delivery-queue-DrrqB4Hi.js +299 -0
- package/dist/device-auth-GEXe9vqR.js +15 -0
- package/dist/device-bootstrap-CwwokLEY.js +96 -0
- package/dist/device-bootstrap-Dbhe6oe8.js +1 -0
- package/dist/device-metadata-normalization-BDSQ_eA7.js +21 -0
- package/dist/device-pairing-cFWbBray.js +553 -0
- package/dist/devices-cli-DzycjFzS.js +366 -0
- package/dist/diagnostic-DqJXx_4Q.js +310 -0
- package/dist/diagnostic-events-ktCoG8Br.js +48 -0
- package/dist/diagnostics-CMhyGsPu.js +33 -0
- package/dist/diagnostics-DpLHpQ9c.js +14 -0
- package/dist/directive-handling.fast-lane-toP_ri_H.js +273 -0
- package/dist/directive-handling.impl-BRARyrsT.js +638 -0
- package/dist/directive-handling.impl-CUB4MOnK.js +214 -0
- package/dist/directive-handling.levels-8vnMeuGX.js +2 -0
- package/dist/directive-handling.levels-CoruY1AA.js +13 -0
- package/dist/directive-handling.persist.runtime-78Du6PgL.js +170 -0
- package/dist/directive-handling.shared-DCGUCHjn.js +147 -0
- package/dist/directory-cli-DVsDcgIU.js +437 -0
- package/dist/directory-config-helpers-CURJ8mj7.js +129 -0
- package/dist/directory-runtime-DhC8QkMq.js +19 -0
- package/dist/directory.static-DQaG9ohH.js +44 -0
- package/dist/discord-CYj8s73O.js +214 -0
- package/dist/discord-L9zvSHVn.js +635 -0
- package/dist/discord-core-5tkl-BzP.js +1 -0
- package/dist/dm-policy-shared-6bCJzHOS.js +188 -0
- package/dist/dns-cli-BMvHy265.js +223 -0
- package/dist/docker-XFNiArwM.js +1254 -0
- package/dist/docs-cli-BTaH94wD.js +176 -0
- package/dist/doctor-completion-DKx5m2UC.js +90 -0
- package/dist/doctor-config-preflight-BzQgc3_t.js +40 -0
- package/dist/doctor-config-preflight-DxVCut8L.js +150 -0
- package/dist/doctor-state-migrations-CTF66iAy.js +732 -0
- package/dist/doctor-state-migrations-D0VP4dUh.js +212 -0
- package/dist/entry-status-B2OWAf0s.js +172 -0
- package/dist/entry.js +210 -0
- package/dist/env-BP70DGuy.js +30 -0
- package/dist/env-overrides-JneV60sd.js +434 -0
- package/dist/env-overrides.runtime-DLrwions.js +18 -0
- package/dist/env-substitution-D6t_sLS_.js +136 -0
- package/dist/errors-BxyFnvP3.js +58 -0
- package/dist/exec-Dmex2w_d.js +310 -0
- package/dist/exec-approvals-BJhuySBz.js +386 -0
- package/dist/exec-approvals-allowlist-B_wPddCb.js +384 -0
- package/dist/exec-approvals-cli-C2dwhSkX.js +427 -0
- package/dist/exec-safe-bin-runtime-policy-BZkObC8r.js +89 -0
- package/dist/exec-safety-CaaBy-Zw.js +24 -0
- package/dist/extension-shared-5txN7IXK.js +74 -0
- package/dist/extensionAPI.js +218 -0
- package/dist/extensions/amazon-bedrock/index.js +231 -0
- package/dist/extensions/anthropic/index.js +330 -0
- package/dist/extensions/bluebubbles/index.js +224 -0
- package/dist/extensions/bluebubbles/setup-entry.js +289 -0
- package/dist/extensions/brave/index.js +23 -0
- package/dist/extensions/byteplus/index.js +112 -0
- package/dist/extensions/chutes/index.js +221 -0
- package/dist/extensions/cloudflare-ai-gateway/index.js +218 -0
- package/dist/extensions/copilot-proxy/index.js +125 -0
- package/dist/extensions/device-pair/index.js +1040 -0
- package/dist/extensions/discord/index.js +215 -0
- package/dist/extensions/discord/setup-entry.js +215 -0
- package/dist/extensions/elevenlabs/index.js +223 -0
- package/dist/extensions/fal/index.js +112 -0
- package/dist/extensions/feishu/index.js +227 -0
- package/dist/extensions/feishu/setup-entry.js +112 -0
- package/dist/extensions/firecrawl/index.js +211 -0
- package/dist/extensions/github-copilot/index.js +490 -0
- package/dist/extensions/google/index.js +211 -0
- package/dist/extensions/huggingface/index.js +108 -0
- package/dist/extensions/imessage/index.js +223 -0
- package/dist/extensions/imessage/setup-entry.js +220 -0
- package/dist/extensions/irc/index.js +220 -0
- package/dist/extensions/irc/setup-entry.js +222 -0
- package/dist/extensions/kilocode/index.js +282 -0
- package/dist/extensions/kimi-coding/index.js +148 -0
- package/dist/extensions/line/index.js +57 -0
- package/dist/extensions/line/setup-entry.js +49 -0
- package/dist/extensions/llm-task/index.js +157 -0
- package/dist/extensions/lobster/index.js +261 -0
- package/dist/extensions/mattermost/index.js +220 -0
- package/dist/extensions/mattermost/setup-entry.js +222 -0
- package/dist/extensions/memory-core/index.js +36 -0
- package/dist/extensions/microsoft/index.js +223 -0
- package/dist/extensions/minimax/index.js +437 -0
- package/dist/extensions/mistral/index.js +149 -0
- package/dist/extensions/modelstudio/index.js +144 -0
- package/dist/extensions/moonshot/index.js +211 -0
- package/dist/extensions/nextcloud-talk/index.js +221 -0
- package/dist/extensions/nextcloud-talk/setup-entry.js +223 -0
- package/dist/extensions/nvidia/index.js +29 -0
- package/dist/extensions/ollama/index.js +118 -0
- package/dist/extensions/open-prose/index.js +10 -0
- package/dist/extensions/openai/index.js +677 -0
- package/dist/extensions/opencode/index.js +116 -0
- package/dist/extensions/opencode-go/index.js +114 -0
- package/dist/extensions/openrouter/index.js +398 -0
- package/dist/extensions/openshell/index.js +923 -0
- package/dist/extensions/perplexity/index.js +23 -0
- package/dist/extensions/phone-control/index.js +276 -0
- package/dist/extensions/qianfan/index.js +114 -0
- package/dist/extensions/qwen-portal-auth/index.js +350 -0
- package/dist/extensions/sglang/index.js +285 -0
- package/dist/extensions/signal/index.js +218 -0
- package/dist/extensions/signal/setup-entry.js +218 -0
- package/dist/extensions/slack/index.js +222 -0
- package/dist/extensions/slack/setup-entry.js +220 -0
- package/dist/extensions/synology-chat/index.js +56 -0
- package/dist/extensions/synology-chat/setup-entry.js +58 -0
- package/dist/extensions/synthetic/index.js +112 -0
- package/dist/extensions/talk-voice/index.js +197 -0
- package/dist/extensions/tavily/index.js +211 -0
- package/dist/extensions/telegram/index.js +221 -0
- package/dist/extensions/telegram/setup-entry.js +221 -0
- package/dist/extensions/thread-ownership/index.js +70 -0
- package/dist/extensions/together/index.js +113 -0
- package/dist/extensions/venice/index.js +132 -0
- package/dist/extensions/vercel-ai-gateway/index.js +86 -0
- package/dist/extensions/vllm/index.js +285 -0
- package/dist/extensions/voice-call/index.js +5715 -0
- package/dist/extensions/volcengine/index.js +112 -0
- package/dist/extensions/xai/index.js +211 -0
- package/dist/extensions/xiaomi/index.js +115 -0
- package/dist/extensions/zai/index.js +559 -0
- package/dist/extensions/zalo/index.js +225 -0
- package/dist/extensions/zalo/setup-entry.js +226 -0
- package/dist/external-content-BUdUOqkv.js +238 -0
- package/dist/feishu-CgbwAF0e.js +2664 -0
- package/dist/feishu-Dh5fEbh5.js +59127 -0
- package/dist/fetch-guard-DIyN1HW5.js +165 -0
- package/dist/fetch-timeout-C5xpMuGd.js +36 -0
- package/dist/file-identity-Cw0fQxYY.js +11 -0
- package/dist/file-lock-WbEmczmY.js +107 -0
- package/dist/filter-oMGaNOM1.js +20 -0
- package/dist/format-DH8ysi7s.js +19 -0
- package/dist/format-datetime-BGS6tLDE.js +73 -0
- package/dist/format-duration-CO0BGWB0.js +57 -0
- package/dist/format-relative-C3nDxnXz.js +54 -0
- package/dist/frontmatter-S5vS-I4a.js +309 -0
- package/dist/fs-safe-D3qzH-ab.js +731 -0
- package/dist/gateway-cli-PQNp7o0j.js +28378 -0
- package/dist/gateway-install-token-DV5KjD4F.js +164 -0
- package/dist/gateway-rpc-C0Ey-rik.js +26 -0
- package/dist/gateway-runtime-ih2e7a2K.js +42 -0
- package/dist/gaxios-fetch-compat-KX6bsqFm.js +165 -0
- package/dist/gemini-auth-B5ljg7jr.js +29 -0
- package/dist/git-commit-BIdLubm5.js +2 -0
- package/dist/git-commit-OvUvjri2.js +177 -0
- package/dist/github-copilot-auth-Ccm-cBwy.js +104 -0
- package/dist/global-singleton-4KwY5RvX.js +13 -0
- package/dist/globals-41sdSaKv.js +38 -0
- package/dist/gmail-setup-utils-BX68dZla.js +419 -0
- package/dist/group-access-DJZrYPx1.js +113 -0
- package/dist/group-keys-BD_IYSMs.js +44 -0
- package/dist/group-policy-CWFxv3iB.js +201 -0
- package/dist/group-policy-warnings-Ddu6lBkh.js +175 -0
- package/dist/health-Bu1sbyYy.js +573 -0
- package/dist/health-Cbxc9Bn3.js +59 -0
- package/dist/health-format-B5XfOTuJ.js +26 -0
- package/dist/heartbeat-7aHh0m3d.js +169 -0
- package/dist/heartbeat-summary-Das49TYq.js +57 -0
- package/dist/help-CcbF7-ha.js +81 -0
- package/dist/help-format-Dv45FpYu.js +15 -0
- package/dist/helpers-DJ-5HEbE.js +24 -0
- package/dist/helpers-MxyaLZUk.js +32 -0
- package/dist/history-CHjo8B5W.js +102 -0
- package/dist/hook-runtime-BnNBi_q4.js +1 -0
- package/dist/hooks-cli-DUYK4RM1.js +1102 -0
- package/dist/hooks-policy-BL6HDLUn.js +20 -0
- package/dist/hooks-status-gzNmo3li.js +78 -0
- package/dist/host-env-security-BogNN146.js +223 -0
- package/dist/http-body-CCiSfloA.js +237 -0
- package/dist/http-registry-WFFbLYRd.js +153 -0
- package/dist/identity-DovQV4zD.js +112 -0
- package/dist/identity-cyBYcoXS.js +84 -0
- package/dist/identity-file-EndG1nfc.js +60 -0
- package/dist/image-generation-CNKc-mFK.js +441 -0
- package/dist/image-kJ7Tbov4.js +211 -0
- package/dist/image-ops-j01UkxEv.js +371 -0
- package/dist/imessage-B5pSMT47.js +219 -0
- package/dist/imessage-CoIuY1Ro.js +1451 -0
- package/dist/imessage-Cqjsq4VW.js +190 -0
- package/dist/imessage-core-CsYJuaRZ.js +1 -0
- package/dist/inbound-envelope-4P3IIJc3.js +61 -0
- package/dist/inbound-reply-dispatch-i2Vekqyy.js +72 -0
- package/dist/includes-7XyL3p1c.js +188 -0
- package/dist/includes-scan-y-rS6tTw.js +55 -0
- package/dist/index.js +57 -0
- package/dist/infra/warning-filter.js +2 -0
- package/dist/inspect-CcxlJ1ba.js +279 -0
- package/dist/install-safe-path-Rwbw1XCZ.js +62 -0
- package/dist/installs-iHi2aSjM.js +532 -0
- package/dist/interactive-F7iY0yED.js +8 -0
- package/dist/interactive-runtime-OweOj_Vv.js +90 -0
- package/dist/internal-hooks-0uipqzRY.js +156 -0
- package/dist/io-BX49DsSJ.js +35 -0
- package/dist/io-jOnQRia2.js +7178 -0
- package/dist/ip-C8vmzVu0.js +203 -0
- package/dist/ipv4-DAmsJVOV.js +82 -0
- package/dist/irc-AZ-Ec8be.js +12 -0
- package/dist/irc-CCSRuEC2.js +660 -0
- package/dist/is-main-YViS6wOn.js +27 -0
- package/dist/issue-format-CBEXVico.js +31 -0
- package/dist/issue-format-D3HehoKZ.js +4 -0
- package/dist/json-file-C2zjA0Gv.js +23 -0
- package/dist/json-files-WW-H_psG.js +60 -0
- package/dist/json-pointer-f9dEnBoR.js +43 -0
- package/dist/json-store-O1LwpnBH.js +37 -0
- package/dist/kb-cli-DMZs6PCu.js +65 -0
- package/dist/keyed-async-queue-CPUWV5Pm.js +32 -0
- package/dist/kill-tree-CbjXBw3z.js +149 -0
- package/dist/kilocode-shared-DS7_0IMs.js +29 -0
- package/dist/launchd-tyqGVx9U.js +491 -0
- package/dist/lazy-runtime-BcXbyAaC.js +1 -0
- package/dist/lazy-runtime-bWkd2cs3.js +29 -0
- package/dist/legacy-names-CUNZ4vHN.js +7 -0
- package/dist/legacy-web-search-BgZjNG2h.js +222 -0
- package/dist/lib-CERS7N4b.js +503 -0
- package/dist/lib-PPICrHv1.js +1938 -0
- package/dist/library-CZ461krl.js +211 -0
- package/dist/lifecycle-core-Dnxnw0oy.js +382 -0
- package/dist/line/accounts.js +10 -0
- package/dist/line/send.js +39 -0
- package/dist/line/template-messages.js +2 -0
- package/dist/line-CJSvwApm.js +1 -0
- package/dist/line-N9vL-2JB.js +688 -0
- package/dist/line-core-BOIxkjgu.js +1 -0
- package/dist/links-Bilm-v0z.js +13 -0
- package/dist/llm-slug-generator-BuAuQ5Ft.js +68 -0
- package/dist/llm-slug-generator.js +212 -0
- package/dist/llm-task-Dx8ymRFr.js +1 -0
- package/dist/local-roots-DAzCjWbC.js +34 -0
- package/dist/location-DefAH9WS.js +42 -0
- package/dist/logger-CoEtkjhn.js +550 -0
- package/dist/logger-Cqy7-Maj.js +70 -0
- package/dist/logging-B2wMcpWV.js +13 -0
- package/dist/logging-Bz1qZDPg.js +16 -0
- package/dist/logging-CArEWRgI.js +36 -0
- package/dist/logging-CbTTfADU.js +1 -0
- package/dist/logs-cli-BSjKwaur.js +261 -0
- package/dist/magic-string.es-DJPWMt-n.js +1011 -0
- package/dist/main-session-DKr0lBVk.js +36 -0
- package/dist/manager-ChTGDe87.js +2005 -0
- package/dist/manager-DuwFn87U.js +4226 -0
- package/dist/manager-runtime-E16jsvRe.js +59 -0
- package/dist/manager.runtime-F9F1eFiB.js +827 -0
- package/dist/manifest-registry-B90TyTWl.js +1350 -0
- package/dist/map-size-CMTQVKUV.js +15 -0
- package/dist/markdown-to-line-BWwaRx5F.js +640 -0
- package/dist/mask-api-key-CprzEe7l.js +10 -0
- package/dist/matrix-DzvdUw97.js +228 -0
- package/dist/matrix-migration-snapshot-adoDbNii.js +702 -0
- package/dist/mattermost-DO0BCfF3.js +1 -0
- package/dist/mattermost-SjOt4QDb.js +15 -0
- package/dist/mcp-cli-BC_VPl_o.js +94 -0
- package/dist/mcp-config-Coky4zS4.js +108 -0
- package/dist/media-limits-Cuvmmhop.js +14 -0
- package/dist/media-understanding-DD2uMjK8.js +48 -0
- package/dist/media-understanding.runtime-Kbb2bRmk.js +216 -0
- package/dist/memory-DBjQ0TPd.js +1 -0
- package/dist/memory-cli-Cm4Df0hJ.js +215 -0
- package/dist/memory-cli-yzqneSF8.js +541 -0
- package/dist/memory-search-Das1tiuB.js +204 -0
- package/dist/memory-search-DxmSTjHq.js +18 -0
- package/dist/mention-gating-B_q-EHFx.js +25 -0
- package/dist/mentions-Bxys_va0.js +154 -0
- package/dist/message-channel-Cy-gN4K2.js +106 -0
- package/dist/message-hook-mappers-BBTV3JRQ.js +249 -0
- package/dist/method-scopes-DgypDW23.js +2649 -0
- package/dist/mime-C4vVTBso.js +150 -0
- package/dist/minimal-C5yUxtHy.js +2120 -0
- package/dist/model-auth-B__TJTPw.js +309 -0
- package/dist/model-auth-env-CF9ts7Th.js +111 -0
- package/dist/model-catalog.runtime-CWh17vcc.js +211 -0
- package/dist/model-id-normalization-Y-MIsyK_.js +16 -0
- package/dist/model-input-BB2wSAHb.js +20 -0
- package/dist/model-overrides-sIzKU2wo.js +84 -0
- package/dist/model-param-b-DIFEhICm.js +15 -0
- package/dist/model-picker-CAPjetT3.js +400 -0
- package/dist/model-picker-DEw9viWc.js +215 -0
- package/dist/model-picker.runtime-ixYl7lB5.js +224 -0
- package/dist/model-selection-BTpJnslv.js +437 -0
- package/dist/model-selection-Ci9cPkL2.js +765 -0
- package/dist/model-suppression.runtime-D8cIb6Y5.js +216 -0
- package/dist/models-BQtc3khN.js +226 -0
- package/dist/models-CQgBV5dW.js +2536 -0
- package/dist/models-cli-DbQ-QpQk.js +418 -0
- package/dist/models-config-D2xK-G6c.js +211 -0
- package/dist/models-config.providers.discovery-BaIk1NKL.js +141 -0
- package/dist/models-config.runtime-Cf7q9uAQ.js +211 -0
- package/dist/monitor-B5QmKaD7.js +3272 -0
- package/dist/monitor-CL5OYLih.js +878 -0
- package/dist/monitor-CNZxrM4d.js +3145 -0
- package/dist/monitor-CyQVZdDh.js +223 -0
- package/dist/multimodal-DC43jYNv.js +75 -0
- package/dist/mutable-allowlist-detectors-C6EAzWYE.js +62 -0
- package/dist/net-DlJFp95v.js +270 -0
- package/dist/network-mode-DOgvmom4.js +17 -0
- package/dist/nextcloud-talk-ChMP88s-.js +12 -0
- package/dist/nextcloud-talk-CwnkUy8E.js +1 -0
- package/dist/node-cli-BZDC7rXg.js +2484 -0
- package/dist/node-command-policy-Bg2g6Xjp.js +192 -0
- package/dist/node-commands-B6W6Eo0b.js +11 -0
- package/dist/node-require-BgDD9bTi.js +14 -0
- package/dist/node-resolve-BunMro3f.js +69 -0
- package/dist/node-service-CEZZaqba.js +65 -0
- package/dist/node-startup-env-Gz8ZQniA.js +50 -0
- package/dist/nodes-cli-B4Jr9vct.js +1330 -0
- package/dist/nodes-screen-CQ7IvP62.js +401 -0
- package/dist/normalize-secret-input-_PgpexOG.js +32 -0
- package/dist/note-dfjacCV8.js +109 -0
- package/dist/npm-pack-install-CYNRv-vM.js +574 -0
- package/dist/npm-resolution-Ml2aA6Nu.js +60 -0
- package/dist/oauth.runtime-DA_48MPQ.js +687 -0
- package/dist/oauth.runtime-DS1ry5__.js +318 -0
- package/dist/oauth.runtime-qCkidk8J.js +180 -0
- package/dist/ollama-defaults-asNuGW4_.js +4 -0
- package/dist/onboard-BM6gO6Uw.js +589 -0
- package/dist/onboard-D9IU-7uw.js +48 -0
- package/dist/onboard-DQaHGPRm.js +25 -0
- package/dist/onboard-channels-BdQtLjYb.js +300 -0
- package/dist/onboard-channels-DIVUygs5.js +1257 -0
- package/dist/onboard-config-DFKb-0sE.js +29 -0
- package/dist/onboard-config-DYykzJhx.js +2 -0
- package/dist/onboard-custom-CDP4w1AT.js +216 -0
- package/dist/onboard-custom-DhJN13UV.js +644 -0
- package/dist/onboard-helpers-B7XTd4Pw.js +335 -0
- package/dist/onboard-helpers-BUKtx5Bq.js +54 -0
- package/dist/onboard-hooks-BHSSLAhI.js +73 -0
- package/dist/onboard-remote-BOzEPdHA.js +59 -0
- package/dist/onboard-remote-DVza19_k.js +182 -0
- package/dist/onboard-search-CrS-n9_3.js +446 -0
- package/dist/onboard-skills-BojzIPvk.js +133 -0
- package/dist/onboard-skills-D7HyCVjz.js +69 -0
- package/dist/openai-codex-provider.runtime-BFsopDHI.js +2 -0
- package/dist/openai-defaults-B7FUywsh.js +10 -0
- package/dist/openclaw-exec-env-AcZ9we1N.js +14 -0
- package/dist/openclaw-root-TUHYdr9B.js +88 -0
- package/dist/openclaw-tools.runtime-draZJo5r.js +211 -0
- package/dist/outbound-media-69yrWRDt.js +11 -0
- package/dist/outbound-runtime-ic_7ulJJ.js +1 -0
- package/dist/pairing-challenge-CNrPmmi9.js +48 -0
- package/dist/pairing-cli-BohXW2BK.js +150 -0
- package/dist/pairing-labels-CNKCSmBK.js +7 -0
- package/dist/pairing-message-CBv2njJT.js +4 -0
- package/dist/pairing-store-C4lsd4pO.js +590 -0
- package/dist/pairing-token-gKj4SNFJ.js +55 -0
- package/dist/parse-duration-BBGYkY0S.js +41 -0
- package/dist/parse-finite-number-CP4MQF_w.js +30 -0
- package/dist/parse-log-line-CVh9zu3Q.js +43 -0
- package/dist/parse-port-COyt3COn.js +8 -0
- package/dist/path-alias-guards-ZTKqurNH.js +40 -0
- package/dist/path-env-CPkz6U0Y.js +87 -0
- package/dist/paths-CTjJI9l0.js +179 -0
- package/dist/paths-GHJ97ebE.js +268 -0
- package/dist/paths-nCHyK08H.js +56 -0
- package/dist/perplexity-Beshd9zu.js +422 -0
- package/dist/persistent-dedupe-bjKjVI5u.js +116 -0
- package/dist/pi-embedded-CSQySvOV.js +168518 -0
- package/dist/pi-model-discovery-CuX5CDyZ.js +125 -0
- package/dist/pi-model-discovery-runtime-DNsMrX1n.js +44 -0
- package/dist/pi-tools.before-tool-call.runtime-DxVqzMVf.js +387 -0
- package/dist/platform-launcher-CqGy6UhP.js +83 -0
- package/dist/plugin-entry-CwuwM1jC.js +17 -0
- package/dist/plugin-install-JJwfOXtg.js +216 -0
- package/dist/plugin-install-plan-cixz1_W4.js +49 -0
- package/dist/plugin-install-vkpI1UNd.js +184 -0
- package/dist/plugin-registry-C3j_DUnj.js +51 -0
- package/dist/plugin-registry-DB_yxabS.js +213 -0
- package/dist/plugin-sdk/account-helpers.js +3 -0
- package/dist/plugin-sdk/account-id.js +2 -0
- package/dist/plugin-sdk/account-resolution.js +216 -0
- package/dist/plugin-sdk/acp-runtime.js +46 -0
- package/dist/plugin-sdk/agent-runtime.js +215 -0
- package/dist/plugin-sdk/allow-from.js +17 -0
- package/dist/plugin-sdk/allowlist-config-edit.js +2 -0
- package/dist/plugin-sdk/bluebubbles.js +232 -0
- package/dist/plugin-sdk/boolean-param.js +2 -0
- package/dist/plugin-sdk/channel-actions.js +16 -0
- package/dist/plugin-sdk/channel-config-helpers.js +15 -0
- package/dist/plugin-sdk/channel-config-schema.js +5 -0
- package/dist/plugin-sdk/channel-contract.js +1 -0
- package/dist/plugin-sdk/channel-feedback.js +4 -0
- package/dist/plugin-sdk/channel-inbound.js +53 -0
- package/dist/plugin-sdk/channel-lifecycle.js +2 -0
- package/dist/plugin-sdk/channel-pairing.js +2 -0
- package/dist/plugin-sdk/channel-policy.js +19 -0
- package/dist/plugin-sdk/channel-reply-pipeline.js +23 -0
- package/dist/plugin-sdk/channel-runtime.js +33 -0
- package/dist/plugin-sdk/channel-send-result.js +2 -0
- package/dist/plugin-sdk/channel-setup.js +24 -0
- package/dist/plugin-sdk/channel-targets.js +3 -0
- package/dist/plugin-sdk/cli-runtime.js +5 -0
- package/dist/plugin-sdk/command-auth.js +212 -0
- package/dist/plugin-sdk/compat.js +59 -0
- package/dist/plugin-sdk/config-runtime.js +51 -0
- package/dist/plugin-sdk/conversation-runtime.js +55 -0
- package/dist/plugin-sdk/core.js +40 -0
- package/dist/plugin-sdk/device-bootstrap.js +6 -0
- package/dist/plugin-sdk/diagnostics-otel.js +7 -0
- package/dist/plugin-sdk/diffs.js +3 -0
- package/dist/plugin-sdk/directory-runtime.js +5 -0
- package/dist/plugin-sdk/discord-core.js +26 -0
- package/dist/plugin-sdk/discord.js +219 -0
- package/dist/plugin-sdk/extension-shared.js +15 -0
- package/dist/plugin-sdk/feishu.js +101 -0
- package/dist/plugin-sdk/gateway-runtime.js +46 -0
- package/dist/plugin-sdk/googlechat.js +93 -0
- package/dist/plugin-sdk/group-access.js +2 -0
- package/dist/plugin-sdk/hook-runtime.js +12 -0
- package/dist/plugin-sdk/image-generation.js +51 -0
- package/dist/plugin-sdk/imessage-core.js +214 -0
- package/dist/plugin-sdk/imessage.js +223 -0
- package/dist/plugin-sdk/index.js +55 -0
- package/dist/plugin-sdk/infra-runtime.js +223 -0
- package/dist/plugin-sdk/interactive-runtime.js +3 -0
- package/dist/plugin-sdk/irc.js +232 -0
- package/dist/plugin-sdk/json-store.js +9 -0
- package/dist/plugin-sdk/keyed-async-queue.js +2 -0
- package/dist/plugin-sdk/lazy-runtime.js +2 -0
- package/dist/plugin-sdk/line-core.js +29 -0
- package/dist/plugin-sdk/line.js +22 -0
- package/dist/plugin-sdk/llm-task.js +7 -0
- package/dist/plugin-sdk/matrix-runtime-heavy.js +223 -0
- package/dist/plugin-sdk/matrix-runtime-shared.js +2 -0
- package/dist/plugin-sdk/matrix.js +84 -0
- package/dist/plugin-sdk/mattermost.js +233 -0
- package/dist/plugin-sdk/media-runtime.js +212 -0
- package/dist/plugin-sdk/media-understanding-runtime.js +211 -0
- package/dist/plugin-sdk/media-understanding.js +15 -0
- package/dist/plugin-sdk/memory-core.js +2 -0
- package/dist/plugin-sdk/memory-lancedb.js +2 -0
- package/dist/plugin-sdk/msteams.js +244 -0
- package/dist/plugin-sdk/nextcloud-talk.js +231 -0
- package/dist/plugin-sdk/nostr.js +50 -0
- package/dist/plugin-sdk/ollama-setup.js +33 -0
- package/dist/plugin-sdk/outbound-runtime.js +23 -0
- package/dist/plugin-sdk/plugin-entry.js +3 -0
- package/dist/plugin-sdk/plugin-runtime.js +211 -0
- package/dist/plugin-sdk/process-runtime.js +12 -0
- package/dist/plugin-sdk/provider-auth-api-key.js +53 -0
- package/dist/plugin-sdk/provider-auth-login.js +2 -0
- package/dist/plugin-sdk/provider-auth.js +37 -0
- package/dist/plugin-sdk/provider-catalog.js +2 -0
- package/dist/plugin-sdk/provider-env-vars.js +2 -0
- package/dist/plugin-sdk/provider-google.js +3 -0
- package/dist/plugin-sdk/provider-models.js +27 -0
- package/dist/plugin-sdk/provider-onboard.js +20 -0
- package/dist/plugin-sdk/provider-setup.js +58 -0
- package/dist/plugin-sdk/provider-stream.js +211 -0
- package/dist/plugin-sdk/provider-usage.js +18 -0
- package/dist/plugin-sdk/provider-web-search.js +23 -0
- package/dist/plugin-sdk/provider-zai-endpoint.js +3 -0
- package/dist/plugin-sdk/reply-history.js +23 -0
- package/dist/plugin-sdk/reply-payload.js +2 -0
- package/dist/plugin-sdk/reply-runtime.js +211 -0
- package/dist/plugin-sdk/request-url.js +2 -0
- package/dist/plugin-sdk/routing.js +25 -0
- package/dist/plugin-sdk/runtime-env.js +15 -0
- package/dist/plugin-sdk/runtime-store.js +2 -0
- package/dist/plugin-sdk/runtime.js +15 -0
- package/dist/plugin-sdk/sandbox.js +66 -0
- package/dist/plugin-sdk/secret-input.js +3 -0
- package/dist/plugin-sdk/security-runtime.js +18 -0
- package/dist/plugin-sdk/self-hosted-provider-setup.js +33 -0
- package/dist/plugin-sdk/setup-adapter-runtime.js +2 -0
- package/dist/plugin-sdk/setup-runtime.js +17 -0
- package/dist/plugin-sdk/setup-tools.js +21 -0
- package/dist/plugin-sdk/setup.js +26 -0
- package/dist/plugin-sdk/signal.js +220 -0
- package/dist/plugin-sdk/slack-core.js +22 -0
- package/dist/plugin-sdk/slack.js +223 -0
- package/dist/plugin-sdk/speech-runtime.js +213 -0
- package/dist/plugin-sdk/speech.js +212 -0
- package/dist/plugin-sdk/ssrf-runtime.js +5 -0
- package/dist/plugin-sdk/state-paths.js +3 -0
- package/dist/plugin-sdk/status-helpers.js +9 -0
- package/dist/plugin-sdk/telegram-core.js +23 -0
- package/dist/plugin-sdk/telegram.js +224 -0
- package/dist/plugin-sdk/testing.js +13174 -0
- package/dist/plugin-sdk/text-runtime.js +45 -0
- package/dist/plugin-sdk/thread-bindings-runtime.js +2 -0
- package/dist/plugin-sdk/thread-ownership.js +2 -0
- package/dist/plugin-sdk/tlon.js +57 -0
- package/dist/plugin-sdk/tool-send.js +2 -0
- package/dist/plugin-sdk/twitch.js +46 -0
- package/dist/plugin-sdk/voice-call.js +213 -0
- package/dist/plugin-sdk/web-media.js +28 -0
- package/dist/plugin-sdk/webhook-ingress.js +7 -0
- package/dist/plugin-sdk/webhook-path.js +2 -0
- package/dist/plugin-sdk/whatsapp-core.js +219 -0
- package/dist/plugin-sdk/whatsapp-shared.js +18 -0
- package/dist/plugin-sdk/windows-spawn.js +2 -0
- package/dist/plugin-sdk/zalo.js +239 -0
- package/dist/plugin-sdk/zalouser.js +240 -0
- package/dist/plugins/build-smoke-entry.js +211 -0
- package/dist/plugins/runtime/index.js +229 -0
- package/dist/plugins-1Z50ecJ6.js +1 -0
- package/dist/plugins-C6fKmNuA.js +7 -0
- package/dist/plugins-cli-BkgQkGaU.js +1192 -0
- package/dist/policy-CpkbSAfm.js +60 -0
- package/dist/polls-B2VH7SN9.js +35 -0
- package/dist/ports-BjWuIIQw.js +262 -0
- package/dist/ports-DFiK_Jc-.js +385 -0
- package/dist/ports-lsof-DtJqhFOr.js +25 -0
- package/dist/ports-probe-BQqp8l8E.js +14 -0
- package/dist/preflight-audio.runtime-Fi9mofpp.js +216 -0
- package/dist/probe-BM9sbCgS.js +20 -0
- package/dist/probe-DLBOZftS.js +134 -0
- package/dist/probe-auth-Bjp3G4CI.js +48 -0
- package/dist/probe-auth-DMSPTRRk.js +45 -0
- package/dist/process-runtime-C7el-Ri4.js +1 -0
- package/dist/process-scoped-map-C4gOa-gv.js +61 -0
- package/dist/profile-utils-BcMYGFPT.js +15 -0
- package/dist/profiles-D17eMKQZ.js +683 -0
- package/dist/program-Ch-76sgl.js +155 -0
- package/dist/program-context-BMWNUfqL.js +10 -0
- package/dist/program-context-CD_RvRYh.js +2 -0
- package/dist/progress-D1r9bZU1.js +132 -0
- package/dist/prompt-select-styled-NUKYS9QR.js +4879 -0
- package/dist/prompt-style-BvciNCqy.js +7 -0
- package/dist/prompts-NtuylUyl.js +9 -0
- package/dist/prototype-keys-Cm_8mWvq.js +11 -0
- package/dist/provider-api-key-auth-BE0taXiB.js +108 -0
- package/dist/provider-api-key-auth.runtime-jDZZUAMX.js +34 -0
- package/dist/provider-auth-Bw8x1a3o.js +58 -0
- package/dist/provider-auth-api-key-BrQYvdxi.js +1 -0
- package/dist/provider-auth-choice-BYbPq0eC.js +128 -0
- package/dist/provider-auth-choice-helpers-Bj1GkOSn.js +48 -0
- package/dist/provider-auth-choice-preference-tKq5gaJL.js +192 -0
- package/dist/provider-auth-choice.runtime-DegPpvRJ.js +223 -0
- package/dist/provider-auth-choices-QSilukI1.js +58 -0
- package/dist/provider-auth-guidance-gninjjq8.js +34 -0
- package/dist/provider-auth-helpers-B0dS-1WK.js +86 -0
- package/dist/provider-auth-input-BftBdgvW.js +112 -0
- package/dist/provider-auth-login-D0n0lMuc.js +8 -0
- package/dist/provider-auth-login.runtime-LvuBkQrc.js +243 -0
- package/dist/provider-auth-mode-sTdccIKL.js +20 -0
- package/dist/provider-auth-ref-BS3gwrNr.js +168 -0
- package/dist/provider-auth-ref-BmEcEN7K.js +3 -0
- package/dist/provider-catalog--18-pW5t.js +11 -0
- package/dist/provider-catalog-2P2hel74.js +48 -0
- package/dist/provider-catalog-B0FqWSwe.js +48 -0
- package/dist/provider-catalog-BvORKzzD.js +91 -0
- package/dist/provider-catalog-C34j1_or.js +26 -0
- package/dist/provider-catalog-C5vmXjmb.js +11 -0
- package/dist/provider-catalog-CBufm2Dr.js +36 -0
- package/dist/provider-catalog-D7QvsUXS.js +12 -0
- package/dist/provider-catalog-DKy_dzQZ.js +41 -0
- package/dist/provider-env-vars-CsQlY7bF.js +110 -0
- package/dist/provider-id-BpXo5t6v.js +31 -0
- package/dist/provider-model-allowlist-4HSOnlX-.js +24 -0
- package/dist/provider-model-primary-NJ-xlhec.js +53 -0
- package/dist/provider-models-C2EjYMwW.js +2416 -0
- package/dist/provider-oauth-flow-BQN6F6EC.js +33 -0
- package/dist/provider-ollama-setup-DhQvDwAj.js +309 -0
- package/dist/provider-onboard-CjOfyeQG.js +1 -0
- package/dist/provider-onboarding-config-DOZ3pFA6.js +165 -0
- package/dist/provider-openai-codex-oauth-tls-Bo8U4D3E.js +101 -0
- package/dist/provider-runtime.runtime-DnP2jpoM.js +211 -0
- package/dist/provider-self-hosted-setup-CUrmsugW.js +182 -0
- package/dist/provider-usage-ClDVmkhl.js +633 -0
- package/dist/provider-usage-DIC6cn-3.js +211 -0
- package/dist/provider-web-search-NzK8ep1E.js +507 -0
- package/dist/provider-wizard-C6jCuyQe.js +236 -0
- package/dist/provider-zai-endpoint-DeDABzT4.js +106 -0
- package/dist/proxy-H5O2p6AP.js +121 -0
- package/dist/proxy-env-DG2u55RW.js +40 -0
- package/dist/push-apns-D4zD2tmP.js +1050 -0
- package/dist/pw-ai-BuPUVeUK.js +1876 -0
- package/dist/qmd-manager-BpygGMW9.js +1571 -0
- package/dist/qr-cli-DnWHXcxh.js +370 -0
- package/dist/qr-cli-yaZ0FZ6z.js +213 -0
- package/dist/query-expansion-Do45hILP.js +1114 -0
- package/dist/reactions-BcC_XZqD.js +281 -0
- package/dist/read-only-account-inspect-DPJzadPo.js +42 -0
- package/dist/read-only-account-inspect.discord.runtime-CW9DDKH8.js +216 -0
- package/dist/read-only-account-inspect.slack.runtime-BcXBPyh3.js +216 -0
- package/dist/read-only-account-inspect.telegram.runtime-Y7h0Jbdj.js +216 -0
- package/dist/redact-BDinS1q9.js +102 -0
- package/dist/redact-identifier-FUiWQxv5.js +13 -0
- package/dist/redact-snapshot-DBPmeYy2.js +2654 -0
- package/dist/ref-contract-CCBBbf1r.js +53 -0
- package/dist/register-CppP7Ddc.js +43 -0
- package/dist/register.agent-BOD5ROGQ.js +546 -0
- package/dist/register.backup-Y2VGqcRu.js +269 -0
- package/dist/register.configure-1qiTINph.js +354 -0
- package/dist/register.maintenance-shn-zigv.js +694 -0
- package/dist/register.message-mR4CLSoo.js +812 -0
- package/dist/register.onboard-CkDryVid.js +298 -0
- package/dist/register.setup-B0xW5olD.js +318 -0
- package/dist/register.status-health-sessions-CuhWc03j.js +604 -0
- package/dist/register.subclis-BazXM5TW.js +315 -0
- package/dist/register.subclis-C2d8UDhH.js +13 -0
- package/dist/registry-C3q59Qj0.js +55 -0
- package/dist/registry-CPsHw6xU.js +219 -0
- package/dist/registry-CxgtJ09C.js +28 -0
- package/dist/registry-rgYi7KoO.js +160 -0
- package/dist/repair-qXnOAvDy.js +105 -0
- package/dist/replies-EiwmmZ_W.js +122 -0
- package/dist/reply-history-CVCD5oE9.js +1 -0
- package/dist/reply-payload-DBGc074f.js +232 -0
- package/dist/report-cli-DB1jQx32.js +42 -0
- package/dist/request-url-BKfWAQx8.js +10 -0
- package/dist/resolve-Ckjd8TAk.js +14 -0
- package/dist/resolve-T2q_0ARF.js +619 -0
- package/dist/resolve-route-vEY3ONZ2.js +466 -0
- package/dist/resolve-utils-CbqJY2bs.js +102 -0
- package/dist/response-generator-VdoCcQ3y.js +153 -0
- package/dist/restart-stale-pids-CLGiqU2E.js +187 -0
- package/dist/retry-D15TD1S3.js +168 -0
- package/dist/root-help-B9Aou4ho.js +32 -0
- package/dist/routes-TpLEcKO8.js +7084 -0
- package/dist/routing-Y3m0o-kB.js +26 -0
- package/dist/rpc-C6MN-nVc.js +67 -0
- package/dist/run-command-DRKv5Lj6.js +32 -0
- package/dist/run-main-YZSMdx0B.js +424 -0
- package/dist/run-with-concurrency-BrSjWzpg.js +41 -0
- package/dist/runtime-B66W9flm.js +43 -0
- package/dist/runtime-C9VaVKYZ.js +2338 -0
- package/dist/runtime-CT2LIJZu.js +91 -0
- package/dist/runtime-CqDQ81eY.js +143 -0
- package/dist/runtime-CuvWMN7E.js +89 -0
- package/dist/runtime-D4_OpzA1.js +5 -0
- package/dist/runtime-DP-4DZja.js +5 -0
- package/dist/runtime-Dl17x_cV.js +1 -0
- package/dist/runtime-Z35JoYPC.js +30 -0
- package/dist/runtime-api-D79M0lQN.js +1 -0
- package/dist/runtime-api-y3zfnQGK.js +39 -0
- package/dist/runtime-discord-ops.runtime-Bg5h5v9-.js +234 -0
- package/dist/runtime-env-a_iwdJIv.js +1 -0
- package/dist/runtime-forwarders-DtMc8rBP.js +44 -0
- package/dist/runtime-group-policy-B7irU4eu.js +59 -0
- package/dist/runtime-guard-y62lPDGY.js +58 -0
- package/dist/runtime-parse-CeqXmZHJ.js +84 -0
- package/dist/runtime-paths-CstaCCMi.js +334 -0
- package/dist/runtime-slack-ops.runtime-BumgKDhS.js +226 -0
- package/dist/runtime-status-CgL02wYX.js +15 -0
- package/dist/runtime-store-Bt3Sdbrn.js +22 -0
- package/dist/runtime-telegram-ops.runtime-rSLQ3KrE.js +233 -0
- package/dist/runtime-whatsapp-boundary-xZem0NyQ.js +364 -0
- package/dist/safe-open-sync-Bt9R1Mnf.js +83 -0
- package/dist/safe-regex-tLlDZYfM.js +244 -0
- package/dist/safe-text-B_CQuica.js +16 -0
- package/dist/sandbox-CUUouiKs.js +2795 -0
- package/dist/sandbox-cli-BN8y0Get.js +499 -0
- package/dist/sandbox-paths-fqp_TZdO.js +144 -0
- package/dist/sandbox-qSs4h3sk.js +1 -0
- package/dist/sanitize-env-vars-vNSNqm0y.js +74 -0
- package/dist/scan-paths-BJmvUZ1E.js +28 -0
- package/dist/search-manager-DWhFgwyp.js +17 -0
- package/dist/search-manager-r8Cw4ZRv.js +392 -0
- package/dist/secret-equal-ObQfyZGa.js +9 -0
- package/dist/secret-file-Ch0yuOXR.js +11 -0
- package/dist/secret-file-DYJtH6kf.js +92 -0
- package/dist/secret-input-4REZ4sHo.js +35 -0
- package/dist/secrets-cli-D1df8b0o.js +2304 -0
- package/dist/secure-random-Cs8tw_HQ.js +10 -0
- package/dist/security-cli-V66ESmdT.js +676 -0
- package/dist/security-runtime-BuEhpJVE.js +23 -0
- package/dist/send-3tabvle6.js +100 -0
- package/dist/send-CC5J3tyW.js +1026 -0
- package/dist/send-deps-CrFMNvqO.js +19 -0
- package/dist/send-i2-mdtiE.js +250 -0
- package/dist/server-BTOjmlyi.js +116 -0
- package/dist/server-middleware-CCqKhKUb.js +106 -0
- package/dist/server-node-events-D6y22Tt8.js +611 -0
- package/dist/server-startup-matrix-migration-DHWSoS73.js +1595 -0
- package/dist/service-Bxc9uL2e.js +774 -0
- package/dist/service-CBLajPZL.js +21 -0
- package/dist/session-cost-usage-BmbaBvk4.js +212 -0
- package/dist/session-cost-usage-C30Jl2SI.js +615 -0
- package/dist/session-fork.runtime-BZfcC1Nc.js +51 -0
- package/dist/session-key-gFFk3uv9.js +216 -0
- package/dist/session-write-lock-DNKvpjKf.js +324 -0
- package/dist/sessions-BIH_j_XS.js +222 -0
- package/dist/sessions-D5dWcxC_.js +212 -0
- package/dist/sessions-DaSBVNwD.js +669 -0
- package/dist/setup-C2XF1YH3.js +397 -0
- package/dist/setup-CN-teRpz.js +8 -0
- package/dist/setup-adapter-runtime-Bjv2adwG.js +1 -0
- package/dist/setup-binary-BOJA7zdN.js +30 -0
- package/dist/setup-browser-BhNPCUtK.js +71 -0
- package/dist/setup-core-BsG09DZH.js +149 -0
- package/dist/setup-core-D-O1GQax.js +162 -0
- package/dist/setup-core-Dtm54Rcq.js +510 -0
- package/dist/setup-entry-B1mTa7bU.js +10 -0
- package/dist/setup-entry-CTMgw-K5.js +13 -0
- package/dist/setup-entry-Cmd_cufO.js +13 -0
- package/dist/setup-entry-CybgA3zP.js +12 -0
- package/dist/setup-entry-DED_hL6i.js +12 -0
- package/dist/setup-entry-WCq9VMWx.js +14 -0
- package/dist/setup-group-access-BtPApRvE.js +70 -0
- package/dist/setup-helpers-B62Ecg9r.js +362 -0
- package/dist/setup-surface-B7A7qowY.js +452 -0
- package/dist/setup-surface-BBYJVRXc.js +380 -0
- package/dist/setup-surface-CFUz_BJi.js +298 -0
- package/dist/setup-tools-BPiMjAN7.js +1 -0
- package/dist/setup-wizard-helpers-COZ1UAdX.js +770 -0
- package/dist/setup-wizard-proxy-Slwi-1gX.js +116 -0
- package/dist/setup.finalize-B8O01nge.js +633 -0
- package/dist/setup.gateway-config-BPDIFk__.js +288 -0
- package/dist/setup.secret-input-BL-bqJpt.js +25 -0
- package/dist/shared-AygSbeCK.js +50 -0
- package/dist/shared-BHqDLkMG.js +127 -0
- package/dist/shared-BPtG8PgB.js +70 -0
- package/dist/shared-BU0QgVMZ.js +36 -0
- package/dist/shared-Bzr2UyEm.js +351 -0
- package/dist/shared-C_XXbGIF.js +87 -0
- package/dist/shared-Diw3KzwZ.js +82 -0
- package/dist/shared-DngjQumT.js +196 -0
- package/dist/shared-DzH3zmAy.js +64 -0
- package/dist/shared-LeP8iUTz.js +54 -0
- package/dist/shell-argv-DWV43Vya.js +72 -0
- package/dist/shell-env-cD92jEyV.js +181 -0
- package/dist/signal-BQd9f9dF.js +315 -0
- package/dist/signal-Ca7y47bM.js +46 -0
- package/dist/signal-Did9U_fa.js +214 -0
- package/dist/signal-cli-install-DxoL8CgF.js +188 -0
- package/dist/skill-commands-CiSwTFBQ.js +652 -0
- package/dist/skill-commands.runtime-CEwlWT4j.js +34 -0
- package/dist/skill-scanner-DG7MT7pu.js +354 -0
- package/dist/skills-BC8GJ9Rp.js +22 -0
- package/dist/skills-CCgKs_NJ.js +863 -0
- package/dist/skills-cli-dhYXJCuL.js +339 -0
- package/dist/skills-install-DiriUXJd.js +763 -0
- package/dist/skills-status-BmQTn4jL.js +23 -0
- package/dist/skills-status-a9b899Y3.js +169 -0
- package/dist/slack-CXgv7nu7.js +730 -0
- package/dist/slack-CcSByPzI.js +217 -0
- package/dist/slack-CtcCh0Lj.js +24537 -0
- package/dist/slack-core-DcsbATUs.js +1 -0
- package/dist/slash-commands.runtime-kO8EUKYW.js +228 -0
- package/dist/slash-dispatch.runtime-Bu2yMeFy.js +238 -0
- package/dist/slash-skill-commands.runtime-wwX3tF84.js +216 -0
- package/dist/speech-bSreRuDH.js +1 -0
- package/dist/speech-runtime-y1FcnGVA.js +1 -0
- package/dist/src-CmXHIz5f.js +846 -0
- package/dist/ssh-config-ChqR6ijV.js +77 -0
- package/dist/ssh-tunnel-Cz51VBAt.js +159 -0
- package/dist/ssh-tunnel-DWze2IQS.js +16 -0
- package/dist/ssrf-Dk9XaoKN.js +220 -0
- package/dist/ssrf-policy-Dk6oMa20.js +69 -0
- package/dist/ssrf-runtime-C-mAQLVA.js +1 -0
- package/dist/stagger-DU7FjHYo.js +54 -0
- package/dist/state-paths-DJIGEFq_.js +1 -0
- package/dist/status-69r8-Zey.js +75 -0
- package/dist/status-BdLTvZOL.js +44 -0
- package/dist/status-Bt7DQmRI.js +1665 -0
- package/dist/status-CoUFSBgt.js +202 -0
- package/dist/status-DbI3Kbh5.js +235 -0
- package/dist/status-DeKlzu_o.js +212 -0
- package/dist/status-Haie42Fc.js +606 -0
- package/dist/status-helpers-Cda-rGLX.js +101 -0
- package/dist/status-json-DS1M_MWJ.js +322 -0
- package/dist/status.link-channel-Cb8bZ_Od.js +40 -0
- package/dist/status.scan.deps.runtime-7_6VUs50.js +77 -0
- package/dist/status.scan.runtime-DtR8BIE9.js +14 -0
- package/dist/status.summary-l_Bi1buR.js +600 -0
- package/dist/status.summary.runtime-Cng6MzRU.js +151 -0
- package/dist/status.update-DtbnnPKx.js +79 -0
- package/dist/store-CvL8MPei.js +1446 -0
- package/dist/store.runtime-hgnvmZgO.js +43 -0
- package/dist/string-normalization-CvzuCAZv.js +19 -0
- package/dist/string-sample-BOLqzr4Y.js +11 -0
- package/dist/subagent-orphan-recovery-si1z2iBu.js +407 -0
- package/dist/subagent-registry-runtime-CXUDI8gL.js +211 -0
- package/dist/subcli-descriptors-CY_nHzpZ.js +151 -0
- package/dist/subsystem-CUp-6QQf.js +421 -0
- package/dist/synology-chat-CdejNfs0.js +12 -0
- package/dist/system-cli-DkOaXHkQ.js +99 -0
- package/dist/system-events-mAu6Ap6K.js +75 -0
- package/dist/system-message-DA9eUYzB.js +16 -0
- package/dist/system-run-command-Cxq2F1MB.js +258 -0
- package/dist/systemd-CrxZBFae.js +557 -0
- package/dist/systemd-hints-y-zJ9aTm.js +315 -0
- package/dist/systemd-linger-BdklDcLg.js +16 -0
- package/dist/systemd-linger-DLrbG9_d.js +68 -0
- package/dist/table-DFMOhmNZ.js +305 -0
- package/dist/tailnet-ofqBrXzu.js +38 -0
- package/dist/tailscale-Cbsx-2HB.js +254 -0
- package/dist/target-errors-ksphhzJg.js +26 -0
- package/dist/target-registry-krAVlXi_.js +1321 -0
- package/dist/telegram/audit.js +2 -0
- package/dist/telegram/token.js +211 -0
- package/dist/telegram-BjDUP22F.js +10910 -0
- package/dist/telegram-DMiNSGAJ.js +575 -0
- package/dist/telegram-Dt11B3JL.js +218 -0
- package/dist/telegram-core-B4Jo-uko.js +1 -0
- package/dist/template-messages-kh7VfgOb.js +214 -0
- package/dist/text-chunking-CUf5WgqG.js +19 -0
- package/dist/text-format-sFXlJfHH.js +8 -0
- package/dist/text-runtime-C_Roi_Je.js +1418 -0
- package/dist/theme-B5HDbQfl.js +2 -0
- package/dist/theme-CdOoMzRk.js +34 -0
- package/dist/thinking-BBD_0HSp.js +68 -0
- package/dist/thinking.shared-CncvRHts.js +246 -0
- package/dist/thread-bindings-messages-Cdo8jSa9.js +229 -0
- package/dist/thread-bindings-policy-DMjOaNyR.js +119 -0
- package/dist/thread-bindings-runtime-Ckwk3Uuz.js +1 -0
- package/dist/threading-helpers-Cq55SUtb.js +14 -0
- package/dist/timeouts-BwR1sGom.js +72 -0
- package/dist/tmp-openclaw-dir-idKIOMmb.js +102 -0
- package/dist/token-Bgv8XEsC.js +50 -0
- package/dist/tool-catalog-BV6FcEWS.js +337 -0
- package/dist/tool-policy-match-CHqTCSdK.js +46 -0
- package/dist/tool-send-9LXKcrda.js +16 -0
- package/dist/topology-cli-BhUXVViF.js +43 -0
- package/dist/transcript-events-B1V6z5ct.js +29 -0
- package/dist/tui-DDJMGCFK.js +3838 -0
- package/dist/tui-cli-ByN-ZH6y.js +237 -0
- package/dist/typebox-D0SHDJST.js +175 -0
- package/dist/types-BCKGVVld.js +83 -0
- package/dist/types-CtpUGsDP.js +30 -0
- package/dist/types.secrets-BWSeXrF4.js +80 -0
- package/dist/types.tools-BBO8HCi6.js +22 -0
- package/dist/typing-DG_YqWJ7.js +224 -0
- package/dist/unhandled-rejections-CDJ8dOVP.js +170 -0
- package/dist/unhandled-rejections-O6cVOz2D.js +4 -0
- package/dist/update-Br8U-txJ.js +1039 -0
- package/dist/update-check-C3TeQaWg.js +464 -0
- package/dist/update-cli-XHfIntD0.js +1625 -0
- package/dist/update-offset-store-36vzzZXw.js +211 -0
- package/dist/upsert-with-lock-Bb96JHpb.js +34 -0
- package/dist/url-userinfo-Db63ng4y.js +14 -0
- package/dist/utils-Bxk6BLTg.js +236 -0
- package/dist/utils-vDeUf98G.js +7 -0
- package/dist/version-DCY9_obP.js +64 -0
- package/dist/version-DRF-wKTV.js +2 -0
- package/dist/voice-call-D4fgwZNO.js +1 -0
- package/dist/warning-filter-CgvLQB4Y.js +56 -0
- package/dist/web-media-BfBb8i48.js +1 -0
- package/dist/web-media-CtU6jM5V.js +498 -0
- package/dist/webhook-ingress-CupqYpKM.js +338 -0
- package/dist/webhook-memory-guards-BHrFZ4yq.js +129 -0
- package/dist/webhook-path-BGFZ55ML.js +22 -0
- package/dist/webhook-shared-Cvk3b0ac.js +349 -0
- package/dist/webhooks-cli-vOAoBF9b.js +357 -0
- package/dist/whatsapp-D5nD0rGG.js +58 -0
- package/dist/whatsapp-DXbWlm3A.js +82 -0
- package/dist/whatsapp-core-C2WGMsaY.js +89451 -0
- package/dist/whatsapp-heartbeat-CSWnPQ7q.js +84 -0
- package/dist/whatsapp-shared-BmHKqTtR.js +95 -0
- package/dist/widearea-dns-CXimgJzu.js +125 -0
- package/dist/windows-argv-IXrdWrJj.js +145 -0
- package/dist/windows-spawn-vMJGZo89.js +154 -0
- package/dist/with-timeout-2AKTISee.js +58 -0
- package/dist/workspace-BH7CXmrr.js +479 -0
- package/dist/workspace-dirs-_O4V3xCR.js +13 -0
- package/dist/workspace-v5XppK5M.js +302 -0
- package/dist/ws-By-QcLjg.js +11 -0
- package/dist/wsl-BV3Cb66X.js +57 -0
- package/dist/zalo-CHQzsLhE.js +301 -0
- package/dist/zalo-CcJ3J9f2.js +13 -0
- package/dist/zod-schema.agent-runtime-T_EC_6fg.js +600 -0
- package/dist/zod-schema.core-BdgRr-F1.js +545 -0
- package/dist/zod-schema.providers-core-Dgq7MTqU.js +1613 -0
- package/docs/.i18n/README.md +31 -0
- package/docs/.i18n/glossary.ja-JP.json +14 -0
- package/docs/.i18n/glossary.zh-CN.json +242 -0
- package/docs/.i18n/ja-JP.tm.jsonl +0 -0
- package/docs/assets/install-script.svg +1 -0
- package/docs/assets/macos-onboarding/01-macos-warning.jpeg +0 -0
- package/docs/assets/macos-onboarding/02-local-networks.jpeg +0 -0
- package/docs/assets/macos-onboarding/03-security-notice.png +0 -0
- package/docs/assets/macos-onboarding/04-choose-gateway.png +0 -0
- package/docs/assets/macos-onboarding/05-permissions.png +0 -0
- package/docs/assets/openclaw-logo-text-dark.png +0 -0
- package/docs/assets/openclaw-logo-text-dark.svg +418 -0
- package/docs/assets/openclaw-logo-text.png +0 -0
- package/docs/assets/openclaw-logo-text.svg +418 -0
- package/docs/assets/pixel-lobster.svg +60 -0
- package/docs/assets/showcase/agents-ui.jpg +0 -0
- package/docs/assets/showcase/bambu-cli.png +0 -0
- package/docs/assets/showcase/codexmonitor.png +0 -0
- package/docs/assets/showcase/gohome-grafana.png +0 -0
- package/docs/assets/showcase/ios-testflight.jpg +0 -0
- package/docs/assets/showcase/oura-health.png +0 -0
- package/docs/assets/showcase/padel-cli.svg +11 -0
- package/docs/assets/showcase/padel-screenshot.jpg +0 -0
- package/docs/assets/showcase/papla-tts.jpg +0 -0
- package/docs/assets/showcase/pr-review-telegram.jpg +0 -0
- package/docs/assets/showcase/roborock-screenshot.jpg +0 -0
- package/docs/assets/showcase/roborock-status.svg +13 -0
- package/docs/assets/showcase/roof-camera-sky.jpg +0 -0
- package/docs/assets/showcase/snag.png +0 -0
- package/docs/assets/showcase/tesco-shop.jpg +0 -0
- package/docs/assets/showcase/wienerlinien.png +0 -0
- package/docs/assets/showcase/wine-cellar-skill.jpg +0 -0
- package/docs/assets/showcase/winix-air-purifier.jpg +0 -0
- package/docs/assets/showcase/xuezh-pronunciation.jpeg +0 -0
- package/docs/assets/sponsors/blacksmith.svg +14 -0
- package/docs/assets/sponsors/convex.svg +16 -0
- package/docs/assets/sponsors/openai.svg +3 -0
- package/docs/assets/sponsors/vercel.svg +5 -0
- package/docs/auth-credential-semantics.md +53 -0
- package/docs/automation/auth-monitoring.md +44 -0
- package/docs/automation/cron-jobs.md +727 -0
- package/docs/automation/cron-vs-heartbeat.md +286 -0
- package/docs/automation/gmail-pubsub.md +256 -0
- package/docs/automation/hooks.md +1049 -0
- package/docs/automation/poll.md +86 -0
- package/docs/automation/standing-orders.md +251 -0
- package/docs/automation/troubleshooting.md +122 -0
- package/docs/automation/webhook.md +217 -0
- package/docs/brave-search.md +93 -0
- package/docs/channels/bluebubbles.md +347 -0
- package/docs/channels/broadcast-groups.md +442 -0
- package/docs/channels/channel-routing.md +139 -0
- package/docs/channels/discord.md +1229 -0
- package/docs/channels/feishu.md +747 -0
- package/docs/channels/googlechat.md +261 -0
- package/docs/channels/group-messages.md +84 -0
- package/docs/channels/groups.md +379 -0
- package/docs/channels/imessage.md +367 -0
- package/docs/channels/index.md +47 -0
- package/docs/channels/irc.md +242 -0
- package/docs/channels/line.md +194 -0
- package/docs/channels/location.md +56 -0
- package/docs/channels/matrix.md +677 -0
- package/docs/channels/mattermost.md +427 -0
- package/docs/channels/msteams.md +780 -0
- package/docs/channels/nextcloud-talk.md +138 -0
- package/docs/channels/nostr.md +242 -0
- package/docs/channels/pairing.md +114 -0
- package/docs/channels/signal.md +329 -0
- package/docs/channels/slack.md +603 -0
- package/docs/channels/synology-chat.md +132 -0
- package/docs/channels/telegram.md +987 -0
- package/docs/channels/tlon.md +276 -0
- package/docs/channels/troubleshooting.md +118 -0
- package/docs/channels/twitch.md +379 -0
- package/docs/channels/whatsapp.md +460 -0
- package/docs/channels/zalo.md +243 -0
- package/docs/channels/zalouser.md +181 -0
- package/docs/ci.md +55 -0
- package/docs/cli/acp.md +288 -0
- package/docs/cli/agent.md +29 -0
- package/docs/cli/agents.md +123 -0
- package/docs/cli/approvals.md +50 -0
- package/docs/cli/backup.md +76 -0
- package/docs/cli/browser.md +106 -0
- package/docs/cli/channels.md +102 -0
- package/docs/cli/clawbot.md +21 -0
- package/docs/cli/completion.md +35 -0
- package/docs/cli/config.md +295 -0
- package/docs/cli/configure.md +36 -0
- package/docs/cli/cron.md +77 -0
- package/docs/cli/daemon.md +53 -0
- package/docs/cli/dashboard.md +22 -0
- package/docs/cli/devices.md +139 -0
- package/docs/cli/directory.md +63 -0
- package/docs/cli/dns.md +23 -0
- package/docs/cli/docs.md +15 -0
- package/docs/cli/doctor.md +48 -0
- package/docs/cli/gateway.md +235 -0
- package/docs/cli/health.md +21 -0
- package/docs/cli/hooks.md +318 -0
- package/docs/cli/index.md +1147 -0
- package/docs/cli/logs.md +28 -0
- package/docs/cli/memory.md +66 -0
- package/docs/cli/message.md +278 -0
- package/docs/cli/models.md +81 -0
- package/docs/cli/node.md +127 -0
- package/docs/cli/nodes.md +75 -0
- package/docs/cli/onboard.md +157 -0
- package/docs/cli/pairing.md +32 -0
- package/docs/cli/plugins.md +186 -0
- package/docs/cli/qr.md +46 -0
- package/docs/cli/reset.md +20 -0
- package/docs/cli/sandbox.md +197 -0
- package/docs/cli/secrets.md +188 -0
- package/docs/cli/security.md +79 -0
- package/docs/cli/sessions.md +110 -0
- package/docs/cli/setup.md +29 -0
- package/docs/cli/skills.md +26 -0
- package/docs/cli/status.md +30 -0
- package/docs/cli/system.md +60 -0
- package/docs/cli/tui.md +30 -0
- package/docs/cli/uninstall.md +20 -0
- package/docs/cli/update.md +103 -0
- package/docs/cli/voicecall.md +34 -0
- package/docs/cli/webhooks.md +25 -0
- package/docs/concepts/agent-loop.md +148 -0
- package/docs/concepts/agent-workspace.md +236 -0
- package/docs/concepts/agent.md +122 -0
- package/docs/concepts/architecture.md +137 -0
- package/docs/concepts/compaction.md +123 -0
- package/docs/concepts/context-engine.md +268 -0
- package/docs/concepts/context.md +172 -0
- package/docs/concepts/delegate-architecture.md +296 -0
- package/docs/concepts/features.md +73 -0
- package/docs/concepts/markdown-formatting.md +130 -0
- package/docs/concepts/memory.md +108 -0
- package/docs/concepts/messages.md +154 -0
- package/docs/concepts/model-failover.md +152 -0
- package/docs/concepts/model-providers.md +607 -0
- package/docs/concepts/models.md +225 -0
- package/docs/concepts/multi-agent.md +552 -0
- package/docs/concepts/oauth.md +158 -0
- package/docs/concepts/presence.md +102 -0
- package/docs/concepts/queue.md +89 -0
- package/docs/concepts/retry.md +69 -0
- package/docs/concepts/session-pruning.md +121 -0
- package/docs/concepts/session-tool.md +242 -0
- package/docs/concepts/session.md +310 -0
- package/docs/concepts/streaming.md +155 -0
- package/docs/concepts/system-prompt.md +132 -0
- package/docs/concepts/timezone.md +91 -0
- package/docs/concepts/typebox.md +291 -0
- package/docs/concepts/typing-indicators.md +68 -0
- package/docs/concepts/usage-tracking.md +35 -0
- package/docs/date-time.md +128 -0
- package/docs/debug/node-issue.md +85 -0
- package/docs/diagnostics/flags.md +91 -0
- package/docs/docs.json +2061 -0
- package/docs/gateway/authentication.md +179 -0
- package/docs/gateway/background-process.md +97 -0
- package/docs/gateway/bonjour.md +177 -0
- package/docs/gateway/bridge-protocol.md +91 -0
- package/docs/gateway/cli-backends.md +225 -0
- package/docs/gateway/configuration-examples.md +651 -0
- package/docs/gateway/configuration-reference.md +3123 -0
- package/docs/gateway/configuration.md +633 -0
- package/docs/gateway/discovery.md +123 -0
- package/docs/gateway/doctor.md +362 -0
- package/docs/gateway/gateway-lock.md +34 -0
- package/docs/gateway/health.md +44 -0
- package/docs/gateway/heartbeat.md +393 -0
- package/docs/gateway/index.md +261 -0
- package/docs/gateway/local-models.md +152 -0
- package/docs/gateway/logging.md +113 -0
- package/docs/gateway/multiple-gateways.md +112 -0
- package/docs/gateway/network-model.md +22 -0
- package/docs/gateway/openai-http-api.md +132 -0
- package/docs/gateway/openresponses-http-api.md +295 -0
- package/docs/gateway/openshell.md +307 -0
- package/docs/gateway/pairing.md +99 -0
- package/docs/gateway/protocol.md +267 -0
- package/docs/gateway/remote-gateway-readme.md +158 -0
- package/docs/gateway/remote.md +153 -0
- package/docs/gateway/sandbox-vs-tool-policy-vs-elevated.md +134 -0
- package/docs/gateway/sandboxing.md +469 -0
- package/docs/gateway/secrets-plan-contract.md +116 -0
- package/docs/gateway/secrets.md +503 -0
- package/docs/gateway/security/index.md +1213 -0
- package/docs/gateway/tailscale.md +132 -0
- package/docs/gateway/tools-invoke-http-api.md +110 -0
- package/docs/gateway/troubleshooting.md +378 -0
- package/docs/gateway/trusted-proxy-auth.md +330 -0
- package/docs/help/debugging.md +168 -0
- package/docs/help/environment.md +163 -0
- package/docs/help/faq.md +2999 -0
- package/docs/help/index.md +28 -0
- package/docs/help/scripts.md +28 -0
- package/docs/help/testing.md +524 -0
- package/docs/help/troubleshooting.md +297 -0
- package/docs/images/configure-model-picker-unsearchable.png +0 -0
- package/docs/images/feishu-step2-create-app.png +0 -0
- package/docs/images/feishu-step3-credentials.png +0 -0
- package/docs/images/feishu-step4-permissions.png +0 -0
- package/docs/images/feishu-step5-bot-capability.png +0 -0
- package/docs/images/feishu-step6-event-subscription.png +0 -0
- package/docs/images/feishu-verification-token.png +0 -0
- package/docs/images/groups-flow.svg +52 -0
- package/docs/images/mobile-ui-screenshot.png +0 -0
- package/docs/index.md +196 -0
- package/docs/install/ansible.md +230 -0
- package/docs/install/azure.md +311 -0
- package/docs/install/bun.md +55 -0
- package/docs/install/development-channels.md +120 -0
- package/docs/install/digitalocean.md +129 -0
- package/docs/install/docker-vm-runtime.md +142 -0
- package/docs/install/docker.md +375 -0
- package/docs/install/exe-dev.md +126 -0
- package/docs/install/fly.md +501 -0
- package/docs/install/gcp.md +402 -0
- package/docs/install/hetzner.md +251 -0
- package/docs/install/index.md +183 -0
- package/docs/install/installer.md +415 -0
- package/docs/install/kubernetes.md +191 -0
- package/docs/install/macos-vm.md +281 -0
- package/docs/install/migrating-matrix.md +346 -0
- package/docs/install/migrating.md +110 -0
- package/docs/install/nix.md +89 -0
- package/docs/install/node.md +138 -0
- package/docs/install/northflank.mdx +54 -0
- package/docs/install/oracle.md +156 -0
- package/docs/install/podman.md +133 -0
- package/docs/install/railway.mdx +100 -0
- package/docs/install/raspberry-pi.md +159 -0
- package/docs/install/render.mdx +169 -0
- package/docs/install/uninstall.md +128 -0
- package/docs/install/updating.md +128 -0
- package/docs/ja-JP/index.md +186 -0
- package/docs/ja-JP/start/getting-started.md +125 -0
- package/docs/ja-JP/start/wizard.md +77 -0
- package/docs/logging.md +352 -0
- package/docs/nav-tabs-underline.js +100 -0
- package/docs/network.md +54 -0
- package/docs/nodes/audio.md +187 -0
- package/docs/nodes/camera.md +162 -0
- package/docs/nodes/images.md +72 -0
- package/docs/nodes/index.md +393 -0
- package/docs/nodes/location-command.md +98 -0
- package/docs/nodes/media-understanding.md +394 -0
- package/docs/nodes/talk.md +92 -0
- package/docs/nodes/troubleshooting.md +114 -0
- package/docs/nodes/voicewake.md +66 -0
- package/docs/perplexity.md +174 -0
- package/docs/pi-dev.md +80 -0
- package/docs/pi.md +567 -0
- package/docs/platforms/android.md +168 -0
- package/docs/platforms/digitalocean.md +266 -0
- package/docs/platforms/index.md +54 -0
- package/docs/platforms/ios.md +220 -0
- package/docs/platforms/linux.md +94 -0
- package/docs/platforms/mac/bundled-gateway.md +73 -0
- package/docs/platforms/mac/canvas.md +125 -0
- package/docs/platforms/mac/child-process.md +69 -0
- package/docs/platforms/mac/dev-setup.md +104 -0
- package/docs/platforms/mac/health.md +34 -0
- package/docs/platforms/mac/icon.md +31 -0
- package/docs/platforms/mac/logging.md +57 -0
- package/docs/platforms/mac/menu-bar.md +81 -0
- package/docs/platforms/mac/peekaboo.md +65 -0
- package/docs/platforms/mac/permissions.md +50 -0
- package/docs/platforms/mac/remote.md +84 -0
- package/docs/platforms/mac/signing.md +47 -0
- package/docs/platforms/mac/skills.md +33 -0
- package/docs/platforms/mac/voice-overlay.md +60 -0
- package/docs/platforms/mac/voicewake.md +67 -0
- package/docs/platforms/mac/webchat.md +43 -0
- package/docs/platforms/mac/xpc.md +61 -0
- package/docs/platforms/macos.md +226 -0
- package/docs/platforms/oracle.md +303 -0
- package/docs/platforms/raspberry-pi.md +412 -0
- package/docs/platforms/windows.md +241 -0
- package/docs/plugins/agent-tools.md +10 -0
- package/docs/plugins/architecture.md +1363 -0
- package/docs/plugins/building-extensions.md +10 -0
- package/docs/plugins/building-plugins.md +376 -0
- package/docs/plugins/bundles.md +181 -0
- package/docs/plugins/community.md +141 -0
- package/docs/plugins/manifest.md +145 -0
- package/docs/plugins/sdk-migration.md +169 -0
- package/docs/plugins/voice-call.md +380 -0
- package/docs/plugins/zalouser.md +77 -0
- package/docs/prose.md +134 -0
- package/docs/providers/anthropic.md +259 -0
- package/docs/providers/bedrock.md +176 -0
- package/docs/providers/claude-max-api-proxy.md +154 -0
- package/docs/providers/cloudflare-ai-gateway.md +71 -0
- package/docs/providers/deepgram.md +93 -0
- package/docs/providers/github-copilot.md +72 -0
- package/docs/providers/glm.md +43 -0
- package/docs/providers/google.md +78 -0
- package/docs/providers/groq.md +96 -0
- package/docs/providers/huggingface.md +209 -0
- package/docs/providers/index.md +69 -0
- package/docs/providers/kilocode.md +74 -0
- package/docs/providers/litellm.md +154 -0
- package/docs/providers/minimax.md +224 -0
- package/docs/providers/mistral.md +54 -0
- package/docs/providers/models.md +45 -0
- package/docs/providers/modelstudio.md +66 -0
- package/docs/providers/moonshot.md +175 -0
- package/docs/providers/nvidia.md +55 -0
- package/docs/providers/ollama.md +352 -0
- package/docs/providers/openai.md +303 -0
- package/docs/providers/opencode-go.md +45 -0
- package/docs/providers/opencode.md +64 -0
- package/docs/providers/openrouter.md +37 -0
- package/docs/providers/perplexity-provider.md +62 -0
- package/docs/providers/qianfan.md +38 -0
- package/docs/providers/qwen.md +53 -0
- package/docs/providers/sglang.md +104 -0
- package/docs/providers/synthetic.md +99 -0
- package/docs/providers/together.md +66 -0
- package/docs/providers/venice.md +282 -0
- package/docs/providers/vercel-ai-gateway.md +60 -0
- package/docs/providers/vllm.md +92 -0
- package/docs/providers/volcengine.md +74 -0
- package/docs/providers/xai.md +60 -0
- package/docs/providers/xiaomi.md +86 -0
- package/docs/providers/zai.md +46 -0
- package/docs/reference/AGENTS.default.md +126 -0
- package/docs/reference/RELEASING.md +42 -0
- package/docs/reference/api-usage-costs.md +144 -0
- package/docs/reference/credits.md +30 -0
- package/docs/reference/device-models.md +47 -0
- package/docs/reference/memory-config.md +711 -0
- package/docs/reference/prompt-caching.md +185 -0
- package/docs/reference/rpc.md +43 -0
- package/docs/reference/secretref-credential-surface.md +140 -0
- package/docs/reference/secretref-user-supplied-credentials-matrix.json +563 -0
- package/docs/reference/session-management-compaction.md +324 -0
- package/docs/reference/templates/AGENTS.dev.md +83 -0
- package/docs/reference/templates/AGENTS.md +219 -0
- package/docs/reference/templates/BOOT.md +11 -0
- package/docs/reference/templates/BOOTSTRAP.md +62 -0
- package/docs/reference/templates/HEARTBEAT.md +14 -0
- package/docs/reference/templates/IDENTITY.dev.md +47 -0
- package/docs/reference/templates/IDENTITY.md +29 -0
- package/docs/reference/templates/SOUL.dev.md +76 -0
- package/docs/reference/templates/SOUL.md +43 -0
- package/docs/reference/templates/TOOLS.dev.md +24 -0
- package/docs/reference/templates/TOOLS.md +47 -0
- package/docs/reference/templates/USER.dev.md +18 -0
- package/docs/reference/templates/USER.md +23 -0
- package/docs/reference/test.md +90 -0
- package/docs/reference/token-use.md +175 -0
- package/docs/reference/transcript-hygiene.md +151 -0
- package/docs/reference/wizard.md +235 -0
- package/docs/security/CONTRIBUTING-THREAT-MODEL.md +98 -0
- package/docs/security/THREAT-MODEL-ATLAS.md +611 -0
- package/docs/security/formal-verification.md +167 -0
- package/docs/start/bootstrapping.md +41 -0
- package/docs/start/docs-directory.md +66 -0
- package/docs/start/getting-started.md +116 -0
- package/docs/start/hubs.md +198 -0
- package/docs/start/lore.md +219 -0
- package/docs/start/onboarding-overview.md +67 -0
- package/docs/start/onboarding.md +91 -0
- package/docs/start/openclaw.md +216 -0
- package/docs/start/quickstart.md +22 -0
- package/docs/start/setup.md +164 -0
- package/docs/start/showcase.md +418 -0
- package/docs/start/wizard-cli-automation.md +215 -0
- package/docs/start/wizard-cli-reference.md +299 -0
- package/docs/start/wizard.md +125 -0
- package/docs/style.css +37 -0
- package/docs/tools/acp-agents.md +623 -0
- package/docs/tools/agent-send.md +100 -0
- package/docs/tools/apply-patch.md +51 -0
- package/docs/tools/brave-search.md +93 -0
- package/docs/tools/browser-linux-troubleshooting.md +138 -0
- package/docs/tools/browser-login.md +73 -0
- package/docs/tools/browser-wsl2-windows-remote-cdp-troubleshooting.md +211 -0
- package/docs/tools/browser.md +731 -0
- package/docs/tools/btw.md +142 -0
- package/docs/tools/capability-cookbook.md +119 -0
- package/docs/tools/clawhub.md +257 -0
- package/docs/tools/creating-skills.md +117 -0
- package/docs/tools/diffs.md +386 -0
- package/docs/tools/elevated.md +114 -0
- package/docs/tools/exec-approvals.md +400 -0
- package/docs/tools/exec.md +204 -0
- package/docs/tools/firecrawl.md +140 -0
- package/docs/tools/index.md +137 -0
- package/docs/tools/llm-task.md +119 -0
- package/docs/tools/lobster.md +340 -0
- package/docs/tools/loop-detection.md +100 -0
- package/docs/tools/multi-agent-sandbox-tools.md +364 -0
- package/docs/tools/pdf.md +156 -0
- package/docs/tools/perplexity-search.md +174 -0
- package/docs/tools/plugin.md +251 -0
- package/docs/tools/reactions.md +64 -0
- package/docs/tools/skills-config.md +86 -0
- package/docs/tools/skills.md +306 -0
- package/docs/tools/slash-commands.md +294 -0
- package/docs/tools/subagents.md +295 -0
- package/docs/tools/tavily.md +125 -0
- package/docs/tools/thinking.md +96 -0
- package/docs/tools/tts.md +406 -0
- package/docs/tools/web.md +516 -0
- package/docs/tts.md +406 -0
- package/docs/vps.md +112 -0
- package/docs/web/control-ui.md +275 -0
- package/docs/web/dashboard.md +54 -0
- package/docs/web/index.md +120 -0
- package/docs/web/tui.md +170 -0
- package/docs/web/webchat.md +61 -0
- package/docs/whatsapp-openclaw-ai-zh.jpg +0 -0
- package/docs/whatsapp-openclaw.jpg +0 -0
- package/docs/zh-CN/AGENTS.md +61 -0
- package/docs/zh-CN/automation/auth-monitoring.md +47 -0
- package/docs/zh-CN/automation/cron-jobs.md +435 -0
- package/docs/zh-CN/automation/cron-vs-heartbeat.md +286 -0
- package/docs/zh-CN/automation/gmail-pubsub.md +249 -0
- package/docs/zh-CN/automation/hooks.md +1051 -0
- package/docs/zh-CN/automation/poll.md +76 -0
- package/docs/zh-CN/automation/troubleshooting.md +8 -0
- package/docs/zh-CN/automation/webhook.md +163 -0
- package/docs/zh-CN/brave-search.md +60 -0
- package/docs/zh-CN/channels/bluebubbles.md +354 -0
- package/docs/zh-CN/channels/broadcast-groups.md +449 -0
- package/docs/zh-CN/channels/channel-routing.md +117 -0
- package/docs/zh-CN/channels/discord.md +468 -0
- package/docs/zh-CN/channels/feishu.md +728 -0
- package/docs/zh-CN/channels/googlechat.md +257 -0
- package/docs/zh-CN/channels/grammy.md +38 -0
- package/docs/zh-CN/channels/group-messages.md +91 -0
- package/docs/zh-CN/channels/groups.md +379 -0
- package/docs/zh-CN/channels/imessage.md +302 -0
- package/docs/zh-CN/channels/index.md +53 -0
- package/docs/zh-CN/channels/line.md +180 -0
- package/docs/zh-CN/channels/location.md +63 -0
- package/docs/zh-CN/channels/matrix.md +221 -0
- package/docs/zh-CN/channels/mattermost.md +144 -0
- package/docs/zh-CN/channels/msteams.md +775 -0
- package/docs/zh-CN/channels/nextcloud-talk.md +142 -0
- package/docs/zh-CN/channels/nostr.md +249 -0
- package/docs/zh-CN/channels/pairing.md +89 -0
- package/docs/zh-CN/channels/signal.md +209 -0
- package/docs/zh-CN/channels/slack.md +531 -0
- package/docs/zh-CN/channels/synology-chat.md +138 -0
- package/docs/zh-CN/channels/telegram.md +751 -0
- package/docs/zh-CN/channels/tlon.md +136 -0
- package/docs/zh-CN/channels/troubleshooting.md +36 -0
- package/docs/zh-CN/channels/twitch.md +385 -0
- package/docs/zh-CN/channels/whatsapp.md +411 -0
- package/docs/zh-CN/channels/zalo.md +196 -0
- package/docs/zh-CN/channels/zalouser.md +147 -0
- package/docs/zh-CN/cli/acp.md +173 -0
- package/docs/zh-CN/cli/agent.md +30 -0
- package/docs/zh-CN/cli/agents.md +82 -0
- package/docs/zh-CN/cli/approvals.md +57 -0
- package/docs/zh-CN/cli/browser.md +114 -0
- package/docs/zh-CN/cli/channels.md +86 -0
- package/docs/zh-CN/cli/config.md +57 -0
- package/docs/zh-CN/cli/configure.md +38 -0
- package/docs/zh-CN/cli/cron.md +43 -0
- package/docs/zh-CN/cli/dashboard.md +23 -0
- package/docs/zh-CN/cli/devices.md +74 -0
- package/docs/zh-CN/cli/directory.md +70 -0
- package/docs/zh-CN/cli/dns.md +30 -0
- package/docs/zh-CN/cli/docs.md +22 -0
- package/docs/zh-CN/cli/doctor.md +48 -0
- package/docs/zh-CN/cli/gateway.md +206 -0
- package/docs/zh-CN/cli/health.md +28 -0
- package/docs/zh-CN/cli/hooks.md +298 -0
- package/docs/zh-CN/cli/index.md +1143 -0
- package/docs/zh-CN/cli/logs.md +31 -0
- package/docs/zh-CN/cli/memory.md +52 -0
- package/docs/zh-CN/cli/message.md +246 -0
- package/docs/zh-CN/cli/models.md +85 -0
- package/docs/zh-CN/cli/node.md +115 -0
- package/docs/zh-CN/cli/nodes.md +80 -0
- package/docs/zh-CN/cli/onboard.md +164 -0
- package/docs/zh-CN/cli/pairing.md +28 -0
- package/docs/zh-CN/cli/plugins.md +66 -0
- package/docs/zh-CN/cli/reset.md +24 -0
- package/docs/zh-CN/cli/sandbox.md +158 -0
- package/docs/zh-CN/cli/security.md +33 -0
- package/docs/zh-CN/cli/sessions.md +23 -0
- package/docs/zh-CN/cli/setup.md +36 -0
- package/docs/zh-CN/cli/skills.md +33 -0
- package/docs/zh-CN/cli/status.md +33 -0
- package/docs/zh-CN/cli/system.md +63 -0
- package/docs/zh-CN/cli/tui.md +30 -0
- package/docs/zh-CN/cli/uninstall.md +24 -0
- package/docs/zh-CN/cli/update.md +101 -0
- package/docs/zh-CN/cli/voicecall.md +41 -0
- package/docs/zh-CN/cli/webhooks.md +32 -0
- package/docs/zh-CN/concepts/agent-loop.md +146 -0
- package/docs/zh-CN/concepts/agent-workspace.md +219 -0
- package/docs/zh-CN/concepts/agent.md +115 -0
- package/docs/zh-CN/concepts/architecture.md +123 -0
- package/docs/zh-CN/concepts/compaction.md +67 -0
- package/docs/zh-CN/concepts/context.md +168 -0
- package/docs/zh-CN/concepts/features.md +59 -0
- package/docs/zh-CN/concepts/markdown-formatting.md +117 -0
- package/docs/zh-CN/concepts/memory.md +412 -0
- package/docs/zh-CN/concepts/messages.md +141 -0
- package/docs/zh-CN/concepts/model-failover.md +145 -0
- package/docs/zh-CN/concepts/model-providers.md +606 -0
- package/docs/zh-CN/concepts/models.md +225 -0
- package/docs/zh-CN/concepts/multi-agent.md +372 -0
- package/docs/zh-CN/concepts/oauth.md +164 -0
- package/docs/zh-CN/concepts/presence.md +99 -0
- package/docs/zh-CN/concepts/queue.md +94 -0
- package/docs/zh-CN/concepts/retry.md +76 -0
- package/docs/zh-CN/concepts/session-pruning.md +129 -0
- package/docs/zh-CN/concepts/session-tool.md +200 -0
- package/docs/zh-CN/concepts/session.md +166 -0
- package/docs/zh-CN/concepts/streaming.md +133 -0
- package/docs/zh-CN/concepts/system-prompt.md +101 -0
- package/docs/zh-CN/concepts/timezone.md +96 -0
- package/docs/zh-CN/concepts/typebox.md +284 -0
- package/docs/zh-CN/concepts/typing-indicators.md +74 -0
- package/docs/zh-CN/concepts/usage-tracking.md +42 -0
- package/docs/zh-CN/date-time.md +129 -0
- package/docs/zh-CN/debug/node-issue.md +90 -0
- package/docs/zh-CN/diagnostics/flags.md +98 -0
- package/docs/zh-CN/gateway/authentication.md +184 -0
- package/docs/zh-CN/gateway/background-process.md +100 -0
- package/docs/zh-CN/gateway/bonjour.md +174 -0
- package/docs/zh-CN/gateway/bridge-protocol.md +86 -0
- package/docs/zh-CN/gateway/cli-backends.md +213 -0
- package/docs/zh-CN/gateway/configuration-examples.md +587 -0
- package/docs/zh-CN/gateway/configuration-reference.md +3103 -0
- package/docs/zh-CN/gateway/configuration.md +640 -0
- package/docs/zh-CN/gateway/discovery.md +123 -0
- package/docs/zh-CN/gateway/doctor.md +238 -0
- package/docs/zh-CN/gateway/gateway-lock.md +41 -0
- package/docs/zh-CN/gateway/health.md +42 -0
- package/docs/zh-CN/gateway/heartbeat.md +274 -0
- package/docs/zh-CN/gateway/index.md +335 -0
- package/docs/zh-CN/gateway/local-models.md +159 -0
- package/docs/zh-CN/gateway/logging.md +114 -0
- package/docs/zh-CN/gateway/multiple-gateways.md +119 -0
- package/docs/zh-CN/gateway/network-model.md +23 -0
- package/docs/zh-CN/gateway/openai-http-api.md +125 -0
- package/docs/zh-CN/gateway/openresponses-http-api.md +317 -0
- package/docs/zh-CN/gateway/pairing.md +99 -0
- package/docs/zh-CN/gateway/protocol.md +220 -0
- package/docs/zh-CN/gateway/remote-gateway-readme.md +164 -0
- package/docs/zh-CN/gateway/remote.md +133 -0
- package/docs/zh-CN/gateway/sandbox-vs-tool-policy-vs-elevated.md +135 -0
- package/docs/zh-CN/gateway/sandboxing.md +188 -0
- package/docs/zh-CN/gateway/security/index.md +777 -0
- package/docs/zh-CN/gateway/tailscale.md +124 -0
- package/docs/zh-CN/gateway/tools-invoke-http-api.md +92 -0
- package/docs/zh-CN/gateway/troubleshooting.md +771 -0
- package/docs/zh-CN/help/debugging.md +160 -0
- package/docs/zh-CN/help/environment.md +88 -0
- package/docs/zh-CN/help/faq.md +2640 -0
- package/docs/zh-CN/help/index.md +28 -0
- package/docs/zh-CN/help/scripts.md +35 -0
- package/docs/zh-CN/help/testing.md +375 -0
- package/docs/zh-CN/help/troubleshooting.md +104 -0
- package/docs/zh-CN/index.md +186 -0
- package/docs/zh-CN/install/ansible.md +215 -0
- package/docs/zh-CN/install/bun.md +65 -0
- package/docs/zh-CN/install/development-channels.md +81 -0
- package/docs/zh-CN/install/docker.md +532 -0
- package/docs/zh-CN/install/exe-dev.md +133 -0
- package/docs/zh-CN/install/fly.md +490 -0
- package/docs/zh-CN/install/gcp.md +510 -0
- package/docs/zh-CN/install/hetzner.md +337 -0
- package/docs/zh-CN/install/index.md +235 -0
- package/docs/zh-CN/install/installer.md +422 -0
- package/docs/zh-CN/install/macos-vm.md +288 -0
- package/docs/zh-CN/install/migrating.md +199 -0
- package/docs/zh-CN/install/nix.md +99 -0
- package/docs/zh-CN/install/node.md +8 -0
- package/docs/zh-CN/install/northflank.mdx +60 -0
- package/docs/zh-CN/install/railway.mdx +106 -0
- package/docs/zh-CN/install/render.mdx +169 -0
- package/docs/zh-CN/install/uninstall.md +135 -0
- package/docs/zh-CN/install/updating.md +233 -0
- package/docs/zh-CN/logging.md +329 -0
- package/docs/zh-CN/network.md +59 -0
- package/docs/zh-CN/nodes/audio.md +120 -0
- package/docs/zh-CN/nodes/camera.md +162 -0
- package/docs/zh-CN/nodes/images.md +79 -0
- package/docs/zh-CN/nodes/index.md +348 -0
- package/docs/zh-CN/nodes/location-command.md +120 -0
- package/docs/zh-CN/nodes/media-understanding.md +380 -0
- package/docs/zh-CN/nodes/talk.md +97 -0
- package/docs/zh-CN/nodes/troubleshooting.md +8 -0
- package/docs/zh-CN/nodes/voicewake.md +72 -0
- package/docs/zh-CN/perplexity.md +102 -0
- package/docs/zh-CN/pi-dev.md +77 -0
- package/docs/zh-CN/pi.md +619 -0
- package/docs/zh-CN/platforms/android.md +155 -0
- package/docs/zh-CN/platforms/digitalocean.md +273 -0
- package/docs/zh-CN/platforms/index.md +60 -0
- package/docs/zh-CN/platforms/ios.md +114 -0
- package/docs/zh-CN/platforms/linux.md +100 -0
- package/docs/zh-CN/platforms/mac/bundled-gateway.md +75 -0
- package/docs/zh-CN/platforms/mac/canvas.md +128 -0
- package/docs/zh-CN/platforms/mac/child-process.md +73 -0
- package/docs/zh-CN/platforms/mac/dev-setup.md +109 -0
- package/docs/zh-CN/platforms/mac/health.md +41 -0
- package/docs/zh-CN/platforms/mac/icon.md +38 -0
- package/docs/zh-CN/platforms/mac/logging.md +64 -0
- package/docs/zh-CN/platforms/mac/menu-bar.md +88 -0
- package/docs/zh-CN/platforms/mac/peekaboo.md +62 -0
- package/docs/zh-CN/platforms/mac/permissions.md +46 -0
- package/docs/zh-CN/platforms/mac/remote.md +90 -0
- package/docs/zh-CN/platforms/mac/signing.md +54 -0
- package/docs/zh-CN/platforms/mac/skills.md +40 -0
- package/docs/zh-CN/platforms/mac/voice-overlay.md +67 -0
- package/docs/zh-CN/platforms/mac/voicewake.md +74 -0
- package/docs/zh-CN/platforms/mac/webchat.md +43 -0
- package/docs/zh-CN/platforms/mac/xpc.md +68 -0
- package/docs/zh-CN/platforms/macos.md +193 -0
- package/docs/zh-CN/platforms/oracle.md +310 -0
- package/docs/zh-CN/platforms/raspberry-pi.md +416 -0
- package/docs/zh-CN/platforms/windows.md +247 -0
- package/docs/zh-CN/plugins/agent-tools.md +99 -0
- package/docs/zh-CN/plugins/manifest.md +68 -0
- package/docs/zh-CN/plugins/voice-call.md +250 -0
- package/docs/zh-CN/plugins/zalouser.md +88 -0
- package/docs/zh-CN/prose.md +141 -0
- package/docs/zh-CN/providers/anthropic.md +265 -0
- package/docs/zh-CN/providers/bedrock.md +170 -0
- package/docs/zh-CN/providers/claude-max-api-proxy.md +155 -0
- package/docs/zh-CN/providers/cloudflare-ai-gateway.md +78 -0
- package/docs/zh-CN/providers/deepgram.md +97 -0
- package/docs/zh-CN/providers/github-copilot.md +67 -0
- package/docs/zh-CN/providers/glm.md +50 -0
- package/docs/zh-CN/providers/huggingface.md +216 -0
- package/docs/zh-CN/providers/index.md +69 -0
- package/docs/zh-CN/providers/kilocode.md +80 -0
- package/docs/zh-CN/providers/litellm.md +160 -0
- package/docs/zh-CN/providers/minimax.md +222 -0
- package/docs/zh-CN/providers/mistral.md +61 -0
- package/docs/zh-CN/providers/models.md +51 -0
- package/docs/zh-CN/providers/moonshot.md +182 -0
- package/docs/zh-CN/providers/nvidia.md +62 -0
- package/docs/zh-CN/providers/ollama.md +359 -0
- package/docs/zh-CN/providers/openai.md +308 -0
- package/docs/zh-CN/providers/opencode-go.md +52 -0
- package/docs/zh-CN/providers/opencode.md +71 -0
- package/docs/zh-CN/providers/openrouter.md +44 -0
- package/docs/zh-CN/providers/qianfan.md +45 -0
- package/docs/zh-CN/providers/qwen.md +55 -0
- package/docs/zh-CN/providers/sglang.md +111 -0
- package/docs/zh-CN/providers/synthetic.md +106 -0
- package/docs/zh-CN/providers/together.md +72 -0
- package/docs/zh-CN/providers/venice.md +289 -0
- package/docs/zh-CN/providers/vercel-ai-gateway.md +66 -0
- package/docs/zh-CN/providers/xiaomi.md +93 -0
- package/docs/zh-CN/providers/zai.md +53 -0
- package/docs/zh-CN/reference/AGENTS.default.md +131 -0
- package/docs/zh-CN/reference/RELEASING.md +48 -0
- package/docs/zh-CN/reference/api-usage-costs.md +141 -0
- package/docs/zh-CN/reference/credits.md +34 -0
- package/docs/zh-CN/reference/device-models.md +54 -0
- package/docs/zh-CN/reference/rpc.md +48 -0
- package/docs/zh-CN/reference/session-management-compaction.md +287 -0
- package/docs/zh-CN/reference/templates/AGENTS.dev.md +89 -0
- package/docs/zh-CN/reference/templates/AGENTS.md +225 -0
- package/docs/zh-CN/reference/templates/BOOT.md +17 -0
- package/docs/zh-CN/reference/templates/BOOTSTRAP.md +68 -0
- package/docs/zh-CN/reference/templates/HEARTBEAT.md +18 -0
- package/docs/zh-CN/reference/templates/IDENTITY.dev.md +54 -0
- package/docs/zh-CN/reference/templates/IDENTITY.md +36 -0
- package/docs/zh-CN/reference/templates/SOUL.dev.md +83 -0
- package/docs/zh-CN/reference/templates/SOUL.md +49 -0
- package/docs/zh-CN/reference/templates/TOOLS.dev.md +31 -0
- package/docs/zh-CN/reference/templates/TOOLS.md +53 -0
- package/docs/zh-CN/reference/templates/USER.dev.md +25 -0
- package/docs/zh-CN/reference/templates/USER.md +30 -0
- package/docs/zh-CN/reference/test.md +57 -0
- package/docs/zh-CN/reference/token-use.md +119 -0
- package/docs/zh-CN/reference/transcript-hygiene.md +109 -0
- package/docs/zh-CN/reference/wizard.md +242 -0
- package/docs/zh-CN/security/formal-verification.md +171 -0
- package/docs/zh-CN/start/bootstrapping.md +9 -0
- package/docs/zh-CN/start/docs-directory.md +70 -0
- package/docs/zh-CN/start/getting-started.md +143 -0
- package/docs/zh-CN/start/hubs.md +194 -0
- package/docs/zh-CN/start/lore.md +226 -0
- package/docs/zh-CN/start/onboarding-overview.md +58 -0
- package/docs/zh-CN/start/onboarding.md +105 -0
- package/docs/zh-CN/start/openclaw.md +248 -0
- package/docs/zh-CN/start/quickstart.md +88 -0
- package/docs/zh-CN/start/setup.md +153 -0
- package/docs/zh-CN/start/showcase.md +423 -0
- package/docs/zh-CN/start/wizard-cli-automation.md +222 -0
- package/docs/zh-CN/start/wizard-cli-reference.md +306 -0
- package/docs/zh-CN/start/wizard.md +132 -0
- package/docs/zh-CN/tools/agent-send.md +59 -0
- package/docs/zh-CN/tools/apply-patch.md +57 -0
- package/docs/zh-CN/tools/browser-linux-troubleshooting.md +144 -0
- package/docs/zh-CN/tools/browser-login.md +75 -0
- package/docs/zh-CN/tools/browser.md +553 -0
- package/docs/zh-CN/tools/chrome-extension.md +183 -0
- package/docs/zh-CN/tools/clawhub.md +209 -0
- package/docs/zh-CN/tools/creating-skills.md +61 -0
- package/docs/zh-CN/tools/elevated.md +64 -0
- package/docs/zh-CN/tools/exec-approvals.md +234 -0
- package/docs/zh-CN/tools/exec.md +169 -0
- package/docs/zh-CN/tools/firecrawl.md +68 -0
- package/docs/zh-CN/tools/index.md +515 -0
- package/docs/zh-CN/tools/llm-task.md +117 -0
- package/docs/zh-CN/tools/lobster.md +349 -0
- package/docs/zh-CN/tools/multi-agent-sandbox-tools.md +401 -0
- package/docs/zh-CN/tools/plugin.md +1612 -0
- package/docs/zh-CN/tools/reactions.md +29 -0
- package/docs/zh-CN/tools/skills-config.md +78 -0
- package/docs/zh-CN/tools/skills.md +279 -0
- package/docs/zh-CN/tools/slash-commands.md +205 -0
- package/docs/zh-CN/tools/subagents.md +167 -0
- package/docs/zh-CN/tools/thinking.md +80 -0
- package/docs/zh-CN/tools/web.md +289 -0
- package/docs/zh-CN/tts.md +375 -0
- package/docs/zh-CN/vps.md +47 -0
- package/docs/zh-CN/web/control-ui.md +191 -0
- package/docs/zh-CN/web/dashboard.md +53 -0
- package/docs/zh-CN/web/index.md +118 -0
- package/docs/zh-CN/web/tui.md +166 -0
- package/docs/zh-CN/web/webchat.md +56 -0
- package/openclaw.mjs +135 -0
- package/package.json +835 -0
- package/skills/1password/SKILL.md +70 -0
- package/skills/1password/references/cli-examples.md +29 -0
- package/skills/1password/references/get-started.md +17 -0
- package/skills/apple-notes/SKILL.md +77 -0
- package/skills/apple-reminders/SKILL.md +118 -0
- package/skills/bear-notes/SKILL.md +107 -0
- package/skills/blogwatcher/SKILL.md +69 -0
- package/skills/blucli/SKILL.md +47 -0
- package/skills/bluebubbles/SKILL.md +131 -0
- package/skills/camsnap/SKILL.md +45 -0
- package/skills/canvas/SKILL.md +198 -0
- package/skills/clawhub/SKILL.md +77 -0
- package/skills/coding-agent/SKILL.md +295 -0
- package/skills/discord/SKILL.md +197 -0
- package/skills/doubao-code/SKILL.md +43 -0
- package/skills/eightctl/SKILL.md +50 -0
- package/skills/gemini/SKILL.md +43 -0
- package/skills/gh-issues/SKILL.md +865 -0
- package/skills/gifgrep/SKILL.md +79 -0
- package/skills/github/SKILL.md +163 -0
- package/skills/gog/SKILL.md +116 -0
- package/skills/goplaces/SKILL.md +52 -0
- package/skills/healthcheck/SKILL.md +245 -0
- package/skills/himalaya/SKILL.md +257 -0
- package/skills/himalaya/references/configuration.md +184 -0
- package/skills/himalaya/references/message-composition.md +199 -0
- package/skills/imsg/SKILL.md +122 -0
- package/skills/kimi-code/SKILL.md +42 -0
- package/skills/mcporter/SKILL.md +61 -0
- package/skills/model-usage/SKILL.md +69 -0
- package/skills/model-usage/references/codexbar-cli.md +33 -0
- package/skills/model-usage/scripts/model_usage.py +320 -0
- package/skills/model-usage/scripts/test_model_usage.py +40 -0
- package/skills/nano-pdf/SKILL.md +38 -0
- package/skills/node-connect/SKILL.md +142 -0
- package/skills/notion/SKILL.md +174 -0
- package/skills/obsidian/SKILL.md +81 -0
- package/skills/openai-image-gen/SKILL.md +92 -0
- package/skills/openai-image-gen/scripts/gen.py +328 -0
- package/skills/openai-image-gen/scripts/test_gen.py +140 -0
- package/skills/openai-whisper/SKILL.md +38 -0
- package/skills/openai-whisper-api/SKILL.md +52 -0
- package/skills/openai-whisper-api/scripts/transcribe.sh +85 -0
- package/skills/openhue/SKILL.md +112 -0
- package/skills/oracle/SKILL.md +125 -0
- package/skills/ordercli/SKILL.md +78 -0
- package/skills/peekaboo/SKILL.md +190 -0
- package/skills/sag/SKILL.md +87 -0
- package/skills/session-logs/SKILL.md +115 -0
- package/skills/sherpa-onnx-tts/SKILL.md +103 -0
- package/skills/sherpa-onnx-tts/bin/sherpa-onnx-tts +178 -0
- package/skills/skill-creator/SKILL.md +372 -0
- package/skills/skill-creator/license.txt +202 -0
- package/skills/skill-creator/scripts/init_skill.py +378 -0
- package/skills/skill-creator/scripts/package_skill.py +139 -0
- package/skills/skill-creator/scripts/quick_validate.py +159 -0
- package/skills/skill-creator/scripts/test_package_skill.py +160 -0
- package/skills/skill-creator/scripts/test_quick_validate.py +72 -0
- package/skills/slack/SKILL.md +144 -0
- package/skills/songsee/SKILL.md +49 -0
- package/skills/sonoscli/SKILL.md +65 -0
- package/skills/spotify-player/SKILL.md +64 -0
- package/skills/summarize/SKILL.md +87 -0
- package/skills/things-mac/SKILL.md +86 -0
- package/skills/tmux/SKILL.md +153 -0
- package/skills/tmux/scripts/find-sessions.sh +112 -0
- package/skills/tmux/scripts/wait-for-text.sh +83 -0
- package/skills/trello/SKILL.md +95 -0
- package/skills/video-frames/SKILL.md +46 -0
- package/skills/video-frames/scripts/frame.sh +81 -0
- package/skills/voice-call/SKILL.md +45 -0
- package/skills/wacli/SKILL.md +72 -0
- package/skills/weather/SKILL.md +112 -0
- package/skills/xurl/SKILL.md +461 -0
|
@@ -0,0 +1,2664 @@
|
|
|
1
|
+
import { i as defineChannelPluginEntry } from "./core-C7aHA4Aq.js";
|
|
2
|
+
import { c as createFeishuClient, f as listEnabledFeishuAccounts, h as resolveFeishuAccount, i as parseFeishuConversationId, n as getFeishuThreadBindingManager, r as buildFeishuConversationId } from "./feishu-Dh5fEbh5.js";
|
|
3
|
+
import { c as registerFeishuChatTools, l as resolveToolsConfig } from "./reactions-BcC_XZqD.js";
|
|
4
|
+
import { i as normalizeFeishuTarget, n as setFeishuRuntime, t as getFeishuRuntime } from "./runtime-B66W9flm.js";
|
|
5
|
+
import { t as feishuPlugin } from "./channel-Ci3K8fI9.js";
|
|
6
|
+
import { existsSync, promises } from "node:fs";
|
|
7
|
+
import { basename, isAbsolute } from "node:path";
|
|
8
|
+
import { homedir } from "node:os";
|
|
9
|
+
import { Type } from "@sinclair/typebox";
|
|
10
|
+
//#region extensions/feishu/src/tool-account.ts
|
|
11
|
+
function normalizeOptionalAccountId(value) {
|
|
12
|
+
const trimmed = value?.trim();
|
|
13
|
+
return trimmed ? trimmed : void 0;
|
|
14
|
+
}
|
|
15
|
+
function readConfiguredDefaultAccountId(config) {
|
|
16
|
+
const value = (config?.channels?.feishu)?.defaultAccount;
|
|
17
|
+
if (typeof value !== "string") return;
|
|
18
|
+
return normalizeOptionalAccountId(value);
|
|
19
|
+
}
|
|
20
|
+
function resolveFeishuToolAccount(params) {
|
|
21
|
+
if (!params.api.config) throw new Error("Feishu config unavailable");
|
|
22
|
+
return resolveFeishuAccount({
|
|
23
|
+
cfg: params.api.config,
|
|
24
|
+
accountId: normalizeOptionalAccountId(params.executeParams?.accountId) ?? readConfiguredDefaultAccountId(params.api.config) ?? normalizeOptionalAccountId(params.defaultAccountId)
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
function createFeishuToolClient(params) {
|
|
28
|
+
return createFeishuClient(resolveFeishuToolAccount(params));
|
|
29
|
+
}
|
|
30
|
+
function resolveAnyEnabledFeishuToolsConfig(accounts) {
|
|
31
|
+
const merged = {
|
|
32
|
+
doc: false,
|
|
33
|
+
chat: false,
|
|
34
|
+
wiki: false,
|
|
35
|
+
drive: false,
|
|
36
|
+
perm: false,
|
|
37
|
+
scopes: false
|
|
38
|
+
};
|
|
39
|
+
for (const account of accounts) {
|
|
40
|
+
const cfg = resolveToolsConfig(account.config.tools);
|
|
41
|
+
merged.doc = merged.doc || cfg.doc;
|
|
42
|
+
merged.chat = merged.chat || cfg.chat;
|
|
43
|
+
merged.wiki = merged.wiki || cfg.wiki;
|
|
44
|
+
merged.drive = merged.drive || cfg.drive;
|
|
45
|
+
merged.perm = merged.perm || cfg.perm;
|
|
46
|
+
merged.scopes = merged.scopes || cfg.scopes;
|
|
47
|
+
}
|
|
48
|
+
return merged;
|
|
49
|
+
}
|
|
50
|
+
//#endregion
|
|
51
|
+
//#region extensions/feishu/src/bitable.ts
|
|
52
|
+
function json$1(data) {
|
|
53
|
+
return {
|
|
54
|
+
content: [{
|
|
55
|
+
type: "text",
|
|
56
|
+
text: JSON.stringify(data, null, 2)
|
|
57
|
+
}],
|
|
58
|
+
details: data
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
var LarkApiError = class extends Error {
|
|
62
|
+
constructor(code, message, api, context) {
|
|
63
|
+
super(`[${api}] code=${code} message=${message}`);
|
|
64
|
+
this.name = "LarkApiError";
|
|
65
|
+
this.code = code;
|
|
66
|
+
this.api = api;
|
|
67
|
+
this.context = context;
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
function ensureLarkSuccess(res, api, context) {
|
|
71
|
+
if (res.code !== 0) throw new LarkApiError(res.code ?? -1, res.msg ?? "unknown error", api, context);
|
|
72
|
+
}
|
|
73
|
+
/** Field type ID to human-readable name */
|
|
74
|
+
const FIELD_TYPE_NAMES = {
|
|
75
|
+
1: "Text",
|
|
76
|
+
2: "Number",
|
|
77
|
+
3: "SingleSelect",
|
|
78
|
+
4: "MultiSelect",
|
|
79
|
+
5: "DateTime",
|
|
80
|
+
7: "Checkbox",
|
|
81
|
+
11: "User",
|
|
82
|
+
13: "Phone",
|
|
83
|
+
15: "URL",
|
|
84
|
+
17: "Attachment",
|
|
85
|
+
18: "SingleLink",
|
|
86
|
+
19: "Lookup",
|
|
87
|
+
20: "Formula",
|
|
88
|
+
21: "DuplexLink",
|
|
89
|
+
22: "Location",
|
|
90
|
+
23: "GroupChat",
|
|
91
|
+
1001: "CreatedTime",
|
|
92
|
+
1002: "ModifiedTime",
|
|
93
|
+
1003: "CreatedUser",
|
|
94
|
+
1004: "ModifiedUser",
|
|
95
|
+
1005: "AutoNumber"
|
|
96
|
+
};
|
|
97
|
+
/** Parse bitable URL and extract tokens */
|
|
98
|
+
function parseBitableUrl(url) {
|
|
99
|
+
try {
|
|
100
|
+
const u = new URL(url);
|
|
101
|
+
const tableId = u.searchParams.get("table") ?? void 0;
|
|
102
|
+
const wikiMatch = u.pathname.match(/\/wiki\/([A-Za-z0-9]+)/);
|
|
103
|
+
if (wikiMatch) return {
|
|
104
|
+
token: wikiMatch[1],
|
|
105
|
+
tableId,
|
|
106
|
+
isWiki: true
|
|
107
|
+
};
|
|
108
|
+
const baseMatch = u.pathname.match(/\/base\/([A-Za-z0-9]+)/);
|
|
109
|
+
if (baseMatch) return {
|
|
110
|
+
token: baseMatch[1],
|
|
111
|
+
tableId,
|
|
112
|
+
isWiki: false
|
|
113
|
+
};
|
|
114
|
+
return null;
|
|
115
|
+
} catch {
|
|
116
|
+
return null;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
/** Get app_token from wiki node_token */
|
|
120
|
+
async function getAppTokenFromWiki(client, nodeToken) {
|
|
121
|
+
const res = await client.wiki.space.getNode({ params: { token: nodeToken } });
|
|
122
|
+
ensureLarkSuccess(res, "wiki.space.getNode", { nodeToken });
|
|
123
|
+
const node = res.data?.node;
|
|
124
|
+
if (!node) throw new Error("Node not found");
|
|
125
|
+
if (node.obj_type !== "bitable") throw new Error(`Node is not a bitable (type: ${node.obj_type})`);
|
|
126
|
+
return node.obj_token;
|
|
127
|
+
}
|
|
128
|
+
/** Get bitable metadata from URL (handles both /base/ and /wiki/ URLs) */
|
|
129
|
+
async function getBitableMeta(client, url) {
|
|
130
|
+
const parsed = parseBitableUrl(url);
|
|
131
|
+
if (!parsed) throw new Error("Invalid URL format. Expected /base/XXX or /wiki/XXX URL");
|
|
132
|
+
let appToken;
|
|
133
|
+
if (parsed.isWiki) appToken = await getAppTokenFromWiki(client, parsed.token);
|
|
134
|
+
else appToken = parsed.token;
|
|
135
|
+
const res = await client.bitable.app.get({ path: { app_token: appToken } });
|
|
136
|
+
ensureLarkSuccess(res, "bitable.app.get", { appToken });
|
|
137
|
+
let tables = [];
|
|
138
|
+
if (!parsed.tableId) {
|
|
139
|
+
const tablesRes = await client.bitable.appTable.list({ path: { app_token: appToken } });
|
|
140
|
+
if (tablesRes.code === 0) tables = (tablesRes.data?.items ?? []).map((t) => ({
|
|
141
|
+
table_id: t.table_id,
|
|
142
|
+
name: t.name
|
|
143
|
+
}));
|
|
144
|
+
}
|
|
145
|
+
return {
|
|
146
|
+
app_token: appToken,
|
|
147
|
+
table_id: parsed.tableId,
|
|
148
|
+
name: res.data?.app?.name,
|
|
149
|
+
url_type: parsed.isWiki ? "wiki" : "base",
|
|
150
|
+
...tables.length > 0 && { tables },
|
|
151
|
+
hint: parsed.tableId ? `Use app_token="${appToken}" and table_id="${parsed.tableId}" for other bitable tools` : `Use app_token="${appToken}" for other bitable tools. Select a table_id from the tables list.`
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
async function listFields(client, appToken, tableId) {
|
|
155
|
+
const res = await client.bitable.appTableField.list({ path: {
|
|
156
|
+
app_token: appToken,
|
|
157
|
+
table_id: tableId
|
|
158
|
+
} });
|
|
159
|
+
ensureLarkSuccess(res, "bitable.appTableField.list", {
|
|
160
|
+
appToken,
|
|
161
|
+
tableId
|
|
162
|
+
});
|
|
163
|
+
const fields = res.data?.items ?? [];
|
|
164
|
+
return {
|
|
165
|
+
fields: fields.map((f) => ({
|
|
166
|
+
field_id: f.field_id,
|
|
167
|
+
field_name: f.field_name,
|
|
168
|
+
type: f.type,
|
|
169
|
+
type_name: FIELD_TYPE_NAMES[f.type ?? 0] || `type_${f.type}`,
|
|
170
|
+
is_primary: f.is_primary,
|
|
171
|
+
...f.property && { property: f.property }
|
|
172
|
+
})),
|
|
173
|
+
total: fields.length
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
async function listRecords(client, appToken, tableId, pageSize, pageToken) {
|
|
177
|
+
const res = await client.bitable.appTableRecord.list({
|
|
178
|
+
path: {
|
|
179
|
+
app_token: appToken,
|
|
180
|
+
table_id: tableId
|
|
181
|
+
},
|
|
182
|
+
params: {
|
|
183
|
+
page_size: pageSize ?? 100,
|
|
184
|
+
...pageToken && { page_token: pageToken }
|
|
185
|
+
}
|
|
186
|
+
});
|
|
187
|
+
ensureLarkSuccess(res, "bitable.appTableRecord.list", {
|
|
188
|
+
appToken,
|
|
189
|
+
tableId,
|
|
190
|
+
pageSize
|
|
191
|
+
});
|
|
192
|
+
return {
|
|
193
|
+
records: res.data?.items ?? [],
|
|
194
|
+
has_more: res.data?.has_more ?? false,
|
|
195
|
+
page_token: res.data?.page_token,
|
|
196
|
+
total: res.data?.total
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
async function getRecord(client, appToken, tableId, recordId) {
|
|
200
|
+
const res = await client.bitable.appTableRecord.get({ path: {
|
|
201
|
+
app_token: appToken,
|
|
202
|
+
table_id: tableId,
|
|
203
|
+
record_id: recordId
|
|
204
|
+
} });
|
|
205
|
+
ensureLarkSuccess(res, "bitable.appTableRecord.get", {
|
|
206
|
+
appToken,
|
|
207
|
+
tableId,
|
|
208
|
+
recordId
|
|
209
|
+
});
|
|
210
|
+
return { record: res.data?.record };
|
|
211
|
+
}
|
|
212
|
+
async function createRecord(client, appToken, tableId, fields) {
|
|
213
|
+
const res = await client.bitable.appTableRecord.create({
|
|
214
|
+
path: {
|
|
215
|
+
app_token: appToken,
|
|
216
|
+
table_id: tableId
|
|
217
|
+
},
|
|
218
|
+
data: { fields }
|
|
219
|
+
});
|
|
220
|
+
ensureLarkSuccess(res, "bitable.appTableRecord.create", {
|
|
221
|
+
appToken,
|
|
222
|
+
tableId
|
|
223
|
+
});
|
|
224
|
+
return { record: res.data?.record };
|
|
225
|
+
}
|
|
226
|
+
/** Default field types created for new Bitable tables (to be cleaned up) */
|
|
227
|
+
const DEFAULT_CLEANUP_FIELD_TYPES = new Set([
|
|
228
|
+
3,
|
|
229
|
+
5,
|
|
230
|
+
17
|
|
231
|
+
]);
|
|
232
|
+
/** Clean up default placeholder rows and fields in a newly created Bitable table */
|
|
233
|
+
async function cleanupNewBitable(client, appToken, tableId, tableName, logger) {
|
|
234
|
+
let cleanedRows = 0;
|
|
235
|
+
let cleanedFields = 0;
|
|
236
|
+
const fieldsRes = await client.bitable.appTableField.list({ path: {
|
|
237
|
+
app_token: appToken,
|
|
238
|
+
table_id: tableId
|
|
239
|
+
} });
|
|
240
|
+
if (fieldsRes.code === 0 && fieldsRes.data?.items) {
|
|
241
|
+
const primaryField = fieldsRes.data.items.find((f) => f.is_primary);
|
|
242
|
+
if (primaryField?.field_id) try {
|
|
243
|
+
const newFieldName = tableName.length <= 20 ? tableName : "Name";
|
|
244
|
+
await client.bitable.appTableField.update({
|
|
245
|
+
path: {
|
|
246
|
+
app_token: appToken,
|
|
247
|
+
table_id: tableId,
|
|
248
|
+
field_id: primaryField.field_id
|
|
249
|
+
},
|
|
250
|
+
data: {
|
|
251
|
+
field_name: newFieldName,
|
|
252
|
+
type: 1
|
|
253
|
+
}
|
|
254
|
+
});
|
|
255
|
+
cleanedFields++;
|
|
256
|
+
} catch (err) {
|
|
257
|
+
logger.debug(`Failed to rename primary field: ${err}`);
|
|
258
|
+
}
|
|
259
|
+
const defaultFieldsToDelete = fieldsRes.data.items.filter((f) => !f.is_primary && DEFAULT_CLEANUP_FIELD_TYPES.has(f.type ?? 0));
|
|
260
|
+
for (const field of defaultFieldsToDelete) if (field.field_id) try {
|
|
261
|
+
await client.bitable.appTableField.delete({ path: {
|
|
262
|
+
app_token: appToken,
|
|
263
|
+
table_id: tableId,
|
|
264
|
+
field_id: field.field_id
|
|
265
|
+
} });
|
|
266
|
+
cleanedFields++;
|
|
267
|
+
} catch (err) {
|
|
268
|
+
logger.debug(`Failed to delete default field ${field.field_name}: ${err}`);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
const recordsRes = await client.bitable.appTableRecord.list({
|
|
272
|
+
path: {
|
|
273
|
+
app_token: appToken,
|
|
274
|
+
table_id: tableId
|
|
275
|
+
},
|
|
276
|
+
params: { page_size: 100 }
|
|
277
|
+
});
|
|
278
|
+
if (recordsRes.code === 0 && recordsRes.data?.items) {
|
|
279
|
+
const emptyRecordIds = recordsRes.data.items.filter((r) => !r.fields || Object.keys(r.fields).length === 0).map((r) => r.record_id).filter((id) => Boolean(id));
|
|
280
|
+
if (emptyRecordIds.length > 0) try {
|
|
281
|
+
await client.bitable.appTableRecord.batchDelete({
|
|
282
|
+
path: {
|
|
283
|
+
app_token: appToken,
|
|
284
|
+
table_id: tableId
|
|
285
|
+
},
|
|
286
|
+
data: { records: emptyRecordIds }
|
|
287
|
+
});
|
|
288
|
+
cleanedRows = emptyRecordIds.length;
|
|
289
|
+
} catch {
|
|
290
|
+
for (const recordId of emptyRecordIds) try {
|
|
291
|
+
await client.bitable.appTableRecord.delete({ path: {
|
|
292
|
+
app_token: appToken,
|
|
293
|
+
table_id: tableId,
|
|
294
|
+
record_id: recordId
|
|
295
|
+
} });
|
|
296
|
+
cleanedRows++;
|
|
297
|
+
} catch (err) {
|
|
298
|
+
logger.debug(`Failed to delete empty row ${recordId}: ${err}`);
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
return {
|
|
303
|
+
cleanedRows,
|
|
304
|
+
cleanedFields
|
|
305
|
+
};
|
|
306
|
+
}
|
|
307
|
+
async function createApp(client, name, folderToken, logger) {
|
|
308
|
+
const res = await client.bitable.app.create({ data: {
|
|
309
|
+
name,
|
|
310
|
+
...folderToken && { folder_token: folderToken }
|
|
311
|
+
} });
|
|
312
|
+
ensureLarkSuccess(res, "bitable.app.create", {
|
|
313
|
+
name,
|
|
314
|
+
folderToken
|
|
315
|
+
});
|
|
316
|
+
const appToken = res.data?.app?.app_token;
|
|
317
|
+
if (!appToken) throw new Error("Failed to create Bitable: no app_token returned");
|
|
318
|
+
const log = logger ?? {
|
|
319
|
+
debug: () => {},
|
|
320
|
+
warn: () => {}
|
|
321
|
+
};
|
|
322
|
+
let tableId;
|
|
323
|
+
let cleanedRows = 0;
|
|
324
|
+
let cleanedFields = 0;
|
|
325
|
+
try {
|
|
326
|
+
const tablesRes = await client.bitable.appTable.list({ path: { app_token: appToken } });
|
|
327
|
+
if (tablesRes.code === 0 && tablesRes.data?.items && tablesRes.data.items.length > 0) {
|
|
328
|
+
tableId = tablesRes.data.items[0].table_id ?? void 0;
|
|
329
|
+
if (tableId) {
|
|
330
|
+
const cleanup = await cleanupNewBitable(client, appToken, tableId, name, log);
|
|
331
|
+
cleanedRows = cleanup.cleanedRows;
|
|
332
|
+
cleanedFields = cleanup.cleanedFields;
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
} catch (err) {
|
|
336
|
+
log.debug(`Cleanup failed (non-critical): ${err}`);
|
|
337
|
+
}
|
|
338
|
+
return {
|
|
339
|
+
app_token: appToken,
|
|
340
|
+
table_id: tableId,
|
|
341
|
+
name: res.data?.app?.name,
|
|
342
|
+
url: res.data?.app?.url,
|
|
343
|
+
cleaned_placeholder_rows: cleanedRows,
|
|
344
|
+
cleaned_default_fields: cleanedFields,
|
|
345
|
+
hint: tableId ? `Table created. Use app_token="${appToken}" and table_id="${tableId}" for other bitable tools.` : "Table created. Use feishu_bitable_get_meta to get table_id and field details."
|
|
346
|
+
};
|
|
347
|
+
}
|
|
348
|
+
async function createField(client, appToken, tableId, fieldName, fieldType, property) {
|
|
349
|
+
const res = await client.bitable.appTableField.create({
|
|
350
|
+
path: {
|
|
351
|
+
app_token: appToken,
|
|
352
|
+
table_id: tableId
|
|
353
|
+
},
|
|
354
|
+
data: {
|
|
355
|
+
field_name: fieldName,
|
|
356
|
+
type: fieldType,
|
|
357
|
+
...property && { property }
|
|
358
|
+
}
|
|
359
|
+
});
|
|
360
|
+
ensureLarkSuccess(res, "bitable.appTableField.create", {
|
|
361
|
+
appToken,
|
|
362
|
+
tableId,
|
|
363
|
+
fieldName,
|
|
364
|
+
fieldType
|
|
365
|
+
});
|
|
366
|
+
return {
|
|
367
|
+
field_id: res.data?.field?.field_id,
|
|
368
|
+
field_name: res.data?.field?.field_name,
|
|
369
|
+
type: res.data?.field?.type,
|
|
370
|
+
type_name: FIELD_TYPE_NAMES[res.data?.field?.type ?? 0] || `type_${res.data?.field?.type}`
|
|
371
|
+
};
|
|
372
|
+
}
|
|
373
|
+
async function updateRecord(client, appToken, tableId, recordId, fields) {
|
|
374
|
+
const res = await client.bitable.appTableRecord.update({
|
|
375
|
+
path: {
|
|
376
|
+
app_token: appToken,
|
|
377
|
+
table_id: tableId,
|
|
378
|
+
record_id: recordId
|
|
379
|
+
},
|
|
380
|
+
data: { fields }
|
|
381
|
+
});
|
|
382
|
+
ensureLarkSuccess(res, "bitable.appTableRecord.update", {
|
|
383
|
+
appToken,
|
|
384
|
+
tableId,
|
|
385
|
+
recordId
|
|
386
|
+
});
|
|
387
|
+
return { record: res.data?.record };
|
|
388
|
+
}
|
|
389
|
+
const GetMetaSchema = Type.Object({ url: Type.String({ description: "Bitable URL. Supports both formats: /base/XXX?table=YYY or /wiki/XXX?table=YYY" }) });
|
|
390
|
+
const ListFieldsSchema = Type.Object({
|
|
391
|
+
app_token: Type.String({ description: "Bitable app token (use feishu_bitable_get_meta to get from URL)" }),
|
|
392
|
+
table_id: Type.String({ description: "Table ID (from URL: ?table=YYY)" })
|
|
393
|
+
});
|
|
394
|
+
const ListRecordsSchema = Type.Object({
|
|
395
|
+
app_token: Type.String({ description: "Bitable app token (use feishu_bitable_get_meta to get from URL)" }),
|
|
396
|
+
table_id: Type.String({ description: "Table ID (from URL: ?table=YYY)" }),
|
|
397
|
+
page_size: Type.Optional(Type.Number({
|
|
398
|
+
description: "Number of records per page (1-500, default 100)",
|
|
399
|
+
minimum: 1,
|
|
400
|
+
maximum: 500
|
|
401
|
+
})),
|
|
402
|
+
page_token: Type.Optional(Type.String({ description: "Pagination token from previous response" }))
|
|
403
|
+
});
|
|
404
|
+
const GetRecordSchema = Type.Object({
|
|
405
|
+
app_token: Type.String({ description: "Bitable app token (use feishu_bitable_get_meta to get from URL)" }),
|
|
406
|
+
table_id: Type.String({ description: "Table ID (from URL: ?table=YYY)" }),
|
|
407
|
+
record_id: Type.String({ description: "Record ID to retrieve" })
|
|
408
|
+
});
|
|
409
|
+
const CreateRecordSchema = Type.Object({
|
|
410
|
+
app_token: Type.String({ description: "Bitable app token (use feishu_bitable_get_meta to get from URL)" }),
|
|
411
|
+
table_id: Type.String({ description: "Table ID (from URL: ?table=YYY)" }),
|
|
412
|
+
fields: Type.Record(Type.String(), Type.Any(), { description: "Field values keyed by field name. Format by type: Text='string', Number=123, SingleSelect='Option', MultiSelect=['A','B'], DateTime=timestamp_ms, User=[{id:'ou_xxx'}], URL={text:'Display',link:'https://...'}" })
|
|
413
|
+
});
|
|
414
|
+
const CreateAppSchema = Type.Object({
|
|
415
|
+
name: Type.String({ description: "Name for the new Bitable application" }),
|
|
416
|
+
folder_token: Type.Optional(Type.String({ description: "Optional folder token to place the Bitable in a specific folder" }))
|
|
417
|
+
});
|
|
418
|
+
const CreateFieldSchema = Type.Object({
|
|
419
|
+
app_token: Type.String({ description: "Bitable app token (use feishu_bitable_get_meta to get from URL, or feishu_bitable_create_app to create new)" }),
|
|
420
|
+
table_id: Type.String({ description: "Table ID (from URL: ?table=YYY)" }),
|
|
421
|
+
field_name: Type.String({ description: "Name for the new field" }),
|
|
422
|
+
field_type: Type.Number({
|
|
423
|
+
description: "Field type ID: 1=Text, 2=Number, 3=SingleSelect, 4=MultiSelect, 5=DateTime, 7=Checkbox, 11=User, 13=Phone, 15=URL, 17=Attachment, 18=SingleLink, 19=Lookup, 20=Formula, 21=DuplexLink, 22=Location, 23=GroupChat, 1001=CreatedTime, 1002=ModifiedTime, 1003=CreatedUser, 1004=ModifiedUser, 1005=AutoNumber",
|
|
424
|
+
minimum: 1
|
|
425
|
+
}),
|
|
426
|
+
property: Type.Optional(Type.Record(Type.String(), Type.Any(), { description: "Field-specific properties (e.g., options for SingleSelect, format for Number)" }))
|
|
427
|
+
});
|
|
428
|
+
const UpdateRecordSchema = Type.Object({
|
|
429
|
+
app_token: Type.String({ description: "Bitable app token (use feishu_bitable_get_meta to get from URL)" }),
|
|
430
|
+
table_id: Type.String({ description: "Table ID (from URL: ?table=YYY)" }),
|
|
431
|
+
record_id: Type.String({ description: "Record ID to update" }),
|
|
432
|
+
fields: Type.Record(Type.String(), Type.Any(), { description: "Field values to update (same format as create_record)" })
|
|
433
|
+
});
|
|
434
|
+
function registerFeishuBitableTools(api) {
|
|
435
|
+
if (!api.config) {
|
|
436
|
+
api.logger.debug?.("feishu_bitable: No config available, skipping bitable tools");
|
|
437
|
+
return;
|
|
438
|
+
}
|
|
439
|
+
if (listEnabledFeishuAccounts(api.config).length === 0) {
|
|
440
|
+
api.logger.debug?.("feishu_bitable: No Feishu accounts configured, skipping bitable tools");
|
|
441
|
+
return;
|
|
442
|
+
}
|
|
443
|
+
const getClient = (params, defaultAccountId) => createFeishuToolClient({
|
|
444
|
+
api,
|
|
445
|
+
executeParams: params,
|
|
446
|
+
defaultAccountId
|
|
447
|
+
});
|
|
448
|
+
const registerBitableTool = (params) => {
|
|
449
|
+
api.registerTool((ctx) => ({
|
|
450
|
+
name: params.name,
|
|
451
|
+
label: params.label,
|
|
452
|
+
description: params.description,
|
|
453
|
+
parameters: params.parameters,
|
|
454
|
+
async execute(_toolCallId, rawParams) {
|
|
455
|
+
try {
|
|
456
|
+
return json$1(await params.execute({
|
|
457
|
+
params: rawParams,
|
|
458
|
+
defaultAccountId: ctx.agentAccountId
|
|
459
|
+
}));
|
|
460
|
+
} catch (err) {
|
|
461
|
+
return json$1({ error: err instanceof Error ? err.message : String(err) });
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
}), { name: params.name });
|
|
465
|
+
};
|
|
466
|
+
registerBitableTool({
|
|
467
|
+
name: "feishu_bitable_get_meta",
|
|
468
|
+
label: "Feishu Bitable Get Meta",
|
|
469
|
+
description: "Parse a Bitable URL and get app_token, table_id, and table list. Use this first when given a /wiki/ or /base/ URL.",
|
|
470
|
+
parameters: GetMetaSchema,
|
|
471
|
+
async execute({ params, defaultAccountId }) {
|
|
472
|
+
return getBitableMeta(getClient(params, defaultAccountId), params.url);
|
|
473
|
+
}
|
|
474
|
+
});
|
|
475
|
+
registerBitableTool({
|
|
476
|
+
name: "feishu_bitable_list_fields",
|
|
477
|
+
label: "Feishu Bitable List Fields",
|
|
478
|
+
description: "List all fields (columns) in a Bitable table with their types and properties",
|
|
479
|
+
parameters: ListFieldsSchema,
|
|
480
|
+
async execute({ params, defaultAccountId }) {
|
|
481
|
+
return listFields(getClient(params, defaultAccountId), params.app_token, params.table_id);
|
|
482
|
+
}
|
|
483
|
+
});
|
|
484
|
+
registerBitableTool({
|
|
485
|
+
name: "feishu_bitable_list_records",
|
|
486
|
+
label: "Feishu Bitable List Records",
|
|
487
|
+
description: "List records (rows) from a Bitable table with pagination support",
|
|
488
|
+
parameters: ListRecordsSchema,
|
|
489
|
+
async execute({ params, defaultAccountId }) {
|
|
490
|
+
return listRecords(getClient(params, defaultAccountId), params.app_token, params.table_id, params.page_size, params.page_token);
|
|
491
|
+
}
|
|
492
|
+
});
|
|
493
|
+
registerBitableTool({
|
|
494
|
+
name: "feishu_bitable_get_record",
|
|
495
|
+
label: "Feishu Bitable Get Record",
|
|
496
|
+
description: "Get a single record by ID from a Bitable table",
|
|
497
|
+
parameters: GetRecordSchema,
|
|
498
|
+
async execute({ params, defaultAccountId }) {
|
|
499
|
+
return getRecord(getClient(params, defaultAccountId), params.app_token, params.table_id, params.record_id);
|
|
500
|
+
}
|
|
501
|
+
});
|
|
502
|
+
registerBitableTool({
|
|
503
|
+
name: "feishu_bitable_create_record",
|
|
504
|
+
label: "Feishu Bitable Create Record",
|
|
505
|
+
description: "Create a new record (row) in a Bitable table",
|
|
506
|
+
parameters: CreateRecordSchema,
|
|
507
|
+
async execute({ params, defaultAccountId }) {
|
|
508
|
+
return createRecord(getClient(params, defaultAccountId), params.app_token, params.table_id, params.fields);
|
|
509
|
+
}
|
|
510
|
+
});
|
|
511
|
+
registerBitableTool({
|
|
512
|
+
name: "feishu_bitable_update_record",
|
|
513
|
+
label: "Feishu Bitable Update Record",
|
|
514
|
+
description: "Update an existing record (row) in a Bitable table",
|
|
515
|
+
parameters: UpdateRecordSchema,
|
|
516
|
+
async execute({ params, defaultAccountId }) {
|
|
517
|
+
return updateRecord(getClient(params, defaultAccountId), params.app_token, params.table_id, params.record_id, params.fields);
|
|
518
|
+
}
|
|
519
|
+
});
|
|
520
|
+
registerBitableTool({
|
|
521
|
+
name: "feishu_bitable_create_app",
|
|
522
|
+
label: "Feishu Bitable Create App",
|
|
523
|
+
description: "Create a new Bitable (multidimensional table) application",
|
|
524
|
+
parameters: CreateAppSchema,
|
|
525
|
+
async execute({ params, defaultAccountId }) {
|
|
526
|
+
return createApp(getClient(params, defaultAccountId), params.name, params.folder_token, {
|
|
527
|
+
debug: (msg) => api.logger.debug?.(msg),
|
|
528
|
+
warn: (msg) => api.logger.warn?.(msg)
|
|
529
|
+
});
|
|
530
|
+
}
|
|
531
|
+
});
|
|
532
|
+
registerBitableTool({
|
|
533
|
+
name: "feishu_bitable_create_field",
|
|
534
|
+
label: "Feishu Bitable Create Field",
|
|
535
|
+
description: "Create a new field (column) in a Bitable table",
|
|
536
|
+
parameters: CreateFieldSchema,
|
|
537
|
+
async execute({ params, defaultAccountId }) {
|
|
538
|
+
return createField(getClient(params, defaultAccountId), params.app_token, params.table_id, params.field_name, params.field_type, params.property);
|
|
539
|
+
}
|
|
540
|
+
});
|
|
541
|
+
api.logger.info?.("feishu_bitable: Registered bitable tools");
|
|
542
|
+
}
|
|
543
|
+
//#endregion
|
|
544
|
+
//#region extensions/feishu/src/doc-schema.ts
|
|
545
|
+
const tableCreationProperties = {
|
|
546
|
+
doc_token: Type.String({ description: "Document token" }),
|
|
547
|
+
parent_block_id: Type.Optional(Type.String({ description: "Parent block ID (default: document root)" })),
|
|
548
|
+
row_size: Type.Integer({
|
|
549
|
+
description: "Table row count",
|
|
550
|
+
minimum: 1
|
|
551
|
+
}),
|
|
552
|
+
column_size: Type.Integer({
|
|
553
|
+
description: "Table column count",
|
|
554
|
+
minimum: 1
|
|
555
|
+
}),
|
|
556
|
+
column_width: Type.Optional(Type.Array(Type.Number({ minimum: 1 }), { description: "Column widths in px (length should match column_size)" }))
|
|
557
|
+
};
|
|
558
|
+
const FeishuDocSchema = Type.Union([
|
|
559
|
+
Type.Object({
|
|
560
|
+
action: Type.Literal("read"),
|
|
561
|
+
doc_token: Type.String({ description: "Document token (extract from URL /docx/XXX)" })
|
|
562
|
+
}),
|
|
563
|
+
Type.Object({
|
|
564
|
+
action: Type.Literal("write"),
|
|
565
|
+
doc_token: Type.String({ description: "Document token" }),
|
|
566
|
+
content: Type.String({ description: "Markdown content to write (replaces entire document content)" })
|
|
567
|
+
}),
|
|
568
|
+
Type.Object({
|
|
569
|
+
action: Type.Literal("append"),
|
|
570
|
+
doc_token: Type.String({ description: "Document token" }),
|
|
571
|
+
content: Type.String({ description: "Markdown content to append to end of document" })
|
|
572
|
+
}),
|
|
573
|
+
Type.Object({
|
|
574
|
+
action: Type.Literal("insert"),
|
|
575
|
+
doc_token: Type.String({ description: "Document token" }),
|
|
576
|
+
content: Type.String({ description: "Markdown content to insert" }),
|
|
577
|
+
after_block_id: Type.String({ description: "Insert content after this block ID. Use list_blocks to find block IDs." })
|
|
578
|
+
}),
|
|
579
|
+
Type.Object({
|
|
580
|
+
action: Type.Literal("create"),
|
|
581
|
+
title: Type.String({ description: "Document title" }),
|
|
582
|
+
folder_token: Type.Optional(Type.String({ description: "Target folder token (optional)" })),
|
|
583
|
+
grant_to_requester: Type.Optional(Type.Boolean({ description: "Grant edit permission to the trusted requesting Feishu user from runtime context (default: true)." }))
|
|
584
|
+
}),
|
|
585
|
+
Type.Object({
|
|
586
|
+
action: Type.Literal("list_blocks"),
|
|
587
|
+
doc_token: Type.String({ description: "Document token" })
|
|
588
|
+
}),
|
|
589
|
+
Type.Object({
|
|
590
|
+
action: Type.Literal("get_block"),
|
|
591
|
+
doc_token: Type.String({ description: "Document token" }),
|
|
592
|
+
block_id: Type.String({ description: "Block ID (from list_blocks)" })
|
|
593
|
+
}),
|
|
594
|
+
Type.Object({
|
|
595
|
+
action: Type.Literal("update_block"),
|
|
596
|
+
doc_token: Type.String({ description: "Document token" }),
|
|
597
|
+
block_id: Type.String({ description: "Block ID (from list_blocks)" }),
|
|
598
|
+
content: Type.String({ description: "New text content" })
|
|
599
|
+
}),
|
|
600
|
+
Type.Object({
|
|
601
|
+
action: Type.Literal("delete_block"),
|
|
602
|
+
doc_token: Type.String({ description: "Document token" }),
|
|
603
|
+
block_id: Type.String({ description: "Block ID" })
|
|
604
|
+
}),
|
|
605
|
+
Type.Object({
|
|
606
|
+
action: Type.Literal("create_table"),
|
|
607
|
+
...tableCreationProperties
|
|
608
|
+
}),
|
|
609
|
+
Type.Object({
|
|
610
|
+
action: Type.Literal("write_table_cells"),
|
|
611
|
+
doc_token: Type.String({ description: "Document token" }),
|
|
612
|
+
table_block_id: Type.String({ description: "Table block ID" }),
|
|
613
|
+
values: Type.Array(Type.Array(Type.String()), {
|
|
614
|
+
description: "2D matrix values[row][col] to write into table cells",
|
|
615
|
+
minItems: 1
|
|
616
|
+
})
|
|
617
|
+
}),
|
|
618
|
+
Type.Object({
|
|
619
|
+
action: Type.Literal("create_table_with_values"),
|
|
620
|
+
...tableCreationProperties,
|
|
621
|
+
values: Type.Array(Type.Array(Type.String()), {
|
|
622
|
+
description: "2D matrix values[row][col] to write into table cells",
|
|
623
|
+
minItems: 1
|
|
624
|
+
})
|
|
625
|
+
}),
|
|
626
|
+
Type.Object({
|
|
627
|
+
action: Type.Literal("insert_table_row"),
|
|
628
|
+
doc_token: Type.String({ description: "Document token" }),
|
|
629
|
+
block_id: Type.String({ description: "Table block ID" }),
|
|
630
|
+
row_index: Type.Optional(Type.Number({ description: "Row index to insert at (-1 for end, default: -1)" }))
|
|
631
|
+
}),
|
|
632
|
+
Type.Object({
|
|
633
|
+
action: Type.Literal("insert_table_column"),
|
|
634
|
+
doc_token: Type.String({ description: "Document token" }),
|
|
635
|
+
block_id: Type.String({ description: "Table block ID" }),
|
|
636
|
+
column_index: Type.Optional(Type.Number({ description: "Column index to insert at (-1 for end, default: -1)" }))
|
|
637
|
+
}),
|
|
638
|
+
Type.Object({
|
|
639
|
+
action: Type.Literal("delete_table_rows"),
|
|
640
|
+
doc_token: Type.String({ description: "Document token" }),
|
|
641
|
+
block_id: Type.String({ description: "Table block ID" }),
|
|
642
|
+
row_start: Type.Number({ description: "Start row index (0-based)" }),
|
|
643
|
+
row_count: Type.Optional(Type.Number({ description: "Number of rows to delete (default: 1)" }))
|
|
644
|
+
}),
|
|
645
|
+
Type.Object({
|
|
646
|
+
action: Type.Literal("delete_table_columns"),
|
|
647
|
+
doc_token: Type.String({ description: "Document token" }),
|
|
648
|
+
block_id: Type.String({ description: "Table block ID" }),
|
|
649
|
+
column_start: Type.Number({ description: "Start column index (0-based)" }),
|
|
650
|
+
column_count: Type.Optional(Type.Number({ description: "Number of columns to delete (default: 1)" }))
|
|
651
|
+
}),
|
|
652
|
+
Type.Object({
|
|
653
|
+
action: Type.Literal("merge_table_cells"),
|
|
654
|
+
doc_token: Type.String({ description: "Document token" }),
|
|
655
|
+
block_id: Type.String({ description: "Table block ID" }),
|
|
656
|
+
row_start: Type.Number({ description: "Start row index" }),
|
|
657
|
+
row_end: Type.Number({ description: "End row index (exclusive)" }),
|
|
658
|
+
column_start: Type.Number({ description: "Start column index" }),
|
|
659
|
+
column_end: Type.Number({ description: "End column index (exclusive)" })
|
|
660
|
+
}),
|
|
661
|
+
Type.Object({
|
|
662
|
+
action: Type.Literal("upload_image"),
|
|
663
|
+
doc_token: Type.String({ description: "Document token" }),
|
|
664
|
+
url: Type.Optional(Type.String({ description: "Remote image URL (http/https)" })),
|
|
665
|
+
file_path: Type.Optional(Type.String({ description: "Local image file path" })),
|
|
666
|
+
image: Type.Optional(Type.String({ description: "Image as data URI (data:image/png;base64,...) or plain base64 string. Use instead of url/file_path for DALL-E outputs, canvas screenshots, etc." })),
|
|
667
|
+
parent_block_id: Type.Optional(Type.String({ description: "Parent block ID (default: document root)" })),
|
|
668
|
+
filename: Type.Optional(Type.String({ description: "Optional filename override" })),
|
|
669
|
+
index: Type.Optional(Type.Integer({
|
|
670
|
+
minimum: 0,
|
|
671
|
+
description: "Insert position (0-based index among siblings). Omit to append."
|
|
672
|
+
}))
|
|
673
|
+
}),
|
|
674
|
+
Type.Object({
|
|
675
|
+
action: Type.Literal("upload_file"),
|
|
676
|
+
doc_token: Type.String({ description: "Document token" }),
|
|
677
|
+
url: Type.Optional(Type.String({ description: "Remote file URL (http/https)" })),
|
|
678
|
+
file_path: Type.Optional(Type.String({ description: "Local file path" })),
|
|
679
|
+
parent_block_id: Type.Optional(Type.String({ description: "Parent block ID (default: document root)" })),
|
|
680
|
+
filename: Type.Optional(Type.String({ description: "Optional filename override" }))
|
|
681
|
+
}),
|
|
682
|
+
Type.Object({
|
|
683
|
+
action: Type.Literal("color_text"),
|
|
684
|
+
doc_token: Type.String({ description: "Document token" }),
|
|
685
|
+
block_id: Type.String({ description: "Text block ID to update" }),
|
|
686
|
+
content: Type.String({ description: "Text with color markup. Tags: [red], [green], [blue], [orange], [yellow], [purple], [grey], [bold], [bg:yellow]. Example: \"Revenue [green]+15%[/green] YoY\"" })
|
|
687
|
+
})
|
|
688
|
+
]);
|
|
689
|
+
//#endregion
|
|
690
|
+
//#region extensions/feishu/src/docx-table-ops.ts
|
|
691
|
+
const MIN_COLUMN_WIDTH = 50;
|
|
692
|
+
const MAX_COLUMN_WIDTH = 400;
|
|
693
|
+
const DEFAULT_TABLE_WIDTH = 730;
|
|
694
|
+
/**
|
|
695
|
+
* Calculate adaptive column widths based on cell content length.
|
|
696
|
+
*
|
|
697
|
+
* Algorithm:
|
|
698
|
+
* 1. For each column, find the max content length across all rows
|
|
699
|
+
* 2. Weight CJK characters as 2x width (they render wider)
|
|
700
|
+
* 3. Calculate proportional widths based on content length
|
|
701
|
+
* 4. Apply min/max constraints
|
|
702
|
+
* 5. Redistribute remaining space to fill total table width
|
|
703
|
+
*
|
|
704
|
+
* Total width is derived from the original column_width values returned
|
|
705
|
+
* by the Convert API, ensuring tables match Feishu's expected dimensions.
|
|
706
|
+
*
|
|
707
|
+
* @param blocks - Array of blocks from Convert API
|
|
708
|
+
* @param tableBlockId - The block_id of the table block
|
|
709
|
+
* @returns Array of column widths in pixels
|
|
710
|
+
*/
|
|
711
|
+
function calculateAdaptiveColumnWidths(blocks, tableBlockId) {
|
|
712
|
+
const tableBlock = blocks.find((b) => b.block_id === tableBlockId && b.block_type === 31);
|
|
713
|
+
if (!tableBlock?.table?.property) return [];
|
|
714
|
+
const { row_size, column_size, column_width: originalWidths } = tableBlock.table.property;
|
|
715
|
+
const totalWidth = originalWidths && originalWidths.length > 0 ? originalWidths.reduce((a, b) => a + b, 0) : DEFAULT_TABLE_WIDTH;
|
|
716
|
+
const cellIds = tableBlock.children || [];
|
|
717
|
+
const blockMap = /* @__PURE__ */ new Map();
|
|
718
|
+
for (const block of blocks) blockMap.set(block.block_id, block);
|
|
719
|
+
function getCellText(cellId) {
|
|
720
|
+
const cell = blockMap.get(cellId);
|
|
721
|
+
if (!cell?.children) return "";
|
|
722
|
+
let text = "";
|
|
723
|
+
const childIds = Array.isArray(cell.children) ? cell.children : [cell.children];
|
|
724
|
+
for (const childId of childIds) {
|
|
725
|
+
const child = blockMap.get(childId);
|
|
726
|
+
if (child?.text?.elements) {
|
|
727
|
+
for (const elem of child.text.elements) if (elem.text_run?.content) text += elem.text_run.content;
|
|
728
|
+
}
|
|
729
|
+
}
|
|
730
|
+
return text;
|
|
731
|
+
}
|
|
732
|
+
function getWeightedLength(text) {
|
|
733
|
+
return [...text].reduce((sum, char) => {
|
|
734
|
+
return sum + (char.charCodeAt(0) > 255 ? 2 : 1);
|
|
735
|
+
}, 0);
|
|
736
|
+
}
|
|
737
|
+
const maxLengths = new Array(column_size).fill(0);
|
|
738
|
+
for (let row = 0; row < row_size; row++) for (let col = 0; col < column_size; col++) {
|
|
739
|
+
const cellId = cellIds[row * column_size + col];
|
|
740
|
+
if (cellId) {
|
|
741
|
+
const length = getWeightedLength(getCellText(cellId));
|
|
742
|
+
maxLengths[col] = Math.max(maxLengths[col], length);
|
|
743
|
+
}
|
|
744
|
+
}
|
|
745
|
+
const totalLength = maxLengths.reduce((a, b) => a + b, 0);
|
|
746
|
+
if (totalLength === 0) {
|
|
747
|
+
const equalWidth = Math.max(MIN_COLUMN_WIDTH, Math.min(MAX_COLUMN_WIDTH, Math.floor(totalWidth / column_size)));
|
|
748
|
+
return new Array(column_size).fill(equalWidth);
|
|
749
|
+
}
|
|
750
|
+
let widths = maxLengths.map((len) => {
|
|
751
|
+
const proportion = len / totalLength;
|
|
752
|
+
return Math.round(proportion * totalWidth);
|
|
753
|
+
});
|
|
754
|
+
widths = widths.map((w) => Math.max(MIN_COLUMN_WIDTH, Math.min(MAX_COLUMN_WIDTH, w)));
|
|
755
|
+
let remaining = totalWidth - widths.reduce((a, b) => a + b, 0);
|
|
756
|
+
while (remaining > 0) {
|
|
757
|
+
const growable = widths.map((w, i) => w < MAX_COLUMN_WIDTH ? i : -1).filter((i) => i >= 0);
|
|
758
|
+
if (growable.length === 0) break;
|
|
759
|
+
const perColumn = Math.floor(remaining / growable.length);
|
|
760
|
+
if (perColumn === 0) break;
|
|
761
|
+
for (const i of growable) {
|
|
762
|
+
const add = Math.min(perColumn, MAX_COLUMN_WIDTH - widths[i]);
|
|
763
|
+
widths[i] += add;
|
|
764
|
+
remaining -= add;
|
|
765
|
+
}
|
|
766
|
+
}
|
|
767
|
+
return widths;
|
|
768
|
+
}
|
|
769
|
+
/**
|
|
770
|
+
* Clean blocks for Descendant API with adaptive column widths.
|
|
771
|
+
*
|
|
772
|
+
* - Removes parent_id from all blocks
|
|
773
|
+
* - Fixes children type (string → array) for TableCell blocks
|
|
774
|
+
* - Removes merge_info (read-only, causes API error)
|
|
775
|
+
* - Calculates and applies adaptive column_width for tables
|
|
776
|
+
*
|
|
777
|
+
* @param blocks - Array of blocks from Convert API
|
|
778
|
+
* @returns Cleaned blocks ready for Descendant API
|
|
779
|
+
*/
|
|
780
|
+
function cleanBlocksForDescendant(blocks) {
|
|
781
|
+
const tableWidths = /* @__PURE__ */ new Map();
|
|
782
|
+
for (const block of blocks) if (block.block_type === 31) {
|
|
783
|
+
const widths = calculateAdaptiveColumnWidths(blocks, block.block_id);
|
|
784
|
+
tableWidths.set(block.block_id, widths);
|
|
785
|
+
}
|
|
786
|
+
return blocks.map((block) => {
|
|
787
|
+
const { parent_id: _parentId, ...cleanBlock } = block;
|
|
788
|
+
if (cleanBlock.block_type === 32 && typeof cleanBlock.children === "string") cleanBlock.children = [cleanBlock.children];
|
|
789
|
+
if (cleanBlock.block_type === 31 && cleanBlock.table) {
|
|
790
|
+
const { cells: _cells, ...tableWithoutCells } = cleanBlock.table;
|
|
791
|
+
const { row_size, column_size } = tableWithoutCells.property || {};
|
|
792
|
+
const adaptiveWidths = tableWidths.get(block.block_id);
|
|
793
|
+
cleanBlock.table = { property: {
|
|
794
|
+
row_size,
|
|
795
|
+
column_size,
|
|
796
|
+
...adaptiveWidths?.length && { column_width: adaptiveWidths }
|
|
797
|
+
} };
|
|
798
|
+
}
|
|
799
|
+
return cleanBlock;
|
|
800
|
+
});
|
|
801
|
+
}
|
|
802
|
+
async function insertTableRow(client, docToken, blockId, rowIndex = -1) {
|
|
803
|
+
const res = await client.docx.documentBlock.patch({
|
|
804
|
+
path: {
|
|
805
|
+
document_id: docToken,
|
|
806
|
+
block_id: blockId
|
|
807
|
+
},
|
|
808
|
+
data: { insert_table_row: { row_index: rowIndex } }
|
|
809
|
+
});
|
|
810
|
+
if (res.code !== 0) throw new Error(res.msg);
|
|
811
|
+
return {
|
|
812
|
+
success: true,
|
|
813
|
+
block: res.data?.block
|
|
814
|
+
};
|
|
815
|
+
}
|
|
816
|
+
async function insertTableColumn(client, docToken, blockId, columnIndex = -1) {
|
|
817
|
+
const res = await client.docx.documentBlock.patch({
|
|
818
|
+
path: {
|
|
819
|
+
document_id: docToken,
|
|
820
|
+
block_id: blockId
|
|
821
|
+
},
|
|
822
|
+
data: { insert_table_column: { column_index: columnIndex } }
|
|
823
|
+
});
|
|
824
|
+
if (res.code !== 0) throw new Error(res.msg);
|
|
825
|
+
return {
|
|
826
|
+
success: true,
|
|
827
|
+
block: res.data?.block
|
|
828
|
+
};
|
|
829
|
+
}
|
|
830
|
+
async function deleteTableRows(client, docToken, blockId, rowStart, rowCount = 1) {
|
|
831
|
+
const res = await client.docx.documentBlock.patch({
|
|
832
|
+
path: {
|
|
833
|
+
document_id: docToken,
|
|
834
|
+
block_id: blockId
|
|
835
|
+
},
|
|
836
|
+
data: { delete_table_rows: {
|
|
837
|
+
row_start_index: rowStart,
|
|
838
|
+
row_end_index: rowStart + rowCount
|
|
839
|
+
} }
|
|
840
|
+
});
|
|
841
|
+
if (res.code !== 0) throw new Error(res.msg);
|
|
842
|
+
return {
|
|
843
|
+
success: true,
|
|
844
|
+
rows_deleted: rowCount,
|
|
845
|
+
block: res.data?.block
|
|
846
|
+
};
|
|
847
|
+
}
|
|
848
|
+
async function deleteTableColumns(client, docToken, blockId, columnStart, columnCount = 1) {
|
|
849
|
+
const res = await client.docx.documentBlock.patch({
|
|
850
|
+
path: {
|
|
851
|
+
document_id: docToken,
|
|
852
|
+
block_id: blockId
|
|
853
|
+
},
|
|
854
|
+
data: { delete_table_columns: {
|
|
855
|
+
column_start_index: columnStart,
|
|
856
|
+
column_end_index: columnStart + columnCount
|
|
857
|
+
} }
|
|
858
|
+
});
|
|
859
|
+
if (res.code !== 0) throw new Error(res.msg);
|
|
860
|
+
return {
|
|
861
|
+
success: true,
|
|
862
|
+
columns_deleted: columnCount,
|
|
863
|
+
block: res.data?.block
|
|
864
|
+
};
|
|
865
|
+
}
|
|
866
|
+
async function mergeTableCells(client, docToken, blockId, rowStart, rowEnd, columnStart, columnEnd) {
|
|
867
|
+
const res = await client.docx.documentBlock.patch({
|
|
868
|
+
path: {
|
|
869
|
+
document_id: docToken,
|
|
870
|
+
block_id: blockId
|
|
871
|
+
},
|
|
872
|
+
data: { merge_table_cells: {
|
|
873
|
+
row_start_index: rowStart,
|
|
874
|
+
row_end_index: rowEnd,
|
|
875
|
+
column_start_index: columnStart,
|
|
876
|
+
column_end_index: columnEnd
|
|
877
|
+
} }
|
|
878
|
+
});
|
|
879
|
+
if (res.code !== 0) throw new Error(res.msg);
|
|
880
|
+
return {
|
|
881
|
+
success: true,
|
|
882
|
+
block: res.data?.block
|
|
883
|
+
};
|
|
884
|
+
}
|
|
885
|
+
//#endregion
|
|
886
|
+
//#region extensions/feishu/src/docx-batch-insert.ts
|
|
887
|
+
const BATCH_SIZE = 1e3;
|
|
888
|
+
/**
|
|
889
|
+
* Collect all descendant blocks for a given first-level block ID.
|
|
890
|
+
* Recursively traverses the block tree to gather all children.
|
|
891
|
+
*/
|
|
892
|
+
function collectDescendants(blockMap, rootId) {
|
|
893
|
+
const result = [];
|
|
894
|
+
const visited = /* @__PURE__ */ new Set();
|
|
895
|
+
function collect(blockId) {
|
|
896
|
+
if (visited.has(blockId)) return;
|
|
897
|
+
visited.add(blockId);
|
|
898
|
+
const block = blockMap.get(blockId);
|
|
899
|
+
if (!block) return;
|
|
900
|
+
result.push(block);
|
|
901
|
+
const children = block.children;
|
|
902
|
+
if (Array.isArray(children)) for (const childId of children) collect(childId);
|
|
903
|
+
else if (typeof children === "string") collect(children);
|
|
904
|
+
}
|
|
905
|
+
collect(rootId);
|
|
906
|
+
return result;
|
|
907
|
+
}
|
|
908
|
+
/**
|
|
909
|
+
* Insert a single batch of blocks using Descendant API.
|
|
910
|
+
*
|
|
911
|
+
* @param parentBlockId - Parent block to insert into (defaults to docToken)
|
|
912
|
+
* @param index - Position within parent's children (-1 = end)
|
|
913
|
+
*/
|
|
914
|
+
async function insertBatch(client, docToken, blocks, firstLevelBlockIds, parentBlockId = docToken, index = -1) {
|
|
915
|
+
const descendants = cleanBlocksForDescendant(blocks);
|
|
916
|
+
if (descendants.length === 0) return [];
|
|
917
|
+
const res = await client.docx.documentBlockDescendant.create({
|
|
918
|
+
path: {
|
|
919
|
+
document_id: docToken,
|
|
920
|
+
block_id: parentBlockId
|
|
921
|
+
},
|
|
922
|
+
data: {
|
|
923
|
+
children_id: firstLevelBlockIds,
|
|
924
|
+
descendants,
|
|
925
|
+
index
|
|
926
|
+
}
|
|
927
|
+
});
|
|
928
|
+
if (res.code !== 0) throw new Error(`${res.msg} (code: ${res.code})`);
|
|
929
|
+
return res.data?.children ?? [];
|
|
930
|
+
}
|
|
931
|
+
/**
|
|
932
|
+
* Insert blocks in batches for large documents (>1000 blocks).
|
|
933
|
+
*
|
|
934
|
+
* Batches are split to ensure BOTH children_id AND descendants
|
|
935
|
+
* arrays stay under the 1000 block API limit.
|
|
936
|
+
*
|
|
937
|
+
* @param client - Feishu API client
|
|
938
|
+
* @param docToken - Document ID
|
|
939
|
+
* @param blocks - All blocks from Convert API
|
|
940
|
+
* @param firstLevelBlockIds - IDs of top-level blocks to insert
|
|
941
|
+
* @param logger - Optional logger for progress updates
|
|
942
|
+
* @param parentBlockId - Parent block to insert into (defaults to docToken = document root)
|
|
943
|
+
* @param startIndex - Starting position within parent (-1 = end). For multi-batch inserts,
|
|
944
|
+
* each batch advances this by the number of first-level IDs inserted so far.
|
|
945
|
+
* @returns Inserted children blocks and any skipped block IDs
|
|
946
|
+
*/
|
|
947
|
+
async function insertBlocksInBatches(client, docToken, blocks, firstLevelBlockIds, logger, parentBlockId = docToken, startIndex = -1) {
|
|
948
|
+
const allChildren = [];
|
|
949
|
+
const batches = [];
|
|
950
|
+
let currentBatch = {
|
|
951
|
+
firstLevelIds: [],
|
|
952
|
+
blocks: []
|
|
953
|
+
};
|
|
954
|
+
const usedBlockIds = /* @__PURE__ */ new Set();
|
|
955
|
+
const blockMap = /* @__PURE__ */ new Map();
|
|
956
|
+
for (const block of blocks) blockMap.set(block.block_id, block);
|
|
957
|
+
for (const firstLevelId of firstLevelBlockIds) {
|
|
958
|
+
const newBlocks = collectDescendants(blockMap, firstLevelId).filter((b) => !usedBlockIds.has(b.block_id));
|
|
959
|
+
if (newBlocks.length > 1e3) throw new Error(`Block "${firstLevelId}" has ${newBlocks.length} descendants, which exceeds the Feishu API limit of ${BATCH_SIZE} blocks per request. Please split the content into smaller sections.`);
|
|
960
|
+
if (currentBatch.blocks.length + newBlocks.length > 1e3 && currentBatch.blocks.length > 0) {
|
|
961
|
+
batches.push(currentBatch);
|
|
962
|
+
currentBatch = {
|
|
963
|
+
firstLevelIds: [],
|
|
964
|
+
blocks: []
|
|
965
|
+
};
|
|
966
|
+
}
|
|
967
|
+
currentBatch.firstLevelIds.push(firstLevelId);
|
|
968
|
+
for (const block of newBlocks) {
|
|
969
|
+
currentBatch.blocks.push(block);
|
|
970
|
+
usedBlockIds.add(block.block_id);
|
|
971
|
+
}
|
|
972
|
+
}
|
|
973
|
+
if (currentBatch.blocks.length > 0) batches.push(currentBatch);
|
|
974
|
+
let currentIndex = startIndex;
|
|
975
|
+
for (let i = 0; i < batches.length; i++) {
|
|
976
|
+
const batch = batches[i];
|
|
977
|
+
logger?.info?.(`feishu_doc: Inserting batch ${i + 1}/${batches.length} (${batch.blocks.length} blocks)...`);
|
|
978
|
+
const children = await insertBatch(client, docToken, batch.blocks, batch.firstLevelIds, parentBlockId, currentIndex);
|
|
979
|
+
allChildren.push(...children);
|
|
980
|
+
if (currentIndex !== -1) currentIndex += batch.firstLevelIds.length;
|
|
981
|
+
}
|
|
982
|
+
return {
|
|
983
|
+
children: allChildren,
|
|
984
|
+
skipped: []
|
|
985
|
+
};
|
|
986
|
+
}
|
|
987
|
+
//#endregion
|
|
988
|
+
//#region extensions/feishu/src/docx-color-text.ts
|
|
989
|
+
const TEXT_COLOR = {
|
|
990
|
+
red: 1,
|
|
991
|
+
orange: 2,
|
|
992
|
+
yellow: 3,
|
|
993
|
+
green: 4,
|
|
994
|
+
blue: 5,
|
|
995
|
+
purple: 6,
|
|
996
|
+
grey: 7,
|
|
997
|
+
gray: 7
|
|
998
|
+
};
|
|
999
|
+
const BACKGROUND_COLOR = {
|
|
1000
|
+
red: 1,
|
|
1001
|
+
orange: 2,
|
|
1002
|
+
yellow: 3,
|
|
1003
|
+
green: 4,
|
|
1004
|
+
blue: 5,
|
|
1005
|
+
purple: 6,
|
|
1006
|
+
grey: 7,
|
|
1007
|
+
gray: 7
|
|
1008
|
+
};
|
|
1009
|
+
/**
|
|
1010
|
+
* Parse color markup into segments.
|
|
1011
|
+
*
|
|
1012
|
+
* Supports:
|
|
1013
|
+
* [red]text[/red] → red text
|
|
1014
|
+
* [bg:yellow]text[/bg] → yellow background
|
|
1015
|
+
* [bold]text[/bold] → bold
|
|
1016
|
+
* [green bold]text[/green] → green + bold
|
|
1017
|
+
*/
|
|
1018
|
+
function parseColorMarkup(content) {
|
|
1019
|
+
const segments = [];
|
|
1020
|
+
const KNOWN = "(?:bg:[a-z]+|bold|red|orange|yellow|green|blue|purple|gr[ae]y)";
|
|
1021
|
+
const tagPattern = new RegExp(`\\[(${KNOWN}(?:\\s+${KNOWN})*)\\](.*?)\\[\\/(?:[^\\]]+)\\]|([^[]+|\\[)`, "gis");
|
|
1022
|
+
let match;
|
|
1023
|
+
while ((match = tagPattern.exec(content)) !== null) if (match[3] !== void 0) {
|
|
1024
|
+
if (match[3]) segments.push({ text: match[3] });
|
|
1025
|
+
} else {
|
|
1026
|
+
const tagStr = match[1].toLowerCase().trim();
|
|
1027
|
+
const text = match[2];
|
|
1028
|
+
const tags = tagStr.split(/\s+/);
|
|
1029
|
+
const segment = { text };
|
|
1030
|
+
for (const tag of tags) if (tag.startsWith("bg:")) {
|
|
1031
|
+
const color = tag.slice(3);
|
|
1032
|
+
if (BACKGROUND_COLOR[color]) segment.bgColor = BACKGROUND_COLOR[color];
|
|
1033
|
+
} else if (tag === "bold") segment.bold = true;
|
|
1034
|
+
else if (TEXT_COLOR[tag]) segment.textColor = TEXT_COLOR[tag];
|
|
1035
|
+
if (text) segments.push(segment);
|
|
1036
|
+
}
|
|
1037
|
+
return segments;
|
|
1038
|
+
}
|
|
1039
|
+
/**
|
|
1040
|
+
* Update a text block with colored segments.
|
|
1041
|
+
*/
|
|
1042
|
+
async function updateColorText(client, docToken, blockId, content) {
|
|
1043
|
+
const segments = parseColorMarkup(content);
|
|
1044
|
+
const elements = segments.map((seg) => ({ text_run: {
|
|
1045
|
+
content: seg.text,
|
|
1046
|
+
text_element_style: {
|
|
1047
|
+
...seg.textColor && { text_color: seg.textColor },
|
|
1048
|
+
...seg.bgColor && { background_color: seg.bgColor },
|
|
1049
|
+
...seg.bold && { bold: true }
|
|
1050
|
+
}
|
|
1051
|
+
} }));
|
|
1052
|
+
const res = await client.docx.documentBlock.patch({
|
|
1053
|
+
path: {
|
|
1054
|
+
document_id: docToken,
|
|
1055
|
+
block_id: blockId
|
|
1056
|
+
},
|
|
1057
|
+
data: { update_text_elements: { elements } }
|
|
1058
|
+
});
|
|
1059
|
+
if (res.code !== 0) throw new Error(res.msg);
|
|
1060
|
+
return {
|
|
1061
|
+
success: true,
|
|
1062
|
+
segments: segments.length,
|
|
1063
|
+
block: res.data?.block
|
|
1064
|
+
};
|
|
1065
|
+
}
|
|
1066
|
+
//#endregion
|
|
1067
|
+
//#region extensions/feishu/src/docx.ts
|
|
1068
|
+
function json(data) {
|
|
1069
|
+
return {
|
|
1070
|
+
content: [{
|
|
1071
|
+
type: "text",
|
|
1072
|
+
text: JSON.stringify(data, null, 2)
|
|
1073
|
+
}],
|
|
1074
|
+
details: data
|
|
1075
|
+
};
|
|
1076
|
+
}
|
|
1077
|
+
/** Extract image URLs from markdown content */
|
|
1078
|
+
function extractImageUrls(markdown) {
|
|
1079
|
+
const regex = /!\[[^\]]*\]\(([^)]+)\)/g;
|
|
1080
|
+
const urls = [];
|
|
1081
|
+
let match;
|
|
1082
|
+
while ((match = regex.exec(markdown)) !== null) {
|
|
1083
|
+
const url = match[1].trim();
|
|
1084
|
+
if (url.startsWith("http://") || url.startsWith("https://")) urls.push(url);
|
|
1085
|
+
}
|
|
1086
|
+
return urls;
|
|
1087
|
+
}
|
|
1088
|
+
const BLOCK_TYPE_NAMES = {
|
|
1089
|
+
1: "Page",
|
|
1090
|
+
2: "Text",
|
|
1091
|
+
3: "Heading1",
|
|
1092
|
+
4: "Heading2",
|
|
1093
|
+
5: "Heading3",
|
|
1094
|
+
12: "Bullet",
|
|
1095
|
+
13: "Ordered",
|
|
1096
|
+
14: "Code",
|
|
1097
|
+
15: "Quote",
|
|
1098
|
+
17: "Todo",
|
|
1099
|
+
18: "Bitable",
|
|
1100
|
+
21: "Diagram",
|
|
1101
|
+
22: "Divider",
|
|
1102
|
+
23: "File",
|
|
1103
|
+
27: "Image",
|
|
1104
|
+
30: "Sheet",
|
|
1105
|
+
31: "Table",
|
|
1106
|
+
32: "TableCell"
|
|
1107
|
+
};
|
|
1108
|
+
const UNSUPPORTED_CREATE_TYPES = new Set([31, 32]);
|
|
1109
|
+
/** Clean blocks for insertion (remove unsupported types and read-only fields) */
|
|
1110
|
+
function cleanBlocksForInsert(blocks) {
|
|
1111
|
+
const skipped = [];
|
|
1112
|
+
return {
|
|
1113
|
+
cleaned: blocks.filter((block) => {
|
|
1114
|
+
if (UNSUPPORTED_CREATE_TYPES.has(block.block_type)) {
|
|
1115
|
+
const typeName = BLOCK_TYPE_NAMES[block.block_type] || `type_${block.block_type}`;
|
|
1116
|
+
skipped.push(typeName);
|
|
1117
|
+
return false;
|
|
1118
|
+
}
|
|
1119
|
+
return true;
|
|
1120
|
+
}).map((block) => {
|
|
1121
|
+
if (block.block_type === 31 && block.table?.merge_info) {
|
|
1122
|
+
const { merge_info: _merge_info, ...tableRest } = block.table;
|
|
1123
|
+
return {
|
|
1124
|
+
...block,
|
|
1125
|
+
table: tableRest
|
|
1126
|
+
};
|
|
1127
|
+
}
|
|
1128
|
+
return block;
|
|
1129
|
+
}),
|
|
1130
|
+
skipped
|
|
1131
|
+
};
|
|
1132
|
+
}
|
|
1133
|
+
const MAX_CONVERT_RETRY_DEPTH = 8;
|
|
1134
|
+
async function convertMarkdown(client, markdown) {
|
|
1135
|
+
const res = await client.docx.document.convert({ data: {
|
|
1136
|
+
content_type: "markdown",
|
|
1137
|
+
content: markdown
|
|
1138
|
+
} });
|
|
1139
|
+
if (res.code !== 0) throw new Error(res.msg);
|
|
1140
|
+
return {
|
|
1141
|
+
blocks: res.data?.blocks ?? [],
|
|
1142
|
+
firstLevelBlockIds: res.data?.first_level_block_ids ?? []
|
|
1143
|
+
};
|
|
1144
|
+
}
|
|
1145
|
+
function sortBlocksByFirstLevel(blocks, firstLevelIds) {
|
|
1146
|
+
if (!firstLevelIds || firstLevelIds.length === 0) return blocks;
|
|
1147
|
+
const sorted = firstLevelIds.map((id) => blocks.find((b) => b.block_id === id)).filter(Boolean);
|
|
1148
|
+
const sortedIds = new Set(firstLevelIds);
|
|
1149
|
+
const remaining = blocks.filter((b) => !sortedIds.has(b.block_id));
|
|
1150
|
+
return [...sorted, ...remaining];
|
|
1151
|
+
}
|
|
1152
|
+
async function insertBlocks(client, docToken, blocks, parentBlockId, index) {
|
|
1153
|
+
const { cleaned, skipped } = cleanBlocksForInsert(blocks);
|
|
1154
|
+
const blockId = parentBlockId ?? docToken;
|
|
1155
|
+
if (cleaned.length === 0) return {
|
|
1156
|
+
children: [],
|
|
1157
|
+
skipped
|
|
1158
|
+
};
|
|
1159
|
+
const allInserted = [];
|
|
1160
|
+
for (const [offset, block] of cleaned.entries()) {
|
|
1161
|
+
const res = await client.docx.documentBlockChildren.create({
|
|
1162
|
+
path: {
|
|
1163
|
+
document_id: docToken,
|
|
1164
|
+
block_id: blockId
|
|
1165
|
+
},
|
|
1166
|
+
data: {
|
|
1167
|
+
children: [block],
|
|
1168
|
+
...index !== void 0 ? { index: index + offset } : {}
|
|
1169
|
+
}
|
|
1170
|
+
});
|
|
1171
|
+
if (res.code !== 0) throw new Error(res.msg);
|
|
1172
|
+
allInserted.push(...res.data?.children ?? []);
|
|
1173
|
+
}
|
|
1174
|
+
return {
|
|
1175
|
+
children: allInserted,
|
|
1176
|
+
skipped
|
|
1177
|
+
};
|
|
1178
|
+
}
|
|
1179
|
+
/** Split markdown into chunks at top-level headings (# or ##) to stay within API content limits */
|
|
1180
|
+
function splitMarkdownByHeadings(markdown) {
|
|
1181
|
+
const lines = markdown.split("\n");
|
|
1182
|
+
const chunks = [];
|
|
1183
|
+
let current = [];
|
|
1184
|
+
let inFencedBlock = false;
|
|
1185
|
+
for (const line of lines) {
|
|
1186
|
+
if (/^(`{3,}|~{3,})/.test(line)) inFencedBlock = !inFencedBlock;
|
|
1187
|
+
if (!inFencedBlock && /^#{1,2}\s/.test(line) && current.length > 0) {
|
|
1188
|
+
chunks.push(current.join("\n"));
|
|
1189
|
+
current = [];
|
|
1190
|
+
}
|
|
1191
|
+
current.push(line);
|
|
1192
|
+
}
|
|
1193
|
+
if (current.length > 0) chunks.push(current.join("\n"));
|
|
1194
|
+
return chunks;
|
|
1195
|
+
}
|
|
1196
|
+
/** Split markdown by size, preferring to break outside fenced code blocks when possible */
|
|
1197
|
+
function splitMarkdownBySize(markdown, maxChars) {
|
|
1198
|
+
if (markdown.length <= maxChars) return [markdown];
|
|
1199
|
+
const lines = markdown.split("\n");
|
|
1200
|
+
const chunks = [];
|
|
1201
|
+
let current = [];
|
|
1202
|
+
let currentLength = 0;
|
|
1203
|
+
let inFencedBlock = false;
|
|
1204
|
+
for (const line of lines) {
|
|
1205
|
+
if (/^(`{3,}|~{3,})/.test(line)) inFencedBlock = !inFencedBlock;
|
|
1206
|
+
const lineLength = line.length + 1;
|
|
1207
|
+
const wouldExceed = currentLength + lineLength > maxChars;
|
|
1208
|
+
if (current.length > 0 && wouldExceed && !inFencedBlock) {
|
|
1209
|
+
chunks.push(current.join("\n"));
|
|
1210
|
+
current = [];
|
|
1211
|
+
currentLength = 0;
|
|
1212
|
+
}
|
|
1213
|
+
current.push(line);
|
|
1214
|
+
currentLength += lineLength;
|
|
1215
|
+
}
|
|
1216
|
+
if (current.length > 0) chunks.push(current.join("\n"));
|
|
1217
|
+
if (chunks.length > 1) return chunks;
|
|
1218
|
+
const midpoint = Math.floor(lines.length / 2);
|
|
1219
|
+
if (midpoint <= 0 || midpoint >= lines.length) return [markdown];
|
|
1220
|
+
return [lines.slice(0, midpoint).join("\n"), lines.slice(midpoint).join("\n")];
|
|
1221
|
+
}
|
|
1222
|
+
async function convertMarkdownWithFallback(client, markdown, depth = 0) {
|
|
1223
|
+
try {
|
|
1224
|
+
return await convertMarkdown(client, markdown);
|
|
1225
|
+
} catch (error) {
|
|
1226
|
+
if (depth >= MAX_CONVERT_RETRY_DEPTH || markdown.length < 2) throw error;
|
|
1227
|
+
const chunks = splitMarkdownBySize(markdown, Math.max(256, Math.floor(markdown.length / 2)));
|
|
1228
|
+
if (chunks.length <= 1) throw error;
|
|
1229
|
+
const blocks = [];
|
|
1230
|
+
const firstLevelBlockIds = [];
|
|
1231
|
+
for (const chunk of chunks) {
|
|
1232
|
+
const converted = await convertMarkdownWithFallback(client, chunk, depth + 1);
|
|
1233
|
+
blocks.push(...converted.blocks);
|
|
1234
|
+
firstLevelBlockIds.push(...converted.firstLevelBlockIds);
|
|
1235
|
+
}
|
|
1236
|
+
return {
|
|
1237
|
+
blocks,
|
|
1238
|
+
firstLevelBlockIds
|
|
1239
|
+
};
|
|
1240
|
+
}
|
|
1241
|
+
}
|
|
1242
|
+
/** Convert markdown in chunks to avoid document.convert content size limits */
|
|
1243
|
+
async function chunkedConvertMarkdown(client, markdown) {
|
|
1244
|
+
const chunks = splitMarkdownByHeadings(markdown);
|
|
1245
|
+
const allBlocks = [];
|
|
1246
|
+
const allFirstLevelBlockIds = [];
|
|
1247
|
+
for (const chunk of chunks) {
|
|
1248
|
+
const { blocks, firstLevelBlockIds } = await convertMarkdownWithFallback(client, chunk);
|
|
1249
|
+
const sorted = sortBlocksByFirstLevel(blocks, firstLevelBlockIds);
|
|
1250
|
+
allBlocks.push(...sorted);
|
|
1251
|
+
allFirstLevelBlockIds.push(...firstLevelBlockIds);
|
|
1252
|
+
}
|
|
1253
|
+
return {
|
|
1254
|
+
blocks: allBlocks,
|
|
1255
|
+
firstLevelBlockIds: allFirstLevelBlockIds
|
|
1256
|
+
};
|
|
1257
|
+
}
|
|
1258
|
+
/**
|
|
1259
|
+
* Insert blocks using the Descendant API (supports tables, nested lists, large docs).
|
|
1260
|
+
* Unlike the Children API, this supports block_type 31/32 (Table/TableCell).
|
|
1261
|
+
*
|
|
1262
|
+
* @param parentBlockId - Parent block to insert into (defaults to docToken = document root)
|
|
1263
|
+
* @param index - Position within parent's children (-1 = end, 0 = first)
|
|
1264
|
+
*/
|
|
1265
|
+
async function insertBlocksWithDescendant(client, docToken, blocks, firstLevelBlockIds, { parentBlockId = docToken, index = -1 } = {}) {
|
|
1266
|
+
const descendants = cleanBlocksForDescendant(blocks);
|
|
1267
|
+
if (descendants.length === 0) return { children: [] };
|
|
1268
|
+
const res = await client.docx.documentBlockDescendant.create({
|
|
1269
|
+
path: {
|
|
1270
|
+
document_id: docToken,
|
|
1271
|
+
block_id: parentBlockId
|
|
1272
|
+
},
|
|
1273
|
+
data: {
|
|
1274
|
+
children_id: firstLevelBlockIds,
|
|
1275
|
+
descendants,
|
|
1276
|
+
index
|
|
1277
|
+
}
|
|
1278
|
+
});
|
|
1279
|
+
if (res.code !== 0) throw new Error(`${res.msg} (code: ${res.code})`);
|
|
1280
|
+
return { children: res.data?.children ?? [] };
|
|
1281
|
+
}
|
|
1282
|
+
async function clearDocumentContent(client, docToken) {
|
|
1283
|
+
const existing = await client.docx.documentBlock.list({ path: { document_id: docToken } });
|
|
1284
|
+
if (existing.code !== 0) throw new Error(existing.msg);
|
|
1285
|
+
const childIds = existing.data?.items?.filter((b) => b.parent_id === docToken && b.block_type !== 1).map((b) => b.block_id) ?? [];
|
|
1286
|
+
if (childIds.length > 0) {
|
|
1287
|
+
const res = await client.docx.documentBlockChildren.batchDelete({
|
|
1288
|
+
path: {
|
|
1289
|
+
document_id: docToken,
|
|
1290
|
+
block_id: docToken
|
|
1291
|
+
},
|
|
1292
|
+
data: {
|
|
1293
|
+
start_index: 0,
|
|
1294
|
+
end_index: childIds.length
|
|
1295
|
+
}
|
|
1296
|
+
});
|
|
1297
|
+
if (res.code !== 0) throw new Error(res.msg);
|
|
1298
|
+
}
|
|
1299
|
+
return childIds.length;
|
|
1300
|
+
}
|
|
1301
|
+
async function uploadImageToDocx(client, blockId, imageBuffer, fileName, docToken) {
|
|
1302
|
+
const fileToken = (await client.drive.media.uploadAll({ data: {
|
|
1303
|
+
file_name: fileName,
|
|
1304
|
+
parent_type: "docx_image",
|
|
1305
|
+
parent_node: blockId,
|
|
1306
|
+
size: imageBuffer.length,
|
|
1307
|
+
file: imageBuffer,
|
|
1308
|
+
...docToken ? { extra: JSON.stringify({ drive_route_token: docToken }) } : {}
|
|
1309
|
+
} }))?.file_token;
|
|
1310
|
+
if (!fileToken) throw new Error("Image upload failed: no file_token returned");
|
|
1311
|
+
return fileToken;
|
|
1312
|
+
}
|
|
1313
|
+
async function downloadImage(url, maxBytes) {
|
|
1314
|
+
return (await getFeishuRuntime().channel.media.fetchRemoteMedia({
|
|
1315
|
+
url,
|
|
1316
|
+
maxBytes
|
|
1317
|
+
})).buffer;
|
|
1318
|
+
}
|
|
1319
|
+
async function resolveUploadInput(url, filePath, maxBytes, explicitFileName, imageInput) {
|
|
1320
|
+
const inputSources = [
|
|
1321
|
+
url ? "url" : null,
|
|
1322
|
+
filePath ? "file_path" : null,
|
|
1323
|
+
imageInput ? "image" : null
|
|
1324
|
+
].filter(Boolean);
|
|
1325
|
+
if (inputSources.length > 1) throw new Error(`Provide only one image source; got: ${inputSources.join(", ")}`);
|
|
1326
|
+
if (imageInput?.startsWith("data:")) {
|
|
1327
|
+
const commaIdx = imageInput.indexOf(",");
|
|
1328
|
+
if (commaIdx === -1) throw new Error("Invalid data URI: missing comma separator.");
|
|
1329
|
+
const header = imageInput.slice(0, commaIdx);
|
|
1330
|
+
const data = imageInput.slice(commaIdx + 1);
|
|
1331
|
+
if (!header.includes(";base64")) throw new Error("Invalid data URI: missing ';base64' marker. Expected format: data:image/png;base64,<base64data>");
|
|
1332
|
+
const trimmedData = data.trim();
|
|
1333
|
+
if (trimmedData.length === 0 || !/^[A-Za-z0-9+/]+=*$/.test(trimmedData)) throw new Error(`Invalid data URI: base64 payload contains characters outside the standard alphabet.`);
|
|
1334
|
+
const ext = header.match(/data:([^;]+)/)?.[1]?.split("/")[1] ?? "png";
|
|
1335
|
+
const estimatedBytes = Math.ceil(trimmedData.length * 3 / 4);
|
|
1336
|
+
if (estimatedBytes > maxBytes) throw new Error(`Image data URI exceeds limit: estimated ${estimatedBytes} bytes > ${maxBytes} bytes`);
|
|
1337
|
+
return {
|
|
1338
|
+
buffer: Buffer.from(trimmedData, "base64"),
|
|
1339
|
+
fileName: explicitFileName ?? `image.${ext}`
|
|
1340
|
+
};
|
|
1341
|
+
}
|
|
1342
|
+
if (imageInput) {
|
|
1343
|
+
const candidate = imageInput.startsWith("~") ? imageInput.replace(/^~/, homedir()) : imageInput;
|
|
1344
|
+
const unambiguousPath = imageInput.startsWith("~") || imageInput.startsWith("./") || imageInput.startsWith("../");
|
|
1345
|
+
const absolutePath = isAbsolute(imageInput);
|
|
1346
|
+
if (unambiguousPath || absolutePath && existsSync(candidate)) {
|
|
1347
|
+
const buffer = await promises.readFile(candidate);
|
|
1348
|
+
if (buffer.length > maxBytes) throw new Error(`Local file exceeds limit: ${buffer.length} bytes > ${maxBytes} bytes`);
|
|
1349
|
+
return {
|
|
1350
|
+
buffer,
|
|
1351
|
+
fileName: explicitFileName ?? basename(candidate)
|
|
1352
|
+
};
|
|
1353
|
+
}
|
|
1354
|
+
if (absolutePath && !existsSync(candidate)) throw new Error(`File not found: "${candidate}". If you intended to pass image binary data, use a data URI instead: data:image/jpeg;base64,...`);
|
|
1355
|
+
}
|
|
1356
|
+
if (imageInput) {
|
|
1357
|
+
const trimmed = imageInput.trim();
|
|
1358
|
+
if (trimmed.length === 0 || !/^[A-Za-z0-9+/]+=*$/.test(trimmed)) throw new Error("Invalid base64: image input contains characters outside the standard base64 alphabet. Use a data URI (data:image/png;base64,...) or a local file path instead.");
|
|
1359
|
+
const estimatedBytes = Math.ceil(trimmed.length * 3 / 4);
|
|
1360
|
+
if (estimatedBytes > maxBytes) throw new Error(`Base64 image exceeds limit: estimated ${estimatedBytes} bytes > ${maxBytes} bytes`);
|
|
1361
|
+
const buffer = Buffer.from(trimmed, "base64");
|
|
1362
|
+
if (buffer.length === 0) throw new Error("Base64 image decoded to empty buffer; check the input.");
|
|
1363
|
+
return {
|
|
1364
|
+
buffer,
|
|
1365
|
+
fileName: explicitFileName ?? "image.png"
|
|
1366
|
+
};
|
|
1367
|
+
}
|
|
1368
|
+
if (!url && !filePath) throw new Error("Either url, file_path, or image (base64/data URI) must be provided");
|
|
1369
|
+
if (url && filePath) throw new Error("Provide only one of url or file_path");
|
|
1370
|
+
if (url) {
|
|
1371
|
+
const fetched = await getFeishuRuntime().channel.media.fetchRemoteMedia({
|
|
1372
|
+
url,
|
|
1373
|
+
maxBytes
|
|
1374
|
+
});
|
|
1375
|
+
const guessed = new URL(url).pathname.split("/").pop() || "upload.bin";
|
|
1376
|
+
return {
|
|
1377
|
+
buffer: fetched.buffer,
|
|
1378
|
+
fileName: explicitFileName || guessed
|
|
1379
|
+
};
|
|
1380
|
+
}
|
|
1381
|
+
const buffer = await promises.readFile(filePath);
|
|
1382
|
+
if (buffer.length > maxBytes) throw new Error(`Local file exceeds limit: ${buffer.length} bytes > ${maxBytes} bytes`);
|
|
1383
|
+
return {
|
|
1384
|
+
buffer,
|
|
1385
|
+
fileName: explicitFileName || basename(filePath)
|
|
1386
|
+
};
|
|
1387
|
+
}
|
|
1388
|
+
async function processImages(client, docToken, markdown, insertedBlocks, maxBytes) {
|
|
1389
|
+
const imageUrls = extractImageUrls(markdown);
|
|
1390
|
+
if (imageUrls.length === 0) return 0;
|
|
1391
|
+
const imageBlocks = insertedBlocks.filter((b) => b.block_type === 27);
|
|
1392
|
+
let processed = 0;
|
|
1393
|
+
for (let i = 0; i < Math.min(imageUrls.length, imageBlocks.length); i++) {
|
|
1394
|
+
const url = imageUrls[i];
|
|
1395
|
+
const blockId = imageBlocks[i].block_id;
|
|
1396
|
+
try {
|
|
1397
|
+
const fileToken = await uploadImageToDocx(client, blockId, await downloadImage(url, maxBytes), new URL(url).pathname.split("/").pop() || `image_${i}.png`, docToken);
|
|
1398
|
+
await client.docx.documentBlock.patch({
|
|
1399
|
+
path: {
|
|
1400
|
+
document_id: docToken,
|
|
1401
|
+
block_id: blockId
|
|
1402
|
+
},
|
|
1403
|
+
data: { replace_image: { token: fileToken } }
|
|
1404
|
+
});
|
|
1405
|
+
processed++;
|
|
1406
|
+
} catch (err) {
|
|
1407
|
+
console.error(`Failed to process image ${url}:`, err);
|
|
1408
|
+
}
|
|
1409
|
+
}
|
|
1410
|
+
return processed;
|
|
1411
|
+
}
|
|
1412
|
+
async function uploadImageBlock(client, docToken, maxBytes, url, filePath, parentBlockId, filename, index, imageInput) {
|
|
1413
|
+
const insertRes = await client.docx.documentBlockChildren.create({
|
|
1414
|
+
path: {
|
|
1415
|
+
document_id: docToken,
|
|
1416
|
+
block_id: parentBlockId ?? docToken
|
|
1417
|
+
},
|
|
1418
|
+
params: { document_revision_id: -1 },
|
|
1419
|
+
data: {
|
|
1420
|
+
children: [{
|
|
1421
|
+
block_type: 27,
|
|
1422
|
+
image: {}
|
|
1423
|
+
}],
|
|
1424
|
+
index: index ?? -1
|
|
1425
|
+
}
|
|
1426
|
+
});
|
|
1427
|
+
if (insertRes.code !== 0) throw new Error(`Failed to create image block: ${insertRes.msg}`);
|
|
1428
|
+
const imageBlockId = insertRes.data?.children?.find((b) => b.block_type === 27)?.block_id;
|
|
1429
|
+
if (!imageBlockId) throw new Error("Failed to create image block");
|
|
1430
|
+
const upload = await resolveUploadInput(url, filePath, maxBytes, filename, imageInput);
|
|
1431
|
+
const fileToken = await uploadImageToDocx(client, imageBlockId, upload.buffer, upload.fileName, docToken);
|
|
1432
|
+
const patchRes = await client.docx.documentBlock.patch({
|
|
1433
|
+
path: {
|
|
1434
|
+
document_id: docToken,
|
|
1435
|
+
block_id: imageBlockId
|
|
1436
|
+
},
|
|
1437
|
+
data: { replace_image: { token: fileToken } }
|
|
1438
|
+
});
|
|
1439
|
+
if (patchRes.code !== 0) throw new Error(patchRes.msg);
|
|
1440
|
+
return {
|
|
1441
|
+
success: true,
|
|
1442
|
+
block_id: imageBlockId,
|
|
1443
|
+
file_token: fileToken,
|
|
1444
|
+
file_name: upload.fileName,
|
|
1445
|
+
size: upload.buffer.length
|
|
1446
|
+
};
|
|
1447
|
+
}
|
|
1448
|
+
async function uploadFileBlock(client, docToken, maxBytes, url, filePath, parentBlockId, filename) {
|
|
1449
|
+
const blockId = parentBlockId ?? docToken;
|
|
1450
|
+
const upload = await resolveUploadInput(url, filePath, maxBytes, filename);
|
|
1451
|
+
const converted = await convertMarkdown(client, `[${upload.fileName}](https://example.com/placeholder)`);
|
|
1452
|
+
const { children: inserted } = await insertBlocks(client, docToken, sortBlocksByFirstLevel(converted.blocks, converted.firstLevelBlockIds), blockId);
|
|
1453
|
+
const placeholderBlock = inserted[0];
|
|
1454
|
+
if (!placeholderBlock?.block_id) throw new Error("Failed to create placeholder block for file upload");
|
|
1455
|
+
const parentId = placeholderBlock.parent_id ?? blockId;
|
|
1456
|
+
const childrenRes = await client.docx.documentBlockChildren.get({ path: {
|
|
1457
|
+
document_id: docToken,
|
|
1458
|
+
block_id: parentId
|
|
1459
|
+
} });
|
|
1460
|
+
if (childrenRes.code !== 0) throw new Error(childrenRes.msg);
|
|
1461
|
+
const placeholderIdx = (childrenRes.data?.items ?? []).findIndex((item) => item.block_id === placeholderBlock.block_id);
|
|
1462
|
+
if (placeholderIdx >= 0) {
|
|
1463
|
+
const deleteRes = await client.docx.documentBlockChildren.batchDelete({
|
|
1464
|
+
path: {
|
|
1465
|
+
document_id: docToken,
|
|
1466
|
+
block_id: parentId
|
|
1467
|
+
},
|
|
1468
|
+
data: {
|
|
1469
|
+
start_index: placeholderIdx,
|
|
1470
|
+
end_index: placeholderIdx + 1
|
|
1471
|
+
}
|
|
1472
|
+
});
|
|
1473
|
+
if (deleteRes.code !== 0) throw new Error(deleteRes.msg);
|
|
1474
|
+
}
|
|
1475
|
+
const fileToken = (await client.drive.media.uploadAll({ data: {
|
|
1476
|
+
file_name: upload.fileName,
|
|
1477
|
+
parent_type: "docx_file",
|
|
1478
|
+
parent_node: docToken,
|
|
1479
|
+
size: upload.buffer.length,
|
|
1480
|
+
file: upload.buffer
|
|
1481
|
+
} }))?.file_token;
|
|
1482
|
+
if (!fileToken) throw new Error("File upload failed: no file_token returned");
|
|
1483
|
+
return {
|
|
1484
|
+
success: true,
|
|
1485
|
+
file_token: fileToken,
|
|
1486
|
+
file_name: upload.fileName,
|
|
1487
|
+
size: upload.buffer.length,
|
|
1488
|
+
note: "File uploaded to drive. Use the file_token to reference it. Direct file block creation is not supported by the Feishu API."
|
|
1489
|
+
};
|
|
1490
|
+
}
|
|
1491
|
+
const STRUCTURED_BLOCK_TYPES = new Set([
|
|
1492
|
+
14,
|
|
1493
|
+
18,
|
|
1494
|
+
21,
|
|
1495
|
+
23,
|
|
1496
|
+
27,
|
|
1497
|
+
30,
|
|
1498
|
+
31,
|
|
1499
|
+
32
|
|
1500
|
+
]);
|
|
1501
|
+
async function readDoc(client, docToken) {
|
|
1502
|
+
const [contentRes, infoRes, blocksRes] = await Promise.all([
|
|
1503
|
+
client.docx.document.rawContent({ path: { document_id: docToken } }),
|
|
1504
|
+
client.docx.document.get({ path: { document_id: docToken } }),
|
|
1505
|
+
client.docx.documentBlock.list({ path: { document_id: docToken } })
|
|
1506
|
+
]);
|
|
1507
|
+
if (contentRes.code !== 0) throw new Error(contentRes.msg);
|
|
1508
|
+
const blocks = blocksRes.data?.items ?? [];
|
|
1509
|
+
const blockCounts = {};
|
|
1510
|
+
const structuredTypes = [];
|
|
1511
|
+
for (const b of blocks) {
|
|
1512
|
+
const type = b.block_type ?? 0;
|
|
1513
|
+
const name = BLOCK_TYPE_NAMES[type] || `type_${type}`;
|
|
1514
|
+
blockCounts[name] = (blockCounts[name] || 0) + 1;
|
|
1515
|
+
if (STRUCTURED_BLOCK_TYPES.has(type) && !structuredTypes.includes(name)) structuredTypes.push(name);
|
|
1516
|
+
}
|
|
1517
|
+
let hint;
|
|
1518
|
+
if (structuredTypes.length > 0) hint = `This document contains ${structuredTypes.join(", ")} which are NOT included in the plain text above. Use feishu_doc with action: "list_blocks" to get full content.`;
|
|
1519
|
+
return {
|
|
1520
|
+
title: infoRes.data?.document?.title,
|
|
1521
|
+
content: contentRes.data?.content,
|
|
1522
|
+
revision_id: infoRes.data?.document?.revision_id,
|
|
1523
|
+
block_count: blocks.length,
|
|
1524
|
+
block_types: blockCounts,
|
|
1525
|
+
...hint && { hint }
|
|
1526
|
+
};
|
|
1527
|
+
}
|
|
1528
|
+
async function createDoc(client, title, folderToken, options) {
|
|
1529
|
+
const res = await client.docx.document.create({ data: {
|
|
1530
|
+
title,
|
|
1531
|
+
folder_token: folderToken
|
|
1532
|
+
} });
|
|
1533
|
+
if (res.code !== 0) throw new Error(res.msg);
|
|
1534
|
+
const doc = res.data?.document;
|
|
1535
|
+
const docToken = doc?.document_id;
|
|
1536
|
+
if (!docToken) throw new Error("Document creation succeeded but no document_id was returned");
|
|
1537
|
+
const shouldGrantToRequester = options?.grantToRequester !== false;
|
|
1538
|
+
const requesterOpenId = options?.requesterOpenId?.trim();
|
|
1539
|
+
const requesterPermType = "edit";
|
|
1540
|
+
let requesterPermissionAdded = false;
|
|
1541
|
+
let requesterPermissionSkippedReason;
|
|
1542
|
+
let requesterPermissionError;
|
|
1543
|
+
if (shouldGrantToRequester) if (!requesterOpenId) requesterPermissionSkippedReason = "trusted requester identity unavailable";
|
|
1544
|
+
else try {
|
|
1545
|
+
await client.drive.permissionMember.create({
|
|
1546
|
+
path: { token: docToken },
|
|
1547
|
+
params: {
|
|
1548
|
+
type: "docx",
|
|
1549
|
+
need_notification: false
|
|
1550
|
+
},
|
|
1551
|
+
data: {
|
|
1552
|
+
member_type: "openid",
|
|
1553
|
+
member_id: requesterOpenId,
|
|
1554
|
+
perm: requesterPermType
|
|
1555
|
+
}
|
|
1556
|
+
});
|
|
1557
|
+
requesterPermissionAdded = true;
|
|
1558
|
+
} catch (err) {
|
|
1559
|
+
requesterPermissionError = err instanceof Error ? err.message : String(err);
|
|
1560
|
+
}
|
|
1561
|
+
return {
|
|
1562
|
+
document_id: docToken,
|
|
1563
|
+
title: doc?.title,
|
|
1564
|
+
url: `https://feishu.cn/docx/${docToken}`,
|
|
1565
|
+
...shouldGrantToRequester && {
|
|
1566
|
+
requester_permission_added: requesterPermissionAdded,
|
|
1567
|
+
...requesterOpenId && { requester_open_id: requesterOpenId },
|
|
1568
|
+
requester_perm_type: requesterPermType,
|
|
1569
|
+
...requesterPermissionSkippedReason && { requester_permission_skipped_reason: requesterPermissionSkippedReason },
|
|
1570
|
+
...requesterPermissionError && { requester_permission_error: requesterPermissionError }
|
|
1571
|
+
}
|
|
1572
|
+
};
|
|
1573
|
+
}
|
|
1574
|
+
async function writeDoc(client, docToken, markdown, maxBytes, logger) {
|
|
1575
|
+
const deleted = await clearDocumentContent(client, docToken);
|
|
1576
|
+
logger?.info?.("feishu_doc: Converting markdown...");
|
|
1577
|
+
const { blocks, firstLevelBlockIds } = await chunkedConvertMarkdown(client, markdown);
|
|
1578
|
+
if (blocks.length === 0) return {
|
|
1579
|
+
success: true,
|
|
1580
|
+
blocks_deleted: deleted,
|
|
1581
|
+
blocks_added: 0,
|
|
1582
|
+
images_processed: 0
|
|
1583
|
+
};
|
|
1584
|
+
logger?.info?.(`feishu_doc: Converted to ${blocks.length} blocks, inserting...`);
|
|
1585
|
+
const sortedBlocks = sortBlocksByFirstLevel(blocks, firstLevelBlockIds);
|
|
1586
|
+
const { children: inserted } = blocks.length > 1e3 ? await insertBlocksInBatches(client, docToken, sortedBlocks, firstLevelBlockIds, logger) : await insertBlocksWithDescendant(client, docToken, sortedBlocks, firstLevelBlockIds);
|
|
1587
|
+
const imagesProcessed = await processImages(client, docToken, markdown, inserted, maxBytes);
|
|
1588
|
+
logger?.info?.(`feishu_doc: Done (${blocks.length} blocks, ${imagesProcessed} images)`);
|
|
1589
|
+
return {
|
|
1590
|
+
success: true,
|
|
1591
|
+
blocks_deleted: deleted,
|
|
1592
|
+
blocks_added: blocks.length,
|
|
1593
|
+
images_processed: imagesProcessed
|
|
1594
|
+
};
|
|
1595
|
+
}
|
|
1596
|
+
async function appendDoc(client, docToken, markdown, maxBytes, logger) {
|
|
1597
|
+
logger?.info?.("feishu_doc: Converting markdown...");
|
|
1598
|
+
const { blocks, firstLevelBlockIds } = await chunkedConvertMarkdown(client, markdown);
|
|
1599
|
+
if (blocks.length === 0) throw new Error("Content is empty");
|
|
1600
|
+
logger?.info?.(`feishu_doc: Converted to ${blocks.length} blocks, inserting...`);
|
|
1601
|
+
const sortedBlocks = sortBlocksByFirstLevel(blocks, firstLevelBlockIds);
|
|
1602
|
+
const { children: inserted } = blocks.length > 1e3 ? await insertBlocksInBatches(client, docToken, sortedBlocks, firstLevelBlockIds, logger) : await insertBlocksWithDescendant(client, docToken, sortedBlocks, firstLevelBlockIds);
|
|
1603
|
+
const imagesProcessed = await processImages(client, docToken, markdown, inserted, maxBytes);
|
|
1604
|
+
logger?.info?.(`feishu_doc: Done (${blocks.length} blocks, ${imagesProcessed} images)`);
|
|
1605
|
+
return {
|
|
1606
|
+
success: true,
|
|
1607
|
+
blocks_added: blocks.length,
|
|
1608
|
+
images_processed: imagesProcessed,
|
|
1609
|
+
block_ids: inserted.map((b) => b.block_id)
|
|
1610
|
+
};
|
|
1611
|
+
}
|
|
1612
|
+
async function insertDoc(client, docToken, markdown, afterBlockId, maxBytes, logger) {
|
|
1613
|
+
const blockInfo = await client.docx.documentBlock.get({ path: {
|
|
1614
|
+
document_id: docToken,
|
|
1615
|
+
block_id: afterBlockId
|
|
1616
|
+
} });
|
|
1617
|
+
if (blockInfo.code !== 0) throw new Error(blockInfo.msg);
|
|
1618
|
+
const parentId = blockInfo.data?.block?.parent_id ?? docToken;
|
|
1619
|
+
const items = [];
|
|
1620
|
+
let pageToken;
|
|
1621
|
+
do {
|
|
1622
|
+
const childrenRes = await client.docx.documentBlockChildren.get({
|
|
1623
|
+
path: {
|
|
1624
|
+
document_id: docToken,
|
|
1625
|
+
block_id: parentId
|
|
1626
|
+
},
|
|
1627
|
+
params: pageToken ? { page_token: pageToken } : {}
|
|
1628
|
+
});
|
|
1629
|
+
if (childrenRes.code !== 0) throw new Error(childrenRes.msg);
|
|
1630
|
+
items.push(...childrenRes.data?.items ?? []);
|
|
1631
|
+
pageToken = childrenRes.data?.page_token ?? void 0;
|
|
1632
|
+
} while (pageToken);
|
|
1633
|
+
const blockIndex = items.findIndex((item) => item.block_id === afterBlockId);
|
|
1634
|
+
if (blockIndex === -1) throw new Error(`after_block_id "${afterBlockId}" was not found among the children of parent block "${parentId}". Use list_blocks to verify the block ID.`);
|
|
1635
|
+
const insertIndex = blockIndex + 1;
|
|
1636
|
+
logger?.info?.("feishu_doc: Converting markdown...");
|
|
1637
|
+
const { blocks, firstLevelBlockIds } = await chunkedConvertMarkdown(client, markdown);
|
|
1638
|
+
if (blocks.length === 0) throw new Error("Content is empty");
|
|
1639
|
+
const sortedBlocks = sortBlocksByFirstLevel(blocks, firstLevelBlockIds);
|
|
1640
|
+
logger?.info?.(`feishu_doc: Converted to ${blocks.length} blocks, inserting at index ${insertIndex}...`);
|
|
1641
|
+
const { children: inserted } = blocks.length > 1e3 ? await insertBlocksInBatches(client, docToken, sortedBlocks, firstLevelBlockIds, logger, parentId, insertIndex) : await insertBlocksWithDescendant(client, docToken, sortedBlocks, firstLevelBlockIds, {
|
|
1642
|
+
parentBlockId: parentId,
|
|
1643
|
+
index: insertIndex
|
|
1644
|
+
});
|
|
1645
|
+
const imagesProcessed = await processImages(client, docToken, markdown, inserted, maxBytes);
|
|
1646
|
+
logger?.info?.(`feishu_doc: Done (${blocks.length} blocks, ${imagesProcessed} images)`);
|
|
1647
|
+
return {
|
|
1648
|
+
success: true,
|
|
1649
|
+
blocks_added: blocks.length,
|
|
1650
|
+
images_processed: imagesProcessed,
|
|
1651
|
+
block_ids: inserted.map((b) => b.block_id)
|
|
1652
|
+
};
|
|
1653
|
+
}
|
|
1654
|
+
async function createTable(client, docToken, rowSize, columnSize, parentBlockId, columnWidth) {
|
|
1655
|
+
if (columnWidth && columnWidth.length !== columnSize) throw new Error("column_width length must equal column_size");
|
|
1656
|
+
const blockId = parentBlockId ?? docToken;
|
|
1657
|
+
const res = await client.docx.documentBlockChildren.create({
|
|
1658
|
+
path: {
|
|
1659
|
+
document_id: docToken,
|
|
1660
|
+
block_id: blockId
|
|
1661
|
+
},
|
|
1662
|
+
data: { children: [{
|
|
1663
|
+
block_type: 31,
|
|
1664
|
+
table: { property: {
|
|
1665
|
+
row_size: rowSize,
|
|
1666
|
+
column_size: columnSize,
|
|
1667
|
+
...columnWidth && columnWidth.length > 0 ? { column_width: columnWidth } : {}
|
|
1668
|
+
} }
|
|
1669
|
+
}] }
|
|
1670
|
+
});
|
|
1671
|
+
if (res.code !== 0) throw new Error(res.msg);
|
|
1672
|
+
const tableBlock = (res.data?.children)?.find((b) => b.block_type === 31);
|
|
1673
|
+
const cells = tableBlock?.children ?? [];
|
|
1674
|
+
return {
|
|
1675
|
+
success: true,
|
|
1676
|
+
table_block_id: tableBlock?.block_id,
|
|
1677
|
+
row_size: rowSize,
|
|
1678
|
+
column_size: columnSize,
|
|
1679
|
+
table_cell_block_ids: cells.map((c) => c.block_id).filter(Boolean),
|
|
1680
|
+
raw_children_count: res.data?.children?.length ?? 0
|
|
1681
|
+
};
|
|
1682
|
+
}
|
|
1683
|
+
async function writeTableCells(client, docToken, tableBlockId, values) {
|
|
1684
|
+
if (!values.length || !values[0]?.length) throw new Error("values must be a non-empty 2D array");
|
|
1685
|
+
const tableRes = await client.docx.documentBlock.get({ path: {
|
|
1686
|
+
document_id: docToken,
|
|
1687
|
+
block_id: tableBlockId
|
|
1688
|
+
} });
|
|
1689
|
+
if (tableRes.code !== 0) throw new Error(tableRes.msg);
|
|
1690
|
+
const tableBlock = tableRes.data?.block;
|
|
1691
|
+
if (tableBlock?.block_type !== 31) throw new Error("table_block_id is not a table block");
|
|
1692
|
+
const tableData = tableBlock.table;
|
|
1693
|
+
const rows = tableData?.property?.row_size;
|
|
1694
|
+
const cols = tableData?.property?.column_size;
|
|
1695
|
+
const cellIds = tableData?.cells ?? [];
|
|
1696
|
+
if (!rows || !cols || !cellIds.length) throw new Error("Table cell IDs unavailable from table block. Use list_blocks/get_block and pass explicit cell block IDs if needed.");
|
|
1697
|
+
const writeRows = Math.min(values.length, rows);
|
|
1698
|
+
let written = 0;
|
|
1699
|
+
for (let r = 0; r < writeRows; r++) {
|
|
1700
|
+
const rowValues = values[r] ?? [];
|
|
1701
|
+
const writeCols = Math.min(rowValues.length, cols);
|
|
1702
|
+
for (let c = 0; c < writeCols; c++) {
|
|
1703
|
+
const cellId = cellIds[r * cols + c];
|
|
1704
|
+
if (!cellId) continue;
|
|
1705
|
+
const childrenRes = await client.docx.documentBlockChildren.get({ path: {
|
|
1706
|
+
document_id: docToken,
|
|
1707
|
+
block_id: cellId
|
|
1708
|
+
} });
|
|
1709
|
+
if (childrenRes.code !== 0) throw new Error(childrenRes.msg);
|
|
1710
|
+
const existingChildren = childrenRes.data?.items ?? [];
|
|
1711
|
+
if (existingChildren.length > 0) {
|
|
1712
|
+
const delRes = await client.docx.documentBlockChildren.batchDelete({
|
|
1713
|
+
path: {
|
|
1714
|
+
document_id: docToken,
|
|
1715
|
+
block_id: cellId
|
|
1716
|
+
},
|
|
1717
|
+
data: {
|
|
1718
|
+
start_index: 0,
|
|
1719
|
+
end_index: existingChildren.length
|
|
1720
|
+
}
|
|
1721
|
+
});
|
|
1722
|
+
if (delRes.code !== 0) throw new Error(delRes.msg);
|
|
1723
|
+
}
|
|
1724
|
+
const converted = await convertMarkdown(client, rowValues[c] ?? "");
|
|
1725
|
+
const sorted = sortBlocksByFirstLevel(converted.blocks, converted.firstLevelBlockIds);
|
|
1726
|
+
if (sorted.length > 0) await insertBlocks(client, docToken, sorted, cellId);
|
|
1727
|
+
written++;
|
|
1728
|
+
}
|
|
1729
|
+
}
|
|
1730
|
+
return {
|
|
1731
|
+
success: true,
|
|
1732
|
+
table_block_id: tableBlockId,
|
|
1733
|
+
cells_written: written,
|
|
1734
|
+
table_size: {
|
|
1735
|
+
rows,
|
|
1736
|
+
cols
|
|
1737
|
+
}
|
|
1738
|
+
};
|
|
1739
|
+
}
|
|
1740
|
+
async function createTableWithValues(client, docToken, rowSize, columnSize, values, parentBlockId, columnWidth) {
|
|
1741
|
+
const tableBlockId = (await createTable(client, docToken, rowSize, columnSize, parentBlockId, columnWidth)).table_block_id;
|
|
1742
|
+
if (!tableBlockId) throw new Error("create_table succeeded but table_block_id is missing");
|
|
1743
|
+
return {
|
|
1744
|
+
success: true,
|
|
1745
|
+
table_block_id: tableBlockId,
|
|
1746
|
+
row_size: rowSize,
|
|
1747
|
+
column_size: columnSize,
|
|
1748
|
+
cells_written: (await writeTableCells(client, docToken, tableBlockId, values)).cells_written
|
|
1749
|
+
};
|
|
1750
|
+
}
|
|
1751
|
+
async function updateBlock(client, docToken, blockId, content) {
|
|
1752
|
+
const blockInfo = await client.docx.documentBlock.get({ path: {
|
|
1753
|
+
document_id: docToken,
|
|
1754
|
+
block_id: blockId
|
|
1755
|
+
} });
|
|
1756
|
+
if (blockInfo.code !== 0) throw new Error(blockInfo.msg);
|
|
1757
|
+
const res = await client.docx.documentBlock.patch({
|
|
1758
|
+
path: {
|
|
1759
|
+
document_id: docToken,
|
|
1760
|
+
block_id: blockId
|
|
1761
|
+
},
|
|
1762
|
+
data: { update_text_elements: { elements: [{ text_run: { content } }] } }
|
|
1763
|
+
});
|
|
1764
|
+
if (res.code !== 0) throw new Error(res.msg);
|
|
1765
|
+
return {
|
|
1766
|
+
success: true,
|
|
1767
|
+
block_id: blockId
|
|
1768
|
+
};
|
|
1769
|
+
}
|
|
1770
|
+
async function deleteBlock(client, docToken, blockId) {
|
|
1771
|
+
const blockInfo = await client.docx.documentBlock.get({ path: {
|
|
1772
|
+
document_id: docToken,
|
|
1773
|
+
block_id: blockId
|
|
1774
|
+
} });
|
|
1775
|
+
if (blockInfo.code !== 0) throw new Error(blockInfo.msg);
|
|
1776
|
+
const parentId = blockInfo.data?.block?.parent_id ?? docToken;
|
|
1777
|
+
const children = await client.docx.documentBlockChildren.get({ path: {
|
|
1778
|
+
document_id: docToken,
|
|
1779
|
+
block_id: parentId
|
|
1780
|
+
} });
|
|
1781
|
+
if (children.code !== 0) throw new Error(children.msg);
|
|
1782
|
+
const index = (children.data?.items ?? []).findIndex((item) => item.block_id === blockId);
|
|
1783
|
+
if (index === -1) throw new Error("Block not found");
|
|
1784
|
+
const res = await client.docx.documentBlockChildren.batchDelete({
|
|
1785
|
+
path: {
|
|
1786
|
+
document_id: docToken,
|
|
1787
|
+
block_id: parentId
|
|
1788
|
+
},
|
|
1789
|
+
data: {
|
|
1790
|
+
start_index: index,
|
|
1791
|
+
end_index: index + 1
|
|
1792
|
+
}
|
|
1793
|
+
});
|
|
1794
|
+
if (res.code !== 0) throw new Error(res.msg);
|
|
1795
|
+
return {
|
|
1796
|
+
success: true,
|
|
1797
|
+
deleted_block_id: blockId
|
|
1798
|
+
};
|
|
1799
|
+
}
|
|
1800
|
+
async function listBlocks(client, docToken) {
|
|
1801
|
+
const res = await client.docx.documentBlock.list({ path: { document_id: docToken } });
|
|
1802
|
+
if (res.code !== 0) throw new Error(res.msg);
|
|
1803
|
+
return { blocks: res.data?.items ?? [] };
|
|
1804
|
+
}
|
|
1805
|
+
async function getBlock(client, docToken, blockId) {
|
|
1806
|
+
const res = await client.docx.documentBlock.get({ path: {
|
|
1807
|
+
document_id: docToken,
|
|
1808
|
+
block_id: blockId
|
|
1809
|
+
} });
|
|
1810
|
+
if (res.code !== 0) throw new Error(res.msg);
|
|
1811
|
+
return { block: res.data?.block };
|
|
1812
|
+
}
|
|
1813
|
+
async function listAppScopes(client) {
|
|
1814
|
+
const res = await client.application.scope.list({});
|
|
1815
|
+
if (res.code !== 0) throw new Error(res.msg);
|
|
1816
|
+
const scopes = res.data?.scopes ?? [];
|
|
1817
|
+
const granted = scopes.filter((s) => s.grant_status === 1);
|
|
1818
|
+
const pending = scopes.filter((s) => s.grant_status !== 1);
|
|
1819
|
+
return {
|
|
1820
|
+
granted: granted.map((s) => ({
|
|
1821
|
+
name: s.scope_name,
|
|
1822
|
+
type: s.scope_type
|
|
1823
|
+
})),
|
|
1824
|
+
pending: pending.map((s) => ({
|
|
1825
|
+
name: s.scope_name,
|
|
1826
|
+
type: s.scope_type
|
|
1827
|
+
})),
|
|
1828
|
+
summary: `${granted.length} granted, ${pending.length} pending`
|
|
1829
|
+
};
|
|
1830
|
+
}
|
|
1831
|
+
function registerFeishuDocTools(api) {
|
|
1832
|
+
if (!api.config) {
|
|
1833
|
+
api.logger.debug?.("feishu_doc: No config available, skipping doc tools");
|
|
1834
|
+
return;
|
|
1835
|
+
}
|
|
1836
|
+
const accounts = listEnabledFeishuAccounts(api.config);
|
|
1837
|
+
if (accounts.length === 0) {
|
|
1838
|
+
api.logger.debug?.("feishu_doc: No Feishu accounts configured, skipping doc tools");
|
|
1839
|
+
return;
|
|
1840
|
+
}
|
|
1841
|
+
const toolsCfg = resolveAnyEnabledFeishuToolsConfig(accounts);
|
|
1842
|
+
const registered = [];
|
|
1843
|
+
const getClient = (params, defaultAccountId) => createFeishuToolClient({
|
|
1844
|
+
api,
|
|
1845
|
+
executeParams: params,
|
|
1846
|
+
defaultAccountId
|
|
1847
|
+
});
|
|
1848
|
+
const getMediaMaxBytes = (params, defaultAccountId) => (resolveFeishuToolAccount({
|
|
1849
|
+
api,
|
|
1850
|
+
executeParams: params,
|
|
1851
|
+
defaultAccountId
|
|
1852
|
+
}).config?.mediaMaxMb ?? 30) * 1024 * 1024;
|
|
1853
|
+
if (toolsCfg.doc) {
|
|
1854
|
+
api.registerTool((ctx) => {
|
|
1855
|
+
const defaultAccountId = ctx.agentAccountId;
|
|
1856
|
+
const trustedRequesterOpenId = ctx.messageChannel === "feishu" ? ctx.requesterSenderId?.trim() || void 0 : void 0;
|
|
1857
|
+
return {
|
|
1858
|
+
name: "feishu_doc",
|
|
1859
|
+
label: "Feishu Doc",
|
|
1860
|
+
description: "Feishu document operations. Actions: read, write, append, insert, create, list_blocks, get_block, update_block, delete_block, create_table, write_table_cells, create_table_with_values, insert_table_row, insert_table_column, delete_table_rows, delete_table_columns, merge_table_cells, upload_image, upload_file, color_text",
|
|
1861
|
+
parameters: FeishuDocSchema,
|
|
1862
|
+
async execute(_toolCallId, params) {
|
|
1863
|
+
const p = params;
|
|
1864
|
+
try {
|
|
1865
|
+
const client = getClient(p, defaultAccountId);
|
|
1866
|
+
switch (p.action) {
|
|
1867
|
+
case "read": return json(await readDoc(client, p.doc_token));
|
|
1868
|
+
case "write": return json(await writeDoc(client, p.doc_token, p.content, getMediaMaxBytes(p, defaultAccountId), api.logger));
|
|
1869
|
+
case "append": return json(await appendDoc(client, p.doc_token, p.content, getMediaMaxBytes(p, defaultAccountId), api.logger));
|
|
1870
|
+
case "insert": return json(await insertDoc(client, p.doc_token, p.content, p.after_block_id, getMediaMaxBytes(p, defaultAccountId), api.logger));
|
|
1871
|
+
case "create": return json(await createDoc(client, p.title, p.folder_token, {
|
|
1872
|
+
grantToRequester: p.grant_to_requester,
|
|
1873
|
+
requesterOpenId: trustedRequesterOpenId
|
|
1874
|
+
}));
|
|
1875
|
+
case "list_blocks": return json(await listBlocks(client, p.doc_token));
|
|
1876
|
+
case "get_block": return json(await getBlock(client, p.doc_token, p.block_id));
|
|
1877
|
+
case "update_block": return json(await updateBlock(client, p.doc_token, p.block_id, p.content));
|
|
1878
|
+
case "delete_block": return json(await deleteBlock(client, p.doc_token, p.block_id));
|
|
1879
|
+
case "create_table": return json(await createTable(client, p.doc_token, p.row_size, p.column_size, p.parent_block_id, p.column_width));
|
|
1880
|
+
case "write_table_cells": return json(await writeTableCells(client, p.doc_token, p.table_block_id, p.values));
|
|
1881
|
+
case "create_table_with_values": return json(await createTableWithValues(client, p.doc_token, p.row_size, p.column_size, p.values, p.parent_block_id, p.column_width));
|
|
1882
|
+
case "upload_image": return json(await uploadImageBlock(client, p.doc_token, getMediaMaxBytes(p, defaultAccountId), p.url, p.file_path, p.parent_block_id, p.filename, p.index, p.image));
|
|
1883
|
+
case "upload_file": return json(await uploadFileBlock(client, p.doc_token, getMediaMaxBytes(p, defaultAccountId), p.url, p.file_path, p.parent_block_id, p.filename));
|
|
1884
|
+
case "color_text": return json(await updateColorText(client, p.doc_token, p.block_id, p.content));
|
|
1885
|
+
case "insert_table_row": return json(await insertTableRow(client, p.doc_token, p.block_id, p.row_index));
|
|
1886
|
+
case "insert_table_column": return json(await insertTableColumn(client, p.doc_token, p.block_id, p.column_index));
|
|
1887
|
+
case "delete_table_rows": return json(await deleteTableRows(client, p.doc_token, p.block_id, p.row_start, p.row_count));
|
|
1888
|
+
case "delete_table_columns": return json(await deleteTableColumns(client, p.doc_token, p.block_id, p.column_start, p.column_count));
|
|
1889
|
+
case "merge_table_cells": return json(await mergeTableCells(client, p.doc_token, p.block_id, p.row_start, p.row_end, p.column_start, p.column_end));
|
|
1890
|
+
default: return json({ error: `Unknown action: ${p.action}` });
|
|
1891
|
+
}
|
|
1892
|
+
} catch (err) {
|
|
1893
|
+
return json({ error: err instanceof Error ? err.message : String(err) });
|
|
1894
|
+
}
|
|
1895
|
+
}
|
|
1896
|
+
};
|
|
1897
|
+
}, { name: "feishu_doc" });
|
|
1898
|
+
registered.push("feishu_doc");
|
|
1899
|
+
}
|
|
1900
|
+
if (toolsCfg.scopes) {
|
|
1901
|
+
api.registerTool((ctx) => ({
|
|
1902
|
+
name: "feishu_app_scopes",
|
|
1903
|
+
label: "Feishu App Scopes",
|
|
1904
|
+
description: "List current app permissions (scopes). Use to debug permission issues or check available capabilities.",
|
|
1905
|
+
parameters: Type.Object({}),
|
|
1906
|
+
async execute() {
|
|
1907
|
+
try {
|
|
1908
|
+
return json(await listAppScopes(getClient(void 0, ctx.agentAccountId)));
|
|
1909
|
+
} catch (err) {
|
|
1910
|
+
return json({ error: err instanceof Error ? err.message : String(err) });
|
|
1911
|
+
}
|
|
1912
|
+
}
|
|
1913
|
+
}), { name: "feishu_app_scopes" });
|
|
1914
|
+
registered.push("feishu_app_scopes");
|
|
1915
|
+
}
|
|
1916
|
+
if (registered.length > 0) api.logger.info?.(`feishu_doc: Registered ${registered.join(", ")}`);
|
|
1917
|
+
}
|
|
1918
|
+
//#endregion
|
|
1919
|
+
//#region extensions/feishu/src/drive-schema.ts
|
|
1920
|
+
const FileType = Type.Union([
|
|
1921
|
+
Type.Literal("doc"),
|
|
1922
|
+
Type.Literal("docx"),
|
|
1923
|
+
Type.Literal("sheet"),
|
|
1924
|
+
Type.Literal("bitable"),
|
|
1925
|
+
Type.Literal("folder"),
|
|
1926
|
+
Type.Literal("file"),
|
|
1927
|
+
Type.Literal("mindnote"),
|
|
1928
|
+
Type.Literal("shortcut")
|
|
1929
|
+
]);
|
|
1930
|
+
const FeishuDriveSchema = Type.Union([
|
|
1931
|
+
Type.Object({
|
|
1932
|
+
action: Type.Literal("list"),
|
|
1933
|
+
folder_token: Type.Optional(Type.String({ description: "Folder token (optional, omit for root directory)" }))
|
|
1934
|
+
}),
|
|
1935
|
+
Type.Object({
|
|
1936
|
+
action: Type.Literal("info"),
|
|
1937
|
+
file_token: Type.String({ description: "File or folder token" }),
|
|
1938
|
+
type: FileType
|
|
1939
|
+
}),
|
|
1940
|
+
Type.Object({
|
|
1941
|
+
action: Type.Literal("create_folder"),
|
|
1942
|
+
name: Type.String({ description: "Folder name" }),
|
|
1943
|
+
folder_token: Type.Optional(Type.String({ description: "Parent folder token (optional, omit for root)" }))
|
|
1944
|
+
}),
|
|
1945
|
+
Type.Object({
|
|
1946
|
+
action: Type.Literal("move"),
|
|
1947
|
+
file_token: Type.String({ description: "File token to move" }),
|
|
1948
|
+
type: FileType,
|
|
1949
|
+
folder_token: Type.String({ description: "Target folder token" })
|
|
1950
|
+
}),
|
|
1951
|
+
Type.Object({
|
|
1952
|
+
action: Type.Literal("delete"),
|
|
1953
|
+
file_token: Type.String({ description: "File token to delete" }),
|
|
1954
|
+
type: FileType
|
|
1955
|
+
})
|
|
1956
|
+
]);
|
|
1957
|
+
//#endregion
|
|
1958
|
+
//#region extensions/feishu/src/tool-result.ts
|
|
1959
|
+
function jsonToolResult(data) {
|
|
1960
|
+
return {
|
|
1961
|
+
content: [{
|
|
1962
|
+
type: "text",
|
|
1963
|
+
text: JSON.stringify(data, null, 2)
|
|
1964
|
+
}],
|
|
1965
|
+
details: data
|
|
1966
|
+
};
|
|
1967
|
+
}
|
|
1968
|
+
function unknownToolActionResult(action) {
|
|
1969
|
+
return jsonToolResult({ error: `Unknown action: ${String(action)}` });
|
|
1970
|
+
}
|
|
1971
|
+
function toolExecutionErrorResult(error) {
|
|
1972
|
+
return jsonToolResult({ error: error instanceof Error ? error.message : String(error) });
|
|
1973
|
+
}
|
|
1974
|
+
//#endregion
|
|
1975
|
+
//#region extensions/feishu/src/drive.ts
|
|
1976
|
+
async function getRootFolderToken(client) {
|
|
1977
|
+
const domain = client.domain ?? "https://open.feishu.cn";
|
|
1978
|
+
const res = await client.httpInstance.get(`${domain}/open-apis/drive/explorer/v2/root_folder/meta`);
|
|
1979
|
+
if (res.code !== 0) throw new Error(res.msg ?? "Failed to get root folder");
|
|
1980
|
+
const token = res.data?.token;
|
|
1981
|
+
if (!token) throw new Error("Root folder token not found");
|
|
1982
|
+
return token;
|
|
1983
|
+
}
|
|
1984
|
+
async function listFolder(client, folderToken) {
|
|
1985
|
+
const validFolderToken = folderToken && folderToken !== "0" ? folderToken : void 0;
|
|
1986
|
+
const res = await client.drive.file.list({ params: validFolderToken ? { folder_token: validFolderToken } : {} });
|
|
1987
|
+
if (res.code !== 0) throw new Error(res.msg);
|
|
1988
|
+
return {
|
|
1989
|
+
files: res.data?.files?.map((f) => ({
|
|
1990
|
+
token: f.token,
|
|
1991
|
+
name: f.name,
|
|
1992
|
+
type: f.type,
|
|
1993
|
+
url: f.url,
|
|
1994
|
+
created_time: f.created_time,
|
|
1995
|
+
modified_time: f.modified_time,
|
|
1996
|
+
owner_id: f.owner_id
|
|
1997
|
+
})) ?? [],
|
|
1998
|
+
next_page_token: res.data?.next_page_token
|
|
1999
|
+
};
|
|
2000
|
+
}
|
|
2001
|
+
async function getFileInfo(client, fileToken, folderToken) {
|
|
2002
|
+
const res = await client.drive.file.list({ params: folderToken ? { folder_token: folderToken } : {} });
|
|
2003
|
+
if (res.code !== 0) throw new Error(res.msg);
|
|
2004
|
+
const file = res.data?.files?.find((f) => f.token === fileToken);
|
|
2005
|
+
if (!file) throw new Error(`File not found: ${fileToken}`);
|
|
2006
|
+
return {
|
|
2007
|
+
token: file.token,
|
|
2008
|
+
name: file.name,
|
|
2009
|
+
type: file.type,
|
|
2010
|
+
url: file.url,
|
|
2011
|
+
created_time: file.created_time,
|
|
2012
|
+
modified_time: file.modified_time,
|
|
2013
|
+
owner_id: file.owner_id
|
|
2014
|
+
};
|
|
2015
|
+
}
|
|
2016
|
+
async function createFolder(client, name, folderToken) {
|
|
2017
|
+
let effectiveToken = folderToken && folderToken !== "0" ? folderToken : "0";
|
|
2018
|
+
if (effectiveToken === "0") try {
|
|
2019
|
+
effectiveToken = await getRootFolderToken(client);
|
|
2020
|
+
} catch {}
|
|
2021
|
+
const res = await client.drive.file.createFolder({ data: {
|
|
2022
|
+
name,
|
|
2023
|
+
folder_token: effectiveToken
|
|
2024
|
+
} });
|
|
2025
|
+
if (res.code !== 0) throw new Error(res.msg);
|
|
2026
|
+
return {
|
|
2027
|
+
token: res.data?.token,
|
|
2028
|
+
url: res.data?.url
|
|
2029
|
+
};
|
|
2030
|
+
}
|
|
2031
|
+
async function moveFile(client, fileToken, type, folderToken) {
|
|
2032
|
+
const res = await client.drive.file.move({
|
|
2033
|
+
path: { file_token: fileToken },
|
|
2034
|
+
data: {
|
|
2035
|
+
type,
|
|
2036
|
+
folder_token: folderToken
|
|
2037
|
+
}
|
|
2038
|
+
});
|
|
2039
|
+
if (res.code !== 0) throw new Error(res.msg);
|
|
2040
|
+
return {
|
|
2041
|
+
success: true,
|
|
2042
|
+
task_id: res.data?.task_id
|
|
2043
|
+
};
|
|
2044
|
+
}
|
|
2045
|
+
async function deleteFile(client, fileToken, type) {
|
|
2046
|
+
const res = await client.drive.file.delete({
|
|
2047
|
+
path: { file_token: fileToken },
|
|
2048
|
+
params: { type }
|
|
2049
|
+
});
|
|
2050
|
+
if (res.code !== 0) throw new Error(res.msg);
|
|
2051
|
+
return {
|
|
2052
|
+
success: true,
|
|
2053
|
+
task_id: res.data?.task_id
|
|
2054
|
+
};
|
|
2055
|
+
}
|
|
2056
|
+
function registerFeishuDriveTools(api) {
|
|
2057
|
+
if (!api.config) {
|
|
2058
|
+
api.logger.debug?.("feishu_drive: No config available, skipping drive tools");
|
|
2059
|
+
return;
|
|
2060
|
+
}
|
|
2061
|
+
const accounts = listEnabledFeishuAccounts(api.config);
|
|
2062
|
+
if (accounts.length === 0) {
|
|
2063
|
+
api.logger.debug?.("feishu_drive: No Feishu accounts configured, skipping drive tools");
|
|
2064
|
+
return;
|
|
2065
|
+
}
|
|
2066
|
+
if (!resolveAnyEnabledFeishuToolsConfig(accounts).drive) {
|
|
2067
|
+
api.logger.debug?.("feishu_drive: drive tool disabled in config");
|
|
2068
|
+
return;
|
|
2069
|
+
}
|
|
2070
|
+
api.registerTool((ctx) => {
|
|
2071
|
+
const defaultAccountId = ctx.agentAccountId;
|
|
2072
|
+
return {
|
|
2073
|
+
name: "feishu_drive",
|
|
2074
|
+
label: "Feishu Drive",
|
|
2075
|
+
description: "Feishu cloud storage operations. Actions: list, info, create_folder, move, delete",
|
|
2076
|
+
parameters: FeishuDriveSchema,
|
|
2077
|
+
async execute(_toolCallId, params) {
|
|
2078
|
+
const p = params;
|
|
2079
|
+
try {
|
|
2080
|
+
const client = createFeishuToolClient({
|
|
2081
|
+
api,
|
|
2082
|
+
executeParams: p,
|
|
2083
|
+
defaultAccountId
|
|
2084
|
+
});
|
|
2085
|
+
switch (p.action) {
|
|
2086
|
+
case "list": return jsonToolResult(await listFolder(client, p.folder_token));
|
|
2087
|
+
case "info": return jsonToolResult(await getFileInfo(client, p.file_token));
|
|
2088
|
+
case "create_folder": return jsonToolResult(await createFolder(client, p.name, p.folder_token));
|
|
2089
|
+
case "move": return jsonToolResult(await moveFile(client, p.file_token, p.type, p.folder_token));
|
|
2090
|
+
case "delete": return jsonToolResult(await deleteFile(client, p.file_token, p.type));
|
|
2091
|
+
default: return unknownToolActionResult(p.action);
|
|
2092
|
+
}
|
|
2093
|
+
} catch (err) {
|
|
2094
|
+
return toolExecutionErrorResult(err);
|
|
2095
|
+
}
|
|
2096
|
+
}
|
|
2097
|
+
};
|
|
2098
|
+
}, { name: "feishu_drive" });
|
|
2099
|
+
api.logger.info?.(`feishu_drive: Registered feishu_drive tool`);
|
|
2100
|
+
}
|
|
2101
|
+
//#endregion
|
|
2102
|
+
//#region extensions/feishu/src/perm-schema.ts
|
|
2103
|
+
const TokenType = Type.Union([
|
|
2104
|
+
Type.Literal("doc"),
|
|
2105
|
+
Type.Literal("docx"),
|
|
2106
|
+
Type.Literal("sheet"),
|
|
2107
|
+
Type.Literal("bitable"),
|
|
2108
|
+
Type.Literal("folder"),
|
|
2109
|
+
Type.Literal("file"),
|
|
2110
|
+
Type.Literal("wiki"),
|
|
2111
|
+
Type.Literal("mindnote")
|
|
2112
|
+
]);
|
|
2113
|
+
const MemberType = Type.Union([
|
|
2114
|
+
Type.Literal("email"),
|
|
2115
|
+
Type.Literal("openid"),
|
|
2116
|
+
Type.Literal("userid"),
|
|
2117
|
+
Type.Literal("unionid"),
|
|
2118
|
+
Type.Literal("openchat"),
|
|
2119
|
+
Type.Literal("opendepartmentid")
|
|
2120
|
+
]);
|
|
2121
|
+
const Permission = Type.Union([
|
|
2122
|
+
Type.Literal("view"),
|
|
2123
|
+
Type.Literal("edit"),
|
|
2124
|
+
Type.Literal("full_access")
|
|
2125
|
+
]);
|
|
2126
|
+
const FeishuPermSchema = Type.Union([
|
|
2127
|
+
Type.Object({
|
|
2128
|
+
action: Type.Literal("list"),
|
|
2129
|
+
token: Type.String({ description: "File token" }),
|
|
2130
|
+
type: TokenType
|
|
2131
|
+
}),
|
|
2132
|
+
Type.Object({
|
|
2133
|
+
action: Type.Literal("add"),
|
|
2134
|
+
token: Type.String({ description: "File token" }),
|
|
2135
|
+
type: TokenType,
|
|
2136
|
+
member_type: MemberType,
|
|
2137
|
+
member_id: Type.String({ description: "Member ID (email, open_id, user_id, etc.)" }),
|
|
2138
|
+
perm: Permission
|
|
2139
|
+
}),
|
|
2140
|
+
Type.Object({
|
|
2141
|
+
action: Type.Literal("remove"),
|
|
2142
|
+
token: Type.String({ description: "File token" }),
|
|
2143
|
+
type: TokenType,
|
|
2144
|
+
member_type: MemberType,
|
|
2145
|
+
member_id: Type.String({ description: "Member ID to remove" })
|
|
2146
|
+
})
|
|
2147
|
+
]);
|
|
2148
|
+
//#endregion
|
|
2149
|
+
//#region extensions/feishu/src/perm.ts
|
|
2150
|
+
async function listMembers(client, token, type) {
|
|
2151
|
+
const res = await client.drive.permissionMember.list({
|
|
2152
|
+
path: { token },
|
|
2153
|
+
params: { type }
|
|
2154
|
+
});
|
|
2155
|
+
if (res.code !== 0) throw new Error(res.msg);
|
|
2156
|
+
return { members: res.data?.items?.map((m) => ({
|
|
2157
|
+
member_type: m.member_type,
|
|
2158
|
+
member_id: m.member_id,
|
|
2159
|
+
perm: m.perm,
|
|
2160
|
+
name: m.name
|
|
2161
|
+
})) ?? [] };
|
|
2162
|
+
}
|
|
2163
|
+
async function addMember(client, token, type, memberType, memberId, perm) {
|
|
2164
|
+
const res = await client.drive.permissionMember.create({
|
|
2165
|
+
path: { token },
|
|
2166
|
+
params: {
|
|
2167
|
+
type,
|
|
2168
|
+
need_notification: false
|
|
2169
|
+
},
|
|
2170
|
+
data: {
|
|
2171
|
+
member_type: memberType,
|
|
2172
|
+
member_id: memberId,
|
|
2173
|
+
perm
|
|
2174
|
+
}
|
|
2175
|
+
});
|
|
2176
|
+
if (res.code !== 0) throw new Error(res.msg);
|
|
2177
|
+
return {
|
|
2178
|
+
success: true,
|
|
2179
|
+
member: res.data?.member
|
|
2180
|
+
};
|
|
2181
|
+
}
|
|
2182
|
+
async function removeMember(client, token, type, memberType, memberId) {
|
|
2183
|
+
const res = await client.drive.permissionMember.delete({
|
|
2184
|
+
path: {
|
|
2185
|
+
token,
|
|
2186
|
+
member_id: memberId
|
|
2187
|
+
},
|
|
2188
|
+
params: {
|
|
2189
|
+
type,
|
|
2190
|
+
member_type: memberType
|
|
2191
|
+
}
|
|
2192
|
+
});
|
|
2193
|
+
if (res.code !== 0) throw new Error(res.msg);
|
|
2194
|
+
return { success: true };
|
|
2195
|
+
}
|
|
2196
|
+
function registerFeishuPermTools(api) {
|
|
2197
|
+
if (!api.config) {
|
|
2198
|
+
api.logger.debug?.("feishu_perm: No config available, skipping perm tools");
|
|
2199
|
+
return;
|
|
2200
|
+
}
|
|
2201
|
+
const accounts = listEnabledFeishuAccounts(api.config);
|
|
2202
|
+
if (accounts.length === 0) {
|
|
2203
|
+
api.logger.debug?.("feishu_perm: No Feishu accounts configured, skipping perm tools");
|
|
2204
|
+
return;
|
|
2205
|
+
}
|
|
2206
|
+
if (!resolveAnyEnabledFeishuToolsConfig(accounts).perm) {
|
|
2207
|
+
api.logger.debug?.("feishu_perm: perm tool disabled in config (default: false)");
|
|
2208
|
+
return;
|
|
2209
|
+
}
|
|
2210
|
+
api.registerTool((ctx) => {
|
|
2211
|
+
const defaultAccountId = ctx.agentAccountId;
|
|
2212
|
+
return {
|
|
2213
|
+
name: "feishu_perm",
|
|
2214
|
+
label: "Feishu Perm",
|
|
2215
|
+
description: "Feishu permission management. Actions: list, add, remove",
|
|
2216
|
+
parameters: FeishuPermSchema,
|
|
2217
|
+
async execute(_toolCallId, params) {
|
|
2218
|
+
const p = params;
|
|
2219
|
+
try {
|
|
2220
|
+
const client = createFeishuToolClient({
|
|
2221
|
+
api,
|
|
2222
|
+
executeParams: p,
|
|
2223
|
+
defaultAccountId
|
|
2224
|
+
});
|
|
2225
|
+
switch (p.action) {
|
|
2226
|
+
case "list": return jsonToolResult(await listMembers(client, p.token, p.type));
|
|
2227
|
+
case "add": return jsonToolResult(await addMember(client, p.token, p.type, p.member_type, p.member_id, p.perm));
|
|
2228
|
+
case "remove": return jsonToolResult(await removeMember(client, p.token, p.type, p.member_type, p.member_id));
|
|
2229
|
+
default: return unknownToolActionResult(p.action);
|
|
2230
|
+
}
|
|
2231
|
+
} catch (err) {
|
|
2232
|
+
return toolExecutionErrorResult(err);
|
|
2233
|
+
}
|
|
2234
|
+
}
|
|
2235
|
+
};
|
|
2236
|
+
}, { name: "feishu_perm" });
|
|
2237
|
+
api.logger.info?.(`feishu_perm: Registered feishu_perm tool`);
|
|
2238
|
+
}
|
|
2239
|
+
//#endregion
|
|
2240
|
+
//#region extensions/feishu/src/subagent-hooks.ts
|
|
2241
|
+
function summarizeError(err) {
|
|
2242
|
+
if (err instanceof Error) return err.message;
|
|
2243
|
+
if (typeof err === "string") return err;
|
|
2244
|
+
return "error";
|
|
2245
|
+
}
|
|
2246
|
+
function stripProviderPrefix(raw) {
|
|
2247
|
+
return raw.replace(/^(feishu|lark):/i, "").trim();
|
|
2248
|
+
}
|
|
2249
|
+
function resolveFeishuRequesterConversation(params) {
|
|
2250
|
+
const manager = getFeishuThreadBindingManager(params.accountId);
|
|
2251
|
+
if (!manager) return null;
|
|
2252
|
+
const rawTo = params.to?.trim();
|
|
2253
|
+
const withoutProviderPrefix = rawTo ? stripProviderPrefix(rawTo) : "";
|
|
2254
|
+
const normalizedTarget = rawTo ? normalizeFeishuTarget(rawTo) : null;
|
|
2255
|
+
const threadId = params.threadId != null && params.threadId !== "" ? String(params.threadId).trim() : "";
|
|
2256
|
+
const isChatTarget = /^(chat|group|channel):/i.test(withoutProviderPrefix);
|
|
2257
|
+
const parsedRequesterTopic = normalizedTarget && threadId && isChatTarget ? parseFeishuConversationId({
|
|
2258
|
+
conversationId: buildFeishuConversationId({
|
|
2259
|
+
chatId: normalizedTarget,
|
|
2260
|
+
scope: "group_topic",
|
|
2261
|
+
topicId: threadId
|
|
2262
|
+
}),
|
|
2263
|
+
parentConversationId: normalizedTarget
|
|
2264
|
+
}) : null;
|
|
2265
|
+
const requesterSessionKey = params.requesterSessionKey?.trim();
|
|
2266
|
+
if (requesterSessionKey) {
|
|
2267
|
+
const existingBindings = manager.listBySessionKey(requesterSessionKey);
|
|
2268
|
+
if (existingBindings.length === 1) {
|
|
2269
|
+
const existing = existingBindings[0];
|
|
2270
|
+
return {
|
|
2271
|
+
accountId: existing.accountId,
|
|
2272
|
+
conversationId: existing.conversationId,
|
|
2273
|
+
parentConversationId: existing.parentConversationId
|
|
2274
|
+
};
|
|
2275
|
+
}
|
|
2276
|
+
if (existingBindings.length > 1) {
|
|
2277
|
+
if (rawTo && normalizedTarget && !threadId && !isChatTarget) {
|
|
2278
|
+
const directMatches = existingBindings.filter((entry) => entry.accountId === manager.accountId && entry.conversationId === normalizedTarget && !entry.parentConversationId);
|
|
2279
|
+
if (directMatches.length === 1) {
|
|
2280
|
+
const existing = directMatches[0];
|
|
2281
|
+
return {
|
|
2282
|
+
accountId: existing.accountId,
|
|
2283
|
+
conversationId: existing.conversationId,
|
|
2284
|
+
parentConversationId: existing.parentConversationId
|
|
2285
|
+
};
|
|
2286
|
+
}
|
|
2287
|
+
return null;
|
|
2288
|
+
}
|
|
2289
|
+
if (parsedRequesterTopic) {
|
|
2290
|
+
const matchingTopicBindings = existingBindings.filter((entry) => {
|
|
2291
|
+
const parsed = parseFeishuConversationId({
|
|
2292
|
+
conversationId: entry.conversationId,
|
|
2293
|
+
parentConversationId: entry.parentConversationId
|
|
2294
|
+
});
|
|
2295
|
+
return parsed?.chatId === parsedRequesterTopic.chatId && parsed?.topicId === parsedRequesterTopic.topicId;
|
|
2296
|
+
});
|
|
2297
|
+
if (matchingTopicBindings.length === 1) {
|
|
2298
|
+
const existing = matchingTopicBindings[0];
|
|
2299
|
+
return {
|
|
2300
|
+
accountId: existing.accountId,
|
|
2301
|
+
conversationId: existing.conversationId,
|
|
2302
|
+
parentConversationId: existing.parentConversationId
|
|
2303
|
+
};
|
|
2304
|
+
}
|
|
2305
|
+
const senderScopedTopicBindings = matchingTopicBindings.filter((entry) => {
|
|
2306
|
+
return parseFeishuConversationId({
|
|
2307
|
+
conversationId: entry.conversationId,
|
|
2308
|
+
parentConversationId: entry.parentConversationId
|
|
2309
|
+
})?.scope === "group_topic_sender";
|
|
2310
|
+
});
|
|
2311
|
+
if (senderScopedTopicBindings.length === 1 && matchingTopicBindings.length === senderScopedTopicBindings.length) {
|
|
2312
|
+
const existing = senderScopedTopicBindings[0];
|
|
2313
|
+
return {
|
|
2314
|
+
accountId: existing.accountId,
|
|
2315
|
+
conversationId: existing.conversationId,
|
|
2316
|
+
parentConversationId: existing.parentConversationId
|
|
2317
|
+
};
|
|
2318
|
+
}
|
|
2319
|
+
return null;
|
|
2320
|
+
}
|
|
2321
|
+
}
|
|
2322
|
+
}
|
|
2323
|
+
if (!rawTo) return null;
|
|
2324
|
+
if (!normalizedTarget) return null;
|
|
2325
|
+
if (threadId) {
|
|
2326
|
+
if (!isChatTarget) return null;
|
|
2327
|
+
return {
|
|
2328
|
+
accountId: manager.accountId,
|
|
2329
|
+
conversationId: buildFeishuConversationId({
|
|
2330
|
+
chatId: normalizedTarget,
|
|
2331
|
+
scope: "group_topic",
|
|
2332
|
+
topicId: threadId
|
|
2333
|
+
}),
|
|
2334
|
+
parentConversationId: normalizedTarget
|
|
2335
|
+
};
|
|
2336
|
+
}
|
|
2337
|
+
if (isChatTarget) return null;
|
|
2338
|
+
return {
|
|
2339
|
+
accountId: manager.accountId,
|
|
2340
|
+
conversationId: normalizedTarget
|
|
2341
|
+
};
|
|
2342
|
+
}
|
|
2343
|
+
function resolveFeishuDeliveryOrigin(params) {
|
|
2344
|
+
const deliveryTo = params.deliveryTo?.trim();
|
|
2345
|
+
const deliveryThreadId = params.deliveryThreadId?.trim();
|
|
2346
|
+
if (deliveryTo) return {
|
|
2347
|
+
channel: "feishu",
|
|
2348
|
+
accountId: params.accountId,
|
|
2349
|
+
to: deliveryTo,
|
|
2350
|
+
...deliveryThreadId ? { threadId: deliveryThreadId } : {}
|
|
2351
|
+
};
|
|
2352
|
+
const parsed = parseFeishuConversationId({
|
|
2353
|
+
conversationId: params.conversationId,
|
|
2354
|
+
parentConversationId: params.parentConversationId
|
|
2355
|
+
});
|
|
2356
|
+
if (parsed?.topicId) return {
|
|
2357
|
+
channel: "feishu",
|
|
2358
|
+
accountId: params.accountId,
|
|
2359
|
+
to: `chat:${params.parentConversationId?.trim() || parsed.chatId}`,
|
|
2360
|
+
threadId: parsed.topicId
|
|
2361
|
+
};
|
|
2362
|
+
return {
|
|
2363
|
+
channel: "feishu",
|
|
2364
|
+
accountId: params.accountId,
|
|
2365
|
+
to: `user:${params.conversationId}`
|
|
2366
|
+
};
|
|
2367
|
+
}
|
|
2368
|
+
function resolveMatchingChildBinding(params) {
|
|
2369
|
+
const manager = getFeishuThreadBindingManager(params.accountId);
|
|
2370
|
+
if (!manager) return null;
|
|
2371
|
+
const childBindings = manager.listBySessionKey(params.childSessionKey.trim());
|
|
2372
|
+
if (childBindings.length === 0) return null;
|
|
2373
|
+
const requesterConversation = resolveFeishuRequesterConversation({
|
|
2374
|
+
accountId: manager.accountId,
|
|
2375
|
+
to: params.requesterOrigin?.to,
|
|
2376
|
+
threadId: params.requesterOrigin?.threadId,
|
|
2377
|
+
requesterSessionKey: params.requesterSessionKey
|
|
2378
|
+
});
|
|
2379
|
+
if (requesterConversation) {
|
|
2380
|
+
const matched = childBindings.find((entry) => entry.accountId === requesterConversation.accountId && entry.conversationId === requesterConversation.conversationId && (entry.parentConversationId?.trim() || void 0) === (requesterConversation.parentConversationId?.trim() || void 0));
|
|
2381
|
+
if (matched) return matched;
|
|
2382
|
+
}
|
|
2383
|
+
return childBindings.length === 1 ? childBindings[0] : null;
|
|
2384
|
+
}
|
|
2385
|
+
function registerFeishuSubagentHooks(api) {
|
|
2386
|
+
api.on("subagent_spawning", async (event, ctx) => {
|
|
2387
|
+
if (!event.threadRequested) return;
|
|
2388
|
+
if (event.requester?.channel?.trim().toLowerCase() !== "feishu") return;
|
|
2389
|
+
const manager = getFeishuThreadBindingManager(event.requester?.accountId);
|
|
2390
|
+
if (!manager) return {
|
|
2391
|
+
status: "error",
|
|
2392
|
+
error: "Feishu current-conversation binding is unavailable because the Feishu account monitor is not active."
|
|
2393
|
+
};
|
|
2394
|
+
const conversation = resolveFeishuRequesterConversation({
|
|
2395
|
+
accountId: event.requester?.accountId,
|
|
2396
|
+
to: event.requester?.to,
|
|
2397
|
+
threadId: event.requester?.threadId,
|
|
2398
|
+
requesterSessionKey: ctx.requesterSessionKey
|
|
2399
|
+
});
|
|
2400
|
+
if (!conversation) return {
|
|
2401
|
+
status: "error",
|
|
2402
|
+
error: "Feishu current-conversation binding is only available in direct messages or topic conversations."
|
|
2403
|
+
};
|
|
2404
|
+
try {
|
|
2405
|
+
if (!manager.bindConversation({
|
|
2406
|
+
conversationId: conversation.conversationId,
|
|
2407
|
+
parentConversationId: conversation.parentConversationId,
|
|
2408
|
+
targetKind: "subagent",
|
|
2409
|
+
targetSessionKey: event.childSessionKey,
|
|
2410
|
+
metadata: {
|
|
2411
|
+
agentId: event.agentId,
|
|
2412
|
+
label: event.label,
|
|
2413
|
+
boundBy: "system",
|
|
2414
|
+
deliveryTo: event.requester?.to,
|
|
2415
|
+
deliveryThreadId: event.requester?.threadId != null && event.requester.threadId !== "" ? String(event.requester.threadId) : void 0
|
|
2416
|
+
}
|
|
2417
|
+
})) return {
|
|
2418
|
+
status: "error",
|
|
2419
|
+
error: "Unable to bind this Feishu conversation to the spawned subagent session. Session mode is unavailable for this target."
|
|
2420
|
+
};
|
|
2421
|
+
return {
|
|
2422
|
+
status: "ok",
|
|
2423
|
+
threadBindingReady: true
|
|
2424
|
+
};
|
|
2425
|
+
} catch (err) {
|
|
2426
|
+
return {
|
|
2427
|
+
status: "error",
|
|
2428
|
+
error: `Feishu conversation bind failed: ${summarizeError(err)}`
|
|
2429
|
+
};
|
|
2430
|
+
}
|
|
2431
|
+
});
|
|
2432
|
+
api.on("subagent_delivery_target", (event) => {
|
|
2433
|
+
if (!event.expectsCompletionMessage) return;
|
|
2434
|
+
if (event.requesterOrigin?.channel?.trim().toLowerCase() !== "feishu") return;
|
|
2435
|
+
const binding = resolveMatchingChildBinding({
|
|
2436
|
+
accountId: event.requesterOrigin?.accountId,
|
|
2437
|
+
childSessionKey: event.childSessionKey,
|
|
2438
|
+
requesterSessionKey: event.requesterSessionKey,
|
|
2439
|
+
requesterOrigin: {
|
|
2440
|
+
to: event.requesterOrigin?.to,
|
|
2441
|
+
threadId: event.requesterOrigin?.threadId
|
|
2442
|
+
}
|
|
2443
|
+
});
|
|
2444
|
+
if (!binding) return;
|
|
2445
|
+
return { origin: resolveFeishuDeliveryOrigin({
|
|
2446
|
+
conversationId: binding.conversationId,
|
|
2447
|
+
parentConversationId: binding.parentConversationId,
|
|
2448
|
+
accountId: binding.accountId,
|
|
2449
|
+
deliveryTo: binding.deliveryTo,
|
|
2450
|
+
deliveryThreadId: binding.deliveryThreadId
|
|
2451
|
+
}) };
|
|
2452
|
+
});
|
|
2453
|
+
api.on("subagent_ended", (event) => {
|
|
2454
|
+
getFeishuThreadBindingManager(event.accountId)?.unbindBySessionKey(event.targetSessionKey);
|
|
2455
|
+
});
|
|
2456
|
+
}
|
|
2457
|
+
//#endregion
|
|
2458
|
+
//#region extensions/feishu/src/wiki-schema.ts
|
|
2459
|
+
const FeishuWikiSchema = Type.Union([
|
|
2460
|
+
Type.Object({ action: Type.Literal("spaces") }),
|
|
2461
|
+
Type.Object({
|
|
2462
|
+
action: Type.Literal("nodes"),
|
|
2463
|
+
space_id: Type.String({ description: "Knowledge space ID" }),
|
|
2464
|
+
parent_node_token: Type.Optional(Type.String({ description: "Parent node token (optional, omit for root)" }))
|
|
2465
|
+
}),
|
|
2466
|
+
Type.Object({
|
|
2467
|
+
action: Type.Literal("get"),
|
|
2468
|
+
token: Type.String({ description: "Wiki node token (from URL /wiki/XXX)" })
|
|
2469
|
+
}),
|
|
2470
|
+
Type.Object({
|
|
2471
|
+
action: Type.Literal("search"),
|
|
2472
|
+
query: Type.String({ description: "Search query" }),
|
|
2473
|
+
space_id: Type.Optional(Type.String({ description: "Limit search to this space (optional)" }))
|
|
2474
|
+
}),
|
|
2475
|
+
Type.Object({
|
|
2476
|
+
action: Type.Literal("create"),
|
|
2477
|
+
space_id: Type.String({ description: "Knowledge space ID" }),
|
|
2478
|
+
title: Type.String({ description: "Node title" }),
|
|
2479
|
+
obj_type: Type.Optional(Type.Union([
|
|
2480
|
+
Type.Literal("docx"),
|
|
2481
|
+
Type.Literal("sheet"),
|
|
2482
|
+
Type.Literal("bitable")
|
|
2483
|
+
], { description: "Object type (default: docx)" })),
|
|
2484
|
+
parent_node_token: Type.Optional(Type.String({ description: "Parent node token (optional, omit for root)" }))
|
|
2485
|
+
}),
|
|
2486
|
+
Type.Object({
|
|
2487
|
+
action: Type.Literal("move"),
|
|
2488
|
+
space_id: Type.String({ description: "Source knowledge space ID" }),
|
|
2489
|
+
node_token: Type.String({ description: "Node token to move" }),
|
|
2490
|
+
target_space_id: Type.Optional(Type.String({ description: "Target space ID (optional, same space if omitted)" })),
|
|
2491
|
+
target_parent_token: Type.Optional(Type.String({ description: "Target parent node token (optional, root if omitted)" }))
|
|
2492
|
+
}),
|
|
2493
|
+
Type.Object({
|
|
2494
|
+
action: Type.Literal("rename"),
|
|
2495
|
+
space_id: Type.String({ description: "Knowledge space ID" }),
|
|
2496
|
+
node_token: Type.String({ description: "Node token to rename" }),
|
|
2497
|
+
title: Type.String({ description: "New title" })
|
|
2498
|
+
})
|
|
2499
|
+
]);
|
|
2500
|
+
//#endregion
|
|
2501
|
+
//#region extensions/feishu/src/wiki.ts
|
|
2502
|
+
const WIKI_ACCESS_HINT = "To grant wiki access: Open wiki space → Settings → Members → Add the bot. See: https://open.feishu.cn/document/server-docs/docs/wiki-v2/wiki-qa#a40ad4ca";
|
|
2503
|
+
async function listSpaces(client) {
|
|
2504
|
+
const res = await client.wiki.space.list({});
|
|
2505
|
+
if (res.code !== 0) throw new Error(res.msg);
|
|
2506
|
+
const spaces = res.data?.items?.map((s) => ({
|
|
2507
|
+
space_id: s.space_id,
|
|
2508
|
+
name: s.name,
|
|
2509
|
+
description: s.description,
|
|
2510
|
+
visibility: s.visibility
|
|
2511
|
+
})) ?? [];
|
|
2512
|
+
return {
|
|
2513
|
+
spaces,
|
|
2514
|
+
...spaces.length === 0 && { hint: WIKI_ACCESS_HINT }
|
|
2515
|
+
};
|
|
2516
|
+
}
|
|
2517
|
+
async function listNodes(client, spaceId, parentNodeToken) {
|
|
2518
|
+
const res = await client.wiki.spaceNode.list({
|
|
2519
|
+
path: { space_id: spaceId },
|
|
2520
|
+
params: { parent_node_token: parentNodeToken }
|
|
2521
|
+
});
|
|
2522
|
+
if (res.code !== 0) throw new Error(res.msg);
|
|
2523
|
+
return { nodes: res.data?.items?.map((n) => ({
|
|
2524
|
+
node_token: n.node_token,
|
|
2525
|
+
obj_token: n.obj_token,
|
|
2526
|
+
obj_type: n.obj_type,
|
|
2527
|
+
title: n.title,
|
|
2528
|
+
has_child: n.has_child
|
|
2529
|
+
})) ?? [] };
|
|
2530
|
+
}
|
|
2531
|
+
async function getNode(client, token) {
|
|
2532
|
+
const res = await client.wiki.space.getNode({ params: { token } });
|
|
2533
|
+
if (res.code !== 0) throw new Error(res.msg);
|
|
2534
|
+
const node = res.data?.node;
|
|
2535
|
+
return {
|
|
2536
|
+
node_token: node?.node_token,
|
|
2537
|
+
space_id: node?.space_id,
|
|
2538
|
+
obj_token: node?.obj_token,
|
|
2539
|
+
obj_type: node?.obj_type,
|
|
2540
|
+
title: node?.title,
|
|
2541
|
+
parent_node_token: node?.parent_node_token,
|
|
2542
|
+
has_child: node?.has_child,
|
|
2543
|
+
creator: node?.creator,
|
|
2544
|
+
create_time: node?.node_create_time
|
|
2545
|
+
};
|
|
2546
|
+
}
|
|
2547
|
+
async function createNode(client, spaceId, title, objType, parentNodeToken) {
|
|
2548
|
+
const res = await client.wiki.spaceNode.create({
|
|
2549
|
+
path: { space_id: spaceId },
|
|
2550
|
+
data: {
|
|
2551
|
+
obj_type: objType || "docx",
|
|
2552
|
+
node_type: "origin",
|
|
2553
|
+
title,
|
|
2554
|
+
parent_node_token: parentNodeToken
|
|
2555
|
+
}
|
|
2556
|
+
});
|
|
2557
|
+
if (res.code !== 0) throw new Error(res.msg);
|
|
2558
|
+
const node = res.data?.node;
|
|
2559
|
+
return {
|
|
2560
|
+
node_token: node?.node_token,
|
|
2561
|
+
obj_token: node?.obj_token,
|
|
2562
|
+
obj_type: node?.obj_type,
|
|
2563
|
+
title: node?.title
|
|
2564
|
+
};
|
|
2565
|
+
}
|
|
2566
|
+
async function moveNode(client, spaceId, nodeToken, targetSpaceId, targetParentToken) {
|
|
2567
|
+
const res = await client.wiki.spaceNode.move({
|
|
2568
|
+
path: {
|
|
2569
|
+
space_id: spaceId,
|
|
2570
|
+
node_token: nodeToken
|
|
2571
|
+
},
|
|
2572
|
+
data: {
|
|
2573
|
+
target_space_id: targetSpaceId || spaceId,
|
|
2574
|
+
target_parent_token: targetParentToken
|
|
2575
|
+
}
|
|
2576
|
+
});
|
|
2577
|
+
if (res.code !== 0) throw new Error(res.msg);
|
|
2578
|
+
return {
|
|
2579
|
+
success: true,
|
|
2580
|
+
node_token: res.data?.node?.node_token
|
|
2581
|
+
};
|
|
2582
|
+
}
|
|
2583
|
+
async function renameNode(client, spaceId, nodeToken, title) {
|
|
2584
|
+
const res = await client.wiki.spaceNode.updateTitle({
|
|
2585
|
+
path: {
|
|
2586
|
+
space_id: spaceId,
|
|
2587
|
+
node_token: nodeToken
|
|
2588
|
+
},
|
|
2589
|
+
data: { title }
|
|
2590
|
+
});
|
|
2591
|
+
if (res.code !== 0) throw new Error(res.msg);
|
|
2592
|
+
return {
|
|
2593
|
+
success: true,
|
|
2594
|
+
node_token: nodeToken,
|
|
2595
|
+
title
|
|
2596
|
+
};
|
|
2597
|
+
}
|
|
2598
|
+
function registerFeishuWikiTools(api) {
|
|
2599
|
+
if (!api.config) {
|
|
2600
|
+
api.logger.debug?.("feishu_wiki: No config available, skipping wiki tools");
|
|
2601
|
+
return;
|
|
2602
|
+
}
|
|
2603
|
+
const accounts = listEnabledFeishuAccounts(api.config);
|
|
2604
|
+
if (accounts.length === 0) {
|
|
2605
|
+
api.logger.debug?.("feishu_wiki: No Feishu accounts configured, skipping wiki tools");
|
|
2606
|
+
return;
|
|
2607
|
+
}
|
|
2608
|
+
if (!resolveAnyEnabledFeishuToolsConfig(accounts).wiki) {
|
|
2609
|
+
api.logger.debug?.("feishu_wiki: wiki tool disabled in config");
|
|
2610
|
+
return;
|
|
2611
|
+
}
|
|
2612
|
+
api.registerTool((ctx) => {
|
|
2613
|
+
const defaultAccountId = ctx.agentAccountId;
|
|
2614
|
+
return {
|
|
2615
|
+
name: "feishu_wiki",
|
|
2616
|
+
label: "Feishu Wiki",
|
|
2617
|
+
description: "Feishu knowledge base operations. Actions: spaces, nodes, get, create, move, rename",
|
|
2618
|
+
parameters: FeishuWikiSchema,
|
|
2619
|
+
async execute(_toolCallId, params) {
|
|
2620
|
+
const p = params;
|
|
2621
|
+
try {
|
|
2622
|
+
const client = createFeishuToolClient({
|
|
2623
|
+
api,
|
|
2624
|
+
executeParams: p,
|
|
2625
|
+
defaultAccountId
|
|
2626
|
+
});
|
|
2627
|
+
switch (p.action) {
|
|
2628
|
+
case "spaces": return jsonToolResult(await listSpaces(client));
|
|
2629
|
+
case "nodes": return jsonToolResult(await listNodes(client, p.space_id, p.parent_node_token));
|
|
2630
|
+
case "get": return jsonToolResult(await getNode(client, p.token));
|
|
2631
|
+
case "search": return jsonToolResult({ error: "Search is not available. Use feishu_wiki with action: 'nodes' to browse or action: 'get' to lookup by token." });
|
|
2632
|
+
case "create": return jsonToolResult(await createNode(client, p.space_id, p.title, p.obj_type, p.parent_node_token));
|
|
2633
|
+
case "move": return jsonToolResult(await moveNode(client, p.space_id, p.node_token, p.target_space_id, p.target_parent_token));
|
|
2634
|
+
case "rename": return jsonToolResult(await renameNode(client, p.space_id, p.node_token, p.title));
|
|
2635
|
+
default: return unknownToolActionResult(p.action);
|
|
2636
|
+
}
|
|
2637
|
+
} catch (err) {
|
|
2638
|
+
return toolExecutionErrorResult(err);
|
|
2639
|
+
}
|
|
2640
|
+
}
|
|
2641
|
+
};
|
|
2642
|
+
}, { name: "feishu_wiki" });
|
|
2643
|
+
api.logger.info?.(`feishu_wiki: Registered feishu_wiki tool`);
|
|
2644
|
+
}
|
|
2645
|
+
//#endregion
|
|
2646
|
+
//#region extensions/feishu/index.ts
|
|
2647
|
+
var feishu_default = defineChannelPluginEntry({
|
|
2648
|
+
id: "feishu",
|
|
2649
|
+
name: "Feishu",
|
|
2650
|
+
description: "Feishu/Lark channel plugin",
|
|
2651
|
+
plugin: feishuPlugin,
|
|
2652
|
+
setRuntime: setFeishuRuntime,
|
|
2653
|
+
registerFull(api) {
|
|
2654
|
+
registerFeishuSubagentHooks(api);
|
|
2655
|
+
registerFeishuDocTools(api);
|
|
2656
|
+
registerFeishuChatTools(api);
|
|
2657
|
+
registerFeishuWikiTools(api);
|
|
2658
|
+
registerFeishuDriveTools(api);
|
|
2659
|
+
registerFeishuPermTools(api);
|
|
2660
|
+
registerFeishuBitableTools(api);
|
|
2661
|
+
}
|
|
2662
|
+
});
|
|
2663
|
+
//#endregion
|
|
2664
|
+
export { feishu_default as t };
|