botmux 2.99.0 → 2.101.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (147) hide show
  1. package/README.en.md +33 -7
  2. package/README.md +33 -7
  3. package/dist/adapters/backend/sandbox.d.ts +33 -4
  4. package/dist/adapters/backend/sandbox.d.ts.map +1 -1
  5. package/dist/adapters/backend/sandbox.js +90 -29
  6. package/dist/adapters/backend/sandbox.js.map +1 -1
  7. package/dist/adapters/cli/hermes.d.ts.map +1 -1
  8. package/dist/adapters/cli/hermes.js +6 -0
  9. package/dist/adapters/cli/hermes.js.map +1 -1
  10. package/dist/adapters/cli/opencode.d.ts.map +1 -1
  11. package/dist/adapters/cli/opencode.js +241 -13
  12. package/dist/adapters/cli/opencode.js.map +1 -1
  13. package/dist/adapters/cli/traex.d.ts.map +1 -1
  14. package/dist/adapters/cli/traex.js +8 -6
  15. package/dist/adapters/cli/traex.js.map +1 -1
  16. package/dist/adapters/cli/types.d.ts +10 -3
  17. package/dist/adapters/cli/types.d.ts.map +1 -1
  18. package/dist/bot-registry.d.ts +12 -0
  19. package/dist/bot-registry.d.ts.map +1 -1
  20. package/dist/bot-registry.js +10 -3
  21. package/dist/bot-registry.js.map +1 -1
  22. package/dist/cli.d.ts.map +1 -1
  23. package/dist/cli.js +659 -154
  24. package/dist/cli.js.map +1 -1
  25. package/dist/core/cost-calculator.d.ts.map +1 -1
  26. package/dist/core/cost-calculator.js +26 -36
  27. package/dist/core/cost-calculator.js.map +1 -1
  28. package/dist/core/dashboard-ipc-server.d.ts.map +1 -1
  29. package/dist/core/dashboard-ipc-server.js +37 -2
  30. package/dist/core/dashboard-ipc-server.js.map +1 -1
  31. package/dist/core/session-manager.d.ts +11 -0
  32. package/dist/core/session-manager.d.ts.map +1 -1
  33. package/dist/core/session-manager.js +87 -17
  34. package/dist/core/session-manager.js.map +1 -1
  35. package/dist/core/worker-pool.d.ts.map +1 -1
  36. package/dist/core/worker-pool.js +6 -0
  37. package/dist/core/worker-pool.js.map +1 -1
  38. package/dist/daemon.d.ts +1 -1
  39. package/dist/daemon.d.ts.map +1 -1
  40. package/dist/daemon.js +24 -8
  41. package/dist/daemon.js.map +1 -1
  42. package/dist/dashboard/bot-onboarding.d.ts +6 -0
  43. package/dist/dashboard/bot-onboarding.d.ts.map +1 -1
  44. package/dist/dashboard/bot-onboarding.js +3 -1
  45. package/dist/dashboard/bot-onboarding.js.map +1 -1
  46. package/dist/dashboard/web/bot-onboarding.d.ts.map +1 -1
  47. package/dist/dashboard/web/bot-onboarding.js +24 -3
  48. package/dist/dashboard/web/bot-onboarding.js.map +1 -1
  49. package/dist/dashboard/web/i18n.d.ts.map +1 -1
  50. package/dist/dashboard/web/i18n.js +14 -4
  51. package/dist/dashboard/web/i18n.js.map +1 -1
  52. package/dist/dashboard/web/sessions.d.ts.map +1 -1
  53. package/dist/dashboard/web/sessions.js +5 -19
  54. package/dist/dashboard/web/sessions.js.map +1 -1
  55. package/dist/dashboard-web/app.js +40 -33
  56. package/dist/dashboard-web/chunks/{bot-defaults-page-3EV7K6LJ.js → bot-defaults-page-HOGLABBC.js} +1 -1
  57. package/dist/dashboard-web/chunks/{chunk-NASYW5FD.js → chunk-ECXPBQ3J.js} +1 -1
  58. package/dist/dashboard-web/chunks/chunk-MR57RUVP.js +31 -0
  59. package/dist/dashboard-web/chunks/{connectors-XPZKEHF6.js → connectors-UGTF4Q4I.js} +1 -1
  60. package/dist/dashboard-web/chunks/{groups-page-C54PVKYP.js → groups-page-IKTCMQ4A.js} +1 -1
  61. package/dist/dashboard-web/chunks/{insights-page-BBQYR7WY.js → insights-page-7CCSHEKM.js} +1 -1
  62. package/dist/dashboard-web/chunks/{overview-page-5PJCAMID.js → overview-page-JOJW65P5.js} +1 -1
  63. package/dist/dashboard-web/chunks/{roles-page-APUDLPVM.js → roles-page-E2VN2DLV.js} +1 -1
  64. package/dist/dashboard-web/chunks/{schedules-WG2UKHSO.js → schedules-6QIHJIHX.js} +1 -1
  65. package/dist/dashboard-web/chunks/sessions-page-QN2TARF2.js +238 -0
  66. package/dist/dashboard-web/chunks/{settings-page-OSBZNCXL.js → settings-page-WWTXB577.js} +1 -1
  67. package/dist/dashboard-web/chunks/{skills-page-Y3VUAOYG.js → skills-page-2FAUPQ6H.js} +1 -1
  68. package/dist/dashboard-web/chunks/{team-federation-page-CRH3WZPH.js → team-federation-page-PTBQQSFS.js} +1 -1
  69. package/dist/dashboard-web/chunks/{workflows-UB7OPYGI.js → workflows-ZNBB5KFV.js} +1 -1
  70. package/dist/dashboard.js +86 -1
  71. package/dist/dashboard.js.map +1 -1
  72. package/dist/i18n/en.d.ts.map +1 -1
  73. package/dist/i18n/en.js +2 -0
  74. package/dist/i18n/en.js.map +1 -1
  75. package/dist/i18n/zh.d.ts.map +1 -1
  76. package/dist/i18n/zh.js +2 -0
  77. package/dist/i18n/zh.js.map +1 -1
  78. package/dist/im/lark/card-builder.d.ts +2 -2
  79. package/dist/im/lark/card-builder.js +2 -2
  80. package/dist/im/lark/event-dispatcher.d.ts +8 -3
  81. package/dist/im/lark/event-dispatcher.d.ts.map +1 -1
  82. package/dist/im/lark/event-dispatcher.js +45 -9
  83. package/dist/im/lark/event-dispatcher.js.map +1 -1
  84. package/dist/platform/bind.d.ts.map +1 -1
  85. package/dist/platform/bind.js +36 -15
  86. package/dist/platform/bind.js.map +1 -1
  87. package/dist/platform/binding.d.ts +5 -0
  88. package/dist/platform/binding.d.ts.map +1 -1
  89. package/dist/platform/binding.js +11 -0
  90. package/dist/platform/binding.js.map +1 -1
  91. package/dist/platform/platform-http.d.ts +11 -0
  92. package/dist/platform/platform-http.d.ts.map +1 -0
  93. package/dist/platform/platform-http.js +41 -0
  94. package/dist/platform/platform-http.js.map +1 -0
  95. package/dist/platform/tunnel-client.d.ts +14 -0
  96. package/dist/platform/tunnel-client.d.ts.map +1 -1
  97. package/dist/platform/tunnel-client.js +40 -3
  98. package/dist/platform/tunnel-client.js.map +1 -1
  99. package/dist/services/bot-union-ids-store.d.ts +9 -0
  100. package/dist/services/bot-union-ids-store.d.ts.map +1 -0
  101. package/dist/services/bot-union-ids-store.js +59 -0
  102. package/dist/services/bot-union-ids-store.js.map +1 -0
  103. package/dist/services/coco-transcript.d.ts.map +1 -1
  104. package/dist/services/coco-transcript.js +59 -64
  105. package/dist/services/coco-transcript.js.map +1 -1
  106. package/dist/services/jsonl-cursor.d.ts +12 -0
  107. package/dist/services/jsonl-cursor.d.ts.map +1 -1
  108. package/dist/services/jsonl-cursor.js +63 -4
  109. package/dist/services/jsonl-cursor.js.map +1 -1
  110. package/dist/services/opencode-paths.d.ts +7 -0
  111. package/dist/services/opencode-paths.d.ts.map +1 -0
  112. package/dist/services/opencode-paths.js +18 -0
  113. package/dist/services/opencode-paths.js.map +1 -0
  114. package/dist/services/platform-team-store.d.ts +37 -0
  115. package/dist/services/platform-team-store.d.ts.map +1 -0
  116. package/dist/services/platform-team-store.js +120 -0
  117. package/dist/services/platform-team-store.js.map +1 -0
  118. package/dist/services/team-groups-store.d.ts +14 -1
  119. package/dist/services/team-groups-store.d.ts.map +1 -1
  120. package/dist/services/team-groups-store.js +28 -1
  121. package/dist/services/team-groups-store.js.map +1 -1
  122. package/dist/setup/bot-config-editor.d.ts +6 -0
  123. package/dist/setup/bot-config-editor.d.ts.map +1 -1
  124. package/dist/setup/bot-config-editor.js +18 -15
  125. package/dist/setup/bot-config-editor.js.map +1 -1
  126. package/dist/setup/interactive-select.d.ts +22 -0
  127. package/dist/setup/interactive-select.d.ts.map +1 -1
  128. package/dist/setup/interactive-select.js +101 -7
  129. package/dist/setup/interactive-select.js.map +1 -1
  130. package/dist/setup/open-platform-automation.d.ts +42 -0
  131. package/dist/setup/open-platform-automation.d.ts.map +1 -1
  132. package/dist/setup/open-platform-automation.js +107 -0
  133. package/dist/setup/open-platform-automation.js.map +1 -1
  134. package/dist/setup/setup-args.d.ts +77 -0
  135. package/dist/setup/setup-args.d.ts.map +1 -0
  136. package/dist/setup/setup-args.js +272 -0
  137. package/dist/setup/setup-args.js.map +1 -0
  138. package/dist/types.d.ts +6 -0
  139. package/dist/types.d.ts.map +1 -1
  140. package/dist/worker.js +12 -2
  141. package/dist/worker.js.map +1 -1
  142. package/dist/workflows/attempt-resume.d.ts.map +1 -1
  143. package/dist/workflows/attempt-resume.js +4 -1
  144. package/dist/workflows/attempt-resume.js.map +1 -1
  145. package/package.json +1 -1
  146. package/dist/dashboard-web/chunks/chunk-JXLHRRJD.js +0 -31
  147. package/dist/dashboard-web/chunks/sessions-page-F3U5NFPD.js +0 -238
