botmux 3.1.0 → 3.2.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 (204) hide show
  1. package/dist/adapters/backend/sandbox.d.ts +23 -0
  2. package/dist/adapters/backend/sandbox.d.ts.map +1 -1
  3. package/dist/adapters/backend/sandbox.js +69 -4
  4. package/dist/adapters/backend/sandbox.js.map +1 -1
  5. package/dist/adapters/backend/tmux-backend.d.ts.map +1 -1
  6. package/dist/adapters/backend/tmux-backend.js +11 -1
  7. package/dist/adapters/backend/tmux-backend.js.map +1 -1
  8. package/dist/adapters/cli/read-isolation.d.ts +1 -1
  9. package/dist/adapters/cli/read-isolation.d.ts.map +1 -1
  10. package/dist/adapters/cli/read-isolation.js +15 -7
  11. package/dist/adapters/cli/read-isolation.js.map +1 -1
  12. package/dist/cli.d.ts.map +1 -1
  13. package/dist/cli.js +117 -25
  14. package/dist/cli.js.map +1 -1
  15. package/dist/core/command-handler.d.ts.map +1 -1
  16. package/dist/core/command-handler.js +154 -90
  17. package/dist/core/command-handler.js.map +1 -1
  18. package/dist/core/dashboard-ipc-server.d.ts +1 -0
  19. package/dist/core/dashboard-ipc-server.d.ts.map +1 -1
  20. package/dist/core/dashboard-ipc-server.js +132 -0
  21. package/dist/core/dashboard-ipc-server.js.map +1 -1
  22. package/dist/core/maintenance.d.ts +23 -1
  23. package/dist/core/maintenance.d.ts.map +1 -1
  24. package/dist/core/maintenance.js +63 -25
  25. package/dist/core/maintenance.js.map +1 -1
  26. package/dist/core/plugins/cli-generation.d.ts.map +1 -1
  27. package/dist/core/plugins/cli-generation.js +7 -0
  28. package/dist/core/plugins/cli-generation.js.map +1 -1
  29. package/dist/core/plugins/convention-scanner.d.ts +3 -3
  30. package/dist/core/plugins/convention-scanner.d.ts.map +1 -1
  31. package/dist/core/plugins/convention-scanner.js.map +1 -1
  32. package/dist/core/plugins/install.d.ts.map +1 -1
  33. package/dist/core/plugins/install.js +84 -26
  34. package/dist/core/plugins/install.js.map +1 -1
  35. package/dist/core/plugins/mcp/environment.d.ts +12 -0
  36. package/dist/core/plugins/mcp/environment.d.ts.map +1 -0
  37. package/dist/core/plugins/mcp/environment.js +17 -0
  38. package/dist/core/plugins/mcp/environment.js.map +1 -0
  39. package/dist/core/plugins/mcp/gateway-installer.d.ts.map +1 -1
  40. package/dist/core/plugins/mcp/gateway-installer.js +9 -3
  41. package/dist/core/plugins/mcp/gateway-installer.js.map +1 -1
  42. package/dist/core/plugins/mcp/gateway.d.ts +13 -1
  43. package/dist/core/plugins/mcp/gateway.d.ts.map +1 -1
  44. package/dist/core/plugins/mcp/gateway.js +143 -23
  45. package/dist/core/plugins/mcp/gateway.js.map +1 -1
  46. package/dist/core/plugins/mcp/host.d.ts +18 -0
  47. package/dist/core/plugins/mcp/host.d.ts.map +1 -0
  48. package/dist/core/plugins/mcp/host.js +126 -0
  49. package/dist/core/plugins/mcp/host.js.map +1 -0
  50. package/dist/core/plugins/mcp/private-store.d.ts +15 -0
  51. package/dist/core/plugins/mcp/private-store.d.ts.map +1 -0
  52. package/dist/core/plugins/mcp/private-store.js +162 -0
  53. package/dist/core/plugins/mcp/private-store.js.map +1 -0
  54. package/dist/core/plugins/mcp/session-runtime.d.ts +25 -0
  55. package/dist/core/plugins/mcp/session-runtime.d.ts.map +1 -0
  56. package/dist/core/plugins/mcp/session-runtime.js +76 -0
  57. package/dist/core/plugins/mcp/session-runtime.js.map +1 -0
  58. package/dist/core/plugins/mcp/socket-auth.d.ts +9 -0
  59. package/dist/core/plugins/mcp/socket-auth.d.ts.map +1 -0
  60. package/dist/core/plugins/mcp/socket-auth.js +94 -0
  61. package/dist/core/plugins/mcp/socket-auth.js.map +1 -0
  62. package/dist/core/plugins/paths.d.ts +3 -0
  63. package/dist/core/plugins/paths.d.ts.map +1 -1
  64. package/dist/core/plugins/paths.js +9 -0
  65. package/dist/core/plugins/paths.js.map +1 -1
  66. package/dist/core/plugins/pm2.d.ts.map +1 -1
  67. package/dist/core/plugins/pm2.js +3 -1
  68. package/dist/core/plugins/pm2.js.map +1 -1
  69. package/dist/core/plugins/runtime.d.ts +2 -0
  70. package/dist/core/plugins/runtime.d.ts.map +1 -1
  71. package/dist/core/plugins/runtime.js.map +1 -1
  72. package/dist/core/plugins/service-manager.d.ts +22 -0
  73. package/dist/core/plugins/service-manager.d.ts.map +1 -1
  74. package/dist/core/plugins/service-manager.js +189 -52
  75. package/dist/core/plugins/service-manager.js.map +1 -1
  76. package/dist/core/plugins/types.d.ts +15 -1
  77. package/dist/core/plugins/types.d.ts.map +1 -1
  78. package/dist/core/restart-report.d.ts +1 -1
  79. package/dist/core/restart-report.d.ts.map +1 -1
  80. package/dist/core/restart-report.js +5 -3
  81. package/dist/core/restart-report.js.map +1 -1
  82. package/dist/core/scheduler.d.ts +47 -0
  83. package/dist/core/scheduler.d.ts.map +1 -1
  84. package/dist/core/scheduler.js +117 -0
  85. package/dist/core/scheduler.js.map +1 -1
  86. package/dist/core/session-manager.d.ts +7 -0
  87. package/dist/core/session-manager.d.ts.map +1 -1
  88. package/dist/core/session-manager.js +130 -33
  89. package/dist/core/session-manager.js.map +1 -1
  90. package/dist/core/session-marker.d.ts.map +1 -1
  91. package/dist/core/session-marker.js +5 -2
  92. package/dist/core/session-marker.js.map +1 -1
  93. package/dist/core/silent-schedule-turns.d.ts +5 -0
  94. package/dist/core/silent-schedule-turns.d.ts.map +1 -0
  95. package/dist/core/silent-schedule-turns.js +47 -0
  96. package/dist/core/silent-schedule-turns.js.map +1 -0
  97. package/dist/core/types.d.ts +54 -0
  98. package/dist/core/types.d.ts.map +1 -1
  99. package/dist/core/types.js +55 -0
  100. package/dist/core/types.js.map +1 -1
  101. package/dist/core/update-check.d.ts +16 -0
  102. package/dist/core/update-check.d.ts.map +1 -1
  103. package/dist/core/update-check.js +52 -0
  104. package/dist/core/update-check.js.map +1 -1
  105. package/dist/core/worker-pool.d.ts.map +1 -1
  106. package/dist/core/worker-pool.js +40 -31
  107. package/dist/core/worker-pool.js.map +1 -1
  108. package/dist/daemon.d.ts.map +1 -1
  109. package/dist/daemon.js +90 -9
  110. package/dist/daemon.js.map +1 -1
  111. package/dist/dashboard/schedule-card-model.d.ts +3 -0
  112. package/dist/dashboard/schedule-card-model.d.ts.map +1 -1
  113. package/dist/dashboard/schedule-card-model.js +5 -0
  114. package/dist/dashboard/schedule-card-model.js.map +1 -1
  115. package/dist/dashboard/web/app.d.ts.map +1 -1
  116. package/dist/dashboard/web/app.js +295 -6
  117. package/dist/dashboard/web/app.js.map +1 -1
  118. package/dist/dashboard/web/i18n.d.ts.map +1 -1
  119. package/dist/dashboard/web/i18n.js +92 -0
  120. package/dist/dashboard/web/i18n.js.map +1 -1
  121. package/dist/dashboard/web/plugin-page.d.ts.map +1 -1
  122. package/dist/dashboard/web/plugin-page.js +1 -3
  123. package/dist/dashboard/web/plugin-page.js.map +1 -1
  124. package/dist/dashboard/web/schedules-page.d.ts.map +1 -1
  125. package/dist/dashboard/web/schedules-page.js +111 -4
  126. package/dist/dashboard/web/schedules-page.js.map +1 -1
  127. package/dist/dashboard/web/settings-page.d.ts.map +1 -1
  128. package/dist/dashboard/web/settings-page.js +5 -1
  129. package/dist/dashboard/web/settings-page.js.map +1 -1
  130. package/dist/dashboard/web/update-action.d.ts +16 -0
  131. package/dist/dashboard/web/update-action.d.ts.map +1 -0
  132. package/dist/dashboard/web/update-action.js +64 -0
  133. package/dist/dashboard/web/update-action.js.map +1 -0
  134. package/dist/dashboard-web/app.js +1 -1
  135. package/dist/dashboard-web/chunks/{bot-defaults-page-KLDCZNLP.js → bot-defaults-page-4PM4T6QQ.js} +1 -1
  136. package/dist/dashboard-web/chunks/{chunk-FMJNOATE.js → chunk-3PMN55Z6.js} +1 -1
  137. package/dist/dashboard-web/chunks/{chunk-MLNI5BKE.js → chunk-AIDN2WZB.js} +1 -1
  138. package/dist/dashboard-web/chunks/{chunk-EZAW2EPM.js → chunk-IKCZ677K.js} +1 -1
  139. package/dist/dashboard-web/chunks/{chunk-KEAOTUL3.js → chunk-RXVA6XW3.js} +7 -7
  140. package/dist/dashboard-web/chunks/{connectors-page-O32LFAL5.js → connectors-page-2MKF4YTN.js} +1 -1
  141. package/dist/dashboard-web/chunks/{groups-page-PSAFIZ6M.js → groups-page-TAU2UIVS.js} +1 -1
  142. package/dist/dashboard-web/chunks/{insights-page-V23LLATX.js → insights-page-PJ2XVM6T.js} +1 -1
  143. package/dist/dashboard-web/chunks/{monitor-room-7X5AKYOF.js → monitor-room-D6445HJO.js} +1 -1
  144. package/dist/dashboard-web/chunks/{monitoring-page-CBA3CQYL.js → monitoring-page-GUHMCKSO.js} +1 -1
  145. package/dist/dashboard-web/chunks/{office-page-RL6QSEM7.js → office-page-6K6U2MS5.js} +1 -1
  146. package/dist/dashboard-web/chunks/{overview-page-XQIPO6KH.js → overview-page-USDYU7U5.js} +1 -1
  147. package/dist/dashboard-web/chunks/plugin-page-JXC5F5YV.js +1 -0
  148. package/dist/dashboard-web/chunks/{roles-page-ACIWV7QS.js → roles-page-O4OUA7ZH.js} +1 -1
  149. package/dist/dashboard-web/chunks/schedules-page-LNIBXJSZ.js +1 -0
  150. package/dist/dashboard-web/chunks/{sessions-page-2WDWHSP4.js → sessions-page-B6U6TCFF.js} +1 -1
  151. package/dist/dashboard-web/chunks/{settings-page-6VX4OUGG.js → settings-page-PXLRFF7I.js} +2 -2
  152. package/dist/dashboard-web/chunks/{skills-page-WXE3UYLT.js → skills-page-M5KYNXBA.js} +1 -1
  153. package/dist/dashboard-web/chunks/{team-federation-page-PYTF4FLM.js → team-federation-page-GT7UFQMN.js} +1 -1
  154. package/dist/dashboard-web/chunks/{v3-page-G6CD6O3I.js → v3-page-UYZIRJ2C.js} +1 -1
  155. package/dist/dashboard-web/chunks/{whiteboards-page-6SG33GP4.js → whiteboards-page-WAR77DQE.js} +1 -1
  156. package/dist/dashboard-web/style.css +697 -0
  157. package/dist/dashboard.js +404 -29
  158. package/dist/dashboard.js.map +1 -1
  159. package/dist/i18n/en.d.ts.map +1 -1
  160. package/dist/i18n/en.js +5 -0
  161. package/dist/i18n/en.js.map +1 -1
  162. package/dist/i18n/zh.d.ts.map +1 -1
  163. package/dist/i18n/zh.js +5 -0
  164. package/dist/i18n/zh.js.map +1 -1
  165. package/dist/im/lark/card-handler.d.ts +2 -0
  166. package/dist/im/lark/card-handler.d.ts.map +1 -1
  167. package/dist/im/lark/card-handler.js +219 -139
  168. package/dist/im/lark/card-handler.js.map +1 -1
  169. package/dist/im/lark/schedules-card.d.ts.map +1 -1
  170. package/dist/im/lark/schedules-card.js +2 -0
  171. package/dist/im/lark/schedules-card.js.map +1 -1
  172. package/dist/services/plugin-registry-store.d.ts.map +1 -1
  173. package/dist/services/plugin-registry-store.js +100 -18
  174. package/dist/services/plugin-registry-store.js.map +1 -1
  175. package/dist/services/restart-intent-store.d.ts +17 -2
  176. package/dist/services/restart-intent-store.d.ts.map +1 -1
  177. package/dist/services/restart-intent-store.js +110 -0
  178. package/dist/services/restart-intent-store.js.map +1 -1
  179. package/dist/services/schedule-store.d.ts +3 -1
  180. package/dist/services/schedule-store.d.ts.map +1 -1
  181. package/dist/services/schedule-store.js +5 -0
  182. package/dist/services/schedule-store.js.map +1 -1
  183. package/dist/skills/definitions.d.ts.map +1 -1
  184. package/dist/skills/definitions.js +3 -2
  185. package/dist/skills/definitions.js.map +1 -1
  186. package/dist/types.d.ts +18 -0
  187. package/dist/types.d.ts.map +1 -1
  188. package/dist/utils/child-env.d.ts +9 -1
  189. package/dist/utils/child-env.d.ts.map +1 -1
  190. package/dist/utils/child-env.js +24 -0
  191. package/dist/utils/child-env.js.map +1 -1
  192. package/dist/utils/global-install.d.ts +2 -0
  193. package/dist/utils/global-install.d.ts.map +1 -1
  194. package/dist/utils/global-install.js +14 -0
  195. package/dist/utils/global-install.js.map +1 -1
  196. package/dist/worker.js +135 -18
  197. package/dist/worker.js.map +1 -1
  198. package/dist/workflows/hostExecutors/botmux-schedule.d.ts +3 -0
  199. package/dist/workflows/hostExecutors/botmux-schedule.d.ts.map +1 -1
  200. package/dist/workflows/hostExecutors/botmux-schedule.js +9 -0
  201. package/dist/workflows/hostExecutors/botmux-schedule.js.map +1 -1
  202. package/package.json +1 -1
  203. package/dist/dashboard-web/chunks/plugin-page-7FW2LPJH.js +0 -1
  204. package/dist/dashboard-web/chunks/schedules-page-KJDUKOJV.js +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"command-handler.d.ts","sourceRoot":"","sources":["../../src/core/command-handler.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"command-handler.d.ts","sourceRoot":"","sources":["../../src/core/command-handler.ts"],"names":[],"mappings":"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"}
@@ -25,7 +25,7 @@ import { claimPairing } from '../services/pairing-store.js';
25
25
  import { logger } from '../utils/logger.js';
26
26
  import { scheduleTimeZone } from '../utils/timezone.js';
27
27
  import { killWorker, suspendWorker, forkWorker, forkAdoptWorker, getCurrentCliVersion, postFreshStreamingCard, postPrivateSnapshotCard, resolvePrivateCardAudience, deliverEphemeralOrReply, deliverWritableTerminalCardTo } from './worker-pool.js';
28
- import { expandHome, getSessionWorkingDir, getProjectScanDirs, rememberLastCliInput } from './session-manager.js';
28
+ import { expandHome, getSessionWorkingDir, getProjectScanDirs, rememberLastCliInput, buildNewTopicCliInput, ensureSessionWhiteboard, getAvailableBots, } from './session-manager.js';
29
29
  import { discoverSlashCommandsForAdapter, listMcpServerNames, supportsFilesystemCommandDiscovery } from './command-discovery.js';
30
30
  import { validateWorkingDir } from './working-dir.js';
31
31
  import { repinSessionWorkingDir } from './session-cwd.js';
@@ -52,7 +52,7 @@ import { invalidWorkingDirs } from '../utils/working-dir.js';
52
52
  import { writeRoleFile, deleteRoleFile, resolveRole, resolveRoleFile, resolveTeamRoleFile, writeTeamRoleFile, deleteTeamRoleFile, MAX_ROLE_BYTES } from './role-resolver.js';
53
53
  import { getBotCapability, setBotCapability, clearBotCapability } from '../services/bot-profile-store.js';
54
54
  import { deleteRoleProfileEntry, deleteRoleProfileIfEmpty, isValidRoleProfileId, listRoleProfileEntries, listRoleProfiles, MAX_ROLE_PROFILE_ENTRY_BYTES, readRoleProfileEntry, writeRoleProfileEntry, } from '../services/role-profile-store.js';
55
- import { sessionKey, sessionAnchorId } from './types.js';
55
+ import { sessionKey, sessionAnchorId, markRepoCardConsumed, claimCurrentRepoCard } from './types.js';
56
56
  import { t, localeForBot } from '../i18n/index.js';
57
57
  import { runSkillsImCommand } from './skills/im-command.js';
58
58
  import { fetchDaemonIpc } from './daemon-ipc-auth.js';
@@ -639,7 +639,7 @@ async function handleScheduleCommand(args, rootId, chatId, deps, larkAppId) {
639
639
  const nextStr = next ? t('schedule.next_label', { time: next.toLocaleString(timeLocale, { timeZone }) }, loc) : '';
640
640
  const lastStr = task.lastRunAt ? t('schedule.last_label', { time: new Date(task.lastRunAt).toLocaleString(timeLocale, { timeZone }) }, loc) : '';
641
641
  const display = task.parsed?.display ?? task.schedule;
642
- return `${status} [${task.id}] ${display} | ${task.name}\n prompt: ${task.prompt.substring(0, 50)}${task.prompt.length > 50 ? '...' : ''}${nextStr}${lastStr}`;
642
+ return `${status} [${task.id}] ${display} | ${task.name}${task.silent ? ' 🔇' : ''}\n prompt: ${task.prompt.substring(0, 50)}${task.prompt.length > 50 ? '...' : ''}${nextStr}${lastStr}`;
643
643
  });
