duclaw-cli 1.9.14 → 1.9.16

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/bundle.js CHANGED
@@ -30242,7 +30242,7 @@ function printHelp() {
30242
30242
  `);
30243
30243
  }
30244
30244
  function printVersion() {
30245
- console.log(`duclaw-cli v${true ? "1.9.14" : "unknown"}`);
30245
+ console.log(`duclaw-cli v${true ? "1.9.16" : "unknown"}`);
30246
30246
  }
30247
30247
  function getDuclawTemplate() {
30248
30248
  return {
@@ -38854,13 +38854,13 @@ var searchChatHistory = async (messageStorage, topicStorage, userId, query, date
38854
38854
  return { matches: [], total, matchCount: 0 };
38855
38855
  }
38856
38856
  const keyCache = /* @__PURE__ */ new Map();
38857
- const buildKey = (d, c) => {
38857
+ const buildKey2 = (d, c) => {
38858
38858
  let k = `mem:${userId}:${d}`;
38859
38859
  if (c) k += `:${c}`;
38860
38860
  return k;
38861
38861
  };
38862
38862
  const loadMessages = async (d, c) => {
38863
- const k = buildKey(d, c);
38863
+ const k = buildKey2(d, c);
38864
38864
  if (keyCache.has(k)) return keyCache.get(k);
38865
38865
  const msgs = await messageStorage.get(k);
38866
38866
  keyCache.set(k, msgs);
@@ -41823,6 +41823,7 @@ var controlPlaneBaseUrl = () => {
41823
41823
  return process.env.DUCLAW_CONTROL_PLANE_BASE_URL?.replace(/\/$/, "");
41824
41824
  };
41825
41825
  var USER_IMAGE_REUPLOAD_MESSAGE = `\u8FD9\u5F20\u56FE\u7247\u6682\u65F6\u65E0\u6CD5\u6309\u56FE\u7247\u683C\u5F0F\u89E3\u6790\u3002\u8BF7\u91CD\u65B0\u53D1\u9001 JPG/PNG/WebP \u56FE\u7247\uFF0C\u6216\u8005\u5728\u624B\u673A\u4E0A\u622A\u56FE\u540E\u518D\u53D1\u4E00\u6B21\u3002`;
41826
+ var USER_IMAGE_UNDERSTAND_CREDIT_EXHAUSTED_MESSAGE = `Credit \u4F59\u989D\u4E0D\u8DB3\uFF0C\u65E0\u6CD5\u5B8C\u6210\u672C\u6B21\u56FE\u7247\u7406\u89E3\u3002\u8BF7\u5148\u5145\u503C\u6216\u4F7F\u7528\u6FC0\u6D3B\u7801\u589E\u52A0 Credit\u3002`;
41826
41827
  var normalizeRuntimeAttachmentUrl = (input) => {
41827
41828
  return input.replace("/api/mobile/attachments/", "/internal/runtime/mobile/attachments/");
41828
41829
  };
@@ -41958,6 +41959,15 @@ var imageUnderstand = {
41958
41959
  providerResponseId: response.providerResponseId,
41959
41960
  authStyle,
41960
41961
  userRequest
41962
+ }).catch((error) => {
41963
+ if (error instanceof ImageUnderstandMeteringError && (error.meteringStatus === "credit_exhausted" || error.statusCode === 402)) {
41964
+ throw new UserRecoverableToolError(
41965
+ "credit_exhausted",
41966
+ USER_IMAGE_UNDERSTAND_CREDIT_EXHAUSTED_MESSAGE,
41967
+ error.message
41968
+ );
41969
+ }
41970
+ throw error;
41961
41971
  });
41962
41972
  return resultText;
41963
41973
  }
@@ -43642,6 +43652,45 @@ var departmentCreate = {
43642
43652
  }
43643
43653
  };
43644
43654
 
43655
+ // src/tools/tools/department/mailboxQueueGuard.ts
43656
+ var states = /* @__PURE__ */ new Map();
43657
+ var buildKey = (userRequest) => {
43658
+ const mailboxId = userRequest?.departmentAgentId;
43659
+ const requestId = userRequest?.requestId;
43660
+ if (!mailboxId || !requestId) return null;
43661
+ return `${mailboxId}::${requestId}`;
43662
+ };
43663
+ var sameMessageSet = (left, right) => {
43664
+ if (left.length !== right.length) return false;
43665
+ const sortedLeft = [...left].sort();
43666
+ const sortedRight = [...right].sort();
43667
+ return sortedLeft.every((id, index) => id === sortedRight[index]);
43668
+ };
43669
+ var beginMailboxListOrBlock = (userRequest, visibleMessageIds) => {
43670
+ const key = buildKey(userRequest);
43671
+ if (!key) return null;
43672
+ const previous = states.get(key);
43673
+ if (previous?.awaitingAction && sameMessageSet(previous.listedMessageIds, visibleMessageIds)) {
43674
+ return [
43675
+ `[listMailbox] \u5DF2\u963B\u6B62\u91CD\u590D\u67E5\u770B\u540C\u4E00\u6279\u90AE\u7BB1\u961F\u5217\u3002`,
43676
+ `\u4F60\u521A\u521A\u5DF2\u7ECF\u770B\u8FC7\u8FD9\u4E9B\u5F85\u5904\u7406 message_id: ${visibleMessageIds.join(", ") || "-"}`,
43677
+ `\u7981\u6B62\u7A7A\u8F6C list_mailbox\u3002\u4E0B\u4E00\u6B65\u5FC5\u987B\u9009\u62E9\u4E00\u5C01\u8C03\u7528 get_mailbox(message_id="...") \u6253\u5F00\u5904\u7406\uFF0C\u6216\u5BF9\u65E0\u9700\u5904\u7406\u7684\u90AE\u4EF6\u8C03\u7528 discard_mailbox\uFF0C\u6216\u5BF9\u5DF2\u5F62\u6210\u8FDB\u5C55/\u7ED3\u679C\u7684\u90AE\u4EF6\u8C03\u7528 mailbox_followup / reply_mailbox\u3002`,
43678
+ `\u5B8C\u6210\u4E00\u4E2A\u5B9E\u9645\u52A8\u4F5C\u540E\uFF0C\u624D\u53EF\u4EE5\u518D\u6B21\u8C03\u7528 list_mailbox \u91CD\u65B0\u8BC4\u4F30\u961F\u5217\u3002`
43679
+ ].join(`
43680
+ `);
43681
+ }
43682
+ states.set(key, {
43683
+ awaitingAction: visibleMessageIds.length > 0,
43684
+ listedMessageIds: visibleMessageIds
43685
+ });
43686
+ return null;
43687
+ };
43688
+ var markMailboxQueueAction = (userRequest) => {
43689
+ const key = buildKey(userRequest);
43690
+ if (!key) return;
43691
+ states.delete(key);
43692
+ };
43693
+
43645
43694
  // src/tools/tools/department/DepartmentCommunicate.ts
43646
43695
  var CEO_MAILBOX_ID = `manager`;
43647
43696
  var MANAGER_ALIAS_PATTERN = /(^|::)(manager|main[-_\s]?manager|ceo)$/i;
@@ -43795,6 +43844,9 @@ var departmentCommunicate = {
43795
43844
  } catch (err) {
43796
43845
  return `[departmentCommunicate] \u53D1\u9001\u6D88\u606F\u5931\u8D25: ${err.message}`;
43797
43846
  }
43847
+ if (departmentAgentId) {
43848
+ markMailboxQueueAction(userRequest);
43849
+ }
43798
43850
  return `[departmentCommunicate] \u6D88\u606F\u5DF2\u53D1\u9001\u5230 ${toMailboxId}`;
43799
43851
  }
43800
43852
  };
@@ -44845,6 +44897,7 @@ var mailboxFollowup = {
44845
44897
  preview: content.slice(0, 200)
44846
44898
  }
44847
44899
  });
44900
+ markMailboxQueueAction(userRequest);
44848
44901
  return `[mailboxFollowup] \u5DF2\u5728\u6D88\u606F ${messageId} \u6240\u5C5E\u7EBF\u7A0B\u4E2D\u8FFD\u52A0\u4E00\u6761${kind}\u6D88\u606F\uFF0C\u53D1\u9001\u5230 ${counterpartMailboxId}\uFF08message: ${followupMsg.id}, thread: ${followupMsg.threadId}\uFF09`;
44849
44902
  }
44850
44903
  };
@@ -45366,12 +45419,11 @@ var createSaasCreditToolHookPlugin = () => ({
45366
45419
  toolCallId: ctx.toolCallId,
45367
45420
  requestId: ctx.userRequest?.requestId ?? null,
45368
45421
  occurredAt: (/* @__PURE__ */ new Date()).toISOString(),
45369
- ...usage,
45370
- metadata: {
45371
- platform: ctx.userRequest?.platform ?? null,
45372
- departmentAgentId: ctx.userRequest?.departmentAgentId ?? null,
45373
- input: sanitizedWebSearchInput(ctx.input)
45374
- }
45422
+ meterType: usage.meterType,
45423
+ provider: usage.provider,
45424
+ unit: usage.unit,
45425
+ quantity: usage.quantity,
45426
+ metadata: usage.metadata
45375
45427
  })
45376
45428
  });
45377
45429
  const body = await parseJson2(response);
@@ -45379,7 +45431,7 @@ var createSaasCreditToolHookPlugin = () => ({
45379
45431
  if (response.status === 402 || status === "credit_exhausted") {
45380
45432
  throw new UserRecoverableToolError(
45381
45433
  "credit_exhausted",
45382
- "Credit \u4F59\u989D\u4E0D\u8DB3\uFF0C\u65E0\u6CD5\u5B8C\u6210\u672C\u6B21\u7F51\u9875\u641C\u7D22\u3002\u8BF7\u5148\u5145\u503C\u6216\u4F7F\u7528\u6FC0\u6D3B\u7801\u589E\u52A0 Credit\u3002",
45434
+ usage.userMessage,
45383
45435
  `[saas-credit] ${ctx.toolName} credit exhausted`
45384
45436
  );
45385
45437
  }
@@ -45389,14 +45441,27 @@ var createSaasCreditToolHookPlugin = () => ({
45389
45441
  }
45390
45442
  });
45391
45443
  function meteredToolUsage(ctx) {
45392
- if (ctx.toolName !== "websearch") return null;
45393
- if (isWebSearchErrorResult(ctx.resultText)) return null;
45394
- return {
45395
- meterType: "web.content_retrieval",
45396
- provider: "exa",
45397
- unit: "content",
45398
- quantity: normalizeNumResults(ctx.input.numResults)
45399
- };
45444
+ if (ctx.toolName === "websearch") {
45445
+ if (isWebSearchErrorResult(ctx.resultText)) return null;
45446
+ return {
45447
+ meterType: "web.content_retrieval",
45448
+ provider: "exa",
45449
+ unit: "content",
45450
+ quantity: normalizeNumResults(ctx.input.numResults),
45451
+ userMessage: "Credit \u4F59\u989D\u4E0D\u8DB3\uFF0C\u65E0\u6CD5\u5B8C\u6210\u672C\u6B21\u7F51\u9875\u641C\u7D22\u3002\u8BF7\u5148\u5145\u503C\u6216\u4F7F\u7528\u6FC0\u6D3B\u7801\u589E\u52A0 Credit\u3002",
45452
+ metadata: {
45453
+ platform: ctx.userRequest?.platform ?? null,
45454
+ departmentAgentId: ctx.userRequest?.departmentAgentId ?? null,
45455
+ input: sanitizedWebSearchInput(ctx.input)
45456
+ }
45457
+ };
45458
+ }
45459
+ if (ctx.toolName === "image_generate") {
45460
+ const usage = imageGenerateUsage(ctx);
45461
+ if (!usage) return null;
45462
+ return usage;
45463
+ }
45464
+ return null;
45400
45465
  }
45401
45466
  function normalizeNumResults(value) {
45402
45467
  if (typeof value !== "number" || !Number.isFinite(value)) return DEFAULT_WEB_SEARCH_NUM_RESULTS;
@@ -45415,6 +45480,37 @@ function sanitizedWebSearchInput(input) {
45415
45480
  contextMaxCharacters: typeof input.contextMaxCharacters === "number" ? input.contextMaxCharacters : null
45416
45481
  };
45417
45482
  }
45483
+ function imageGenerateUsage(ctx) {
45484
+ const result = parseResultJson(ctx.resultText);
45485
+ if (!result || result.ok !== true) return null;
45486
+ const savedFiles = Array.isArray(result.savedFiles) ? result.savedFiles : [];
45487
+ const quantity = savedFiles.length > 0 ? savedFiles.length : 1;
45488
+ return {
45489
+ meterType: "image.generate",
45490
+ provider: "shanyi",
45491
+ unit: "image",
45492
+ quantity,
45493
+ userMessage: "Credit \u4F59\u989D\u4E0D\u8DB3\uFF0C\u65E0\u6CD5\u751F\u6210\u56FE\u7247\u3002\u751F\u6210\u56FE\u7247\u6BCF\u5F20\u9700\u8981 20 Credit\uFF08\u7EA6 0.2 \u5143\uFF09\uFF0C\u8BF7\u5148\u5145\u503C\u6216\u4F7F\u7528\u6FC0\u6D3B\u7801\u589E\u52A0 Credit\u3002",
45494
+ metadata: {
45495
+ platform: ctx.userRequest?.platform ?? null,
45496
+ departmentAgentId: ctx.userRequest?.departmentAgentId ?? null,
45497
+ model: typeof result.model === "string" ? result.model : null,
45498
+ size: typeof result.size === "string" ? result.size : null,
45499
+ resolution: typeof result.resolution === "string" ? result.resolution : null,
45500
+ requestId: typeof result.requestId === "string" ? result.requestId : null,
45501
+ prompt: typeof ctx.input.prompt === "string" ? ctx.input.prompt.slice(0, 500) : null
45502
+ }
45503
+ };
45504
+ }
45505
+ function parseResultJson(value) {
45506
+ if (!value) return null;
45507
+ try {
45508
+ const parsed = JSON.parse(value);
45509
+ return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : null;
45510
+ } catch {
45511
+ return null;
45512
+ }
45513
+ }
45418
45514
  async function parseJson2(response) {
45419
45515
  try {
45420
45516
  return await response.json();
@@ -46971,6 +47067,16 @@ var llmRequestIdForTurn = (request, messages, system, tools) => {
46971
47067
  const hash = (0, import_node_crypto16.createHash)("sha256").update(request.requestId).update("\0").update(system).update("\0").update(JSON.stringify(messages)).update("\0").update(JSON.stringify(tools.map((tool) => tool.name).sort())).digest("hex").slice(0, 40);
46972
47068
  return `dreq_${hash}`;
46973
47069
  };
47070
+ var LLM_CREDIT_EXHAUSTED_MESSAGE = "Credit \u4F59\u989D\u4E0D\u8DB3\uFF0C\u6682\u65F6\u65E0\u6CD5\u7EE7\u7EED\u8C03\u7528\u4E3B\u6A21\u578B\u5904\u7406\u8FD9\u6761\u6D88\u606F\u3002\u8BF7\u5148\u5145\u503C\u6216\u4F7F\u7528\u6FC0\u6D3B\u7801\u589E\u52A0 Credit \u540E\u518D\u8BD5\u3002";
47071
+ var isLlmCreditExhaustedError = (error) => {
47072
+ const err = error;
47073
+ const message = [
47074
+ err?.message,
47075
+ err?.error?.type,
47076
+ err?.error?.message
47077
+ ].filter((value) => typeof value === "string").join("\n");
47078
+ return err?.status === 402 || err?.status === 403 && /预扣费额度失败|额度不足|剩余额度|pre_consume.*quota|insufficient.*quota/i.test(message) || /预扣费额度失败|用户剩余额度|Credit balance is insufficient|credit_exhausted/i.test(message);
47079
+ };
46974
47080
  var getDefaultAgentConfig = (tools, systemPrompt) => {
46975
47081
  loadEnv();
46976
47082
  (0, import_node_fs8.mkdirSync)(DEFAULT_WORKSPACE_PATH, { recursive: true });
@@ -47526,6 +47632,29 @@ ${memoryInjection}` : "") + dreamInjection;
47526
47632
  await recoverFromContextOverflow("prompt_too_long", messages, effectiveSystemPrompt);