package/dist/dashboard.js CHANGED
@@ -57,6 +57,8 @@ import { isValidRoleProfileId } from './services/role-profile-store.js';
57
57
  import { mergeSafeInsightOverviews } from './services/insight/report.js';
58
58
  import { readPlatformBinding } from './platform/binding.js';
59
59
  import { startPlatformTunnelClient } from './platform/tunnel-client.js';
60
+ import { applyPlatformTeamSync, getPlatformTeamSyncRev, listPlatformTeams } from './services/platform-team-store.js';
61
+ import { getBotUnionId } from './services/bot-union-ids-store.js';
60
62
  import { cleanupIdleSessions, parseIdleCleanupHours } from './dashboard/session-cleanup.js';
61
63
  const SECRET_PATH = join(homedir(), '.botmux', '.dashboard-secret');
62
64
  const TOKEN_PATH = join(homedir(), '.botmux', '.dashboard-token');
@@ -1472,8 +1474,15 @@ const server = createServer(async (req, res) => {
1472
1474
  if (bad.length > 0) {
1473
1475
  return jsonRes(res, 400, { ok: false, error: 'invalid_working_dir', message: `目录不存在或不是目录: ${bad.join(', ')}` });
1474
1476
  }
1477
+ // 目录模式: 'fixed' → defaultWorkingDir(直接启动);'card' → workingDir(弹卡)。
1478
+ // 缺省不传按 'card' 处理,兼容不带该字段的旧客户端。
1479
+ const dirModeRaw = typeof parsed.dirMode === 'string' ? parsed.dirMode.trim() : '';
1480
+ if (dirModeRaw && dirModeRaw !== 'fixed' && dirModeRaw !== 'card') {
1481
+ return jsonRes(res, 400, { ok: false, error: 'invalid_dir_mode', message: 'dirMode 必须是 fixed 或 card' });
1482
+ }
1483
+ const dirMode = dirModeRaw === 'fixed' ? 'fixed' : dirModeRaw === 'card' ? 'card' : undefined;
1475
1484
  const model = typeof parsed.model === 'string' && parsed.model.trim() ? parsed.model.trim() : undefined;
1476
- const job = botOnboarding.start({ cliId, wrapperCli, workingDir, model });
1485
+ const job = botOnboarding.start({ cliId, wrapperCli, workingDir, dirMode, model });
1477
1486
  return jsonRes(res, 202, { job: botOnboarding.get(job.id) });
1478
1487
  }
1479
1488
  let mOwner;
@@ -2647,6 +2656,9 @@ function readPlatformBotsInfo() {
2647
2656
  avatar: e.botAvatarUrl || undefined,
2648
2657
  cli: e.cliId,
2649
2658
  showInTeam: cfg?.showInTeam !== false, // default true
2659
+ // 自家消息回声学到的租户稳定 union_id(可能尚未学到 → undefined)。
2660
+ // 平台聚合团队 roster 用,见 bot-union-ids-store / platform-team-store。
2661
+ unionId: e.larkAppId ? getBotUnionId(config.session.dataDir, e.larkAppId) : undefined,
2650
2662
  };
2651
2663
  })
