@fased/fased 0.1.36 → 0.1.38

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.
Files changed (240) hide show
  1. package/config/capability-catalog.json +241 -0
  2. package/config/dependency-ownership.json +130 -0
  3. package/config/official-channel-catalog.json +39 -0
  4. package/dist/agents/tools/web-fetch-utils.js +2 -1
  5. package/dist/agents/tools/web-fetch-visibility.js +3 -1
  6. package/dist/brand.js +1 -1
  7. package/dist/browser/pw-session.js +2 -1
  8. package/dist/browser/pw-tools-core.state.js +3 -2
  9. package/dist/browser/runtime-dependency.js +27 -0
  10. package/dist/build-info.json +3 -3
  11. package/dist/canvas-host/a2ui/.bundle.hash +1 -1
  12. package/dist/capabilities/catalog.js +228 -0
  13. package/dist/cli/components-cli.js +105 -0
  14. package/dist/cli/hooks-cli.js +1 -1
  15. package/dist/cli/plugins-cli.js +3 -3
  16. package/dist/cli/program/register.subclis.js +9 -0
  17. package/dist/cli/update-cli/update-command.js +1 -1
  18. package/dist/commands/doctor-capabilities.js +26 -0
  19. package/dist/commands/doctor.js +2 -0
  20. package/dist/control-ui/assets/{app-DXYMrRJ9.js → app-JBrTSsNu.js} +1480 -1465
  21. package/dist/control-ui/assets/{index-iGQkJE0l.js → index-H-2DWAnH.js} +3 -3
  22. package/dist/control-ui/index.html +1 -1
  23. package/dist/gateway/method-scopes.js +1 -0
  24. package/dist/gateway/server-methods/plugins-marketplace.js +1 -1
  25. package/dist/gateway/server-methods/services.js +8 -0
  26. package/dist/gateway/server-methods-list.js +1 -0
  27. package/dist/infra/optional-runtime-dependency.js +46 -0
  28. package/dist/media/image-ops.js +6 -1
  29. package/dist/media/input-files.js +11 -2
  30. package/dist/media/mime.js +6 -1
  31. package/dist/memory/sqlite-vec.js +7 -1
  32. package/dist/plugin-sdk/{accounts-VqAX3HJ0.js → accounts-BwkH5bTD.js} +1 -1
  33. package/dist/plugin-sdk/{accounts-Zgt0NP54.js → accounts-RT6y7n3H.js} +1 -1
  34. package/dist/plugin-sdk/{actions-lB3PCwsz.js → actions-BrU_JMqM.js} +2 -2
  35. package/dist/plugin-sdk/{actions-BI5QViLk.js → actions-CUdVHzeJ.js} +2 -2
  36. package/dist/plugin-sdk/{active-listener-DKZiSaRA.js → active-listener-CE8t5g6l.js} +1 -1
  37. package/dist/plugin-sdk/{active-listener-D6_pdTMC.js → active-listener-Dx1SEGDn.js} +1 -1
  38. package/dist/plugin-sdk/{audio-preflight-Dx8J7XhV.js → audio-preflight-BPK8t0tI.js} +22 -22
  39. package/dist/plugin-sdk/{audio-preflight-CeRstduc.js → audio-preflight-kCa_KGRH.js} +22 -22
  40. package/dist/plugin-sdk/{audit-BImNOQvk.js → audit-DxB2Kml5.js} +11 -11
  41. package/dist/plugin-sdk/{audit-CKWkq0Un.js → audit-sSeRDwJb.js} +11 -11
  42. package/dist/plugin-sdk/channel-plugin-common.js +3 -2
  43. package/dist/plugin-sdk/{chunk-skAJZWCT.js → chunk-KCxbJLsV.js} +1 -1
  44. package/dist/plugin-sdk/{chunk-Cjw4712g.js → chunk-M2d7r-Zt.js} +1 -1
  45. package/dist/plugin-sdk/{chunk-items-Df5811D0.js → chunk-items-DGHUeFuI.js} +1 -1
  46. package/dist/plugin-sdk/command-status.js +22 -22
  47. package/dist/plugin-sdk/{commands-registry-5J619bQ2.js → commands-registry-CdT-nl7v.js} +2 -2
  48. package/dist/plugin-sdk/{commands-registry-CoLAT03J.js → commands-registry-DoWdYAJd.js} +2 -2
  49. package/dist/plugin-sdk/{common-CSTxewqY.js → common-Cpw-vuuM.js} +1 -1
  50. package/dist/plugin-sdk/{common-BiF0sTnY.js → common-DJWrErdE.js} +1 -1
  51. package/dist/plugin-sdk/{config-BxVjLTIv.js → config-C0qggNKQ.js} +7 -7
  52. package/dist/plugin-sdk/{config-TFokWwvO.js → config-CgwTaper.js} +45 -2
  53. package/dist/plugin-sdk/{config-DXlISPlx.js → config-DtqAN2L3.js} +45 -2
  54. package/dist/plugin-sdk/discord.js +2 -1
  55. package/dist/plugin-sdk/{fetch-guard-DPMynms8.js → fetch-guard-BLdujDnt.js} +1 -1
  56. package/dist/plugin-sdk/{fetch-guard-COLmW2TM.js → fetch-guard-DTKgMN9f.js} +1 -1
  57. package/dist/plugin-sdk/{handle-action-C-UndB8E.js → handle-action-B61D85yo.js} +12 -12
  58. package/dist/plugin-sdk/{handle-action-hhufKxmU.js → handle-action-CjcxGzQD.js} +12 -12
  59. package/dist/plugin-sdk/index.js +22 -22
  60. package/dist/plugin-sdk/{login-DL1oBBfL.js → login-CB_nCjX3.js} +3 -3
  61. package/dist/plugin-sdk/{login-Dnxas1dI.js → login-CzUuDd1v.js} +3 -3
  62. package/dist/plugin-sdk/{login-qr-CVQsGWKq.js → login-qr-D7MEpFza.js} +3 -3
  63. package/dist/plugin-sdk/{login-qr-B343JNXJ.js → login-qr-DgxfBFVN.js} +3 -3
  64. package/dist/plugin-sdk/{manager-BytwRIfK.js → manager-9see0IX5.js} +8 -3
  65. package/dist/plugin-sdk/{manager-BZjd_PCt.js → manager-D2kZ0Cps.js} +8 -3
  66. package/dist/plugin-sdk/{markdown-tables-krKiU4cT.js → markdown-tables-CCSD52rA.js} +1 -1
  67. package/dist/plugin-sdk/{markdown-tables-9rJDQ1X-.js → markdown-tables-DWUNvLrc.js} +1 -1
  68. package/dist/plugin-sdk/{media-D7ZkWU-A.js → media-C7YT4DeU.js} +13 -4
  69. package/dist/plugin-sdk/{media-C6C2c9a4.js → media-Cxw-xLGU.js} +13 -4
  70. package/dist/plugin-sdk/{monitor-BsLMfn3U.js → monitor-6lkdOqhQ.js} +26 -26
  71. package/dist/plugin-sdk/{monitor-BCxkQBoh.js → monitor-C6Ohw9BA.js} +26 -26
  72. package/dist/plugin-sdk/{monitor-BzDW50H6.js → monitor-o20KTHIi.js} +29 -29
  73. package/dist/plugin-sdk/{monitor-CVQNDfhs.js → monitor-rOs3mUol.js} +27 -27
  74. package/dist/plugin-sdk/{openresponses-http-BB67Z4QM.js → openresponses-http-BJONnUdy.js} +22 -22
  75. package/dist/plugin-sdk/{openresponses-http-NE76GGhj.js → openresponses-http-DkWqYznu.js} +22 -22
  76. package/dist/plugin-sdk/{ssrf-u0Ul7okY.js → optional-runtime-dependency-szS49voX.js} +46 -2
  77. package/dist/plugin-sdk/{outbound-PGNWU6T-.js → outbound-BCxOxdi-.js} +6 -6
  78. package/dist/plugin-sdk/{outbound-BHWJD9q0.js → outbound-JIwQbpRY.js} +6 -6
  79. package/dist/plugin-sdk/{outbound-attachment-BVzfhqnk.js → outbound-attachment-C-jSFaEB.js} +1 -1
  80. package/dist/plugin-sdk/{outbound-attachment-ClMvNW17.js → outbound-attachment-D6tj5Y5H.js} +1 -1
  81. package/dist/plugin-sdk/{pi-embedded-runner-DQ6UPx6-.js → pi-embedded-runner-DqDy0MWN.js} +72 -60
  82. package/dist/plugin-sdk/{pi-model-discovery-D51L5E9I.js → pi-model-discovery-DadlvsZW.js} +1 -1
  83. package/dist/plugin-sdk/{pi-model-discovery-runtime-DxoFm4Vd.js → pi-model-discovery-runtime-C5ssE6EW.js} +1 -1
  84. package/dist/plugin-sdk/{pi-model-discovery-runtime-DRuh4PNV.js → pi-model-discovery-runtime-DAaOPt64.js} +2 -2
  85. package/dist/plugin-sdk/{pi-model-discovery-runtime-BTWgkx4x.js → pi-model-discovery-runtime-gd77b0UF.js} +2 -2
  86. package/dist/plugin-sdk/{pi-model-discovery-CkH5l9X5.js → pi-model-discovery-yifTIDIn.js} +1 -1
  87. package/dist/plugin-sdk/{pw-ai-DZs6uYRd.js → pw-ai-Boor5vYw.js} +6 -5
  88. package/dist/plugin-sdk/{pw-ai-Cn-EUPZK.js → pw-ai-sH1Pi-Fh.js} +6 -5
  89. package/dist/plugin-sdk/{registry-B4HvWzob.js → registry-DNkJsNsz.js} +4 -3
  90. package/dist/plugin-sdk/{replies-jDMUBsNO.js → replies-fvzN5wnU.js} +2 -2
  91. package/dist/plugin-sdk/{replies-B_LW9c9f.js → replies-zebgZCHX.js} +2 -2
  92. package/dist/plugin-sdk/{resolve-route-_YZHbS-z.js → resolve-route-CNhTJG_2.js} +1 -1
  93. package/dist/plugin-sdk/{resolve-route-DlHzggnG.js → resolve-route-DO0WR4nB.js} +1 -1
  94. package/dist/plugin-sdk/{resolve-utils-zBhVX3Vx.js → resolve-utils-bixHYDBj.js} +1 -1
  95. package/dist/plugin-sdk/{retry-policy-DGLs5ebP.js → retry-policy-BLYEgIwP.js} +1 -1
  96. package/dist/plugin-sdk/{retry-policy-DaodShGa.js → retry-policy-sM01QZT2.js} +1 -1
  97. package/dist/plugin-sdk/{runtime-Dd0sswuW.js → runtime-BPyuAmka.js} +4 -3
  98. package/dist/plugin-sdk/{paths-CBCpJ5bu.js → runtime-dependency-Csswyv5r.js} +27 -3
  99. package/dist/plugin-sdk/{paths-DW-U2r7Y.js → runtime-dependency-Deg_sw2k.js} +36 -12
  100. package/dist/plugin-sdk/sat-runtime.js +1 -0
  101. package/dist/plugin-sdk/{send-8remZhsH.js → send-B09HRfHN.js} +6 -6
  102. package/dist/plugin-sdk/{send-DaaAscWj.js → send-BBYcgXA4.js} +5 -5
  103. package/dist/plugin-sdk/{send-DFTB0cnx.js → send-BQXQA81e.js} +6 -6
  104. package/dist/plugin-sdk/{send-CtMVvMJs.js → send-BzFdvD_i.js} +6 -6
  105. package/dist/plugin-sdk/{send-Di9irjS-.js → send-C3u-F_8s.js} +6 -6
  106. package/dist/plugin-sdk/{send-Dl88ZKq2.js → send-D3836_UN.js} +6 -6
  107. package/dist/plugin-sdk/{send-ifgZCHVB.js → send-D7tr-EsH.js} +5 -5
  108. package/dist/plugin-sdk/{send-DvUpYh0d.js → send-DRGzRdI3.js} +6 -6
  109. package/dist/plugin-sdk/{send-D2jlPeKH.js → send-DfkPKz_0.js} +4 -4
  110. package/dist/plugin-sdk/{send-QSt6nbny.js → send-DsxFXrCO.js} +4 -4
  111. package/dist/plugin-sdk/{session-CknrceVU.js → session-DG_bYisw.js} +2 -2
  112. package/dist/plugin-sdk/{session-CyRTcJ8N.js → session-EIStzK0E.js} +2 -2
  113. package/dist/plugin-sdk/{skill-commands-DHxkTA0s.js → skill-commands-CkgGmWBS.js} +2 -2
  114. package/dist/plugin-sdk/{skill-commands-CLXAG5sU.js → skill-commands-hyZA0LE3.js} +2 -2
  115. package/dist/plugin-sdk/{slack-Br9c6Yzs.js → slack-BErIh0uj.js} +34 -34
  116. package/dist/plugin-sdk/{slack-BpJXkwxF.js → slack-CGTAN4UD.js} +34 -34
  117. package/dist/plugin-sdk/{slack-actions-8tLGt1Ht.js → slack-actions-BQawWGTJ.js} +11 -11
  118. package/dist/plugin-sdk/{slack-actions-CDSSRo8Y.js → slack-actions-DDMszx56.js} +11 -11
  119. package/dist/plugin-sdk/slack.js +2 -1
  120. package/dist/plugin-sdk/src/brand.d.ts +2 -2
  121. package/dist/plugin-sdk/src/browser/runtime-dependency.d.ts +3 -0
  122. package/dist/plugin-sdk/src/infra/optional-runtime-dependency.d.ts +6 -0
  123. package/dist/plugin-sdk/{ssrf-fG4UHKBw.js → ssrf-Cce6LubA.js} +41 -7
  124. package/dist/plugin-sdk/{status-DoxnzyMC.js → status-CCGFb0f2.js} +76 -64
  125. package/dist/plugin-sdk/{sticker-cache-zmJ39ByC.js → sticker-cache-CKAkkCoU.js} +3 -3
  126. package/dist/plugin-sdk/{sticker-cache-D7WcMYsF.js → sticker-cache-wxl1Me2i.js} +3 -3
  127. package/dist/plugin-sdk/{tables-CkxblF0u.js → tables-BD7H5ug-.js} +1 -1
  128. package/dist/plugin-sdk/{tables-RBtf8G4P.js → tables-CJE8kB35.js} +1 -1
  129. package/dist/plugin-sdk/{telegram-actions-DAeYXSLk.js → telegram-actions-BRUNEXMr.js} +25 -25
  130. package/dist/plugin-sdk/{telegram-actions-BDeS3ocd.js → telegram-actions-r86ntIKR.js} +25 -25
  131. package/dist/plugin-sdk/telegram.js +2 -1
  132. package/dist/plugin-sdk/{thread-bindings.lifecycle-DsB94WbE.js → thread-bindings.lifecycle-Djem8FWF.js} +2 -2
  133. package/dist/plugin-sdk/{thread-bindings.lifecycle-DMhV3TsR.js → thread-bindings.lifecycle-gmHv3hc7.js} +2 -2
  134. package/dist/plugin-sdk/{thread-bindings.state-DYWpy7hJ.js → thread-bindings.state-CNT2vxm3.js} +2 -2
  135. package/dist/plugin-sdk/{thread-bindings.state-DG5cBaRn.js → thread-bindings.state-D8kN2X6H.js} +2 -2
  136. package/dist/plugin-sdk/{web-DJwacWQo.js → web-02I0vmdu.js} +26 -26
  137. package/dist/plugin-sdk/{web-IJ4NoGPJ.js → web-CXz56wyu.js} +26 -26
  138. package/dist/plugin-sdk/{whatsapp-actions-DAY8hWpD.js → whatsapp-actions-68Mfs2dJ.js} +12 -12
  139. package/dist/plugin-sdk/{whatsapp-actions-6opfo-oB.js → whatsapp-actions-DRqtzvTO.js} +12 -12
  140. package/dist/plugin-sdk/whatsapp.js +2 -1
  141. package/dist/plugin-sdk/{wsl-B2euLEc2.js → wsl-DcM2PgSS.js} +3 -3
  142. package/dist/plugin-sdk/{wsl-B8eyviuv.js → wsl-PXrdWitE.js} +3 -3
  143. package/dist/plugins/update.js +1 -1
  144. package/dist/tts/tts-core.js +6 -1
  145. package/dist/wizard/onboarding.finalize.js +9 -0
  146. package/extensions/acpx/package.json +1 -1
  147. package/extensions/bluebubbles/package.json +1 -1
  148. package/extensions/copilot-proxy/package.json +1 -1
  149. package/extensions/diagnostics-otel/package.json +1 -1
  150. package/extensions/fased-federation/package.json +1 -1
  151. package/extensions/google-gemini-cli-auth/package.json +1 -1
  152. package/extensions/imessage/package.json +1 -1
  153. package/extensions/irc/package.json +1 -1
  154. package/extensions/line/package.json +1 -1
  155. package/extensions/llm-task/package.json +1 -1
  156. package/extensions/lobster/package.json +1 -1
  157. package/extensions/matrix/CHANGELOG.md +12 -0
  158. package/extensions/matrix/package.json +1 -1
  159. package/extensions/mattermost/package.json +1 -1
  160. package/extensions/memory-core/package.json +2 -2
  161. package/extensions/memory-lancedb/package.json +1 -1
  162. package/extensions/minimax-portal-auth/package.json +1 -1
  163. package/extensions/msteams/CHANGELOG.md +12 -0
  164. package/extensions/msteams/package.json +1 -1
  165. package/extensions/nextcloud-talk/package.json +1 -1
  166. package/extensions/nostr/CHANGELOG.md +12 -0
  167. package/extensions/nostr/package.json +1 -1
  168. package/extensions/open-prose/package.json +1 -1
  169. package/extensions/sat-mining/package.json +1 -1
  170. package/extensions/signal/package.json +1 -1
  171. package/extensions/synology-chat/package.json +1 -1
  172. package/extensions/tlon/package.json +1 -1
  173. package/extensions/twitch/CHANGELOG.md +12 -0
  174. package/extensions/twitch/package.json +1 -1
  175. package/extensions/voice-call/CHANGELOG.md +12 -0
  176. package/extensions/voice-call/package.json +1 -1
  177. package/extensions/zalo/CHANGELOG.md +12 -0
  178. package/extensions/zalo/package.json +1 -1
  179. package/extensions/zalouser/CHANGELOG.md +12 -0
  180. package/extensions/zalouser/package.json +1 -1
  181. package/package.json +22 -15
  182. package/extensions/feishu/fased.plugin.json +0 -10
  183. package/extensions/feishu/index.ts +0 -63
  184. package/extensions/feishu/package.json +0 -33
  185. package/extensions/feishu/skills/feishu-doc/SKILL.md +0 -211
  186. package/extensions/feishu/skills/feishu-doc/references/block-types.md +0 -103
  187. package/extensions/feishu/skills/feishu-drive/SKILL.md +0 -97
  188. package/extensions/feishu/skills/feishu-perm/SKILL.md +0 -119
  189. package/extensions/feishu/skills/feishu-wiki/SKILL.md +0 -111
  190. package/extensions/feishu/src/accounts.ts +0 -159
  191. package/extensions/feishu/src/bitable.ts +0 -713
  192. package/extensions/feishu/src/bot.ts +0 -979
  193. package/extensions/feishu/src/channel.ts +0 -359
  194. package/extensions/feishu/src/client.ts +0 -118
  195. package/extensions/feishu/src/config-schema.ts +0 -226
  196. package/extensions/feishu/src/dedup.ts +0 -54
  197. package/extensions/feishu/src/directory.ts +0 -177
  198. package/extensions/feishu/src/doc-schema.ts +0 -122
  199. package/extensions/feishu/src/docx.ts +0 -998
  200. package/extensions/feishu/src/drive-schema.ts +0 -46
  201. package/extensions/feishu/src/drive.ts +0 -232
  202. package/extensions/feishu/src/dynamic-agent.ts +0 -131
  203. package/extensions/feishu/src/external-keys.ts +0 -19
  204. package/extensions/feishu/src/media.ts +0 -447
  205. package/extensions/feishu/src/mention.ts +0 -133
  206. package/extensions/feishu/src/monitor.ts +0 -434
  207. package/extensions/feishu/src/onboarding.ts +0 -430
  208. package/extensions/feishu/src/outbound.ts +0 -56
  209. package/extensions/feishu/src/perm-schema.ts +0 -52
  210. package/extensions/feishu/src/perm.ts +0 -180
  211. package/extensions/feishu/src/policy.ts +0 -116
  212. package/extensions/feishu/src/probe.ts +0 -44
  213. package/extensions/feishu/src/reactions.ts +0 -160
  214. package/extensions/feishu/src/reply-dispatcher.ts +0 -239
  215. package/extensions/feishu/src/runtime.ts +0 -14
  216. package/extensions/feishu/src/send-result.ts +0 -29
  217. package/extensions/feishu/src/send-target.ts +0 -25
  218. package/extensions/feishu/src/send.ts +0 -313
  219. package/extensions/feishu/src/streaming-card.ts +0 -218
  220. package/extensions/feishu/src/targets.ts +0 -78
  221. package/extensions/feishu/src/tool-account.ts +0 -58
  222. package/extensions/feishu/src/tools-config.ts +0 -21
  223. package/extensions/feishu/src/types.ts +0 -81
  224. package/extensions/feishu/src/typing.ts +0 -80
  225. package/extensions/feishu/src/wiki-schema.ts +0 -55
  226. package/extensions/feishu/src/wiki.ts +0 -237
  227. package/extensions/googlechat/fased.plugin.json +0 -9
  228. package/extensions/googlechat/index.ts +0 -19
  229. package/extensions/googlechat/package.json +0 -37
  230. package/extensions/googlechat/src/accounts.ts +0 -147
  231. package/extensions/googlechat/src/actions.ts +0 -176
  232. package/extensions/googlechat/src/api.ts +0 -282
  233. package/extensions/googlechat/src/auth.ts +0 -137
  234. package/extensions/googlechat/src/channel.ts +0 -591
  235. package/extensions/googlechat/src/monitor.ts +0 -996
  236. package/extensions/googlechat/src/onboarding.ts +0 -344
  237. package/extensions/googlechat/src/runtime.ts +0 -14
  238. package/extensions/googlechat/src/targets.ts +0 -65
  239. package/extensions/googlechat/src/types.config.ts +0 -3
  240. package/extensions/googlechat/src/types.ts +0 -73