644
644
  await sessionReply(rootId, `${t('schedule.list_header', { count: tasks.length }, loc)}\n\n${lines.join('\n\n')}`);
645
645
  return;
@@ -699,8 +699,13 @@ async function handleScheduleCommand(args, rootId, chatId, deps, larkAppId) {
699
699
  const workingDir = resolveScheduleWorkingDir(ds, chatId, larkAppId);
700
700
  const taskScope = ds?.scope === 'chat' ? 'chat' : 'thread';
701
701
  // "新话题" keyword → every fire opens a brand-new topic in a fresh session.
702
- const { deliver, prompt: schedPrompt } = scheduler.extractDeliveryMode(parsed.prompt);
703
- const schedName = deliver === 'new-topic'
702
+ // "静默" keyword fires post no banner; the model decides whether to send.
703
+ const { deliver, silent, prompt: schedPrompt } = scheduler.extractScheduleModifiers(parsed.prompt);
704
+ if (silent && deliver === 'new-topic') {
705
+ await sessionReply(rootId, t('schedule.silent_new_topic_conflict', undefined, loc));
706
+ return;
707
+ }
708
+ const schedName = schedPrompt !== parsed.prompt
704
709
  ? (schedPrompt.length > 20 ? schedPrompt.slice(0, 20) + '...' : schedPrompt)
705
710
  : parsed.name;
706
711
  const task = scheduler.addTask({
@@ -715,6 +720,7 @@ async function handleScheduleCommand(args, rootId, chatId, deps, larkAppId) {
715
720
  chatType: ds?.chatType === 'p2p' ? 'p2p' : 'topic_group',
716
721
  larkAppId,
717
722
  deliver,
723
+ silent,
718
724
  });
719
725
  const next = scheduler.getNextRun(task.id);
720
726
  const nextStr = next ? next.toLocaleString(timeLocale, { timeZone }) : 'N/A';
@@ -727,7 +733,8 @@ async function handleScheduleCommand(args, rootId, chatId, deps, larkAppId) {
727
733
  next: nextStr,
728
734
  }, loc);
729
735
  const deliverNote = deliver === 'new-topic' ? '\n' + t('schedule.deliver_new_topic', undefined, loc) : '';
730
- await sessionReply(rootId, createdMsg + deliverNote);
736
+ const silentNote = silent ? '\n' + t('schedule.silent_note', undefined, loc) : '';
737
+ await sessionReply(rootId, createdMsg + deliverNote + silentNote);
731
738
  return;
732
739
  }
