@openclaw/feishu 2026.7.2-beta.3 → 2026.7.2-beta.5

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 (159) hide show
  1. package/README.md +1 -1
  2. package/dist/{accounts-BDoGHJDk.js → accounts-CKhCa76b.js} +2 -19
  3. package/dist/api.js +65 -43
  4. package/dist/{app-registration-BzkyrVZu.js → app-registration-cN1bVV6s.js} +5 -5
  5. package/dist/{channel-BdnXYU6g.js → channel-CBNICmK9.js} +37 -75
  6. package/dist/channel-plugin-api.js +1 -1
  7. package/dist/{channel.runtime-CVIzo2dV.js → channel.runtime-CSlJVqy4.js} +7 -7
  8. package/dist/{client-87BmeMpj.js → client-Dee7cKsS.js} +62 -1
  9. package/dist/contract-api.js +2 -2
  10. package/dist/doctor-contract-BiD9tyIv.js +102 -0
  11. package/dist/doctor-contract-api.js +1 -1
  12. package/dist/{drive-BHv8WW9i.js → drive-DG6pKTPE.js} +23 -20
  13. package/dist/{send-DcrXbqqA.js → media-DOwcLJ1j.js} +1050 -1021
  14. package/dist/{monitor-BVQf7-Bl.js → monitor-DEHJlyWW.js} +6 -5
  15. package/dist/{monitor.account-Blbf2T6J.js → monitor.account-DEHl8Non.js} +1556 -592
  16. package/dist/monitor.startup-CSUPT_U1.js +143 -0
  17. package/dist/{probe-BgboTHIn.js → probe-Za1kgUvx.js} +70 -10
  18. package/dist/runtime-api.js +1 -2
  19. package/dist/{security-audit-BIeA3W3Q.js → security-audit-D7WK_BHh.js} +1 -1
  20. package/dist/{security-audit-shared-BIHeF-S_.js → security-audit-shared-BgpY7AiJ.js} +6 -11
  21. package/dist/security-contract-api.js +1 -1
  22. package/dist/{send-result-DfE5Fhz6.js → send-result-Bcofg0Vv.js} +1 -1
  23. package/dist/session-binding-contract-api.js +1 -1
  24. package/dist/setup-api.js +1 -1
  25. package/dist/{subagent-hooks-BKTOxB-T.js → subagent-hooks-DL2SC5zX.js} +1 -1
  26. package/dist/subagent-hooks-api.js +1 -1
  27. package/dist/{thread-bindings-V0bwk0A1.js → thread-bindings-Dqs_A0du.js} +2 -1
  28. package/node_modules/@larksuiteoapi/node-sdk/README.md +13 -0
  29. package/node_modules/@larksuiteoapi/node-sdk/README.zh.md +12 -0
  30. package/node_modules/@larksuiteoapi/node-sdk/es/index.js +8950 -3084
  31. package/node_modules/@larksuiteoapi/node-sdk/lib/index.js +8951 -3083
  32. package/node_modules/@larksuiteoapi/node-sdk/package.json +1 -1
  33. package/node_modules/@larksuiteoapi/node-sdk/types/index.d.ts +12522 -698
  34. package/node_modules/@protobufjs/utf8/CHANGELOG.md +8 -0
  35. package/node_modules/@protobufjs/utf8/index.js +29 -18
  36. package/node_modules/@protobufjs/utf8/package.json +2 -2
  37. package/node_modules/@protobufjs/utf8/tests/index.js +5 -0
  38. package/node_modules/@types/node/README.md +1 -1
  39. package/node_modules/@types/node/fs/promises.d.ts +16 -6
  40. package/node_modules/@types/node/package.json +2 -2
  41. package/node_modules/agent-base/README.md +145 -0
  42. package/node_modules/agent-base/dist/src/index.d.ts +78 -0
  43. package/node_modules/agent-base/dist/src/index.js +203 -0
  44. package/node_modules/agent-base/dist/src/index.js.map +1 -0
  45. package/node_modules/agent-base/dist/src/promisify.d.ts +4 -0
  46. package/node_modules/agent-base/dist/src/promisify.js +18 -0
  47. package/node_modules/agent-base/dist/src/promisify.js.map +1 -0
  48. package/node_modules/agent-base/package.json +64 -0
  49. package/node_modules/agent-base/src/index.ts +345 -0
  50. package/node_modules/agent-base/src/promisify.ts +33 -0
  51. package/node_modules/axios/CHANGELOG.md +197 -1
  52. package/node_modules/axios/README.md +424 -256
  53. package/node_modules/axios/dist/axios.js +589 -204
  54. package/node_modules/axios/dist/axios.min.js +3 -3
  55. package/node_modules/axios/dist/axios.min.js.map +1 -1
  56. package/node_modules/axios/dist/browser/axios.cjs +630 -185
  57. package/node_modules/axios/dist/esm/axios.js +630 -185
  58. package/node_modules/axios/dist/esm/axios.min.js +2 -2
  59. package/node_modules/axios/dist/esm/axios.min.js.map +1 -1
  60. package/node_modules/axios/dist/node/axios.cjs +949 -301
  61. package/node_modules/axios/index.d.cts +28 -5
  62. package/node_modules/axios/index.d.ts +24 -3
  63. package/node_modules/axios/lib/adapters/adapters.js +1 -1
  64. package/node_modules/axios/lib/adapters/fetch.js +223 -49
  65. package/node_modules/axios/lib/adapters/http.js +408 -193
  66. package/node_modules/axios/lib/adapters/xhr.js +3 -1
  67. package/node_modules/axios/lib/core/Axios.js +4 -2
  68. package/node_modules/axios/lib/core/AxiosError.js +13 -1
  69. package/node_modules/axios/lib/core/AxiosHeaders.js +13 -42
  70. package/node_modules/axios/lib/core/buildFullPath.js +29 -1
  71. package/node_modules/axios/lib/core/mergeConfig.js +35 -0
  72. package/node_modules/axios/lib/defaults/transitional.js +2 -0
  73. package/node_modules/axios/lib/env/data.js +1 -1
  74. package/node_modules/axios/lib/helpers/AxiosURLSearchParams.js +1 -3
  75. package/node_modules/axios/lib/helpers/Http2Sessions.js +119 -0
  76. package/node_modules/axios/lib/helpers/buildURL.js +7 -4
  77. package/node_modules/axios/lib/helpers/composeSignals.js +48 -47
  78. package/node_modules/axios/lib/helpers/cookies.js +5 -1
  79. package/node_modules/axios/lib/helpers/estimateDataURLDecodedBytes.js +16 -11
  80. package/node_modules/axios/lib/helpers/formDataToJSON.js +26 -4
  81. package/node_modules/axios/lib/helpers/formDataToStream.js +2 -2
  82. package/node_modules/axios/lib/helpers/fromDataURI.js +20 -5
  83. package/node_modules/axios/lib/helpers/progressEventReducer.js +3 -0
  84. package/node_modules/axios/lib/helpers/resolveConfig.js +26 -13
  85. package/node_modules/axios/lib/helpers/sanitizeHeaderValue.js +60 -0
  86. package/node_modules/axios/lib/helpers/shouldBypassProxy.js +33 -1
  87. package/node_modules/axios/lib/helpers/toFormData.js +48 -12
  88. package/node_modules/axios/lib/helpers/validator.js +1 -1
  89. package/node_modules/axios/lib/utils.js +105 -19
  90. package/node_modules/axios/package.json +31 -13
  91. package/node_modules/https-proxy-agent/README.md +137 -0
  92. package/node_modules/https-proxy-agent/dist/agent.d.ts +30 -0
  93. package/node_modules/https-proxy-agent/dist/agent.js +177 -0
  94. package/node_modules/https-proxy-agent/dist/agent.js.map +1 -0
  95. package/node_modules/https-proxy-agent/dist/index.d.ts +23 -0
  96. package/node_modules/https-proxy-agent/dist/index.js +14 -0
  97. package/node_modules/https-proxy-agent/dist/index.js.map +1 -0
  98. package/node_modules/https-proxy-agent/dist/parse-proxy-response.d.ts +7 -0
  99. package/node_modules/https-proxy-agent/dist/parse-proxy-response.js +66 -0
  100. package/node_modules/https-proxy-agent/dist/parse-proxy-response.js.map +1 -0
  101. package/node_modules/https-proxy-agent/package.json +56 -0
  102. package/node_modules/protobufjs/dist/light/protobuf.js +145 -188
  103. package/node_modules/protobufjs/dist/light/protobuf.js.map +1 -1
  104. package/node_modules/protobufjs/dist/light/protobuf.min.js +3 -3
  105. package/node_modules/protobufjs/dist/light/protobuf.min.js.map +1 -1
  106. package/node_modules/protobufjs/dist/minimal/protobuf.js +33 -76
  107. package/node_modules/protobufjs/dist/minimal/protobuf.js.map +1 -1
  108. package/node_modules/protobufjs/dist/minimal/protobuf.min.js +3 -3
  109. package/node_modules/protobufjs/dist/minimal/protobuf.min.js.map +1 -1
  110. package/node_modules/protobufjs/dist/protobuf.js +168 -208
  111. package/node_modules/protobufjs/dist/protobuf.js.map +1 -1
  112. package/node_modules/protobufjs/dist/protobuf.min.js +3 -3
  113. package/node_modules/protobufjs/dist/protobuf.min.js.map +1 -1
  114. package/node_modules/protobufjs/index.d.ts +0 -8
  115. package/node_modules/protobufjs/package.json +2 -3
  116. package/node_modules/protobufjs/src/parse.js +3 -0
  117. package/node_modules/protobufjs/src/util/minimal.js +0 -3
  118. package/node_modules/qs/CHANGELOG.md +11 -0
  119. package/node_modules/qs/dist/qs.js +17 -17
  120. package/node_modules/qs/lib/parse.js +19 -8
  121. package/node_modules/qs/lib/utils.js +47 -8
  122. package/node_modules/qs/package.json +6 -5
  123. package/node_modules/qs/test/parse.js +230 -0
  124. package/node_modules/qs/test/utils.js +194 -0
  125. package/node_modules/typebox/build/compile/validator.d.mts +1 -4
  126. package/node_modules/typebox/build/guard/guard.d.mts +1 -1
  127. package/node_modules/typebox/build/guard/guard.mjs +5 -2
  128. package/node_modules/typebox/build/guard/string.mjs +16 -4
  129. package/node_modules/typebox/build/schema/engine/_functions.mjs +34 -15
  130. package/node_modules/typebox/build/type/action/readonly_object.d.mts +5 -0
  131. package/node_modules/typebox/build/type/action/readonly_object.mjs +8 -0
  132. package/node_modules/typebox/build/typebox.d.mts +1 -1
  133. package/node_modules/typebox/build/typebox.mjs +1 -1
  134. package/node_modules/typebox/package.json +1 -1
  135. package/node_modules/typebox/readme.md +29 -32
  136. package/node_modules/ws/lib/receiver.js +15 -32
  137. package/node_modules/ws/lib/websocket-server.js +4 -4
  138. package/node_modules/ws/lib/websocket.js +4 -4
  139. package/node_modules/ws/package.json +5 -1
  140. package/openclaw.plugin.json +2 -16
  141. package/package.json +20 -8
  142. package/dist/doctor-contract-DXH5hux1.js +0 -97
  143. package/dist/monitor.startup-Cy8NPGAX.js +0 -43
  144. package/node_modules/@protobufjs/inquire/CHANGELOG.md +0 -8
  145. package/node_modules/@protobufjs/inquire/LICENSE +0 -26
  146. package/node_modules/@protobufjs/inquire/README.md +0 -13
  147. package/node_modules/@protobufjs/inquire/index.d.ts +0 -10
  148. package/node_modules/@protobufjs/inquire/index.js +0 -38
  149. package/node_modules/@protobufjs/inquire/package.json +0 -21
  150. package/node_modules/@protobufjs/inquire/tests/data/array.js +0 -1
  151. package/node_modules/@protobufjs/inquire/tests/data/emptyArray.js +0 -1
  152. package/node_modules/@protobufjs/inquire/tests/data/emptyObject.js +0 -1
  153. package/node_modules/@protobufjs/inquire/tests/data/object.js +0 -1
  154. package/node_modules/@protobufjs/inquire/tests/index.js +0 -20
  155. package/node_modules/axios/dist/axios.js.map +0 -1
  156. package/node_modules/axios/dist/browser/axios.cjs.map +0 -1
  157. package/node_modules/axios/dist/esm/axios.js.map +0 -1
  158. package/node_modules/axios/dist/node/axios.cjs.map +0 -1
  159. package/npm-shrinkwrap.json +0 -1354
