botmux 2.84.0 → 2.85.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 (186) hide show
  1. package/README.md +4 -0
  2. package/dist/adapters/backend/sandbox.d.ts +4 -0
  3. package/dist/adapters/backend/sandbox.d.ts.map +1 -1
  4. package/dist/adapters/backend/sandbox.js +14 -0
  5. package/dist/adapters/backend/sandbox.js.map +1 -1
  6. package/dist/adapters/cli/claude-code.d.ts.map +1 -1
  7. package/dist/adapters/cli/claude-code.js +4 -1
  8. package/dist/adapters/cli/claude-code.js.map +1 -1
  9. package/dist/adapters/cli/types.d.ts +11 -0
  10. package/dist/adapters/cli/types.d.ts.map +1 -1
  11. package/dist/bot-registry.d.ts +18 -0
  12. package/dist/bot-registry.d.ts.map +1 -1
  13. package/dist/bot-registry.js +34 -0
  14. package/dist/bot-registry.js.map +1 -1
  15. package/dist/cli.d.ts.map +1 -1
  16. package/dist/cli.js +30 -65
  17. package/dist/cli.js.map +1 -1
  18. package/dist/core/command-handler.d.ts.map +1 -1
  19. package/dist/core/command-handler.js +42 -1
  20. package/dist/core/command-handler.js.map +1 -1
  21. package/dist/core/dashboard-ipc-server.d.ts.map +1 -1
  22. package/dist/core/dashboard-ipc-server.js +100 -1
  23. package/dist/core/dashboard-ipc-server.js.map +1 -1
  24. package/dist/core/passthrough-commands.d.ts.map +1 -1
  25. package/dist/core/passthrough-commands.js +1 -1
  26. package/dist/core/passthrough-commands.js.map +1 -1
  27. package/dist/core/pending-response.d.ts +2 -39
  28. package/dist/core/pending-response.d.ts.map +1 -1
  29. package/dist/core/pending-response.js +5 -99
  30. package/dist/core/pending-response.js.map +1 -1
  31. package/dist/core/session-manager.d.ts.map +1 -1
  32. package/dist/core/session-manager.js +4 -16
  33. package/dist/core/session-manager.js.map +1 -1
  34. package/dist/core/skills/claude-plugin-delivery.d.ts +6 -0
  35. package/dist/core/skills/claude-plugin-delivery.d.ts.map +1 -0
  36. package/dist/core/skills/claude-plugin-delivery.js +21 -0
  37. package/dist/core/skills/claude-plugin-delivery.js.map +1 -0
  38. package/dist/core/skills/cli-admin-command.d.ts +7 -0
  39. package/dist/core/skills/cli-admin-command.d.ts.map +1 -0
  40. package/dist/core/skills/cli-admin-command.js +243 -0
  41. package/dist/core/skills/cli-admin-command.js.map +1 -0
  42. package/dist/core/skills/cli-session-command.d.ts +7 -0
  43. package/dist/core/skills/cli-session-command.d.ts.map +1 -0
  44. package/dist/core/skills/cli-session-command.js +45 -0
  45. package/dist/core/skills/cli-session-command.js.map +1 -0
  46. package/dist/core/skills/delivery.d.ts +11 -0
  47. package/dist/core/skills/delivery.d.ts.map +1 -0
  48. package/dist/core/skills/delivery.js +22 -0
  49. package/dist/core/skills/delivery.js.map +1 -0
  50. package/dist/core/skills/discovery.d.ts +3 -0
  51. package/dist/core/skills/discovery.d.ts.map +1 -0
  52. package/dist/core/skills/discovery.js +34 -0
  53. package/dist/core/skills/discovery.js.map +1 -0
  54. package/dist/core/skills/frontmatter.d.ts +9 -0
  55. package/dist/core/skills/frontmatter.d.ts.map +1 -0
  56. package/dist/core/skills/frontmatter.js +42 -0
  57. package/dist/core/skills/frontmatter.js.map +1 -0
  58. package/dist/core/skills/im-command.d.ts +9 -0
  59. package/dist/core/skills/im-command.d.ts.map +1 -0
  60. package/dist/core/skills/im-command.js +107 -0
  61. package/dist/core/skills/im-command.js.map +1 -0
  62. package/dist/core/skills/manifest-store.d.ts +4 -0
  63. package/dist/core/skills/manifest-store.d.ts.map +1 -0
  64. package/dist/core/skills/manifest-store.js +26 -0
  65. package/dist/core/skills/manifest-store.js.map +1 -0
  66. package/dist/core/skills/package.d.ts +13 -0
  67. package/dist/core/skills/package.d.ts.map +1 -0
  68. package/dist/core/skills/package.js +35 -0
  69. package/dist/core/skills/package.js.map +1 -0
  70. package/dist/core/skills/policy.d.ts +18 -0
  71. package/dist/core/skills/policy.d.ts.map +1 -0
  72. package/dist/core/skills/policy.js +69 -0
  73. package/dist/core/skills/policy.js.map +1 -0
  74. package/dist/core/skills/prompt.d.ts +3 -0
  75. package/dist/core/skills/prompt.d.ts.map +1 -0
  76. package/dist/core/skills/prompt.js +25 -0
  77. package/dist/core/skills/prompt.js.map +1 -0
  78. package/dist/core/skills/references.d.ts +21 -0
  79. package/dist/core/skills/references.d.ts.map +1 -0
  80. package/dist/core/skills/references.js +27 -0
  81. package/dist/core/skills/references.js.map +1 -0
  82. package/dist/core/skills/registry-paths.d.ts +5 -0
  83. package/dist/core/skills/registry-paths.d.ts.map +1 -0
  84. package/dist/core/skills/registry-paths.js +15 -0
  85. package/dist/core/skills/registry-paths.js.map +1 -0
  86. package/dist/core/skills/resource-reader.d.ts +9 -0
  87. package/dist/core/skills/resource-reader.d.ts.map +1 -0
  88. package/dist/core/skills/resource-reader.js +97 -0
  89. package/dist/core/skills/resource-reader.js.map +1 -0
  90. package/dist/core/skills/session-resolver.d.ts +14 -0
  91. package/dist/core/skills/session-resolver.d.ts.map +1 -0
  92. package/dist/core/skills/session-resolver.js +24 -0
  93. package/dist/core/skills/session-resolver.js.map +1 -0
  94. package/dist/core/skills/session-runtime.d.ts +14 -0
  95. package/dist/core/skills/session-runtime.d.ts.map +1 -0
  96. package/dist/core/skills/session-runtime.js +32 -0
  97. package/dist/core/skills/session-runtime.js.map +1 -0
  98. package/dist/core/skills/sources.d.ts +21 -0
  99. package/dist/core/skills/sources.d.ts.map +1 -0
  100. package/dist/core/skills/sources.js +155 -0
  101. package/dist/core/skills/sources.js.map +1 -0
  102. package/dist/core/skills/types.d.ts +71 -0
  103. package/dist/core/skills/types.d.ts.map +1 -0
  104. package/dist/core/skills/types.js +2 -0
  105. package/dist/core/skills/types.js.map +1 -0
  106. package/dist/core/startup-commands.d.ts +57 -0
  107. package/dist/core/startup-commands.d.ts.map +1 -0
  108. package/dist/core/startup-commands.js +85 -0
  109. package/dist/core/startup-commands.js.map +1 -0
  110. package/dist/core/types.d.ts +10 -3
  111. package/dist/core/types.d.ts.map +1 -1
  112. package/dist/core/types.js.map +1 -1
  113. package/dist/core/worker-pool.d.ts +14 -1
  114. package/dist/core/worker-pool.d.ts.map +1 -1
  115. package/dist/core/worker-pool.js +93 -62
  116. package/dist/core/worker-pool.js.map +1 -1
  117. package/dist/daemon.d.ts +2 -2
  118. package/dist/daemon.d.ts.map +1 -1
  119. package/dist/daemon.js +49 -52
  120. package/dist/daemon.js.map +1 -1
  121. package/dist/dashboard/skill-install-request.d.ts +21 -0
  122. package/dist/dashboard/skill-install-request.d.ts.map +1 -0
  123. package/dist/dashboard/skill-install-request.js +62 -0
  124. package/dist/dashboard/skill-install-request.js.map +1 -0
  125. package/dist/dashboard/web/app.d.ts.map +1 -1
  126. package/dist/dashboard/web/app.js +4 -1
  127. package/dist/dashboard/web/app.js.map +1 -1
  128. package/dist/dashboard/web/bot-defaults.d.ts.map +1 -1
  129. package/dist/dashboard/web/bot-defaults.js +61 -1
  130. package/dist/dashboard/web/bot-defaults.js.map +1 -1
  131. package/dist/dashboard/web/i18n.d.ts.map +1 -1
  132. package/dist/dashboard/web/i18n.js +146 -0
  133. package/dist/dashboard/web/i18n.js.map +1 -1
  134. package/dist/dashboard/web/skills.d.ts +2 -0
  135. package/dist/dashboard/web/skills.d.ts.map +1 -0
  136. package/dist/dashboard/web/skills.js +539 -0
  137. package/dist/dashboard/web/skills.js.map +1 -0
  138. package/dist/dashboard-web/app.js +599 -446
  139. package/dist/dashboard-web/index.html +1 -0
  140. package/dist/dashboard-web/style.css +793 -0
  141. package/dist/dashboard.js +250 -0
  142. package/dist/dashboard.js.map +1 -1
  143. package/dist/global-config.d.ts +7 -0
  144. package/dist/global-config.d.ts.map +1 -1
  145. package/dist/global-config.js +16 -0
  146. package/dist/global-config.js.map +1 -1
  147. package/dist/i18n/en.d.ts.map +1 -1
  148. package/dist/i18n/en.js +3 -5
  149. package/dist/i18n/en.js.map +1 -1
  150. package/dist/i18n/zh.d.ts.map +1 -1
  151. package/dist/i18n/zh.js +3 -5
  152. package/dist/i18n/zh.js.map +1 -1
  153. package/dist/im/lark/card-builder.d.ts +0 -3
  154. package/dist/im/lark/card-builder.d.ts.map +1 -1
  155. package/dist/im/lark/card-builder.js +2 -33
  156. package/dist/im/lark/card-builder.js.map +1 -1
  157. package/dist/services/bot-config-store.d.ts +10 -4
  158. package/dist/services/bot-config-store.d.ts.map +1 -1
  159. package/dist/services/bot-config-store.js +29 -2
  160. package/dist/services/bot-config-store.js.map +1 -1
  161. package/dist/services/session-store.d.ts +1 -0
  162. package/dist/services/session-store.d.ts.map +1 -1
  163. package/dist/services/session-store.js +12 -5
  164. package/dist/services/session-store.js.map +1 -1
  165. package/dist/services/skill-registry-store.d.ts +42 -0
  166. package/dist/services/skill-registry-store.d.ts.map +1 -0
  167. package/dist/services/skill-registry-store.js +343 -0
  168. package/dist/services/skill-registry-store.js.map +1 -0
  169. package/dist/skills/installer.d.ts.map +1 -1
  170. package/dist/skills/installer.js +3 -0
  171. package/dist/skills/installer.js.map +1 -1
  172. package/dist/types.d.ts +3 -5
  173. package/dist/types.d.ts.map +1 -1
  174. package/dist/utils/file-lock.d.ts +1 -0
  175. package/dist/utils/file-lock.d.ts.map +1 -1
  176. package/dist/utils/file-lock.js +87 -1
  177. package/dist/utils/file-lock.js.map +1 -1
  178. package/dist/worker.js +127 -20
  179. package/dist/worker.js.map +1 -1
  180. package/dist/workflows/definition.d.ts +16 -16
  181. package/dist/workflows/events/schema.d.ts +280 -280
  182. package/package.json +1 -1
  183. package/dist/services/pending-response-transaction-store.d.ts +0 -12
  184. package/dist/services/pending-response-transaction-store.d.ts.map +0 -1
  185. package/dist/services/pending-response-transaction-store.js +0 -52
  186. package/dist/services/pending-response-transaction-store.js.map +0 -1
