@fased/fased 0.1.36 → 0.1.37

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 (244) 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-COY-15zJ.js → accounts-C5BjfxoO.js} +1 -1
  34. package/dist/plugin-sdk/{accounts-Zgt0NP54.js → accounts-RT6y7n3H.js} +1 -1
  35. package/dist/plugin-sdk/{actions-lB3PCwsz.js → actions-BrU_JMqM.js} +2 -2
  36. package/dist/plugin-sdk/{actions-BI5QViLk.js → actions-CUdVHzeJ.js} +2 -2
  37. package/dist/plugin-sdk/{active-listener-DKZiSaRA.js → active-listener-CE8t5g6l.js} +1 -1
  38. package/dist/plugin-sdk/{active-listener-D6_pdTMC.js → active-listener-Dx1SEGDn.js} +1 -1
  39. package/dist/plugin-sdk/{audio-preflight-Dx8J7XhV.js → audio-preflight-C8SbY4fV.js} +22 -22
  40. package/dist/plugin-sdk/{audio-preflight-CeRstduc.js → audio-preflight-CuABlLDL.js} +22 -22
  41. package/dist/plugin-sdk/{audit-BImNOQvk.js → audit-DxB2Kml5.js} +11 -11
  42. package/dist/plugin-sdk/{audit-CKWkq0Un.js → audit-sSeRDwJb.js} +11 -11
  43. package/dist/plugin-sdk/channel-plugin-common.js +3 -2
  44. package/dist/plugin-sdk/{chunk-skAJZWCT.js → chunk-KCxbJLsV.js} +1 -1
  45. package/dist/plugin-sdk/{chunk-Cjw4712g.js → chunk-M2d7r-Zt.js} +1 -1
  46. package/dist/plugin-sdk/{chunk-items-Df5811D0.js → chunk-items-BGbYyNvO.js} +1 -1
  47. package/dist/plugin-sdk/command-status.js +22 -22
  48. package/dist/plugin-sdk/{commands-registry-5J619bQ2.js → commands-registry-CdT-nl7v.js} +2 -2
  49. package/dist/plugin-sdk/{commands-registry-CoLAT03J.js → commands-registry-DoWdYAJd.js} +2 -2
  50. package/dist/plugin-sdk/{common-CSTxewqY.js → common-Cpw-vuuM.js} +1 -1
  51. package/dist/plugin-sdk/{common-BiF0sTnY.js → common-DJWrErdE.js} +1 -1
  52. package/dist/plugin-sdk/{config-BxVjLTIv.js → config-C0qggNKQ.js} +7 -7
  53. package/dist/plugin-sdk/{config-TFokWwvO.js → config-CgwTaper.js} +45 -2
  54. package/dist/plugin-sdk/{config-DXlISPlx.js → config-DtqAN2L3.js} +45 -2
  55. package/dist/plugin-sdk/{config-DgD5T-Ui.js → config-g1MG9Bet.js} +7 -7
  56. package/dist/plugin-sdk/discord.js +2 -1
  57. package/dist/plugin-sdk/{fetch-guard-DPMynms8.js → fetch-guard-BLdujDnt.js} +1 -1
  58. package/dist/plugin-sdk/{fetch-guard-COLmW2TM.js → fetch-guard-DTKgMN9f.js} +1 -1
  59. package/dist/plugin-sdk/{handle-action-C-UndB8E.js → handle-action-B61D85yo.js} +12 -12
  60. package/dist/plugin-sdk/{handle-action-hhufKxmU.js → handle-action-CjcxGzQD.js} +12 -12
  61. package/dist/plugin-sdk/index.js +22 -22
  62. package/dist/plugin-sdk/{login-DL1oBBfL.js → login-CB_nCjX3.js} +3 -3
  63. package/dist/plugin-sdk/{login-YveoqEvH.js → login-CfRfRNc7.js} +2 -2
  64. package/dist/plugin-sdk/{login-Dnxas1dI.js → login-CzUuDd1v.js} +3 -3
  65. package/dist/plugin-sdk/{login-qr-CVQsGWKq.js → login-qr-D7MEpFza.js} +3 -3
  66. package/dist/plugin-sdk/{login-qr-B343JNXJ.js → login-qr-DgxfBFVN.js} +3 -3
  67. package/dist/plugin-sdk/{manager-BytwRIfK.js → manager-9see0IX5.js} +8 -3
  68. package/dist/plugin-sdk/{manager-BZjd_PCt.js → manager-D2kZ0Cps.js} +8 -3
  69. package/dist/plugin-sdk/{markdown-tables-krKiU4cT.js → markdown-tables-CCSD52rA.js} +1 -1
  70. package/dist/plugin-sdk/{markdown-tables-9rJDQ1X-.js → markdown-tables-DWUNvLrc.js} +1 -1
  71. package/dist/plugin-sdk/{media-D7ZkWU-A.js → media-C7YT4DeU.js} +13 -4
  72. package/dist/plugin-sdk/{media-C6C2c9a4.js → media-Cxw-xLGU.js} +13 -4
  73. package/dist/plugin-sdk/{monitor-CVQNDfhs.js → monitor-9X7wapUN.js} +27 -27
  74. package/dist/plugin-sdk/{monitor-BCxkQBoh.js → monitor-B3IfJzKX.js} +26 -26
  75. package/dist/plugin-sdk/{monitor-BzDW50H6.js → monitor-CTjAST_W.js} +27 -27
  76. package/dist/plugin-sdk/{monitor-BsLMfn3U.js → monitor-tYFfy2u-.js} +26 -26
  77. package/dist/plugin-sdk/{openresponses-http-BB67Z4QM.js → openresponses-http-DEB2fEya.js} +22 -22
  78. package/dist/plugin-sdk/{openresponses-http-NE76GGhj.js → openresponses-http-YgMg1jnp.js} +22 -22
  79. package/dist/plugin-sdk/{ssrf-u0Ul7okY.js → optional-runtime-dependency-szS49voX.js} +46 -2
  80. package/dist/plugin-sdk/{outbound-PGNWU6T-.js → outbound-BCxOxdi-.js} +6 -6
  81. package/dist/plugin-sdk/{outbound-BHWJD9q0.js → outbound-JIwQbpRY.js} +6 -6
  82. package/dist/plugin-sdk/{outbound-attachment-BVzfhqnk.js → outbound-attachment-C-jSFaEB.js} +1 -1
  83. package/dist/plugin-sdk/{outbound-attachment-ClMvNW17.js → outbound-attachment-D6tj5Y5H.js} +1 -1
  84. package/dist/plugin-sdk/{pi-embedded-runner-DQ6UPx6-.js → pi-embedded-runner-CUVk8CIj.js} +72 -60
  85. package/dist/plugin-sdk/{pi-model-discovery-D51L5E9I.js → pi-model-discovery-DadlvsZW.js} +1 -1
  86. package/dist/plugin-sdk/{pi-model-discovery-runtime-DxoFm4Vd.js → pi-model-discovery-runtime-C5ssE6EW.js} +1 -1
  87. package/dist/plugin-sdk/{pi-model-discovery-runtime-DRuh4PNV.js → pi-model-discovery-runtime-DAaOPt64.js} +2 -2
  88. package/dist/plugin-sdk/{pi-model-discovery-runtime-CQOauapl.js → pi-model-discovery-runtime-LB-5lX5L.js} +1 -1
  89. package/dist/plugin-sdk/{pi-model-discovery-runtime-BTWgkx4x.js → pi-model-discovery-runtime-gd77b0UF.js} +2 -2
  90. package/dist/plugin-sdk/{pi-model-discovery-CkH5l9X5.js → pi-model-discovery-yifTIDIn.js} +1 -1
  91. package/dist/plugin-sdk/{pw-ai-DZs6uYRd.js → pw-ai-SNCI9UXT.js} +6 -5
  92. package/dist/plugin-sdk/{pw-ai-Cn-EUPZK.js → pw-ai-sH1Pi-Fh.js} +6 -5
  93. package/dist/plugin-sdk/{registry-B4HvWzob.js → registry-DNkJsNsz.js} +4 -3
  94. package/dist/plugin-sdk/{replies-jDMUBsNO.js → replies-fvzN5wnU.js} +2 -2
  95. package/dist/plugin-sdk/{replies-B_LW9c9f.js → replies-zebgZCHX.js} +2 -2
  96. package/dist/plugin-sdk/{resolve-route-_YZHbS-z.js → resolve-route-CNhTJG_2.js} +1 -1
  97. package/dist/plugin-sdk/{resolve-route-DlHzggnG.js → resolve-route-DO0WR4nB.js} +1 -1
  98. package/dist/plugin-sdk/{resolve-utils-zBhVX3Vx.js → resolve-utils-EFP1DYqG.js} +1 -1
  99. package/dist/plugin-sdk/{retry-policy-DGLs5ebP.js → retry-policy-BLYEgIwP.js} +1 -1
  100. package/dist/plugin-sdk/{retry-policy-DaodShGa.js → retry-policy-sM01QZT2.js} +1 -1
  101. package/dist/plugin-sdk/{runtime-Dd0sswuW.js → runtime-BPyuAmka.js} +4 -3
  102. package/dist/plugin-sdk/{paths-DW-U2r7Y.js → runtime-dependency-B-1u41Ph.js} +27 -3
  103. package/dist/plugin-sdk/{paths-CBCpJ5bu.js → runtime-dependency-Csswyv5r.js} +27 -3
  104. package/dist/plugin-sdk/sat-runtime.js +1 -0
  105. package/dist/plugin-sdk/{send-8remZhsH.js → send-B09HRfHN.js} +6 -6
  106. package/dist/plugin-sdk/{send-DaaAscWj.js → send-BBYcgXA4.js} +5 -5
  107. package/dist/plugin-sdk/{send-DFTB0cnx.js → send-BQXQA81e.js} +6 -6
  108. package/dist/plugin-sdk/{send-CtMVvMJs.js → send-BzFdvD_i.js} +6 -6
  109. package/dist/plugin-sdk/{send-Di9irjS-.js → send-C3u-F_8s.js} +6 -6
  110. package/dist/plugin-sdk/{send-Dl88ZKq2.js → send-D3836_UN.js} +6 -6
  111. package/dist/plugin-sdk/{send-ifgZCHVB.js → send-D7tr-EsH.js} +5 -5
  112. package/dist/plugin-sdk/{send-DvUpYh0d.js → send-DRGzRdI3.js} +6 -6
  113. package/dist/plugin-sdk/{send-D2jlPeKH.js → send-DfkPKz_0.js} +4 -4
  114. package/dist/plugin-sdk/{send-QSt6nbny.js → send-DsxFXrCO.js} +4 -4
  115. package/dist/plugin-sdk/{session-CknrceVU.js → session-DG_bYisw.js} +2 -2
  116. package/dist/plugin-sdk/{session-CyRTcJ8N.js → session-EIStzK0E.js} +2 -2
  117. package/dist/plugin-sdk/{skill-commands-DHxkTA0s.js → skill-commands-CkgGmWBS.js} +2 -2
  118. package/dist/plugin-sdk/{skill-commands-CLXAG5sU.js → skill-commands-hyZA0LE3.js} +2 -2
  119. package/dist/plugin-sdk/{slack-BpJXkwxF.js → slack-C0WZVJPZ.js} +34 -34
  120. package/dist/plugin-sdk/{slack-Br9c6Yzs.js → slack-DtlPw_PN.js} +34 -34
  121. package/dist/plugin-sdk/{slack-actions-8tLGt1Ht.js → slack-actions-BQawWGTJ.js} +11 -11
  122. package/dist/plugin-sdk/{slack-actions-CDSSRo8Y.js → slack-actions-DDMszx56.js} +11 -11
  123. package/dist/plugin-sdk/slack.js +2 -1
  124. package/dist/plugin-sdk/src/brand.d.ts +2 -2
  125. package/dist/plugin-sdk/src/browser/runtime-dependency.d.ts +3 -0
  126. package/dist/plugin-sdk/src/infra/optional-runtime-dependency.d.ts +6 -0
  127. package/dist/plugin-sdk/{ssrf-fG4UHKBw.js → ssrf-Cce6LubA.js} +41 -7
  128. package/dist/plugin-sdk/{status-DoxnzyMC.js → status-CIiBeb9B.js} +72 -60
  129. package/dist/plugin-sdk/{sticker-cache-zmJ39ByC.js → sticker-cache-9houHChV.js} +3 -3
  130. package/dist/plugin-sdk/{sticker-cache-D7WcMYsF.js → sticker-cache-Dwi-XsgB.js} +3 -3
  131. package/dist/plugin-sdk/{tables-CkxblF0u.js → tables-BD7H5ug-.js} +1 -1
  132. package/dist/plugin-sdk/{tables-RBtf8G4P.js → tables-CJE8kB35.js} +1 -1
  133. package/dist/plugin-sdk/{telegram-actions-DAeYXSLk.js → telegram-actions-Bu1edXF2.js} +25 -25
  134. package/dist/plugin-sdk/{telegram-actions-BDeS3ocd.js → telegram-actions-CRXVO8lG.js} +25 -25
  135. package/dist/plugin-sdk/telegram.js +2 -1
  136. package/dist/plugin-sdk/{thread-bindings.lifecycle-DsB94WbE.js → thread-bindings.lifecycle-Djem8FWF.js} +2 -2
  137. package/dist/plugin-sdk/{thread-bindings.lifecycle-DMhV3TsR.js → thread-bindings.lifecycle-gmHv3hc7.js} +2 -2
  138. package/dist/plugin-sdk/{thread-bindings.state-DYWpy7hJ.js → thread-bindings.state-CNT2vxm3.js} +2 -2
  139. package/dist/plugin-sdk/{thread-bindings.state-DG5cBaRn.js → thread-bindings.state-D8kN2X6H.js} +2 -2
  140. package/dist/plugin-sdk/{web-IJ4NoGPJ.js → web-DCrVQr6y.js} +26 -26
  141. package/dist/plugin-sdk/{web-DJwacWQo.js → web-Ds6OWw3C.js} +26 -26
  142. package/dist/plugin-sdk/{whatsapp-actions-DAY8hWpD.js → whatsapp-actions-68Mfs2dJ.js} +12 -12
  143. package/dist/plugin-sdk/{whatsapp-actions-6opfo-oB.js → whatsapp-actions-DRqtzvTO.js} +12 -12
  144. package/dist/plugin-sdk/whatsapp.js +6 -5
  145. package/dist/plugin-sdk/{wsl-B2euLEc2.js → wsl-DcM2PgSS.js} +3 -3
  146. package/dist/plugin-sdk/{wsl-B8eyviuv.js → wsl-PXrdWitE.js} +3 -3
  147. package/dist/plugins/update.js +1 -1
  148. package/dist/tts/tts-core.js +6 -1
  149. package/dist/wizard/onboarding.finalize.js +9 -0
  150. package/extensions/acpx/package.json +1 -1
  151. package/extensions/bluebubbles/package.json +1 -1
  152. package/extensions/copilot-proxy/package.json +1 -1
  153. package/extensions/diagnostics-otel/package.json +1 -1
  154. package/extensions/fased-federation/package.json +1 -1
  155. package/extensions/google-gemini-cli-auth/package.json +1 -1
  156. package/extensions/imessage/package.json +1 -1
  157. package/extensions/irc/package.json +1 -1
  158. package/extensions/line/package.json +1 -1
  159. package/extensions/llm-task/package.json +1 -1
  160. package/extensions/lobster/package.json +1 -1
  161. package/extensions/matrix/CHANGELOG.md +6 -0
  162. package/extensions/matrix/package.json +1 -1
  163. package/extensions/mattermost/package.json +1 -1
  164. package/extensions/memory-core/package.json +2 -2
  165. package/extensions/memory-lancedb/package.json +1 -1
  166. package/extensions/minimax-portal-auth/package.json +1 -1
  167. package/extensions/msteams/CHANGELOG.md +6 -0
  168. package/extensions/msteams/package.json +1 -1
  169. package/extensions/nextcloud-talk/package.json +1 -1
  170. package/extensions/nostr/CHANGELOG.md +6 -0
  171. package/extensions/nostr/package.json +1 -1
  172. package/extensions/open-prose/package.json +1 -1
  173. package/extensions/sat-mining/package.json +1 -1
  174. package/extensions/signal/package.json +1 -1
  175. package/extensions/synology-chat/package.json +1 -1
  176. package/extensions/tlon/package.json +1 -1
  177. package/extensions/twitch/CHANGELOG.md +6 -0
  178. package/extensions/twitch/package.json +1 -1
  179. package/extensions/voice-call/CHANGELOG.md +6 -0
  180. package/extensions/voice-call/package.json +1 -1
  181. package/extensions/zalo/CHANGELOG.md +6 -0
  182. package/extensions/zalo/package.json +1 -1
  183. package/extensions/zalouser/CHANGELOG.md +6 -0
  184. package/extensions/zalouser/package.json +1 -1
  185. package/package.json +22 -15
  186. package/extensions/feishu/fased.plugin.json +0 -10
  187. package/extensions/feishu/index.ts +0 -63
  188. package/extensions/feishu/package.json +0 -33
  189. package/extensions/feishu/skills/feishu-doc/SKILL.md +0 -211
  190. package/extensions/feishu/skills/feishu-doc/references/block-types.md +0 -103
  191. package/extensions/feishu/skills/feishu-drive/SKILL.md +0 -97
  192. package/extensions/feishu/skills/feishu-perm/SKILL.md +0 -119
  193. package/extensions/feishu/skills/feishu-wiki/SKILL.md +0 -111
  194. package/extensions/feishu/src/accounts.ts +0 -159
  195. package/extensions/feishu/src/bitable.ts +0 -713
  196. package/extensions/feishu/src/bot.ts +0 -979
  197. package/extensions/feishu/src/channel.ts +0 -359
  198. package/extensions/feishu/src/client.ts +0 -118
  199. package/extensions/feishu/src/config-schema.ts +0 -226
  200. package/extensions/feishu/src/dedup.ts +0 -54
  201. package/extensions/feishu/src/directory.ts +0 -177
  202. package/extensions/feishu/src/doc-schema.ts +0 -122
  203. package/extensions/feishu/src/docx.ts +0 -998
  204. package/extensions/feishu/src/drive-schema.ts +0 -46
  205. package/extensions/feishu/src/drive.ts +0 -232
  206. package/extensions/feishu/src/dynamic-agent.ts +0 -131
  207. package/extensions/feishu/src/external-keys.ts +0 -19
  208. package/extensions/feishu/src/media.ts +0 -447
  209. package/extensions/feishu/src/mention.ts +0 -133
  210. package/extensions/feishu/src/monitor.ts +0 -434
  211. package/extensions/feishu/src/onboarding.ts +0 -430
  212. package/extensions/feishu/src/outbound.ts +0 -56
  213. package/extensions/feishu/src/perm-schema.ts +0 -52
  214. package/extensions/feishu/src/perm.ts +0 -180
  215. package/extensions/feishu/src/policy.ts +0 -116
  216. package/extensions/feishu/src/probe.ts +0 -44
  217. package/extensions/feishu/src/reactions.ts +0 -160
  218. package/extensions/feishu/src/reply-dispatcher.ts +0 -239
  219. package/extensions/feishu/src/runtime.ts +0 -14
  220. package/extensions/feishu/src/send-result.ts +0 -29
  221. package/extensions/feishu/src/send-target.ts +0 -25
  222. package/extensions/feishu/src/send.ts +0 -313
  223. package/extensions/feishu/src/streaming-card.ts +0 -218
  224. package/extensions/feishu/src/targets.ts +0 -78
  225. package/extensions/feishu/src/tool-account.ts +0 -58
  226. package/extensions/feishu/src/tools-config.ts +0 -21
  227. package/extensions/feishu/src/types.ts +0 -81
  228. package/extensions/feishu/src/typing.ts +0 -80
  229. package/extensions/feishu/src/wiki-schema.ts +0 -55
  230. package/extensions/feishu/src/wiki.ts +0 -237
  231. package/extensions/googlechat/fased.plugin.json +0 -9
  232. package/extensions/googlechat/index.ts +0 -19
  233. package/extensions/googlechat/package.json +0 -37
  234. package/extensions/googlechat/src/accounts.ts +0 -147
  235. package/extensions/googlechat/src/actions.ts +0 -176
  236. package/extensions/googlechat/src/api.ts +0 -282
  237. package/extensions/googlechat/src/auth.ts +0 -137
  238. package/extensions/googlechat/src/channel.ts +0 -591
  239. package/extensions/googlechat/src/monitor.ts +0 -996
  240. package/extensions/googlechat/src/onboarding.ts +0 -344
  241. package/extensions/googlechat/src/runtime.ts +0 -14
  242. package/extensions/googlechat/src/targets.ts +0 -65
  243. package/extensions/googlechat/src/types.config.ts +0 -3
  244. package/extensions/googlechat/src/types.ts +0 -73
