@openclaw/feishu 2026.9.3 → 2026.9.4

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/api.js CHANGED
@@ -1,9 +1,9 @@
1
- import { a as setFeishuNamedAccountEnabled, i as feishuSetupAdapter, n as feishuSetupWizard, r as runFeishuLogin, t as feishuPlugin } from "./channel-DrAqd5ED.js";
2
- import { G as feishuExternalToolResult, J as createFeishuToolClient, K as toolExecutionErrorResult, W as registerFeishuDriveTools, X as resolveFeishuToolAccount, Y as resolveAnyEnabledFeishuToolsConfig, ft as parseFeishuMarkdown, lt as chunkFeishuMarkdown, q as unknownToolActionResult } from "./reply-delivery-result-BXEmtKpf.js";
1
+ import { a as setFeishuNamedAccountEnabled, i as feishuSetupAdapter, n as feishuSetupWizard, r as runFeishuLogin, t as feishuPlugin } from "./channel-HDnQAH4Z.js";
2
+ import { G as feishuExternalToolResult, J as createFeishuToolClient, K as toolExecutionErrorResult, W as registerFeishuDriveTools, X as resolveFeishuToolAccount, Y as resolveAnyEnabledFeishuToolsConfig, ft as parseFeishuMarkdown, lt as chunkFeishuMarkdown, q as unknownToolActionResult } from "./reply-delivery-result-C3smdVzb.js";
3
3
  import { a as parseFeishuTargetId, i as parseFeishuDirectConversationId, n as buildFeishuModelOverrideParentCandidates, r as parseFeishuConversationId, t as buildFeishuConversationId } from "./conversation-id-VYgGQ-GX.js";
4
- import { s as resolveConfiguredHttpTimeoutMs } from "./client-DMbIL3UH.js";
4
+ import { r as createFeishuClient, s as resolveConfiguredHttpTimeoutMs } from "./client-DMbIL3UH.js";
5
5
  import { t as getFeishuRuntime } from "./runtime-C5JxBWZp.js";
6
- import { o as registerFeishuChatTools } from "./chat-BZSnEtgb.js";
6
+ import { o as registerFeishuChatTools } from "./chat-zhIPXu4X.js";
7
7
  import { n as getFeishuThreadBindingManager, t as createFeishuThreadBindingManager } from "./thread-bindings-BiL1wGqK.js";
8
8
  import { n as handleFeishuSubagentEnded, t as handleFeishuSubagentDeliveryTarget } from "./subagent-hooks-Buadpie_.js";
9
9
  import { optionalPositiveIntegerSchema } from "openclaw/plugin-sdk/channel-actions";
@@ -1492,36 +1492,9 @@ async function listAppScopes(client) {
1492
1492
  };
1493
1493
  }