package/dist/cli.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAu+IA;;;;;;;;;;;GAWG;AACH,wBAAsB,OAAO,CAC3B,OAAO,EAAE,OAAO,EAChB,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,EACvC,SAAS,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC,OAAO,qBAAqB,EAAE,SAAS,CAAC,EAC9F,KAAK,EAAE,MAAM,EACb,mBAAmB,CAAC,EAAE,MAAM,OAAO,CAAC,OAAO,2BAA2B,EAAE,UAAU,GAAG,IAAI,CAAC,GACzF,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CA8F7B"}
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AA86IA;;;;;;;;;;;GAWG;AACH,wBAAsB,OAAO,CAC3B,OAAO,EAAE,OAAO,EAChB,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,EACvC,SAAS,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC,OAAO,qBAAqB,EAAE,SAAS,CAAC,EAC9F,KAAK,EAAE,MAAM,EACb,mBAAmB,CAAC,EAAE,MAAM,OAAO,CAAC,OAAO,2BAA2B,EAAE,UAAU,GAAG,IAAI,CAAC,GACzF,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CA8F7B"}
package/dist/cli.js CHANGED
@@ -50,6 +50,7 @@ import { chatAppLink, larkHosts, normalizeBrand, sdkDomain } from './im/lark/lar
50
50
  import { readGlobalConfig, setGlobalLocale, globalConfigPath } from './global-config.js';
