@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,430 +0,0 @@
1
- import type {
2
- ChannelOnboardingAdapter,
3
- ChannelOnboardingDmPolicy,
4
- FasedAgentConfig,
5
- DmPolicy,
6
- WizardPrompter,
7
- } from "fased/plugin-sdk";
8
- import { addWildcardAllowFrom, DEFAULT_ACCOUNT_ID, formatDocsLink } from "fased/plugin-sdk";
9
- import { resolveFeishuCredentials } from "./accounts.js";
10
- import { probeFeishu } from "./probe.js";
11
- import type { FeishuConfig } from "./types.js";
12
-
13
- const channel = "feishu" as const;
14
-
15
- function setFeishuDmPolicy(cfg: FasedAgentConfig, dmPolicy: DmPolicy): FasedAgentConfig {
16
- const allowFrom =
17
- dmPolicy === "open"
18
- ? addWildcardAllowFrom(cfg.channels?.feishu?.allowFrom)?.map((entry) => String(entry))
19
- : undefined;
20
- return {
21
- ...cfg,
22
- channels: {
23
- ...cfg.channels,
24
- feishu: {
25
- ...cfg.channels?.feishu,
26
- dmPolicy,
27
- ...(allowFrom ? { allowFrom } : {}),
28
- },
29
- },
30
- };
31
- }
32
-
33
- function setFeishuAllowFrom(cfg: FasedAgentConfig, allowFrom: string[]): FasedAgentConfig {
34
- return {
35
- ...cfg,
36
- channels: {
37
- ...cfg.channels,
38
- feishu: {
39
- ...cfg.channels?.feishu,
40
- allowFrom,
41
- },
42
- },
43
- };
44
- }
45
-
46
- function parseAllowFromInput(raw: string): string[] {
47
- return raw
48
- .split(/[\n,;]+/g)
49
- .map((entry) => entry.trim())
50
- .filter(Boolean);
51
- }
52
-
53
- async function promptFeishuAllowFrom(params: {
54
- cfg: FasedAgentConfig;
55
- prompter: WizardPrompter;
56
- }): Promise<FasedAgentConfig> {
57
- const existing = params.cfg.channels?.feishu?.allowFrom ?? [];
58
- await params.prompter.note(
59
- [
60
- "Allowlist Feishu DMs by open_id or user_id.",
61
- "You can find user open_id in Feishu admin console or via API.",
62
- "Examples:",
63
- "- ou_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
64
- "- on_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
65
- ].join("\n"),
66
- "Feishu allowlist",
67
- );
68
-
69
- while (true) {
70
- const entry = await params.prompter.text({
71
- message: "Feishu allowFrom (user open_ids)",
72
- placeholder: "ou_xxxxx, ou_yyyyy",
73
- initialValue: existing[0] ? String(existing[0]) : undefined,
74
- validate: (value) => (String(value ?? "").trim() ? undefined : "Required"),
75
- });
76
- const parts = parseAllowFromInput(String(entry));
77
- if (parts.length === 0) {
78
- await params.prompter.note("Enter at least one user.", "Feishu allowlist");
79
- continue;
80
- }
81
-
82
- const unique = [
83
- ...new Set([
84
- ...existing.map((v: string | number) => String(v).trim()).filter(Boolean),
85
- ...parts,
86
- ]),
87
- ];
88
- return setFeishuAllowFrom(params.cfg, unique);
89
- }
90
- }
91
-
92
- async function noteFeishuCredentialHelp(prompter: WizardPrompter): Promise<void> {
93
- await prompter.note(
94
- [
95
- "1) Go to Feishu Open Platform (open.feishu.cn)",
96
- "2) Create a self-built app",
97
- "3) Get App ID and App Secret from Credentials page",
98
- "4) Enable required permissions: im:message, im:chat, contact:user.base:readonly",
99
- "5) Publish the app or add it to a test group",
100
- "Tip: you can also set FEISHU_APP_ID / FEISHU_APP_SECRET env vars.",
101
- `Docs: ${formatDocsLink("/channels/feishu", "feishu")}`,
102
- ].join("\n"),
103
- "Feishu credentials",
104
- );
105
- }
106
-
107
- async function promptFeishuCredentials(prompter: WizardPrompter): Promise<{
108
- appId: string;
109
- appSecret: string;
110
- }> {
111
- const appId = String(
112
- await prompter.text({
113
- message: "Enter Feishu App ID",
114
- validate: (value) => (value?.trim() ? undefined : "Required"),
115
- }),
116
- ).trim();
117
- const appSecret = String(
118
- await prompter.text({
119
- message: "Enter Feishu App Secret",
120
- validate: (value) => (value?.trim() ? undefined : "Required"),
121
- }),
122
- ).trim();
123
- return { appId, appSecret };
124
- }
125
-
126
- function setFeishuGroupPolicy(
127
- cfg: FasedAgentConfig,
128
- groupPolicy: "open" | "allowlist" | "disabled",
129
- ): FasedAgentConfig {
130
- return {
131
- ...cfg,
132
- channels: {
133
- ...cfg.channels,
134
- feishu: {
135
- ...cfg.channels?.feishu,
136
- enabled: true,
137
- groupPolicy,
138
- },
139
- },
140
- };
141
- }
142
-
143
- function setFeishuGroupAllowFrom(
144
- cfg: FasedAgentConfig,
145
- groupAllowFrom: string[],
146
- ): FasedAgentConfig {
147
- return {
148
- ...cfg,
149
- channels: {
150
- ...cfg.channels,
151
- feishu: {
152
- ...cfg.channels?.feishu,
153
- groupAllowFrom,
154
- },
155
- },
156
- };
157
- }
158
-
159
- const dmPolicy: ChannelOnboardingDmPolicy = {
160
- label: "Feishu",
161
- channel,
162
- policyKey: "channels.feishu.dmPolicy",
163
- allowFromKey: "channels.feishu.allowFrom",
164
- getCurrent: (cfg) => (cfg.channels?.feishu as FeishuConfig | undefined)?.dmPolicy ?? "pairing",
165
- setPolicy: (cfg, policy) => setFeishuDmPolicy(cfg, policy),
166
- promptAllowFrom: promptFeishuAllowFrom,
167
- };
168
-
169
- export const feishuOnboardingAdapter: ChannelOnboardingAdapter = {
170
- channel,
171
- uiSetup: {
172
- title: "Feishu",
173
- detail: "App credentials.",
174
- notes: [
175
- "1) Go to Feishu Open Platform (open.feishu.cn)",
176
- "2) Create a self-built app",
177
- "3) Get App ID and App Secret from Credentials page",
178
- "4) Enable required permissions: im:message, im:chat, contact:user.base:readonly",
179
- "5) Publish the app or add it to a test group",
180
- "Tip: you can also set FEISHU_APP_ID / FEISHU_APP_SECRET env vars.",
181
- ],
182
- fields: [
183
- {
184
- label: "App ID",
185
- path: ["channels", "feishu", "appId"],
186
- placeholder: "cli_xxxxx",
187
- },
188
- {
189
- label: "App Secret",
190
- path: ["channels", "feishu", "appSecret"],
191
- placeholder: "App Secret",
192
- kind: "password",
193
- },
194
- {
195
- label: "Domain",
196
- path: ["channels", "feishu", "domain"],
197
- kind: "select",
198
- options: [
199
- { label: "Feishu (China)", value: "feishu" },
200
- { label: "Lark (International)", value: "lark" },
201
- ],
202
- },
203
- {
204
- label: "Connection mode",
205
- path: ["channels", "feishu", "connectionMode"],
206
- kind: "select",
207
- options: [
208
- { label: "WebSocket", value: "websocket" },
209
- { label: "Webhook", value: "webhook" },
210
- ],
211
- },
212
- {
213
- label: "Verification token",
214
- path: ["channels", "feishu", "verificationToken"],
215
- placeholder: "Required for webhook mode",
216
- kind: "password",
217
- },
218
- {
219
- label: "Encrypt key",
220
- path: ["channels", "feishu", "encryptKey"],
221
- placeholder: "Optional",
222
- kind: "password",
223
- },
224
- {
225
- label: "Webhook path",
226
- path: ["channels", "feishu", "webhookPath"],
227
- placeholder: "/feishu/events",
228
- },
229
- {
230
- label: "Group policy",
231
- path: ["channels", "feishu", "groupPolicy"],
232
- kind: "select",
233
- options: [
234
- { label: "Allowlist", value: "allowlist" },
235
- { label: "Open", value: "open" },
236
- { label: "Disabled", value: "disabled" },
237
- ],
238
- },
239
- {
240
- label: "Group allowlist",
241
- path: ["channels", "feishu", "groupAllowFrom"],
242
- placeholder: "oc_xxxxx, oc_yyyyy",
243
- kind: "list",
244
- },
245
- ],
246
- },
247
- getStatus: async ({ cfg }) => {
248
- const feishuCfg = cfg.channels?.feishu as FeishuConfig | undefined;
249
- const configured = Boolean(resolveFeishuCredentials(feishuCfg));
250
-
251
- // Try to probe if configured
252
- let probeResult = null;
253
- if (configured && feishuCfg) {
254
- try {
255
- probeResult = await probeFeishu(feishuCfg);
256
- } catch {
257
- // Ignore probe errors
258
- }
259
- }
260
-
261
- const statusLines: string[] = [];
262
- if (!configured) {
263
- statusLines.push("Feishu: needs app credentials");
264
- } else if (probeResult?.ok) {
265
- statusLines.push(
266
- `Feishu: connected as ${probeResult.botName ?? probeResult.botOpenId ?? "bot"}`,
267
- );
268
- } else {
269
- statusLines.push("Feishu: configured (connection not verified)");
270
- }
271
-
272
- return {
273
- channel,
274
- configured,
275
- statusLines,
276
- selectionHint: configured ? "configured" : "needs app creds",
277
- quickstartScore: configured ? 2 : 0,
278
- };
279
- },
280
-
281
- configure: async ({ cfg, prompter }) => {
282
- const feishuCfg = cfg.channels?.feishu as FeishuConfig | undefined;
283
- const resolved = resolveFeishuCredentials(feishuCfg);
284
- const hasConfigCreds = Boolean(feishuCfg?.appId?.trim() && feishuCfg?.appSecret?.trim());
285
- const canUseEnv = Boolean(
286
- !hasConfigCreds && process.env.FEISHU_APP_ID?.trim() && process.env.FEISHU_APP_SECRET?.trim(),
287
- );
288
-
289
- let next = cfg;
290
- let appId: string | null = null;
291
- let appSecret: string | null = null;
292
-
293
- if (!resolved) {
294
- await noteFeishuCredentialHelp(prompter);
295
- }
296
-
297
- if (canUseEnv) {
298
- const keepEnv = await prompter.confirm({
299
- message: "FEISHU_APP_ID + FEISHU_APP_SECRET detected. Use env vars?",
300
- initialValue: true,
301
- });
302
- if (keepEnv) {
303
- next = {
304
- ...next,
305
- channels: {
306
- ...next.channels,
307
- feishu: { ...next.channels?.feishu, enabled: true },
308
- },
309
- };
310
- } else {
311
- const entered = await promptFeishuCredentials(prompter);
312
- appId = entered.appId;
313
- appSecret = entered.appSecret;
314
- }
315
- } else if (hasConfigCreds) {
316
- const keep = await prompter.confirm({
317
- message: "Feishu credentials already configured. Keep them?",
318
- initialValue: true,
319
- });
320
- if (!keep) {
321
- const entered = await promptFeishuCredentials(prompter);
322
- appId = entered.appId;
323
- appSecret = entered.appSecret;
324
- }
325
- } else {
326
- const entered = await promptFeishuCredentials(prompter);
327
- appId = entered.appId;
328
- appSecret = entered.appSecret;
329
- }
330
-
331
- if (appId && appSecret) {
332
- next = {
333
- ...next,
334
- channels: {
335
- ...next.channels,
336
- feishu: {
337
- ...next.channels?.feishu,
338
- enabled: true,
339
- appId,
340
- appSecret,
341
- },
342
- },
343
- };
344
-
345
- // Test connection
346
- const testCfg = next.channels?.feishu as FeishuConfig;
347
- try {
348
- const probe = await probeFeishu(testCfg);
349
- if (probe.ok) {
350
- await prompter.note(
351
- `Connected as ${probe.botName ?? probe.botOpenId ?? "bot"}`,
352
- "Feishu connection test",
353
- );
354
- } else {
355
- await prompter.note(
356
- `Connection failed: ${probe.error ?? "unknown error"}`,
357
- "Feishu connection test",
358
- );
359
- }
360
- } catch (err) {
361
- await prompter.note(`Connection test failed: ${String(err)}`, "Feishu connection test");
362
- }
363
- }
364
-
365
- // Domain selection
366
- const currentDomain = (next.channels?.feishu as FeishuConfig | undefined)?.domain ?? "feishu";
367
- const domain = await prompter.select({
368
- message: "Which Feishu domain?",
369
- options: [
370
- { value: "feishu", label: "Feishu (feishu.cn) - China" },
371
- { value: "lark", label: "Lark (larksuite.com) - International" },
372
- ],
373
- initialValue: currentDomain,
374
- });
375
- if (domain) {
376
- next = {
377
- ...next,
378
- channels: {
379
- ...next.channels,
380
- feishu: {
381
- ...next.channels?.feishu,
382
- domain: domain as "feishu" | "lark",
383
- },
384
- },
385
- };
386
- }
387
-
388
- // Group policy
389
- const groupPolicy = await prompter.select({
390
- message: "Group chat policy",
391
- options: [
392
- { value: "allowlist", label: "Allowlist - only respond in specific groups" },
393
- { value: "open", label: "Open - respond in all groups (requires mention)" },
394
- { value: "disabled", label: "Disabled - don't respond in groups" },
395
- ],
396
- initialValue: (next.channels?.feishu as FeishuConfig | undefined)?.groupPolicy ?? "allowlist",
397
- });
398
- if (groupPolicy) {
399
- next = setFeishuGroupPolicy(next, groupPolicy as "open" | "allowlist" | "disabled");
400
- }
401
-
402
- // Group allowlist if needed
403
- if (groupPolicy === "allowlist") {
404
- const existing = (next.channels?.feishu as FeishuConfig | undefined)?.groupAllowFrom ?? [];
405
- const entry = await prompter.text({
406
- message: "Group chat allowlist (chat_ids)",
407
- placeholder: "oc_xxxxx, oc_yyyyy",
408
- initialValue: existing.length > 0 ? existing.map(String).join(", ") : undefined,
409
- });
410
- if (entry) {
411
- const parts = parseAllowFromInput(String(entry));
412
- if (parts.length > 0) {
413
- next = setFeishuGroupAllowFrom(next, parts);
414
- }
415
- }
416
- }
417
-
418
- return { cfg: next, accountId: DEFAULT_ACCOUNT_ID };
419
- },
420
-
421
- dmPolicy,
422
-
423
- disable: (cfg) => ({
424
- ...cfg,
425
- channels: {
426
- ...cfg.channels,
427
- feishu: { ...cfg.channels?.feishu, enabled: false },
428
- },
429
- }),
430
- };
@@ -1,56 +0,0 @@
1
- import type { ChannelOutboundAdapter } from "fased/plugin-sdk";
2
- import { sendMediaFeishu } from "./media.js";
3
- import { getFeishuRuntime } from "./runtime.js";
4
- import { sendMessageFeishu } from "./send.js";
5
-
6
- export const feishuOutbound: ChannelOutboundAdapter = {
7
- deliveryMode: "direct",
8
- chunker: (text, limit) => getFeishuRuntime().channel.text.chunkMarkdownText(text, limit),
9
- chunkerMode: "markdown",
10
- textChunkLimit: 4000,
11
- sendText: async ({ cfg, to, text, accountId }) => {
12
- const result = await sendMessageFeishu({ cfg, to, text, accountId: accountId ?? undefined });
13
- return { channel: "feishu", ...result };
14
- },
15
- sendMedia: async ({ cfg, to, text, mediaUrl, accountId, mediaLocalRoots }) => {
16
- // Send text first if provided
17
- if (text?.trim()) {
18
- await sendMessageFeishu({ cfg, to, text, accountId: accountId ?? undefined });
19
- }
20
-
21
- // Upload and send media if URL or local path provided
22
- if (mediaUrl) {
23
- try {
24
- const result = await sendMediaFeishu({
25
- cfg,
26
- to,
27
- mediaUrl,
28
- accountId: accountId ?? undefined,
29
- mediaLocalRoots,
30
- });
31
- return { channel: "feishu", ...result };
32
- } catch (err) {
33
- // Log the error for debugging
34
- console.error(`[feishu] sendMediaFeishu failed:`, err);
35
- // Fallback to URL link if upload fails
36
- const fallbackText = `📎 ${mediaUrl}`;
37
- const result = await sendMessageFeishu({
38
- cfg,
39
- to,
40
- text: fallbackText,
41
- accountId: accountId ?? undefined,
42
- });
43
- return { channel: "feishu", ...result };
44
- }
45
- }
46
-
47
- // No media URL, just return text result
48
- const result = await sendMessageFeishu({
49
- cfg,
50
- to,
51
- text: text ?? "",
52
- accountId: accountId ?? undefined,
53
- });
54
- return { channel: "feishu", ...result };
55
- },
56
- };
@@ -1,52 +0,0 @@
1
- import { Type, type Static } from "@sinclair/typebox";
2
-
3
- const TokenType = Type.Union([
4
- Type.Literal("doc"),
5
- Type.Literal("docx"),
6
- Type.Literal("sheet"),
7
- Type.Literal("bitable"),
8
- Type.Literal("folder"),
9
- Type.Literal("file"),
10
- Type.Literal("wiki"),
11
- Type.Literal("mindnote"),
12
- ]);
13
-
14
- const MemberType = Type.Union([
15
- Type.Literal("email"),
16
- Type.Literal("openid"),
17
- Type.Literal("userid"),
18
- Type.Literal("unionid"),
19
- Type.Literal("openchat"),
20
- Type.Literal("opendepartmentid"),
21
- ]);
22
-
23
- const Permission = Type.Union([
24
- Type.Literal("view"),
25
- Type.Literal("edit"),
26
- Type.Literal("full_access"),
27
- ]);
28
-
29
- export const FeishuPermSchema = Type.Union([
30
- Type.Object({
31
- action: Type.Literal("list"),
32
- token: Type.String({ description: "File token" }),
33
- type: TokenType,
34
- }),
35
- Type.Object({
36
- action: Type.Literal("add"),
37
- token: Type.String({ description: "File token" }),
38
- type: TokenType,
39
- member_type: MemberType,
40
- member_id: Type.String({ description: "Member ID (email, open_id, user_id, etc.)" }),
41
- perm: Permission,
42
- }),
43
- Type.Object({
44
- action: Type.Literal("remove"),
45
- token: Type.String({ description: "File token" }),
46
- type: TokenType,
47
- member_type: MemberType,
48
- member_id: Type.String({ description: "Member ID to remove" }),
49
- }),
50
- ]);
51
-
52
- export type FeishuPermParams = Static<typeof FeishuPermSchema>;