@vibe-lark/larkpal 0.1.80 → 0.1.82
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/main.mjs +55 -16
- package/package.json +1 -1
package/dist/main.mjs
CHANGED
|
@@ -22,7 +22,6 @@ import { pipeline } from "node:stream/promises";
|
|
|
22
22
|
import { PassThrough, Readable, Transform } from "node:stream";
|
|
23
23
|
import express, { Router } from "express";
|
|
24
24
|
import Busboy from "busboy";
|
|
25
|
-
import { EventEmitter as EventEmitter$1 } from "events";
|
|
26
25
|
import cron from "node-cron";
|
|
27
26
|
import * as Lark from "@larksuiteoapi/node-sdk";
|
|
28
27
|
import { DEFAULT_ACCOUNT_ID, normalizeAccountId } from "openclaw/plugin-sdk/account-id";
|
|
@@ -894,7 +893,7 @@ var CCStreamParser = class extends EventEmitter {
|
|
|
894
893
|
displayName: getToolDisplayName(block.name),
|
|
895
894
|
toolUseId: block.id
|
|
896
895
|
});
|
|
897
|
-
this.emit("toolUseStart", block.name, block.input ?? {});
|
|
896
|
+
this.emit("toolUseStart", block.name, block.input ?? {}, block.id);
|
|
898
897
|
}
|
|
899
898
|
break;
|
|
900
899
|
}
|
|
@@ -942,7 +941,7 @@ var CCStreamParser = class extends EventEmitter {
|
|
|
942
941
|
displayName: getToolDisplayName(block.name),
|
|
943
942
|
toolUseId: block.id
|
|
944
943
|
});
|
|
945
|
-
this.emit("toolUseStart", block.name, block.input ?? {});
|
|
944
|
+
this.emit("toolUseStart", block.name, block.input ?? {}, block.id);
|
|
946
945
|
}
|
|
947
946
|
}
|
|
948
947
|
this.emit("assistant", msg);
|
|
@@ -1757,8 +1756,8 @@ var SessionProcessManager = class {
|
|
|
1757
1756
|
}
|
|
1758
1757
|
getCallbacks()?.onThinkingDelta?.(text);
|
|
1759
1758
|
});
|
|
1760
|
-
parser.on("toolUseStart", (toolName, toolInput) => {
|
|
1761
|
-
getCallbacks()?.onToolUseStart?.(toolName, toolInput);
|
|
1759
|
+
parser.on("toolUseStart", (toolName, toolInput, toolUseId) => {
|
|
1760
|
+
getCallbacks()?.onToolUseStart?.(toolName, toolInput, toolUseId);
|
|
1762
1761
|
});
|
|
1763
1762
|
parser.on("toolResult", (toolUseId, result) => {
|
|
1764
1763
|
getCallbacks()?.onToolResult?.(toolUseId, result);
|
|
@@ -4779,6 +4778,14 @@ function normalizeRuntimeResult(result) {
|
|
|
4779
4778
|
error
|
|
4780
4779
|
};
|
|
4781
4780
|
}
|
|
4781
|
+
function shouldTreatUnknownToolErrorAsRecovered(run, normalizedResult, result) {
|
|
4782
|
+
if (!normalizedResult.isError || normalizedResult.finalStatus !== "error_during_execution") return false;
|
|
4783
|
+
if (!run.unknownToolCallCount || run.lastToolError !== void 0) return false;
|
|
4784
|
+
if (!run.lastToolName || run.lastToolName === run.lastUnknownToolName) return false;
|
|
4785
|
+
const terminalText = normalizeWhitespace(result.result || "");
|
|
4786
|
+
if (terminalText && /\bNo such tool available\b/i.test(terminalText)) return false;
|
|
4787
|
+
return Boolean(run.text.trim() || terminalText);
|
|
4788
|
+
}
|
|
4782
4789
|
function buildRuntimeErrorSummary(subtype, result) {
|
|
4783
4790
|
const message = normalizeWhitespace(result || `Runtime execution failed: ${subtype}`);
|
|
4784
4791
|
const httpStatus = extractHttpStatus(message);
|
|
@@ -4874,6 +4881,11 @@ function readBooleanField(value, key) {
|
|
|
4874
4881
|
const field = value[key];
|
|
4875
4882
|
return typeof field === "boolean" ? field : void 0;
|
|
4876
4883
|
}
|
|
4884
|
+
function isUnknownToolResult(result) {
|
|
4885
|
+
const summary = readStringField(result, "resultSummary") ?? "";
|
|
4886
|
+
const content = readStringField(result, "content") ?? "";
|
|
4887
|
+
return /\bNo such tool available\b/i.test(`${summary}\n${content}`);
|
|
4888
|
+
}
|
|
4877
4889
|
/**
|
|
4878
4890
|
* 创建 Chat 流式对话 + 历史查询路由
|
|
4879
4891
|
*
|
|
@@ -5194,10 +5206,11 @@ function createChatRouter(config) {
|
|
|
5194
5206
|
recordRunEvent(run, "thinking-delta");
|
|
5195
5207
|
broadcastRunEvent(run, "thinking-delta", { text });
|
|
5196
5208
|
},
|
|
5197
|
-
onToolUseStart: (toolName, toolInput) => {
|
|
5209
|
+
onToolUseStart: (toolName, toolInput, toolUseId) => {
|
|
5198
5210
|
if (run.status !== "running") return;
|
|
5199
5211
|
recordRunEvent(run, "tool-use-start", { toolName });
|
|
5200
5212
|
if (runtimeConfig.requestContext) logChatAudit(buildAuditEvent(runtimeConfig.requestContext, "tool_call_started", {
|
|
5213
|
+
toolCallId: toolUseId,
|
|
5201
5214
|
toolName,
|
|
5202
5215
|
inputSummary: summarizeForAudit(toolInput)
|
|
5203
5216
|
}));
|
|
@@ -5215,11 +5228,13 @@ function createChatRouter(config) {
|
|
|
5215
5228
|
traceId,
|
|
5216
5229
|
scenarioId,
|
|
5217
5230
|
runtimeEventType: "tool-use-start",
|
|
5231
|
+
toolCallId: toolUseId,
|
|
5218
5232
|
toolName
|
|
5219
5233
|
}
|
|
5220
5234
|
}, "[stream] 保存 tool 消息失败");
|
|
5221
5235
|
broadcastRunEvent(run, "tool-use-start", {
|
|
5222
5236
|
toolName,
|
|
5237
|
+
toolUseId,
|
|
5223
5238
|
input: toolInput
|
|
5224
5239
|
});
|
|
5225
5240
|
},
|
|
@@ -5229,7 +5244,8 @@ function createChatRouter(config) {
|
|
|
5229
5244
|
const resultSummary = summarizeForAudit(result);
|
|
5230
5245
|
const toolName = readStringField(result, "toolName") || run.lastToolName;
|
|
5231
5246
|
const isError = readBooleanField(result, "isError");
|
|
5232
|
-
if (isError) run.lastToolError = resultSummary;
|
|
5247
|
+
if (isError && !isUnknownToolResult(result)) run.lastToolError = resultSummary;
|
|
5248
|
+
else if (!isError) run.lastToolError = void 0;
|
|
5233
5249
|
if (runtimeConfig.requestContext) logChatAudit(buildAuditEvent(runtimeConfig.requestContext, "tool_call_finished", {
|
|
5234
5250
|
toolCallId: toolUseId,
|
|
5235
5251
|
toolName,
|
|
@@ -5267,12 +5283,6 @@ function createChatRouter(config) {
|
|
|
5267
5283
|
if (run.status !== "running") return;
|
|
5268
5284
|
run.unknownToolCallCount = (run.unknownToolCallCount ?? 0) + 1;
|
|
5269
5285
|
run.lastUnknownToolName = toolName;
|
|
5270
|
-
run.lastToolError = {
|
|
5271
|
-
isError: true,
|
|
5272
|
-
reasonCode: "UNKNOWN_TOOL_CALL",
|
|
5273
|
-
toolName,
|
|
5274
|
-
toolCallId: toolUseId
|
|
5275
|
-
};
|
|
5276
5286
|
recordRunEvent(run, "unknown-tool-use", { toolName });
|
|
5277
5287
|
broadcastRunEvent(run, "runtime-event", {
|
|
5278
5288
|
type: "unknown-tool-use",
|
|
@@ -5298,8 +5308,14 @@ function createChatRouter(config) {
|
|
|
5298
5308
|
onResult: async (result) => {
|
|
5299
5309
|
if (run.status !== "running") return;
|
|
5300
5310
|
recordRunEvent(run, "result");
|
|
5301
|
-
|
|
5311
|
+
let normalizedResult = normalizeRuntimeResult(result);
|
|
5302
5312
|
const partialText = run.text.trim() ? run.text : void 0;
|
|
5313
|
+
if (shouldTreatUnknownToolErrorAsRecovered(run, normalizedResult, result)) normalizedResult = {
|
|
5314
|
+
status: "completed",
|
|
5315
|
+
finalStatus: "completed_with_warnings",
|
|
5316
|
+
isError: false,
|
|
5317
|
+
finalText: partialText || result.result
|
|
5318
|
+
};
|
|
5303
5319
|
const finalText = normalizedResult.isError ? normalizedResult.finalText || partialText || "" : partialText || normalizedResult.finalText || "";
|
|
5304
5320
|
run.text = finalText;
|
|
5305
5321
|
run.runtimeError = normalizedResult.error;
|
|
@@ -7794,13 +7810,17 @@ const sessionNoReplyFlags = /* @__PURE__ */ new Map();
|
|
|
7794
7810
|
/** TTL: 30 分钟 */
|
|
7795
7811
|
const TTL_MS = 1800 * 1e3;
|
|
7796
7812
|
/** 定期清理过期的 pending requests(每 5 分钟检查一次) */
|
|
7797
|
-
|
|
7813
|
+
function cleanupExpiredPendingRequests() {
|
|
7798
7814
|
const now = Date.now();
|
|
7799
7815
|
let cleaned = 0;
|
|
7800
7816
|
for (const [id, req] of pendingRequests) if (now - req.createdAt > TTL_MS) {
|
|
7801
7817
|
pendingRequests.delete(id);
|
|
7802
7818
|
cleaned++;
|
|
7803
7819
|
}
|
|
7820
|
+
return cleaned;
|
|
7821
|
+
}
|
|
7822
|
+
setInterval(() => {
|
|
7823
|
+
const cleaned = cleanupExpiredPendingRequests();
|
|
7804
7824
|
if (cleaned > 0) logger$4.info("TTL cleanup completed", {
|
|
7805
7825
|
cleaned,
|
|
7806
7826
|
remaining: pendingRequests.size
|
|
@@ -7811,7 +7831,7 @@ setInterval(() => {
|
|
|
7811
7831
|
* 事件名: `callback:${sessionId}`,payload 为 PendingMcpRequest。
|
|
7812
7832
|
* 用于 dispatch-cc 订阅并在收到 ask_user/request_permission 回调时发送飞书卡片。
|
|
7813
7833
|
*/
|
|
7814
|
-
const onMcpCallback = new EventEmitter
|
|
7834
|
+
const onMcpCallback = new EventEmitter();
|
|
7815
7835
|
onMcpCallback.setMaxListeners(100);
|
|
7816
7836
|
/**
|
|
7817
7837
|
* 将 result 存入对应的 pending request
|
|
@@ -7943,6 +7963,25 @@ function createMcpCallbackRouter() {
|
|
|
7943
7963
|
requestId
|
|
7944
7964
|
});
|
|
7945
7965
|
});
|
|
7966
|
+
router.get("/pending", (req, res) => {
|
|
7967
|
+
const sessionId = typeof req.query.session_id === "string" ? req.query.session_id : typeof req.query.sessionId === "string" ? req.query.sessionId : void 0;
|
|
7968
|
+
const cleaned = cleanupExpiredPendingRequests();
|
|
7969
|
+
const now = Date.now();
|
|
7970
|
+
const requests = [...pendingRequests.values()].filter((pending) => pending.result === void 0).filter((pending) => !sessionId || pending.sessionId === sessionId).map((pending) => ({
|
|
7971
|
+
requestId: pending.requestId,
|
|
7972
|
+
tool: pending.tool,
|
|
7973
|
+
sessionId: pending.sessionId,
|
|
7974
|
+
params: pending.params,
|
|
7975
|
+
createdAt: pending.createdAt,
|
|
7976
|
+
waitingMs: now - pending.createdAt
|
|
7977
|
+
}));
|
|
7978
|
+
logger$4.debug("pending requests listed", {
|
|
7979
|
+
sessionId,
|
|
7980
|
+
count: requests.length,
|
|
7981
|
+
cleaned
|
|
7982
|
+
});
|
|
7983
|
+
res.json({ requests });
|
|
7984
|
+
});
|
|
7946
7985
|
router.get("/resolve/:requestId", (req, res) => {
|
|
7947
7986
|
const requestId = req.params.requestId;
|
|
7948
7987
|
logger$4.debug("resolve poll", { requestId });
|