51
51
  import { buildBridgeSendMarkerContent } from './services/bridge-fallback-gate.js';
52
52
  import { writeManualIntentIfAbsentTo } from './services/restart-intent-store.js';
53
+ import { stripLegacyPendingCardFields } from './services/session-store.js';
53
54
  // Resolve the CLI's UI locale once from the global config file, so subsequent
54
55
  // CLI output (and any t() callers that don't pass an explicit locale) honour
55
56
  // the user's chosen language. Daemon entrypoint sets this separately for the
@@ -1585,12 +1586,17 @@ function saveSession(session) {
1585
1586
  }
1586
1587
  catch { /* start fresh */ }
1587
1588
  }
1588
- data[session.sessionId] = mergePendingResponseState(session, data[session.sessionId]);
1589
- // Clean up entries where file key doesn't match the entry's sessionId (data corruption)
1589
+ data[session.sessionId] = session;
1590
+ // Clean up entries where file key doesn't match the entry's sessionId (data
1591
+ // corruption), and strip legacy placeholder-card fields so the file converges
1592
+ // to clean (see stripLegacyPendingCardFields in services/session-store).
1590
1593
  for (const [key, val] of Object.entries(data)) {
1591
1594
  if (val && typeof val === 'object' && 'sessionId' in val && val.sessionId !== key) {
1592
1595
  delete data[key];
1596
+ continue;
1593
1597
  }
1598
+ if (val && typeof val === 'object')
1599
+ stripLegacyPendingCardFields(val);
1594
1600
  }