1494
1494
  function registerFeishuDocTools(api) {
1495
- if (!api.config) return;
1496
- const toolsCfg = resolveAnyEnabledFeishuToolsConfig(api.config);
1497
- const getClient = (params, defaultAccountId) => createFeishuToolClient({
1498
- api,
1499
- executeParams: params,
1500
- defaultAccountId,
1501
- requiredTool: {
1502
- family: "doc",
1503
- label: "Doc"
1504
- }
1505
- });
1506
- const getMediaMaxBytes = (params, defaultAccountId) => (resolveFeishuToolAccount({
1507
- api,
1508
- executeParams: params,
1509
- defaultAccountId,
1510
- requiredTool: {
1511
- family: "doc",
1512
- label: "Doc"
1513
- }
1514
- }).config?.mediaMaxMb ?? 30) * 1024 * 1024;
1515
- const getImageReadTimeoutMs = (params, defaultAccountId) => resolveConfiguredHttpTimeoutMs(resolveFeishuToolAccount({
1516
- api,
1517
- executeParams: params,
1518
- defaultAccountId,
1519
- requiredTool: {
1520
- family: "doc",
1521
- label: "Doc"
1522
- }
1523
- }));
1524
- if (toolsCfg.doc) api.registerTool((ctx) => {
1495
+ api.registerTool((ctx) => {
1496
+ const cfg = ctx.runtimeConfig ?? ctx.config ?? api.config;
1497
+ if (!cfg || !resolveAnyEnabledFeishuToolsConfig(cfg).doc) return null;
1525
1498
  const defaultAccountId = ctx.agentAccountId;
1526
1499
  const mediaLocalRoots = resolveDocToolLocalRoots(ctx);
1527
1500
  const trustedRequesterOpenId = ctx.messageChannel === "feishu" ? normalizeOptionalString(ctx.requesterSenderId) : void 0;
@@ -1535,12 +1508,23 @@ function registerFeishuDocTools(api) {
1535
1508
  const p = params;
1536
1509
  try {
1537
1510
  if (p.action === "create" && Object.hasOwn(p, "content")) return feishuExternalToolResult({ error: "Feishu document creation does not support content. Call action \"create\" first, then call action \"write\" with the returned document_id as doc_token." });
1538
- const client = getClient(p, defaultAccountId);
1511
+ const account = resolveFeishuToolAccount({
1512
+ cfg,
1513
+ executeParams: p,
1514
+ defaultAccountId,
1515
+ requiredTool: {
1516
+ family: "doc",
1517
+ label: "Doc"
1518
+ }
1519
+ });
1520
+ const client = createFeishuClient(account);
1521
+ const mediaMaxBytes = (account.config.mediaMaxMb ?? 30) * 1024 * 1024;
1522
+ const imageReadTimeoutMs = resolveConfiguredHttpTimeoutMs(account);
1539
1523
  switch (p.action) {
1540
1524
  case "read": return feishuExternalToolResult(await readDoc(client, p.doc_token));
1541
- case "write": return feishuExternalToolResult(await writeDoc(client, p.doc_token, p.content, getMediaMaxBytes(p, defaultAccountId), getImageReadTimeoutMs(p, defaultAccountId), api.logger));
1542
- case "append": return feishuExternalToolResult(await appendDoc(client, p.doc_token, p.content, getMediaMaxBytes(p, defaultAccountId), getImageReadTimeoutMs(p, defaultAccountId), api.logger));
1543
- case "insert": return feishuExternalToolResult(await insertDoc(client, p.doc_token, p.content, p.after_block_id, getMediaMaxBytes(p, defaultAccountId), getImageReadTimeoutMs(p, defaultAccountId), api.logger));
1525
+ case "write": return feishuExternalToolResult(await writeDoc(client, p.doc_token, p.content, mediaMaxBytes, imageReadTimeoutMs, api.logger));
1526
+ case "append": return feishuExternalToolResult(await appendDoc(client, p.doc_token, p.content, mediaMaxBytes, imageReadTimeoutMs, api.logger));
1527
+ case "insert": return feishuExternalToolResult(await insertDoc(client, p.doc_token, p.content, p.after_block_id, mediaMaxBytes, imageReadTimeoutMs, api.logger));
1544
1528
  case "create": return feishuExternalToolResult(await createDoc(client, p.title, p.folder_token, {
1545
1529
  grantToRequester: p.grant_to_requester,
1546
1530
  requesterOpenId: trustedRequesterOpenId
@@ -1552,8 +1536,8 @@ function registerFeishuDocTools(api) {
1552
1536
  case "create_table": return feishuExternalToolResult(await createTable(client, p.doc_token, p.row_size, p.column_size, p.parent_block_id, p.column_width));
1553
1537
  case "write_table_cells": return feishuExternalToolResult(await writeTableCells(client, p.doc_token, p.table_block_id, p.values));
1554
1538
  case "create_table_with_values": return feishuExternalToolResult(await createTableWithValues(client, p.doc_token, p.row_size, p.column_size, p.values, p.parent_block_id, p.column_width));
1555
- case "upload_image": return feishuExternalToolResult(await uploadImageBlock(client, p.doc_token, getMediaMaxBytes(p, defaultAccountId), getImageReadTimeoutMs(p, defaultAccountId), mediaLocalRoots, p.url, p.file_path, p.parent_block_id, p.filename, p.index, p.image));
1556
- case "upload_file": return feishuExternalToolResult(await uploadFileBlock(client, p.doc_token, getMediaMaxBytes(p, defaultAccountId), mediaLocalRoots, p.url, p.file_path, p.parent_block_id, p.filename));
1539
+ case "upload_image": return feishuExternalToolResult(await uploadImageBlock(client, p.doc_token, mediaMaxBytes, imageReadTimeoutMs, mediaLocalRoots, p.url, p.file_path, p.parent_block_id, p.filename, p.index, p.image));
1540
+ case "upload_file": return feishuExternalToolResult(await uploadFileBlock(client, p.doc_token, mediaMaxBytes, mediaLocalRoots, p.url, p.file_path, p.parent_block_id, p.filename));
1557
1541
  case "color_text": return feishuExternalToolResult(await updateColorText(client, p.doc_token, p.block_id, p.content));
1558
1542
  case "insert_table_row":
1559
1543
  case "insert_table_column":
@@ -1568,28 +1552,32 @@ function registerFeishuDocTools(api) {
1568
1552
  }
1569
1553
  };
1570
1554
  }, { name: "feishu_doc" });
1571
- if (toolsCfg.scopes) api.registerTool((ctx) => ({
1572
- name: "feishu_app_scopes",
1573
- resultContentSource: "network",
1574
- label: "Feishu App Scopes",
1575
- description: "List current app permissions (scopes). Use to debug permission issues or check available capabilities.",
1576
- parameters: Type.Object({}),
1577
- async execute() {
1578
- try {
1579
- const result = await listAppScopes(createFeishuToolClient({
1580
- api,
1581
- defaultAccountId: ctx.agentAccountId,
1582
- requiredTool: {
1583
- family: "scopes",
1584
- label: "App Scopes"
1585
- }
1586
- }));
1587
- return feishuExternalToolResult(result);
1588
- } catch (err) {
1589
- return feishuExternalToolResult({ error: formatErrorMessage(err) });
1555
+ api.registerTool((ctx) => {
1556
+ const cfg = ctx.runtimeConfig ?? ctx.config ?? api.config;
1557
+ if (!cfg || !resolveAnyEnabledFeishuToolsConfig(cfg).scopes) return null;
1558
+ return {
1559
+ name: "feishu_app_scopes",
1560
+ resultContentSource: "network",
1561
+ label: "Feishu App Scopes",
1562
+ description: "List current app permissions (scopes). Use to debug permission issues or check available capabilities.",
1563
+ parameters: Type.Object({}),
1564
+ async execute() {
1565
+ try {
1566
+ const result = await listAppScopes(createFeishuToolClient({
1567
+ cfg,
1568
+ defaultAccountId: ctx.agentAccountId,
1569
+ requiredTool: {
1570
+ family: "scopes",
1571
+ label: "App Scopes"
1572
+ }
1573
+ }));
1574
+ return feishuExternalToolResult(result);
1575
+ } catch (err) {
1576
+ return feishuExternalToolResult({ error: formatErrorMessage(err) });
1577
+ }
1590
1578
  }
1591
- }
1592
- }), { name: "feishu_app_scopes" });
1579
+ };
1580
+ }, { name: "feishu_app_scopes" });
1593
1581
  }
1594
1582
  //#endregion
1595
1583
  //#region extensions/feishu/src/wiki-schema.ts
@@ -1776,9 +1764,9 @@ async function renameNode(client, spaceId, nodeToken, title) {
1776
1764
  };
1777
1765
  }
1778
1766
  function registerFeishuWikiTools(api) {
1779
- if (!api.config) return;
1780
- if (!resolveAnyEnabledFeishuToolsConfig(api.config).wiki) return;
1781
1767
  api.registerTool((ctx) => {
1768
+ const cfg = ctx.runtimeConfig ?? ctx.config ?? api.config;
1769
+ if (!cfg || !resolveAnyEnabledFeishuToolsConfig(cfg).wiki) return null;
1782
1770
  const defaultAccountId = ctx.agentAccountId;
1783
1771
  return {
1784
1772
  name: "feishu_wiki",
@@ -1790,7 +1778,7 @@ function registerFeishuWikiTools(api) {
1790
1778
  const p = params;
1791
1779
  try {
1792
1780
  const createClient = () => createFeishuToolClient({
1793
- api,
1781
+ cfg,
1794
1782
  executeParams: p,
1795
1783
  defaultAccountId,
1796
1784
  requiredTool: {
@@ -1926,9 +1914,9 @@ async function removeMember(client, token, type, memberType, memberId) {
1926
1914
  return { success: true };
1927
1915
  }
1928
1916
  function registerFeishuPermTools(api) {
1929
- if (!api.config) return;
1930
- if (!resolveAnyEnabledFeishuToolsConfig(api.config).perm) return;
1931
1917
  api.registerTool((ctx) => {
1918
+ const cfg = ctx.runtimeConfig ?? ctx.config ?? api.config;
1919
+ if (!cfg || !resolveAnyEnabledFeishuToolsConfig(cfg).perm) return null;
1932
1920
  const defaultAccountId = ctx.agentAccountId;
1933
1921
  return {
1934
1922
  name: "feishu_perm",
@@ -1940,7 +1928,7 @@ function registerFeishuPermTools(api) {
1940
1928
  const p = params;
1941
1929
  try {
1942
1930
  const client = createFeishuToolClient({
1943
- api,
1931
+ cfg,
1944
1932
  executeParams: p,
1945
1933
  defaultAccountId,
1946
1934
  requiredTool: {
@@ -2374,43 +2362,45 @@ const UpdateRecordSchema = Type.Object({
2374
2362
  fields: Type.Record(Type.String(), BitableFieldValueSchema, { description: BITABLE_RECORD_FIELDS_DESCRIPTION })
2375
2363
  });
2376
2364
  function registerFeishuBitableTools(api) {
2377
- if (!api.config) return;
2378
- if (!resolveAnyEnabledFeishuToolsConfig(api.config).bitable) return;
2379
- const getClient = (params, defaultAccountId) => createFeishuToolClient({
2380
- api,
2381
- executeParams: params,
2382
- defaultAccountId,
2383
- requiredTool: {
2384
- family: "bitable",
2385
- label: "Bitable"
2386
- }
2387
- });
2388
2365
  const registerBitableTool = (params) => {
2389
- api.registerTool((ctx) => ({
2390
- name: params.name,
2391
- resultContentSource: "network",
2392
- label: params.label,
2393
- description: params.description,
2394
- parameters: params.parameters,
2395
- async execute(_toolCallId, rawParams) {
2396
- try {
2397
- return feishuExternalToolResult(await params.execute({
2398
- params: rawParams,
2399
- defaultAccountId: ctx.agentAccountId
2400
- }));
2401
- } catch (err) {
2402
- return feishuExternalToolResult({ error: formatErrorMessage(err) });
2366
+ api.registerTool((ctx) => {
2367
+ const cfg = ctx.runtimeConfig ?? ctx.config ?? api.config;
2368
+ if (!cfg || !resolveAnyEnabledFeishuToolsConfig(cfg).bitable) return null;
2369
+ return {
2370
+ name: params.name,
2371
+ resultContentSource: "network",
2372
+ label: params.label,
2373
+ description: params.description,
2374
+ parameters: params.parameters,
2375
+ async execute(_toolCallId, rawParams) {
2376
+ const executeParams = rawParams;
2377
+ try {
2378
+ return feishuExternalToolResult(await params.execute({
2379
+ params: executeParams,
2380
+ client: createFeishuToolClient({
2381
+ cfg,
2382
+ executeParams,
2383
+ defaultAccountId: ctx.agentAccountId,
2384
+ requiredTool: {
2385
+ family: "bitable",
2386
+ label: "Bitable"
2387
+ }
2388
+ })
2389
+ }));
2390
+ } catch (err) {
2391
+ return feishuExternalToolResult({ error: formatErrorMessage(err) });
2392
+ }
2403
2393
  }
2404
- }
2405
- }), { name: params.name });
2394
+ };
2395
+ }, { name: params.name });
2406
2396
  };
2407
2397
  registerBitableTool({
2408
2398
  name: "feishu_bitable_get_meta",
2409
2399
  label: "Feishu Bitable Get Meta",
2410
2400
  description: "Parse a Bitable URL and get app_token, table_id, and table list. Use this first when given a /wiki/ or /base/ URL.",
2411
2401
  parameters: GetMetaSchema,
2412
- async execute({ params, defaultAccountId }) {
2413
- return getBitableMeta(getClient(params, defaultAccountId), params.url);
2402
+ async execute({ params, client }) {
2403
+ return getBitableMeta(client, params.url);
2414
2404
  }
2415
2405
  });
2416
2406
  registerBitableTool({
@@ -2418,8 +2408,8 @@ function registerFeishuBitableTools(api) {
2418
2408
  label: "Feishu Bitable List Fields",
2419
2409
  description: "List all fields (columns) in a Bitable table with their types and properties",
2420
2410
  parameters: ListFieldsSchema,
2421
- async execute({ params, defaultAccountId }) {
2422
- return listFields(getClient(params, defaultAccountId), params.app_token, params.table_id);
2411
+ async execute({ params, client }) {
2412
+ return listFields(client, params.app_token, params.table_id);
2423
2413
  }
2424
2414
  });
2425
2415
  registerBitableTool({
@@ -2427,8 +2417,8 @@ function registerFeishuBitableTools(api) {
2427
2417
  label: "Feishu Bitable List Records",
2428
2418
  description: "List records (rows) from a Bitable table with pagination support",
2429
2419
  parameters: ListRecordsSchema,
2430
- async execute({ params, defaultAccountId }) {
2431
- return listRecords(getClient(params, defaultAccountId), params.app_token, params.table_id, readBitableListRecordsPageSize(params), params.page_token);
2420
+ async execute({ params, client }) {
2421
+ return listRecords(client, params.app_token, params.table_id, readBitableListRecordsPageSize(params), params.page_token);
2432
2422
  }
2433
2423
  });
2434
2424
  registerBitableTool({
@@ -2436,8 +2426,8 @@ function registerFeishuBitableTools(api) {
2436
2426
  label: "Feishu Bitable Get Record",
2437
2427
  description: "Get a single record by ID from a Bitable table",
2438
2428
  parameters: GetRecordSchema,
2439
- async execute({ params, defaultAccountId }) {
2440
- return getRecord(getClient(params, defaultAccountId), params.app_token, params.table_id, params.record_id);
2429
+ async execute({ params, client }) {
2430
+ return getRecord(client, params.app_token, params.table_id, params.record_id);
2441
2431
  }
2442
2432
  });
2443
2433
  registerBitableTool({
@@ -2445,8 +2435,8 @@ function registerFeishuBitableTools(api) {
2445
2435
  label: "Feishu Bitable Create Record",
2446
2436
  description: "Create a new record (row) in a Bitable table",
2447
2437
  parameters: CreateRecordSchema,
2448
- async execute({ params, defaultAccountId }) {
2449
- return createRecord(getClient(params, defaultAccountId), params.app_token, params.table_id, params.fields);
2438
+ async execute({ params, client }) {
2439
+ return createRecord(client, params.app_token, params.table_id, params.fields);
2450
2440
  }
2451
2441
  });
2452
2442
  registerBitableTool({
@@ -2454,8 +2444,8 @@ function registerFeishuBitableTools(api) {
2454
2444
  label: "Feishu Bitable Update Record",
2455
2445
  description: "Update an existing record (row) in a Bitable table",
2456
2446
  parameters: UpdateRecordSchema,
2457
- async execute({ params, defaultAccountId }) {
2458
- return updateRecord(getClient(params, defaultAccountId), params.app_token, params.table_id, params.record_id, params.fields);
2447
+ async execute({ params, client }) {
2448
+ return updateRecord(client, params.app_token, params.table_id, params.record_id, params.fields);
2459
2449
  }
2460
2450
  });
2461
2451
  registerBitableTool({
@@ -2463,8 +2453,8 @@ function registerFeishuBitableTools(api) {
2463
2453
  label: "Feishu Bitable Create App",
2464
2454
  description: "Create a new Bitable (multidimensional table) application",
2465
2455
  parameters: CreateAppSchema,
2466
- async execute({ params, defaultAccountId }) {
2467
- return createApp(getClient(params, defaultAccountId), params.name, params.folder_token, {
2456
+ async execute({ params, client }) {
2457
+ return createApp(client, params.name, params.folder_token, {
2468
2458
  debug: (msg) => api.logger.debug?.(msg),
2469
2459
  warn: (msg) => api.logger.warn?.(msg)
2470
2460
  });
@@ -2475,8 +2465,8 @@ function registerFeishuBitableTools(api) {
2475
2465
  label: "Feishu Bitable Create Field",
2476
2466
  description: "Create a new field (column) in a Bitable table",
2477
2467
  parameters: CreateFieldSchema,
2478
- async execute({ params, defaultAccountId }) {
2479
- return createField(getClient(params, defaultAccountId), params.app_token, params.table_id, params.field_name, params.field_type, params.property);
2468
+ async execute({ params, client }) {
2469
+ return createField(client, params.app_token, params.table_id, params.field_name, params.field_type, params.property);
2480
2470
  }
2481
2471
  });
2482
2472
  }
@@ -1,6 +1,6 @@
1
1
  import { a as resolveDefaultFeishuAccountId, i as listFeishuAccountIds, n as inspectFeishuCredentials, o as resolveFeishuAccount, r as listEnabledFeishuAccounts, s as resolveFeishuRuntimeAccount } from "./accounts-cCMNFBKg.js";
2
2
  import { i as resolveReceiveIdType, n as looksLikeFeishuId, r as normalizeFeishuTarget } from "./targets-BTQCYRZQ.js";
3
- import { A as sendStructuredCardFeishu, B as buildFeishuMediaFallbackText, C as shouldSuppressFeishuTextForVoiceMedia, Ct as resolveFeishuGroupConfig, Et as resolveFeishuGroupToolPolicy, H as resolveFeishuIdentityHeaderTitle, O as sendCardFeishu, Ot as normalizeFeishuChatType, R as createFeishuSendReceipt, U as deliverCommentThreadText, Z as cleanupAmbientCommentTypingReaction, _t as isFeishuGroupReadAllowed, a as FEISHU_PRESENTATION_CAPABILITIES, c as buildFeishuPresentationCard, d as feishuCardWithinTableLimit, dt as materializeFeishuPostMarkdownSoftBreaks, f as isFeishuCardWithinEnvelope, g as renderFeishuPresentationPayload, gt as canEnumerateAllFeishuPeers, h as renderFeishuPresentationFallbackText, ht as canEnumerateAllFeishuGroups, k as sendMessageFeishu, kt as resolveFeishuChatType, l as buildFeishuPresentationFallback, lt as chunkFeishuMarkdown, m as readNativeFeishuCard, mt as authorizeFeishuChatMemberRead, n as createFeishuReplyDeliveryResult, o as assertFeishuCardWithinEnvelope, ot as parseFeishuCommentTarget, p as markRenderedFeishuCard, pt as assertFeishuChatReadAllowed, s as buildFeishuPayloadCard, st as readNativeFeishuCardJson, t as createFeishuPartialReplyDeliveryError, u as consumeFeishuPresentationFallbackMarker, ut as chunkFeishuPostMarkdown, v as resolveFeishuRichReply, vt as isFeishuGroupReadEnabled, w as chunkFeishuCardMarkdown, x as sendMediaFeishu, y as withinCardTableLimit, yt as resolveFeishuChatReadPreliminaryAuthorization } from "./reply-delivery-result-BXEmtKpf.js";
3
+ import { A as sendStructuredCardFeishu, B as buildFeishuMediaFallbackText, C as shouldSuppressFeishuTextForVoiceMedia, Ct as resolveFeishuGroupConfig, Et as resolveFeishuGroupToolPolicy, H as resolveFeishuIdentityHeaderTitle, O as sendCardFeishu, Ot as normalizeFeishuChatType, R as createFeishuSendReceipt, U as deliverCommentThreadText, Z as cleanupAmbientCommentTypingReaction, _t as isFeishuGroupReadAllowed, a as FEISHU_PRESENTATION_CAPABILITIES, c as buildFeishuPresentationCard, d as feishuCardWithinTableLimit, dt as materializeFeishuPostMarkdownSoftBreaks, f as isFeishuCardWithinEnvelope, g as renderFeishuPresentationPayload, gt as canEnumerateAllFeishuPeers, h as renderFeishuPresentationFallbackText, ht as canEnumerateAllFeishuGroups, k as sendMessageFeishu, kt as resolveFeishuChatType, l as buildFeishuPresentationFallback, lt as chunkFeishuMarkdown, m as readNativeFeishuCard, mt as authorizeFeishuChatMemberRead, n as createFeishuReplyDeliveryResult, o as assertFeishuCardWithinEnvelope, ot as parseFeishuCommentTarget, p as markRenderedFeishuCard, pt as assertFeishuChatReadAllowed, s as buildFeishuPayloadCard, st as readNativeFeishuCardJson, t as createFeishuPartialReplyDeliveryError, u as consumeFeishuPresentationFallbackMarker, ut as chunkFeishuPostMarkdown, v as resolveFeishuRichReply, vt as isFeishuGroupReadEnabled, w as chunkFeishuCardMarkdown, x as sendMediaFeishu, y as withinCardTableLimit, yt as resolveFeishuChatReadPreliminaryAuthorization } from "./reply-delivery-result-C3smdVzb.js";
4
4
  import { n as normalizeCompatibilityConfig, o as normalizeFeishuExternalKey, r as FeishuChannelConfigSchema, t as legacyConfigRules } from "./doctor-contract-w6FpMypv.js";
5
5
  import { a as parseFeishuTargetId, i as parseFeishuDirectConversationId, n as buildFeishuModelOverrideParentCandidates, o as resolveConfiguredFeishuGroupSessionScope, r as parseFeishuConversationId, t as buildFeishuConversationId } from "./conversation-id-VYgGQ-GX.js";
6
6
  import { t as messageActionTargetAliases } from "./security-audit-DKfR4Cv3.js";
@@ -25,6 +25,7 @@ import { applyDirectoryQueryAndLimit, createChannelDirectoryAdapter, createRunti
25
25
  import { PlatformMessageNotDispatchedError } from "openclaw/plugin-sdk/error-runtime";
26
26
  import { resolveLegacyInteractiveTextFallback } from "openclaw/plugin-sdk/interactive-runtime";
27
27
  import { parseStrictPositiveInteger } from "openclaw/plugin-sdk/number-runtime";
28
+ import { DEFAULT_ACCOUNT_ID as DEFAULT_ACCOUNT_ID$1, createSetupTranslator, formatDocsLink, hasConfiguredSecretInput, mergeAllowFromEntries, patchScopedAccountConfig, patchTopLevelChannelConfigSection, promptSingleChannelSecretInput, setSetupChannelEnabled, splitSetupEntries } from "openclaw/plugin-sdk/setup";
28
29
  import { buildProbeChannelStatusSummary, createComputedAccountStatusAdapter, createDefaultChannelRuntimeState } from "openclaw/plugin-sdk/status-helpers";
29
30
  import { isRecord, normalizeLowercaseStringOrEmpty, normalizeOptionalLowercaseString, normalizeOptionalString, normalizeStringEntries } from "openclaw/plugin-sdk/string-coerce-runtime";
30
31
  import { convertMarkdownTables, sanitizeAssistantVisibleText } from "openclaw/plugin-sdk/text-chunking";
@@ -44,7 +45,6 @@ import { getReplyPayloadTtsSupplement, resolvePayloadMediaUrls, sendPayloadMedia
44
45
  import { statRegularFileSync } from "openclaw/plugin-sdk/security-runtime";
45
46
  import { readStringParam } from "openclaw/plugin-sdk/param-readers";
46
47
  import { defineChannelSetupContract } from "openclaw/plugin-sdk/channel-setup";
47
- import { DEFAULT_ACCOUNT_ID as DEFAULT_ACCOUNT_ID$1, createSetupTranslator, formatDocsLink, hasConfiguredSecretInput, mergeAllowFromEntries, patchScopedAccountConfig, patchTopLevelChannelConfigSection, promptSingleChannelSecretInput, setSetupChannelEnabled, splitSetupEntries } from "openclaw/plugin-sdk/setup";
48
48
  import { createChannelDmPolicy } from "openclaw/plugin-sdk/channel-dm-policy";
49
49
  //#region extensions/feishu/src/approval-auth.ts
50
50
  function normalizeFeishuApproverId(value) {
@@ -1882,7 +1882,7 @@ const meta = {
1882
1882
  order: 70,
1883
1883
  preferSessionLookupForAnnounceTarget: true
1884
1884
  };
1885
- const loadFeishuChannelRuntime = createLazyRuntimeNamedExport(() => import("./channel.runtime-BZzuDlOS.js"), "feishuChannelRuntime");
1885
+ const loadFeishuChannelRuntime = createLazyRuntimeNamedExport(() => import("./channel.runtime-B-f6ajOp.js"), "feishuChannelRuntime");
1886
1886
  async function resolveFeishuMessageSender(params) {
1887
1887
  try {
1888
1888
  const sender = params.resolve(await loadFeishuChannelRuntime());
@@ -2389,19 +2389,13 @@ const feishuPlugin = createChatChannelPlugin({
2389
2389
  else delete next.channels;
2390
2390
  return next;
2391
2391
  }
2392
- const feishuCfg = cfg.channels?.feishu;
2393
- const accounts = { ...feishuCfg?.accounts };
2392
+ const accounts = { ...(cfg.channels?.feishu)?.accounts };
2394
2393
  delete accounts[accountId];
2395
- return {
2396
- ...cfg,
2397
- channels: {
2398
- ...cfg.channels,
2399
- feishu: {
2400
- ...feishuCfg,
2401
- accounts: Object.keys(accounts).length > 0 ? accounts : void 0
2402
- }
2403
- }
2404
- };
2394
+ return patchTopLevelChannelConfigSection({
2395
+ cfg,
2396
+ channel: "feishu",
2397
+ patch: { accounts: Object.keys(accounts).length > 0 ? accounts : void 0 }
2398
+ });
2405
2399
  },
2406
2400
  isConfigured: (account) => account.configured,
2407
2401
  describeAccount: (account) => describeAccountSnapshot({
@@ -3009,7 +3003,7 @@ const feishuPlugin = createChatChannelPlugin({
3009
3003
  })
3010
3004
  }),
3011
3005
  gateway: { startAccount: async (ctx) => {
3012
- const { monitorFeishuProvider } = await import("./monitor-DSGtOPio.js");
3006
+ const { monitorFeishuProvider } = await import("./monitor-EuNsFn2T.js");
3013
3007
  const account = resolveFeishuRuntimeAccount({
3014
3008
  cfg: ctx.cfg,
3015
3009
  accountId: ctx.accountId
@@ -1,2 +1,2 @@
1
- import { t as feishuPlugin } from "./channel-DrAqd5ED.js";
1
+ import { t as feishuPlugin } from "./channel-HDnQAH4Z.js";
2
2
  export { feishuPlugin };
@@ -1,8 +1,8 @@
1
1
  import { o as resolveFeishuAccount, s as resolveFeishuRuntimeAccount } from "./accounts-cCMNFBKg.js";
2
- import { c as listFeishuDirectoryPeers, o as feishuOutbound, s as listFeishuDirectoryGroups } from "./channel-DrAqd5ED.js";
3
- import { E as getMessageFeishu, O as sendCardFeishu, S as sendStickerFeishu, T as editMessageFeishu, k as sendMessageFeishu, z as assertFeishuApiSuccess } from "./reply-delivery-result-BXEmtKpf.js";
2
+ import { c as listFeishuDirectoryPeers, o as feishuOutbound, s as listFeishuDirectoryGroups } from "./channel-HDnQAH4Z.js";
3
+ import { E as getMessageFeishu, O as sendCardFeishu, S as sendStickerFeishu, T as editMessageFeishu, k as sendMessageFeishu, z as assertFeishuApiSuccess } from "./reply-delivery-result-C3smdVzb.js";
4
4
  import { r as createFeishuClient } from "./client-DMbIL3UH.js";
5
- import { a as getFeishuMemberInfo, i as getChatMembers, n as buildFeishuDirectChatMembers, r as getChatInfo, t as assertFeishuChatMember } from "./chat-BZSnEtgb.js";
5
+ import { a as getFeishuMemberInfo, i as getChatMembers, n as buildFeishuDirectChatMembers, r as getChatInfo, t as assertFeishuChatMember } from "./chat-zhIPXu4X.js";
6
6
  import { t as probeFeishu } from "./probe-D_SatdZl.js";
7
7
  import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/string-coerce-runtime";
8
8
  //#region extensions/feishu/src/directory.ts
@@ -1,4 +1,4 @@
1
- import { G as feishuExternalToolResult, X as resolveFeishuToolAccount, Y as resolveAnyEnabledFeishuToolsConfig, kt as resolveFeishuChatType, mt as authorizeFeishuChatMemberRead, pt as assertFeishuChatReadAllowed, tt as formatFeishuApiError, yt as resolveFeishuChatReadPreliminaryAuthorization } from "./reply-delivery-result-BXEmtKpf.js";
1
+ import { G as feishuExternalToolResult, X as resolveFeishuToolAccount, Y as resolveAnyEnabledFeishuToolsConfig, kt as resolveFeishuChatType, mt as authorizeFeishuChatMemberRead, pt as assertFeishuChatReadAllowed, tt as formatFeishuApiError, yt as resolveFeishuChatReadPreliminaryAuthorization } from "./reply-delivery-result-C3smdVzb.js";
2
2
  import { r as createFeishuClient } from "./client-DMbIL3UH.js";
3
3
  import { optionalPositiveIntegerSchema } from "openclaw/plugin-sdk/channel-actions";
4
4
  import { readPositiveIntegerParam } from "openclaw/plugin-sdk/param-readers";
@@ -189,96 +189,97 @@ async function getFeishuMemberInfo(client, memberId, memberIdType = "open_id") {
189
189
  };
190
190
  }
191
191
  function registerFeishuChatTools(api) {
192
- if (!api.config) return;
193
- const cfg = api.config;
194
- if (!resolveAnyEnabledFeishuToolsConfig(cfg).chat) return;
195
- api.registerTool((toolContext) => ({
196
- name: "feishu_chat",
197
- resultContentSource: "network",
198
- label: "Feishu Chat",
199
- description: "Feishu chat operations. Actions: members, info, member_info",
200
- parameters: FeishuChatSchema,
201
- async execute(_toolCallId, params) {
202
- const rawParams = params;
203
- const p = params;
204
- try {
205
- const account = resolveFeishuToolAccount({
206
- api,
207
- defaultAccountId: toolContext.agentAccountId,
208
- requiredTool: {
209
- family: "chat",
210
- label: "chat"
211
- }
212
- });
213
- const client = createFeishuClient(account);
214
- switch (p.action) {
215
- case "members":
216
- if (!p.chat_id) return feishuExternalToolResult({ error: "chat_id is required for action members" });
217
- {
218
- const chat = await getAuthorizedFeishuChatInfo({
219
- client,
220
- cfg,
221
- account,
222
- chatId: p.chat_id,
223
- ctx: toolContext
224
- });
225
- const authorization = authorizeFeishuChatMemberRead({
226
- cfg,
227
- account,
228
- chatId: p.chat_id,
229
- chatType: resolveFeishuChatType(chat),
230
- ctx: toolContext,
231
- memberIdType: p.member_id_type
232
- });
233
- if (authorization.kind === "direct") return feishuExternalToolResult(buildFeishuDirectChatMembers(authorization));
234
- }
235
- return feishuExternalToolResult(await getChatMembers(client, p.chat_id, readChatPageSize(rawParams), p.page_token, p.member_id_type));
236
- case "info":
237
- if (!p.chat_id) return feishuExternalToolResult({ error: "chat_id is required for action info" });
238
- {
239
- const chat = await getAuthorizedFeishuChatInfo({
240
- client,
241
- cfg,
242
- account,
243
- chatId: p.chat_id,
244
- ctx: toolContext
245
- });
246
- return feishuExternalToolResult(chat);
192
+ api.registerTool((toolContext) => {
193
+ const cfg = toolContext.runtimeConfig ?? toolContext.config ?? api.config;
194
+ if (!cfg || !resolveAnyEnabledFeishuToolsConfig(cfg).chat) return null;
195
+ return {
196
+ name: "feishu_chat",
197
+ resultContentSource: "network",
198
+ label: "Feishu Chat",
199
+ description: "Feishu chat operations. Actions: members, info, member_info",
200
+ parameters: FeishuChatSchema,
201
+ async execute(_toolCallId, params) {
202
+ const rawParams = params;
203
+ const p = params;
204
+ try {
205
+ const account = resolveFeishuToolAccount({
206
+ cfg,
207
+ defaultAccountId: toolContext.agentAccountId,
208
+ requiredTool: {
209
+ family: "chat",
210
+ label: "chat"
247
211
  }
248
- case "member_info":
249
- if (!p.member_id) return feishuExternalToolResult({ error: "member_id is required for action member_info" });
250
- if (!p.chat_id) return feishuExternalToolResult({ error: "chat_id is required for action member_info" });
251
- {
252
- const chat = await getAuthorizedFeishuChatInfo({
253
- client,
254
- cfg,
255
- account,
256
- chatId: p.chat_id,
257
- ctx: toolContext
258
- });
259
- const authorization = authorizeFeishuChatMemberRead({
260
- cfg,
261
- account,
262
- chatId: p.chat_id,
263
- chatType: resolveFeishuChatType(chat),
264
- ctx: toolContext,
265
- memberId: p.member_id,
266
- memberIdType: p.member_id_type
267
- });
268
- if (authorization.kind === "group") {
269
- const memberIdType = p.member_id_type ?? "open_id";
270
- await assertFeishuChatMember(client, p.chat_id, p.member_id, memberIdType);
271
- return feishuExternalToolResult(await getFeishuMemberInfo(client, p.member_id, memberIdType));
212
+ });
213
+ const client = createFeishuClient(account);
214
+ switch (p.action) {
215
+ case "members":
216
+ if (!p.chat_id) return feishuExternalToolResult({ error: "chat_id is required for action members" });
217
+ {
218
+ const chat = await getAuthorizedFeishuChatInfo({
219
+ client,
220
+ cfg,
221
+ account,
222
+ chatId: p.chat_id,
223
+ ctx: toolContext
224
+ });
225
+ const authorization = authorizeFeishuChatMemberRead({
226
+ cfg,
227
+ account,
228
+ chatId: p.chat_id,
229
+ chatType: resolveFeishuChatType(chat),
230
+ ctx: toolContext,
231
+ memberIdType: p.member_id_type
232
+ });
233
+ if (authorization.kind === "direct") return feishuExternalToolResult(buildFeishuDirectChatMembers(authorization));
272
234
  }
273
- return feishuExternalToolResult(await getFeishuMemberInfo(client, authorization.memberId, authorization.memberIdType));
274
- }
275
- default: return feishuExternalToolResult({ error: `Unknown action: ${String(p.action)}` });
235
+ return feishuExternalToolResult(await getChatMembers(client, p.chat_id, readChatPageSize(rawParams), p.page_token, p.member_id_type));
236
+ case "info":
237
+ if (!p.chat_id) return feishuExternalToolResult({ error: "chat_id is required for action info" });
238
+ {
239
+ const chat = await getAuthorizedFeishuChatInfo({
240
+ client,
241
+ cfg,
242
+ account,
243
+ chatId: p.chat_id,
244
+ ctx: toolContext
245
+ });
246
+ return feishuExternalToolResult(chat);
247
+ }
248
+ case "member_info":
249
+ if (!p.member_id) return feishuExternalToolResult({ error: "member_id is required for action member_info" });
250
+ if (!p.chat_id) return feishuExternalToolResult({ error: "chat_id is required for action member_info" });
251
+ {
252
+ const chat = await getAuthorizedFeishuChatInfo({
253
+ client,
254
+ cfg,
255
+ account,
256
+ chatId: p.chat_id,
257
+ ctx: toolContext
258
+ });
259
+ const authorization = authorizeFeishuChatMemberRead({
260
+ cfg,
261
+ account,
262
+ chatId: p.chat_id,
263
+ chatType: resolveFeishuChatType(chat),
264
+ ctx: toolContext,
265
+ memberId: p.member_id,
266
+ memberIdType: p.member_id_type
267
+ });
268
+ if (authorization.kind === "group") {
269
+ const memberIdType = p.member_id_type ?? "open_id";
270
+ await assertFeishuChatMember(client, p.chat_id, p.member_id, memberIdType);
271
+ return feishuExternalToolResult(await getFeishuMemberInfo(client, p.member_id, memberIdType));
272
+ }
273
+ return feishuExternalToolResult(await getFeishuMemberInfo(client, authorization.memberId, authorization.memberIdType));
274
+ }
275
+ default: return feishuExternalToolResult({ error: `Unknown action: ${String(p.action)}` });
276
+ }
277
+ } catch (err) {
278
+ return feishuExternalToolResult({ error: formatFeishuApiError(err, { includeNestedErrorLogId: true }) });
276
279
  }
277
- } catch (err) {
278
- return feishuExternalToolResult({ error: formatFeishuApiError(err, { includeNestedErrorLogId: true }) });
279
280
  }
280
- }
281
- }), { name: "feishu_chat" });
281
+ };
282
+ }, { name: "feishu_chat" });
282
283
  }
283
284
  //#endregion
284
285
  export { getFeishuMemberInfo as a, getChatMembers as i, buildFeishuDirectChatMembers as n, registerFeishuChatTools as o, getChatInfo as r, assertFeishuChatMember as t };
@@ -143,7 +143,7 @@ async function fetchBotIdentityForMonitor(account, options = {}) {
143
143
  }
144
144
  //#endregion
145
145
  //#region extensions/feishu/src/monitor.ts
146
- const loadMonitorAccountRuntime = createLazyRuntimeModule(() => import("./monitor.account-BRDUsS_q.js"));
146
+ const loadMonitorAccountRuntime = createLazyRuntimeModule(() => import("./monitor.account-CZ7EtqYS.js"));
147
147
  async function monitorFeishuProvider(opts = {}) {
148
148
  const cfg = opts.config;
149
149
  if (!cfg) throw new Error("Config is required for Feishu monitor");
@@ -1,16 +1,16 @@
1
1
  import { o as resolveFeishuAccount, s as resolveFeishuRuntimeAccount } from "./accounts-cCMNFBKg.js";
2
2
  import { i as resolveReceiveIdType } from "./targets-BTQCYRZQ.js";
3
- import { $ as encodeQuery, A as sendStructuredCardFeishu, B as buildFeishuMediaFallbackText, C as shouldSuppressFeishuTextForVoiceMedia, Ct as resolveFeishuGroupConfig, D as listFeishuThreadMessages, Dt as resolveFeishuReplyPolicy, E as getMessageFeishu, F as isFeishuGroupChatType, I as parseInteractiveCardContent, L as parsePostContent, M as extractMentionTargets, Mt as createFeishuCardInteractionEnvelope, N as isFeishuBroadcastMention, Nt as decodeFeishuCardAction, O as sendCardFeishu, Ot as normalizeFeishuChatType$2, P as isMentionForwardRequest, Q as createCommentTypingReactionLifecycle, St as resolveFeishuDmIngressAccess, Tt as resolveFeishuGroupSenderActivationIngressAccess, U as deliverCommentThreadText, V as resolveFeishuIdentityEmoji, _ as renderFeishuReplyPayload, at as normalizeCommentFileType, b as saveMessageResourceFeishu, bt as hasExplicitFeishuGroupConfig, ct as resolveFeishuCardTemplate, dt as materializeFeishuPostMarkdownSoftBreaks, et as extractReplyText, i as noVisibleFeishuReplyDelivery, it as buildFeishuCommentTarget, j as formatFeishuMediaContent, jt as buildFeishuCardActionTextFallback, k as sendMessageFeishu, kt as resolveFeishuChatType, l as buildFeishuPresentationFallback, n as createFeishuReplyDeliveryResult, nt as parseCommentContentElements, r as mergeFeishuReplyDeliveryResults, rt as requestFeishuApi, t as createFeishuPartialReplyDeliveryError, u as consumeFeishuPresentationFallbackMarker, ut as chunkFeishuPostMarkdown, v as resolveFeishuRichReply, w as chunkFeishuCardMarkdown, wt as resolveFeishuGroupConversationIngressAccess, x as sendMediaFeishu, xt as normalizeFeishuAllowEntry, y as withinCardTableLimit } from "./reply-delivery-result-BXEmtKpf.js";
3
+ import { $ as encodeQuery, A as sendStructuredCardFeishu, B as buildFeishuMediaFallbackText, C as shouldSuppressFeishuTextForVoiceMedia, Ct as resolveFeishuGroupConfig, D as listFeishuThreadMessages, Dt as resolveFeishuReplyPolicy, E as getMessageFeishu, F as isFeishuGroupChatType, I as parseInteractiveCardContent, L as parsePostContent, M as extractMentionTargets, Mt as createFeishuCardInteractionEnvelope, N as isFeishuBroadcastMention, Nt as decodeFeishuCardAction, O as sendCardFeishu, Ot as normalizeFeishuChatType$2, P as isMentionForwardRequest, Q as createCommentTypingReactionLifecycle, St as resolveFeishuDmIngressAccess, Tt as resolveFeishuGroupSenderActivationIngressAccess, U as deliverCommentThreadText, V as resolveFeishuIdentityEmoji, _ as renderFeishuReplyPayload, at as normalizeCommentFileType, b as saveMessageResourceFeishu, bt as hasExplicitFeishuGroupConfig, ct as resolveFeishuCardTemplate, dt as materializeFeishuPostMarkdownSoftBreaks, et as extractReplyText, i as noVisibleFeishuReplyDelivery, it as buildFeishuCommentTarget, j as formatFeishuMediaContent, jt as buildFeishuCardActionTextFallback, k as sendMessageFeishu, kt as resolveFeishuChatType, l as buildFeishuPresentationFallback, n as createFeishuReplyDeliveryResult, nt as parseCommentContentElements, r as mergeFeishuReplyDeliveryResults, rt as requestFeishuApi, t as createFeishuPartialReplyDeliveryError, u as consumeFeishuPresentationFallbackMarker, ut as chunkFeishuPostMarkdown, v as resolveFeishuRichReply, w as chunkFeishuCardMarkdown, wt as resolveFeishuGroupConversationIngressAccess, x as sendMediaFeishu, xt as normalizeFeishuAllowEntry, y as withinCardTableLimit } from "./reply-delivery-result-C3smdVzb.js";
4
4
  import { a as normalizeFeishuWebhookPath, o as normalizeFeishuExternalKey } from "./doctor-contract-w6FpMypv.js";
5
5
  import { o as resolveConfiguredFeishuGroupSessionScope, t as buildFeishuConversationId } from "./conversation-id-VYgGQ-GX.js";
6
6
  import { a as getFeishuUserAgent, i as createFeishuWSClient, n as createEventDispatcher, r as createFeishuClient, s as resolveConfiguredHttpTimeoutMs } from "./client-DMbIL3UH.js";
7
7
  import { t as getFeishuRuntime } from "./runtime-C5JxBWZp.js";
8
- import { r as getChatInfo } from "./chat-BZSnEtgb.js";
8
+ import { r as getChatInfo } from "./chat-zhIPXu4X.js";
9
9
  import { t as createFeishuThreadBindingManager } from "./thread-bindings-BiL1wGqK.js";
10
10
  import { evaluateSupplementalContextVisibility, normalizeAgentId as normalizeAgentId$1, resolveChannelContextVisibilityMode } from "./runtime-api.js";
11
11
  import { t as readFeishuJsonResponse } from "./json-response-DXajw_FU.js";
12
12
  import { a as waitForAbortableDelay, i as raceWithTimeoutAndAbort } from "./probe-D_SatdZl.js";
13
- import { t as fetchBotIdentityForMonitor } from "./monitor-DSGtOPio.js";
13
+ import { t as fetchBotIdentityForMonitor } from "./monitor-EuNsFn2T.js";
14
14
  import { resolveAgentConfig } from "openclaw/plugin-sdk/agent-scope-runtime";
15
15
  import { DEFAULT_INGRESS_ADOPTION_STALL_MS, bindIngressLifecycleToReplyOptions, createChannelIngressError, createChannelIngressMonitor, createChannelMessageReplyPipeline, createReplyPrefixContext, formatChannelProgressDraftLineForEntry, isChannelProgressDraftWorkToolName, resolveAgentOutboundIdentity, resolveChannelPreviewStreamMode, resolveChannelStreamingBlockEnabled } from "openclaw/plugin-sdk/channel-outbound";
16
16
  import { createChannelPairingController } from "openclaw/plugin-sdk/channel-pairing";
@@ -6298,6 +6298,7 @@ function buildFeishuWebhookRateLimitKey(params) {
6298
6298
  //#region extensions/feishu/src/monitor.transport.ts
6299
6299
  const FEISHU_WEBHOOK_ACCEPTED_HEADER = "x-openclaw-delivery-accepted";
6300
6300
  const FEISHU_WEBHOOK_ACCEPTED_VALUE = "durable";
6301
+ const FEISHU_WEBHOOK_TIMESTAMP_MAX_SKEW_MS = 36e5;
6301
6302
  const FEISHU_WS_RECONNECT_INITIAL_DELAY_MS = 1e3;
6302
6303
  const FEISHU_WS_RECONNECT_MAX_DELAY_MS = 3e4;
6303
6304
  const FEISHU_WS_LOG_ERROR_MAX_LENGTH = 500;
@@ -6325,6 +6326,12 @@ function parseFeishuWebhookPayload(rawBody) {
6325
6326
  return null;
6326
6327
  }
6327
6328
  }
6329
+ function isFeishuWebhookTimestampFresh(timestamp) {
6330
+ const parsed = Number.parseInt(timestamp, 10);
6331
+ if (!Number.isFinite(parsed)) return false;
6332
+ const timestampMs = parsed < 0xe8d4a51000 ? parsed * 1e3 : parsed;
6333
+ return Math.abs(Date.now() - timestampMs) <= FEISHU_WEBHOOK_TIMESTAMP_MAX_SKEW_MS;
6334
+ }
6328
6335
  function isFeishuWebhookSignatureValid(params) {
6329
6336
  const encryptKey = params.encryptKey?.trim();
6330
6337
  if (!encryptKey) return false;
@@ -6335,6 +6342,7 @@ function isFeishuWebhookSignatureValid(params) {
6335
6342
  const nonce = Array.isArray(nonceHeader) ? nonceHeader[0] : nonceHeader;
6336
6343
  const signature = Array.isArray(signatureHeader) ? signatureHeader[0] : signatureHeader;
6337
6344
  if (!timestamp || !nonce || !signature) return false;
6345
+ if (!isFeishuWebhookTimestampFresh(timestamp)) return false;
6338
6346
  const computedSignature = crypto.createHash("sha256").update(timestamp + nonce + encryptKey + params.rawBody).digest("hex");
6339
6347
  return safeEqualSecret(computedSignature, signature);
6340
6348
  }
@@ -1267,32 +1267,32 @@ function resolveImplicitToolAccountId(params) {
1267
1267
  if (explicitAccountId) {
1268
1268
  const normalizedAccountId = normalizeOptionalAccountId(explicitAccountId);
1269
1269
  if (!normalizedAccountId) throw new Error(`Invalid Feishu account ID "${explicitAccountId}"`);
1270
- const listedAccountId = listFeishuAccountIds(params.api.config).find((accountId) => normalizeOptionalAccountId(accountId) === normalizedAccountId) ?? (() => {
1271
- const defaultAccountId = resolveDefaultFeishuAccountId(params.api.config);
1270
+ const listedAccountId = listFeishuAccountIds(params.cfg).find((accountId) => normalizeOptionalAccountId(accountId) === normalizedAccountId) ?? (() => {
1271
+ const defaultAccountId = resolveDefaultFeishuAccountId(params.cfg);
1272
1272
  return normalizeOptionalAccountId(defaultAccountId) === normalizedAccountId ? defaultAccountId : void 0;
1273
1273
  })();
1274
1274
  if (!listedAccountId) throw new Error(`Unknown Feishu account "${explicitAccountId}"`);
1275
1275
  if (!resolveFeishuAccount({
1276
- cfg: params.api.config,
1276
+ cfg: params.cfg,
1277
1277
  accountId: normalizedAccountId
1278
1278
  }).enabled) throw new Error(`Feishu account "${listedAccountId}" is disabled`);
1279
1279
  return normalizedAccountId;
1280
1280
  }
1281
1281
  const contextualAccountId = normalizeOptionalString(params.defaultAccountId);
1282
- if (contextualAccountId && listFeishuAccountIds(params.api.config).includes(contextualAccountId)) {
1282
+ if (contextualAccountId && listFeishuAccountIds(params.cfg).includes(contextualAccountId)) {
1283
1283
  if (resolveFeishuAccount({
1284
- cfg: params.api.config,
1284
+ cfg: params.cfg,
1285
1285
  accountId: contextualAccountId
1286
1286
  }).enabled) return contextualAccountId;
1287
1287
  }
1288
- const configuredDefaultAccountId = normalizeOptionalString((params.api.config?.channels?.feishu)?.defaultAccount);
1288
+ const configuredDefaultAccountId = normalizeOptionalString((params.cfg.channels?.feishu)?.defaultAccount);
1289
1289
  if (configuredDefaultAccountId && resolveFeishuAccount({
1290
- cfg: params.api.config,
1290
+ cfg: params.cfg,
1291
1291
  accountId: configuredDefaultAccountId
1292
1292
  }).enabled) return configuredDefaultAccountId;
1293
- if (params.api.config) for (const accountId of listFeishuAccountIds(params.api.config)) {
1293
+ for (const accountId of listFeishuAccountIds(params.cfg)) {
1294
1294
  const account = resolveFeishuAccount({
1295
- cfg: params.api.config,
1295
+ cfg: params.cfg,
1296
1296
  accountId
1297
1297
  });
1298
1298
  if (account.enabled && account.configured && resolveToolsConfig(account.config.tools)[params.requiredTool.family]) return accountId;
@@ -1300,9 +1300,8 @@ function resolveImplicitToolAccountId(params) {
1300
1300
  throw new Error(`No usable Feishu account has ${params.requiredTool.label} tools enabled`);
1301
1301
  }
1302
1302
  function resolveFeishuToolAccount(params) {
1303
- if (!params.api.config) throw new Error("Feishu config unavailable");
1304
1303
  const account = resolveFeishuRuntimeAccount({
1305
- cfg: params.api.config,
1304
+ cfg: params.cfg,
1306
1305
  accountId: resolveImplicitToolAccountId(params)
1307
1306
  });
1308
1307
  if (!resolveToolsConfig(account.config.tools)[params.requiredTool.family]) throw new Error(`Feishu ${params.requiredTool.label} tools are disabled for account "${account.accountId}"`);
@@ -1708,9 +1707,9 @@ async function deliverCommentThreadText(client, params) {
1708
1707
  }
1709
1708
  }
1710
1709
  function registerFeishuDriveTools(api) {
1711
- if (!api.config) return;
1712
- if (!resolveAnyEnabledFeishuToolsConfig(api.config).drive) return;
1713
1710
  api.registerTool((ctx) => {
1711
+ const cfg = ctx.runtimeConfig ?? ctx.config ?? api.config;
1712
+ if (!cfg || !resolveAnyEnabledFeishuToolsConfig(cfg).drive) return null;
1714
1713
  const defaultAccountId = ctx.agentAccountId;
1715
1714
  return {
1716
1715
  name: "feishu_drive",
@@ -1722,7 +1721,7 @@ function registerFeishuDriveTools(api) {
1722
1721
  const p = params;
1723
1722
  try {
1724
1723
  const client = createFeishuToolClient({
1725
- api,
1724
+ cfg,
1726
1725
  executeParams: p,
1727
1726
  defaultAccountId,
1728
1727
  requiredTool: {
@@ -1942,13 +1941,6 @@ function toStringOrEmpty(value) {
1942
1941
  function escapeMarkdownText(text) {
1943
1942
  return text.replace(MARKDOWN_SPECIAL_CHARS, "\\$1");
1944
1943
  }
1945
- function toBoolean(value) {
1946
- return value === true || value === 1 || value === "true";
1947
- }
1948
- function isStyleEnabled(style, key) {
1949
- if (!style) return false;
1950
- return toBoolean(style[key]);
1951
- }
1952
1944
  function wrapInlineCode(text) {
1953
1945
  const maxRun = Math.max(0, ...(text.match(/`+/g) ?? []).map((run) => run.length));
1954
1946
  const fence = "`".repeat(maxRun + 1);
@@ -1957,17 +1949,15 @@ function wrapInlineCode(text) {
1957
1949
  function sanitizeFenceLanguage(language) {
1958
1950
  return language.trim().replace(/[^A-Za-z0-9_+#.-]/g, "");
1959
1951
  }
1960
- function renderTextElement(element) {
1961
- const text = toStringOrEmpty(element.text);
1962
- const style = isRecord(element.style) ? element.style : void 0;
1963
- if (isStyleEnabled(style, "code")) return wrapInlineCode(text);
1964
- let rendered = escapeMarkdownText(text);
1965
- if (!rendered) return "";
1966
- if (isStyleEnabled(style, "bold")) rendered = `**${rendered}**`;
1967
- if (isStyleEnabled(style, "italic")) rendered = `*${rendered}*`;
1968
- if (isStyleEnabled(style, "underline")) rendered = `<u>${rendered}</u>`;
1969
- if (isStyleEnabled(style, "strikethrough") || isStyleEnabled(style, "line_through") || isStyleEnabled(style, "lineThrough")) rendered = `~~${rendered}~~`;
1970
- return rendered;
1952
+ function applyInlineStyles(text, style) {
1953
+ const content = text.trim();
1954
+ if (!content || !Array.isArray(style)) return text;
1955
+ let rendered = content;
1956
+ if (style.includes("bold")) rendered = `**${rendered}**`;
1957
+ if (style.includes("italic")) rendered = `*${rendered}*`;
1958
+ if (style.includes("underline")) rendered = `<u>${rendered}</u>`;
1959
+ if (style.includes("lineThrough")) rendered = `~~${rendered}~~`;
1960
+ return text.replace(content, () => rendered);
1971
1961
  }
1972
1962
  function renderLinkElement(element) {
1973
1963
  const href = toStringOrEmpty(element.href).trim();
@@ -1992,15 +1982,15 @@ function renderCodeBlockElement(element) {
1992
1982
  function renderElement(element, attachments, mentionedOpenIds, renderMediaPlaceholders) {
1993
1983
  if (!isRecord(element)) return escapeMarkdownText(toStringOrEmpty(element));
1994
1984
  switch (normalizeLowercaseStringOrEmpty(toStringOrEmpty(element.tag))) {
1995
- case "text": return renderTextElement(element);
1996
- case "a": return renderLinkElement(element);
1985
+ case "text": return applyInlineStyles(escapeMarkdownText(toStringOrEmpty(element.text)), element.style);
1986
+ case "a": return applyInlineStyles(renderLinkElement(element), element.style);
1997
1987
  case "at":
1998
1988
  {
1999
1989
  const mentioned = toStringOrEmpty(element.open_id) || toStringOrEmpty(element.user_id);
2000
1990
  const normalizedMention = normalizeFeishuExternalKey(mentioned);
2001
1991
  if (normalizedMention) mentionedOpenIds.push(normalizedMention);
2002
1992
  }
2003
- return renderMentionElement(element);
1993
+ return applyInlineStyles(renderMentionElement(element), element.style);
2004
1994
  case "img": {
2005
1995
  const imageKey = normalizeFeishuExternalKey(toStringOrEmpty(element.image_key));
2006
1996
  if (imageKey) attachments.push({
@@ -3353,24 +3343,20 @@ function assertFeishuCardWithinEnvelope(card, label = "Feishu card") {
3353
3343
  /** Feishu allows at most five table components per static interactive card. */
3354
3344
  const FEISHU_CARD_TABLE_LIMIT = 5;
3355
3345
  function countMarkdownTables(text) {
3356
- return text ? markdownToIRWithMeta(text, { tableMode: "block" }).tables.length : 0;
3346
+ return text.includes("|") ? markdownToIRWithMeta(text, { tableMode: "block" }).tables.length : 0;
3357
3347
  }
3358
3348
  function withinCardTableLimit(text) {
3359
3349
  return countMarkdownTables(text) <= FEISHU_CARD_TABLE_LIMIT;
3360
3350
  }
3361
- function collectFeishuCardMarkdownTexts(value, output) {
3362
- if (Array.isArray(value)) {
3363
- for (const item of value) collectFeishuCardMarkdownTexts(item, output);
3364
- return;
3365
- }
3366
- if (!isRecord(value)) return;
3367
- if (value.tag === "markdown" && typeof value.content === "string") output.push(value.content);
3368
- for (const child of Object.values(value)) collectFeishuCardMarkdownTexts(child, output);
3369
- }
3370
3351
  function feishuCardWithinTableLimit(card) {
3371
- const markdownTexts = [];
3372
- collectFeishuCardMarkdownTexts(card, markdownTexts);
3373
- return markdownTexts.reduce((total, text) => total + countMarkdownTables(text), 0) <= FEISHU_CARD_TABLE_LIMIT;
3352
+ let remaining = FEISHU_CARD_TABLE_LIMIT;
3353
+ const visit = (value) => {
3354
+ if (Array.isArray(value)) return value.every(visit);
3355
+ if (!isRecord(value)) return true;
3356
+ if (value.tag === "markdown" && typeof value.content === "string") remaining -= countMarkdownTables(value.content);
3357
+ return remaining >= 0 && Object.values(value).every(visit);
3358
+ };
3359
+ return visit(card);
3374
3360
  }
3375
3361
  function resolveFeishuButtonUrl(button) {
3376
3362
  if (button.action?.type === "url" || button.action?.type === "web-app") return button.action.url;
package/dist/setup-api.js CHANGED
@@ -1,2 +1,2 @@
1
- import { i as feishuSetupAdapter, n as feishuSetupWizard, t as feishuPlugin } from "./channel-DrAqd5ED.js";
1
+ import { i as feishuSetupAdapter, n as feishuSetupWizard, t as feishuPlugin } from "./channel-HDnQAH4Z.js";
2
2
  export { feishuPlugin, feishuSetupAdapter, feishuSetupWizard };
@@ -1,5 +1,9 @@
1
1
  {
2
2
  "id": "feishu",
3
+ "categories": [
4
+ "channels",
5
+ "tools"
6
+ ],
3
7
  "doctorContract": {
4
8
  "configRepair": true
5
9
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openclaw/feishu",
3
- "version": "2026.9.3",
3
+ "version": "2026.9.4",
4
4
  "description": "OpenClaw Feishu/Lark channel plugin for chats and workplace tools (community maintained by @m1heng).",
5
5
  "repository": {
6
6
  "type": "git",
@@ -16,7 +16,7 @@
16
16
  "zod": "4.4.3"
17
17
  },
18
18
  "peerDependencies": {
19
- "openclaw": ">=2026.9.3"
19
+ "openclaw": ">=2026.9.4"
20
20
  },
21
21
  "peerDependenciesMeta": {
22
22
  "openclaw": {
@@ -62,11 +62,11 @@
62
62
  "minHostVersion": ">=2026.5.29"
63
63
  },
64
64
  "compat": {
65
- "pluginApi": ">=2026.9.3"
65
+ "pluginApi": ">=2026.9.4"
66
66
  },
67
67
  "build": {
68
68
  "bundledDist": false,
69
- "openclawVersion": "2026.9.3"
69
+ "openclawVersion": "2026.9.4"
70
70
  },
71
71
  "release": {
72
72
  "publishToClawHub": true,