duclaw-cli 1.8.36 → 1.8.38

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.8.36" : "unknown"}`);
30245
+ console.log(`duclaw-cli v${true ? "1.8.38" : "unknown"}`);
30246
30246
  }
30247
30247
  function getDuclawTemplate() {
30248
30248
  return {
@@ -32629,7 +32629,7 @@ var chokidar_default = { watch, FSWatcher };
32629
32629
  var import_node_cron = __toESM(require_node_cron());
32630
32630
 
32631
32631
  // src/agent/createAgent.ts
32632
- var import_node_crypto11 = require("node:crypto");
32632
+ var import_node_crypto12 = require("node:crypto");
32633
32633
  var import_node_fs7 = require("node:fs");
32634
32634
 
32635
32635
  // src/background/BackgroundManager.ts
@@ -41407,10 +41407,10 @@ var goalDelete = {
41407
41407
  };
41408
41408
 
41409
41409
  // src/tools/tools/department/DepartmentCreate.ts
41410
- var import_node_crypto5 = require("node:crypto");
41410
+ var import_node_crypto6 = require("node:crypto");
41411
41411
 
41412
41412
  // src/department/mailbox/mailbox.ts
41413
- var import_node_crypto4 = require("node:crypto");
41413
+ var import_node_crypto5 = require("node:crypto");
41414
41414
 
41415
41415
  // src/db/createDB.ts
41416
41416
  var import_better_sqlite3 = __toESM(require("better-sqlite3"));
@@ -41433,6 +41433,7 @@ var _ensure_table_exist = () => {
41433
41433
  create_workspace_table();
41434
41434
  create_mailbox_table();
41435
41435
  create_mailbox_events_table();
41436
+ create_ceo_followups_table();
41436
41437
  create_agent_events_table();
41437
41438
  };
41438
41439
  var create_workspace_table = () => {
@@ -41463,6 +41464,9 @@ var create_mailbox_table = () => {
41463
41464
  origin_platform TEXT,
41464
41465
  thread_id TEXT,
41465
41466
  parent_message_id TEXT,
41467
+ work_item_id TEXT,
41468
+ work_item_role TEXT,
41469
+ upstream_message_id TEXT,
41466
41470
  send_time INTEGER DEFAULT ((strftime('%s', 'now')) * 1000),
41467
41471
  created_at INTEGER DEFAULT ((strftime('%s', 'now')) * 1000),
41468
41472
  updated_at INTEGER DEFAULT ((strftime('%s', 'now')) * 1000)
@@ -41486,9 +41490,23 @@ var create_mailbox_table = () => {
41486
41490
  db3.exec(`ALTER TABLE mailbox ADD COLUMN parent_message_id TEXT`);
41487
41491
  } catch (_) {
41488
41492
  }
41493
+ try {
41494
+ db3.exec(`ALTER TABLE mailbox ADD COLUMN work_item_id TEXT`);
41495
+ } catch (_) {
41496
+ }
41497
+ try {
41498
+ db3.exec(`ALTER TABLE mailbox ADD COLUMN work_item_role TEXT`);
41499
+ } catch (_) {
41500
+ }
41501
+ try {
41502
+ db3.exec(`ALTER TABLE mailbox ADD COLUMN upstream_message_id TEXT`);
41503
+ } catch (_) {
41504
+ }
41489
41505
  const columns = db3.prepare(`PRAGMA table_info(mailbox)`).all();
41490
41506
  const hasThreadId = columns.some((column) => column.name === "thread_id");
41491
41507
  const hasParentMessageId = columns.some((column) => column.name === "parent_message_id");
41508
+ const hasWorkItemId = columns.some((column) => column.name === "work_item_id");
41509
+ const hasUpstreamMessageId = columns.some((column) => column.name === "upstream_message_id");
41492
41510
  if (hasThreadId) {
41493
41511
  db3.exec(`
41494
41512
  CREATE INDEX IF NOT EXISTS idx_mailbox_thread
@@ -41502,6 +41520,18 @@ var create_mailbox_table = () => {
41502
41520
  ON mailbox(parent_message_id)
41503
41521
  `);
41504
41522
  }
41523
+ if (hasWorkItemId) {
41524
+ db3.exec(`
41525
+ CREATE INDEX IF NOT EXISTS idx_mailbox_work_item
41526
+ ON mailbox(work_item_id, send_time DESC)
41527
+ `);
41528
+ }
41529
+ if (hasUpstreamMessageId) {
41530
+ db3.exec(`
41531
+ CREATE INDEX IF NOT EXISTS idx_mailbox_upstream
41532
+ ON mailbox(upstream_message_id)
41533
+ `);
41534
+ }
41505
41535
  };
41506
41536
  var create_mailbox_events_table = () => {
41507
41537
  const db3 = createSqliteDB();
@@ -41536,6 +41566,34 @@ var create_mailbox_events_table = () => {
41536
41566
  } catch (_) {
41537
41567
  }
41538
41568
  };
41569
+ var create_ceo_followups_table = () => {
41570
+ const db3 = createSqliteDB();
41571
+ db3.exec(`
41572
+ CREATE TABLE IF NOT EXISTS ceo_followups (
41573
+ id TEXT PRIMARY KEY,
41574
+ source_message_id TEXT NOT NULL UNIQUE,
41575
+ status TEXT DEFAULT ('pending') NOT NULL,
41576
+ origin_user_id TEXT NOT NULL,
41577
+ origin_platform TEXT NOT NULL,
41578
+ from_mailbox_id TEXT NOT NULL,
41579
+ thread_id TEXT,
41580
+ parent_message_id TEXT,
41581
+ work_item_id TEXT,
41582
+ content TEXT NOT NULL,
41583
+ attempts INTEGER DEFAULT 0 NOT NULL,
41584
+ last_error TEXT,
41585
+ created_at INTEGER DEFAULT ((strftime('%s', 'now')) * 1000),
41586
+ updated_at INTEGER DEFAULT ((strftime('%s', 'now')) * 1000),
41587
+ completed_at INTEGER
41588
+ );
41589
+
41590
+ CREATE INDEX IF NOT EXISTS idx_ceo_followups_status_created
41591
+ ON ceo_followups(status, created_at);
41592
+
41593
+ CREATE INDEX IF NOT EXISTS idx_ceo_followups_user_status
41594
+ ON ceo_followups(origin_user_id, status, created_at);
41595
+ `);
41596
+ };
41539
41597
  var create_agent_events_table = () => {
41540
41598
  const db3 = createSqliteDB();
41541
41599
  db3.exec(`
@@ -41742,11 +41800,21 @@ var renderAgentEventReminder = (events) => {
41742
41800
  summary ? `summary=${summary}` : ""
41743
41801
  ].filter(Boolean).join(" ");
41744
41802
  }).join("\n");
41803
+ const hasCeoFollowup = events.some((event) => event.type === "ceo.followup_required");
41804
+ const ceoFollowupInstruction = hasCeoFollowup ? [
41805
+ ``,
41806
+ `CEO followup \u786C\u89C4\u5219\uFF1A`,
41807
+ `- type=ceo.followup_required \u8868\u793A Department Head/Executor \u5DF2\u7ECF\u628A\u5185\u90E8\u7ED3\u679C\u56DE\u7ED9 Main Manager/CEO\u3002`,
41808
+ `- \u8FD9\u4E0D\u662F\u666E\u901A\u63D0\u9192\uFF1BBoss/User \u6B63\u5728\u7B49\u5F85\u6700\u7EC8\u53EF\u89C1\u7ED3\u679C\u3002`,
41809
+ `- \u4F60\u5FC5\u987B\u8BFB\u53D6 summary/contentPreview\uFF0C\u76F4\u63A5\u8C03\u7528 send_message \u5411 Boss/User \u6C47\u62A5\u7ED3\u679C\u3002`,
41810
+ `- \u4E0D\u8981\u53EA\u8BF4\u201C\u6682\u65E0\u56DE\u4FE1/\u8FD8\u5728\u6267\u884C/\u7A0D\u540E\u540C\u6B65\u201D\uFF0C\u9664\u975E summary \u660E\u786E\u8BF4\u660E\u4ECD\u5728\u7B49\u5F85\u6216\u5931\u8D25\u3002`
41811
+ ].join("\n") : "";
41745
41812
  return `<system-reminder>
41746
41813
  \u672C\u8F6E\u6709 ${events.length} \u6761\u5185\u90E8\u4E8B\u4EF6\u53EF\u7528\uFF1A
41747
41814
  ${lines}
41748
41815
 
41749
41816
  \u8FD9\u4E9B\u4E8B\u4EF6\u4E0D\u662F\u7528\u6237\u7684\u65B0\u8BF7\u6C42\uFF0C\u4E5F\u4E0D\u5E94\u8BE5\u4F5C\u4E3A\u7528\u6237\u786E\u8BA4\u3002\u82E5\u4E8B\u4EF6\u7C7B\u578B\u662F mailbox.message_received\uFF0C\u8868\u793A\u4F60\u7684 mailbox \u5728\u5F53\u524D\u5DE5\u4F5C\u671F\u95F4\u6536\u5230\u65B0\u5185\u90E8\u534F\u4F5C\u6D88\u606F\uFF1B\u8BF7\u5C3D\u5FEB\u8C03\u7528 list_mailbox \u67E5\u770B\u961F\u5217\uFF0C\u5E76\u5728\u9700\u8981\u65F6\u7528 get_mailbox(message_id) \u9886\u53D6\u5173\u8054\u6D88\u606F\u3002\u4E0D\u8981\u76F4\u63A5\u628A\u4E8B\u4EF6\u5F53\u4F5C\u5DF2\u9886\u53D6\u90AE\u4EF6\u3002\u8BF7\u53EA\u5728\u9700\u8981\u65F6\u81EA\u7136\u5730\u6C47\u603B\u7ED9\u7528\u6237\uFF1B\u5982\u9700\u7EE7\u7EED\u534F\u4F5C\uFF0C\u4F18\u5148\u4F7F\u7528\u4E8B\u4EF6\u4E2D\u5173\u8054\u7684 mailboxMessageId/thread \u7EE7\u7EED\u5904\u7406\u3002\u4E0D\u8981\u590D\u8FF0\u672C system-reminder\u3002
41817
+ ${ceoFollowupInstruction}
41750
41818
  </system-reminder>`;
41751
41819
  };
41752
41820
 
@@ -42075,6 +42143,208 @@ var deleteDepartmentMemberById = (departmentName, memberId) => {
42075
42143
  deleteWorkspace(workspaceId);
42076
42144
  };
42077
42145
 
42146
+ // src/department/mailbox/ceoFollowup.ts
42147
+ var import_node_crypto4 = require("node:crypto");
42148
+ var rowToFollowup = (row) => ({
42149
+ id: row.id,
42150
+ sourceMessageId: row.sourceMessageId,
42151
+ status: row.status,
42152
+ originUserId: row.originUserId,
42153
+ originPlatform: row.originPlatform,
42154
+ fromMailboxId: row.fromMailboxId,
42155
+ threadId: row.threadId ?? void 0,
42156
+ parentMessageId: row.parentMessageId ?? void 0,
42157
+ workItemId: row.workItemId ?? void 0,
42158
+ content: row.content,
42159
+ attempts: row.attempts,
42160
+ lastError: row.lastError ?? void 0,
42161
+ createdAt: row.createdAt,
42162
+ updatedAt: row.updatedAt,
42163
+ completedAt: row.completedAt ?? void 0
42164
+ });
42165
+ var selectById = (id) => {
42166
+ const db3 = createSqliteDB();
42167
+ const row = db3.prepare(`
42168
+ SELECT
42169
+ id,
42170
+ source_message_id as sourceMessageId,
42171
+ status,
42172
+ origin_user_id as originUserId,
42173
+ origin_platform as originPlatform,
42174
+ from_mailbox_id as fromMailboxId,
42175
+ thread_id as threadId,
42176
+ parent_message_id as parentMessageId,
42177
+ work_item_id as workItemId,
42178
+ content,
42179
+ attempts,
42180
+ last_error as lastError,
42181
+ created_at as createdAt,
42182
+ updated_at as updatedAt,
42183
+ completed_at as completedAt
42184
+ FROM ceo_followups
42185
+ WHERE id = ?
42186
+ `).get(id);
42187
+ return row ? rowToFollowup(row) : null;
42188
+ };
42189
+ var enqueueCeoFollowupFromMailbox = (message) => {
42190
+ if (message.toMailboxId !== "manager") return null;
42191
+ if (!message.originUserId || !message.originPlatform) return null;
42192
+ const db3 = createSqliteDB();
42193
+ const now = Date.now();
42194
+ const id = `cfu_${(0, import_node_crypto4.randomUUID)().slice(0, 12)}`;
42195
+ db3.prepare(`
42196
+ INSERT INTO ceo_followups (
42197
+ id,
42198
+ source_message_id,
42199
+ status,
42200
+ origin_user_id,
42201
+ origin_platform,
42202
+ from_mailbox_id,
42203
+ thread_id,
42204
+ parent_message_id,
42205
+ work_item_id,
42206
+ content,
42207
+ created_at,
42208
+ updated_at
42209
+ ) VALUES (?, ?, 'pending', ?, ?, ?, ?, ?, ?, ?, ?, ?)
42210
+ ON CONFLICT(source_message_id) DO UPDATE SET
42211
+ status = CASE
42212
+ WHEN ceo_followups.status = 'completed' THEN ceo_followups.status
42213
+ ELSE 'pending'
42214
+ END,
42215
+ origin_user_id = excluded.origin_user_id,
42216
+ origin_platform = excluded.origin_platform,
42217
+ from_mailbox_id = excluded.from_mailbox_id,
42218
+ thread_id = excluded.thread_id,
42219
+ parent_message_id = excluded.parent_message_id,
42220
+ work_item_id = excluded.work_item_id,
42221
+ content = excluded.content,
42222
+ updated_at = excluded.updated_at
42223
+ `).run(
42224
+ id,
42225
+ message.id,
42226
+ message.originUserId,
42227
+ message.originPlatform,
42228
+ message.fromMailboxId,
42229
+ message.threadId ?? message.id,
42230
+ message.parentMessageId ?? null,
42231
+ message.workItemId ?? null,
42232
+ message.content,
42233
+ now,
42234
+ now
42235
+ );
42236
+ const row = db3.prepare(`
42237
+ SELECT id FROM ceo_followups WHERE source_message_id = ?
42238
+ `).get(message.id);
42239
+ return row ? selectById(row.id) : null;
42240
+ };
42241
+ var listPendingCeoFollowups = (limit = 10) => {
42242
+ const db3 = createSqliteDB();
42243
+ const rows = db3.prepare(`
42244
+ SELECT
42245
+ id,
42246
+ source_message_id as sourceMessageId,
42247
+ status,
42248
+ origin_user_id as originUserId,
42249
+ origin_platform as originPlatform,
42250
+ from_mailbox_id as fromMailboxId,
42251
+ thread_id as threadId,
42252
+ parent_message_id as parentMessageId,
42253
+ work_item_id as workItemId,
42254
+ content,
42255
+ attempts,
42256
+ last_error as lastError,
42257
+ created_at as createdAt,
42258
+ updated_at as updatedAt,
42259
+ completed_at as completedAt
42260
+ FROM ceo_followups
42261
+ WHERE status IN ('pending', 'failed')
42262
+ ORDER BY created_at ASC
42263
+ LIMIT ?
42264
+ `).all(limit);
42265
+ return rows.map(rowToFollowup);
42266
+ };
42267
+ var claimCeoFollowup = (id) => {
42268
+ const db3 = createSqliteDB();
42269
+ const now = Date.now();
42270
+ const result = db3.prepare(`
42271
+ UPDATE ceo_followups
42272
+ SET status = 'processing',
42273
+ attempts = attempts + 1,
42274
+ updated_at = ?
42275
+ WHERE id = ?
42276
+ AND status IN ('pending', 'failed')
42277
+ `).run(now, id);
42278
+ if (result.changes === 0) return null;
42279
+ return selectById(id);
42280
+ };
42281
+ var completeCeoFollowup = (id) => {
42282
+ const db3 = createSqliteDB();
42283
+ const now = Date.now();
42284
+ db3.prepare(`
42285
+ UPDATE ceo_followups
42286
+ SET status = 'completed',
42287
+ completed_at = COALESCE(completed_at, ?),
42288
+ updated_at = ?,
42289
+ last_error = NULL
42290
+ WHERE id = ?
42291
+ AND status IN ('pending', 'processing', 'failed')
42292
+ `).run(now, now, id);
42293
+ db3.prepare(`
42294
+ UPDATE mailbox
42295
+ SET status = 'done',
42296
+ updated_at = ?
42297
+ WHERE id = (SELECT source_message_id FROM ceo_followups WHERE id = ?)
42298
+ AND status IN ('pending', 'processing', 'read')
42299
+ `).run(now, id);
42300
+ };
42301
+ var failCeoFollowup = (id, error) => {
42302
+ const db3 = createSqliteDB();
42303
+ const now = Date.now();
42304
+ db3.prepare(`
42305
+ UPDATE ceo_followups
42306
+ SET status = 'failed',
42307
+ last_error = ?,
42308
+ updated_at = ?
42309
+ WHERE id = ?
42310
+ AND status IN ('pending', 'processing', 'failed')
42311
+ `).run(error.slice(0, 1e3), now, id);
42312
+ };
42313
+ var completePendingCeoFollowupsForUser = (originUserId) => {
42314
+ const db3 = createSqliteDB();
42315
+ const now = Date.now();
42316
+ const rows = db3.prepare(`
42317
+ SELECT id, source_message_id as sourceMessageId
42318
+ FROM ceo_followups
42319
+ WHERE origin_user_id = ?
42320
+ AND status IN ('pending', 'processing', 'failed')
42321
+ `).all(originUserId);
42322
+ const tx = db3.transaction((items) => {
42323
+ const completeStmt = db3.prepare(`
42324
+ UPDATE ceo_followups
42325
+ SET status = 'completed',
42326
+ completed_at = COALESCE(completed_at, ?),
42327
+ updated_at = ?,
42328
+ last_error = NULL
42329
+ WHERE id = ?
42330
+ AND status IN ('pending', 'processing', 'failed')
42331
+ `);
42332
+ const doneStmt = db3.prepare(`
42333
+ UPDATE mailbox
42334
+ SET status = 'done',
42335
+ updated_at = ?
42336
+ WHERE id = ?
42337
+ AND status IN ('pending', 'processing', 'read')
42338
+ `);
42339
+ for (const item of items) {
42340
+ completeStmt.run(now, now, item.id);
42341
+ doneStmt.run(now, item.sourceMessageId);
42342
+ }
42343
+ });
42344
+ tx(rows);
42345
+ return rows.length;
42346
+ };
42347
+
42078
42348
  // src/department/mailbox/mailbox.ts
42079
42349
  var getMailBoxId = (departmentName, memberName) => {
42080
42350
  return `${departmentName}::${memberName}`;
@@ -42102,6 +42372,87 @@ var cancelMailboxMessages = (mailboxId) => {
42102
42372
  }
42103
42373
  return messages.length;
42104
42374
  };
42375
+ var getWorkItemContextFromMessage = (messageId) => {
42376
+ if (!messageId) return null;
42377
+ const db3 = createSqliteDB();
42378
+ const row = db3.prepare(
42379
+ `SELECT
42380
+ work_item_id as workItemId,
42381
+ work_item_role as workItemRole,
42382
+ upstream_message_id as upstreamMessageId
42383
+ FROM mailbox
42384
+ WHERE id = ?`
42385
+ ).get(messageId);
42386
+ if (!row?.workItemId) return null;
42387
+ return row;
42388
+ };
42389
+ var getWorkItemContextFromThread = (threadId) => {
42390
+ if (!threadId) return null;
42391
+ const db3 = createSqliteDB();
42392
+ const row = db3.prepare(
42393
+ `SELECT
42394
+ work_item_id as workItemId,
42395
+ work_item_role as workItemRole,
42396
+ upstream_message_id as upstreamMessageId
42397
+ FROM mailbox
42398
+ WHERE thread_id = ?
42399
+ AND work_item_id IS NOT NULL
42400
+ ORDER BY send_time ASC
42401
+ LIMIT 1`
42402
+ ).get(threadId);
42403
+ if (!row?.workItemId) return null;
42404
+ return row;
42405
+ };
42406
+ var mailboxLooksLikeRole = (mailboxId, role) => {
42407
+ const lower = mailboxId.toLowerCase();
42408
+ if (role === "department_head") {
42409
+ return lower.includes("department-head") || mailboxId.includes("\u8D1F\u8D23\u4EBA");
42410
+ }
42411
+ return lower.includes("executor") || mailboxId.includes("\u6267\u884C\u8005") || mailboxId.includes("\u4E13\u5458");
42412
+ };
42413
+ var inferWorkItemRole = (fromMailboxId, toMailboxId, inherited) => {
42414
+ if (fromMailboxId === "manager") return "upstream_request";
42415
+ if (toMailboxId === "manager") return "upstream_report";
42416
+ const fromMember = getDepartmentMemberByMailboxId(fromMailboxId);
42417
+ const toMember = getDepartmentMemberByMailboxId(toMailboxId);
42418
+ const fromIsHead = fromMember?.role === "department_head" || mailboxLooksLikeRole(fromMailboxId, "department_head");
42419
+ const toIsHead = toMember?.role === "department_head" || mailboxLooksLikeRole(toMailboxId, "department_head");
42420
+ const fromIsExecutor = fromMember?.role === "executor" || mailboxLooksLikeRole(fromMailboxId, "executor");
42421
+ const toIsExecutor = toMember?.role === "executor" || mailboxLooksLikeRole(toMailboxId, "executor");
42422
+ if (fromIsHead && toIsExecutor) {
42423
+ return inherited?.workItemRole === "executor_result" ? "downstream_reply" : "delegation";
42424
+ }
42425
+ if (fromIsExecutor && toIsHead) return "executor_result";
42426
+ return inherited?.workItemRole ? "followup" : "message";
42427
+ };
42428
+ var resolveWorkItemContext = (fromMailboxId, toMailboxId, id, options) => {
42429
+ if (options?.workItemId) {
42430
+ return {
42431
+ workItemId: options.workItemId,
42432
+ workItemRole: options.workItemRole ?? inferWorkItemRole(fromMailboxId, toMailboxId),
42433
+ upstreamMessageId: options.upstreamMessageId ?? options.workItemId
42434
+ };
42435
+ }
42436
+ const inherited = getWorkItemContextFromMessage(options?.parentMessageId) ?? getWorkItemContextFromThread(options?.threadId);
42437
+ if (inherited?.workItemId) {
42438
+ return {
42439
+ workItemId: inherited.workItemId,
42440
+ workItemRole: options?.workItemRole ?? inferWorkItemRole(fromMailboxId, toMailboxId, inherited),
42441
+ upstreamMessageId: inherited.upstreamMessageId ?? inherited.workItemId
42442
+ };
42443
+ }
42444
+ const targetMember = getDepartmentMemberByMailboxId(toMailboxId);
42445
+ if (fromMailboxId === "manager" && targetMember?.role === "department_head") {
42446
+ return {
42447
+ workItemId: id,
42448
+ workItemRole: "upstream_request",
42449
+ upstreamMessageId: id
42450
+ };
42451
+ }
42452
+ return {
42453
+ workItemRole: options?.workItemRole ?? inferWorkItemRole(fromMailboxId, toMailboxId)
42454
+ };
42455
+ };
42105
42456
  var buildMailboxInterruptContent = (msg) => {
42106
42457
  const from = msg.fromMailboxId;
42107
42458
  return [
@@ -42157,6 +42508,9 @@ var recordMailboxReceivedAgentEvent = (msg) => {
42157
42508
  };
42158
42509
  var sendMessage2 = (fromMailboxId, toMailboxId, content, options) => {
42159
42510
  const db3 = createSqliteDB();
42511
+ const id = (0, import_node_crypto5.randomUUID)().slice(0, 8);
42512
+ const threadId = options?.threadId || id;
42513
+ const workItemContext = resolveWorkItemContext(fromMailboxId, toMailboxId, id, options);
42160
42514
  const stmt = db3.prepare(`insert into mailbox (
42161
42515
  id,
42162
42516
  to_mailbox_id,
@@ -42167,10 +42521,11 @@ var sendMessage2 = (fromMailboxId, toMailboxId, content, options) => {
42167
42521
  origin_user_id,
42168
42522
  origin_platform,
42169
42523
  thread_id,
42170
- parent_message_id
42171
- ) values (?,?,?,?,?,?,?,?,?,?) `);
42172
- const id = (0, import_node_crypto4.randomUUID)().slice(0, 8);
42173
- const threadId = options?.threadId || id;
42524
+ parent_message_id,
42525
+ work_item_id,
42526
+ work_item_role,
42527
+ upstream_message_id
42528
+ ) values (?,?,?,?,?,?,?,?,?,?,?,?,?) `);
42174
42529
  let mailboxMsg = {
42175
42530
  id,
42176
42531
  toMailboxId,
@@ -42181,7 +42536,10 @@ var sendMessage2 = (fromMailboxId, toMailboxId, content, options) => {
42181
42536
  originUserId: options?.originUserId,
42182
42537
  originPlatform: options?.originPlatform,
42183
42538
  threadId,
42184
- parentMessageId: options?.parentMessageId
42539
+ parentMessageId: options?.parentMessageId,
42540
+ workItemId: workItemContext.workItemId,
42541
+ workItemRole: workItemContext.workItemRole,
42542
+ upstreamMessageId: workItemContext.upstreamMessageId
42185
42543
  };
42186
42544
  const result = stmt.run(
42187
42545
  mailboxMsg.id,
@@ -42193,7 +42551,10 @@ var sendMessage2 = (fromMailboxId, toMailboxId, content, options) => {
42193
42551
  mailboxMsg.originUserId || null,
42194
42552
  mailboxMsg.originPlatform || null,
42195
42553
  mailboxMsg.threadId || mailboxMsg.id,
42196
- mailboxMsg.parentMessageId || null
42554
+ mailboxMsg.parentMessageId || null,
42555
+ mailboxMsg.workItemId || null,
42556
+ mailboxMsg.workItemRole || null,
42557
+ mailboxMsg.upstreamMessageId || null
42197
42558
  );
42198
42559
  recordMailboxEvent({
42199
42560
  messageId: mailboxMsg.id,
@@ -42203,12 +42564,16 @@ var sendMessage2 = (fromMailboxId, toMailboxId, content, options) => {
42203
42564
  eventType: "message_sent",
42204
42565
  detail: {
42205
42566
  initialStatus: mailboxMsg.status,
42567
+ workItemId: mailboxMsg.workItemId ?? null,
42568
+ workItemRole: mailboxMsg.workItemRole ?? null,
42569
+ upstreamMessageId: mailboxMsg.upstreamMessageId ?? null,
42206
42570
  ...options?.auditDetail ?? {}
42207
42571
  },
42208
42572
  createdAt: mailboxMsg.sendTime
42209
42573
  });
42210
42574
  recordMailboxReceivedAgentEvent(mailboxMsg);
42211
42575
  queueMailboxInterruptIfRunning(mailboxMsg);
42576
+ enqueueCeoFollowupFromMailbox(mailboxMsg);
42212
42577
  return mailboxMsg;
42213
42578
  };
42214
42579
  var updateMailboxMessageStatus = (messageId, nextStatus, options) => {
@@ -42286,7 +42651,7 @@ var departmentCreate = {
42286
42651
  return `[departmentCreate] \u4E0D\u5B58\u5728 id=${sourceGoalId} \u7684\u76EE\u6807`;
42287
42652
  }
42288
42653
  let departmentDefinition = {
42289
- id: (0, import_node_crypto5.randomUUID)().slice(0, 8),
42654
+ id: (0, import_node_crypto6.randomUUID)().slice(0, 8),
42290
42655
  name,
42291
42656
  charter,
42292
42657
  sourceGoalId,
@@ -42314,7 +42679,9 @@ var getActiveMailboxContext = (actorMailboxId, messageId) => {
42314
42679
  to_mailbox_id as toMailboxId,
42315
42680
  origin_user_id as originUserId,
42316
42681
  origin_platform as originPlatform,
42317
- thread_id as threadId
42682
+ thread_id as threadId,
42683
+ work_item_id as workItemId,
42684
+ upstream_message_id as upstreamMessageId
42318
42685
  FROM mailbox
42319
42686
  WHERE id = ?
42320
42687
  AND (from_mailbox_id = ? OR to_mailbox_id = ?)`
@@ -42420,6 +42787,8 @@ var departmentCommunicate = {
42420
42787
  options.originPlatform = activeContext.originPlatform;
42421
42788
  options.threadId = activeContext.threadId || activeContext.id;
42422
42789
  options.parentMessageId = activeContext.id;
42790
+ options.workItemId = activeContext.workItemId;
42791
+ options.upstreamMessageId = activeContext.upstreamMessageId;
42423
42792
  }
42424
42793
  }
42425
42794
  try {
@@ -42525,7 +42894,7 @@ var departmentList = {
42525
42894
  };
42526
42895
 
42527
42896
  // src/tools/tools/department/DepartmentMemberCreate.ts
42528
- var import_node_crypto6 = require("node:crypto");
42897
+ var import_node_crypto7 = require("node:crypto");
42529
42898
  var DESCRIPTION24 = `
42530
42899
  \u521B\u5EFA\u90E8\u95E8\u6210\u5458\u3002
42531
42900
 
@@ -42591,7 +42960,7 @@ var departmentMemberCreate = {
42591
42960
  }
42592
42961
  }
42593
42962
  let departmentMember = {
42594
- id: (0, import_node_crypto6.randomUUID)().slice(0, 8),
42963
+ id: (0, import_node_crypto7.randomUUID)().slice(0, 8),
42595
42964
  name,
42596
42965
  departmentId: department.id,
42597
42966
  mailBoxId: getMailBoxId(department.name, name),
@@ -42782,7 +43151,7 @@ ${replies}`;
42782
43151
  // src/department/learning.ts
42783
43152
  var import_node_fs4 = require("node:fs");
42784
43153
  var import_node_path12 = __toESM(require("node:path"));
42785
- var import_node_crypto7 = require("node:crypto");
43154
+ var import_node_crypto8 = require("node:crypto");
42786
43155
 
42787
43156
  // src/skill/SkillValidator.ts
42788
43157
  var import_node_fs3 = require("node:fs");
@@ -43020,7 +43389,7 @@ var listDepartmentMemories = (departmentName) => {
43020
43389
  var createDepartmentMemory = (departmentName, input) => {
43021
43390
  const now = Date.now();
43022
43391
  const memory = {
43023
- id: (0, import_node_crypto7.randomUUID)().slice(0, 8),
43392
+ id: (0, import_node_crypto8.randomUUID)().slice(0, 8),
43024
43393
  departmentName,
43025
43394
  title: input.title,
43026
43395
  content: input.content,
@@ -43071,7 +43440,7 @@ ${formatSkillValidationIssues(validation)}`);
43071
43440
  }
43072
43441
  const now = Date.now();
43073
43442
  const skill = {
43074
- id: (0, import_node_crypto7.randomUUID)().slice(0, 8),
43443
+ id: (0, import_node_crypto8.randomUUID)().slice(0, 8),
43075
43444
  departmentName,
43076
43445
  skillName: input.skillName,
43077
43446
  description: input.description,
@@ -43123,7 +43492,7 @@ var createDepartmentProposal = (input) => {
43123
43492
  const records = readJsonArray(proposalsPath());
43124
43493
  const proposal = {
43125
43494
  ...input,
43126
- id: (0, import_node_crypto7.randomUUID)().slice(0, 8),
43495
+ id: (0, import_node_crypto8.randomUUID)().slice(0, 8),
43127
43496
  status: "pending",
43128
43497
  createdAt: Date.now()
43129
43498
  };
@@ -43454,7 +43823,7 @@ var mailboxFollowup = {
43454
43823
 
43455
43824
  // src/tools/tools/Bash.ts
43456
43825
  var import_node_child_process = require("node:child_process");
43457
- var import_node_crypto8 = require("node:crypto");
43826
+ var import_node_crypto9 = require("node:crypto");
43458
43827
  var import_node_fs5 = require("node:fs");
43459
43828
  var DESCRIPTION29 = `\u5728\u7CFB\u7EDF shell \u4E2D\u6267\u884C\u547D\u4EE4\u3002
43460
43829
 
@@ -43658,7 +44027,7 @@ var bashTool = {
43658
44027
  ...options,
43659
44028
  stdio: ["pipe", "pipe", "pipe"]
43660
44029
  });
43661
- const id = (0, import_node_crypto8.randomUUID)().slice(0, 8);
44030
+ const id = (0, import_node_crypto9.randomUUID)().slice(0, 8);
43662
44031
  const session = {
43663
44032
  id,
43664
44033
  command,
@@ -44239,7 +44608,7 @@ var readDreamHistoryLimit = () => {
44239
44608
  var import_node_fs6 = require("node:fs");
44240
44609
  var import_node_os2 = require("node:os");
44241
44610
  var import_node_path13 = require("node:path");
44242
- var import_node_crypto9 = require("node:crypto");
44611
+ var import_node_crypto10 = require("node:crypto");
44243
44612
  var SkillForgeEngine = class {
44244
44613
  proposalStorage;
44245
44614
  draftRoot;
@@ -44273,7 +44642,7 @@ ${formatSkillValidationIssues(validation)}`);
44273
44642
  if (pending.some((p) => p.skillName === skillName)) {
44274
44643
  return null;
44275
44644
  }
44276
- const id = (0, import_node_crypto9.randomBytes)(4).toString("hex");
44645
+ const id = (0, import_node_crypto10.randomBytes)(4).toString("hex");
44277
44646
  const draftDir = (0, import_node_path13.join)(this.draftRoot, userId, id);
44278
44647
  (0, import_node_fs6.mkdirSync)(draftDir, { recursive: true });
44279
44648
  (0, import_node_fs6.writeFileSync)((0, import_node_path13.join)(draftDir, "SKILL.md"), skillMd, "utf-8");
@@ -44555,7 +44924,7 @@ var skillForgeDrop = (engine) => ({
44555
44924
  });
44556
44925
 
44557
44926
  // src/memory/MemoryEngine.ts
44558
- var import_node_crypto10 = require("node:crypto");
44927
+ var import_node_crypto11 = require("node:crypto");
44559
44928
  var MemoryEngine = class {
44560
44929
  storage;
44561
44930
  recallIndexStorage;
@@ -44583,7 +44952,7 @@ var MemoryEngine = class {
44583
44952
  }
44584
44953
  const now = Date.now();
44585
44954
  const memory = {
44586
- id: (0, import_node_crypto10.randomBytes)(4).toString("hex"),
44955
+ id: (0, import_node_crypto11.randomBytes)(4).toString("hex"),
44587
44956
  userId,
44588
44957
  title,
44589
44958
  content,
@@ -45249,7 +45618,7 @@ var isAbortError2 = (error) => {
45249
45618
  return error.name === "AbortError" || error.message.includes("aborted") || error.message.includes("AbortError");
45250
45619
  };
45251
45620
  var llmRequestIdForTurn = (request, messages, system, tools) => {
45252
- const hash = (0, import_node_crypto11.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);
45621
+ const hash = (0, import_node_crypto12.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);
45253
45622
  return `dreq_${hash}`;
45254
45623
  };
45255
45624
  var getDefaultAgentConfig = (tools, systemPrompt) => {
@@ -45855,6 +46224,7 @@ ${memoryInjection}` : "") + dreamInjection;
45855
46224
  }
45856
46225
  hasSentMessage = true;
45857
46226
  sentMessageContent = answer;
46227
+ completePendingCeoFollowupsForUser(request.userId);
45858
46228
  }
45859
46229
  }
45860
46230
  if (useBlock.name === `send_file`) {
@@ -46534,9 +46904,25 @@ var DESCRIPTION41 = `
46534
46904
  1. \u5C06\u56DE\u590D\u5185\u5BB9\u53D1\u9001\u5230\u539F\u53D1\u9001\u8005\u7684\u90AE\u7BB1
46535
46905
  2. \u5C06\u8BE5\u90AE\u4EF6\u6807\u8BB0\u4E3A\u5DF2\u5904\u7406\uFF08done\uFF09
46536
46906
  `;
46537
- var findUpstreamManagerMessage = (myMailboxId, threadId) => {
46538
- if (!threadId) return null;
46907
+ var findUpstreamManagerMessage = (myMailboxId, threadId, workItemId) => {
46539
46908
  const db3 = createSqliteDB();
46909
+ if (workItemId) {
46910
+ const row2 = db3.prepare(
46911
+ `SELECT
46912
+ id,
46913
+ from_mailbox_id as fromMailboxId,
46914
+ to_mailbox_id as toMailboxId,
46915
+ status
46916
+ FROM mailbox
46917
+ WHERE work_item_id = ?
46918
+ AND from_mailbox_id = 'manager'
46919
+ AND to_mailbox_id = ?
46920
+ ORDER BY send_time ASC
46921
+ LIMIT 1`
46922
+ ).get(workItemId, myMailboxId);
46923
+ if (row2) return row2;
46924
+ }
46925
+ if (!threadId) return null;
46540
46926
  const row = db3.prepare(
46541
46927
  `SELECT
46542
46928
  id,
@@ -46552,16 +46938,18 @@ var findUpstreamManagerMessage = (myMailboxId, threadId) => {
46552
46938
  ).get(threadId, myMailboxId);
46553
46939
  return row ?? null;
46554
46940
  };
46555
- var buildUpstreamReminder = (myMailboxId, repliedToMailboxId, threadId) => {
46941
+ var buildUpstreamReminder = (myMailboxId, repliedToMailboxId, threadId, workItemId) => {
46556
46942
  const member = getDepartmentMemberByMailboxId(myMailboxId);
46557
- if (member?.role !== "department_head") return "";
46943
+ const looksLikeHead = myMailboxId.toLowerCase().includes("department-head") || myMailboxId.includes("\u8D1F\u8D23\u4EBA");
46944
+ if (member?.role !== "department_head" && !looksLikeHead) return "";
46558
46945
  if (repliedToMailboxId === "manager") return "";
46559
- const upstream = findUpstreamManagerMessage(myMailboxId, threadId);
46946
+ const upstream = findUpstreamManagerMessage(myMailboxId, threadId, workItemId);
46560
46947
  if (!upstream) return "";
46948
+ if (upstream.status === "done" || upstream.status === "read") return "";
46561
46949
  return [
46562
46950
  ``,
46563
- `[replyMailbox] \u63D0\u9192\uFF1A\u4F60\u521A\u521A\u56DE\u590D\u7684\u662F\u4E0B\u6E38\u6210\u5458 ${repliedToMailboxId}\uFF0C\u4F46\u672C\u7EBF\u7A0B\u7684\u4E0A\u6E38 manager \u90AE\u4EF6 ${upstream.id} \u4ECD\u9700\u8981\u4F60\u540C\u6B65\u6700\u7EC8\u9A8C\u6536/\u6C47\u603B\u3002`,
46564
- `\u5982\u679C\u8FD9\u6B21\u56DE\u590D\u4EE3\u8868\u4EFB\u52A1\u5DF2\u5B8C\u6210\u6216\u5DF2\u9A8C\u6536\uFF0C\u8BF7\u7EE7\u7EED\u8C03\u7528 reply_mailbox(message_id="${upstream.id}", content="...")\uFF08\u82E5\u8BE5\u90AE\u4EF6\u4ECD\u5728 processing\uFF09\uFF0C\u6216 mailbox_followup(message_id="${upstream.id}", content="...", kind="partial_result") \u5C06\u7ED3\u679C\u540C\u6B65\u7ED9 manager\u3002`
46951
+ `[replyMailbox] \u5F3A\u5236\u95ED\u73AF\u63D0\u9192\uFF1A\u4F60\u521A\u521A\u56DE\u590D\u7684\u662F\u4E0B\u6E38\u6210\u5458 ${repliedToMailboxId}\uFF0C\u4F46 work_item \u7684\u4E0A\u6E38 manager \u90AE\u4EF6 ${upstream.id} \u5F53\u524D\u72B6\u6001\u4E3A ${upstream.status}\uFF0C\u4ECD\u9700\u8981\u6700\u7EC8\u6C47\u62A5\u3002`,
46952
+ `\u5982\u679C\u8FD9\u6B21\u56DE\u590D\u4EE3\u8868\u4EFB\u52A1\u5DF2\u5B8C\u6210\u6216\u5DF2\u9A8C\u6536\uFF0C\u8BF7\u7EE7\u7EED\u8C03\u7528 reply_mailbox(message_id="${upstream.id}", content="...") \u5C06\u6700\u7EC8\u7ED3\u679C\u540C\u6B65\u7ED9 manager\uFF1B\u5982\u679C\u4ECD\u5728\u7B49\u5F85\u4E0B\u6E38\uFF0C\u8BF7\u7528 mailbox_followup(message_id="${upstream.id}", content="...", kind="progress") \u6C47\u62A5\u5F53\u524D\u8FDB\u5EA6\u3002`
46565
46953
  ].join("\n");
46566
46954
  };
46567
46955
  var replyMailbox = {
@@ -46598,7 +46986,10 @@ var replyMailbox = {
46598
46986
  origin_user_id as originUserId,
46599
46987
  origin_platform as originPlatform,
46600
46988
  thread_id as threadId,
46601
- parent_message_id as parentMessageId
46989
+ parent_message_id as parentMessageId,
46990
+ work_item_id as workItemId,
46991
+ work_item_role as workItemRole,
46992
+ upstream_message_id as upstreamMessageId
46602
46993
  FROM mailbox WHERE id = ?`
46603
46994
  );
46604
46995
  const msg = stmt.get(messageId);
@@ -46625,7 +47016,10 @@ var replyMailbox = {
46625
47016
  originUserId: msg.originUserId,
46626
47017
  originPlatform: msg.originPlatform,
46627
47018
  threadId: msg.threadId || msg.id,
46628
- parentMessageId: msg.id
47019
+ parentMessageId: msg.id,
47020
+ workItemId: msg.workItemId,
47021
+ workItemRole: msg.workItemRole === "executor_result" ? "downstream_reply" : void 0,
47022
+ upstreamMessageId: msg.upstreamMessageId
46629
47023
  });
46630
47024
  recordMailboxEvent({
46631
47025
  messageId,
@@ -46636,22 +47030,37 @@ var replyMailbox = {
46636
47030
  detail: {
46637
47031
  replyPreview: content.slice(0, 200),
46638
47032
  replyMessageId: replyMsg.id,
46639
- threadId: replyMsg.threadId || msg.threadId || msg.id
47033
+ threadId: replyMsg.threadId || msg.threadId || msg.id,
47034
+ workItemId: msg.workItemId ?? null,
47035
+ upstreamMessageId: msg.upstreamMessageId ?? null
46640
47036
  }
46641
47037
  });
46642
- const upstreamReminder = buildUpstreamReminder(myMailboxId, msg.fromMailboxId, msg.threadId || msg.id);
47038
+ const upstreamReminder = buildUpstreamReminder(myMailboxId, msg.fromMailboxId, msg.threadId || msg.id, msg.workItemId);
46643
47039
  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}`;
46644
47040
  }
46645
47041
  };
46646
47042
 
46647
47043
  // src/cron/mailbox.ts
46648
47044
  var db2 = createSqliteDB();
46649
- var selectStmt = db2.prepare(`select id, to_mailbox_id as toMailboxId, from_mailbox_id as fromMailboxId, content, send_time as sendTime, status
47045
+ var selectStmt = db2.prepare(`select
47046
+ id,
47047
+ to_mailbox_id as toMailboxId,
47048
+ from_mailbox_id as fromMailboxId,
47049
+ content,
47050
+ send_time as sendTime,
47051
+ status,
47052
+ origin_user_id as originUserId,
47053
+ origin_platform as originPlatform,
47054
+ thread_id as threadId,
47055
+ parent_message_id as parentMessageId,
47056
+ work_item_id as workItemId,
47057
+ work_item_role as workItemRole,
47058
+ upstream_message_id as upstreamMessageId
46650
47059
  from mailbox where status = ?`);
46651
47060
  var markMailboxStatus = (msgId, status) => {
46652
47061
  const fromStatusMap = {
46653
47062
  processing: ["pending"],
46654
- done: ["processing"],
47063
+ done: ["pending", "processing", "read"],
46655
47064
  failed: ["processing"],
46656
47065
  cancelled: ["pending", "processing"],
46657
47066
  pending: ["processing"]
@@ -46661,75 +47070,87 @@ var markMailboxStatus = (msgId, status) => {
46661
47070
  reason: "mailbox_poller"
46662
47071
  });
46663
47072
  };
46664
- var handleCeoReply = async (replyMsg) => {
46665
- const { fromMailboxId, content } = replyMsg;
46666
- const originStmt = db2.prepare(
46667
- `SELECT origin_user_id as originUserId, origin_platform as originPlatform
46668
- FROM mailbox
46669
- WHERE from_mailbox_id = 'manager' AND to_mailbox_id = ? AND origin_user_id IS NOT NULL
46670
- ORDER BY send_time DESC LIMIT 1`
46671
- );
46672
- const origin = originStmt.get(fromMailboxId);
46673
- if (!origin || !origin.originUserId) {
46674
- console.warn(`[mailbox] \u65E0\u6CD5\u627E\u5230 ${fromMailboxId} \u7684\u539F\u59CB\u7528\u6237\u4E0A\u4E0B\u6587\uFF0C\u8DF3\u8FC7\u5524\u9192`);
46675
- return;
46676
- }
46677
- console.log(`[mailbox] \u627E\u5230\u539F\u59CB\u7528\u6237\u4E0A\u4E0B\u6587: userId=${origin.originUserId}, platform=${origin.originPlatform}`);
47073
+ var handleCeoFollowup = async (followup) => {
46678
47074
  const event = recordAgentEvent({
46679
- userId: origin.originUserId,
46680
- type: "department.reply_received",
46681
- source: "mailbox",
46682
- sourceId: replyMsg.id,
47075
+ userId: followup.originUserId,
47076
+ type: "ceo.followup_required",
47077
+ source: "ceo_followup",
47078
+ sourceId: followup.id,
46683
47079
  payload: {
46684
- ownerMailboxId: fromMailboxId,
46685
- mailboxMessageId: replyMsg.id,
46686
- threadId: replyMsg.threadId || replyMsg.id,
46687
- parentMessageId: replyMsg.parentMessageId || null,
46688
- contentPreview: content.slice(0, 600),
46689
- originPlatform: origin.originPlatform
47080
+ ownerMailboxId: followup.fromMailboxId,
47081
+ mailboxMessageId: followup.sourceMessageId,
47082
+ ceoFollowupId: followup.id,
47083
+ threadId: followup.threadId || followup.sourceMessageId,
47084
+ parentMessageId: followup.parentMessageId || null,
47085
+ workItemId: followup.workItemId || null,
47086
+ contentPreview: followup.content.slice(0, 1200),
47087
+ summary: `\u90E8\u95E8\u5DF2\u56DE\u4FE1\uFF0CMain Manager/CEO \u5FC5\u987B\u5C06\u7ED3\u679C\u901A\u8FC7 send_message \u6C47\u62A5\u7ED9 Boss/User\uFF1A${followup.content.slice(0, 400)}`,
47088
+ originPlatform: followup.originPlatform
46690
47089
  }
46691
47090
  });
46692
- if (hasRunningAgent(origin.originUserId)) {
46693
- queueInterrupt(origin.originUserId, {
47091
+ if (hasRunningAgent(followup.originUserId)) {
47092
+ queueInterrupt(followup.originUserId, {
46694
47093
  content: "",
46695
47094
  metadata: {
46696
47095
  internalOnly: true,
46697
47096
  eventId: event.id,
46698
- trigger: "department.reply_received"
47097
+ trigger: "ceo.followup_required"
46699
47098
  }
46700
47099
  });
46701
- console.log(`[mailbox] \u4E3B agent \u6B63\u5728\u8FD0\u884C\u4E2D\uFF0C${fromMailboxId} \u7684\u56DE\u4FE1\u5DF2\u5165\u961F\u7B49\u5F85\u4E2D\u65AD\u6CE8\u5165`);
46702
- return;
47100
+ console.log(`[mailbox] \u4E3B agent \u6B63\u5728\u8FD0\u884C\u4E2D\uFF0C${followup.fromMailboxId} \u7684\u56DE\u4FE1\u5DF2\u5165\u961F\u7B49\u5F85\u4E2D\u65AD\u6CE8\u5165 followup=${followup.id}`);
47101
+ return "queued";
46703
47102
  }
46704
47103
  const request = {
46705
- platform: origin.originPlatform,
46706
- userId: origin.originUserId,
46707
- requestId: replyMsg.id,
47104
+ platform: followup.originPlatform,
47105
+ userId: followup.originUserId,
47106
+ requestId: followup.sourceMessageId,
46708
47107
  departmentAgentId: "",
46709
47108
  content: "",
46710
47109
  metadata: {
46711
47110
  internalOnly: true,
46712
47111
  eventId: event.id,
46713
- trigger: "department.reply_received"
47112
+ trigger: "ceo.followup_required",
47113
+ ceoFollowupId: followup.id
46714
47114
  }
46715
47115
  };
46716
47116
  const config2 = getDefaultAgentConfig();
46717
47117
  const mainAgent = createAgent(config2);
46718
47118
  const result = await mainAgent(request);
46719
- console.log(`[mailbox] \u4E3B agent \u5904\u7406\u5B8C ${fromMailboxId} \u7684\u56DE\u4FE1, alreadySent=${result.alreadySent}`);
46720
- if (!result.alreadySent && result.content && config2.channelPlugin) {
47119
+ console.log(`[mailbox] \u4E3B agent \u5904\u7406\u5B8C ${followup.fromMailboxId} \u7684\u56DE\u4FE1, alreadySent=${result.alreadySent}`);
47120
+ if (result.alreadySent) return "completed";
47121
+ const fallback = result.content?.trim() || followup.content;
47122
+ if (fallback && config2.channelPlugin) {
46721
47123
  try {
46722
47124
  await config2.channelPlugin.outbound.sendText({
46723
47125
  cfg: {},
46724
- to: origin.originUserId,
46725
- text: result.content,
46726
- accountId: replyMsg.id
47126
+ to: followup.originUserId,
47127
+ text: fallback,
47128
+ accountId: followup.sourceMessageId
46727
47129
  });
46728
- console.log(`[mailbox] \u4E3B agent \u672A\u4E3B\u52A8\u53D1\u9001\uFF0C\u5DF2\u901A\u8FC7\u6E20\u9053\u8865\u53D1\u7ED3\u679C\u7ED9\u7528\u6237 ${origin.originUserId}`);
47130
+ console.log(`[mailbox] \u4E3B agent \u672A\u4E3B\u52A8\u53D1\u9001\uFF0C\u5DF2\u901A\u8FC7\u6E20\u9053\u8865\u53D1 followup=${followup.id} \u7ED9\u7528\u6237 ${followup.originUserId}`);
47131
+ return "completed";
46729
47132
  } catch (sendErr) {
46730
47133
  console.error(`[mailbox] \u8865\u53D1\u6D88\u606F\u5931\u8D25:`, sendErr);
47134
+ throw sendErr;
46731
47135
  }
46732
47136
  }
47137
+ if (fallback && !config2.channelPlugin) return "completed";
47138
+ throw new Error(`ceo_followup_no_user_visible_message:${followup.id}`);
47139
+ };
47140
+ var processCeoFollowup = async (followup) => {
47141
+ const claimed = claimCeoFollowup(followup.id);
47142
+ if (!claimed) return;
47143
+ try {
47144
+ markMailboxStatus(claimed.sourceMessageId, "processing");
47145
+ const outcome = await handleCeoFollowup(claimed);
47146
+ if (outcome === "queued") return;
47147
+ completeCeoFollowup(claimed.id);
47148
+ markMailboxStatus(claimed.sourceMessageId, "done");
47149
+ } catch (err) {
47150
+ const message = err.message;
47151
+ failCeoFollowup(claimed.id, message);
47152
+ console.error(`[mailbox] CEO followup \u5904\u7406\u5931\u8D25 followup=${claimed.id}:`, err);
47153
+ }
46733
47154
  };
46734
47155
  var wakeDepartmentAgent = async (mailboxId, msgIds) => {
46735
47156
  try {
@@ -46883,7 +47304,8 @@ var pollMailbox = async () => {
46883
47304
  polling = true;
46884
47305
  try {
46885
47306
  const mailBoxMsgs = selectStmt.all("pending");
46886
- if (mailBoxMsgs.length === 0) return;
47307
+ const pendingFollowups = listPendingCeoFollowups();
47308
+ if (mailBoxMsgs.length === 0 && pendingFollowups.length === 0) return;
46887
47309
  console.log(`[mailbox] \u62C9\u53D6\u5230 ${mailBoxMsgs.length} \u6761\u5F85\u5904\u7406\u6D88\u606F`);
46888
47310
  const grouped = /* @__PURE__ */ new Map();
46889
47311
  for (const msg of mailBoxMsgs) {
@@ -46893,20 +47315,28 @@ var pollMailbox = async () => {
46893
47315
  }
46894
47316
  const ceoMsgs = grouped.get("manager") || [];
46895
47317
  grouped.delete("manager");
47318
+ const newFollowups = [];
46896
47319
  for (const msg of ceoMsgs) {
46897
- if (inFlightCeoReplyMessages.has(msg.id)) continue;
46898
- inFlightCeoReplyMessages.add(msg.id);
46899
- console.log(`[mailbox] \u6536\u5230 department agent \u56DE\u4FE1\uFF08\u6765\u81EA ${msg.fromMailboxId}\uFF09\uFF0C\u6B63\u5728\u5524\u9192\u4E3B agent...`);
47320
+ const followup = enqueueCeoFollowupFromMailbox(msg);
47321
+ if (followup) {
47322
+ newFollowups.push(followup);
47323
+ } else {
47324
+ console.warn(`[mailbox] \u6536\u5230\u53D1\u7ED9 manager \u7684\u56DE\u4FE1 ${msg.id}\uFF0C\u4F46\u7F3A\u5C11\u7528\u6237\u4E0A\u4E0B\u6587\uFF0C\u65E0\u6CD5\u521B\u5EFA CEO followup`);
47325
+ }
47326
+ }
47327
+ const followups = [...pendingFollowups, ...newFollowups];
47328
+ const uniqueFollowups = Array.from(new Map(followups.map((followup) => [followup.id, followup])).values());
47329
+ for (const followup of uniqueFollowups) {
47330
+ if (inFlightCeoReplyMessages.has(followup.id)) continue;
47331
+ inFlightCeoReplyMessages.add(followup.id);
47332
+ console.log(`[mailbox] \u6536\u5230 department agent \u56DE\u4FE1\uFF08\u6765\u81EA ${followup.fromMailboxId}\uFF09\uFF0C\u6B63\u5728\u5524\u9192\u4E3B agent followup=${followup.id}...`);
46900
47333
  void (async () => {
46901
47334
  try {
46902
- markMailboxStatus(msg.id, "processing");
46903
- await handleCeoReply(msg);
46904
- markMailboxStatus(msg.id, "done");
47335
+ await processCeoFollowup(followup);
46905
47336
  } catch (err) {
46906
47337
  console.error(`[mailbox] \u5524\u9192\u4E3B agent \u5904\u7406\u56DE\u4FE1\u5931\u8D25:`, err);
46907
- markMailboxStatus(msg.id, "failed");
46908
47338
  } finally {
46909
- inFlightCeoReplyMessages.delete(msg.id);
47339
+ inFlightCeoReplyMessages.delete(followup.id);
46910
47340
  }
46911
47341
  })();
46912
47342
  }
@@ -52002,7 +52432,7 @@ var systemRoutes = new Hono2();
52002
52432
  var startTime = Date.now();
52003
52433
  systemRoutes.get("/system/info", (c) => {
52004
52434
  return c.json({
52005
- version: true ? "1.8.36" : "unknown",
52435
+ version: true ? "1.8.38" : "unknown",
52006
52436
  uptime: Math.floor((Date.now() - startTime) / 1e3),
52007
52437
  env: process.env.NODE_ENV || "development",
52008
52438
  nodeVersion: process.version