1595
1601
  const tmpFp = fp + '.tmp';
1596
1602
  writeFileSync(tmpFp, JSON.stringify(data, null, 2), 'utf-8');
@@ -2949,9 +2955,7 @@ function argValues(args, ...flags) {
2949
2955
  // Card v2 body builder helpers — extracted to im/lark/md-card.ts so the
2950
2956
  // daemon's bridge fallback path can produce identical cards. cmdSend
2951
2957
  // keeps using `buildImageCardElements` from there.
2952
- import { buildMentionedPendingResponseCard } from './im/lark/card-builder.js';
2953
2958
  import { buildImageCardElements, brandFooterSegment } from './im/lark/md-card.js';
2954
- import { COMPLETED_REACTION_EMOJI_TYPE, claimPendingResponseCard, markPendingResponseCardPatchedIfCurrent, mergePendingResponseState, shouldMarkPendingAsMentionedSend, shouldPatchPendingOnExplicitSend } from './core/pending-response.js';
2955
2959
  import { resolveBrandLabel } from './bot-registry.js';
2956
2960
  import { config } from './config.js';
2957
2961
  import { resolveQuoteTarget, validateMentionDecision, parseAttentionFlag, attentionUsageError } from './services/send-policy.js';
@@ -3271,19 +3275,6 @@ async function cmdSend(rest) {
3271
3275
  appendFileSync(join(markerDir, `${sid}.jsonl`), JSON.stringify({ sentAtMs: Date.now(), messageId: `doc:${docTarget.commentId}`, contentLength: content.length }) + '\n');
3272
3276
  }
3273
3277
  catch { /* best-effort:漏记只多一条兜底 */ }
3274
- // 收尾飞书侧占位卡(streaming-disabled 会话)避免停在「处理中」。
3275
- try {
3276
- const pendingCardId = claimPendingResponseCard(s);
3277
- const latest = pendingCardId ? loadSessionFresh(s) : undefined;
3278
- if (pendingCardId && latest?.pendingResponseCardId === pendingCardId) {
3279
- const { updateMessage } = await import('./im/lark/client.js');
3280
- const { buildMarkdownCard } = await import('./im/lark/md-card.js');
3281
- await updateMessage(appId, pendingCardId, buildMarkdownCard(t('daemon.doc_comment_replied_card', undefined, loc), undefined, resolveBrandLabel(appId), loc));
3282
- if (markPendingResponseCardPatchedIfCurrent(latest, pendingCardId))
3283
- saveSession(latest);
3284
- }
3285
- }
3286
- catch { /* best-effort */ }
3287
3278
  console.error(`✓ 已回复文档评论 ${docTarget.commentId.slice(0, 12)}(${chunks.length} 条)`);
3288
3279
  console.log(JSON.stringify({ success: true, commentId: docTarget.commentId, sessionId: sid, kind: 'doc-comment', chunks: chunks.length }));
3289
3280
  }