733
740
  // Unrecognized format
@@ -1381,29 +1388,43 @@ export async function handleCommand(cmd, rootId, message, deps, larkAppId) {
1381
1388
  // CLI in whatever workingDir is currently set on the session. Shared by
1382
1389
  // `commitRepoSelection` (a repo was named) and the bare-`/repo` launch
1383
1390
  // (use the default workingDir) — both only run while `pendingRepo`.
1384
- const forkPendingCli = async (replyText) => {
1391
+ const forkPendingCli = async (replyText, claimAlready = false) => {
1392
+ if (!claimAlready) {
1393
+ if (ds.pendingRepoCommitInFlight) {
1394
+ await sessionReply(rootId, t('cmd.repo.worktree_in_progress', undefined, loc));
1395
+ return false;
1396
+ }
1397
+ ds.pendingRepoCommitInFlight = true;
1398
+ }
1385
1399
  const selfBot = getBot(ds.larkAppId);
1386
1400
  const botCfg = selfBot.config;
1387
1401
  const commitGenSessionId = ds.session.sessionId;
1388
- ds.pendingRepo = false;
1389
- publishAttentionPatch(ds);
1390
- const pendingPrompt = ds.pendingPrompt ?? '';
1391
- const pendingRawInput = ds.pendingRawInput;
1392
- // Was there an actual buffered user message to deliver? A session
1393
- // launched *via* `/repo` (the command itself is the first message) has
1394
- // none so boot the CLI idle and let the user's NEXT message be the
1395
- // first prompt, instead of submitting an empty/boilerplate user_message.
1396
- const hasBufferedInput = pendingPrompt.trim().length > 0 ||
1397
- (ds.pendingAttachments?.length ?? 0) > 0 ||
1398
- (ds.pendingFollowUps?.length ?? 0) > 0;
1399
- if (pendingRawInput) {
1400
- // Messages buffered while the repo card was pending must not be
1401
- // dropped: wrap them now (full prompt-building context lives here)
1402
- // and stash for delivery right after the raw input on prompt_ready.
1403
- if (hasBufferedInput) {
1404
- const { buildNewTopicCliInput, ensureSessionWhiteboard, getAvailableBots } = await import('./session-manager.js');
1402
+ let committed = false;
1403
+ try {
1404
+ // Keep pendingRepo=true while prompt context is awaited. Incoming
1405
+ // messages stay in the same buffer and card selections see the
1406
+ // shared in-flight claim instead of treating this as a repo switch.
1407
+ const initiallyBuffered = (ds.pendingPrompt?.trim().length ?? 0) > 0 ||
1408
+ (ds.pendingAttachments?.length ?? 0) > 0 ||
1409
+ (ds.pendingFollowUps?.length ?? 0) > 0;
1410
+ const availableBots = initiallyBuffered
1411
+ ? await getAvailableBots(ds.larkAppId, ds.chatId)
1412
+ : [];
1413
+ const stillActive = activeSessions.get(sessionKey(rootId, larkAppId)) === ds;
1414
+ if (!stillActive || ds.session.sessionId !== commitGenSessionId ||
1415
+ !ds.pendingRepo || (ds.worker && !ds.worker.killed)) {
1416
+ logger.warn(`[${logTag}] Session changed while preparing the pending CLI (${commitGenSessionId} ${ds.session.sessionId}, active=${stillActive}, pending=${!!ds.pendingRepo}, worker=${!!ds.worker})`);
1417
+ return false;
1418
+ }
1419
+ const pendingPrompt = ds.pendingPrompt ?? '';
1420
+ const pendingRawInput = ds.pendingRawInput;
1421
+ const hasBufferedInput = pendingPrompt.trim().length > 0 ||
1422
+ (ds.pendingAttachments?.length ?? 0) > 0 ||
1423
+ (ds.pendingFollowUps?.length ?? 0) > 0;
1424
+ if (hasBufferedInput)
1405
1425
  ensureSessionWhiteboard(ds);
1406
- const followUpInput = buildNewTopicCliInput(pendingPrompt, ds.session.sessionId, ds.session.cliId ?? botCfg.cliId, ds.session.cliPathOverride ?? botCfg.cliPathOverride, ds.pendingAttachments, ds.pendingMentions, await getAvailableBots(ds.larkAppId, ds.chatId), ds.pendingFollowUps, { name: selfBot.botName, openId: selfBot.botOpenId }, loc, ds.pendingSender, {
1426
+ const wrappedInput = hasBufferedInput
1427
+ ? buildNewTopicCliInput(pendingPrompt, ds.session.sessionId, ds.session.cliId ?? botCfg.cliId, ds.session.cliPathOverride ?? botCfg.cliPathOverride, ds.pendingAttachments, ds.pendingMentions, availableBots, ds.pendingFollowUps, { name: selfBot.botName, openId: selfBot.botOpenId }, loc, ds.pendingSender, {
1407
1428
  larkAppId,
1408
1429
  chatId: ds.chatId,
1409
1430
  whiteboardId: ds.session.whiteboardId,
@@ -1413,64 +1434,82 @@ export async function handleCommand(cmd, rootId, message, deps, larkAppId) {
1413
1434
  codexAppMessageContext: ds.pendingCodexAppMessageContext,
1414
1435
  codexAppFollowUps: ds.pendingCodexAppFollowUps,
1415
1436
  codexAppFollowUpContexts: ds.pendingCodexAppFollowUpContexts,
1416
- });
1437
+ })
1438
+ : { content: '' };
1439
+ const pendingTurnId = ds.pendingTurnId;
1440
+ const previousPendingFollowUpInput = ds.pendingFollowUpInput;
1441
+ if (pendingRawInput && hasBufferedInput) {
1417
1442
  ds.pendingFollowUpInput = {
1418
1443
  userPrompt: ds.pendingCodexAppText !== undefined || ds.pendingCodexAppFollowUps
1419
1444
  ? [ds.pendingCodexAppText ?? '', ...(ds.pendingCodexAppFollowUps ?? [])].filter(Boolean).join('\n\n')
1420
1445
  : pendingPrompt || ds.pendingFollowUps?.join('\n\n') || '',
1421
- cliInput: followUpInput.content,
1422
- ...((ds.session.cliId ?? botCfg.cliId) === 'codex-app' && botCfg.codexAppCleanInput === true && followUpInput.codexAppInput
1423
- ? { codexAppInput: followUpInput.codexAppInput }
1446
+ cliInput: wrappedInput.content,
1447
+ ...(ds.pendingFollowUpTurnId ? { turnId: ds.pendingFollowUpTurnId } : {}),
1448
+ ...((ds.session.cliId ?? botCfg.cliId) === 'codex-app' && botCfg.codexAppCleanInput === true && wrappedInput.codexAppInput
1449
+ ? { codexAppInput: wrappedInput.codexAppInput }
1424
1450
  : {}),
1425
1451
  codexAppInputGateFrozen: true,
1426
1452
  };
1427
1453
  }
1428
- rememberLastCliInput(ds, pendingRawInput, pendingRawInput);
1429
- forkWorker(ds, '', false);
1430
- }
1431
- else if (hasBufferedInput) {
1432
- const { buildNewTopicCliInput, ensureSessionWhiteboard, getAvailableBots } = await import('./session-manager.js');
1433
- ensureSessionWhiteboard(ds);
1434
- const prompt = buildNewTopicCliInput(pendingPrompt, ds.session.sessionId, ds.session.cliId ?? botCfg.cliId, ds.session.cliPathOverride ?? botCfg.cliPathOverride, ds.pendingAttachments, ds.pendingMentions, await getAvailableBots(ds.larkAppId, ds.chatId), ds.pendingFollowUps, { name: selfBot.botName, openId: selfBot.botOpenId }, loc, ds.pendingSender, {
1435
- larkAppId,
1436
- chatId: ds.chatId,
1437
- whiteboardId: ds.session.whiteboardId,
1438
- substituteTrigger: ds.pendingSubstituteTrigger,
1439
- codexAppText: ds.pendingCodexAppText,
1440
- codexAppApplicationContext: ds.pendingCodexAppApplicationContext,
1441
- codexAppMessageContext: ds.pendingCodexAppMessageContext,
1442
- codexAppFollowUps: ds.pendingCodexAppFollowUps,
1443
- codexAppFollowUpContexts: ds.pendingCodexAppFollowUpContexts,
1444
- });
1445
- // Last-line defence: prompt prep awaited above — if anything
1446
- // replaced OR closed the session in that window (`/close` deletes
1447
- // the active-map entry without touching sessionId), forking now
1448
- // would clobber it or resurrect a closed session.
1449
- const stillActive = activeSessions.get(sessionKey(rootId, larkAppId)) === ds;
1450
- if (!stillActive || ds.session.sessionId !== commitGenSessionId) {
1451
- logger.warn(`[${logTag}] Session replaced or closed while preparing the pending-CLI prompt (${commitGenSessionId} → ${ds.session.sessionId}, active=${stillActive}) — aborting this fork`);
1452
- return;
1454
+ ds.pendingRepo = false;
1455
+ publishAttentionPatch(ds);
1456
+ try {
1457
+ if (pendingRawInput)
1458
+ forkWorker(ds, '', false);
1459
+ else if (pendingTurnId && hasBufferedInput)
1460
+ forkWorker(ds, wrappedInput, { turnId: pendingTurnId });
1461
+ else if (hasBufferedInput)
1462
+ forkWorker(ds, wrappedInput);
1463
+ else
1464
+ forkWorker(ds, '', false);
1465
+ }
1466
+ catch (e) {
1467
+ ds.pendingRepo = true;
1468
+ ds.pendingFollowUpInput = previousPendingFollowUpInput;
1469
+ publishAttentionPatch(ds);
1470
+ throw e;
1471
+ }
1472
+ if (pendingRawInput || hasBufferedInput) {
1473
+ rememberLastCliInput(ds, pendingRawInput ?? pendingPrompt, pendingRawInput ?? wrappedInput);
1474
+ }
1475
+ ds.pendingPrompt = undefined;
1476
+ ds.pendingCodexAppText = undefined;
1477
+ ds.pendingCodexAppApplicationContext = undefined;
1478
+ ds.pendingCodexAppMessageContext = undefined;
1479
+ ds.pendingAttachments = undefined;
1480
+ ds.pendingMentions = undefined;
1481
+ ds.pendingSubstituteTrigger = undefined;
1482
+ ds.pendingSender = undefined;
1483
+ ds.pendingFollowUps = undefined;
1484
+ ds.pendingCodexAppFollowUps = undefined;
1485
+ ds.pendingCodexAppFollowUpContexts = undefined;
1486
+ ds.pendingFollowUpTurnId = undefined;
1487
+ ds.pendingTurnId = undefined;
1488
+ committed = true;
1489
+ // Local one-shot consume BEFORE network awaits. Feishu withdraw is
1490
+ // best-effort; stale card clicks must be rejected via this mark even
1491
+ // if sessionReply throws or deleteMessage lags/fails.
1492
+ const cardToWithdraw = ds.repoCardMessageId;
1493
+ markRepoCardConsumed(ds, cardToWithdraw);
1494
+ ds.repoCardMessageId = undefined;
1495
+ // Hold the claim through confirmation + best-effort card withdraw.
1496
+ try {
1497
+ await sessionReply(rootId, replyText);
1498
+ }
1499
+ catch (e) {
1500
+ logger.warn(`[${logTag}] Confirm reply after pending repo commit failed: ${e instanceof Error ? e.message : e}`);
1501
+ }
1502
+ if (cardToWithdraw) {
1503
+ try {
1504
+ await deleteMessage(ds.larkAppId, cardToWithdraw);
1505
+ }
1506
+ catch { /* best-effort */ }
1453
1507
  }
1454
- rememberLastCliInput(ds, pendingPrompt, prompt);
1455
- forkWorker(ds, prompt);
1456
1508
  }
1457
- else {
1458
- // Empty initial prompt → worker spawns the CLI without submitting
1459
- // anything (see worker.ts: the init prompt is only queued when truthy).
1460
- forkWorker(ds, '', false);
1509
+ finally {
1510
+ ds.pendingRepoCommitInFlight = false;
1461
1511
  }
1462
- ds.pendingPrompt = undefined;
1463
- ds.pendingCodexAppText = undefined;
1464
- ds.pendingCodexAppApplicationContext = undefined;
1465
- ds.pendingCodexAppMessageContext = undefined;
1466
- ds.pendingAttachments = undefined;
1467
- ds.pendingMentions = undefined;
1468
- ds.pendingSubstituteTrigger = undefined;
1469
- ds.pendingSender = undefined;
1470
- ds.pendingFollowUps = undefined;
1471
- ds.pendingCodexAppFollowUps = undefined;
1472
- ds.pendingCodexAppFollowUpContexts = undefined;
1473
- await sessionReply(rootId, replyText);
1512
+ return committed;
1474
1513
  };
1475
1514
  // Shared commit path for an already-resolved repo: update the session's
1476
1515
  // working dir, then either fork into the pending CLI (first spawn) or
@@ -1478,13 +1517,27 @@ export async function handleCommand(cmd, rootId, message, deps, larkAppId) {
1478
1517
  // numeric `/repo <N>` form and the `/repo <path|name>` form.
1479
1518
  const commitRepoSelection = async (selectedPath, displayName, how) => {
1480
1519
  if (ds.pendingRepo) {
1481
- // First spawn: pin the new cwd onto the CURRENT session, then fork.
1482
- ds.workingDir = selectedPath;
1483
- ds.session.workingDir = selectedPath;
1484
- // A single repo selection supersedes any stale multi-Riff stamp.
1485
- ds.session.riffRepoDirs = undefined;
1486
- sessionStore.updateSession(ds.session);
1487
- await forkPendingCli(t('cmd.repo.selected_in_pending', { name: displayName }, loc));
1520
+ if (ds.pendingRepoCommitInFlight) {
1521
+ await sessionReply(rootId, t('cmd.repo.worktree_in_progress', undefined, loc));
1522
+ return false;
1523
+ }
1524
+ ds.pendingRepoCommitInFlight = true;
1525
+ try {
1526
+ // Claim before changing cwd so a card selection cannot overwrite
1527
+ // this choice while the pending prompt is prepared.
1528
+ ds.workingDir = selectedPath;
1529
+ ds.session.workingDir = selectedPath;
1530
+ ds.session.riffRepoDirs = undefined;
1531
+ sessionStore.updateSession(ds.session);
1532
+ // forkPendingCli owns claim release + confirm reply + card withdraw.
1533
+ if (!await forkPendingCli(t('cmd.repo.selected_in_pending', { name: displayName }, loc), true)) {
1534
+ return false;
1535
+ }
1536
+ }
1537
+ catch (e) {
1538
+ ds.pendingRepoCommitInFlight = false;
1539
+ throw e;
1540
+ }
1488
1541
  }
1489
1542
  else {
1490
1543
  // Safety net: a mid-session `/repo` switch closes the running
@@ -1498,11 +1551,15 @@ export async function handleCommand(cmd, rootId, message, deps, larkAppId) {
1498
1551
  // anchor — expected; `/close` the new one first, or use the
1499
1552
  // command.) Mirrors the `/close` case above.
1500
1553
  //
1554
+ // Claim any open repo card BEFORE killWorker / await so a concurrent
1555
+ // card click cannot double-switch while this text path runs.
1556
+ //
1501
1557
  // The new cwd is NOT written onto the old session here — it would
1502
1558
  // pollute the displaced session's stored workingDir (and the closed
1503
1559
  // card), so `claude --resume` later would reopen the old context in
1504
1560
  // the new repo's cwd. The new repo is pinned onto the fresh session
1505
1561
  // below instead.
1562
+ const claimedCard = claimCurrentRepoCard(ds, undefined);
1506
1563
  const closedCard = buildClosedSessionCard(ds, loc);
1507
1564
  killWorker(ds);
1508
1565
  sessionStore.closeSession(ds.session.sessionId);
@@ -1522,13 +1579,21 @@ export async function handleCommand(cmd, rootId, message, deps, larkAppId) {
1522
1579
  sessionStore.updateSession(ds.session);
1523
1580
  ds.hasHistory = false;
1524
1581
  forkWorker(ds, '', false);
1525
- await sessionReply(rootId, t('cmd.repo.switched_to', { name: displayName }, loc));
1526
- }
1527
- if (ds.repoCardMessageId) {
1528
- deleteMessage(ds.larkAppId, ds.repoCardMessageId);
1529
- ds.repoCardMessageId = undefined;
1582
+ try {
1583
+ await sessionReply(rootId, t('cmd.repo.switched_to', { name: displayName }, loc));
1584
+ }
1585
+ catch (e) {
1586
+ logger.warn(`[${logTag}] Confirm reply after mid-session repo switch failed: ${e instanceof Error ? e.message : e}`);
1587
+ }
1588
+ if (claimedCard) {
1589
+ try {
1590
+ await deleteMessage(ds.larkAppId, claimedCard);
1591
+ }
1592
+ catch { /* best-effort */ }
1593
+ }
1530
1594
  }
1531
1595
  logger.info(`[${logTag}] Repo selected via ${how}: ${selectedPath}`);
1596
+ return true;
1532
1597
  };
1533
1598
  // `/repo wt <N|name|path> [branch]` → create a worktree off the repo's
1534
1599
  // remote default branch and open THAT as the session repo. Without a
@@ -1563,7 +1628,7 @@ export async function handleCommand(cmd, rootId, message, deps, larkAppId) {
1563
1628
  }
1564
1629
  repoPath = resolved.path;
1565
1630
  }
1566
- if (ds.worktreeCreating) {
1631
+ if (ds.worktreeCreating || ds.pendingRepoCommitInFlight) {
1567
1632
  await sessionReply(rootId, t('cmd.repo.worktree_in_progress', undefined, loc));
1568
1633
  break;
1569
1634
  }
@@ -1644,7 +1709,7 @@ export async function handleCommand(cmd, rootId, message, deps, larkAppId) {
1644
1709
  // would double-fork. One lock gates both kinds until the commit
1645
1710
  // settles. (Bare `/repo` without pending only posts the picker card —
1646
1711
  // harmless, so it stays open.)
1647
- if (ds?.worktreeCreating && (repoArg || ds.pendingRepo)) {
1712
+ if ((ds?.worktreeCreating || ds?.pendingRepoCommitInFlight) && (repoArg || ds?.pendingRepo)) {
1648
1713
  await sessionReply(rootId, t('cmd.repo.worktree_in_progress', undefined, loc));
1649
1714
  break;
1650
1715
  }
@@ -1690,11 +1755,10 @@ export async function handleCommand(cmd, rootId, message, deps, larkAppId) {
1690
1755
  break;
1691
1756
  }
1692
1757
  const cwd = getSessionWorkingDir(ds);
1758
+ // bare /repo is the text twin of skip_repo: launch in the default
1759
+ // cwd without pinning it (forkPendingCli does not write workingDir).
1760
+ // Confirmation + card withdraw run under the claim inside forkPendingCli.
1693
1761
  await forkPendingCli(t('cmd.skip.opened', { cwd }, loc));
1694
- if (ds.repoCardMessageId) {
1695
- deleteMessage(ds.larkAppId, ds.repoCardMessageId);
1696
- ds.repoCardMessageId = undefined;
1697
- }
1698
1762
  logger.info(`[${logTag}] Bare /repo while pending → launch in workingDir ${cwd}`);
1699
1763
  break;
1700
1764
  }