2652
2664
  .filter((b) => b.appId);
@@ -2667,14 +2679,87 @@ function startPlatformTunnelIfBound() {
2667
2679
  getDashboardToken: () => activeToken,
2668
2680
  getVersion: () => version,
2669
2681
  getBots: () => readPlatformBotsInfo(),
2682
+ getTeamSyncRev: () => getPlatformTeamSyncRev(config.session.dataDir),
2683
+ onTeamSync: handlePlatformTeamSync,
2670
2684
  log: (msg, extra) => logger.info(`[platform-tunnel] ${msg}${extra ? ' ' + JSON.stringify(extra) : ''}`),
2671
2685
  });
2672
2686
  logger.info(`[platform-tunnel] 绑定到 ${binding.platformUrl},启动隧道`);
2687
+ // 大厅打卡自愈重试:team-sync 应用时会立即尝试一次;这里的低频周期兜住
2688
+ // "当时 daemon 离线 / bot 还没进大厅 / 发送失败"的漏拍。无平台绑定不启动。
2689
+ const hallTimer = setInterval(() => { void maybeAnnounceHallPresence(); }, 5 * 60 * 1000);
2690
+ hallTimer.unref();
2673
2691
  }
2674
2692
  catch (e) {
2675
2693
  logger.warn(`[platform-tunnel] 启动失败: ${e.message}`);
2676
2694
  }