@@ -3343,7 +3334,7 @@ async function cmdSend(rest) {
3343
3334
  registerBot(cfg);
3344
3335
  }
3345
3336
  catch { /* */ }
3346
- const { sendMessage, replyMessage, uploadImage, uploadFile, updateMessage, addReaction, MessageWithdrawnError } = await import('./im/lark/client.js');
3337
+ const { sendMessage, replyMessage, uploadImage, uploadFile, MessageWithdrawnError } = await import('./im/lark/client.js');
3347
3338
  const appId = s.larkAppId;
3348
3339
  // Effective target chat for top-level mode (defaults to session's chat)
3349
3340
  const targetChatId = overrideChatId ?? s.chatId;
@@ -3422,51 +3413,6 @@ async function cmdSend(rest) {
3422
3413
  catch { /* best-effort: marker miss only causes a redundant fallback message */ }
3423
3414
  };
3424
3415
  const shouldRecordBridgeMarker = !sendTopLevel && !overrideChatId && !sendInto;
3425
- let hasNotificationMentionsForPending = mentionArgs.length > 0;
3426
- const dispatchOrPatchPending = async (content, msgType) => {
3427
- const pendingCardId = shouldPatchPendingOnExplicitSend(s, { msgType, sendTopLevel, overrideChatId: !!overrideChatId, sendInto: !!sendInto, hasNotificationMentions: hasNotificationMentionsForPending })
3428
- ? claimPendingResponseCard(s)
3429
- : undefined;
3430
- if (!pendingCardId) {
3431
- const sentId = await dispatchPrimary(content, msgType);
3432
- if (shouldMarkPendingAsMentionedSend({ msgType, sendTopLevel, overrideChatId: !!overrideChatId, sendInto: !!sendInto, hasNotificationMentions: hasNotificationMentionsForPending })) {
3433
- const stalePendingCardId = claimPendingResponseCard(s);
3434
- const latest = stalePendingCardId ? loadSessionFresh(s) : undefined;
3435
- if (stalePendingCardId && latest?.pendingResponseCardId === stalePendingCardId) {
3436
- updateMessage(appId, stalePendingCardId, buildMentionedPendingResponseCard(localeForBot(appId)))
3437
- .then(() => {
3438
- if (markPendingResponseCardPatchedIfCurrent(latest, stalePendingCardId))
3439
- saveSession(latest);
3440
- })
3441
- .catch((err) => logger.warn(`[send:${sid.substring(0, 8)}] failed to mark pending card after mentioned send: ${err?.message ?? err}`));
3442
- }
3443
- }
3444
- return sentId;
3445
- }
3446
- const latest = loadSessionFresh(s);
3447
- if (latest?.pendingResponseCardId !== pendingCardId)
3448
- return dispatchPrimary(content, msgType);
3449
- try {
3450
- await updateMessage(appId, pendingCardId, content);
3451
- if (markPendingResponseCardPatchedIfCurrent(latest, pendingCardId)) {
3452
- saveSession(latest);
3453
- if (latest.quoteTargetId) {
3454
- addReaction(appId, latest.quoteTargetId, COMPLETED_REACTION_EMOJI_TYPE)
3455
- .catch((err) => logger.warn(`[send:${sid.substring(0, 8)}] failed to add completion reaction to ${latest.quoteTargetId}: ${err?.message ?? err}`));
3456
- }
3457
- }
3458
- return pendingCardId;
3459
- }
3460
- catch (err) {
3461
- if (err instanceof MessageWithdrawnError) {
3462
- logger.warn(`[send:${sid.substring(0, 8)}] pending card withdrawn before explicit send patch; sending a new reply`);
3463
- markPendingResponseCardPatchedIfCurrent(latest, pendingCardId);
3464
- saveSession(latest);
3465
- return dispatchPrimary(content, msgType);
3466
- }
3467
- throw err;
3468
- }
3469
- };
3470
3416
  // Quote chain (普通群): the primary message replies to the turn's target so
