@vibe-lark/larkpal 0.1.81 → 0.1.83

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.
Files changed (2) hide show
  1. package/dist/main.mjs +52 -17
  2. package/package.json +1 -1
package/dist/main.mjs CHANGED
@@ -893,7 +893,7 @@ var CCStreamParser = class extends EventEmitter {
893
893
  displayName: getToolDisplayName(block.name),
894
894
  toolUseId: block.id
895
895
  });
896
- this.emit("toolUseStart", block.name, block.input ?? {});
896
+ this.emit("toolUseStart", block.name, block.input ?? {}, block.id);
897
897
  }
898
898
  break;
899
899
  }
@@ -941,7 +941,7 @@ var CCStreamParser = class extends EventEmitter {
941
941
  displayName: getToolDisplayName(block.name),
942
942
  toolUseId: block.id
943
943
  });
944
- this.emit("toolUseStart", block.name, block.input ?? {});
944
+ this.emit("toolUseStart", block.name, block.input ?? {}, block.id);
945
945
  }
946
946
  }
947
947
  this.emit("assistant", msg);
@@ -1756,8 +1756,8 @@ var SessionProcessManager = class {
1756
1756
  }
1757
1757
  getCallbacks()?.onThinkingDelta?.(text);
1758
1758
  });
1759
- parser.on("toolUseStart", (toolName, toolInput) => {
1760
- getCallbacks()?.onToolUseStart?.(toolName, toolInput);
1759
+ parser.on("toolUseStart", (toolName, toolInput, toolUseId) => {
1760
+ getCallbacks()?.onToolUseStart?.(toolName, toolInput, toolUseId);
1761
1761
  });
1762
1762
  parser.on("toolResult", (toolUseId, result) => {
1763
1763
  getCallbacks()?.onToolResult?.(toolUseId, result);
@@ -4473,10 +4473,13 @@ async function reconcileRunWithAdapter(run, messageStore, processManager) {
4473
4473
  } else if (idleMs >= getStaleRunIdleMs()) staleReason = `run idle for ${Math.floor(idleMs / 1e3)}s`;
4474
4474
  if (!staleReason) return;
4475
4475
  let cleanupRequired = false;
4476
- if (!adapterBusy && (processInfo?.status === "running" || processInfo?.status === "starting")) {
4476
+ if (processInfo?.status === "running" || processInfo?.status === "starting") {
4477
4477
  cleanupRequired = true;
4478
4478
  try {
4479
4479
  await processManager.stopProcess(run.sessionId);
4480
+ const stoppedInfo = processManager.getProcessInfo(run.sessionId);
4481
+ run.adapterBusy = processManager.isSessionBusy?.(run.sessionId) ?? false;
4482
+ run.processStatus = stoppedInfo?.status ?? "stopped";
4480
4483
  log$30.warn("[stream] stale run 已触发 runtime process 清理", {
4481
4484
  sessionId: run.sessionId,
4482
4485
  runId: run.runId,
@@ -4516,6 +4519,16 @@ async function reconcileRunWithAdapter(run, messageStore, processManager) {
4516
4519
  endRunClients(run);
4517
4520
  }
4518
4521
  }
4522
+ async function reconcileActiveChatRuns(messageStore, processManager, sessionIds) {
4523
+ const targetSessionIds = sessionIds ? new Set(sessionIds) : void 0;
4524
+ const tasks = [];
4525
+ for (const run of chatRunsBySession.values()) {
4526
+ if (run.status !== "running") continue;
4527
+ if (targetSessionIds && !targetSessionIds.has(run.sessionId)) continue;
4528
+ tasks.push(reconcileRunWithAdapter(run, messageStore, processManager));
4529
+ }
4530
+ await Promise.all(tasks);
4531
+ }
4519
4532
  function buildRuntimeEventMessageMetadata(event, runtimeConfig) {
4520
4533
  return {
4521
4534
  runtimeEventType: event.type,
@@ -4778,6 +4791,14 @@ function normalizeRuntimeResult(result) {
4778
4791
  error
4779
4792
  };
4780
4793
  }
4794
+ function shouldTreatUnknownToolErrorAsRecovered(run, normalizedResult, result) {
4795
+ if (!normalizedResult.isError || normalizedResult.finalStatus !== "error_during_execution") return false;
4796
+ if (!run.unknownToolCallCount || run.lastToolError !== void 0) return false;
4797
+ if (!run.lastToolName || run.lastToolName === run.lastUnknownToolName) return false;
4798
+ const terminalText = normalizeWhitespace(result.result || "");
4799
+ if (terminalText && /\bNo such tool available\b/i.test(terminalText)) return false;
4800
+ return Boolean(run.text.trim() || terminalText);
4801
+ }
4781
4802
  function buildRuntimeErrorSummary(subtype, result) {
4782
4803
  const message = normalizeWhitespace(result || `Runtime execution failed: ${subtype}`);
4783
4804
  const httpStatus = extractHttpStatus(message);
@@ -4873,6 +4894,11 @@ function readBooleanField(value, key) {
4873
4894
  const field = value[key];
4874
4895
  return typeof field === "boolean" ? field : void 0;
4875
4896
  }
4897
+ function isUnknownToolResult(result) {
4898
+ const summary = readStringField(result, "resultSummary") ?? "";
4899
+ const content = readStringField(result, "content") ?? "";
4900
+ return /\bNo such tool available\b/i.test(`${summary}\n${content}`);
4901
+ }
4876
4902
  /**
4877
4903
  * 创建 Chat 流式对话 + 历史查询路由
4878
4904
  *
@@ -5193,10 +5219,11 @@ function createChatRouter(config) {
5193
5219
  recordRunEvent(run, "thinking-delta");
5194
5220
  broadcastRunEvent(run, "thinking-delta", { text });
5195
5221
  },
5196
- onToolUseStart: (toolName, toolInput) => {
5222
+ onToolUseStart: (toolName, toolInput, toolUseId) => {
5197
5223
  if (run.status !== "running") return;
5198
5224
  recordRunEvent(run, "tool-use-start", { toolName });
5199
5225
  if (runtimeConfig.requestContext) logChatAudit(buildAuditEvent(runtimeConfig.requestContext, "tool_call_started", {
5226
+ toolCallId: toolUseId,
5200
5227
  toolName,
5201
5228
  inputSummary: summarizeForAudit(toolInput)
5202
5229
  }));
@@ -5214,11 +5241,13 @@ function createChatRouter(config) {
5214
5241
  traceId,
5215
5242
  scenarioId,
5216
5243
  runtimeEventType: "tool-use-start",
5244
+ toolCallId: toolUseId,
5217
5245
  toolName
5218
5246
  }
5219
5247
  }, "[stream] 保存 tool 消息失败");
5220
5248
  broadcastRunEvent(run, "tool-use-start", {
5221
5249
  toolName,
5250
+ toolUseId,
5222
5251
  input: toolInput
5223
5252
  });
5224
5253
  },
@@ -5228,7 +5257,8 @@ function createChatRouter(config) {
5228
5257
  const resultSummary = summarizeForAudit(result);
5229
5258
  const toolName = readStringField(result, "toolName") || run.lastToolName;
5230
5259
  const isError = readBooleanField(result, "isError");
5231
- if (isError) run.lastToolError = resultSummary;
5260
+ if (isError && !isUnknownToolResult(result)) run.lastToolError = resultSummary;
5261
+ else if (!isError) run.lastToolError = void 0;
5232
5262
  if (runtimeConfig.requestContext) logChatAudit(buildAuditEvent(runtimeConfig.requestContext, "tool_call_finished", {
5233
5263
  toolCallId: toolUseId,
5234
5264
  toolName,
@@ -5266,12 +5296,6 @@ function createChatRouter(config) {
5266
5296
  if (run.status !== "running") return;
5267
5297
  run.unknownToolCallCount = (run.unknownToolCallCount ?? 0) + 1;
5268
5298
  run.lastUnknownToolName = toolName;
5269
- run.lastToolError = {
5270
- isError: true,
5271
- reasonCode: "UNKNOWN_TOOL_CALL",
5272
- toolName,
5273
- toolCallId: toolUseId
5274
- };
5275
5299
  recordRunEvent(run, "unknown-tool-use", { toolName });
5276
5300
  broadcastRunEvent(run, "runtime-event", {
5277
5301
  type: "unknown-tool-use",
@@ -5297,8 +5321,14 @@ function createChatRouter(config) {
5297
5321
  onResult: async (result) => {
5298
5322
  if (run.status !== "running") return;
5299
5323
  recordRunEvent(run, "result");
5300
- const normalizedResult = normalizeRuntimeResult(result);
5324
+ let normalizedResult = normalizeRuntimeResult(result);
5301
5325
  const partialText = run.text.trim() ? run.text : void 0;
5326
+ if (shouldTreatUnknownToolErrorAsRecovered(run, normalizedResult, result)) normalizedResult = {
5327
+ status: "completed",
5328
+ finalStatus: "completed_with_warnings",
5329
+ isError: false,
5330
+ finalText: partialText || result.result
5331
+ };
5302
5332
  const finalText = normalizedResult.isError ? normalizedResult.finalText || partialText || "" : partialText || normalizedResult.finalText || "";
5303
5333
  run.text = finalText;
5304
5334
  run.runtimeError = normalizedResult.error;
@@ -8486,6 +8516,7 @@ function createStatusRouter(config) {
8486
8516
  const sessionsDir = getWorkspaceChatsRoot(config?.workspaceRoot ?? resolveWorkspaceRoot("/workspace"));
8487
8517
  const processManager = config?.processManager;
8488
8518
  const messageStore = config?.messageStore;
8519
+ const reconcileActiveRuns = config?.reconcileActiveRuns;
8489
8520
  router.get("/sessions", async (req, res) => {
8490
8521
  logger$2.info("list sessions request", {
8491
8522
  method: req.method,
@@ -8586,7 +8617,7 @@ function createStatusRouter(config) {
8586
8617
  try {
8587
8618
  const uptimeSeconds = process.uptime();
8588
8619
  const memory = process.memoryUsage();
8589
- const { processes, diagnostics } = processManager ? await serializeRuntimeProcesses(processManager, messageStore) : {
8620
+ const { processes, diagnostics } = processManager ? await serializeRuntimeProcesses(processManager, messageStore, reconcileActiveRuns) : {
8590
8621
  processes: [],
8591
8622
  diagnostics: []
8592
8623
  };
@@ -8643,9 +8674,11 @@ function createStatusRouter(config) {
8643
8674
  });
8644
8675
  return router;
8645
8676
  }
8646
- async function serializeRuntimeProcesses(processManager, messageStore) {
8677
+ async function serializeRuntimeProcesses(processManager, messageStore, reconcileActiveRuns) {
8647
8678
  const processes = [];
8648
8679
  const diagnostics = [];
8680
+ const processSnapshot = processManager.getAllProcessInfo();
8681
+ if (reconcileActiveRuns) await reconcileActiveRuns(processSnapshot.map((processInfo) => processInfo.sessionId));
8649
8682
  for (const processInfo of processManager.getAllProcessInfo()) {
8650
8683
  const busy = processManager.isSessionBusy?.(processInfo.sessionId) ?? processInfo.status === "running";
8651
8684
  const terminalRunStatus = messageStore ? await getLatestTerminalRunStatus(messageStore, processInfo.sessionId) : null;
@@ -8678,6 +8711,7 @@ async function serializeRuntimeProcesses(processManager, messageStore) {
8678
8711
  });
8679
8712
  continue;
8680
8713
  }
8714
+ if (terminalRunStatus && !busy && (processInfo.status === "stopped" || processInfo.status === "crashed" || processInfo.status === "stopping")) continue;
8681
8715
  processes.push(serializeRuntimeProcess(processInfo, processManager));
8682
8716
  }
8683
8717
  return {
@@ -8784,7 +8818,8 @@ function registerRoutes(app, processManager, scheduledTaskManager, appCredential
8784
8818
  app.use("/api", createStatusRouter({
8785
8819
  workspaceRoot,
8786
8820
  processManager,
8787
- messageStore
8821
+ messageStore,
8822
+ reconcileActiveRuns: processManager && messageStore ? (sessionIds) => reconcileActiveChatRuns(messageStore, processManager, sessionIds) : void 0
8788
8823
  }));
8789
8824
  app.use("/hooks", createHooksRouter());
8790
8825
  app.use("/api/mcp", createMcpCallbackRouter());
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vibe-lark/larkpal",
3
- "version": "0.1.81",
3
+ "version": "0.1.83",
4
4
  "description": "LarkPal - Lark/Feishu bot service",
5
5
  "type": "module",
6
6
  "main": "./dist/main.mjs",