@@ -0,0 +1,143 @@
1
+ import { t as getFeishuRuntime } from "./runtime-C5JxBWZp.js";
2
+ import { r as registerFeishuAiAgent, t as probeFeishu } from "./probe-Za1kgUvx.js";
3
+ import { parseStrictPositiveInteger } from "openclaw/plugin-sdk/number-runtime";
4
+ import { normalizeLowercaseStringOrEmpty, normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
5
+ import { normalizeAccountId } from "openclaw/plugin-sdk/account-resolution";
6
+ //#region extensions/feishu/src/bot-identity-cache.ts
7
+ const FEISHU_BOT_IDENTITY_CACHE_NAMESPACE = "feishu.bot-identity-cache";
8
+ const FEISHU_BOT_IDENTITY_CACHE_MAX_ENTRIES = 128;
9
+ function openFeishuBotIdentityCache() {
10
+ return getFeishuRuntime().state.openKeyedStore({
11
+ namespace: FEISHU_BOT_IDENTITY_CACHE_NAMESPACE,
12
+ maxEntries: FEISHU_BOT_IDENTITY_CACHE_MAX_ENTRIES
13
+ });
14
+ }
15
+ function parseCachedFeishuBotIdentity(value) {
16
+ if (!value || typeof value !== "object") return null;
17
+ const state = value;
18
+ const appId = normalizeOptionalString(state.appId);
19
+ const botOpenId = normalizeOptionalString(state.botOpenId);
20
+ const botName = normalizeOptionalString(state.botName);
21
+ const fetchedAt = normalizeOptionalString(state.fetchedAt);
22
+ if (!appId || !botOpenId || !fetchedAt || Number.isNaN(Date.parse(fetchedAt))) return null;
23
+ return {
24
+ appId,
25
+ botOpenId,
26
+ botName,
27
+ fetchedAt
28
+ };
29
+ }
30
+ async function readCachedFeishuBotIdentity(params) {
31
+ const appId = normalizeOptionalString(params.appId);
32
+ if (!appId) return null;
33
+ const cached = parseCachedFeishuBotIdentity(await openFeishuBotIdentityCache().lookup(normalizeAccountId(params.accountId)));
34
+ if (!cached || cached.appId !== appId) return null;
35
+ return {
36
+ botOpenId: cached.botOpenId,
37
+ botName: cached.botName,
38
+ fetchedAt: cached.fetchedAt
39
+ };
40
+ }
41
+ async function writeCachedFeishuBotIdentity(params) {
42
+ const appId = normalizeOptionalString(params.appId);
43
+ const botOpenId = normalizeOptionalString(params.botOpenId);
44
+ if (!appId || !botOpenId) return;
45
+ const botName = normalizeOptionalString(params.botName);
46
+ await openFeishuBotIdentityCache().register(normalizeAccountId(params.accountId), {
47
+ appId,
48
+ botOpenId,
49
+ botName,
50
+ fetchedAt: (/* @__PURE__ */ new Date()).toISOString()
51
+ });
52
+ }
53
+ //#endregion
54
+ //#region extensions/feishu/src/monitor-startup-timeout.ts
55
+ const FEISHU_STARTUP_BOT_INFO_TIMEOUT_DEFAULT_MS = 3e4;
56
+ const FEISHU_STARTUP_BOT_INFO_TIMEOUT_ENV = "OPENCLAW_FEISHU_STARTUP_PROBE_TIMEOUT_MS";
57
+ function resolveStartupProbeTimeoutMs(env = process.env) {
58
+ const raw = env[FEISHU_STARTUP_BOT_INFO_TIMEOUT_ENV];
59
+ if (raw) {
60
+ const parsed = parseStrictPositiveInteger(raw);
61
+ if (parsed !== void 0) return parsed;
62
+ console.warn(`[feishu] ${FEISHU_STARTUP_BOT_INFO_TIMEOUT_ENV}="${raw}" is invalid; using default ${FEISHU_STARTUP_BOT_INFO_TIMEOUT_DEFAULT_MS}ms`);
63
+ }
64
+ return FEISHU_STARTUP_BOT_INFO_TIMEOUT_DEFAULT_MS;
65
+ }
66
+ //#endregion
67
+ //#region extensions/feishu/src/monitor.startup.ts
68
+ const FEISHU_STARTUP_BOT_INFO_TIMEOUT_MS = resolveStartupProbeTimeoutMs();
69
+ function isTimeoutErrorMessage(message) {
70
+ const lower = normalizeLowercaseStringOrEmpty(message);
71
+ return lower.includes("timeout") || lower.includes("timed out");
72
+ }
73
+ function isAbortErrorMessage(message) {
74
+ return normalizeLowercaseStringOrEmpty(message).includes("aborted");
75
+ }
76
+ async function writeProviderBotIdentityCache(params) {
77
+ try {
78
+ await writeCachedFeishuBotIdentity({
79
+ accountId: params.account.accountId,
80
+ appId: params.account.appId,
81
+ botOpenId: params.botOpenId,
82
+ botName: params.botName
83
+ });
84
+ } catch {
85
+ params.runtime?.log?.(`feishu[${params.account.accountId}]: bot identity cache write failed; continuing startup`);
86
+ }
87
+ }
88
+ async function readProviderBotIdentityCache(params) {
89
+ try {
90
+ const cached = await readCachedFeishuBotIdentity({
91
+ accountId: params.account.accountId,
92
+ appId: params.account.appId
93
+ });
94
+ if (!cached) return {};
95
+ params.runtime?.log?.(`feishu[${params.account.accountId}]: using cached provider-verified bot identity while the fresh probe is unavailable`);
96
+ return {
97
+ botOpenId: cached.botOpenId,
98
+ botName: cached.botName,
99
+ source: "cache"
100
+ };
101
+ } catch {
102
+ params.runtime?.log?.(`feishu[${params.account.accountId}]: bot identity cache read failed; continuing without cached identity`);
103
+ return {};
104
+ }
105
+ }
106
+ async function fetchBotIdentityForMonitor(account, options = {}) {
107
+ if (options.abortSignal?.aborted) return {};
108
+ const timeoutMs = options.timeoutMs ?? FEISHU_STARTUP_BOT_INFO_TIMEOUT_MS;
109
+ const result = await probeFeishu(account, {
110
+ timeoutMs,
111
+ abortSignal: options.abortSignal
112
+ });
113
+ const resultAppId = normalizeOptionalString(result.appId);
114
+ if (result.ok && resultAppId === account.appId) {
115
+ registerFeishuAiAgent(account, { abortSignal: options.abortSignal }).then((registration) => {
116
+ if (!registration.ok && registration.reason !== "aborted") (options.runtime?.log ?? console.log)(`feishu[${account.accountId}]: AI-agent registration unavailable (${registration.reason}); continuing with standard bot identity`);
117
+ }).catch(() => {
118
+ (options.runtime?.log ?? console.log)(`feishu[${account.accountId}]: AI-agent registration failed unexpectedly; continuing with standard bot identity`);
119
+ });
120
+ await writeProviderBotIdentityCache({
121
+ account,
122
+ botOpenId: result.botOpenId,
123
+ botName: result.botName,
124
+ runtime: options.runtime
125
+ });
126
+ return {
127
+ botOpenId: normalizeOptionalString(result.botOpenId),
128
+ botName: normalizeOptionalString(result.botName),
129
+ source: "provider"
130
+ };
131
+ }
132
+ if (result.ok) (options.runtime?.log ?? console.log)(`feishu[${account.accountId}]: bot info probe returned identity for a different app; ignoring stale result`);
133
+ const probeError = result.error ?? void 0;
134
+ if (options.abortSignal?.aborted || isAbortErrorMessage(probeError)) return {};
135
+ if (isTimeoutErrorMessage(probeError)) (options.runtime?.error ?? console.error)(`feishu[${account.accountId}]: bot info probe timed out after ${timeoutMs}ms; continuing startup`);
136
+ if (options.allowCachedFallback === false) return {};
137
+ return readProviderBotIdentityCache({
138
+ account,
139
+ runtime: options.runtime
140
+ });
141
+ }
142
+ //#endregion
143
+ export { fetchBotIdentityForMonitor as t };
@@ -1,7 +1,8 @@
1
1
  import { t as __exportAll } from "./rolldown-runtime-8H4AJuhK.js";
2
- import { r as createFeishuClient } from "./client-87BmeMpj.js";
2
+ import { r as createFeishuClient } from "./client-Dee7cKsS.js";
3
3
  import { asDateTimestampMs, resolveExpiresAtMsFromDurationMs, resolveTimerTimeoutMs } from "openclaw/plugin-sdk/number-runtime";
4
4
  import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
5
+ import { createHash } from "node:crypto";
5
6
  //#region extensions/feishu/src/async.ts
6
7
  const RACE_TIMEOUT = Symbol("race-timeout");
7
8
  const RACE_ABORT = Symbol("race-abort");
@@ -63,7 +64,10 @@ function waitForAbortableDelay(delayMs, abortSignal) {
63
64
  }
64
65
  //#endregion
65
66
  //#region extensions/feishu/src/probe.ts
66
- var probe_exports = /* @__PURE__ */ __exportAll({ probeFeishu: () => probeFeishu });
67
+ var probe_exports = /* @__PURE__ */ __exportAll({
68
+ probeFeishu: () => probeFeishu,
69
+ registerFeishuAiAgent: () => registerFeishuAiAgent
70
+ });
67
71
  /** Cache probe results to reduce repeated health-check calls.
68
72
  * Gateway health checks call probeFeishu() every minute; without caching this
69
73
  * burns ~43,200 calls/month, easily exceeding Feishu's free-tier quota.
@@ -74,6 +78,15 @@ const PROBE_SUCCESS_TTL_MS = 600 * 1e3;
74
78
  const PROBE_ERROR_TTL_MS = 60 * 1e3;
75
79
  const MAX_PROBE_CACHE_SIZE = 64;
76
80
  const FEISHU_PROBE_REQUEST_TIMEOUT_MS = 1e4;
81
+ function buildProbeCacheKey(creds) {
82
+ const identity = [
83
+ creds.accountId ?? null,
84
+ creds.appId,
85
+ creds.appSecret,
86
+ creds.domain ?? null
87
+ ];
88
+ return createHash("sha256").update(JSON.stringify(identity)).digest("hex");
89
+ }
77
90
  function setCachedProbeResult(cacheKey, result, ttlMs) {
78
91
  const expiresAt = resolveExpiresAtMsFromDurationMs(ttlMs);
79
92
  if (expiresAt === void 0) {
@@ -101,7 +114,7 @@ async function probeFeishu(creds, options = {}) {
101
114
  error: "probe aborted"
102
115
  };
103
116
  const timeoutMs = options.timeoutMs ?? FEISHU_PROBE_REQUEST_TIMEOUT_MS;
104
- const cacheKey = creds.accountId ?? `${creds.appId}:${creds.appSecret.slice(0, 8)}`;
117
+ const cacheKey = buildProbeCacheKey(creds);
105
118
  const cached = probeCache.get(cacheKey);
106
119
  if (cached) {
107
120
  const now = asDateTimestampMs(Date.now());
@@ -111,9 +124,8 @@ async function probeFeishu(creds, options = {}) {
111
124
  }
112
125
  try {
113
126
  const responseResult = await raceWithTimeoutAndAbort(createFeishuClient(creds).request({
114
- method: "POST",
115
- url: "/open-apis/bot/v1/openclaw_bot/ping",
116
- data: { needBotInfo: true },
127
+ method: "GET",
128
+ url: "/open-apis/bot/v3/info",
117
129
  timeout: timeoutMs
118
130
  }), {
119
131
  timeoutMs,
@@ -140,12 +152,17 @@ async function probeFeishu(creds, options = {}) {
140
152
  appId: creds.appId,
141
153
  error: `API error: ${response.msg || `code ${response.code}`}`
142
154
  }, PROBE_ERROR_TTL_MS);
143
- const botInfo = response.data?.pingBotInfo;
155
+ const botInfo = response.bot ?? response.data?.bot;
156
+ if (!botInfo?.open_id) return setCachedProbeResult(cacheKey, {
157
+ ok: false,
158
+ appId: creds.appId,
159
+ error: "API response missing bot open_id"
160
+ }, PROBE_ERROR_TTL_MS);
144
161
  return setCachedProbeResult(cacheKey, {
145
162
  ok: true,
146
163
  appId: creds.appId,
147
- botName: botInfo?.botName,
148
- botOpenId: botInfo?.botID
164
+ botName: botInfo.app_name,
165
+ botOpenId: botInfo.open_id
149
166
  }, PROBE_SUCCESS_TTL_MS);
150
167
  } catch (err) {
151
168
  return setCachedProbeResult(cacheKey, {
@@ -155,5 +172,48 @@ async function probeFeishu(creds, options = {}) {
155
172
  }, PROBE_ERROR_TTL_MS);
156
173
  }
157
174
  }
175
+ /**
176
+ * Preserve Feishu's optional AI-agent registration without coupling it to health or
177
+ * identity. Monitor startup calls this once per account and never awaits it.
178
+ */
179
+ async function registerFeishuAiAgent(creds, options = {}) {
180
+ if (!creds?.appId || !creds?.appSecret) return {
181
+ ok: false,
182
+ reason: "missing-credentials"
183
+ };
184
+ if (options.abortSignal?.aborted) return {
185
+ ok: false,
186
+ reason: "aborted"
187
+ };
188
+ const timeoutMs = options.timeoutMs ?? FEISHU_PROBE_REQUEST_TIMEOUT_MS;
189
+ try {
190
+ const responseResult = await raceWithTimeoutAndAbort(createFeishuClient(creds).request({
191
+ method: "POST",
192
+ url: "/open-apis/bot/v1/openclaw_bot/ping",
193
+ data: { needBotInfo: true },
194
+ timeout: timeoutMs
195
+ }), {
196
+ timeoutMs,
197
+ abortSignal: options.abortSignal
198
+ });
199
+ if (responseResult.status === "aborted" || options.abortSignal?.aborted) return {
200
+ ok: false,
201
+ reason: "aborted"
202
+ };
203
+ if (responseResult.status === "timeout") return {
204
+ ok: false,
205
+ reason: "timeout"
206
+ };
207
+ return responseResult.value.code === 0 ? { ok: true } : {
208
+ ok: false,
209
+ reason: "api-error"
210
+ };
211
+ } catch {
212
+ return {
213
+ ok: false,
214
+ reason: "request-error"
215
+ };
216
+ }
217
+ }
158
218
  //#endregion
159
- export { waitForAbortableDelay as i, probe_exports as n, raceWithTimeoutAndAbort as r, probeFeishu as t };
219
+ export { waitForAbortableDelay as a, raceWithTimeoutAndAbort as i, probe_exports as n, registerFeishuAiAgent as r, probeFeishu as t };
@@ -6,8 +6,7 @@ import { PAIRING_APPROVED_MESSAGE, buildProbeChannelStatusSummary, createDefault
6
6
  import { normalizeAgentId } from "openclaw/plugin-sdk/routing";
7
7
  import { getSessionEntry } from "openclaw/plugin-sdk/session-store-runtime";
8
8
  import { DEFAULT_ACCOUNT_ID, buildChannelConfigSchema, createActionGate, createDedupeCache } from "openclaw/plugin-sdk/core";
9
- import { buildAgentMediaPayload } from "openclaw/plugin-sdk/agent-media-payload";
10
9
  import { evaluateSupplementalContextVisibility, filterSupplementalContextItems, resolveChannelContextVisibilityMode } from "openclaw/plugin-sdk/context-visibility-runtime";
11
10
  import { readJsonFileWithFallback } from "openclaw/plugin-sdk/json-store";
12
11
  import { isRequestBodyLimitError, readRequestBodyWithLimit, requestBodyErrorToText } from "openclaw/plugin-sdk/webhook-ingress";
13
- export { DEFAULT_ACCOUNT_ID, PAIRING_APPROVED_MESSAGE, buildAgentMediaPayload, buildChannelConfigSchema, buildProbeChannelStatusSummary, chunkTextForOutbound, createActionGate, createChannelPairingController, createDedupeCache, createDefaultChannelRuntimeState, createReplyPrefixContext, evaluateSupplementalContextVisibility, filterSupplementalContextItems, getSessionEntry, isRequestBodyLimitError, normalizeAgentId, readJsonFileWithFallback, readRequestBodyWithLimit, requestBodyErrorToText, resolveChannelContextVisibilityMode, setFeishuRuntime };
12
+ export { DEFAULT_ACCOUNT_ID, PAIRING_APPROVED_MESSAGE, buildChannelConfigSchema, buildProbeChannelStatusSummary, chunkTextForOutbound, createActionGate, createChannelPairingController, createDedupeCache, createDefaultChannelRuntimeState, createReplyPrefixContext, evaluateSupplementalContextVisibility, filterSupplementalContextItems, getSessionEntry, isRequestBodyLimitError, normalizeAgentId, readJsonFileWithFallback, readRequestBodyWithLimit, requestBodyErrorToText, resolveChannelContextVisibilityMode, setFeishuRuntime };
@@ -1,4 +1,4 @@
1
- import "./security-audit-shared-BIHeF-S_.js";
1
+ import "./security-audit-shared-BgpY7AiJ.js";
2
2
  //#region extensions/feishu/src/message-action-contract.ts
3
3
  const messageActionTargetAliases = {
4
4
  read: { aliases: ["messageId"] },
@@ -1,25 +1,20 @@
1
+ import { asOptionalRecord, hasNonEmptyString } from "openclaw/plugin-sdk/string-coerce-runtime";
1
2
  import { hasConfiguredSecretInput } from "openclaw/plugin-sdk/secret-input";
2
3
  //#region extensions/feishu/src/security-audit-shared.ts
3
- function asRecord(value) {
4
- return value && typeof value === "object" && !Array.isArray(value) ? value : void 0;
5
- }
6
- function hasNonEmptyString(value) {
7
- return typeof value === "string" && value.trim().length > 0;
8
- }
9
4
  function isFeishuDocToolEnabled(cfg) {
10
- const feishu = asRecord(asRecord(cfg.channels)?.feishu);
5
+ const feishu = asOptionalRecord(asOptionalRecord(cfg.channels)?.feishu);
11
6
  if (!feishu || feishu.enabled === false) return false;
12
- const baseTools = asRecord(feishu.tools);
7
+ const baseTools = asOptionalRecord(feishu.tools);
13
8
  const baseDocEnabled = baseTools?.doc !== false;
14
9
  const baseAppId = hasNonEmptyString(feishu.appId);
15
10
  const baseAppSecret = hasConfiguredSecretInput(feishu.appSecret, cfg.secrets?.defaults);
16
11
  const baseConfigured = baseAppId && baseAppSecret;
17
- const accounts = asRecord(feishu.accounts);
12
+ const accounts = asOptionalRecord(feishu.accounts);
18
13
  if (!accounts || Object.keys(accounts).length === 0) return baseDocEnabled && baseConfigured;
19
14
  for (const accountValue of Object.values(accounts)) {
20
- const account = asRecord(accountValue) ?? {};
15
+ const account = asOptionalRecord(accountValue) ?? {};
21
16
  if (account.enabled === false) continue;
22
- if (!((asRecord(account.tools) ?? baseTools)?.doc !== false)) continue;
17
+ if (!((asOptionalRecord(account.tools) ?? baseTools)?.doc !== false)) continue;
23
18
  if ((hasNonEmptyString(account.appId) || baseAppId) && (hasConfiguredSecretInput(account.appSecret, cfg.secrets?.defaults) || baseAppSecret)) return true;
24
19
  }
25
20
  return false;
@@ -1,2 +1,2 @@
1
- import { t as collectFeishuSecurityAuditFindings } from "./security-audit-shared-BIHeF-S_.js";
1
+ import { t as collectFeishuSecurityAuditFindings } from "./security-audit-shared-BgpY7AiJ.js";
2
2
  export { collectFeishuSecurityAuditFindings };
@@ -1,4 +1,4 @@
1
- import { d as isRecord$1 } from "./accounts-BDoGHJDk.js";
1
+ import { d as isRecord$1 } from "./accounts-CKhCa76b.js";
2
2
  import { r as normalizeFeishuTarget, t as detectIdType } from "./targets-BUjQ1TcA.js";
3
3
  import { compileAllowlist, resolveAllowlistMatchByCandidates } from "openclaw/plugin-sdk/allow-from";
4
4
  import { ToolAuthorizationError } from "openclaw/plugin-sdk/channel-actions";
@@ -1,2 +1,2 @@
1
- import { r as testing, t as createFeishuThreadBindingManager } from "./thread-bindings-V0bwk0A1.js";
1
+ import { r as testing, t as createFeishuThreadBindingManager } from "./thread-bindings-Dqs_A0du.js";
2
2
  export { createFeishuThreadBindingManager, testing as feishuThreadBindingTesting };
package/dist/setup-api.js CHANGED
@@ -1,2 +1,2 @@
1
- import { i as feishuSetupAdapter, n as feishuSetupWizard, t as feishuPlugin } from "./channel-BdnXYU6g.js";
1
+ import { i as feishuSetupAdapter, n as feishuSetupWizard, t as feishuPlugin } from "./channel-CBNICmK9.js";
2
2
  export { feishuPlugin, feishuSetupAdapter, feishuSetupWizard };
@@ -1,7 +1,7 @@
1
1
  import { t as __exportAll } from "./rolldown-runtime-8H4AJuhK.js";
2
2
  import { r as normalizeFeishuTarget } from "./targets-BUjQ1TcA.js";
3
3
  import { r as parseFeishuConversationId, t as buildFeishuConversationId } from "./conversation-id-BeJL-wq7.js";
4
- import { n as getFeishuThreadBindingManager } from "./thread-bindings-V0bwk0A1.js";
4
+ import { n as getFeishuThreadBindingManager } from "./thread-bindings-Dqs_A0du.js";
5
5
  import { normalizeOptionalLowercaseString, normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
6
6
  //#region extensions/feishu/src/subagent-hooks.ts
7
7
  var subagent_hooks_exports = /* @__PURE__ */ __exportAll({
@@ -1,6 +1,6 @@
1
1
  import { createLazyRuntimeModule } from "openclaw/plugin-sdk/lazy-runtime";
2
2
  //#region extensions/feishu/subagent-hooks-api.ts
3
- const loadFeishuSubagentHooksModule = createLazyRuntimeModule(() => import("./subagent-hooks-BKTOxB-T.js").then((n) => n.i));
3
+ const loadFeishuSubagentHooksModule = createLazyRuntimeModule(() => import("./subagent-hooks-DL2SC5zX.js").then((n) => n.i));
4
4
  function registerFeishuSubagentHooks(api) {
5
5
  api.on("subagent_delivery_target", async (event) => {
6
6
  const { handleFeishuSubagentDeliveryTarget } = await loadFeishuSubagentHooksModule();
@@ -1,6 +1,7 @@
1
1
  import { registerSessionBindingAdapter, resolveThreadBindingConversationIdFromBindingId, resolveThreadBindingIdleTimeoutMsForChannel, resolveThreadBindingMaxAgeMsForChannel, unregisterSessionBindingAdapter } from "openclaw/plugin-sdk/conversation-runtime";
2
2
  import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
3
3
  import { normalizeAccountId, resolveAgentIdFromSessionKey } from "openclaw/plugin-sdk/routing";
4
+ import { resolveDefaultAgentId } from "openclaw/plugin-sdk/agent-runtime";
4
5
  //#region extensions/feishu/src/thread-bindings.ts
5
6
  const FEISHU_THREAD_BINDINGS_STATE_KEY = Symbol.for("openclaw.feishuThreadBindingsState");
6
7
  let state;
@@ -94,7 +95,7 @@ function createFeishuThreadBindingManager(params) {
94
95
  deliveryThreadId: typeof metadata?.deliveryThreadId === "string" && metadata.deliveryThreadId.trim() ? metadata.deliveryThreadId.trim() : existingLocal?.deliveryThreadId,
95
96
  targetKind: toFeishuTargetKind(targetKind),
96
97
  targetSessionKey: normalizedTargetSessionKey,
97
- agentId: typeof metadata?.agentId === "string" && metadata.agentId.trim() ? metadata.agentId.trim() : existingLocal?.agentId ?? resolveAgentIdFromSessionKey(normalizedTargetSessionKey),
98
+ agentId: typeof metadata?.agentId === "string" && metadata.agentId.trim() ? metadata.agentId.trim() : existingLocal?.agentId ?? resolveAgentIdFromSessionKey(normalizedTargetSessionKey, resolveDefaultAgentId(params.cfg)),
98
99
  label: typeof metadata?.label === "string" && metadata.label.trim() ? metadata.label.trim() : existingLocal?.label,
99
100
  boundBy: typeof metadata?.boundBy === "string" && metadata.boundBy.trim() ? metadata.boundBy.trim() : existingLocal?.boundBy,
100
101
  boundAt: now,
@@ -705,10 +705,22 @@ await lark.registerApp({
705
705
  addons: { scopes: { tenant: ['drive:drive.metadata:readonly'] } },
706
706
  onQRCodeReady(info) { /* ... */ },
707
707
  });
708
+
709
+ // Minimal base: drop the default template (bot capability only, no business
710
+ // scopes) and show only the explicitly declared items. With `preset: false`
711
+ // an otherwise-empty addons is valid.
712
+ await lark.registerApp({
713
+ addons: {
714
+ preset: false,
715
+ scopes: { tenant: ['im:message:send_as_bot'] },
716
+ },
717
+ onQRCodeReady(info) { /* ... */ },
718
+ });
708
719
  ```
709
720
 
710
721
  Notes:
711
722
 
723
+ - `addons.preset` selects the template base: `true` / omitted keeps the platform default template and layers the declared items on top (additive — the default behavior); `false` drops the default template and starts from the minimal base (bot capability only, no business scopes), showing only the explicitly declared items. Only with `preset: false` may `addons` be otherwise empty (minimal base, zero increments); otherwise at least one scope, event or callback is required.
712
724
  - `addons` is **additive only**: items are merged on top of the base template; base permissions can never be removed.
713
725
  - Only the 5 public config types (tenant/user scopes, tenant/user events, callbacks) are supported. Sensitive config (event subscription type and request URLs, `security.*`, encrypt keys, etc.) cannot travel via `addons` — use the [update application config OpenAPI](https://open.feishu.cn/document/uAjLw4CM/ukTMukTMukTM/application-v7/application-v7/application-config/patch) instead.
714
726
  - The SDK only validates the shape, not the item names; names unknown to the platform catalog are silently ignored by the confirm page.
@@ -728,6 +740,7 @@ Notes:
728
740
  | appPreset.name | App name. Supports the `{user}` placeholder (replaced with the scanning user's name) | string | No | - |
729
741
  | appPreset.desc | App description. Supports the `{user}` placeholder | string | No | - |
730
742
  | addons | Incremental scopes/events/callbacks pre-filled into the confirm page, effective after user confirmation. See "Custom scopes/events/callbacks" above | AppAddons | No | - |
743
+ | addons.preset | Template base selector. `true`/omitted: keep the platform default template and layer the declared items on top; `false`: drop the default template and use the minimal base (bot capability only, no business scopes). With `false`, an otherwise-empty `addons` is valid | boolean | No | `true` |
731
744
  | addons.scopes.tenant | App-identity (tenant) scopes, e.g. `im:message:send_as_bot` | string[] | No | - |
732
745
  | addons.scopes.user | User-identity scopes, e.g. `calendar:calendar:read` | string[] | No | - |
733
746
  | addons.events.items.tenant | App-identity events, e.g. `im.message.receive_v1` | string[] | No | - |
@@ -765,10 +765,21 @@ await lark.registerApp({
765
765
  addons: { scopes: { tenant: ['drive:drive.metadata:readonly'] } },
766
766
  onQRCodeReady(info) { /* ... */ },
767
767
  });
768
+
769
+ // 最小基座:丢弃默认模板(仅保留机器人能力,无业务权限),仅展示显式声明的配置项。
770
+ // 传入 `preset: false` 时,即使 addons 没有其他配置项也是合法的。
771
+ await lark.registerApp({
772
+ addons: {
773
+ preset: false,
774
+ scopes: { tenant: ['im:message:send_as_bot'] },
775
+ },
776
+ onQRCodeReady(info) { /* ... */ },
777
+ });
768
778
  ```
769
779
 
770
780
  注意:
771
781
 
782
+ - `addons.preset` 用于选择模板基座:`true` / 不传表示保留平台默认模板,并在其上叠加声明的配置项(增量,默认行为);`false` 表示丢弃默认模板,从最小基座(仅机器人能力,无业务权限)开始,仅展示显式声明的配置项。仅当 `preset: false` 时 `addons` 可以不含其他配置项(最小基座、零增量),否则至少需包含一个权限、事件或回调。
772
783
  - `addons` 仅支持在基础模板上**增量叠加**,不支持删减基础权限。
773
784
  - 仅支持 5 类公开配置(应用/用户身份权限、应用/用户身份事件、回调)。敏感配置(事件订阅方式与回调地址、`security.*`、加密 key 等)不能通过 `addons` 传入,需调用[更新应用开发配置 OpenAPI](https://open.feishu.cn/document/uAjLw4CM/ukTMukTMukTM/application-v7/application-v7/application-config/patch)。
774
785
  - SDK 只校验数据形状,不校验权限点/事件/回调名称是否存在;平台目录中不存在的名称会被确认页忽略。
@@ -788,6 +799,7 @@ await lark.registerApp({
788
799
  | appPreset.name | 应用名称,支持 `{user}` 占位符(替换为扫码用户名称) | string | 否 | - |
789
800
  | appPreset.desc | 应用描述,支持 `{user}` 占位符 | string | 否 | - |
790
801
  | addons | 增量权限/事件/回调配置,预填到扫码后的确认页,用户确认后生效。详见上方「自定义权限/事件/回调」 | AppAddons | 否 | - |
802
+ | addons.preset | 模板基座选择。`true`/不传:保留平台默认模板,在其上叠加声明的配置项;`false`:丢弃默认模板,使用最小基座(仅机器人能力,无业务权限)。传 `false` 时 `addons` 可不含其他配置项 | boolean | 否 | `true` |
791
803
  | addons.scopes.tenant | 应用身份权限列表,如 `im:message:send_as_bot` | string[] | 否 | - |
792
804
  | addons.scopes.user | 用户身份权限列表,如 `calendar:calendar:read` | string[] | 否 | - |
793
805
  | addons.events.items.tenant | 应用身份事件列表,如 `im.message.receive_v1` | string[] | 否 | - |