openclaw-lark-multi-agent 1.0.2 β†’ 1.0.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.
@@ -33,6 +33,8 @@ export declare class FeishuBot {
33
33
  private delayedFailureTimers;
34
34
  /** Last time a real assistant-visible reply was successfully handed to the delivery pipeline. */
35
35
  private lastRealDeliveryAt;
36
+ /** Active chatSend trigger target so final replies and proactive session.message share one delivery key. */
37
+ private activeDeliveryTargets;
36
38
  private adminOpenId;
37
39
  private static allBots;
38
40
  constructor(config: BotConfig, openclawClient: OpenClawClient, store: MessageStore, adminOpenId?: string);
@@ -84,6 +86,7 @@ export declare class FeishuBot {
84
86
  private formatUserVisibleError;
85
87
  private isRuntimeFailureText;
86
88
  private cancelDelayedFailure;
89
+ private setActiveDeliveryTarget;
87
90
  private scheduleDelayedFailure;
88
91
  private deliverySessionKey;
89
92
  private stableHash;
@@ -1,9 +1,12 @@
1
1
  import * as lark from "@larksuiteoapi/node-sdk";
2
+ import { createRequire } from "module";
2
3
  import { existsSync, readFileSync, statSync } from "fs";
3
4
  import { basename, extname, resolve } from "path";
4
5
  import { getBridgeAttachmentAllowedRoots, getBridgeAttachmentsDir } from "./paths.js";
5
6
  import { buildFeishuCardElements } from "./markdown.js";
6
7
  import { discussionManager } from "./discussion-manager.js";
8
+ const require = createRequire(import.meta.url);
9
+ const LMA_VERSION = require("../package.json").version;
7
10
  const MAX_BOT_STREAK = 10;
8
11
  const BRIDGE_ATTACHMENTS_DIR = getBridgeAttachmentsDir();
9
12
  const BRIDGE_ATTACHMENT_ALLOWED_ROOTS = getBridgeAttachmentAllowedRoots();
@@ -39,6 +42,8 @@ export class FeishuBot {
39
42
  delayedFailureTimers = new Map();
40
43
  /** Last time a real assistant-visible reply was successfully handed to the delivery pipeline. */
41
44
  lastRealDeliveryAt = new Map();
45
+ /** Active chatSend trigger target so final replies and proactive session.message share one delivery key. */
46
+ activeDeliveryTargets = new Map();
42
47
  adminOpenId;
43
48
  static allBots = new Map();
44
49
  constructor(config, openclawClient, store, adminOpenId) {
@@ -146,7 +151,8 @@ export class FeishuBot {
146
151
  const parsed = this.extractBridgeAttachments(text);
147
152
  if (parsed.text.trim() || parsed.attachments.length > 0)
148
153
  this.cancelDelayedFailure(chatId);
149
- await this.enqueueAndDispatchDelivery(chatId, "assistant_visible", this.deliverySourceId("proactive", `${Date.now()}:${Math.random()}:${parsed.text.trim()}|${JSON.stringify(parsed.attachments)}`), parsed.text.trim(), parsed.attachments);
154
+ const activeTarget = this.activeDeliveryTargets.get(chatId);
155
+ await this.enqueueAndDispatchDelivery(chatId, "assistant_visible", this.deliverySourceId("proactive", `${Date.now()}:${Math.random()}:${parsed.text.trim()}|${JSON.stringify(parsed.attachments)}`), parsed.text.trim(), parsed.attachments, activeTarget?.messageId, activeTarget ? `trigger:${activeTarget.triggerId}` : undefined);
150
156
  }
151
157
  catch (err) {
152
158
  console.error(`[${this.config.name}] Failed to deliver proactive msg:`, err.message);
@@ -669,16 +675,26 @@ export class FeishuBot {
669
675
  }
670
676
  }
671
677
  try {
672
- const reply = await this.openclawClient.chatSendWithContext({
673
- sessionKey,
674
- unsyncedMessages: contextMsgs,
675
- currentMessage: lastHuman.content,
676
- currentSenderName: lastHuman.senderName,
677
- deliver: false,
678
- // Keep bridge UX responsive; long agent/tool loops should surface a clear failure
679
- // instead of leaving reactions stuck forever.
680
- timeoutMs: 1_800_000,
681
- });
678
+ const releaseActiveDeliveryTarget = lastHuman.messageId ? this.setActiveDeliveryTarget(chatId, triggerId, lastHuman.messageId) : () => { };
679
+ let reply;
680
+ try {
681
+ reply = await this.openclawClient.chatSendWithContext({
682
+ sessionKey,
683
+ unsyncedMessages: contextMsgs,
684
+ currentMessage: lastHuman.content,
685
+ currentSenderName: lastHuman.senderName,
686
+ deliver: false,
687
+ // Keep bridge UX responsive; long agent/tool loops should surface a clear failure
688
+ // instead of leaving reactions stuck forever.
689
+ timeoutMs: 1_800_000,
690
+ });
691
+ }
692
+ finally {
693
+ // OpenClaw may emit the final assistant session.message just after
694
+ // collectReply returns. Keep the trigger mapping briefly so proactive
695
+ // and chat-final paths share the same delivery key.
696
+ releaseActiveDeliveryTarget();
697
+ }
682
698
  console.log(`[${this.config.name}] OpenClaw reply collected for ${chatId.slice(-8)} in ${Date.now() - queueStartedAt}ms`);
683
699
  const parsedReply = this.extractBridgeAttachments(reply);
684
700
  const visibleReply = parsedReply.text;
@@ -934,6 +950,23 @@ export class FeishuBot {
934
950
  clearTimeout(timer);
935
951
  this.delayedFailureTimers.delete(chatId);
936
952
  }
953
+ setActiveDeliveryTarget(chatId, triggerId, messageId) {
954
+ const existing = this.activeDeliveryTargets.get(chatId);
955
+ if (existing?.timer)
956
+ clearTimeout(existing.timer);
957
+ const token = Symbol(`${chatId}:${triggerId}`);
958
+ this.activeDeliveryTargets.set(chatId, { triggerId, messageId, token });
959
+ return () => {
960
+ const timer = setTimeout(() => {
961
+ const current = this.activeDeliveryTargets.get(chatId);
962
+ if (current?.token === token)
963
+ this.activeDeliveryTargets.delete(chatId);
964
+ }, 60_000);
965
+ const current = this.activeDeliveryTargets.get(chatId);
966
+ if (current?.token === token)
967
+ current.timer = timer;
968
+ };
969
+ }
937
970
  scheduleDelayedFailure(chatId, replyToMessageId, text, triggerId) {
938
971
  const lastRealDelivery = this.lastRealDeliveryAt.get(chatId) || 0;
939
972
  if (Date.now() - lastRealDelivery < 90_000) {
@@ -1435,6 +1468,7 @@ export class FeishuBot {
1435
1468
  `πŸ“Š ${this.config.name} Bot Status`,
1436
1469
  `━━━━━━━━━━━━━━━━━━`,
1437
1470
  `πŸ€– Bot: ${this.config.name}`,
1471
+ `🧩 LMA: ${LMA_VERSION}`,
1438
1472
  `🧠 ζ¨‘εž‹: ${model}`,
1439
1473
  `πŸ’¬ 会话: ${chatLabel} (${chatType === "p2p" ? "私聊" : "羀聊"})`,
1440
1474
  `πŸ“‹ Session: ${sessionExists} | ${status}`,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openclaw-lark-multi-agent",
3
- "version": "1.0.2",
3
+ "version": "1.0.3",
4
4
  "description": "Multi-bot Lark/Feishu bridge for OpenClaw, with per-bot model routing and isolated sessions",
5
5
  "type": "module",
6
6
  "scripts": {