openclaw-lark-multi-agent 1.8.5 → 1.8.7
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/feishu-bot.js +12 -2
- package/dist/openclaw-client.js +46 -0
- package/package.json +2 -2
package/dist/feishu-bot.js
CHANGED
|
@@ -1452,7 +1452,14 @@ export class FeishuBot {
|
|
|
1452
1452
|
state = 'rejected'; // prior explicit backend refusal; never silently move it to a successor
|
|
1453
1453
|
if (state === 'unavailable' || state === 'capability_blocked')
|
|
1454
1454
|
state = 'pending';
|
|
1455
|
-
|
|
1455
|
+
// Unknown is the NORMAL transient state right after a steer attempt
|
|
1456
|
+
// (the backend acceptance receipt has not landed yet); surfacing it on
|
|
1457
|
+
// every insertion spams the chat (user report 2026-10-16: "每次插入消
|
|
1458
|
+
// 息都发个这个"). Stay silent until it persists through several
|
|
1459
|
+
// re-checks (~45s), then notify exactly once.
|
|
1460
|
+
const unknownChecks = state === 'unknown' ? (Number(item.unknownChecks) || 0) + 1 : 0;
|
|
1461
|
+
const unknownNotified = Boolean(item.unknownNotified) || (state === 'unknown' && unknownChecks >= 3);
|
|
1462
|
+
const record = { ...item, attempted: valid ? (receipt.attempted ?? true) : true, sessionId: item.sessionId, reason: receipt.reason, unknownChecks, unknownNotified };
|
|
1456
1463
|
this.store.saveInsertion(this.config.name, chatId, item.rowId, item.insertionId, state, record, Date.now() + (state === 'unknown' ? 15_000 : 5000));
|
|
1457
1464
|
if (state === 'ordinary') {
|
|
1458
1465
|
void this.enqueueAndDispatchDelivery(chatId, 'insertion_status', `insertion:${item.insertionId}:ordinary`, 'ℹ️ 原 run 已明确结束,且这条消息确定未被插入;现已交回普通队列,只执行一次。', [], item.messageId, `insertion:${item.insertionId}:ordinary`).catch(() => { });
|
|
@@ -1475,10 +1482,13 @@ export class FeishuBot {
|
|
|
1475
1482
|
this.admittedSteerAcks.set(chatId, list);
|
|
1476
1483
|
}
|
|
1477
1484
|
}
|
|
1478
|
-
else if (state === '
|
|
1485
|
+
else if (state === 'target_changed' || state === 'rejected') {
|
|
1479
1486
|
if (item.state !== state)
|
|
1480
1487
|
void this.enqueueAndDispatchDelivery(chatId, 'insertion_status', `insertion:${item.insertionId}:${state}`, `ℹ️ 这条插入消息的状态为 ${state},仍保留本地记录,未确认接收前不会显示 Get,也不会自动重复执行。${receipt.reason || ''}`, [], item.messageId, `insertion:${item.insertionId}:${state}`).catch(() => { });
|
|
1481
1488
|
}
|
|
1489
|
+
else if (state === 'unknown' && unknownNotified && !item.unknownNotified) {
|
|
1490
|
+
void this.enqueueAndDispatchDelivery(chatId, 'insertion_status', `insertion:${item.insertionId}:unknown-prolonged`, `ℹ️ 这条插入消息约 45 秒仍未确认接收:本地记录保留中,不会自动重复执行;确认后会自动显示 Get。`, [], item.messageId, `insertion:${item.insertionId}:unknown-prolonged`).catch(() => { });
|
|
1491
|
+
}
|
|
1482
1492
|
}
|
|
1483
1493
|
}
|
|
1484
1494
|
finally {
|
package/dist/openclaw-client.js
CHANGED
|
@@ -900,6 +900,11 @@ export class OpenClawClient {
|
|
|
900
900
|
let lifecycleEndTimer = null;
|
|
901
901
|
let replayInvalidTimer = null;
|
|
902
902
|
let genericChatErrorTimer = null;
|
|
903
|
+
// A channel message-tool send marked terminate=true is the turn's intended
|
|
904
|
+
// user-visible output (2026-10-16 incident: it bypassed the bridge and the
|
|
905
|
+
// collector waited forever). Capture its text and settle on a short grace.
|
|
906
|
+
let terminatingSendText = "";
|
|
907
|
+
let terminatingSendTimer = null;
|
|
903
908
|
let pendingRuntimeFailureText = "";
|
|
904
909
|
let lastActivitySummary = "";
|
|
905
910
|
let lastActivityAt = 0;
|
|
@@ -1174,6 +1179,8 @@ export class OpenClawClient {
|
|
|
1174
1179
|
clearTimeout(replayInvalidTimer);
|
|
1175
1180
|
if (genericChatErrorTimer)
|
|
1176
1181
|
clearTimeout(genericChatErrorTimer);
|
|
1182
|
+
if (terminatingSendTimer)
|
|
1183
|
+
clearTimeout(terminatingSendTimer);
|
|
1177
1184
|
resolve(finalText);
|
|
1178
1185
|
};
|
|
1179
1186
|
const collectEvents = () => {
|
|
@@ -1310,6 +1317,43 @@ export class OpenClawClient {
|
|
|
1310
1317
|
if (hasEffectiveActivity(ev))
|
|
1311
1318
|
resetIdleTimer();
|
|
1312
1319
|
rememberActivity(ev);
|
|
1320
|
+
// Terminating channel-send detection: a message-tool result carrying
|
|
1321
|
+
// terminate=true ends the turn with that send as its user-visible
|
|
1322
|
+
// output. The bridge is the delivery channel for LMA sessions, so
|
|
1323
|
+
// waiting for a further final would hang forever (2026-10-16 frozen
|
|
1324
|
+
// card incident). Capture the sent text at tool start; settle on a
|
|
1325
|
+
// short grace unless a real final arrives first.
|
|
1326
|
+
{
|
|
1327
|
+
const tdata = ev.data || {};
|
|
1328
|
+
if (ev.stream === "tool" || (ev.stream === "item" && tdata.kind === "tool")) {
|
|
1329
|
+
const toolName = String(tdata.name || tdata.toolName || "");
|
|
1330
|
+
const tphase = tdata.phase === "result" ? (tdata.isError || tdata.error ? "error" : "end") : tdata.phase;
|
|
1331
|
+
if (toolName === "message" && tphase === "start") {
|
|
1332
|
+
const raw = tdata.input ?? tdata.args ?? tdata.meta ?? null;
|
|
1333
|
+
if (raw !== null) {
|
|
1334
|
+
try {
|
|
1335
|
+
const parsed = typeof raw === "string" ? JSON.parse(raw) : raw;
|
|
1336
|
+
if (parsed && typeof parsed.message === "string" && parsed.message.trim())
|
|
1337
|
+
terminatingSendText = parsed.message;
|
|
1338
|
+
}
|
|
1339
|
+
catch { /* non-JSON tool input */ }
|
|
1340
|
+
}
|
|
1341
|
+
}
|
|
1342
|
+
else if (toolName === "message" && (tphase === "end" || tphase === "error")) {
|
|
1343
|
+
const out = String(JSON.stringify(tdata.output ?? tdata.result ?? tdata.error ?? ""));
|
|
1344
|
+
if (/"?terminate"?\s*[:=]\s*true/i.test(out) && !terminatingSendTimer) {
|
|
1345
|
+
terminatingSendTimer = setTimeout(() => {
|
|
1346
|
+
terminatingSendTimer = null;
|
|
1347
|
+
if (observationClosed)
|
|
1348
|
+
return;
|
|
1349
|
+
const best = (chatFinalText.trim() || text.trim() || terminatingSendText || "").trim();
|
|
1350
|
+
finish(best || "NO_REPLY");
|
|
1351
|
+
}, 10_000);
|
|
1352
|
+
terminatingSendTimer.unref?.();
|
|
1353
|
+
}
|
|
1354
|
+
}
|
|
1355
|
+
}
|
|
1356
|
+
}
|
|
1313
1357
|
// If more events arrive after a replay-invalid lifecycle end, that lifecycle
|
|
1314
1358
|
// was not terminal for the user-visible run. Keep waiting for the real final.
|
|
1315
1359
|
if (replayInvalidTimer) {
|
|
@@ -1625,6 +1669,8 @@ export class OpenClawClient {
|
|
|
1625
1669
|
clearTimeout(replayInvalidTimer);
|
|
1626
1670
|
if (genericChatErrorTimer)
|
|
1627
1671
|
clearTimeout(genericChatErrorTimer);
|
|
1672
|
+
if (terminatingSendTimer)
|
|
1673
|
+
clearTimeout(terminatingSendTimer);
|
|
1628
1674
|
if (observationKey && this.runStateChecks.get(observationKey) === checkAfterNoActiveRun)
|
|
1629
1675
|
this.runStateChecks.delete(observationKey);
|
|
1630
1676
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "openclaw-lark-multi-agent",
|
|
3
|
-
"version": "1.8.
|
|
3
|
+
"version": "1.8.7",
|
|
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": {
|
|
@@ -81,4 +81,4 @@
|
|
|
81
81
|
"publishConfig": {
|
|
82
82
|
"access": "public"
|
|
83
83
|
}
|
|
84
|
-
}
|
|
84
|
+
}
|