47527
47633
  continue;
47528
47634
  }
47635
+ if (isLlmCreditExhaustedError(error)) {
47636
+ let alreadySent = false;
47637
+ if (config2.channelPlugin && !internalOnly) {
47638
+ if (claimOutboundSend(request.userId, LLM_CREDIT_EXHAUSTED_MESSAGE)) {
47639
+ await config2.channelPlugin.outbound.sendText({
47640
+ cfg: {},
47641
+ to: request.userId,
47642
+ text: LLM_CREDIT_EXHAUSTED_MESSAGE,
47643
+ accountId: request.requestId,
47644
+ metadata: request.metadata
47645
+ });
47646
+ alreadySent = true;
47647
+ } else {
47648
+ console.log(`[outbound-dedup] \u8DF3\u8FC7\u5BF9\u7528\u6237 ${request.userId} \u7684\u8FD1\u91CD\u590D LLM \u989D\u5EA6\u4E0D\u8DB3\u63D0\u793A`);
47649
+ }
47650
+ }
47651
+ await addMessage(storage, userId, assistantMessage(text(LLM_CREDIT_EXHAUSTED_MESSAGE)), beijingTime, job?.title);
47652
+ markAgentEventsHandled([...injectedEventIds], "ignored");
47653
+ return {
47654
+ content: LLM_CREDIT_EXHAUSTED_MESSAGE,
47655
+ alreadySent
47656
+ };
47657
+ }
47529
47658
  throw error;
