duclaw-cli 1.8.37 → 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.37" : "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 = () => {
@@ -41565,6 +41566,34 @@ var create_mailbox_events_table = () => {
41565
41566
  } catch (_) {
41566
41567
  }
41567
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
+ };
41568
41597
  var create_agent_events_table = () => {
41569
41598
  const db3 = createSqliteDB();
41570
41599
  db3.exec(`
@@ -41771,11 +41800,21 @@ var renderAgentEventReminder = (events) => {
41771
41800
  summary ? `summary=${summary}` : ""
41772
41801
  ].filter(Boolean).join(" ");
41773
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") : "";
41774
41812
  return `<system-reminder>
41775
41813
  \u672C\u8F6E\u6709 ${events.length} \u6761\u5185\u90E8\u4E8B\u4EF6\u53EF\u7528\uFF1A
41776
41814
  ${lines}
41777
41815
 
41778
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}
41779
41818
  </system-reminder>`;
41780
41819
  };
41781
41820
 
@@ -42104,6 +42143,208 @@ var deleteDepartmentMemberById = (departmentName, memberId) => {
42104
42143
  deleteWorkspace(workspaceId);
42105
42144
  };
42106
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
+
42107
42348
  // src/department/mailbox/mailbox.ts
42108
42349
  var getMailBoxId = (departmentName, memberName) => {
42109
42350
  return `${departmentName}::${memberName}`;
@@ -42267,7 +42508,7 @@ var recordMailboxReceivedAgentEvent = (msg) => {
42267
42508
  };
42268
42509
  var sendMessage2 = (fromMailboxId, toMailboxId, content, options) => {
42269
42510
  const db3 = createSqliteDB();
42270
- const id = (0, import_node_crypto4.randomUUID)().slice(0, 8);
42511
+ const id = (0, import_node_crypto5.randomUUID)().slice(0, 8);
42271
42512
  const threadId = options?.threadId || id;
42272
42513
  const workItemContext = resolveWorkItemContext(fromMailboxId, toMailboxId, id, options);
42273
42514
  const stmt = db3.prepare(`insert into mailbox (
@@ -42332,6 +42573,7 @@ var sendMessage2 = (fromMailboxId, toMailboxId, content, options) => {
42332
42573
  });
42333
42574
  recordMailboxReceivedAgentEvent(mailboxMsg);
42334
42575
  queueMailboxInterruptIfRunning(mailboxMsg);
42576
+ enqueueCeoFollowupFromMailbox(mailboxMsg);
42335
42577
  return mailboxMsg;
42336
42578
  };