2677
2695
  }
2696
+ /** 平台 team-sync 落盘(roster + 团队群镜像),随后触发一轮大厅打卡检查。 */
2697
+ function handlePlatformTeamSync(payload) {
2698
+ const applied = applyPlatformTeamSync(config.session.dataDir, payload);
2699
+ if (!applied) {
2700
+ logger.warn('[platform-tunnel] team-sync 负载无效,忽略');
2701
+ return;
2702
+ }
2703
+ logger.info(`[platform-tunnel] team-sync 已应用 rev=${applied.rev} teams=${applied.teams.length}`);
2704
+ void maybeAnnounceHallPresence();
2705
+ }
2706
+ // 大厅打卡(union_id 自学触发)节流:per-bot 最小间隔 + 每进程尝试上限。打卡消息
2707
+ // 本身只有 bot 可见(大厅是 bot-only 群),上限只是防御发送持续失败时的无谓重试。
2708
+ const hallAnnounceState = new Map();
2709
+ const HALL_ANNOUNCE_MIN_INTERVAL_MS = 10 * 60 * 1000;
2710
+ const HALL_ANNOUNCE_MAX_TRIES = 6;
2711
+ /**
2712
+ * 让还没学到自己 union_id 的本地 bot 去团队大厅发一条打卡消息:自家消息回声
2713
+ * (event-dispatcher isSelfMessage 分支)带回 sender.sender_id.union_id → 落盘
2714
+ * bot-union-ids → 下个心跳上报平台进 roster。一辈子一次;学到即永久跳过。
2715
+ * 顺带的副作用:大厅在各成员机器的 team-groups 里(team-sync 镜像),其他
2716
+ * daemon 收到这条消息会直接 recordTeamBot 学到该 bot——roster 之外的即时互学。
2717
+ */
2718
+ async function maybeAnnounceHallPresence() {
2719
+ try {
2720
+ const dataDir = config.session.dataDir;
2721
+ const teams = listPlatformTeams(dataDir);
2722
+ if (teams.length === 0)
2723
+ return;
2724
+ const localBotIds = new Set(readPlatformBotsInfo().map(b => b.appId));
2725
+ const now = Date.now();
2726
+ for (const team of teams) {
2727
+ const hallChatId = team.groupChatIds[0];
2728
+ if (!hallChatId)
2729
+ continue;
2730
+ for (const bot of team.bots) {
2731
+ if (!localBotIds.has(bot.appId))
2732
+ continue; // 别的机器的 bot
2733
+ if (getBotUnionId(dataDir, bot.appId))
2734
+ continue; // 已学到 → 永久跳过
2735
+ const st = hallAnnounceState.get(bot.appId);
2736
+ if (st && (now - st.lastAt < HALL_ANNOUNCE_MIN_INTERVAL_MS || st.tries >= HALL_ANNOUNCE_MAX_TRIES))
2737
+ continue;
2738
+ hallAnnounceState.set(bot.appId, { lastAt: now, tries: (st?.tries ?? 0) + 1 });
2739
+ try {
2740
+ const r = await proxyToDaemon(bot.appId, '/api/platform/hall-announce', {
2741
+ method: 'POST',
2742
+ headers: { 'content-type': 'application/json' },
2743
+ body: JSON.stringify({ chatId: hallChatId }),
2744
+ });
2745
+ const j = await r.json().catch(() => ({}));
2746
+ if (!r.ok || !j.ok) {
2747
+ logger.warn(`[platform-tunnel] 大厅打卡失败 bot=${bot.appId} chat=${hallChatId.substring(0, 12)}: ${j.error ?? r.status}`);
2748
+ }
2749
+ else {
2750
+ logger.info(`[platform-tunnel] 大厅打卡已发 bot=${bot.appId} chat=${hallChatId.substring(0, 12)}(等待回声学 union_id)`);
2751
+ }
2752
+ }
2753
+ catch (e) {
2754
+ logger.warn(`[platform-tunnel] 大厅打卡请求异常 bot=${bot.appId}: ${e.message}`);
2755
+ }
2756
+ }
2757
+ }
2758
+ }
2759
+ catch (e) {
2760
+ logger.warn(`[platform-tunnel] 大厅打卡检查异常: ${e.message}`);
2761
+ }
2762
+ }
2678
2763
  // Graceful shutdown
2679
2764
  function shutdown() {
2680
2765
  for (const off of subs.values())