@openclaw/feishu 2026.7.2-beta.7 → 2026.8.1-beta.3
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/dist/accounts-CCCdMen2.js +203 -0
- package/dist/api.js +61 -60
- package/dist/{channel-CScE82zY.js → channel-Ceq80_zP.js} +71 -42
- package/dist/channel-plugin-api.js +1 -1
- package/dist/{channel.runtime-B21e1E0r.js → channel.runtime-DnRyzGoU.js} +201 -152
- package/dist/{client-Dcbs6vml.js → client-Hp7uo_cl.js} +27 -16
- package/dist/contract-api.js +2 -2
- package/dist/{conversation-id-BeJL-wq7.js → conversation-id-VYgGQ-GX.js} +11 -15
- package/dist/doctor-contract-api.js +1 -1
- package/dist/doctor-contract-bEQXIXyP.js +158 -0
- package/dist/{drive-hSi_Utp0.js → drive-BVYM_Y4k.js} +325 -44
- package/dist/{media-CEUraFOR.js → media-BDouVaaM.js} +298 -182
- package/dist/{monitor-DngbaA6a.js → monitor-CZ8cDXrq.js} +3 -3
- package/dist/{monitor.account-BnTWCw55.js → monitor.account-Dq_voVMB.js} +263 -179
- package/dist/{monitor.startup-CqH2tiJq.js → monitor.startup-BGErejNH.js} +1 -1
- package/dist/{probe-p3POS2RN.js → probe-DVpy58s0.js} +2 -2
- package/dist/security-audit-D6Fz2h6p.js +23 -0
- package/dist/{send-result-B9_BpUPx.js → send-result-DEAycmOk.js} +18 -9
- package/dist/session-binding-contract-api.js +2 -2
- package/dist/{session-conversation-BksWrfzm.js → session-conversation-DFCIvQK-.js} +1 -1
- package/dist/session-key-api.js +1 -1
- package/dist/setup-api.js +1 -1
- package/dist/{subagent-hooks-Cx1cX7rW.js → subagent-hooks-KUi-7vUy.js} +4 -64
- package/dist/subagent-hooks-api.js +1 -1
- package/dist/{thread-bindings-N3wkgkIN.js → thread-bindings-CptM_YU6.js} +7 -9
- package/openclaw.plugin.json +143 -1
- package/package.json +4 -4
- package/skills/feishu-doc/SKILL.md +20 -195
- package/skills/feishu-doc/references/block-types.md +9 -14
- package/skills/feishu-drive/SKILL.md +16 -102
- package/skills/feishu-perm/SKILL.md +10 -110
- package/skills/feishu-wiki/SKILL.md +13 -109
- package/dist/accounts-u9X5Wsan.js +0 -469
- package/dist/doctor-contract-BiD9tyIv.js +0 -102
- package/dist/security-audit-D7WK_BHh.js +0 -11
|
@@ -1,17 +1,13 @@
|
|
|
1
|
-
import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
1
|
+
import { normalizeLowercaseStringOrEmpty, normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
2
2
|
//#region extensions/feishu/src/conversation-id.ts
|
|
3
3
|
function resolveConfiguredFeishuGroupSessionScope(params) {
|
|
4
4
|
const legacyTopicSessionMode = params.groupConfig?.topicSessionMode ?? params.feishuCfg?.topicSessionMode ?? "disabled";
|
|
5
5
|
return params.groupConfig?.groupSessionScope ?? params.feishuCfg?.groupSessionScope ?? (legacyTopicSessionMode === "enabled" ? "group_topic" : "group");
|
|
6
6
|
}
|
|
7
|
-
function normalizeText(value) {
|
|
8
|
-
if (typeof value !== "string") return;
|
|
9
|
-
return value.trim() || void 0;
|
|
10
|
-
}
|
|
11
7
|
function buildFeishuConversationId(params) {
|
|
12
|
-
const chatId =
|
|
13
|
-
const senderOpenId =
|
|
14
|
-
const topicId =
|
|
8
|
+
const chatId = normalizeOptionalString(params.chatId) ?? "unknown";
|
|
9
|
+
const senderOpenId = normalizeOptionalString(params.senderOpenId);
|
|
10
|
+
const topicId = normalizeOptionalString(params.topicId);
|
|
15
11
|
switch (params.scope) {
|
|
16
12
|
case "group_sender": return senderOpenId ? `${chatId}:sender:${senderOpenId}` : chatId;
|
|
17
13
|
case "group_topic": return topicId ? `${chatId}:topic:${topicId}` : chatId;
|
|
@@ -23,7 +19,7 @@ function buildFeishuConversationId(params) {
|
|
|
23
19
|
}
|
|
24
20
|
}
|
|
25
21
|
function parseFeishuTargetId(raw) {
|
|
26
|
-
const target =
|
|
22
|
+
const target = normalizeOptionalString(raw);
|
|
27
23
|
if (!target) return;
|
|
28
24
|
const withoutProvider = target.replace(/^(feishu|lark):/i, "").trim();
|
|
29
25
|
if (!withoutProvider) return;
|
|
@@ -35,11 +31,11 @@ function parseFeishuTargetId(raw) {
|
|
|
35
31
|
"user:",
|
|
36
32
|
"dm:",
|
|
37
33
|
"open_id:"
|
|
38
|
-
]) if (lowered.startsWith(prefix)) return
|
|
34
|
+
]) if (lowered.startsWith(prefix)) return normalizeOptionalString(withoutProvider.slice(prefix.length));
|
|
39
35
|
return withoutProvider;
|
|
40
36
|
}
|
|
41
37
|
function parseFeishuDirectConversationId(raw) {
|
|
42
|
-
const target =
|
|
38
|
+
const target = normalizeOptionalString(raw);
|
|
43
39
|
if (!target) return;
|
|
44
40
|
const withoutProvider = target.replace(/^(feishu|lark):/i, "").trim();
|
|
45
41
|
if (!withoutProvider) return;
|
|
@@ -48,14 +44,14 @@ function parseFeishuDirectConversationId(raw) {
|
|
|
48
44
|
"user:",
|
|
49
45
|
"dm:",
|
|
50
46
|
"open_id:"
|
|
51
|
-
]) if (lowered.startsWith(prefix)) return
|
|
47
|
+
]) if (lowered.startsWith(prefix)) return normalizeOptionalString(withoutProvider.slice(prefix.length));
|
|
52
48
|
const id = parseFeishuTargetId(target);
|
|
53
49
|
if (!id) return;
|
|
54
50
|
if (id.startsWith("ou_") || id.startsWith("on_")) return id;
|
|
55
51
|
}
|
|
56
52
|
function parseFeishuConversationId(params) {
|
|
57
|
-
const conversationId =
|
|
58
|
-
const parentConversationId =
|
|
53
|
+
const conversationId = normalizeOptionalString(params.conversationId);
|
|
54
|
+
const parentConversationId = normalizeOptionalString(params.parentConversationId);
|
|
59
55
|
if (!conversationId) return null;
|
|
60
56
|
const topicSenderMatch = conversationId.match(/^(.+):topic:([^:]+):sender:([^:]+)$/i);
|
|
61
57
|
if (topicSenderMatch) {
|
|
@@ -121,7 +117,7 @@ function parseFeishuConversationId(params) {
|
|
|
121
117
|
};
|
|
122
118
|
}
|
|
123
119
|
function buildFeishuModelOverrideParentCandidates(parentConversationId) {
|
|
124
|
-
const rawId =
|
|
120
|
+
const rawId = normalizeOptionalString(parentConversationId);
|
|
125
121
|
if (!rawId) return [];
|
|
126
122
|
const topicSenderMatch = rawId.match(/^(.+):topic:([^:]+):sender:([^:]+)$/i);
|
|
127
123
|
if (topicSenderMatch) {
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { n as normalizeCompatibilityConfig, t as legacyConfigRules } from "./doctor-contract-
|
|
1
|
+
import { n as normalizeCompatibilityConfig, t as legacyConfigRules } from "./doctor-contract-bEQXIXyP.js";
|
|
2
2
|
export { legacyConfigRules, normalizeCompatibilityConfig };
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import { asObjectRecord, defineChannelAliasMigration, defineKeyMoveMigration, hasLegacyAccountStreamingAliases, normalizeChannelConfigEntries } from "openclaw/plugin-sdk/runtime-doctor-migrations";
|
|
2
|
+
//#region extensions/feishu/src/webhook-path.ts
|
|
3
|
+
const DEFAULT_FEISHU_WEBHOOK_PATH = "/feishu/events";
|
|
4
|
+
/** Normalize trusted configuration only; incoming request targets must remain unmodified. */
|
|
5
|
+
function normalizeFeishuWebhookPath(value) {
|
|
6
|
+
const configured = value?.trim();
|
|
7
|
+
if (!configured) return DEFAULT_FEISHU_WEBHOOK_PATH;
|
|
8
|
+
try {
|
|
9
|
+
const parsed = new URL(configured, "http://localhost");
|
|
10
|
+
if (parsed.protocol !== "http:" && parsed.protocol !== "https:") return null;
|
|
11
|
+
const emptyQuery = !parsed.search && parsed.href.endsWith("?") && !configured.includes("#") ? "?" : "";
|
|
12
|
+
return `${parsed.pathname}${parsed.search}${emptyQuery}`;
|
|
13
|
+
} catch {
|
|
14
|
+
return null;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
//#endregion
|
|
18
|
+
//#region extensions/feishu/src/doctor-contract.ts
|
|
19
|
+
const streamingAliasMigration = defineChannelAliasMigration({
|
|
20
|
+
channelId: "feishu",
|
|
21
|
+
streaming: { defaultMode: "partial" },
|
|
22
|
+
accountStreamingReplacesRoot: true
|
|
23
|
+
});
|
|
24
|
+
const LEGACY_COALESCE_FIELDS = [
|
|
25
|
+
"enabled",
|
|
26
|
+
"minDelayMs",
|
|
27
|
+
"maxDelayMs"
|
|
28
|
+
];
|
|
29
|
+
const LEGACY_HEARTBEAT_FIELDS = ["visibility", "intervalMs"];
|
|
30
|
+
const toolsBaseMigration = defineKeyMoveMigration({
|
|
31
|
+
from: ["tools", "base"],
|
|
32
|
+
to: ["tools", "bitable"],
|
|
33
|
+
match: (value) => typeof value === "boolean",
|
|
34
|
+
sourceOwn: false
|
|
35
|
+
});
|
|
36
|
+
function sanitizeLegacyHeartbeatFields(params) {
|
|
37
|
+
const heartbeat = asObjectRecord(params.entry.heartbeat);
|
|
38
|
+
if (!heartbeat || Object.keys(heartbeat).length > 0 && !LEGACY_HEARTBEAT_FIELDS.some((field) => Object.hasOwn(heartbeat, field))) return {
|
|
39
|
+
entry: params.entry,
|
|
40
|
+
changed: false
|
|
41
|
+
};
|
|
42
|
+
const next = { ...params.entry };
|
|
43
|
+
delete next.heartbeat;
|
|
44
|
+
params.changes.push(`Removed ${params.pathPrefix}.heartbeat (legacy Feishu fields were never read by runtime).`);
|
|
45
|
+
return {
|
|
46
|
+
entry: next,
|
|
47
|
+
changed: true
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
function sanitizeLegacyCoalesceFields(params) {
|
|
51
|
+
const streaming = asObjectRecord(params.entry.streaming);
|
|
52
|
+
const block = asObjectRecord(streaming?.block);
|
|
53
|
+
const coalesce = asObjectRecord(block?.coalesce);
|
|
54
|
+
if (!streaming || !block || !coalesce) return {
|
|
55
|
+
entry: params.entry,
|
|
56
|
+
changed: false
|
|
57
|
+
};
|
|
58
|
+
const removed = LEGACY_COALESCE_FIELDS.filter((field) => coalesce[field] !== void 0);
|
|
59
|
+
if (removed.length === 0) return {
|
|
60
|
+
entry: params.entry,
|
|
61
|
+
changed: false
|
|
62
|
+
};
|
|
63
|
+
const nextCoalesce = { ...coalesce };
|
|
64
|
+
for (const field of removed) delete nextCoalesce[field];
|
|
65
|
+
params.changes.push(`Removed ${params.pathPrefix}.streaming.block.coalesce.{${removed.join(",")}} (legacy Feishu-only fields; block delivery reads minChars/maxChars/idleMs).`);
|
|
66
|
+
return {
|
|
67
|
+
entry: {
|
|
68
|
+
...params.entry,
|
|
69
|
+
streaming: {
|
|
70
|
+
...streaming,
|
|
71
|
+
block: {
|
|
72
|
+
...block,
|
|
73
|
+
coalesce: nextCoalesce
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
changed: true
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
function hasLegacyWebhookPath(value) {
|
|
81
|
+
const path = asObjectRecord(value)?.webhookPath;
|
|
82
|
+
return typeof path === "string" && normalizeFeishuWebhookPath(path) !== path;
|
|
83
|
+
}
|
|
84
|
+
function normalizeLegacyWebhookPath(params) {
|
|
85
|
+
const path = params.entry.webhookPath;
|
|
86
|
+
if (typeof path !== "string") return {
|
|
87
|
+
entry: params.entry,
|
|
88
|
+
changed: false
|
|
89
|
+
};
|
|
90
|
+
const normalized = normalizeFeishuWebhookPath(path);
|
|
91
|
+
const canonical = normalized ?? "/feishu/events";
|
|
92
|
+
if (canonical === path) return {
|
|
93
|
+
entry: params.entry,
|
|
94
|
+
changed: false
|
|
95
|
+
};
|
|
96
|
+
params.changes.push(normalized === null ? `Reset invalid ${params.pathPrefix}.webhookPath to ${DEFAULT_FEISHU_WEBHOOK_PATH}.` : `Normalized ${params.pathPrefix}.webhookPath to its HTTP request path.`);
|
|
97
|
+
return {
|
|
98
|
+
entry: {
|
|
99
|
+
...params.entry,
|
|
100
|
+
webhookPath: canonical
|
|
101
|
+
},
|
|
102
|
+
changed: true
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
function normalizeFeishuLegacyConfigEntries(cfg, changes) {
|
|
106
|
+
return normalizeChannelConfigEntries({
|
|
107
|
+
cfg,
|
|
108
|
+
channelId: "feishu",
|
|
109
|
+
changes,
|
|
110
|
+
normalizeEntry: (params) => {
|
|
111
|
+
const tools = toolsBaseMigration.normalize(params);
|
|
112
|
+
const coalesce = sanitizeLegacyCoalesceFields({
|
|
113
|
+
...params,
|
|
114
|
+
entry: tools.entry
|
|
115
|
+
});
|
|
116
|
+
const heartbeat = sanitizeLegacyHeartbeatFields({
|
|
117
|
+
...params,
|
|
118
|
+
entry: coalesce.entry
|
|
119
|
+
});
|
|
120
|
+
const webhook = normalizeLegacyWebhookPath({
|
|
121
|
+
...params,
|
|
122
|
+
entry: heartbeat.entry
|
|
123
|
+
});
|
|
124
|
+
return {
|
|
125
|
+
entry: webhook.entry,
|
|
126
|
+
changed: tools.changed || coalesce.changed || heartbeat.changed || webhook.changed
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
}).config;
|
|
130
|
+
}
|
|
131
|
+
const legacyConfigRules = [
|
|
132
|
+
...streamingAliasMigration.legacyConfigRules,
|
|
133
|
+
{
|
|
134
|
+
path: ["channels", "feishu"],
|
|
135
|
+
message: "channels.feishu[.accounts.<id>].webhookPath must be a canonical HTTP request path; run \"openclaw doctor --fix\".",
|
|
136
|
+
match: (value) => {
|
|
137
|
+
const entry = asObjectRecord(value);
|
|
138
|
+
return hasLegacyWebhookPath(entry) || hasLegacyAccountStreamingAliases(entry?.accounts, hasLegacyWebhookPath);
|
|
139
|
+
}
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
path: ["channels", "feishu"],
|
|
143
|
+
message: "channels.feishu[.accounts.<id>].tools.base is legacy; use tools.bitable. Run \"openclaw doctor --fix\".",
|
|
144
|
+
match: (value) => {
|
|
145
|
+
const entry = asObjectRecord(value);
|
|
146
|
+
return toolsBaseMigration.hasLegacy(entry) || hasLegacyAccountStreamingAliases(entry?.accounts, toolsBaseMigration.hasLegacy);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
];
|
|
150
|
+
function normalizeCompatibilityConfig({ cfg }) {
|
|
151
|
+
const aliases = streamingAliasMigration.normalizeChannelConfig({ cfg });
|
|
152
|
+
return {
|
|
153
|
+
config: normalizeFeishuLegacyConfigEntries(aliases.config, aliases.changes),
|
|
154
|
+
changes: aliases.changes
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
//#endregion
|
|
158
|
+
export { normalizeFeishuWebhookPath as i, normalizeCompatibilityConfig as n, DEFAULT_FEISHU_WEBHOOK_PATH as r, legacyConfigRules as t };
|