42337
42579
  var updateMailboxMessageStatus = (messageId, nextStatus, options) => {
@@ -42409,7 +42651,7 @@ var departmentCreate = {
42409
42651
  return `[departmentCreate] \u4E0D\u5B58\u5728 id=${sourceGoalId} \u7684\u76EE\u6807`;
42410
42652
  }
42411
42653
  let departmentDefinition = {
42412
- id: (0, import_node_crypto5.randomUUID)().slice(0, 8),
42654
+ id: (0, import_node_crypto6.randomUUID)().slice(0, 8),
42413
42655
  name,
42414
42656
  charter,
42415
42657
  sourceGoalId,
@@ -42652,7 +42894,7 @@ var departmentList = {
42652
42894
  };
42653
42895
 
42654
42896
  // src/tools/tools/department/DepartmentMemberCreate.ts
42655
- var import_node_crypto6 = require("node:crypto");
42897
+ var import_node_crypto7 = require("node:crypto");
42656
42898
  var DESCRIPTION24 = `
42657
42899
  \u521B\u5EFA\u90E8\u95E8\u6210\u5458\u3002
42658
42900
 
@@ -42718,7 +42960,7 @@ var departmentMemberCreate = {
42718
42960
  }
42719
42961
  }
42720
42962
  let departmentMember = {
42721
- id: (0, import_node_crypto6.randomUUID)().slice(0, 8),
42963
+ id: (0, import_node_crypto7.randomUUID)().slice(0, 8),
42722
42964
  name,
42723
42965
  departmentId: department.id,
42724
42966
  mailBoxId: getMailBoxId(department.name, name),
@@ -42909,7 +43151,7 @@ ${replies}`;
42909
43151
  // src/department/learning.ts
42910
43152
  var import_node_fs4 = require("node:fs");
42911
43153
  var import_node_path12 = __toESM(require("node:path"));
42912
- var import_node_crypto7 = require("node:crypto");
43154
+ var import_node_crypto8 = require("node:crypto");
42913
43155
 
42914
43156
  // src/skill/SkillValidator.ts
42915
43157
  var import_node_fs3 = require("node:fs");
@@ -43147,7 +43389,7 @@ var listDepartmentMemories = (departmentName) => {
43147
43389
  var createDepartmentMemory = (departmentName, input) => {
43148
43390
  const now = Date.now();
43149
43391
  const memory = {
43150
- id: (0, import_node_crypto7.randomUUID)().slice(0, 8),
43392
+ id: (0, import_node_crypto8.randomUUID)().slice(0, 8),
43151
43393
  departmentName,
43152
43394
  title: input.title,
43153
43395
  content: input.content,
@@ -43198,7 +43440,7 @@ ${formatSkillValidationIssues(validation)}`);
43198
43440
  }
43199
43441
  const now = Date.now();
43200
43442
  const skill = {
43201
- id: (0, import_node_crypto7.randomUUID)().slice(0, 8),
43443
+ id: (0, import_node_crypto8.randomUUID)().slice(0, 8),
43202
43444
  departmentName,
43203
43445
  skillName: input.skillName,
43204
43446
  description: input.description,
@@ -43250,7 +43492,7 @@ var createDepartmentProposal = (input) => {
43250
43492
  const records = readJsonArray(proposalsPath());
43251
43493
  const proposal = {
43252
43494
  ...input,
43253
- id: (0, import_node_crypto7.randomUUID)().slice(0, 8),
43495
+ id: (0, import_node_crypto8.randomUUID)().slice(0, 8),
43254
43496
  status: "pending",
43255
43497
  createdAt: Date.now()
43256
43498
  };
@@ -43581,7 +43823,7 @@ var mailboxFollowup = {
43581
43823
 
43582
43824
  // src/tools/tools/Bash.ts
43583
43825
  var import_node_child_process = require("node:child_process");
43584
- var import_node_crypto8 = require("node:crypto");
43826
+ var import_node_crypto9 = require("node:crypto");
43585
43827
  var import_node_fs5 = require("node:fs");
43586
43828
  var DESCRIPTION29 = `\u5728\u7CFB\u7EDF shell \u4E2D\u6267\u884C\u547D\u4EE4\u3002
43587
43829
 
@@ -43785,7 +44027,7 @@ var bashTool = {
43785
44027
  ...options,
43786
44028
  stdio: ["pipe", "pipe", "pipe"]
43787
44029
  });
43788
- const id = (0, import_node_crypto8.randomUUID)().slice(0, 8);
44030
+ const id = (0, import_node_crypto9.randomUUID)().slice(0, 8);
43789
44031
  const session = {
43790
44032
  id,
43791
44033
  command,
@@ -44366,7 +44608,7 @@ var readDreamHistoryLimit = () => {
44366
44608
  var import_node_fs6 = require("node:fs");
44367
44609
  var import_node_os2 = require("node:os");
44368
44610
  var import_node_path13 = require("node:path");
44369
- var import_node_crypto9 = require("node:crypto");
44611
+ var import_node_crypto10 = require("node:crypto");
44370
44612
  var SkillForgeEngine = class {
44371
44613
  proposalStorage;
44372
44614
  draftRoot;
@@ -44400,7 +44642,7 @@ ${formatSkillValidationIssues(validation)}`);
44400
44642
  if (pending.some((p) => p.skillName === skillName)) {
44401
44643
  return null;
44402
44644
  }
44403
- const id = (0, import_node_crypto9.randomBytes)(4).toString("hex");
44645
+ const id = (0, import_node_crypto10.randomBytes)(4).toString("hex");
44404
44646
  const draftDir = (0, import_node_path13.join)(this.draftRoot, userId, id);
44405
44647
  (0, import_node_fs6.mkdirSync)(draftDir, { recursive: true });
44406
44648
  (0, import_node_fs6.writeFileSync)((0, import_node_path13.join)(draftDir, "SKILL.md"), skillMd, "utf-8");
@@ -44682,7 +44924,7 @@ var skillForgeDrop = (engine) => ({
44682
44924
  });
44683
44925
 
44684
44926
  // src/memory/MemoryEngine.ts
44685
- var import_node_crypto10 = require("node:crypto");
44927
+ var import_node_crypto11 = require("node:crypto");
44686
44928
  var MemoryEngine = class {
44687
44929
  storage;
44688
44930
  recallIndexStorage;
@@ -44710,7 +44952,7 @@ var MemoryEngine = class {
44710
44952
  }
44711
44953
  const now = Date.now();
44712
44954
  const memory = {
44713
- id: (0, import_node_crypto10.randomBytes)(4).toString("hex"),
44955
+ id: (0, import_node_crypto11.randomBytes)(4).toString("hex"),
44714
44956
  userId,
44715
44957
  title,
44716
44958
  content,
@@ -45376,7 +45618,7 @@ var isAbortError2 = (error) => {
45376
45618
  return error.name === "AbortError" || error.message.includes("aborted") || error.message.includes("AbortError");
45377
45619
  };
45378
45620
  var llmRequestIdForTurn = (request, messages, system, tools) => {
45379
- 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);
45380
45622
  return `dreq_${hash}`;
45381
45623
  };
45382
45624
  var getDefaultAgentConfig = (tools, systemPrompt) => {
@@ -45982,6 +46224,7 @@ ${memoryInjection}` : "") + dreamInjection;
45982
46224
  }
45983
46225
  hasSentMessage = true;
45984
46226
  sentMessageContent = answer;
46227
+ completePendingCeoFollowupsForUser(request.userId);
45985
46228
  }
45986
46229
  }
45987
46230
  if (useBlock.name === `send_file`) {
@@ -46799,12 +47042,25 @@ var replyMailbox = {
46799
47042
 
46800
47043
  // src/cron/mailbox.ts
46801
47044
  var db2 = createSqliteDB();
46802
- 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
46803
47059
  from mailbox where status = ?`);
46804
47060
  var markMailboxStatus = (msgId, status) => {
46805
47061
  const fromStatusMap = {
46806
47062
  processing: ["pending"],
46807
- done: ["processing"],
47063
+ done: ["pending", "processing", "read"],
46808
47064
  failed: ["processing"],
46809
47065
  cancelled: ["pending", "processing"],
46810
47066
  pending: ["processing"]
@@ -46814,75 +47070,87 @@ var markMailboxStatus = (msgId, status) => {
46814
47070
  reason: "mailbox_poller"
46815
47071
  });
46816
47072
  };
46817
- var handleCeoReply = async (replyMsg) => {
46818
- const { fromMailboxId, content } = replyMsg;
46819
- const originStmt = db2.prepare(
46820
- `SELECT origin_user_id as originUserId, origin_platform as originPlatform
46821
- FROM mailbox
46822
- WHERE from_mailbox_id = 'manager' AND to_mailbox_id = ? AND origin_user_id IS NOT NULL
46823
- ORDER BY send_time DESC LIMIT 1`
46824
- );
46825
- const origin = originStmt.get(fromMailboxId);
46826
- if (!origin || !origin.originUserId) {
46827
- console.warn(`[mailbox] \u65E0\u6CD5\u627E\u5230 ${fromMailboxId} \u7684\u539F\u59CB\u7528\u6237\u4E0A\u4E0B\u6587\uFF0C\u8DF3\u8FC7\u5524\u9192`);
46828
- return;
46829
- }
46830
- console.log(`[mailbox] \u627E\u5230\u539F\u59CB\u7528\u6237\u4E0A\u4E0B\u6587: userId=${origin.originUserId}, platform=${origin.originPlatform}`);
47073
+ var handleCeoFollowup = async (followup) => {
46831
47074
  const event = recordAgentEvent({
46832
- userId: origin.originUserId,
46833
- type: "department.reply_received",
46834
- source: "mailbox",
46835
- sourceId: replyMsg.id,
47075
+ userId: followup.originUserId,
47076
+ type: "ceo.followup_required",
47077
+ source: "ceo_followup",
47078
+ sourceId: followup.id,
46836
47079
  payload: {
46837
- ownerMailboxId: fromMailboxId,
46838
- mailboxMessageId: replyMsg.id,
46839
- threadId: replyMsg.threadId || replyMsg.id,
46840
- parentMessageId: replyMsg.parentMessageId || null,
46841
- contentPreview: content.slice(0, 600),
46842
- 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
46843
47089
  }
46844
47090
  });
46845
- if (hasRunningAgent(origin.originUserId)) {
46846
- queueInterrupt(origin.originUserId, {
47091
+ if (hasRunningAgent(followup.originUserId)) {
47092
+ queueInterrupt(followup.originUserId, {
46847
47093
  content: "",
46848
47094
  metadata: {
46849
47095
  internalOnly: true,
46850
47096
  eventId: event.id,
46851
- trigger: "department.reply_received"
47097
+ trigger: "ceo.followup_required"
46852
47098
  }
46853
47099
  });
46854
- console.log(`[mailbox] \u4E3B agent \u6B63\u5728\u8FD0\u884C\u4E2D\uFF0C${fromMailboxId} \u7684\u56DE\u4FE1\u5DF2\u5165\u961F\u7B49\u5F85\u4E2D\u65AD\u6CE8\u5165`);
46855
- 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";
46856
47102
  }
46857
47103
  const request = {
46858
- platform: origin.originPlatform,
46859
- userId: origin.originUserId,
46860
- requestId: replyMsg.id,
47104
+ platform: followup.originPlatform,
47105
+ userId: followup.originUserId,
47106
+ requestId: followup.sourceMessageId,
46861
47107
  departmentAgentId: "",
46862
47108
  content: "",
46863
47109
  metadata: {
46864
47110
  internalOnly: true,
46865
47111
  eventId: event.id,
46866
- trigger: "department.reply_received"
47112
+ trigger: "ceo.followup_required",
47113
+ ceoFollowupId: followup.id
46867
47114
  }
46868
47115
  };
46869
47116
  const config2 = getDefaultAgentConfig();
46870
47117
  const mainAgent = createAgent(config2);
46871
47118
  const result = await mainAgent(request);
46872
- console.log(`[mailbox] \u4E3B agent \u5904\u7406\u5B8C ${fromMailboxId} \u7684\u56DE\u4FE1, alreadySent=${result.alreadySent}`);
46873
- 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) {
46874
47123
  try {
46875
47124
  await config2.channelPlugin.outbound.sendText({
46876
47125
  cfg: {},
46877
- to: origin.originUserId,
46878
- text: result.content,
46879
- accountId: replyMsg.id
47126
+ to: followup.originUserId,
47127
+ text: fallback,
47128
+ accountId: followup.sourceMessageId
46880
47129
  });
46881
- 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";
46882
47132
  } catch (sendErr) {
46883
47133
  console.error(`[mailbox] \u8865\u53D1\u6D88\u606F\u5931\u8D25:`, sendErr);
47134
+ throw sendErr;
46884
47135
  }
46885
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
+ }
46886
47154
  };
46887
47155
  var wakeDepartmentAgent = async (mailboxId, msgIds) => {
46888
47156
  try {
@@ -47036,7 +47304,8 @@ var pollMailbox = async () => {
47036
47304
  polling = true;
47037
47305
  try {
47038
47306
  const mailBoxMsgs = selectStmt.all("pending");
47039
- if (mailBoxMsgs.length === 0) return;
47307
+ const pendingFollowups = listPendingCeoFollowups();
47308
+ if (mailBoxMsgs.length === 0 && pendingFollowups.length === 0) return;
47040
47309
  console.log(`[mailbox] \u62C9\u53D6\u5230 ${mailBoxMsgs.length} \u6761\u5F85\u5904\u7406\u6D88\u606F`);
47041
47310
  const grouped = /* @__PURE__ */ new Map();
47042
47311
  for (const msg of mailBoxMsgs) {
@@ -47046,20 +47315,28 @@ var pollMailbox = async () => {
47046
47315
  }
47047
47316
  const ceoMsgs = grouped.get("manager") || [];
47048
47317
  grouped.delete("manager");
47318
+ const newFollowups = [];
47049
47319
  for (const msg of ceoMsgs) {
47050
- if (inFlightCeoReplyMessages.has(msg.id)) continue;
47051
- inFlightCeoReplyMessages.add(msg.id);
47052
- 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}...`);
47053
47333
  void (async () => {
47054
47334
  try {
47055
- markMailboxStatus(msg.id, "processing");
47056
- await handleCeoReply(msg);
47057
- markMailboxStatus(msg.id, "done");
47335
+ await processCeoFollowup(followup);
47058
47336
  } catch (err) {
47059
47337
  console.error(`[mailbox] \u5524\u9192\u4E3B agent \u5904\u7406\u56DE\u4FE1\u5931\u8D25:`, err);
47060
- markMailboxStatus(msg.id, "failed");
47061
47338
  } finally {
47062
- inFlightCeoReplyMessages.delete(msg.id);
47339
+ inFlightCeoReplyMessages.delete(followup.id);
47063
47340
  }
47064
47341
  })();
47065
47342
  }
@@ -52155,7 +52432,7 @@ var systemRoutes = new Hono2();
52155
52432
  var startTime = Date.now();
52156
52433
  systemRoutes.get("/system/info", (c) => {
52157
52434
  return c.json({
52158
- version: true ? "1.8.37" : "unknown",
52435
+ version: true ? "1.8.38" : "unknown",
52159
52436
  uptime: Math.floor((Date.now() - startTime) / 1e3),
52160
52437
  env: process.env.NODE_ENV || "development",
52161
52438
  nodeVersion: process.version