47530
47659
  } finally {
47531
47660
  if (activeTurnAbortController === turnAbortController) {
@@ -48075,6 +48204,11 @@ var listMailbox = {
48075
48204
  ORDER BY send_time ASC`
48076
48205
  );
48077
48206
  const msgs = stmt.all(myMailboxId);
48207
+ const visibleMessageIds = msgs.map((msg) => msg.id);
48208
+ const repeatedListBlock = beginMailboxListOrBlock(userRequest, visibleMessageIds);
48209
+ if (repeatedListBlock) {
48210
+ return repeatedListBlock;
48211
+ }
48078
48212
  if (msgs.length === 0) {
48079
48213
  recordMailboxEvent({
48080
48214
  mailboxId: myMailboxId,
@@ -48082,7 +48216,7 @@ var listMailbox = {
48082
48216
  eventType: "mailbox_listed",
48083
48217
  detail: {
48084
48218
  visibleCount: 0,
48085
- visibleMessageIds: []
48219
+ visibleMessageIds
48086
48220
  }
48087
48221
  });
48088
48222
  return `[listMailbox] \u4F60\u7684\u90AE\u7BB1\u4E2D\u6CA1\u6709\u5F85\u5904\u7406\u90AE\u4EF6\u3002`;
@@ -48094,10 +48228,10 @@ var listMailbox = {
48094
48228
  eventType: "mailbox_listed",
48095
48229
  detail: {
48096
48230
  visibleCount: msgs.length,
48097
- visibleMessageIds: msgs.map((msg) => msg.id)
48231
+ visibleMessageIds
48098
48232
  }
48099
48233
  });
48100
- const list = msgs.map((msg, i) => {
48234
+ const renderMessage2 = (msg, i) => {
48101
48235
  const time = new Date(msg.sendTime).toLocaleString("zh-CN", { timeZone: "Asia/Shanghai" });
48102
48236
  const preview2 = msg.content.length > 100 ? msg.content.slice(0, 100) + "..." : msg.content;
48103
48237
  return `[${i + 1}] id: ${msg.id}
@@ -48105,10 +48239,22 @@ var listMailbox = {
48105
48239
  \u65F6\u95F4: ${time}
48106
48240
  \u72B6\u6001: ${msg.status}
48107
48241
  \u6458\u8981: ${preview2}`;
48108
- }).join("\n\n");
48109
- return `[listMailbox] \u4F60\u6709 ${msgs.length} \u5C01\u5F85\u5904\u7406\u90AE\u4EF6\uFF1A
48110
-
48111
- ${list}`;
48242
+ };
48243
+ const pending = msgs.filter((msg) => msg.status === "pending");
48244
+ const processing = msgs.filter((msg) => msg.status === "processing");
48245
+ const sections = [
48246
+ pending.length > 0 ? `\u65B0\u90AE\u4EF6 pending\uFF08\u5C1A\u672A\u9886\u53D6\uFF09\uFF1A
48247
+ ${pending.map(renderMessage2).join("\n\n")}` : null,
48248
+ processing.length > 0 ? `\u5DF2\u9886\u53D6/\u5904\u7406\u4E2D processing\uFF08\u4ECD\u9700\u7EE7\u7EED\u95ED\u73AF\uFF09\uFF1A
48249
+ ${processing.map(renderMessage2).join("\n\n")}` : null
48250
+ ].filter(Boolean).join("\n\n");
48251
+ return [
48252
+ `[listMailbox] \u4F60\u6709 ${msgs.length} \u5C01\u5F85\u5904\u7406\u90AE\u4EF6\uFF1A`,
48253
+ ``,
48254
+ sections,
48255
+ ``,
48256
+ `\u4E0B\u4E00\u6B65\u5FC5\u987B\u4ECE\u4EE5\u4E0A message_id \u4E2D\u9009\u62E9\u4E00\u5C01\u8C03\u7528 get_mailbox(message_id="...") \u6253\u5F00\u5904\u7406\uFF1B\u5982\u679C\u786E\u8BA4\u67D0\u5C01\u65E0\u7528/\u8FC7\u65F6\uFF0C\u8C03\u7528 discard_mailbox\uFF1B\u5982\u679C\u5DF2\u7ECF\u6709\u8FDB\u5C55\u6216\u7ED3\u679C\uFF0C\u8C03\u7528 mailbox_followup \u6216 reply_mailbox\u3002\u4E0D\u8981\u8FDE\u7EED\u91CD\u590D\u8C03\u7528 list_mailbox\u3002`
48257
+ ].join("\n");
48112
48258
  }
48113
48259
  };
48114
48260
 
@@ -48216,6 +48362,7 @@ var getMailbox = {
48216
48362
  counterpartMailboxId: msg.fromMailboxId,
48217
48363
  eventType: "message_opened"
48218
48364
  });
48365
+ markMailboxQueueAction(userRequest);
48219
48366
  const time = new Date(msg.sendTime).toLocaleString("zh-CN", { timeZone: "Asia/Shanghai" });
48220
48367
  const threadId = msg.threadId || msg.id;
48221
48368
  const upstreamContext = buildUpstreamContext(msg);
@@ -48328,6 +48475,7 @@ var discardMailbox = {
48328
48475
  parentMessageId: msg.parentMessageId || null
48329
48476
  }
48330
48477
  });
48478
+ markMailboxQueueAction(userRequest);
48331
48479
  return `[discardMailbox] \u5DF2\u4E22\u5F03\u90AE\u4EF6 ${messageId}\uFF0C\u539F\u56E0\uFF1A${reason}`;
48332
48480
  }
48333
48481
  };
@@ -48479,6 +48627,7 @@ var replyMailbox = {
48479
48627
  }
48480
48628
  });
48481
48629
  const upstreamReminder = buildUpstreamReminder(myMailboxId, msg.fromMailboxId, msg.threadId || msg.id, msg.workItemId);
48630
+ markMailboxQueueAction(userRequest);
48482
48631
  return `[replyMailbox] ${claimedFromPending ? "\u5DF2\u9886\u53D6\u5E76" : "\u5DF2"}\u6B63\u5F0F\u56DE\u590D\u90AE\u4EF6 ${messageId}\uFF0C\u56DE\u590D\u6D88\u606F ${replyMsg.id} \u5DF2\u53D1\u9001\u5230 ${msg.fromMailboxId} \u7684\u90AE\u7BB1\uFF08thread: ${replyMsg.threadId}\uFF09${upstreamReminder}`;
48483
48632
  }
48484
48633
  };
@@ -48603,6 +48752,10 @@ var recoverStaleProcessingWork = () => {
48603
48752
  console.warn(`[mailbox] \u5DF2\u6062\u590D stale processing: mailbox=${mailboxRecovered}, ceo_followups=${followupsRecovered}`);
48604
48753
  }
48605
48754
  };
48755
+ var isMaxIterationsError = (err) => {
48756
+ const message = err?.message ?? "";
48757
+ return /达到最大迭代次数|max iterations?/i.test(message);
48758
+ };
48606
48759
  var markMailboxStatus = (msgId, status) => {
48607
48760
  const fromStatusMap = {
48608
48761
  processing: ["pending"],
@@ -48616,6 +48769,55 @@ var markMailboxStatus = (msgId, status) => {
48616
48769
  reason: "mailbox_poller"
48617
48770
  });
48618
48771
  };
48772
+ var failDepartmentWakeupMessages = (mailboxId, msgIds, reason) => {
48773
+ const rows = msgIds.map((id) => db2.prepare(
48774
+ `SELECT
48775
+ id,
48776
+ from_mailbox_id as fromMailboxId,
48777
+ status,
48778
+ origin_user_id as originUserId,
48779
+ origin_platform as originPlatform,
48780
+ thread_id as threadId
48781
+ FROM mailbox
48782
+ WHERE id = ?`
48783
+ ).get(id)).filter(
48784
+ (row) => Boolean(row && (row.status === "pending" || row.status === "processing"))
48785
+ );
48786
+ const bySender = /* @__PURE__ */ new Map();
48787
+ for (const row of rows) {
48788
+ const senderRows = bySender.get(row.fromMailboxId) ?? [];
48789
+ senderRows.push(row);
48790
+ bySender.set(row.fromMailboxId, senderRows);
48791
+ }
48792
+ for (const [senderMailboxId, senderRows] of bySender.entries()) {
48793
+ const changedRows = senderRows.filter((row) => updateMailboxMessageStatus(row.id, "failed", {
48794
+ fromStatus: ["pending", "processing"],
48795
+ actorMailboxId: mailboxId,
48796
+ counterpartMailboxId: senderMailboxId,
48797
+ reason: "department_agent_wakeup_terminal_failed"
48798
+ }));
48799
+ if (changedRows.length === 0) continue;
48800
+ const first = changedRows[0];
48801
+ const ids = changedRows.map((row) => row.id).join(", ");
48802
+ sendMessage2(mailboxId, senderMailboxId, [
48803
+ `[\u7CFB\u7EDF\u901A\u77E5] ${mailboxId} \u672C\u8F6E\u5904\u7406\u672A\u80FD\u6B63\u5E38\u5B8C\u6210\uFF0C\u5DF2\u505C\u6B62\u81EA\u52A8\u91CD\u8BD5\uFF0C\u907F\u514D\u540C\u4E00\u6279\u90AE\u4EF6\u88AB\u53CD\u590D\u6295\u9012\u3002`,
48804
+ `\u5931\u8D25\u539F\u56E0: ${reason}`,
48805
+ `\u53D7\u5F71\u54CD\u90AE\u4EF6: ${ids}`,
48806
+ `\u8BF7\u4E0A\u6E38\u6839\u636E\u9700\u8981\u91CD\u65B0\u59D4\u6D3E\u3001\u8865\u5145\u4E0A\u4E0B\u6587\uFF0C\u6216\u4EBA\u5DE5\u68C0\u67E5\u8BE5\u8D1F\u8D23\u4EBA\u3002`
48807
+ ].join("\n"), {
48808
+ originUserId: first.originUserId,
48809
+ originPlatform: first.originPlatform,
48810
+ threadId: first.threadId || first.id,
48811
+ parentMessageId: first.id,
48812
+ auditDetail: {
48813
+ fallbackReason: "department_agent_wakeup_terminal_failed",
48814
+ affectedMessageIds: changedRows.map((row) => row.id),
48815
+ error: reason
48816
+ }
48817
+ });
48818
+ console.warn(`[mailbox] department agent ${mailboxId} \u7EC8\u6B62\u5931\u8D25\uFF0C\u5DF2\u5C06 ${changedRows.length} \u5C01\u90AE\u4EF6\u6807\u8BB0 failed \u5E76\u901A\u77E5 ${senderMailboxId}`);
48819
+ }
48820
+ };
48619
48821
  var handleCeoFollowupGroup = async (followups) => {
48620
48822
  const originUserId = followups[0].originUserId;
48621
48823
  const originPlatform = followups[0].originPlatform;
@@ -48764,6 +48966,10 @@ var wakeDepartmentAgent = async (mailboxId, msgIds) => {
48764
48966
  finalizeDepartmentAgentUnrepliedMessages(mailboxId, msgIds, result);
48765
48967
  } catch (err) {
48766
48968
  console.error(`[mailbox] \u5524\u9192 department agent ${mailboxId} \u5931\u8D25:`, err);
48969
+ if (isMaxIterationsError(err)) {
48970
+ failDepartmentWakeupMessages(mailboxId, msgIds, err.message);
48971
+ return;
48972
+ }
48767
48973
  for (const id of msgIds) {
48768
48974
  updateMailboxMessageStatus(id, "pending", {
48769
48975
  fromStatus: "processing",
@@ -48879,10 +49085,14 @@ var pollMailbox = async () => {
48879
49085
  const livenessSnapshot = getMailboxLivenessSnapshot();
48880
49086
  logMailboxPollerHeartbeat(livenessSnapshot);
48881
49087
  await reportMailboxLiveness(livenessSnapshot);
48882
- const mailBoxMsgs = selectStmt.all("pending");
49088
+ const allPendingMailboxMsgs = selectStmt.all("pending");
49089
+ const mailBoxMsgs = allPendingMailboxMsgs.filter(
49090
+ (msg) => msg.toMailboxId === "manager" || !inFlightDepartmentMailboxes.has(msg.toMailboxId)
49091
+ );
48883
49092
  const pendingFollowups = listPendingCeoFollowups();
48884
49093
  if (mailBoxMsgs.length === 0 && pendingFollowups.length === 0) return;
48885
- console.log(`[mailbox] \u62C9\u53D6\u5230 ${mailBoxMsgs.length} \u6761\u5F85\u5904\u7406\u6D88\u606F`);
49094
+ const skippedInFlight = allPendingMailboxMsgs.length - mailBoxMsgs.length;
49095
+ console.log(`[mailbox] \u62C9\u53D6\u5230 ${mailBoxMsgs.length} \u6761\u53EF\u8C03\u5EA6\u5F85\u5904\u7406\u6D88\u606F${skippedInFlight > 0 ? `\uFF0C\u8DF3\u8FC7 ${skippedInFlight} \u6761 in-flight mailbox \u6D88\u606F` : ""}`);
48886
49096
  const grouped = /* @__PURE__ */ new Map();
48887
49097
  for (const msg of mailBoxMsgs) {
48888
49098
  const group = grouped.get(msg.toMailboxId) || [];
@@ -49026,6 +49236,7 @@ ${workspacePath ? `
49026
49236
  ` : ""}
49027
49237
  <Mailbox \u5DE5\u4F5C\u65B9\u5F0F>
49028
49238
  \u4F60\u901A\u8FC7\u90AE\u7BB1\u548C\u540C\u4E8B\u534F\u4F5C\u3002\u6536\u5230\u65B0\u90AE\u4EF6\u63D0\u9192\u540E\uFF0C\u7528 list_mailbox \u770B\u770B\u6709\u54EA\u4E9B\u5F85\u5904\u7406\u7684\u90AE\u4EF6\uFF0C\u6311\u4E00\u5C01\u7528 get_mailbox \u9886\u53D6\u5E76\u8BFB\u5168\u6587\uFF0C\u628A\u5B83\u505A\u5B8C\u6216\u95EE\u6E05\u695A\uFF0C\u518D\u56DE\u590D\u3002\u5904\u7406\u5B8C\u4E00\u5C01\u7EE7\u7EED list_mailbox \u770B\u4E0B\u4E00\u5C01\u3002
49239
+ list_mailbox \u53EA\u662F\u961F\u5217\u5165\u53E3\uFF0C\u4E0D\u662F\u7B49\u5F85\u52A8\u4F5C\uFF1B\u540C\u4E00\u8F6E\u770B\u8FC7\u5217\u8868\u540E\uFF0C\u4E0B\u4E00\u6B65\u5FC5\u987B\u5BF9\u5176\u4E2D\u4E00\u5C01\u90AE\u4EF6\u8C03\u7528 get_mailbox\u3001reply_mailbox\u3001mailbox_followup\u3001discard_mailbox \u6216 department_communicate\uFF0C\u7981\u6B62\u8FDE\u7EED\u91CD\u590D list_mailbox \u7A7A\u8F6C\u3002
49029
49240
 
49030
49241
  \u51E0\u4E2A\u5DE5\u5177\u7684\u542B\u4E49\u8981\u5206\u6E05\uFF0C\u522B\u53EA\u7528\u81EA\u7136\u8BED\u8A00\u8BF4\u8BF4\u5C31\u7B97\u6570\uFF1A
49031
49242
  - mailbox_followup(message_id, content)\uFF1A\u5728\u540C\u4E00\u7EBF\u7A0B\u91CC\u7EE7\u7EED\u6C9F\u901A\u2014\u2014\u540C\u6B65\u8FDB\u5C55\u3001\u8865\u5145\u7ED3\u679C\u3001\u8865\u5145\u4E0A\u4E0B\u6587\u6216\u8BE2\u95EE\u72B6\u6001\uFF1B\u53EF\u4EE5\u591A\u6B21\uFF0C\u4E0D\u4F1A\u7ED3\u675F\u8FD9\u5C01\u90AE\u4EF6\u3002
@@ -54054,7 +54265,7 @@ var systemRoutes = new Hono2();
54054
54265
  var startTime = Date.now();
54055
54266
  systemRoutes.get("/system/info", (c) => {
54056
54267
  return c.json({
54057
- version: true ? "1.9.14" : "unknown",
54268
+ version: true ? "1.9.16" : "unknown",
54058
54269
  uptime: Math.floor((Date.now() - startTime) / 1e3),
54059
54270
  env: process.env.NODE_ENV || "development",
54060
54271
  nodeVersion: process.version