@@ -1,239 +0,0 @@
1
- import {
2
- createReplyPrefixContext,
3
- createTypingCallbacks,
4
- logTypingFailure,
5
- type FasedAgentConfig,
6
- type ReplyPayload,
7
- type RuntimeEnv,
8
- } from "fased/plugin-sdk";
9
- import { resolveFeishuAccount } from "./accounts.js";
10
- import { createFeishuClient } from "./client.js";
11
- import type { MentionTarget } from "./mention.js";
12
- import { buildMentionedCardContent } from "./mention.js";
13
- import { getFeishuRuntime } from "./runtime.js";
14
- import { sendMarkdownCardFeishu, sendMessageFeishu } from "./send.js";
15
- import { FeishuStreamingSession } from "./streaming-card.js";
16
- import { resolveReceiveIdType } from "./targets.js";
17
- import { addTypingIndicator, removeTypingIndicator, type TypingIndicatorState } from "./typing.js";
18
-
19
- /** Detect if text contains markdown elements that benefit from card rendering */
20
- function shouldUseCard(text: string): boolean {
21
- return /```[\s\S]*?```/.test(text) || /\|.+\|[\r\n]+\|[-:| ]+\|/.test(text);
22
- }
23
-
24
- export type CreateFeishuReplyDispatcherParams = {
25
- cfg: FasedAgentConfig;
26
- agentId: string;
27
- runtime: RuntimeEnv;
28
- chatId: string;
29
- replyToMessageId?: string;
30
- mentionTargets?: MentionTarget[];
31
- accountId?: string;
32
- };
33
-
34
- export function createFeishuReplyDispatcher(params: CreateFeishuReplyDispatcherParams) {
35
- const core = getFeishuRuntime();
36
- const { cfg, agentId, chatId, replyToMessageId, mentionTargets, accountId } = params;
37
- const account = resolveFeishuAccount({ cfg, accountId });
38
- const prefixContext = createReplyPrefixContext({ cfg, agentId });
39
-
40
- let typingState: TypingIndicatorState | null = null;
41
- const typingCallbacks = createTypingCallbacks({
42
- start: async () => {
43
- if (!replyToMessageId) {
44
- return;
45
- }
46
- typingState = await addTypingIndicator({ cfg, messageId: replyToMessageId, accountId });
47
- },
48
- stop: async () => {
49
- if (!typingState) {
50
- return;
51
- }
52
- await removeTypingIndicator({ cfg, state: typingState, accountId });
53
- typingState = null;
54
- },
55
- onStartError: (err) =>
56
- logTypingFailure({
57
- log: (message) => params.runtime.log?.(message),
58
- channel: "feishu",
59
- action: "start",
60
- error: err,
61
- }),
62
- onStopError: (err) =>
63
- logTypingFailure({
64
- log: (message) => params.runtime.log?.(message),
65
- channel: "feishu",
66
- action: "stop",
67
- error: err,
68
- }),
69
- });
70
-
71
- const textChunkLimit = core.channel.text.resolveTextChunkLimit(cfg, "feishu", accountId, {
72
- fallbackLimit: 4000,
73
- });
74
- const chunkMode = core.channel.text.resolveChunkMode(cfg, "feishu");
75
- const tableMode = core.channel.text.resolveMarkdownTableMode({ cfg, channel: "feishu" });
76
- const renderMode = account.config?.renderMode ?? "auto";
77
- const streamingEnabled = account.config?.streaming !== false && renderMode !== "raw";
78
-
79
- let streaming: FeishuStreamingSession | null = null;
80
- let streamText = "";
81
- let lastPartial = "";
82
- let partialUpdateQueue: Promise<void> = Promise.resolve();
83
- let streamingStartPromise: Promise<void> | null = null;
84
-
85
- const startStreaming = () => {
86
- if (!streamingEnabled || streamingStartPromise || streaming) {
87
- return;
88
- }
89
- streamingStartPromise = (async () => {
90
- const creds =
91
- account.appId && account.appSecret
92
- ? { appId: account.appId, appSecret: account.appSecret, domain: account.domain }
93
- : null;
94
- if (!creds) {
95
- return;
96
- }
97
-
98
- streaming = new FeishuStreamingSession(createFeishuClient(account), creds, (message) =>
99
- params.runtime.log?.(`feishu[${account.accountId}] ${message}`),
100
- );
101
- try {
102
- await streaming.start(chatId, resolveReceiveIdType(chatId));
103
- } catch (error) {
104
- params.runtime.error?.(`feishu: streaming start failed: ${String(error)}`);
105
- streaming = null;
106
- }
107
- })();
108
- };
109
-
110
- const closeStreaming = async () => {
111
- if (streamingStartPromise) {
112
- await streamingStartPromise;
113
- }
114
- await partialUpdateQueue;
115
- if (streaming?.isActive()) {
116
- let text = streamText;
117
- if (mentionTargets?.length) {
118
- text = buildMentionedCardContent(mentionTargets, text);
119
- }
120
- await streaming.close(text);
121
- }
122
- streaming = null;
123
- streamingStartPromise = null;
124
- streamText = "";
125
- lastPartial = "";
126
- };
127
-
128
- const { dispatcher, replyOptions, markDispatchIdle } =
129
- core.channel.reply.createReplyDispatcherWithTyping({
130
- responsePrefix: prefixContext.responsePrefix,
131
- responsePrefixContextProvider: prefixContext.responsePrefixContextProvider,
132
- humanDelay: core.channel.reply.resolveHumanDelayConfig(cfg, agentId),
133
- onReplyStart: () => {
134
- if (streamingEnabled && renderMode === "card") {
135
- startStreaming();
136
- }
137
- void typingCallbacks.onReplyStart?.();
138
- },
139
- deliver: async (payload: ReplyPayload, info) => {
140
- const text = payload.text ?? "";
141
- if (!text.trim()) {
142
- return;
143
- }
144
-
145
- const useCard = renderMode === "card" || (renderMode === "auto" && shouldUseCard(text));
146
-
147
- if ((info?.kind === "block" || info?.kind === "final") && streamingEnabled && useCard) {
148
- startStreaming();
149
- if (streamingStartPromise) {
150
- await streamingStartPromise;
151
- }
152
- }
153
-
154
- if (streaming?.isActive()) {
155
- if (info?.kind === "final") {
156
- streamText = text;
157
- await closeStreaming();
158
- }
159
- return;
160
- }
161
-
162
- let first = true;
163
- if (useCard) {
164
- for (const chunk of core.channel.text.chunkTextWithMode(
165
- text,
166
- textChunkLimit,
167
- chunkMode,
168
- )) {
169
- await sendMarkdownCardFeishu({
170
- cfg,
171
- to: chatId,
172
- text: chunk,
173
- replyToMessageId,
174
- mentions: first ? mentionTargets : undefined,
175
- accountId,
176
- });
177
- first = false;
178
- }
179
- } else {
180
- const converted = core.channel.text.convertMarkdownTables(text, tableMode);
181
- for (const chunk of core.channel.text.chunkTextWithMode(
182
- converted,
183
- textChunkLimit,
184
- chunkMode,
185
- )) {
186
- await sendMessageFeishu({
187
- cfg,
188
- to: chatId,
189
- text: chunk,
190
- replyToMessageId,
191
- mentions: first ? mentionTargets : undefined,
192
- accountId,
193
- });
194
- first = false;
195
- }
196
- }
197
- },
198
- onError: async (error, info) => {
199
- params.runtime.error?.(
200
- `feishu[${account.accountId}] ${info.kind} reply failed: ${String(error)}`,
201
- );
202
- await closeStreaming();
203
- typingCallbacks.onIdle?.();
204
- },
205
- onIdle: async () => {
206
- await closeStreaming();
207
- typingCallbacks.onIdle?.();
208
- },
209
- onCleanup: () => {
210
- typingCallbacks.onCleanup?.();
211
- },
212
- });
213
-
214
- return {
215
- dispatcher,
216
- replyOptions: {
217
- ...replyOptions,
218
- onModelSelected: prefixContext.onModelSelected,
219
- onPartialReply: streamingEnabled
220
- ? (payload: ReplyPayload) => {
221
- if (!payload.text || payload.text === lastPartial) {
222
- return;
223
- }
224
- lastPartial = payload.text;
225
- streamText = payload.text;
226
- partialUpdateQueue = partialUpdateQueue.then(async () => {
227
- if (streamingStartPromise) {
228
- await streamingStartPromise;
229
- }
230
- if (streaming?.isActive()) {
231
- await streaming.update(streamText);
232
- }
233
- });
234
- }
235
- : undefined,
236
- },
237
- markDispatchIdle,
238
- };
239
- }
@@ -1,14 +0,0 @@
1
- import type { PluginRuntime } from "fased/plugin-sdk";
2
-
3
- let runtime: PluginRuntime | null = null;
4
-
5
- export function setFeishuRuntime(next: PluginRuntime) {
6
- runtime = next;
7
- }
8
-
9
- export function getFeishuRuntime(): PluginRuntime {
10
- if (!runtime) {
11
- throw new Error("Feishu runtime not initialized");
12
- }
13
- return runtime;
14
- }
@@ -1,29 +0,0 @@
1
- export type FeishuMessageApiResponse = {
2
- code?: number;
3
- msg?: string;
4
- data?: {
5
- message_id?: string;
6
- };
7
- };
8
-
9
- export function assertFeishuMessageApiSuccess(
10
- response: FeishuMessageApiResponse,
11
- errorPrefix: string,
12
- ) {
13
- if (response.code !== 0) {
14
- throw new Error(`${errorPrefix}: ${response.msg || `code ${response.code}`}`);
15
- }
16
- }
17
-
18
- export function toFeishuSendResult(
19
- response: FeishuMessageApiResponse,
20
- chatId: string,
21
- ): {
22
- messageId: string;
23
- chatId: string;
24
- } {
25
- return {
26
- messageId: response.data?.message_id ?? "unknown",
27
- chatId,
28
- };
29
- }
@@ -1,25 +0,0 @@
1
- import type { FasedAgentConfig } from "fased/plugin-sdk";
2
- import { resolveFeishuAccount } from "./accounts.js";
3
- import { createFeishuClient } from "./client.js";
4
- import { resolveReceiveIdType, normalizeFeishuTarget } from "./targets.js";
5
-
6
- export function resolveFeishuSendTarget(params: {
7
- cfg: FasedAgentConfig;
8
- to: string;
9
- accountId?: string;
10
- }) {
11
- const account = resolveFeishuAccount({ cfg: params.cfg, accountId: params.accountId });
12
- if (!account.configured) {
13
- throw new Error(`Feishu account "${account.accountId}" not configured`);
14
- }
15
- const client = createFeishuClient(account);
16
- const receiveId = normalizeFeishuTarget(params.to);
17
- if (!receiveId) {
18
- throw new Error(`Invalid Feishu target: ${params.to}`);
19
- }
20
- return {
21
- client,
22
- receiveId,
23
- receiveIdType: resolveReceiveIdType(receiveId),
24
- };
25
- }
@@ -1,313 +0,0 @@
1
- import type { FasedAgentConfig } from "fased/plugin-sdk";
2
- import { resolveFeishuAccount } from "./accounts.js";
3
- import { createFeishuClient } from "./client.js";
4
- import type { MentionTarget } from "./mention.js";
5
- import { buildMentionedMessage, buildMentionedCardContent } from "./mention.js";
6
- import { getFeishuRuntime } from "./runtime.js";
7
- import { assertFeishuMessageApiSuccess, toFeishuSendResult } from "./send-result.js";
8
- import { resolveFeishuSendTarget } from "./send-target.js";
9
- import type { FeishuSendResult } from "./types.js";
10
-
11
- export type FeishuMessageInfo = {
12
- messageId: string;
13
- chatId: string;
14
- senderId?: string;
15
- senderOpenId?: string;
16
- content: string;
17
- contentType: string;
18
- createTime?: number;
19
- };
20
-
21
- /**
22
- * Get a message by its ID.
23
- * Useful for fetching quoted/replied message content.
24
- */
25
- export async function getMessageFeishu(params: {
26
- cfg: FasedAgentConfig;
27
- messageId: string;
28
- accountId?: string;
29
- }): Promise<FeishuMessageInfo | null> {
30
- const { cfg, messageId, accountId } = params;
31
- const account = resolveFeishuAccount({ cfg, accountId });
32
- if (!account.configured) {
33
- throw new Error(`Feishu account "${account.accountId}" not configured`);
34
- }
35
-
36
- const client = createFeishuClient(account);
37
-
38
- try {
39
- const response = (await client.im.message.get({
40
- path: { message_id: messageId },
41
- })) as {
42
- code?: number;
43
- msg?: string;
44
- data?: {
45
- items?: Array<{
46
- message_id?: string;
47
- chat_id?: string;
48
- msg_type?: string;
49
- body?: { content?: string };
50
- sender?: {
51
- id?: string;
52
- id_type?: string;
53
- sender_type?: string;
54
- };
55
- create_time?: string;
56
- }>;
57
- };
58
- };
59
-
60
- if (response.code !== 0) {
61
- return null;
62
- }
63
-
64
- const item = response.data?.items?.[0];
65
- if (!item) {
66
- return null;
67
- }
68
-
69
- // Parse content based on message type
70
- let content = item.body?.content ?? "";
71
- try {
72
- const parsed = JSON.parse(content);
73
- if (item.msg_type === "text" && parsed.text) {
74
- content = parsed.text;
75
- }
76
- } catch {
77
- // Keep raw content if parsing fails
78
- }
79
-
80
- return {
81
- messageId: item.message_id ?? messageId,
82
- chatId: item.chat_id ?? "",
83
- senderId: item.sender?.id,
84
- senderOpenId: item.sender?.id_type === "open_id" ? item.sender?.id : undefined,
85
- content,
86
- contentType: item.msg_type ?? "text",
87
- createTime: item.create_time ? parseInt(item.create_time, 10) : undefined,
88
- };
89
- } catch {
90
- return null;
91
- }
92
- }
93
-
94
- export type SendFeishuMessageParams = {
95
- cfg: FasedAgentConfig;
96
- to: string;
97
- text: string;
98
- replyToMessageId?: string;
99
- /** Mention target users */
100
- mentions?: MentionTarget[];
101
- /** Account ID (optional, uses default if not specified) */
102
- accountId?: string;
103
- };
104
-
105
- function buildFeishuPostMessagePayload(params: { messageText: string }): {
106
- content: string;
107
- msgType: string;
108
- } {
109
- const { messageText } = params;
110
- return {
111
- content: JSON.stringify({
112
- zh_cn: {
113
- content: [
114
- [
115
- {
116
- tag: "md",
117
- text: messageText,
118
- },
119
- ],
120
- ],
121
- },
122
- }),
123
- msgType: "post",
124
- };
125
- }
126
-
127
- export async function sendMessageFeishu(
128
- params: SendFeishuMessageParams,
129
- ): Promise<FeishuSendResult> {
130
- const { cfg, to, text, replyToMessageId, mentions, accountId } = params;
131
- const { client, receiveId, receiveIdType } = resolveFeishuSendTarget({ cfg, to, accountId });
132
- const tableMode = getFeishuRuntime().channel.text.resolveMarkdownTableMode({
133
- cfg,
134
- channel: "feishu",
135
- });
136
-
137
- // Build message content (with @mention support)
138
- let rawText = text ?? "";
139
- if (mentions && mentions.length > 0) {
140
- rawText = buildMentionedMessage(mentions, rawText);
141
- }
142
- const messageText = getFeishuRuntime().channel.text.convertMarkdownTables(rawText, tableMode);
143
-
144
- const { content, msgType } = buildFeishuPostMessagePayload({ messageText });
145
-
146
- if (replyToMessageId) {
147
- const response = await client.im.message.reply({
148
- path: { message_id: replyToMessageId },
149
- data: {
150
- content,
151
- msg_type: msgType,
152
- },
153
- });
154
- assertFeishuMessageApiSuccess(response, "Feishu reply failed");
155
- return toFeishuSendResult(response, receiveId);
156
- }
157
-
158
- const response = await client.im.message.create({
159
- params: { receive_id_type: receiveIdType },
160
- data: {
161
- receive_id: receiveId,
162
- content,
163
- msg_type: msgType,
164
- },
165
- });
166
- assertFeishuMessageApiSuccess(response, "Feishu send failed");
167
- return toFeishuSendResult(response, receiveId);
168
- }
169
-
170
- export type SendFeishuCardParams = {
171
- cfg: FasedAgentConfig;
172
- to: string;
173
- card: Record<string, unknown>;
174
- replyToMessageId?: string;
175
- accountId?: string;
176
- };
177
-
178
- export async function sendCardFeishu(params: SendFeishuCardParams): Promise<FeishuSendResult> {
179
- const { cfg, to, card, replyToMessageId, accountId } = params;
180
- const { client, receiveId, receiveIdType } = resolveFeishuSendTarget({ cfg, to, accountId });
181
- const content = JSON.stringify(card);
182
-
183
- if (replyToMessageId) {
184
- const response = await client.im.message.reply({
185
- path: { message_id: replyToMessageId },
186
- data: {
187
- content,
188
- msg_type: "interactive",
189
- },
190
- });
191
- assertFeishuMessageApiSuccess(response, "Feishu card reply failed");
192
- return toFeishuSendResult(response, receiveId);
193
- }
194
-
195
- const response = await client.im.message.create({
196
- params: { receive_id_type: receiveIdType },
197
- data: {
198
- receive_id: receiveId,
199
- content,
200
- msg_type: "interactive",
201
- },
202
- });
203
- assertFeishuMessageApiSuccess(response, "Feishu card send failed");
204
- return toFeishuSendResult(response, receiveId);
205
- }
206
-
207
- export async function updateCardFeishu(params: {
208
- cfg: FasedAgentConfig;
209
- messageId: string;
210
- card: Record<string, unknown>;
211
- accountId?: string;
212
- }): Promise<void> {
213
- const { cfg, messageId, card, accountId } = params;
214
- const account = resolveFeishuAccount({ cfg, accountId });
215
- if (!account.configured) {
216
- throw new Error(`Feishu account "${account.accountId}" not configured`);
217
- }
218
-
219
- const client = createFeishuClient(account);
220
- const content = JSON.stringify(card);
221
-
222
- const response = await client.im.message.patch({
223
- path: { message_id: messageId },
224
- data: { content },
225
- });
226
-
227
- if (response.code !== 0) {
228
- throw new Error(`Feishu card update failed: ${response.msg || `code ${response.code}`}`);
229
- }
230
- }
231
-
232
- /**
233
- * Build a Feishu interactive card with markdown content.
234
- * Cards render markdown properly (code blocks, tables, links, etc.)
235
- * Uses schema 2.0 format for proper markdown rendering.
236
- */
237
- export function buildMarkdownCard(text: string): Record<string, unknown> {
238
- return {
239
- schema: "2.0",
240
- config: {
241
- wide_screen_mode: true,
242
- },
243
- body: {
244
- elements: [
245
- {
246
- tag: "markdown",
247
- content: text,
248
- },
249
- ],
250
- },
251
- };
252
- }
253
-
254
- /**
255
- * Send a message as a markdown card (interactive message).
256
- * This renders markdown properly in Feishu (code blocks, tables, bold/italic, etc.)
257
- */
258
- export async function sendMarkdownCardFeishu(params: {
259
- cfg: FasedAgentConfig;
260
- to: string;
261
- text: string;
262
- replyToMessageId?: string;
263
- /** Mention target users */
264
- mentions?: MentionTarget[];
265
- accountId?: string;
266
- }): Promise<FeishuSendResult> {
267
- const { cfg, to, text, replyToMessageId, mentions, accountId } = params;
268
- // Build message content (with @mention support)
269
- let cardText = text;
270
- if (mentions && mentions.length > 0) {
271
- cardText = buildMentionedCardContent(mentions, text);
272
- }
273
- const card = buildMarkdownCard(cardText);
274
- return sendCardFeishu({ cfg, to, card, replyToMessageId, accountId });
275
- }
276
-
277
- /**
278
- * Edit an existing text message.
279
- * Note: Feishu only allows editing messages within 24 hours.
280
- */
281
- export async function editMessageFeishu(params: {
282
- cfg: FasedAgentConfig;
283
- messageId: string;
284
- text: string;
285
- accountId?: string;
286
- }): Promise<void> {
287
- const { cfg, messageId, text, accountId } = params;
288
- const account = resolveFeishuAccount({ cfg, accountId });
289
- if (!account.configured) {
290
- throw new Error(`Feishu account "${account.accountId}" not configured`);
291
- }
292
-
293
- const client = createFeishuClient(account);
294
- const tableMode = getFeishuRuntime().channel.text.resolveMarkdownTableMode({
295
- cfg,
296
- channel: "feishu",
297
- });
298
- const messageText = getFeishuRuntime().channel.text.convertMarkdownTables(text ?? "", tableMode);
299
-
300
- const { content, msgType } = buildFeishuPostMessagePayload({ messageText });
301
-
302
- const response = await client.im.message.update({
303
- path: { message_id: messageId },
304
- data: {
305
- msg_type: msgType,
306
- content,
307
- },
308
- });
309
-
310
- if (response.code !== 0) {
311
- throw new Error(`Feishu message edit failed: ${response.msg || `code ${response.code}`}`);
312
- }
313
- }