@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.
- package/config/capability-catalog.json +241 -0
- package/config/dependency-ownership.json +130 -0
- package/config/official-channel-catalog.json +39 -0
- package/dist/agents/tools/web-fetch-utils.js +2 -1
- package/dist/agents/tools/web-fetch-visibility.js +3 -1
- package/dist/brand.js +1 -1
- package/dist/browser/pw-session.js +2 -1
- package/dist/browser/pw-tools-core.state.js +3 -2
- package/dist/browser/runtime-dependency.js +27 -0
- package/dist/build-info.json +3 -3
- package/dist/canvas-host/a2ui/.bundle.hash +1 -1
- package/dist/capabilities/catalog.js +228 -0
- package/dist/cli/components-cli.js +105 -0
- package/dist/cli/hooks-cli.js +1 -1
- package/dist/cli/plugins-cli.js +3 -3
- package/dist/cli/program/register.subclis.js +9 -0
- package/dist/cli/update-cli/update-command.js +1 -1
- package/dist/commands/doctor-capabilities.js +26 -0
- package/dist/commands/doctor.js +2 -0
- package/dist/control-ui/assets/{app-DXYMrRJ9.js → app-JBrTSsNu.js} +1480 -1465
- package/dist/control-ui/assets/{index-iGQkJE0l.js → index-H-2DWAnH.js} +3 -3
- package/dist/control-ui/index.html +1 -1
- package/dist/gateway/method-scopes.js +1 -0
- package/dist/gateway/server-methods/plugins-marketplace.js +1 -1
- package/dist/gateway/server-methods/services.js +8 -0
- package/dist/gateway/server-methods-list.js +1 -0
- package/dist/infra/optional-runtime-dependency.js +46 -0
- package/dist/media/image-ops.js +6 -1
- package/dist/media/input-files.js +11 -2
- package/dist/media/mime.js +6 -1
- package/dist/memory/sqlite-vec.js +7 -1
- package/dist/plugin-sdk/{accounts-VqAX3HJ0.js → accounts-BwkH5bTD.js} +1 -1
- package/dist/plugin-sdk/{accounts-COY-15zJ.js → accounts-C5BjfxoO.js} +1 -1
- package/dist/plugin-sdk/{accounts-Zgt0NP54.js → accounts-RT6y7n3H.js} +1 -1
- package/dist/plugin-sdk/{actions-lB3PCwsz.js → actions-BrU_JMqM.js} +2 -2
- package/dist/plugin-sdk/{actions-BI5QViLk.js → actions-CUdVHzeJ.js} +2 -2
- package/dist/plugin-sdk/{active-listener-DKZiSaRA.js → active-listener-CE8t5g6l.js} +1 -1
- package/dist/plugin-sdk/{active-listener-D6_pdTMC.js → active-listener-Dx1SEGDn.js} +1 -1
- package/dist/plugin-sdk/{audio-preflight-Dx8J7XhV.js → audio-preflight-C8SbY4fV.js} +22 -22
- package/dist/plugin-sdk/{audio-preflight-CeRstduc.js → audio-preflight-CuABlLDL.js} +22 -22
- package/dist/plugin-sdk/{audit-BImNOQvk.js → audit-DxB2Kml5.js} +11 -11
- package/dist/plugin-sdk/{audit-CKWkq0Un.js → audit-sSeRDwJb.js} +11 -11
- package/dist/plugin-sdk/channel-plugin-common.js +3 -2
- package/dist/plugin-sdk/{chunk-skAJZWCT.js → chunk-KCxbJLsV.js} +1 -1
- package/dist/plugin-sdk/{chunk-Cjw4712g.js → chunk-M2d7r-Zt.js} +1 -1
- package/dist/plugin-sdk/{chunk-items-Df5811D0.js → chunk-items-BGbYyNvO.js} +1 -1
- package/dist/plugin-sdk/command-status.js +22 -22
- package/dist/plugin-sdk/{commands-registry-5J619bQ2.js → commands-registry-CdT-nl7v.js} +2 -2
- package/dist/plugin-sdk/{commands-registry-CoLAT03J.js → commands-registry-DoWdYAJd.js} +2 -2
- package/dist/plugin-sdk/{common-CSTxewqY.js → common-Cpw-vuuM.js} +1 -1
- package/dist/plugin-sdk/{common-BiF0sTnY.js → common-DJWrErdE.js} +1 -1
- package/dist/plugin-sdk/{config-BxVjLTIv.js → config-C0qggNKQ.js} +7 -7
- package/dist/plugin-sdk/{config-TFokWwvO.js → config-CgwTaper.js} +45 -2
- package/dist/plugin-sdk/{config-DXlISPlx.js → config-DtqAN2L3.js} +45 -2
- package/dist/plugin-sdk/{config-DgD5T-Ui.js → config-g1MG9Bet.js} +7 -7
- package/dist/plugin-sdk/discord.js +2 -1
- package/dist/plugin-sdk/{fetch-guard-DPMynms8.js → fetch-guard-BLdujDnt.js} +1 -1
- package/dist/plugin-sdk/{fetch-guard-COLmW2TM.js → fetch-guard-DTKgMN9f.js} +1 -1
- package/dist/plugin-sdk/{handle-action-C-UndB8E.js → handle-action-B61D85yo.js} +12 -12
- package/dist/plugin-sdk/{handle-action-hhufKxmU.js → handle-action-CjcxGzQD.js} +12 -12
- package/dist/plugin-sdk/index.js +22 -22
- package/dist/plugin-sdk/{login-DL1oBBfL.js → login-CB_nCjX3.js} +3 -3
- package/dist/plugin-sdk/{login-YveoqEvH.js → login-CfRfRNc7.js} +2 -2
- package/dist/plugin-sdk/{login-Dnxas1dI.js → login-CzUuDd1v.js} +3 -3
- package/dist/plugin-sdk/{login-qr-CVQsGWKq.js → login-qr-D7MEpFza.js} +3 -3
- package/dist/plugin-sdk/{login-qr-B343JNXJ.js → login-qr-DgxfBFVN.js} +3 -3
- package/dist/plugin-sdk/{manager-BytwRIfK.js → manager-9see0IX5.js} +8 -3
- package/dist/plugin-sdk/{manager-BZjd_PCt.js → manager-D2kZ0Cps.js} +8 -3
- package/dist/plugin-sdk/{markdown-tables-krKiU4cT.js → markdown-tables-CCSD52rA.js} +1 -1
- package/dist/plugin-sdk/{markdown-tables-9rJDQ1X-.js → markdown-tables-DWUNvLrc.js} +1 -1
- package/dist/plugin-sdk/{media-D7ZkWU-A.js → media-C7YT4DeU.js} +13 -4
- package/dist/plugin-sdk/{media-C6C2c9a4.js → media-Cxw-xLGU.js} +13 -4
- package/dist/plugin-sdk/{monitor-CVQNDfhs.js → monitor-9X7wapUN.js} +27 -27
- package/dist/plugin-sdk/{monitor-BCxkQBoh.js → monitor-B3IfJzKX.js} +26 -26
- package/dist/plugin-sdk/{monitor-BzDW50H6.js → monitor-CTjAST_W.js} +27 -27
- package/dist/plugin-sdk/{monitor-BsLMfn3U.js → monitor-tYFfy2u-.js} +26 -26
- package/dist/plugin-sdk/{openresponses-http-BB67Z4QM.js → openresponses-http-DEB2fEya.js} +22 -22
- package/dist/plugin-sdk/{openresponses-http-NE76GGhj.js → openresponses-http-YgMg1jnp.js} +22 -22
- package/dist/plugin-sdk/{ssrf-u0Ul7okY.js → optional-runtime-dependency-szS49voX.js} +46 -2
- package/dist/plugin-sdk/{outbound-PGNWU6T-.js → outbound-BCxOxdi-.js} +6 -6
- package/dist/plugin-sdk/{outbound-BHWJD9q0.js → outbound-JIwQbpRY.js} +6 -6
- package/dist/plugin-sdk/{outbound-attachment-BVzfhqnk.js → outbound-attachment-C-jSFaEB.js} +1 -1
- package/dist/plugin-sdk/{outbound-attachment-ClMvNW17.js → outbound-attachment-D6tj5Y5H.js} +1 -1
- package/dist/plugin-sdk/{pi-embedded-runner-DQ6UPx6-.js → pi-embedded-runner-CUVk8CIj.js} +72 -60
- package/dist/plugin-sdk/{pi-model-discovery-D51L5E9I.js → pi-model-discovery-DadlvsZW.js} +1 -1
- package/dist/plugin-sdk/{pi-model-discovery-runtime-DxoFm4Vd.js → pi-model-discovery-runtime-C5ssE6EW.js} +1 -1
- package/dist/plugin-sdk/{pi-model-discovery-runtime-DRuh4PNV.js → pi-model-discovery-runtime-DAaOPt64.js} +2 -2
- package/dist/plugin-sdk/{pi-model-discovery-runtime-CQOauapl.js → pi-model-discovery-runtime-LB-5lX5L.js} +1 -1
- package/dist/plugin-sdk/{pi-model-discovery-runtime-BTWgkx4x.js → pi-model-discovery-runtime-gd77b0UF.js} +2 -2
- package/dist/plugin-sdk/{pi-model-discovery-CkH5l9X5.js → pi-model-discovery-yifTIDIn.js} +1 -1
- package/dist/plugin-sdk/{pw-ai-DZs6uYRd.js → pw-ai-SNCI9UXT.js} +6 -5
- package/dist/plugin-sdk/{pw-ai-Cn-EUPZK.js → pw-ai-sH1Pi-Fh.js} +6 -5
- package/dist/plugin-sdk/{registry-B4HvWzob.js → registry-DNkJsNsz.js} +4 -3
- package/dist/plugin-sdk/{replies-jDMUBsNO.js → replies-fvzN5wnU.js} +2 -2
- package/dist/plugin-sdk/{replies-B_LW9c9f.js → replies-zebgZCHX.js} +2 -2
- package/dist/plugin-sdk/{resolve-route-_YZHbS-z.js → resolve-route-CNhTJG_2.js} +1 -1
- package/dist/plugin-sdk/{resolve-route-DlHzggnG.js → resolve-route-DO0WR4nB.js} +1 -1
- package/dist/plugin-sdk/{resolve-utils-zBhVX3Vx.js → resolve-utils-EFP1DYqG.js} +1 -1
- package/dist/plugin-sdk/{retry-policy-DGLs5ebP.js → retry-policy-BLYEgIwP.js} +1 -1
- package/dist/plugin-sdk/{retry-policy-DaodShGa.js → retry-policy-sM01QZT2.js} +1 -1
- package/dist/plugin-sdk/{runtime-Dd0sswuW.js → runtime-BPyuAmka.js} +4 -3
- package/dist/plugin-sdk/{paths-DW-U2r7Y.js → runtime-dependency-B-1u41Ph.js} +27 -3
- package/dist/plugin-sdk/{paths-CBCpJ5bu.js → runtime-dependency-Csswyv5r.js} +27 -3
- package/dist/plugin-sdk/sat-runtime.js +1 -0
- package/dist/plugin-sdk/{send-8remZhsH.js → send-B09HRfHN.js} +6 -6
- package/dist/plugin-sdk/{send-DaaAscWj.js → send-BBYcgXA4.js} +5 -5
- package/dist/plugin-sdk/{send-DFTB0cnx.js → send-BQXQA81e.js} +6 -6
- package/dist/plugin-sdk/{send-CtMVvMJs.js → send-BzFdvD_i.js} +6 -6
- package/dist/plugin-sdk/{send-Di9irjS-.js → send-C3u-F_8s.js} +6 -6
- package/dist/plugin-sdk/{send-Dl88ZKq2.js → send-D3836_UN.js} +6 -6
- package/dist/plugin-sdk/{send-ifgZCHVB.js → send-D7tr-EsH.js} +5 -5
- package/dist/plugin-sdk/{send-DvUpYh0d.js → send-DRGzRdI3.js} +6 -6
- package/dist/plugin-sdk/{send-D2jlPeKH.js → send-DfkPKz_0.js} +4 -4
- package/dist/plugin-sdk/{send-QSt6nbny.js → send-DsxFXrCO.js} +4 -4
- package/dist/plugin-sdk/{session-CknrceVU.js → session-DG_bYisw.js} +2 -2
- package/dist/plugin-sdk/{session-CyRTcJ8N.js → session-EIStzK0E.js} +2 -2
- package/dist/plugin-sdk/{skill-commands-DHxkTA0s.js → skill-commands-CkgGmWBS.js} +2 -2
- package/dist/plugin-sdk/{skill-commands-CLXAG5sU.js → skill-commands-hyZA0LE3.js} +2 -2
- package/dist/plugin-sdk/{slack-BpJXkwxF.js → slack-C0WZVJPZ.js} +34 -34
- package/dist/plugin-sdk/{slack-Br9c6Yzs.js → slack-DtlPw_PN.js} +34 -34
- package/dist/plugin-sdk/{slack-actions-8tLGt1Ht.js → slack-actions-BQawWGTJ.js} +11 -11
- package/dist/plugin-sdk/{slack-actions-CDSSRo8Y.js → slack-actions-DDMszx56.js} +11 -11
- package/dist/plugin-sdk/slack.js +2 -1
- package/dist/plugin-sdk/src/brand.d.ts +2 -2
- package/dist/plugin-sdk/src/browser/runtime-dependency.d.ts +3 -0
- package/dist/plugin-sdk/src/infra/optional-runtime-dependency.d.ts +6 -0
- package/dist/plugin-sdk/{ssrf-fG4UHKBw.js → ssrf-Cce6LubA.js} +41 -7
- package/dist/plugin-sdk/{status-DoxnzyMC.js → status-CIiBeb9B.js} +72 -60
- package/dist/plugin-sdk/{sticker-cache-zmJ39ByC.js → sticker-cache-9houHChV.js} +3 -3
- package/dist/plugin-sdk/{sticker-cache-D7WcMYsF.js → sticker-cache-Dwi-XsgB.js} +3 -3
- package/dist/plugin-sdk/{tables-CkxblF0u.js → tables-BD7H5ug-.js} +1 -1
- package/dist/plugin-sdk/{tables-RBtf8G4P.js → tables-CJE8kB35.js} +1 -1
- package/dist/plugin-sdk/{telegram-actions-DAeYXSLk.js → telegram-actions-Bu1edXF2.js} +25 -25
- package/dist/plugin-sdk/{telegram-actions-BDeS3ocd.js → telegram-actions-CRXVO8lG.js} +25 -25
- package/dist/plugin-sdk/telegram.js +2 -1
- package/dist/plugin-sdk/{thread-bindings.lifecycle-DsB94WbE.js → thread-bindings.lifecycle-Djem8FWF.js} +2 -2
- package/dist/plugin-sdk/{thread-bindings.lifecycle-DMhV3TsR.js → thread-bindings.lifecycle-gmHv3hc7.js} +2 -2
- package/dist/plugin-sdk/{thread-bindings.state-DYWpy7hJ.js → thread-bindings.state-CNT2vxm3.js} +2 -2
- package/dist/plugin-sdk/{thread-bindings.state-DG5cBaRn.js → thread-bindings.state-D8kN2X6H.js} +2 -2
- package/dist/plugin-sdk/{web-IJ4NoGPJ.js → web-DCrVQr6y.js} +26 -26
- package/dist/plugin-sdk/{web-DJwacWQo.js → web-Ds6OWw3C.js} +26 -26
- package/dist/plugin-sdk/{whatsapp-actions-DAY8hWpD.js → whatsapp-actions-68Mfs2dJ.js} +12 -12
- package/dist/plugin-sdk/{whatsapp-actions-6opfo-oB.js → whatsapp-actions-DRqtzvTO.js} +12 -12
- package/dist/plugin-sdk/whatsapp.js +6 -5
- package/dist/plugin-sdk/{wsl-B2euLEc2.js → wsl-DcM2PgSS.js} +3 -3
- package/dist/plugin-sdk/{wsl-B8eyviuv.js → wsl-PXrdWitE.js} +3 -3
- package/dist/plugins/update.js +1 -1
- package/dist/tts/tts-core.js +6 -1
- package/dist/wizard/onboarding.finalize.js +9 -0
- package/extensions/acpx/package.json +1 -1
- package/extensions/bluebubbles/package.json +1 -1
- package/extensions/copilot-proxy/package.json +1 -1
- package/extensions/diagnostics-otel/package.json +1 -1
- package/extensions/fased-federation/package.json +1 -1
- package/extensions/google-gemini-cli-auth/package.json +1 -1
- package/extensions/imessage/package.json +1 -1
- package/extensions/irc/package.json +1 -1
- package/extensions/line/package.json +1 -1
- package/extensions/llm-task/package.json +1 -1
- package/extensions/lobster/package.json +1 -1
- package/extensions/matrix/CHANGELOG.md +6 -0
- package/extensions/matrix/package.json +1 -1
- package/extensions/mattermost/package.json +1 -1
- package/extensions/memory-core/package.json +2 -2
- package/extensions/memory-lancedb/package.json +1 -1
- package/extensions/minimax-portal-auth/package.json +1 -1
- package/extensions/msteams/CHANGELOG.md +6 -0
- package/extensions/msteams/package.json +1 -1
- package/extensions/nextcloud-talk/package.json +1 -1
- package/extensions/nostr/CHANGELOG.md +6 -0
- package/extensions/nostr/package.json +1 -1
- package/extensions/open-prose/package.json +1 -1
- package/extensions/sat-mining/package.json +1 -1
- package/extensions/signal/package.json +1 -1
- package/extensions/synology-chat/package.json +1 -1
- package/extensions/tlon/package.json +1 -1
- package/extensions/twitch/CHANGELOG.md +6 -0
- package/extensions/twitch/package.json +1 -1
- package/extensions/voice-call/CHANGELOG.md +6 -0
- package/extensions/voice-call/package.json +1 -1
- package/extensions/zalo/CHANGELOG.md +6 -0
- package/extensions/zalo/package.json +1 -1
- package/extensions/zalouser/CHANGELOG.md +6 -0
- package/extensions/zalouser/package.json +1 -1
- package/package.json +22 -15
- package/extensions/feishu/fased.plugin.json +0 -10
- package/extensions/feishu/index.ts +0 -63
- package/extensions/feishu/package.json +0 -33
- package/extensions/feishu/skills/feishu-doc/SKILL.md +0 -211
- package/extensions/feishu/skills/feishu-doc/references/block-types.md +0 -103
- package/extensions/feishu/skills/feishu-drive/SKILL.md +0 -97
- package/extensions/feishu/skills/feishu-perm/SKILL.md +0 -119
- package/extensions/feishu/skills/feishu-wiki/SKILL.md +0 -111
- package/extensions/feishu/src/accounts.ts +0 -159
- package/extensions/feishu/src/bitable.ts +0 -713
- package/extensions/feishu/src/bot.ts +0 -979
- package/extensions/feishu/src/channel.ts +0 -359
- package/extensions/feishu/src/client.ts +0 -118
- package/extensions/feishu/src/config-schema.ts +0 -226
- package/extensions/feishu/src/dedup.ts +0 -54
- package/extensions/feishu/src/directory.ts +0 -177
- package/extensions/feishu/src/doc-schema.ts +0 -122
- package/extensions/feishu/src/docx.ts +0 -998
- package/extensions/feishu/src/drive-schema.ts +0 -46
- package/extensions/feishu/src/drive.ts +0 -232
- package/extensions/feishu/src/dynamic-agent.ts +0 -131
- package/extensions/feishu/src/external-keys.ts +0 -19
- package/extensions/feishu/src/media.ts +0 -447
- package/extensions/feishu/src/mention.ts +0 -133
- package/extensions/feishu/src/monitor.ts +0 -434
- package/extensions/feishu/src/onboarding.ts +0 -430
- package/extensions/feishu/src/outbound.ts +0 -56
- package/extensions/feishu/src/perm-schema.ts +0 -52
- package/extensions/feishu/src/perm.ts +0 -180
- package/extensions/feishu/src/policy.ts +0 -116
- package/extensions/feishu/src/probe.ts +0 -44
- package/extensions/feishu/src/reactions.ts +0 -160
- package/extensions/feishu/src/reply-dispatcher.ts +0 -239
- package/extensions/feishu/src/runtime.ts +0 -14
- package/extensions/feishu/src/send-result.ts +0 -29
- package/extensions/feishu/src/send-target.ts +0 -25
- package/extensions/feishu/src/send.ts +0 -313
- package/extensions/feishu/src/streaming-card.ts +0 -218
- package/extensions/feishu/src/targets.ts +0 -78
- package/extensions/feishu/src/tool-account.ts +0 -58
- package/extensions/feishu/src/tools-config.ts +0 -21
- package/extensions/feishu/src/types.ts +0 -81
- package/extensions/feishu/src/typing.ts +0 -80
- package/extensions/feishu/src/wiki-schema.ts +0 -55
- package/extensions/feishu/src/wiki.ts +0 -237
- package/extensions/googlechat/fased.plugin.json +0 -9
- package/extensions/googlechat/index.ts +0 -19
- package/extensions/googlechat/package.json +0 -37
- package/extensions/googlechat/src/accounts.ts +0 -147
- package/extensions/googlechat/src/actions.ts +0 -176
- package/extensions/googlechat/src/api.ts +0 -282
- package/extensions/googlechat/src/auth.ts +0 -137
- package/extensions/googlechat/src/channel.ts +0 -591
- package/extensions/googlechat/src/monitor.ts +0 -996
- package/extensions/googlechat/src/onboarding.ts +0 -344
- package/extensions/googlechat/src/runtime.ts +0 -14
- package/extensions/googlechat/src/targets.ts +0 -65
- package/extensions/googlechat/src/types.config.ts +0 -3
- package/extensions/googlechat/src/types.ts +0 -73
|
@@ -1,218 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Feishu Streaming Card - Card Kit streaming API for real-time text output
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import type { Client } from "@larksuiteoapi/node-sdk";
|
|
6
|
-
import type { FeishuDomain } from "./types.js";
|
|
7
|
-
|
|
8
|
-
type Credentials = { appId: string; appSecret: string; domain?: FeishuDomain };
|
|
9
|
-
type CardState = { cardId: string; messageId: string; sequence: number; currentText: string };
|
|
10
|
-
|
|
11
|
-
// Token cache (keyed by domain + appId)
|
|
12
|
-
const tokenCache = new Map<string, { token: string; expiresAt: number }>();
|
|
13
|
-
|
|
14
|
-
function resolveApiBase(domain?: FeishuDomain): string {
|
|
15
|
-
if (domain === "lark") {
|
|
16
|
-
return "https://open.larksuite.com/open-apis";
|
|
17
|
-
}
|
|
18
|
-
if (domain && domain !== "feishu" && domain.startsWith("http")) {
|
|
19
|
-
return `${domain.replace(/\/+$/, "")}/open-apis`;
|
|
20
|
-
}
|
|
21
|
-
return "https://open.feishu.cn/open-apis";
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
async function getToken(creds: Credentials): Promise<string> {
|
|
25
|
-
const key = `${creds.domain ?? "feishu"}|${creds.appId}`;
|
|
26
|
-
const cached = tokenCache.get(key);
|
|
27
|
-
if (cached && cached.expiresAt > Date.now() + 60000) {
|
|
28
|
-
return cached.token;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
const res = await fetch(`${resolveApiBase(creds.domain)}/auth/v3/tenant_access_token/internal`, {
|
|
32
|
-
method: "POST",
|
|
33
|
-
headers: { "Content-Type": "application/json" },
|
|
34
|
-
body: JSON.stringify({ app_id: creds.appId, app_secret: creds.appSecret }),
|
|
35
|
-
});
|
|
36
|
-
const data = (await res.json()) as {
|
|
37
|
-
code: number;
|
|
38
|
-
msg: string;
|
|
39
|
-
tenant_access_token?: string;
|
|
40
|
-
expire?: number;
|
|
41
|
-
};
|
|
42
|
-
if (data.code !== 0 || !data.tenant_access_token) {
|
|
43
|
-
throw new Error(`Token error: ${data.msg}`);
|
|
44
|
-
}
|
|
45
|
-
tokenCache.set(key, {
|
|
46
|
-
token: data.tenant_access_token,
|
|
47
|
-
expiresAt: Date.now() + (data.expire ?? 7200) * 1000,
|
|
48
|
-
});
|
|
49
|
-
return data.tenant_access_token;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
function truncateSummary(text: string, max = 50): string {
|
|
53
|
-
if (!text) {
|
|
54
|
-
return "";
|
|
55
|
-
}
|
|
56
|
-
const clean = text.replace(/\n/g, " ").trim();
|
|
57
|
-
return clean.length <= max ? clean : clean.slice(0, max - 3) + "...";
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
/** Streaming card session manager */
|
|
61
|
-
export class FeishuStreamingSession {
|
|
62
|
-
private client: Client;
|
|
63
|
-
private creds: Credentials;
|
|
64
|
-
private state: CardState | null = null;
|
|
65
|
-
private queue: Promise<void> = Promise.resolve();
|
|
66
|
-
private closed = false;
|
|
67
|
-
private log?: (msg: string) => void;
|
|
68
|
-
private lastUpdateTime = 0;
|
|
69
|
-
private pendingText: string | null = null;
|
|
70
|
-
private updateThrottleMs = 100; // Throttle updates to max 10/sec
|
|
71
|
-
|
|
72
|
-
constructor(client: Client, creds: Credentials, log?: (msg: string) => void) {
|
|
73
|
-
this.client = client;
|
|
74
|
-
this.creds = creds;
|
|
75
|
-
this.log = log;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
async start(
|
|
79
|
-
receiveId: string,
|
|
80
|
-
receiveIdType: "open_id" | "user_id" | "union_id" | "email" | "chat_id" = "chat_id",
|
|
81
|
-
): Promise<void> {
|
|
82
|
-
if (this.state) {
|
|
83
|
-
return;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
const apiBase = resolveApiBase(this.creds.domain);
|
|
87
|
-
const cardJson = {
|
|
88
|
-
schema: "2.0",
|
|
89
|
-
config: {
|
|
90
|
-
streaming_mode: true,
|
|
91
|
-
summary: { content: "[Generating...]" },
|
|
92
|
-
streaming_config: { print_frequency_ms: { default: 50 }, print_step: { default: 2 } },
|
|
93
|
-
},
|
|
94
|
-
body: {
|
|
95
|
-
elements: [{ tag: "markdown", content: "⏳ Thinking...", element_id: "content" }],
|
|
96
|
-
},
|
|
97
|
-
};
|
|
98
|
-
|
|
99
|
-
// Create card entity
|
|
100
|
-
const createRes = await fetch(`${apiBase}/cardkit/v1/cards`, {
|
|
101
|
-
method: "POST",
|
|
102
|
-
headers: {
|
|
103
|
-
Authorization: `Bearer ${await getToken(this.creds)}`,
|
|
104
|
-
"Content-Type": "application/json",
|
|
105
|
-
},
|
|
106
|
-
body: JSON.stringify({ type: "card_json", data: JSON.stringify(cardJson) }),
|
|
107
|
-
});
|
|
108
|
-
const createData = (await createRes.json()) as {
|
|
109
|
-
code: number;
|
|
110
|
-
msg: string;
|
|
111
|
-
data?: { card_id: string };
|
|
112
|
-
};
|
|
113
|
-
if (createData.code !== 0 || !createData.data?.card_id) {
|
|
114
|
-
throw new Error(`Create card failed: ${createData.msg}`);
|
|
115
|
-
}
|
|
116
|
-
const cardId = createData.data.card_id;
|
|
117
|
-
|
|
118
|
-
// Send card message
|
|
119
|
-
const sendRes = await this.client.im.message.create({
|
|
120
|
-
params: { receive_id_type: receiveIdType },
|
|
121
|
-
data: {
|
|
122
|
-
receive_id: receiveId,
|
|
123
|
-
msg_type: "interactive",
|
|
124
|
-
content: JSON.stringify({ type: "card", data: { card_id: cardId } }),
|
|
125
|
-
},
|
|
126
|
-
});
|
|
127
|
-
if (sendRes.code !== 0 || !sendRes.data?.message_id) {
|
|
128
|
-
throw new Error(`Send card failed: ${sendRes.msg}`);
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
this.state = { cardId, messageId: sendRes.data.message_id, sequence: 1, currentText: "" };
|
|
132
|
-
this.log?.(`Started streaming: cardId=${cardId}, messageId=${sendRes.data.message_id}`);
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
private async updateCardContent(text: string, onError?: (error: unknown) => void): Promise<void> {
|
|
136
|
-
if (!this.state) {
|
|
137
|
-
return;
|
|
138
|
-
}
|
|
139
|
-
const apiBase = resolveApiBase(this.creds.domain);
|
|
140
|
-
this.state.sequence += 1;
|
|
141
|
-
await fetch(`${apiBase}/cardkit/v1/cards/${this.state.cardId}/elements/content/content`, {
|
|
142
|
-
method: "PUT",
|
|
143
|
-
headers: {
|
|
144
|
-
Authorization: `Bearer ${await getToken(this.creds)}`,
|
|
145
|
-
"Content-Type": "application/json",
|
|
146
|
-
},
|
|
147
|
-
body: JSON.stringify({
|
|
148
|
-
content: text,
|
|
149
|
-
sequence: this.state.sequence,
|
|
150
|
-
uuid: `s_${this.state.cardId}_${this.state.sequence}`,
|
|
151
|
-
}),
|
|
152
|
-
}).catch((error) => onError?.(error));
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
async update(text: string): Promise<void> {
|
|
156
|
-
if (!this.state || this.closed) {
|
|
157
|
-
return;
|
|
158
|
-
}
|
|
159
|
-
// Throttle: skip if updated recently, but remember pending text
|
|
160
|
-
const now = Date.now();
|
|
161
|
-
if (now - this.lastUpdateTime < this.updateThrottleMs) {
|
|
162
|
-
this.pendingText = text;
|
|
163
|
-
return;
|
|
164
|
-
}
|
|
165
|
-
this.pendingText = null;
|
|
166
|
-
this.lastUpdateTime = now;
|
|
167
|
-
|
|
168
|
-
this.queue = this.queue.then(async () => {
|
|
169
|
-
if (!this.state || this.closed) {
|
|
170
|
-
return;
|
|
171
|
-
}
|
|
172
|
-
this.state.currentText = text;
|
|
173
|
-
await this.updateCardContent(text, (e) => this.log?.(`Update failed: ${String(e)}`));
|
|
174
|
-
});
|
|
175
|
-
await this.queue;
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
async close(finalText?: string): Promise<void> {
|
|
179
|
-
if (!this.state || this.closed) {
|
|
180
|
-
return;
|
|
181
|
-
}
|
|
182
|
-
this.closed = true;
|
|
183
|
-
await this.queue;
|
|
184
|
-
|
|
185
|
-
// Use finalText, or pending throttled text, or current text
|
|
186
|
-
const text = finalText ?? this.pendingText ?? this.state.currentText;
|
|
187
|
-
const apiBase = resolveApiBase(this.creds.domain);
|
|
188
|
-
|
|
189
|
-
// Only send final update if content differs from what's already displayed
|
|
190
|
-
if (text && text !== this.state.currentText) {
|
|
191
|
-
await this.updateCardContent(text);
|
|
192
|
-
this.state.currentText = text;
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
// Close streaming mode
|
|
196
|
-
this.state.sequence += 1;
|
|
197
|
-
await fetch(`${apiBase}/cardkit/v1/cards/${this.state.cardId}/settings`, {
|
|
198
|
-
method: "PATCH",
|
|
199
|
-
headers: {
|
|
200
|
-
Authorization: `Bearer ${await getToken(this.creds)}`,
|
|
201
|
-
"Content-Type": "application/json; charset=utf-8",
|
|
202
|
-
},
|
|
203
|
-
body: JSON.stringify({
|
|
204
|
-
settings: JSON.stringify({
|
|
205
|
-
config: { streaming_mode: false, summary: { content: truncateSummary(text) } },
|
|
206
|
-
}),
|
|
207
|
-
sequence: this.state.sequence,
|
|
208
|
-
uuid: `c_${this.state.cardId}_${this.state.sequence}`,
|
|
209
|
-
}),
|
|
210
|
-
}).catch((e) => this.log?.(`Close failed: ${String(e)}`));
|
|
211
|
-
|
|
212
|
-
this.log?.(`Closed streaming: cardId=${this.state.cardId}`);
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
isActive(): boolean {
|
|
216
|
-
return this.state !== null && !this.closed;
|
|
217
|
-
}
|
|
218
|
-
}
|
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
import type { FeishuIdType } from "./types.js";
|
|
2
|
-
|
|
3
|
-
const CHAT_ID_PREFIX = "oc_";
|
|
4
|
-
const OPEN_ID_PREFIX = "ou_";
|
|
5
|
-
const USER_ID_REGEX = /^[a-zA-Z0-9_-]+$/;
|
|
6
|
-
|
|
7
|
-
export function detectIdType(id: string): FeishuIdType | null {
|
|
8
|
-
const trimmed = id.trim();
|
|
9
|
-
if (trimmed.startsWith(CHAT_ID_PREFIX)) {
|
|
10
|
-
return "chat_id";
|
|
11
|
-
}
|
|
12
|
-
if (trimmed.startsWith(OPEN_ID_PREFIX)) {
|
|
13
|
-
return "open_id";
|
|
14
|
-
}
|
|
15
|
-
if (USER_ID_REGEX.test(trimmed)) {
|
|
16
|
-
return "user_id";
|
|
17
|
-
}
|
|
18
|
-
return null;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export function normalizeFeishuTarget(raw: string): string | null {
|
|
22
|
-
const trimmed = raw.trim();
|
|
23
|
-
if (!trimmed) {
|
|
24
|
-
return null;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
const lowered = trimmed.toLowerCase();
|
|
28
|
-
if (lowered.startsWith("chat:")) {
|
|
29
|
-
return trimmed.slice("chat:".length).trim() || null;
|
|
30
|
-
}
|
|
31
|
-
if (lowered.startsWith("user:")) {
|
|
32
|
-
return trimmed.slice("user:".length).trim() || null;
|
|
33
|
-
}
|
|
34
|
-
if (lowered.startsWith("open_id:")) {
|
|
35
|
-
return trimmed.slice("open_id:".length).trim() || null;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
return trimmed;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
export function formatFeishuTarget(id: string, type?: FeishuIdType): string {
|
|
42
|
-
const trimmed = id.trim();
|
|
43
|
-
if (type === "chat_id" || trimmed.startsWith(CHAT_ID_PREFIX)) {
|
|
44
|
-
return `chat:${trimmed}`;
|
|
45
|
-
}
|
|
46
|
-
if (type === "open_id" || trimmed.startsWith(OPEN_ID_PREFIX)) {
|
|
47
|
-
return `user:${trimmed}`;
|
|
48
|
-
}
|
|
49
|
-
return trimmed;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
export function resolveReceiveIdType(id: string): "chat_id" | "open_id" | "user_id" {
|
|
53
|
-
const trimmed = id.trim();
|
|
54
|
-
if (trimmed.startsWith(CHAT_ID_PREFIX)) {
|
|
55
|
-
return "chat_id";
|
|
56
|
-
}
|
|
57
|
-
if (trimmed.startsWith(OPEN_ID_PREFIX)) {
|
|
58
|
-
return "open_id";
|
|
59
|
-
}
|
|
60
|
-
return "user_id";
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
export function looksLikeFeishuId(raw: string): boolean {
|
|
64
|
-
const trimmed = raw.trim();
|
|
65
|
-
if (!trimmed) {
|
|
66
|
-
return false;
|
|
67
|
-
}
|
|
68
|
-
if (/^(chat|user|open_id):/i.test(trimmed)) {
|
|
69
|
-
return true;
|
|
70
|
-
}
|
|
71
|
-
if (trimmed.startsWith(CHAT_ID_PREFIX)) {
|
|
72
|
-
return true;
|
|
73
|
-
}
|
|
74
|
-
if (trimmed.startsWith(OPEN_ID_PREFIX)) {
|
|
75
|
-
return true;
|
|
76
|
-
}
|
|
77
|
-
return false;
|
|
78
|
-
}
|
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
import type * as Lark from "@larksuiteoapi/node-sdk";
|
|
2
|
-
import type { FasedAgentPluginApi } from "fased/plugin-sdk";
|
|
3
|
-
import { resolveFeishuAccount } from "./accounts.js";
|
|
4
|
-
import { createFeishuClient } from "./client.js";
|
|
5
|
-
import { resolveToolsConfig } from "./tools-config.js";
|
|
6
|
-
import type { FeishuToolsConfig, ResolvedFeishuAccount } from "./types.js";
|
|
7
|
-
|
|
8
|
-
type AccountAwareParams = { accountId?: string };
|
|
9
|
-
|
|
10
|
-
function normalizeOptionalAccountId(value: string | undefined): string | undefined {
|
|
11
|
-
const trimmed = value?.trim();
|
|
12
|
-
return trimmed ? trimmed : undefined;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export function resolveFeishuToolAccount(params: {
|
|
16
|
-
api: Pick<FasedAgentPluginApi, "config">;
|
|
17
|
-
executeParams?: AccountAwareParams;
|
|
18
|
-
defaultAccountId?: string;
|
|
19
|
-
}): ResolvedFeishuAccount {
|
|
20
|
-
if (!params.api.config) {
|
|
21
|
-
throw new Error("Feishu config unavailable");
|
|
22
|
-
}
|
|
23
|
-
return resolveFeishuAccount({
|
|
24
|
-
cfg: params.api.config,
|
|
25
|
-
accountId:
|
|
26
|
-
normalizeOptionalAccountId(params.executeParams?.accountId) ??
|
|
27
|
-
normalizeOptionalAccountId(params.defaultAccountId),
|
|
28
|
-
});
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
export function createFeishuToolClient(params: {
|
|
32
|
-
api: Pick<FasedAgentPluginApi, "config">;
|
|
33
|
-
executeParams?: AccountAwareParams;
|
|
34
|
-
defaultAccountId?: string;
|
|
35
|
-
}): Lark.Client {
|
|
36
|
-
return createFeishuClient(resolveFeishuToolAccount(params));
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
export function resolveAnyEnabledFeishuToolsConfig(
|
|
40
|
-
accounts: ResolvedFeishuAccount[],
|
|
41
|
-
): Required<FeishuToolsConfig> {
|
|
42
|
-
const merged: Required<FeishuToolsConfig> = {
|
|
43
|
-
doc: false,
|
|
44
|
-
wiki: false,
|
|
45
|
-
drive: false,
|
|
46
|
-
perm: false,
|
|
47
|
-
scopes: false,
|
|
48
|
-
};
|
|
49
|
-
for (const account of accounts) {
|
|
50
|
-
const cfg = resolveToolsConfig(account.config.tools);
|
|
51
|
-
merged.doc = merged.doc || cfg.doc;
|
|
52
|
-
merged.wiki = merged.wiki || cfg.wiki;
|
|
53
|
-
merged.drive = merged.drive || cfg.drive;
|
|
54
|
-
merged.perm = merged.perm || cfg.perm;
|
|
55
|
-
merged.scopes = merged.scopes || cfg.scopes;
|
|
56
|
-
}
|
|
57
|
-
return merged;
|
|
58
|
-
}
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import type { FeishuToolsConfig } from "./types.js";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Default tool configuration.
|
|
5
|
-
* - doc, wiki, drive, scopes: enabled by default
|
|
6
|
-
* - perm: disabled by default (sensitive operation)
|
|
7
|
-
*/
|
|
8
|
-
export const DEFAULT_TOOLS_CONFIG: Required<FeishuToolsConfig> = {
|
|
9
|
-
doc: true,
|
|
10
|
-
wiki: true,
|
|
11
|
-
drive: true,
|
|
12
|
-
perm: false,
|
|
13
|
-
scopes: true,
|
|
14
|
-
};
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* Resolve tools config with defaults.
|
|
18
|
-
*/
|
|
19
|
-
export function resolveToolsConfig(cfg?: FeishuToolsConfig): Required<FeishuToolsConfig> {
|
|
20
|
-
return { ...DEFAULT_TOOLS_CONFIG, ...cfg };
|
|
21
|
-
}
|
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
import type { BaseProbeResult } from "fased/plugin-sdk";
|
|
2
|
-
import type {
|
|
3
|
-
FeishuConfigSchema,
|
|
4
|
-
FeishuGroupSchema,
|
|
5
|
-
FeishuAccountConfigSchema,
|
|
6
|
-
z,
|
|
7
|
-
} from "./config-schema.js";
|
|
8
|
-
import type { MentionTarget } from "./mention.js";
|
|
9
|
-
|
|
10
|
-
export type FeishuConfig = z.infer<typeof FeishuConfigSchema>;
|
|
11
|
-
export type FeishuGroupConfig = z.infer<typeof FeishuGroupSchema>;
|
|
12
|
-
export type FeishuAccountConfig = z.infer<typeof FeishuAccountConfigSchema>;
|
|
13
|
-
|
|
14
|
-
export type FeishuDomain = "feishu" | "lark" | (string & {});
|
|
15
|
-
export type FeishuConnectionMode = "websocket" | "webhook";
|
|
16
|
-
|
|
17
|
-
export type ResolvedFeishuAccount = {
|
|
18
|
-
accountId: string;
|
|
19
|
-
enabled: boolean;
|
|
20
|
-
configured: boolean;
|
|
21
|
-
name?: string;
|
|
22
|
-
appId?: string;
|
|
23
|
-
appSecret?: string;
|
|
24
|
-
encryptKey?: string;
|
|
25
|
-
verificationToken?: string;
|
|
26
|
-
domain: FeishuDomain;
|
|
27
|
-
/** Merged config (top-level defaults + account-specific overrides) */
|
|
28
|
-
config: FeishuConfig;
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
export type FeishuIdType = "open_id" | "user_id" | "union_id" | "chat_id";
|
|
32
|
-
|
|
33
|
-
export type FeishuMessageContext = {
|
|
34
|
-
chatId: string;
|
|
35
|
-
messageId: string;
|
|
36
|
-
senderId: string;
|
|
37
|
-
senderOpenId: string;
|
|
38
|
-
senderName?: string;
|
|
39
|
-
chatType: "p2p" | "group";
|
|
40
|
-
mentionedBot: boolean;
|
|
41
|
-
rootId?: string;
|
|
42
|
-
parentId?: string;
|
|
43
|
-
content: string;
|
|
44
|
-
contentType: string;
|
|
45
|
-
/** Mention forward targets (excluding the bot itself) */
|
|
46
|
-
mentionTargets?: MentionTarget[];
|
|
47
|
-
/** Extracted message body (after removing @ placeholders) */
|
|
48
|
-
mentionMessageBody?: string;
|
|
49
|
-
};
|
|
50
|
-
|
|
51
|
-
export type FeishuSendResult = {
|
|
52
|
-
messageId: string;
|
|
53
|
-
chatId: string;
|
|
54
|
-
};
|
|
55
|
-
|
|
56
|
-
export type FeishuProbeResult = BaseProbeResult<string> & {
|
|
57
|
-
appId?: string;
|
|
58
|
-
botName?: string;
|
|
59
|
-
botOpenId?: string;
|
|
60
|
-
};
|
|
61
|
-
|
|
62
|
-
export type FeishuMediaInfo = {
|
|
63
|
-
path: string;
|
|
64
|
-
contentType?: string;
|
|
65
|
-
placeholder: string;
|
|
66
|
-
};
|
|
67
|
-
|
|
68
|
-
export type FeishuToolsConfig = {
|
|
69
|
-
doc?: boolean;
|
|
70
|
-
wiki?: boolean;
|
|
71
|
-
drive?: boolean;
|
|
72
|
-
perm?: boolean;
|
|
73
|
-
scopes?: boolean;
|
|
74
|
-
};
|
|
75
|
-
|
|
76
|
-
export type DynamicAgentCreationConfig = {
|
|
77
|
-
enabled?: boolean;
|
|
78
|
-
workspaceTemplate?: string;
|
|
79
|
-
agentDirTemplate?: string;
|
|
80
|
-
maxAgents?: number;
|
|
81
|
-
};
|
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
import type { FasedAgentConfig } from "fased/plugin-sdk";
|
|
2
|
-
import { resolveFeishuAccount } from "./accounts.js";
|
|
3
|
-
import { createFeishuClient } from "./client.js";
|
|
4
|
-
|
|
5
|
-
// Feishu emoji types for typing indicator
|
|
6
|
-
// See: https://open.feishu.cn/document/server-docs/im-v1/message-reaction/emojis-introduce
|
|
7
|
-
// Full list: https://github.com/go-lark/lark/blob/main/emoji.go
|
|
8
|
-
const TYPING_EMOJI = "Typing"; // Typing indicator emoji
|
|
9
|
-
|
|
10
|
-
export type TypingIndicatorState = {
|
|
11
|
-
messageId: string;
|
|
12
|
-
reactionId: string | null;
|
|
13
|
-
};
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* Add a typing indicator (reaction) to a message
|
|
17
|
-
*/
|
|
18
|
-
export async function addTypingIndicator(params: {
|
|
19
|
-
cfg: FasedAgentConfig;
|
|
20
|
-
messageId: string;
|
|
21
|
-
accountId?: string;
|
|
22
|
-
}): Promise<TypingIndicatorState> {
|
|
23
|
-
const { cfg, messageId, accountId } = params;
|
|
24
|
-
const account = resolveFeishuAccount({ cfg, accountId });
|
|
25
|
-
if (!account.configured) {
|
|
26
|
-
return { messageId, reactionId: null };
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
const client = createFeishuClient(account);
|
|
30
|
-
|
|
31
|
-
try {
|
|
32
|
-
const response = await client.im.messageReaction.create({
|
|
33
|
-
path: { message_id: messageId },
|
|
34
|
-
data: {
|
|
35
|
-
reaction_type: { emoji_type: TYPING_EMOJI },
|
|
36
|
-
},
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- SDK response type
|
|
40
|
-
const reactionId = (response as any)?.data?.reaction_id ?? null;
|
|
41
|
-
return { messageId, reactionId };
|
|
42
|
-
} catch (err) {
|
|
43
|
-
// Silently fail - typing indicator is not critical
|
|
44
|
-
console.log(`[feishu] failed to add typing indicator: ${err}`);
|
|
45
|
-
return { messageId, reactionId: null };
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* Remove a typing indicator (reaction) from a message
|
|
51
|
-
*/
|
|
52
|
-
export async function removeTypingIndicator(params: {
|
|
53
|
-
cfg: FasedAgentConfig;
|
|
54
|
-
state: TypingIndicatorState;
|
|
55
|
-
accountId?: string;
|
|
56
|
-
}): Promise<void> {
|
|
57
|
-
const { cfg, state, accountId } = params;
|
|
58
|
-
if (!state.reactionId) {
|
|
59
|
-
return;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
const account = resolveFeishuAccount({ cfg, accountId });
|
|
63
|
-
if (!account.configured) {
|
|
64
|
-
return;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
const client = createFeishuClient(account);
|
|
68
|
-
|
|
69
|
-
try {
|
|
70
|
-
await client.im.messageReaction.delete({
|
|
71
|
-
path: {
|
|
72
|
-
message_id: state.messageId,
|
|
73
|
-
reaction_id: state.reactionId,
|
|
74
|
-
},
|
|
75
|
-
});
|
|
76
|
-
} catch (err) {
|
|
77
|
-
// Silently fail - cleanup is not critical
|
|
78
|
-
console.log(`[feishu] failed to remove typing indicator: ${err}`);
|
|
79
|
-
}
|
|
80
|
-
}
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
import { Type, type Static } from "@sinclair/typebox";
|
|
2
|
-
|
|
3
|
-
export const FeishuWikiSchema = Type.Union([
|
|
4
|
-
Type.Object({
|
|
5
|
-
action: Type.Literal("spaces"),
|
|
6
|
-
}),
|
|
7
|
-
Type.Object({
|
|
8
|
-
action: Type.Literal("nodes"),
|
|
9
|
-
space_id: Type.String({ description: "Knowledge space ID" }),
|
|
10
|
-
parent_node_token: Type.Optional(
|
|
11
|
-
Type.String({ description: "Parent node token (optional, omit for root)" }),
|
|
12
|
-
),
|
|
13
|
-
}),
|
|
14
|
-
Type.Object({
|
|
15
|
-
action: Type.Literal("get"),
|
|
16
|
-
token: Type.String({ description: "Wiki node token (from URL /wiki/XXX)" }),
|
|
17
|
-
}),
|
|
18
|
-
Type.Object({
|
|
19
|
-
action: Type.Literal("search"),
|
|
20
|
-
query: Type.String({ description: "Search query" }),
|
|
21
|
-
space_id: Type.Optional(Type.String({ description: "Limit search to this space (optional)" })),
|
|
22
|
-
}),
|
|
23
|
-
Type.Object({
|
|
24
|
-
action: Type.Literal("create"),
|
|
25
|
-
space_id: Type.String({ description: "Knowledge space ID" }),
|
|
26
|
-
title: Type.String({ description: "Node title" }),
|
|
27
|
-
obj_type: Type.Optional(
|
|
28
|
-
Type.Union([Type.Literal("docx"), Type.Literal("sheet"), Type.Literal("bitable")], {
|
|
29
|
-
description: "Object type (default: docx)",
|
|
30
|
-
}),
|
|
31
|
-
),
|
|
32
|
-
parent_node_token: Type.Optional(
|
|
33
|
-
Type.String({ description: "Parent node token (optional, omit for root)" }),
|
|
34
|
-
),
|
|
35
|
-
}),
|
|
36
|
-
Type.Object({
|
|
37
|
-
action: Type.Literal("move"),
|
|
38
|
-
space_id: Type.String({ description: "Source knowledge space ID" }),
|
|
39
|
-
node_token: Type.String({ description: "Node token to move" }),
|
|
40
|
-
target_space_id: Type.Optional(
|
|
41
|
-
Type.String({ description: "Target space ID (optional, same space if omitted)" }),
|
|
42
|
-
),
|
|
43
|
-
target_parent_token: Type.Optional(
|
|
44
|
-
Type.String({ description: "Target parent node token (optional, root if omitted)" }),
|
|
45
|
-
),
|
|
46
|
-
}),
|
|
47
|
-
Type.Object({
|
|
48
|
-
action: Type.Literal("rename"),
|
|
49
|
-
space_id: Type.String({ description: "Knowledge space ID" }),
|
|
50
|
-
node_token: Type.String({ description: "Node token to rename" }),
|
|
51
|
-
title: Type.String({ description: "New title" }),
|
|
52
|
-
}),
|
|
53
|
-
]);
|
|
54
|
-
|
|
55
|
-
export type FeishuWikiParams = Static<typeof FeishuWikiSchema>;
|