openclaw-lark-multi-agent 1.2.8 → 1.3.0

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.
@@ -895,11 +895,33 @@ export class FeishuBot {
895
895
  const BUSY_TIMEOUT_MS = 1_800_000; // 30 minutes, matches collectReply safety timeout
896
896
  const isBusy = busySince > 0 && (Date.now() - busySince) < BUSY_TIMEOUT_MS;
897
897
  if (isBusy) {
898
- // Queued: show waiting reaction
898
+ // The agent is mid-run. Instead of only queuing to wait for the current
899
+ // run to finish, try to STEER this message into the active run so it is
900
+ // seen at the next tool-call boundary (lets the user nudge/correct a long
901
+ // run in real time). The lma-steer plugin reports whether it landed.
902
+ const sessionKeyForSteer = this.getSessionKey(chatId);
903
+ const steer = await this.openclawClient.steer(sessionKeyForSteer, cleanText).catch(() => ({ status: "unavailable" }));
904
+ if (steer.status === "steered") {
905
+ // Inserted into the active run. Reuse the existing reaction lifecycle:
906
+ // mark "Get" (received/inserted); the current run's completion will
907
+ // advance it to DONE together with the rest of the batch.
908
+ await this.addReaction(messageId, "Get").catch(() => { });
909
+ pending.push({ messageId, emoji: "Get", rowId: insertedId });
910
+ this.pendingAckMessages.set(chatId, pending);
911
+ console.log(`[${this.config.name}] Agent busy for ${chatId.slice(-8)}, STEERED into active run: "${cleanText.substring(0, 50)}..."`);
912
+ // The message is already in DB with a pending trigger. Clear that
913
+ // trigger so it is NOT re-run as a separate follow-up batch after the
914
+ // current run ends — it has already been injected into this run.
915
+ if (insertedId > 0)
916
+ this.store.clearPendingTrigger(this.config.name, chatId, insertedId);
917
+ return;
918
+ }
919
+ // Could not steer (no active run raced to idle, rejected, or plugin
920
+ // unavailable): fall back to the original behavior — queue and wait.
899
921
  await this.addReaction(messageId, "Typing").catch(() => { });
900
922
  pending.push({ messageId, emoji: "Typing", rowId: insertedId });
901
923
  this.pendingAckMessages.set(chatId, pending);
902
- console.log(`[${this.config.name}] Agent busy for ${chatId.slice(-8)}, queuing: "${cleanText.substring(0, 50)}..."`);
924
+ console.log(`[${this.config.name}] Agent busy for ${chatId.slice(-8)} (steer=${steer.status}), queuing: "${cleanText.substring(0, 50)}..."`);
903
925
  return; // Message is in DB, will be picked up when agent finishes
904
926
  }
905
927
  if (busySince > 0) {
@@ -116,6 +116,23 @@ export declare class OpenClawClient {
116
116
  message: string;
117
117
  label?: string;
118
118
  }): Promise<any>;
119
+ /**
120
+ * Steer a message into the ACTIVE run for a session via the lma-steer plugin's
121
+ * `lma.steer` gateway method. Unlike a plain new message, this injects the text
122
+ * at the next tool-call boundary of the run that is currently executing, so the
123
+ * user can nudge/correct a long run instead of waiting for it to finish.
124
+ *
125
+ * Returns a structured status so the bridge can render the right reaction:
126
+ * - "steered" -> queued into the active run (will be seen next boundary)
127
+ * - "no_active_run" -> no active run; caller should fall back to normal queueing
128
+ * - "rejected" -> active run refused the injection (compacting/not streaming)
129
+ * - "unavailable" -> the lma-steer plugin/method is not available (e.g. not
130
+ * installed or gateway not restarted); caller falls back.
131
+ */
132
+ steer(sessionKey: string, text: string): Promise<{
133
+ status: "steered" | "no_active_run" | "rejected" | "unavailable";
134
+ sessionId?: string;
135
+ }>;
119
136
  /**
120
137
  * Get session info (model, tokens, etc.) for status display.
121
138
  */
@@ -920,6 +920,38 @@ export class OpenClawClient {
920
920
  async injectAssistantMessage(params) {
921
921
  return this.rpc("chat.inject", params, 10000);
922
922
  }
923
+ /**
924
+ * Steer a message into the ACTIVE run for a session via the lma-steer plugin's
925
+ * `lma.steer` gateway method. Unlike a plain new message, this injects the text
926
+ * at the next tool-call boundary of the run that is currently executing, so the
927
+ * user can nudge/correct a long run instead of waiting for it to finish.
928
+ *
929
+ * Returns a structured status so the bridge can render the right reaction:
930
+ * - "steered" -> queued into the active run (will be seen next boundary)
931
+ * - "no_active_run" -> no active run; caller should fall back to normal queueing
932
+ * - "rejected" -> active run refused the injection (compacting/not streaming)
933
+ * - "unavailable" -> the lma-steer plugin/method is not available (e.g. not
934
+ * installed or gateway not restarted); caller falls back.
935
+ */
936
+ async steer(sessionKey, text) {
937
+ try {
938
+ const res = await this.rpc("lma.steer", { sessionKey, text }, 10000);
939
+ const status = res?.status;
940
+ if (status === "steered" || status === "no_active_run" || status === "rejected") {
941
+ return { status, sessionId: typeof res?.sessionId === "string" ? res.sessionId : undefined };
942
+ }
943
+ return { status: "unavailable" };
944
+ }
945
+ catch (err) {
946
+ // Unknown method / plugin missing / transient RPC error -> caller falls back
947
+ // to normal queueing. Never throw into the message path.
948
+ const msg = err?.message || String(err);
949
+ if (!/unknown method/i.test(msg)) {
950
+ console.warn(`[OpenClaw] lma.steer failed for ${sessionKey.slice(-8)}: ${msg}`);
951
+ }
952
+ return { status: "unavailable" };
953
+ }
954
+ }
923
955
  /**
924
956
  * Get session info (model, tokens, etc.) for status display.
925
957
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openclaw-lark-multi-agent",
3
- "version": "1.2.8",
3
+ "version": "1.3.0",
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": {