openclaw-lark-multi-agent 1.0.12 → 1.0.13

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.
@@ -45,6 +45,8 @@ export declare class FeishuBot {
45
45
  * Format: lma-<botname>-<chatId>
46
46
  */
47
47
  getSessionKey(chatId: string): string;
48
+ private lmaBridgePolicy;
49
+ private injectBridgePolicy;
48
50
  /**
49
51
  * Ensure the session for a given chatId exists with the correct model.
50
52
  * Lazy: only creates on first message in that chat.
@@ -100,6 +100,23 @@ export class FeishuBot {
100
100
  getSessionKey(chatId) {
101
101
  return `lma-${this.config.name.toLowerCase()}-${chatId}`;
102
102
  }
103
+ lmaBridgePolicy() {
104
+ return [
105
+ "[LMA bridge policy]",
106
+ "你正在 OpenClaw Lark Multi-Agent bridge 会话中。",
107
+ "不要调用 message、sessions_send、feishu_im_user_message 或任何主动向飞书/外部聊天发送消息的工具。",
108
+ "直接在当前回复中作答;LMA bridge 会负责把最终回复投递回原始飞书群。",
109
+ ].join("\n");
110
+ }
111
+ async injectBridgePolicy(sessionKey) {
112
+ await this.openclawClient.injectAssistantMessage({
113
+ sessionKey,
114
+ message: this.lmaBridgePolicy(),
115
+ label: "LMA bridge policy",
116
+ }).catch((err) => {
117
+ console.warn(`[${this.config.name}] bridge policy inject failed:`, err.message);
118
+ });
119
+ }
103
120
  /**
104
121
  * Ensure the session for a given chatId exists with the correct model.
105
122
  * Lazy: only creates on first message in that chat.
@@ -136,6 +153,7 @@ export class FeishuBot {
136
153
  });
137
154
  // Always patch model after create to ensure it takes effect
138
155
  await this.openclawClient.patchSession({ key: sessionKey, model: this.config.model });
156
+ await this.injectBridgePolicy(sessionKey);
139
157
  console.log(`[${this.config.name}] Session created: ${sessionKey} (model: ${this.config.model})`);
140
158
  }
141
159
  }
@@ -43,6 +43,10 @@ export declare class OpenClawClient {
43
43
  private chatSendConcurrency;
44
44
  private activeChatSends;
45
45
  private chatSendWaiters;
46
+ /** Maintenance RPCs like sessions.compact are heavy and should not fan out. */
47
+ private maintenanceConcurrency;
48
+ private activeMaintenanceRpcs;
49
+ private maintenanceWaiters;
46
50
  constructor(config: OpenClawConfig);
47
51
  connect(): Promise<void>;
48
52
  private _doConnect;
@@ -71,6 +75,11 @@ export declare class OpenClawClient {
71
75
  label?: string;
72
76
  }): Promise<any>;
73
77
  getSessionStatus(key: string): Promise<any>;
78
+ injectAssistantMessage(params: {
79
+ sessionKey: string;
80
+ message: string;
81
+ label?: string;
82
+ }): Promise<any>;
74
83
  /**
75
84
  * Get session info (model, tokens, etc.) for status display.
76
85
  */
@@ -102,6 +111,8 @@ export declare class OpenClawClient {
102
111
  muteProactiveDelivery(sessionKey: string): (delayMs?: number) => void;
103
112
  private acquireChatSendSlot;
104
113
  private releaseChatSendSlot;
114
+ private acquireMaintenanceSlot;
115
+ private releaseMaintenanceSlot;
105
116
  chatSend(params: {
106
117
  sessionKey: string;
107
118
  message: string;
@@ -44,6 +44,10 @@ export class OpenClawClient {
44
44
  chatSendConcurrency = Number(process.env.OPENCLAW_LARK_MULTI_AGENT_CHAT_SEND_CONCURRENCY || 3);
45
45
  activeChatSends = 0;
46
46
  chatSendWaiters = [];
47
+ /** Maintenance RPCs like sessions.compact are heavy and should not fan out. */
48
+ maintenanceConcurrency = Number(process.env.OPENCLAW_LARK_MULTI_AGENT_MAINTENANCE_CONCURRENCY || 1);
49
+ activeMaintenanceRpcs = 0;
50
+ maintenanceWaiters = [];
47
51
  constructor(config) {
48
52
  this.config = config;
49
53
  }
@@ -692,6 +696,9 @@ export class OpenClawClient {
692
696
  async getSessionStatus(key) {
693
697
  return this.rpc("sessions.describe", { key });
694
698
  }
699
+ async injectAssistantMessage(params) {
700
+ return this.rpc("chat.inject", params, 10000);
701
+ }
695
702
  /**
696
703
  * Get session info (model, tokens, etc.) for status display.
697
704
  */
@@ -724,7 +731,15 @@ export class OpenClawClient {
724
731
  return this.rpc("sessions.reset", { key }, 5000).catch(() => { });
725
732
  }
726
733
  async compactSession(key) {
727
- return this.rpc("sessions.compact", { key });
734
+ const release = await this.acquireMaintenanceSlot("sessions.compact");
735
+ const startedAt = Date.now();
736
+ try {
737
+ return await this.rpc("sessions.compact", { key }, 10 * 60 * 1000);
738
+ }
739
+ finally {
740
+ console.log(`[OpenClaw] sessions.compact finished for ${key} in ${Date.now() - startedAt}ms`);
741
+ release();
742
+ }
728
743
  }
729
744
  // --- Chat ---
730
745
  /**
@@ -882,6 +897,24 @@ export class OpenClawClient {
882
897
  if (next)
883
898
  next();
884
899
  }
900
+ async acquireMaintenanceSlot(kind) {
901
+ const limit = Math.max(1, this.maintenanceConcurrency || 1);
902
+ if (this.activeMaintenanceRpcs < limit) {
903
+ this.activeMaintenanceRpcs++;
904
+ return () => this.releaseMaintenanceSlot();
905
+ }
906
+ const startedWaitingAt = Date.now();
907
+ await new Promise((resolve) => this.maintenanceWaiters.push(resolve));
908
+ this.activeMaintenanceRpcs++;
909
+ console.log(`[OpenClaw] ${kind} waited ${Date.now() - startedWaitingAt}ms for maintenance slot (active=${this.activeMaintenanceRpcs}/${limit})`);
910
+ return () => this.releaseMaintenanceSlot();
911
+ }
912
+ releaseMaintenanceSlot() {
913
+ this.activeMaintenanceRpcs = Math.max(0, this.activeMaintenanceRpcs - 1);
914
+ const next = this.maintenanceWaiters.shift();
915
+ if (next)
916
+ next();
917
+ }
885
918
  async chatSend(params) {
886
919
  const sk = params.sessionKey;
887
920
  const fullSessionKey = `agent:main:${sk}`;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openclaw-lark-multi-agent",
3
- "version": "1.0.12",
3
+ "version": "1.0.13",
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": {