3471
3417
  // Lark renders a 引用 chain. --quote overrides, --no-quote opts out. Thread
3472
3418
  // scope and --top-level never quote. Withdrawn target → fall back to plain.
@@ -3608,7 +3554,6 @@ async function cmdSend(rest) {
3608
3554
  }
3609
3555
  catch { /* best-effort */ }
3610
3556
  const explicitKnownBotMention = hasKnownBotMention(text, mentions, botEntries, crossRef, appId);
3611
- hasNotificationMentionsForPending ||= explicitKnownBotMention;
3612
3557
  const knownBotOpenIds = knownBotOpenIdsFromCrossRef(crossRef, botEntries, appId);
3613
3558
  // --no-mention 显式不 @ 任何人 → 连 footer 的"发送给/cc"寻址 <at> 也清空,
3614
3559
  // 否则 footer 仍会 @ 人,与 --no-mention 语义和"未@任何人"输出自相矛盾
@@ -3742,7 +3687,7 @@ async function cmdSend(rest) {
3742
3687
  config: { update_multi: true },
3743
3688
  body: { direction: 'vertical', elements },
3744
3689
  });
3745
- messageId = await dispatchOrPatchPending(cardJson, 'interactive');
3690
+ messageId = await dispatchPrimary(cardJson, 'interactive');
3746
3691
  }
3747
3692
  // Bridge fallback marker — append-only jsonl per session. Same-thread
3748
3693
  // sends can suppress transcript fallback when their content appears to
@@ -5198,6 +5143,26 @@ switch (command) {
5198
5143
  await cmdAsk(sub, rest);
5199
5144
  break;
5200
5145
  }
5146
+ case 'skill': {
5147
+ const { runSkillSessionCommand } = await import('./core/skills/cli-session-command.js');
5148
+ const result = runSkillSessionCommand(process.argv.slice(3));
5149
+ if (result.stdout)
5150
+ process.stdout.write(result.stdout);
5151
+ if (result.stderr)
5152
+ process.stderr.write(result.stderr);
5153
+ process.exitCode = result.code;
5154
+ break;
5155
+ }
5156
+ case 'skills': {
5157
+ const { runSkillsAdminCommand } = await import('./core/skills/cli-admin-command.js');
5158
+ const result = runSkillsAdminCommand(process.argv.slice(3));
5159
+ if (result.stdout)
5160
+ process.stdout.write(result.stdout);
5161
+ if (result.stderr)
5162
+ process.stderr.write(result.stderr);
5163
+ process.exitCode = result.code;
5164
+ break;
5165
+ }
5201
5166
  case 'hook': {
5202
5167
  // `botmux hook <cliId>` — hook 客户端,stdin 读 payload,stdout 写 directive
5203
5168
  const cliId = process.argv[3] ?? '';