@@ -1,359 +0,0 @@
1
- import type { ChannelMeta, ChannelPlugin, FasedAgentConfig } from "fased/plugin-sdk";
2
- import {
3
- buildBaseChannelStatusSummary,
4
- createDefaultChannelRuntimeState,
5
- DEFAULT_ACCOUNT_ID,
6
- PAIRING_APPROVED_MESSAGE,
7
- resolveAllowlistProviderRuntimeGroupPolicy,
8
- resolveDefaultGroupPolicy,
9
- } from "fased/plugin-sdk";
10
- import {
11
- resolveFeishuAccount,
12
- resolveFeishuCredentials,
13
- listFeishuAccountIds,
14
- resolveDefaultFeishuAccountId,
15
- } from "./accounts.js";
16
- import {
17
- listFeishuDirectoryPeers,
18
- listFeishuDirectoryGroups,
19
- listFeishuDirectoryPeersLive,
20
- listFeishuDirectoryGroupsLive,
21
- } from "./directory.js";
22
- import { feishuOnboardingAdapter } from "./onboarding.js";
23
- import { feishuOutbound } from "./outbound.js";
24
- import { resolveFeishuGroupToolPolicy } from "./policy.js";
25
- import { probeFeishu } from "./probe.js";
26
- import { sendMessageFeishu } from "./send.js";
27
- import { normalizeFeishuTarget, looksLikeFeishuId, formatFeishuTarget } from "./targets.js";
28
- import type { ResolvedFeishuAccount, FeishuConfig } from "./types.js";
29
-
30
- const meta: ChannelMeta = {
31
- id: "feishu",
32
- label: "Feishu",
33
- selectionLabel: "Feishu/Lark (飞书)",
34
- docsPath: "/channels/feishu",
35
- docsLabel: "feishu",
36
- blurb: "飞书/Lark enterprise messaging.",
37
- aliases: ["lark"],
38
- order: 70,
39
- };
40
-
41
- export const feishuPlugin: ChannelPlugin<ResolvedFeishuAccount> = {
42
- id: "feishu",
43
- meta: {
44
- ...meta,
45
- },
46
- pairing: {
47
- idLabel: "feishuUserId",
48
- normalizeAllowEntry: (entry) => entry.replace(/^(feishu|user|open_id):/i, ""),
49
- notifyApproval: async ({ cfg, id }) => {
50
- await sendMessageFeishu({
51
- cfg,
52
- to: id,
53
- text: PAIRING_APPROVED_MESSAGE,
54
- });
55
- },
56
- },
57
- capabilities: {
58
- chatTypes: ["direct", "channel"],
59
- polls: false,
60
- threads: true,
61
- media: true,
62
- reactions: true,
63
- edit: true,
64
- reply: true,
65
- },
66
- agentPrompt: {
67
- messageToolHints: () => [
68
- "- Feishu targeting: omit `target` to reply to the current conversation (auto-inferred). Explicit targets: `user:open_id` or `chat:chat_id`.",
69
- "- Feishu supports interactive cards for rich messages.",
70
- ],
71
- },
72
- groups: {
73
- resolveToolPolicy: resolveFeishuGroupToolPolicy,
74
- },
75
- reload: { configPrefixes: ["channels.feishu"] },
76
- configSchema: {
77
- schema: {
78
- type: "object",
79
- additionalProperties: false,
80
- properties: {
81
- enabled: { type: "boolean" },
82
- appId: { type: "string" },
83
- appSecret: { type: "string" },
84
- encryptKey: { type: "string" },
85
- verificationToken: { type: "string" },
86
- domain: {
87
- oneOf: [
88
- { type: "string", enum: ["feishu", "lark"] },
89
- { type: "string", format: "uri", pattern: "^https://" },
90
- ],
91
- },
92
- connectionMode: { type: "string", enum: ["websocket", "webhook"] },
93
- webhookPath: { type: "string" },
94
- webhookHost: { type: "string" },
95
- webhookPort: { type: "integer", minimum: 1 },
96
- dmPolicy: { type: "string", enum: ["open", "pairing", "allowlist"] },
97
- allowFrom: { type: "array", items: { oneOf: [{ type: "string" }, { type: "number" }] } },
98
- groupPolicy: { type: "string", enum: ["open", "allowlist", "disabled"] },
99
- groupAllowFrom: {
100
- type: "array",
101
- items: { oneOf: [{ type: "string" }, { type: "number" }] },
102
- },
103
- requireMention: { type: "boolean" },
104
- topicSessionMode: { type: "string", enum: ["disabled", "enabled"] },
105
- historyLimit: { type: "integer", minimum: 0 },
106
- dmHistoryLimit: { type: "integer", minimum: 0 },
107
- textChunkLimit: { type: "integer", minimum: 1 },
108
- chunkMode: { type: "string", enum: ["length", "newline"] },
109
- mediaMaxMb: { type: "number", minimum: 0 },
110
- renderMode: { type: "string", enum: ["auto", "raw", "card"] },
111
- accounts: {
112
- type: "object",
113
- additionalProperties: {
114
- type: "object",
115
- properties: {
116
- enabled: { type: "boolean" },
117
- name: { type: "string" },
118
- appId: { type: "string" },
119
- appSecret: { type: "string" },
120
- encryptKey: { type: "string" },
121
- verificationToken: { type: "string" },
122
- domain: { type: "string", enum: ["feishu", "lark"] },
123
- connectionMode: { type: "string", enum: ["websocket", "webhook"] },
124
- webhookHost: { type: "string" },
125
- webhookPath: { type: "string" },
126
- webhookPort: { type: "integer", minimum: 1 },
127
- },
128
- },
129
- },
130
- },
131
- },
132
- },
133
- config: {
134
- listAccountIds: (cfg) => listFeishuAccountIds(cfg),
135
- resolveAccount: (cfg, accountId) => resolveFeishuAccount({ cfg, accountId }),
136
- defaultAccountId: (cfg) => resolveDefaultFeishuAccountId(cfg),
137
- setAccountEnabled: ({ cfg, accountId, enabled }) => {
138
- const account = resolveFeishuAccount({ cfg, accountId });
139
- const isDefault = accountId === DEFAULT_ACCOUNT_ID;
140
-
141
- if (isDefault) {
142
- // For default account, set top-level enabled
143
- return {
144
- ...cfg,
145
- channels: {
146
- ...cfg.channels,
147
- feishu: {
148
- ...cfg.channels?.feishu,
149
- enabled,
150
- },
151
- },
152
- };
153
- }
154
-
155
- // For named accounts, set enabled in accounts[accountId]
156
- const feishuCfg = cfg.channels?.feishu as FeishuConfig | undefined;
157
- return {
158
- ...cfg,
159
- channels: {
160
- ...cfg.channels,
161
- feishu: {
162
- ...feishuCfg,
163
- accounts: {
164
- ...feishuCfg?.accounts,
165
- [accountId]: {
166
- ...feishuCfg?.accounts?.[accountId],
167
- enabled,
168
- },
169
- },
170
- },
171
- },
172
- };
173
- },
174
- deleteAccount: ({ cfg, accountId }) => {
175
- const isDefault = accountId === DEFAULT_ACCOUNT_ID;
176
-
177
- if (isDefault) {
178
- // Delete entire feishu config
179
- const next = { ...cfg } as FasedAgentConfig;
180
- const nextChannels = { ...cfg.channels };
181
- delete (nextChannels as Record<string, unknown>).feishu;
182
- if (Object.keys(nextChannels).length > 0) {
183
- next.channels = nextChannels;
184
- } else {
185
- delete next.channels;
186
- }
187
- return next;
188
- }
189
-
190
- // Delete specific account from accounts
191
- const feishuCfg = cfg.channels?.feishu as FeishuConfig | undefined;
192
- const accounts = { ...feishuCfg?.accounts };
193
- delete accounts[accountId];
194
-
195
- return {
196
- ...cfg,
197
- channels: {
198
- ...cfg.channels,
199
- feishu: {
200
- ...feishuCfg,
201
- accounts: Object.keys(accounts).length > 0 ? accounts : undefined,
202
- },
203
- },
204
- };
205
- },
206
- isConfigured: (account) => account.configured,
207
- describeAccount: (account) => ({
208
- accountId: account.accountId,
209
- enabled: account.enabled,
210
- configured: account.configured,
211
- name: account.name,
212
- appId: account.appId,
213
- domain: account.domain,
214
- }),
215
- resolveAllowFrom: ({ cfg, accountId }) => {
216
- const account = resolveFeishuAccount({ cfg, accountId });
217
- return (account.config?.allowFrom ?? []).map((entry) => String(entry));
218
- },
219
- formatAllowFrom: ({ allowFrom }) =>
220
- allowFrom
221
- .map((entry) => String(entry).trim())
222
- .filter(Boolean)
223
- .map((entry) => entry.toLowerCase()),
224
- },
225
- security: {
226
- collectWarnings: ({ cfg, accountId }) => {
227
- const account = resolveFeishuAccount({ cfg, accountId });
228
- const feishuCfg = account.config;
229
- const defaultGroupPolicy = resolveDefaultGroupPolicy(cfg);
230
- const { groupPolicy } = resolveAllowlistProviderRuntimeGroupPolicy({
231
- providerConfigPresent: cfg.channels?.feishu !== undefined,
232
- groupPolicy: feishuCfg?.groupPolicy,
233
- defaultGroupPolicy,
234
- });
235
- if (groupPolicy !== "open") return [];
236
- return [
237
- `- Feishu[${account.accountId}] groups: groupPolicy="open" allows any member to trigger (mention-gated). Set channels.feishu.groupPolicy="allowlist" + channels.feishu.groupAllowFrom to restrict senders.`,
238
- ];
239
- },
240
- },
241
- setup: {
242
- resolveAccountId: () => DEFAULT_ACCOUNT_ID,
243
- applyAccountConfig: ({ cfg, accountId }) => {
244
- const isDefault = !accountId || accountId === DEFAULT_ACCOUNT_ID;
245
-
246
- if (isDefault) {
247
- return {
248
- ...cfg,
249
- channels: {
250
- ...cfg.channels,
251
- feishu: {
252
- ...cfg.channels?.feishu,
253
- enabled: true,
254
- },
255
- },
256
- };
257
- }
258
-
259
- const feishuCfg = cfg.channels?.feishu as FeishuConfig | undefined;
260
- return {
261
- ...cfg,
262
- channels: {
263
- ...cfg.channels,
264
- feishu: {
265
- ...feishuCfg,
266
- accounts: {
267
- ...feishuCfg?.accounts,
268
- [accountId]: {
269
- ...feishuCfg?.accounts?.[accountId],
270
- enabled: true,
271
- },
272
- },
273
- },
274
- },
275
- };
276
- },
277
- },
278
- onboarding: feishuOnboardingAdapter,
279
- messaging: {
280
- normalizeTarget: (raw) => normalizeFeishuTarget(raw) ?? undefined,
281
- targetResolver: {
282
- looksLikeId: looksLikeFeishuId,
283
- hint: "<chatId|user:openId|chat:chatId>",
284
- },
285
- },
286
- directory: {
287
- self: async () => null,
288
- listPeers: async ({ cfg, query, limit, accountId }) =>
289
- listFeishuDirectoryPeers({
290
- cfg,
291
- query: query ?? undefined,
292
- limit: limit ?? undefined,
293
- accountId: accountId ?? undefined,
294
- }),
295
- listGroups: async ({ cfg, query, limit, accountId }) =>
296
- listFeishuDirectoryGroups({
297
- cfg,
298
- query: query ?? undefined,
299
- limit: limit ?? undefined,
300
- accountId: accountId ?? undefined,
301
- }),
302
- listPeersLive: async ({ cfg, query, limit, accountId }) =>
303
- listFeishuDirectoryPeersLive({
304
- cfg,
305
- query: query ?? undefined,
306
- limit: limit ?? undefined,
307
- accountId: accountId ?? undefined,
308
- }),
309
- listGroupsLive: async ({ cfg, query, limit, accountId }) =>
310
- listFeishuDirectoryGroupsLive({
311
- cfg,
312
- query: query ?? undefined,
313
- limit: limit ?? undefined,
314
- accountId: accountId ?? undefined,
315
- }),
316
- },
317
- outbound: feishuOutbound,
318
- status: {
319
- defaultRuntime: createDefaultChannelRuntimeState(DEFAULT_ACCOUNT_ID, { port: null }),
320
- buildChannelSummary: ({ snapshot }) => ({
321
- ...buildBaseChannelStatusSummary(snapshot),
322
- port: snapshot.port ?? null,
323
- probe: snapshot.probe,
324
- lastProbeAt: snapshot.lastProbeAt ?? null,
325
- }),
326
- probeAccount: async ({ account }) => await probeFeishu(account),
327
- buildAccountSnapshot: ({ account, runtime, probe }) => ({
328
- accountId: account.accountId,
329
- enabled: account.enabled,
330
- configured: account.configured,
331
- name: account.name,
332
- appId: account.appId,
333
- domain: account.domain,
334
- running: runtime?.running ?? false,
335
- lastStartAt: runtime?.lastStartAt ?? null,
336
- lastStopAt: runtime?.lastStopAt ?? null,
337
- lastError: runtime?.lastError ?? null,
338
- port: runtime?.port ?? null,
339
- probe,
340
- }),
341
- },
342
- gateway: {
343
- startAccount: async (ctx) => {
344
- const { monitorFeishuProvider } = await import("./monitor.js");
345
- const account = resolveFeishuAccount({ cfg: ctx.cfg, accountId: ctx.accountId });
346
- const port = account.config?.webhookPort ?? null;
347
- ctx.setStatus({ accountId: ctx.accountId, port });
348
- ctx.log?.info(
349
- `starting feishu[${ctx.accountId}] (mode: ${account.config?.connectionMode ?? "websocket"})`,
350
- );
351
- return monitorFeishuProvider({
352
- config: ctx.cfg,
353
- runtime: ctx.runtime,
354
- abortSignal: ctx.abortSignal,
355
- accountId: ctx.accountId,
356
- });
357
- },
358
- },
359
- };
@@ -1,118 +0,0 @@
1
- import * as Lark from "@larksuiteoapi/node-sdk";
2
- import type { FeishuDomain, ResolvedFeishuAccount } from "./types.js";
3
-
4
- // Multi-account client cache
5
- const clientCache = new Map<
6
- string,
7
- {
8
- client: Lark.Client;
9
- config: { appId: string; appSecret: string; domain?: FeishuDomain };
10
- }
11
- >();
12
-
13
- function resolveDomain(domain: FeishuDomain | undefined): Lark.Domain | string {
14
- if (domain === "lark") {
15
- return Lark.Domain.Lark;
16
- }
17
- if (domain === "feishu" || !domain) {
18
- return Lark.Domain.Feishu;
19
- }
20
- return domain.replace(/\/+$/, ""); // Custom URL for private deployment
21
- }
22
-
23
- /**
24
- * Credentials needed to create a Feishu client.
25
- * Both FeishuConfig and ResolvedFeishuAccount satisfy this interface.
26
- */
27
- export type FeishuClientCredentials = {
28
- accountId?: string;
29
- appId?: string;
30
- appSecret?: string;
31
- domain?: FeishuDomain;
32
- };
33
-
34
- /**
35
- * Create or get a cached Feishu client for an account.
36
- * Accepts any object with appId, appSecret, and optional domain/accountId.
37
- */
38
- export function createFeishuClient(creds: FeishuClientCredentials): Lark.Client {
39
- const { accountId = "default", appId, appSecret, domain } = creds;
40
-
41
- if (!appId || !appSecret) {
42
- throw new Error(`Feishu credentials not configured for account "${accountId}"`);
43
- }
44
-
45
- // Check cache
46
- const cached = clientCache.get(accountId);
47
- if (
48
- cached &&
49
- cached.config.appId === appId &&
50
- cached.config.appSecret === appSecret &&
51
- cached.config.domain === domain
52
- ) {
53
- return cached.client;
54
- }
55
-
56
- // Create new client
57
- const client = new Lark.Client({
58
- appId,
59
- appSecret,
60
- appType: Lark.AppType.SelfBuild,
61
- domain: resolveDomain(domain),
62
- });
63
-
64
- // Cache it
65
- clientCache.set(accountId, {
66
- client,
67
- config: { appId, appSecret, domain },
68
- });
69
-
70
- return client;
71
- }
72
-
73
- /**
74
- * Create a Feishu WebSocket client for an account.
75
- * Note: WSClient is not cached since each call creates a new connection.
76
- */
77
- export function createFeishuWSClient(account: ResolvedFeishuAccount): Lark.WSClient {
78
- const { accountId, appId, appSecret, domain } = account;
79
-
80
- if (!appId || !appSecret) {
81
- throw new Error(`Feishu credentials not configured for account "${accountId}"`);
82
- }
83
-
84
- return new Lark.WSClient({
85
- appId,
86
- appSecret,
87
- domain: resolveDomain(domain),
88
- loggerLevel: Lark.LoggerLevel.info,
89
- });
90
- }
91
-
92
- /**
93
- * Create an event dispatcher for an account.
94
- */
95
- export function createEventDispatcher(account: ResolvedFeishuAccount): Lark.EventDispatcher {
96
- return new Lark.EventDispatcher({
97
- encryptKey: account.encryptKey,
98
- verificationToken: account.verificationToken,
99
- });
100
- }
101
-
102
- /**
103
- * Get a cached client for an account (if exists).
104
- */
105
- export function getFeishuClient(accountId: string): Lark.Client | null {
106
- return clientCache.get(accountId)?.client ?? null;
107
- }
108
-
109
- /**
110
- * Clear client cache for a specific account or all accounts.
111
- */
112
- export function clearClientCache(accountId?: string): void {
113
- if (accountId) {
114
- clientCache.delete(accountId);
115
- } else {
116
- clientCache.clear();
117
- }
118
- }
@@ -1,226 +0,0 @@
1
- import { z } from "zod";
2
- export { z };
3
-
4
- const DmPolicySchema = z.enum(["open", "pairing", "allowlist"]);
5
- const GroupPolicySchema = z.enum(["open", "allowlist", "disabled"]);
6
- const FeishuDomainSchema = z.union([
7
- z.enum(["feishu", "lark"]),
8
- z.string().url().startsWith("https://"),
9
- ]);
10
- const FeishuConnectionModeSchema = z.enum(["websocket", "webhook"]);
11
-
12
- const ToolPolicySchema = z
13
- .object({
14
- allow: z.array(z.string()).optional(),
15
- deny: z.array(z.string()).optional(),
16
- })
17
- .strict()
18
- .optional();
19
-
20
- const DmConfigSchema = z
21
- .object({
22
- enabled: z.boolean().optional(),
23
- systemPrompt: z.string().optional(),
24
- })
25
- .strict()
26
- .optional();
27
-
28
- const MarkdownConfigSchema = z
29
- .object({
30
- mode: z.enum(["native", "escape", "strip"]).optional(),
31
- tableMode: z.enum(["native", "ascii", "simple"]).optional(),
32
- })
33
- .strict()
34
- .optional();
35
-
36
- // Message render mode: auto (default) = detect markdown, raw = plain text, card = always card
37
- const RenderModeSchema = z.enum(["auto", "raw", "card"]).optional();
38
-
39
- // Streaming card mode: when enabled, card replies use Feishu's Card Kit streaming API
40
- // for incremental text display with a "Thinking..." placeholder
41
- const StreamingModeSchema = z.boolean().optional();
42
-
43
- const BlockStreamingCoalesceSchema = z
44
- .object({
45
- enabled: z.boolean().optional(),
46
- minDelayMs: z.number().int().positive().optional(),
47
- maxDelayMs: z.number().int().positive().optional(),
48
- })
49
- .strict()
50
- .optional();
51
-
52
- const ChannelHeartbeatVisibilitySchema = z
53
- .object({
54
- visibility: z.enum(["visible", "hidden"]).optional(),
55
- intervalMs: z.number().int().positive().optional(),
56
- })
57
- .strict()
58
- .optional();
59
-
60
- /**
61
- * Dynamic agent creation configuration.
62
- * When enabled, a new agent is created for each unique DM user.
63
- */
64
- const DynamicAgentCreationSchema = z
65
- .object({
66
- enabled: z.boolean().optional(),
67
- workspaceTemplate: z.string().optional(),
68
- agentDirTemplate: z.string().optional(),
69
- maxAgents: z.number().int().positive().optional(),
70
- })
71
- .strict()
72
- .optional();
73
-
74
- /**
75
- * Feishu tools configuration.
76
- * Controls which tool categories are enabled.
77
- *
78
- * Dependencies:
79
- * - wiki requires doc (wiki content is edited via doc tools)
80
- * - perm can work independently but is typically used with drive
81
- */
82
- const FeishuToolsConfigSchema = z
83
- .object({
84
- doc: z.boolean().optional(), // Document operations (default: true)
85
- wiki: z.boolean().optional(), // Knowledge base operations (default: true, requires doc)
86
- drive: z.boolean().optional(), // Cloud storage operations (default: true)
87
- perm: z.boolean().optional(), // Permission management (default: false, sensitive)
88
- scopes: z.boolean().optional(), // App scopes diagnostic (default: true)
89
- })
90
- .strict()
91
- .optional();
92
-
93
- /**
94
- * Topic session isolation mode for group chats.
95
- * - "disabled" (default): All messages in a group share one session
96
- * - "enabled": Messages in different topics get separate sessions
97
- *
98
- * When enabled, the session key becomes `chat:{chatId}:topic:{rootId}`
99
- * for messages within a topic thread, allowing isolated conversations.
100
- */
101
- const TopicSessionModeSchema = z.enum(["disabled", "enabled"]).optional();
102
-
103
- export const FeishuGroupSchema = z
104
- .object({
105
- requireMention: z.boolean().optional(),
106
- tools: ToolPolicySchema,
107
- skills: z.array(z.string()).optional(),
108
- enabled: z.boolean().optional(),
109
- allowFrom: z.array(z.union([z.string(), z.number()])).optional(),
110
- systemPrompt: z.string().optional(),
111
- topicSessionMode: TopicSessionModeSchema,
112
- })
113
- .strict();
114
-
115
- const FeishuSharedConfigShape = {
116
- webhookHost: z.string().optional(),
117
- webhookPort: z.number().int().positive().optional(),
118
- capabilities: z.array(z.string()).optional(),
119
- markdown: MarkdownConfigSchema,
120
- configWrites: z.boolean().optional(),
121
- dmPolicy: DmPolicySchema.optional(),
122
- allowFrom: z.array(z.union([z.string(), z.number()])).optional(),
123
- groupPolicy: GroupPolicySchema.optional(),
124
- groupAllowFrom: z.array(z.union([z.string(), z.number()])).optional(),
125
- requireMention: z.boolean().optional(),
126
- groups: z.record(z.string(), FeishuGroupSchema.optional()).optional(),
127
- historyLimit: z.number().int().min(0).optional(),
128
- dmHistoryLimit: z.number().int().min(0).optional(),
129
- dms: z.record(z.string(), DmConfigSchema).optional(),
130
- textChunkLimit: z.number().int().positive().optional(),
131
- chunkMode: z.enum(["length", "newline"]).optional(),
132
- blockStreamingCoalesce: BlockStreamingCoalesceSchema,
133
- mediaMaxMb: z.number().positive().optional(),
134
- heartbeat: ChannelHeartbeatVisibilitySchema,
135
- renderMode: RenderModeSchema,
136
- streaming: StreamingModeSchema,
137
- tools: FeishuToolsConfigSchema,
138
- };
139
-
140
- /**
141
- * Per-account configuration.
142
- * All fields are optional - missing fields inherit from top-level config.
143
- */
144
- export const FeishuAccountConfigSchema = z
145
- .object({
146
- enabled: z.boolean().optional(),
147
- name: z.string().optional(), // Display name for this account
148
- appId: z.string().optional(),
149
- appSecret: z.string().optional(),
150
- encryptKey: z.string().optional(),
151
- verificationToken: z.string().optional(),
152
- domain: FeishuDomainSchema.optional(),
153
- connectionMode: FeishuConnectionModeSchema.optional(),
154
- webhookPath: z.string().optional(),
155
- ...FeishuSharedConfigShape,
156
- })
157
- .strict();
158
-
159
- export const FeishuConfigSchema = z
160
- .object({
161
- enabled: z.boolean().optional(),
162
- // Top-level credentials (backward compatible for single-account mode)
163
- appId: z.string().optional(),
164
- appSecret: z.string().optional(),
165
- encryptKey: z.string().optional(),
166
- verificationToken: z.string().optional(),
167
- domain: FeishuDomainSchema.optional().default("feishu"),
168
- connectionMode: FeishuConnectionModeSchema.optional().default("websocket"),
169
- webhookPath: z.string().optional().default("/feishu/events"),
170
- ...FeishuSharedConfigShape,
171
- dmPolicy: DmPolicySchema.optional().default("pairing"),
172
- groupPolicy: GroupPolicySchema.optional().default("allowlist"),
173
- requireMention: z.boolean().optional().default(true),
174
- topicSessionMode: TopicSessionModeSchema,
175
- // Dynamic agent creation for DM users
176
- dynamicAgentCreation: DynamicAgentCreationSchema,
177
- // Multi-account configuration
178
- accounts: z.record(z.string(), FeishuAccountConfigSchema.optional()).optional(),
179
- })
180
- .strict()
181
- .superRefine((value, ctx) => {
182
- const defaultConnectionMode = value.connectionMode ?? "websocket";
183
- const defaultVerificationToken = value.verificationToken?.trim();
184
- if (defaultConnectionMode === "webhook" && !defaultVerificationToken) {
185
- ctx.addIssue({
186
- code: z.ZodIssueCode.custom,
187
- path: ["verificationToken"],
188
- message:
189
- 'channels.feishu.connectionMode="webhook" requires channels.feishu.verificationToken',
190
- });
191
- }
192
-
193
- for (const [accountId, account] of Object.entries(value.accounts ?? {})) {
194
- if (!account) {
195
- continue;
196
- }
197
- const accountConnectionMode = account.connectionMode ?? defaultConnectionMode;
198
- if (accountConnectionMode !== "webhook") {
199
- continue;
200
- }
201
- const accountVerificationToken =
202
- account.verificationToken?.trim() || defaultVerificationToken;
203
- if (!accountVerificationToken) {
204
- ctx.addIssue({
205
- code: z.ZodIssueCode.custom,
206
- path: ["accounts", accountId, "verificationToken"],
207
- message:
208
- `channels.feishu.accounts.${accountId}.connectionMode="webhook" requires ` +
209
- "a verificationToken (account-level or top-level)",
210
- });
211
- }
212
- }
213
-
214
- if (value.dmPolicy === "open") {
215
- const allowFrom = value.allowFrom ?? [];
216
- const hasWildcard = allowFrom.some((entry) => String(entry).trim() === "*");
217
- if (!hasWildcard) {
218
- ctx.addIssue({
219
- code: z.ZodIssueCode.custom,
220
- path: ["allowFrom"],
221
- message:
222
- 'channels.feishu.dmPolicy="open" requires channels.feishu.allowFrom to include "*"',
223
- });
224
- }
225
- }
226
- });