workspacecord 1.1.3 → 1.1.4

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 (25) hide show
  1. package/dist/{archive-manager-RW36JGUV.js → archive-manager-FJU7YEEH.js} +4 -4
  2. package/dist/{attachment-cli-MF7XZ4WT.js → attachment-cli-AT4HXAGU.js} +2 -2
  3. package/dist/{chunk-ZO62NAYX.js → chunk-5EMN2IL5.js} +1 -1
  4. package/dist/{chunk-BFINJJYL.js → chunk-66B64WL3.js} +1 -1
  5. package/dist/{chunk-QWPKAUSV.js → chunk-C4L34VJK.js} +8287 -7421
  6. package/dist/{chunk-WON3DPE4.js → chunk-JR4B4L7I.js} +213 -4
  7. package/dist/{chunk-IVXCJA5I.js → chunk-MJ5JKFGS.js} +9 -0
  8. package/dist/{chunk-7GTUWAQR.js → chunk-NNTMVOTM.js} +876 -315
  9. package/dist/{chunk-WP6YJVAE.js → chunk-PWMEOBXG.js} +4 -4
  10. package/dist/{chunk-AGB4GP4G.js → chunk-SNPFYUQ3.js} +441 -654
  11. package/dist/{chunk-4KQ7OSK7.js → chunk-SV7EHL3B.js} +3 -3
  12. package/dist/cli-framework-YF3LPLMT.js +18 -0
  13. package/dist/cli.js +10 -10
  14. package/dist/{codex-launcher-ZBQ5VL6L.js → codex-launcher-CLGG4CVY.js} +1 -1
  15. package/dist/{codex-provider-Q4Z6UKO6.js → codex-provider-VLOS5QB6.js} +18 -4
  16. package/dist/{config-cli-7JEV3WYY.js → config-cli-7G5YWKJU.js} +2 -2
  17. package/dist/{panel-adapter-U75WXDLB.js → panel-adapter-CLI4WDII.js} +4 -4
  18. package/dist/{project-cli-ZXMHOFUJ.js → project-cli-ALKDLRMZ.js} +2 -2
  19. package/dist/{project-registry-ED6P5ZTM.js → project-registry-ZO3KSS25.js} +2 -2
  20. package/dist/sdk-C3D6X4EB.js +55 -0
  21. package/dist/{session-local-registration-MISPPGXF.js → session-local-registration-RL2A3QZB.js} +3 -3
  22. package/dist/{setup-ZFVMMNT2.js → setup-GP3MML2R.js} +1 -1
  23. package/package.json +3 -3
  24. package/dist/cli-framework-7E5MKPMM.js +0 -18
  25. package/dist/sdk-V7A7IF7F.js +0 -43
@@ -1,12 +1,13 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
- Aa
4
- } from "./chunk-QWPKAUSV.js";
3
+ E$$
4
+ } from "./chunk-C4L34VJK.js";
5
5
  import {
6
6
  buildDeliveryPlan,
7
7
  cleanupOldMessages,
8
8
  cleanupSessionPanel,
9
9
  deliver,
10
+ dispatchEvent,
10
11
  flushDigest,
11
12
  generatePerformanceReport,
12
13
  getPendingAnswers,
@@ -14,23 +15,29 @@ import {
14
15
  getSessionContext,
15
16
  getSessionProjection,
16
17
  getSessionView,
18
+ getSubagents,
17
19
  handleAwaitingHuman,
18
20
  handleResultEvent,
19
21
  initializeSessionPanel,
22
+ makeModeButtons,
20
23
  notifyUnmanagedCodexHint,
21
24
  queueDigest,
22
25
  registerExistingStatusCard,
23
26
  relocateSessionPanelToBottom,
27
+ resolveEffectiveClaudePermissionMode as resolveEffectiveClaudePermissionMode2,
28
+ runSubagentWatchdog,
24
29
  sendAckReaction,
30
+ sendSystemNotice,
25
31
  sendTyping,
26
32
  setPendingAnswer,
33
+ spawnSubagent,
27
34
  startPerformanceMonitoring,
28
35
  stopPerformanceMonitoring,
29
36
  updateSessionState
30
- } from "./chunk-7GTUWAQR.js";
37
+ } from "./chunk-NNTMVOTM.js";
31
38
  import {
32
39
  registerMessageAttachments
33
- } from "./chunk-BFINJJYL.js";
40
+ } from "./chunk-66B64WL3.js";
34
41
  import {
35
42
  addMcpServer,
36
43
  addSkill,
@@ -51,14 +58,14 @@ import {
51
58
  setControlChannelId,
52
59
  setHistoryChannelId,
53
60
  setPersonality
54
- } from "./chunk-4KQ7OSK7.js";
61
+ } from "./chunk-SV7EHL3B.js";
55
62
  import {
56
63
  getAllRegisteredProjects
57
- } from "./chunk-ZO62NAYX.js";
64
+ } from "./chunk-5EMN2IL5.js";
58
65
  import {
59
66
  buildClaudeSubagentProviderSessionId,
60
67
  registerLocalSession
61
- } from "./chunk-WP6YJVAE.js";
68
+ } from "./chunk-PWMEOBXG.js";
62
69
  import {
63
70
  abortSession,
64
71
  abortSessionWithReason,
@@ -66,9 +73,12 @@ import {
66
73
  consumeAbortReason,
67
74
  createSession,
68
75
  debouncedSaveSession,
76
+ drainBatchApprovals,
69
77
  endSession,
78
+ enqueueBatchApproval,
70
79
  gateService,
71
80
  getAllSessions,
81
+ getBatchApprovalCount,
72
82
  getOutputPort,
73
83
  getSessionByChannel,
74
84
  getSessionByProviderSession,
@@ -80,6 +90,7 @@ import {
80
90
  markSessionGenerating,
81
91
  normalizeCodexEvent,
82
92
  registerOutputPort,
93
+ removeBatchApproval,
83
94
  resolveCodexSessionFromMonitor,
84
95
  resolveEffectiveClaudePermissionMode,
85
96
  resolveEffectiveCodexOptions,
@@ -96,7 +107,7 @@ import {
96
107
  updateSession,
97
108
  updateSessionPermissions,
98
109
  updateWorkflowState
99
- } from "./chunk-WON3DPE4.js";
110
+ } from "./chunk-JR4B4L7I.js";
100
111
  import {
101
112
  JsonFileRepository,
102
113
  MonitorRunEnded,
@@ -111,7 +122,7 @@ import {
111
122
  isAbortError,
112
123
  isUserAllowed,
113
124
  truncate
114
- } from "./chunk-IVXCJA5I.js";
125
+ } from "./chunk-MJ5JKFGS.js";
115
126
  import {
116
127
  __commonJS,
117
128
  __require,
@@ -607,9 +618,9 @@ var require_cross_spawn = __commonJS({
607
618
  }
608
619
  function spawnSync2(command, args, options) {
609
620
  const parsed = parse(command, args, options);
610
- const result2 = cp.spawnSync(parsed.command, parsed.args, parsed.options);
611
- result2.error = result2.error || enoent.verifyENOENTSync(result2.status, parsed);
612
- return result2;
621
+ const result = cp.spawnSync(parsed.command, parsed.args, parsed.options);
622
+ result.error = result.error || enoent.verifyENOENTSync(result.status, parsed);
623
+ return result;
613
624
  }
614
625
  module.exports = spawn2;
615
626
  module.exports.spawn = spawn2;
@@ -626,15 +637,43 @@ import cac from "cac";
626
637
  import {
627
638
  Client as Client2,
628
639
  GatewayIntentBits,
629
- ChannelType as ChannelType8
640
+ ChannelType as ChannelType7
630
641
  } from "discord.js";
631
642
 
632
643
  // ../bot/src/bot-services-orchestrator.ts
633
- import { ChannelType as ChannelType4 } from "discord.js";
644
+ import { ChannelType as ChannelType3 } from "discord.js";
634
645
  import { homedir as homedir3 } from "os";
635
646
  import { join as join4 } from "path";
636
647
 
637
648
  // ../providers/src/claude-provider.ts
649
+ function mapClaudeTerminalReason(raw) {
650
+ if (!raw) return void 0;
651
+ switch (raw) {
652
+ case "completed":
653
+ return "completed";
654
+ case "max_turns":
655
+ return "max_turns";
656
+ case "blocking_limit":
657
+ case "rapid_refill_breaker":
658
+ return "rate_limited";
659
+ case "prompt_too_long":
660
+ return "context_too_long";
661
+ case "image_error":
662
+ return "image_error";
663
+ case "model_error":
664
+ return "model_error";
665
+ case "aborted_streaming":
666
+ case "aborted_tools":
667
+ return "aborted";
668
+ case "stop_hook_prevented":
669
+ case "hook_stopped":
670
+ return "hook_stopped";
671
+ case "tool_deferred":
672
+ return "tool_deferred";
673
+ default:
674
+ return "error";
675
+ }
676
+ }
638
677
  var TASK_TOOLS = /* @__PURE__ */ new Set(["TaskCreate", "TaskUpdate", "TaskList", "TaskGet"]);
639
678
  var IMAGE_EXTENSIONS = /* @__PURE__ */ new Set([".png", ".jpg", ".jpeg", ".gif", ".webp", ".svg", ".bmp"]);
640
679
  function extractImagePath(toolName, toolInput) {
@@ -687,7 +726,7 @@ var ClaudeProvider = class {
687
726
  let resumeId = options.providerSessionId;
688
727
  while (true) {
689
728
  let failed = false;
690
- const stream = Aa({
729
+ const stream = E$$({
691
730
  prompt: buildQueryPrompt(),
692
731
  options: {
693
732
  cwd: options.directory,
@@ -722,7 +761,7 @@ var ClaudeProvider = class {
722
761
  let resumeId = options.providerSessionId;
723
762
  while (true) {
724
763
  let failed = false;
725
- const stream = Aa({
764
+ const stream = E$$({
726
765
  prompt: "",
727
766
  options: {
728
767
  cwd: options.directory,
@@ -797,13 +836,14 @@ var ClaudeProvider = class {
797
836
  let resultText = "";
798
837
  const toolName = "";
799
838
  if (Array.isArray(content)) {
800
- for (const block of content) {
839
+ for (const rawBlock of content) {
840
+ const block = rawBlock;
801
841
  if (block.type === "tool_result" && block.content) {
802
842
  if (typeof block.content === "string") {
803
843
  resultText += block.content;
804
844
  } else if (Array.isArray(block.content)) {
805
845
  for (const sub of block.content) {
806
- if (sub.type === "text") resultText += sub.text;
846
+ if (sub.type === "text" && sub.text) resultText += sub.text;
807
847
  }
808
848
  }
809
849
  }
@@ -851,7 +891,8 @@ var ClaudeProvider = class {
851
891
  costUsd: r.total_cost_usd ?? 0,
852
892
  durationMs: r.duration_ms ?? 0,
853
893
  numTurns: r.num_turns ?? 0,
854
- errors: r.errors ?? []
894
+ errors: r.errors ?? [],
895
+ terminalReason: mapClaudeTerminalReason(r.terminal_reason) ?? (r.subtype === "success" ? "completed" : "error")
855
896
  };
856
897
  }
857
898
  }
@@ -864,7 +905,7 @@ providers.set("claude", new ClaudeProvider());
864
905
  var codexLoadAttempted = false;
865
906
  async function loadCodexProvider() {
866
907
  try {
867
- const { CodexProvider } = await import("./codex-provider-Q4Z6UKO6.js");
908
+ const { CodexProvider } = await import("./codex-provider-VLOS5QB6.js");
868
909
  providers.set("codex", new CodexProvider());
869
910
  codexLoadAttempted = true;
870
911
  } catch (err) {
@@ -1023,15 +1064,18 @@ function buildMonitorSystemPromptParts(session) {
1023
1064
  // ../engine/src/session/provider-runtime.ts
1024
1065
  function buildProviderOptions(session, controller, isMonitor = false, runtimeOverrides = {}) {
1025
1066
  const effectiveCodex = resolveEffectiveCodexOptions(session);
1067
+ const monitorEffort = isMonitor ? config.monitorReasoningEffort || void 0 : void 0;
1068
+ const useMonitorJudgeModel = isMonitor && session.provider === "claude" && (monitorEffort === "high" || monitorEffort === "xhigh");
1069
+ const model = useMonitorJudgeModel ? config.monitorClaudeModel || session.model : session.model;
1026
1070
  return {
1027
1071
  directory: session.directory,
1028
1072
  providerSessionId: isMonitor ? session.monitorProviderSessionId : session.providerSessionId,
1029
- model: session.model,
1073
+ model,
1030
1074
  sandboxMode: effectiveCodex.sandboxMode,
1031
1075
  approvalPolicy: effectiveCodex.approvalPolicy,
1032
1076
  networkAccessEnabled: effectiveCodex.networkAccessEnabled,
1033
1077
  webSearchMode: effectiveCodex.webSearchMode,
1034
- modelReasoningEffort: config.codexReasoningEffort || void 0,
1078
+ modelReasoningEffort: monitorEffort ?? (config.codexReasoningEffort || void 0),
1035
1079
  claudePermissionMode: resolveEffectiveClaudePermissionMode(session),
1036
1080
  systemPromptParts: isMonitor ? buildMonitorSystemPromptParts(session) : buildSystemPromptParts(session),
1037
1081
  abortController: controller,
@@ -1153,17 +1197,31 @@ async function* sendMonitorPrompt(sessionId, prompt) {
1153
1197
  function refreshSession(session) {
1154
1198
  return getSessionView(session.id) ?? session;
1155
1199
  }
1200
+ async function recordPermissionDenial(session, toolName, reason, source) {
1201
+ await getOutputPort().updateState(session.id, {
1202
+ type: "permission_denied",
1203
+ sessionId: session.id,
1204
+ source: session.provider === "codex" ? "codex" : "claude",
1205
+ confidence: "high",
1206
+ timestamp: Date.now(),
1207
+ metadata: { toolName, reason, source }
1208
+ });
1209
+ getOutputPort().queueDigest(session.id, {
1210
+ kind: "denied",
1211
+ text: `\u26D4 \u6743\u9650\u62D2\u7EDD\uFF1A${truncate(toolName, 40)} \u2014 ${truncate(reason, 80)}`
1212
+ });
1213
+ }
1156
1214
  function waitForGateResolution(session, gateId) {
1157
1215
  console.log(`[SessionExecutor] gate:waiting sessionId=${session.id} gateId=${gateId}`);
1158
1216
  return new Promise((resolve2) => {
1159
1217
  let settled = false;
1160
- const settle = (result2) => {
1218
+ const settle = (result) => {
1161
1219
  if (settled) return;
1162
1220
  settled = true;
1163
1221
  console.log(
1164
- `[SessionExecutor] gate:resolved sessionId=${session.id} gateId=${gateId} action=${result2.action} source=${result2.source}`
1222
+ `[SessionExecutor] gate:resolved sessionId=${session.id} gateId=${gateId} action=${result.action} source=${result.source}`
1165
1223
  );
1166
- resolve2(result2);
1224
+ resolve2(result);
1167
1225
  };
1168
1226
  gateService.registerReceiptHandle(gateId, {
1169
1227
  type: session.provider === "codex" ? "codex" : "claude",
@@ -1192,6 +1250,80 @@ function createClaudePermissionHandler(session, _channel) {
1192
1250
  console.log(
1193
1251
  `[SessionExecutor] permission:request sessionId=${liveSession.id} tool=${toolName} action=${context.displayName || toolName}`
1194
1252
  );
1253
+ const projection = stateMachine.getSnapshot(liveSession.id);
1254
+ if (projection.batchApprovalMode) {
1255
+ const gateId2 = `batch-${liveSession.id}-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
1256
+ const timestamp = Date.now();
1257
+ const displayName = context.displayName || toolName;
1258
+ const batchAction = await new Promise((resolve2) => {
1259
+ let settled = false;
1260
+ const settle = (action) => {
1261
+ if (settled) return;
1262
+ settled = true;
1263
+ resolve2(action);
1264
+ };
1265
+ const enqueueResult = enqueueBatchApproval(liveSession.id, {
1266
+ gateId: gateId2,
1267
+ toolUseID: context.toolUseID,
1268
+ toolName: displayName,
1269
+ detail,
1270
+ timestamp,
1271
+ resolve: settle
1272
+ });
1273
+ if (enqueueResult === "overflow") {
1274
+ console.warn(
1275
+ `[SessionExecutor] permission:batch-overflow sessionId=${liveSession.id} tool=${toolName} reason="queue at capacity"`
1276
+ );
1277
+ settle("reject");
1278
+ return;
1279
+ }
1280
+ stateMachine.enqueuePendingApproval(liveSession.id, {
1281
+ gateId: gateId2,
1282
+ toolName: displayName,
1283
+ detail,
1284
+ timestamp
1285
+ });
1286
+ void getOutputPort().updateState(liveSession.id, {
1287
+ type: "batch_approval_changed",
1288
+ sessionId: liveSession.id,
1289
+ source: liveSession.provider === "codex" ? "codex" : "claude",
1290
+ confidence: "high",
1291
+ timestamp,
1292
+ metadata: {
1293
+ enabled: true,
1294
+ pendingApprovals: stateMachine.getSnapshot(liveSession.id).pendingApprovals
1295
+ }
1296
+ }).catch(() => {
1297
+ });
1298
+ getOutputPort().queueDigest(liveSession.id, {
1299
+ kind: "batch",
1300
+ text: `\u5DF2\u5165\u6279\u91CF\u5BA1\u6279\u961F\u5217\uFF1A${truncate(toolName, 40)}`
1301
+ });
1302
+ const onAbort = () => {
1303
+ settle("reject");
1304
+ removeBatchApproval(liveSession.id, gateId2);
1305
+ stateMachine.removePendingApproval(liveSession.id, gateId2);
1306
+ };
1307
+ if (context.signal.aborted) onAbort();
1308
+ else context.signal.addEventListener("abort", onAbort, { once: true });
1309
+ });
1310
+ if (batchAction === "approve") {
1311
+ console.log(
1312
+ `[SessionExecutor] permission:batch-approved sessionId=${liveSession.id} tool=${toolName}`
1313
+ );
1314
+ return { behavior: "allow", toolUseID: context.toolUseID };
1315
+ }
1316
+ console.log(
1317
+ `[SessionExecutor] permission:batch-rejected sessionId=${liveSession.id} tool=${toolName}`
1318
+ );
1319
+ await recordPermissionDenial(liveSession, toolName, "\u6279\u91CF\u62D2\u7EDD", "user");
1320
+ return {
1321
+ behavior: "deny",
1322
+ message: "\u6279\u91CF\u62D2\u7EDD",
1323
+ interrupt: true,
1324
+ toolUseID: context.toolUseID
1325
+ };
1326
+ }
1195
1327
  await getOutputPort().handleAwaitingHuman(liveSession.id, detail, { source: "claude" });
1196
1328
  const currentSession = refreshSession(liveSession);
1197
1329
  const gateId = currentSession.activeHumanGateId;
@@ -1232,9 +1364,11 @@ function createClaudePermissionHandler(session, _channel) {
1232
1364
  if (resolved.action === "approve") {
1233
1365
  return { behavior: "allow", toolUseID: context.toolUseID };
1234
1366
  }
1367
+ const denyReason = resolved.source === "timeout" ? "\u5BA1\u6279\u8D85\u65F6\uFF085 \u5206\u949F\uFF09" : resolved.source === "terminal" ? "\u5DF2\u5728\u7EC8\u7AEF\u62D2\u7EDD" : "\u5DF2\u5728 Discord \u62D2\u7EDD";
1368
+ await recordPermissionDenial(currentSession, toolName, denyReason, resolved.source);
1235
1369
  return {
1236
1370
  behavior: "deny",
1237
- message: resolved.source === "timeout" ? "\u5BA1\u6279\u8D85\u65F6\uFF085 \u5206\u949F\uFF09" : resolved.source === "terminal" ? "\u5DF2\u5728\u7EC8\u7AEF\u62D2\u7EDD" : "\u5DF2\u5728 Discord \u62D2\u7EDD",
1371
+ message: denyReason,
1238
1372
  interrupt: true,
1239
1373
  toolUseID: context.toolUseID
1240
1374
  };
@@ -1299,30 +1433,30 @@ function extractRemainingGaps(text) {
1299
1433
  (sentence) => /\b(still|missing|need|remaining|not yet|left to|have not)\b/i.test(sentence)
1300
1434
  ).slice(0, 5);
1301
1435
  }
1302
- function buildWorkerProgressReport(goal, result2) {
1303
- const changedFiles = result2.changedFiles ?? [];
1304
- const recentCommands = result2.recentCommands ?? [];
1436
+ function buildWorkerProgressReport(goal, result) {
1437
+ const changedFiles = result.changedFiles ?? [];
1438
+ const recentCommands = result.recentCommands ?? [];
1305
1439
  const validationCommands = recentCommands.filter(
1306
1440
  (command) => /\b(test|vitest|jest|pytest|npm test|pnpm test|yarn test|grader|validate|check|lint)\b/i.test(
1307
1441
  command
1308
1442
  )
1309
1443
  ).slice(0, 10);
1310
- const meaningfulExecution = result2.commandCount > 0 || result2.fileChangeCount > 0;
1311
- const blockers = result2.hadError ? ["The latest pass reported an error or stalled outcome."] : [];
1444
+ const meaningfulExecution = result.commandCount > 0 || result.fileChangeCount > 0;
1445
+ const blockers = result.hadError ? ["The latest pass reported an error or stalled outcome."] : [];
1312
1446
  return {
1313
1447
  originalGoal: goal,
1314
- textualResponse: summarizeWorkerText(result2.text),
1315
- commandCount: result2.commandCount,
1316
- fileChangeCount: result2.fileChangeCount,
1448
+ textualResponse: summarizeWorkerText(result.text),
1449
+ commandCount: result.commandCount,
1450
+ fileChangeCount: result.fileChangeCount,
1317
1451
  meaningfulExecutionEvidence: meaningfulExecution,
1318
- providerReportedSuccess: result2.success === null ? "unknown" : result2.success ? "yes" : "no",
1319
- workerErrorsObserved: result2.hadError,
1320
- askedForHumanInput: result2.askedUser,
1321
- claimedCompletedOutcomes: extractClaimedCompletedOutcomes(result2.text),
1452
+ providerReportedSuccess: result.success === null ? "unknown" : result.success ? "yes" : "no",
1453
+ workerErrorsObserved: result.hadError,
1454
+ askedForHumanInput: result.askedUser,
1455
+ claimedCompletedOutcomes: extractClaimedCompletedOutcomes(result.text),
1322
1456
  artifacts: changedFiles,
1323
1457
  validationCommands,
1324
- goalAssessment: result2.text.trim() ? truncate(result2.text.trim(), 1200) : meaningfulExecution ? "The worker executed commands or changed files but did not provide an explicit textual assessment." : "The worker did not provide a substantive assessment of progress toward the goal.",
1325
- remainingGaps: extractRemainingGaps(result2.text),
1458
+ goalAssessment: result.text.trim() ? truncate(result.text.trim(), 1200) : meaningfulExecution ? "The worker executed commands or changed files but did not provide an explicit textual assessment." : "The worker did not provide a substantive assessment of progress toward the goal.",
1459
+ remainingGaps: extractRemainingGaps(result.text),
1326
1460
  blockers
1327
1461
  };
1328
1462
  }
@@ -2091,7 +2225,7 @@ async function runWorkerPass(session, channel, prompt, iteration, mode = "prompt
2091
2225
  watchdogTimer = setTimeout(scheduleWatchdog, delay);
2092
2226
  };
2093
2227
  watchdogTimer = setTimeout(scheduleWatchdog, WATCHDOG_SLOW_INTERVAL);
2094
- const result2 = await getOutputPort().handleOutputStream(
2228
+ const result = await getOutputPort().handleOutputStream(
2095
2229
  stream,
2096
2230
  channel,
2097
2231
  session.id,
@@ -2107,10 +2241,10 @@ async function runWorkerPass(session, channel, prompt, iteration, mode = "prompt
2107
2241
  const abortReason = consumeAbortReason(session.id);
2108
2242
  if (watchdogTriggered || abortReason === "watchdog") {
2109
2243
  const stalledResult = {
2110
- ...result2,
2244
+ ...result,
2111
2245
  hadError: true,
2112
2246
  abortReason,
2113
- text: annotateInactivityAbort(result2.text, WORKER_IDLE_TIMEOUT_MS)
2247
+ text: annotateInactivityAbort(result.text, WORKER_IDLE_TIMEOUT_MS)
2114
2248
  };
2115
2249
  const stalledReport = buildWorkerProgressReport("", stalledResult);
2116
2250
  applyWorkflowHook(session, "on_stall", {
@@ -2123,17 +2257,17 @@ async function runWorkerPass(session, channel, prompt, iteration, mode = "prompt
2123
2257
  );
2124
2258
  return stalledResult;
2125
2259
  }
2126
- const resultReport = buildWorkerProgressReport("", result2);
2260
+ const resultReport = buildWorkerProgressReport("", result);
2127
2261
  applyWorkflowHook(session, "after_worker_pass", {
2128
2262
  status: session.mode === "monitor" ? "monitor_review" : "idle",
2129
2263
  lastWorkerSummary: summarizeWorkerPass(resultReport),
2130
2264
  lastWorkerReport: resultReport
2131
2265
  });
2132
2266
  console.log(
2133
- `[SessionExecutor] worker:end sessionId=${session.id} iteration=${iteration} commands=${result2.commandCount} files=${result2.fileChangeCount} success=${result2.success} hasError=${result2.hadError}`
2267
+ `[SessionExecutor] worker:end sessionId=${session.id} iteration=${iteration} commands=${result.commandCount} files=${result.fileChangeCount} success=${result.success} hasError=${result.hadError}`
2134
2268
  );
2135
2269
  return {
2136
- ...result2,
2270
+ ...result,
2137
2271
  abortReason
2138
2272
  };
2139
2273
  } finally {
@@ -2419,448 +2553,6 @@ var MessageStreamer = class {
2419
2553
  }
2420
2554
  };
2421
2555
 
2422
- // ../bot/src/output/event-handlers.ts
2423
- import { existsSync } from "fs";
2424
-
2425
- // ../bot/src/subagent-manager.ts
2426
- import {
2427
- ChannelType,
2428
- ThreadAutoArchiveDuration
2429
- } from "discord.js";
2430
-
2431
- // ../bot/src/discord/delivery-notices.ts
2432
- function getDeliveryPolicy() {
2433
- return {
2434
- textChunkLimit: config.textChunkLimit ?? 2e3,
2435
- chunkMode: config.chunkMode ?? "length",
2436
- replyToMode: config.replyToMode ?? "first",
2437
- ackReaction: config.ackReaction ?? "\u{1F440}"
2438
- };
2439
- }
2440
- async function sendSystemNotice(channel, sessionId, text, replyToMessageId) {
2441
- if (!text.trim()) return;
2442
- const plan = buildDeliveryPlan({
2443
- sessionId,
2444
- chatId: channel.id,
2445
- text,
2446
- files: [],
2447
- mode: "system_notice",
2448
- replyToMessageId,
2449
- policy: getDeliveryPolicy()
2450
- });
2451
- try {
2452
- await deliver(channel, plan);
2453
- } catch {
2454
- }
2455
- }
2456
-
2457
- // ../bot/src/subagent-manager.ts
2458
- var SUBAGENT_IDLE_TIMEOUT_MS = 60 * 60 * 1e3;
2459
- function canSpawnSubagent(parentSession) {
2460
- return parentSession.subagentDepth < config.maxSubagentDepth;
2461
- }
2462
- async function spawnSubagent(parentSession, label, provider, sessionChannel) {
2463
- if (!canSpawnSubagent(parentSession)) {
2464
- console.warn(`[SubagentManager] Depth limit hit for session ${parentSession.id} (max depth ${config.maxSubagentDepth})`);
2465
- throw new Error(
2466
- `Max subagent depth (${config.maxSubagentDepth}) reached. Cannot spawn further subagents.`
2467
- );
2468
- }
2469
- const threadName = `[sub:${provider}] ${label}`.slice(0, 100);
2470
- const thread = await sessionChannel.threads.create({
2471
- name: threadName,
2472
- type: ChannelType.PublicThread,
2473
- autoArchiveDuration: ThreadAutoArchiveDuration.OneHour,
2474
- reason: `Subagent spawned by session ${parentSession.id}`
2475
- });
2476
- const session = await createSession({
2477
- channelId: thread.id,
2478
- // Subagent's primary ID is the Thread
2479
- categoryId: parentSession.categoryId,
2480
- projectName: parentSession.projectName,
2481
- agentLabel: label,
2482
- provider,
2483
- directory: parentSession.directory,
2484
- type: "subagent",
2485
- parentChannelId: parentSession.channelId,
2486
- // Parent session's TextChannel
2487
- subagentDepth: parentSession.subagentDepth + 1,
2488
- mode: parentSession.mode,
2489
- claudePermissionMode: provider === "claude" ? parentSession.claudePermissionMode : void 0
2490
- });
2491
- console.log(`[SubagentManager] Spawned subagent "${label}" session ${session.id} thread ${thread.id} (depth ${session.subagentDepth}, parent ${parentSession.id})`);
2492
- return session;
2493
- }
2494
- async function archiveSubagent(session, thread, summary) {
2495
- if (summary) {
2496
- await sendSystemNotice(thread, session.id, `*\u5B50\u4EFB\u52A1\u5B8C\u6210\uFF1A${summary}*`);
2497
- }
2498
- try {
2499
- await thread.setArchived(true, "Subagent task completed");
2500
- } catch (error) {
2501
- console.warn(`[SubagentManager] Failed to archive thread ${thread.id} for subagent ${session.id}: ${error instanceof Error ? error.message : String(error)}`);
2502
- }
2503
- try {
2504
- await endSession(session.id);
2505
- console.log(`[SubagentManager] Archived subagent ${session.id} thread ${thread.id}${summary ? ` \u2014 ${summary}` : ""}`);
2506
- } catch (error) {
2507
- console.warn(`[SubagentManager] Failed to end session for subagent ${session.id}: ${error instanceof Error ? error.message : String(error)}`);
2508
- }
2509
- }
2510
- function getSubagents(parentSession) {
2511
- return getAllSessions().filter(
2512
- (s) => s.type === "subagent" && s.parentChannelId === parentSession.channelId
2513
- );
2514
- }
2515
- async function runSubagentWatchdog(getThread) {
2516
- const now = Date.now();
2517
- const checked = /* @__PURE__ */ new Set();
2518
- let archived = 0;
2519
- let errors = 0;
2520
- for (const session of getSubagentSessions()) {
2521
- if (checked.has(session.id)) continue;
2522
- checked.add(session.id);
2523
- const idle = now - session.lastActivity;
2524
- if (idle < SUBAGENT_IDLE_TIMEOUT_MS) continue;
2525
- if (session.isGenerating) continue;
2526
- const thread = getThread(session.channelId);
2527
- if (!thread) {
2528
- await endSession(session.id).catch((e) => console.warn(`[SubagentWatchdog] Failed to end orphaned subagent ${session.id}: ${e.message}`));
2529
- console.log(`[SubagentWatchdog] Ended orphaned subagent ${session.id} \u2014 thread ${session.channelId} not found`);
2530
- continue;
2531
- }
2532
- try {
2533
- await archiveSubagent(session, thread, "Idle timeout reached.");
2534
- archived += 1;
2535
- } catch (error) {
2536
- console.error(`[SubagentWatchdog] Failed to archive idle subagent ${session.id}: ${error instanceof Error ? error.message : String(error)}`);
2537
- errors += 1;
2538
- }
2539
- }
2540
- console.log(`[SubagentWatchdog] Watchdog run: checked ${checked.size} subagents, archived ${archived}, errors ${errors}`);
2541
- }
2542
- async function autoSpawnSubagentThread(parentSession, taskId, description, sessionChannel) {
2543
- if (parentSession.type === "subagent") return null;
2544
- if (!canSpawnSubagent(parentSession)) return null;
2545
- const threadName = `[task] ${description}`.slice(0, 100);
2546
- const thread = await sessionChannel.threads.create({
2547
- name: threadName,
2548
- type: ChannelType.PublicThread,
2549
- autoArchiveDuration: ThreadAutoArchiveDuration.OneHour,
2550
- reason: `Auto-created for task ${taskId} in session ${parentSession.id}`
2551
- });
2552
- let session;
2553
- try {
2554
- session = await createSession({
2555
- channelId: thread.id,
2556
- categoryId: parentSession.categoryId,
2557
- projectName: parentSession.projectName,
2558
- agentLabel: description,
2559
- provider: parentSession.provider,
2560
- directory: parentSession.directory,
2561
- type: "subagent",
2562
- parentChannelId: parentSession.channelId,
2563
- subagentDepth: (parentSession.subagentDepth || 0) + 1,
2564
- mode: parentSession.mode,
2565
- claudePermissionMode: parentSession.provider === "claude" ? parentSession.claudePermissionMode : void 0
2566
- });
2567
- } catch (err) {
2568
- console.warn(`[SubagentManager] createSession failed for auto-spawned task ${taskId}, deleting orphan thread ${thread.id}: ${err instanceof Error ? err.message : String(err)}`);
2569
- await thread.delete("Session creation failed").catch(
2570
- (deleteErr) => console.warn(`[SubagentManager] Failed to delete orphan thread ${thread.id}: ${deleteErr instanceof Error ? deleteErr.message : String(deleteErr)}`)
2571
- );
2572
- throw err;
2573
- }
2574
- console.log(`[SubagentManager] Auto-spawned thread for task ${taskId} session ${session.id} thread ${thread.id}`);
2575
- return { threadId: thread.id, session };
2576
- }
2577
- function getSubagentSessions() {
2578
- return getAllSessions().filter((s) => s.type === "subagent");
2579
- }
2580
-
2581
- // ../bot/src/codex-renderer.ts
2582
- import { EmbedBuilder } from "discord.js";
2583
-
2584
- // ../bot/src/output/interaction-controls.ts
2585
- import {
2586
- ActionRowBuilder,
2587
- ButtonBuilder,
2588
- ButtonStyle,
2589
- StringSelectMenuBuilder,
2590
- EmbedBuilder as EmbedBuilder2
2591
- } from "discord.js";
2592
- function resolveEffectiveClaudePermissionMode2(currentMode, claudePermissionMode) {
2593
- if (!claudePermissionMode) return void 0;
2594
- return currentMode === "auto" ? "bypass" : claudePermissionMode;
2595
- }
2596
- function makeModeButtons(sessionId, currentMode, claudePermissionMode) {
2597
- const modes = [
2598
- { id: "auto", label: "\u26A1 \u81EA\u52A8\u6A21\u5F0F" },
2599
- { id: "plan", label: "\u{1F4CB} \u8BA1\u5212\u6A21\u5F0F" },
2600
- { id: "normal", label: "\u{1F6E1}\uFE0F \u666E\u901A\u6A21\u5F0F" },
2601
- { id: "monitor", label: "\u{1F9E0} \u76D1\u63A7\u6A21\u5F0F" }
2602
- ];
2603
- const row = new ActionRowBuilder();
2604
- for (const m of modes) {
2605
- row.addComponents(
2606
- new ButtonBuilder().setCustomId(`mode:${sessionId}:${m.id}`).setLabel(m.id === currentMode ? `\u2713 ${m.label}` : m.label).setStyle(m.id === currentMode ? ButtonStyle.Success : ButtonStyle.Secondary).setDisabled(false)
2607
- );
2608
- }
2609
- const effectiveClaudePermissionMode = resolveEffectiveClaudePermissionMode2(
2610
- currentMode,
2611
- claudePermissionMode
2612
- );
2613
- if (effectiveClaudePermissionMode) {
2614
- const permLabel = effectiveClaudePermissionMode === "bypass" ? "\u26A1 \u7ED5\u8FC7\u6743\u9650" : "\u{1F6E1}\uFE0F \u9700\u8981\u786E\u8BA4";
2615
- row.addComponents(
2616
- new ButtonBuilder().setCustomId(`perm-info:${sessionId}`).setLabel(permLabel).setStyle(
2617
- effectiveClaudePermissionMode === "bypass" ? ButtonStyle.Danger : ButtonStyle.Success
2618
- ).setDisabled(true)
2619
- );
2620
- }
2621
- return row;
2622
- }
2623
- function shouldSuppressCommandExecution(command) {
2624
- return command.toLowerCase().includes("total-recall");
2625
- }
2626
-
2627
- // ../bot/src/output/event-handlers.ts
2628
- function providerSource(sessionId) {
2629
- const session = getSessionView(sessionId);
2630
- return session?.provider === "codex" ? "codex" : "claude";
2631
- }
2632
- var textDelta = (event, ctx) => {
2633
- ctx.streamer.append(event.text);
2634
- };
2635
- var askUser = async (event, ctx) => {
2636
- ctx.state.askedUser = true;
2637
- ctx.state.askUserQuestionsJson = event.questionsJson;
2638
- await ctx.streamer.discard();
2639
- const session = getSessionView(ctx.sessionId);
2640
- if (!session) return;
2641
- const source = providerSource(ctx.sessionId);
2642
- await updateSessionState(ctx.sessionId, {
2643
- type: "awaiting_human",
2644
- sessionId: ctx.sessionId,
2645
- source,
2646
- confidence: "high",
2647
- timestamp: Date.now(),
2648
- metadata: { detail: event.questionsJson }
2649
- });
2650
- await flushDigest(ctx.sessionId);
2651
- await handleAwaitingHuman(ctx.sessionId, event.questionsJson, { source });
2652
- };
2653
- var task = async (event, ctx) => {
2654
- await ctx.streamer.finalize();
2655
- queueDigest(ctx.sessionId, { kind: "tool", text: `\u4EFB\u52A1\u5DE5\u5177\uFF1A${event.action}` });
2656
- ctx.state.lastToolName = event.action;
2657
- };
2658
- var taskStarted = async (event, ctx) => {
2659
- await ctx.streamer.finalize();
2660
- queueDigest(ctx.sessionId, {
2661
- kind: "subagent",
2662
- text: `\u5B50\u4EE3\u7406\u542F\u52A8\uFF1A${truncate(event.description, 80)}`
2663
- });
2664
- const session = getSessionView(ctx.sessionId);
2665
- if (!session || ctx.channel.type === void 0) return;
2666
- autoSpawnSubagentThread(session, event.taskId, event.description, ctx.channel).then((result2) => {
2667
- if (result2) ctx.state.taskThreadMap.set(event.taskId, result2.threadId);
2668
- }).catch(
2669
- (err) => console.warn(
2670
- `[OutputHandler] Failed to auto-spawn thread for task ${event.taskId}: ${err.message}`
2671
- )
2672
- );
2673
- };
2674
- var taskProgress = (event, ctx) => {
2675
- if (event.summary) {
2676
- queueDigest(ctx.sessionId, {
2677
- kind: "subagent",
2678
- text: `\u5B50\u4EE3\u7406\u8FDB\u5C55\uFF1A${truncate(event.summary, 100)}`
2679
- });
2680
- }
2681
- const threadId = ctx.state.taskThreadMap.get(event.taskId);
2682
- if (!threadId || !event.summary) return;
2683
- const thread = ctx.channel.threads?.cache.get(threadId);
2684
- if (!thread) return;
2685
- thread.send(`\u{1F4DD} ${truncate(event.summary, 1900)}`).catch(
2686
- (e) => console.warn(
2687
- `[OutputHandler] Failed to send progress to thread: ${e.message}`
2688
- )
2689
- );
2690
- };
2691
- var taskDone = async (event, ctx) => {
2692
- await ctx.streamer.finalize();
2693
- queueDigest(ctx.sessionId, {
2694
- kind: "subagent",
2695
- text: `\u5B50\u4EE3\u7406${event.status === "completed" ? "\u5B8C\u6210" : "\u7ED3\u675F"}\uFF1A${truncate(event.summary || "No summary.", 100)}`
2696
- });
2697
- const threadId = ctx.state.taskThreadMap.get(event.taskId);
2698
- if (!threadId) return;
2699
- const thread = ctx.channel.threads?.cache.get(threadId);
2700
- if (thread) {
2701
- const emoji = event.status === "completed" ? "\u2705" : "\u274C";
2702
- thread.send(`${emoji} \u5B50\u4EFB\u52A1${event.status === "completed" ? "\u5B8C\u6210" : "\u7ED3\u675F"}\uFF1A${truncate(event.summary || "", 1900)}`).catch(
2703
- (e) => console.warn(
2704
- `[OutputHandler] Failed to send task done to thread: ${e.message}`
2705
- )
2706
- );
2707
- }
2708
- ctx.state.taskThreadMap.delete(event.taskId);
2709
- };
2710
- var webSearch = (event, ctx) => {
2711
- if (ctx.verbose) {
2712
- queueDigest(ctx.sessionId, { kind: "search", text: `\u68C0\u7D22\uFF1A${truncate(event.query, 80)}` });
2713
- }
2714
- };
2715
- var toolStart = async (event, ctx) => {
2716
- await ctx.streamer.finalize();
2717
- queueDigest(ctx.sessionId, { kind: "tool", text: `\u5DE5\u5177\uFF1A${event.toolName}` });
2718
- ctx.state.lastToolName = event.toolName;
2719
- };
2720
- var toolResult = async (event, ctx) => {
2721
- await ctx.streamer.finalize();
2722
- if (ctx.verbose && event.result) {
2723
- queueDigest(ctx.sessionId, {
2724
- kind: "tool",
2725
- text: `\u5DE5\u5177\u7ED3\u679C\uFF1A${truncate(ctx.state.lastToolName || event.toolName || "tool", 60)}`
2726
- });
2727
- }
2728
- };
2729
- var imageFile = (event, ctx) => {
2730
- if (existsSync(event.filePath)) {
2731
- ctx.state.pendingAttachments.push(event.filePath);
2732
- }
2733
- };
2734
- var commandExecution = (event, ctx) => {
2735
- ctx.state.commandCount++;
2736
- if (ctx.state.recentCommands.length < 8) ctx.state.recentCommands.push(event.command);
2737
- if (!shouldSuppressCommandExecution(event.command)) {
2738
- queueDigest(ctx.sessionId, {
2739
- kind: "command",
2740
- text: `\u547D\u4EE4\uFF1A${truncate(event.command, 80)}${event.exitCode !== null ? `\uFF08\u9000\u51FA\u7801 ${event.exitCode}\uFF09` : ""}`
2741
- });
2742
- }
2743
- };
2744
- var fileChange = (event, ctx) => {
2745
- ctx.state.fileChangeCount += event.changes.length;
2746
- for (const change of event.changes) {
2747
- if (!change.filePath) continue;
2748
- if (ctx.state.changedFiles.includes(change.filePath)) continue;
2749
- if (ctx.state.changedFiles.length >= 12) break;
2750
- ctx.state.changedFiles.push(change.filePath);
2751
- }
2752
- queueDigest(ctx.sessionId, {
2753
- kind: "file",
2754
- text: `\u6587\u4EF6\u53D8\u66F4\uFF1A${event.changes.length} \u4E2A\uFF08\u6700\u8FD1\uFF1A${truncate(ctx.state.changedFiles.slice(-3).join(", "), 120)}\uFF09`
2755
- });
2756
- };
2757
- var reasoning = (event, ctx) => {
2758
- if (ctx.verbose) {
2759
- queueDigest(ctx.sessionId, { kind: "reasoning", text: `\u63A8\u7406\uFF1A${truncate(event.text, 100)}` });
2760
- }
2761
- };
2762
- var todoList = (event, ctx) => {
2763
- const completed = event.items.filter((item) => item.completed).length;
2764
- queueDigest(ctx.sessionId, {
2765
- kind: "todo",
2766
- text: `\u5F85\u529E\u66F4\u65B0\uFF1A${completed}/${event.items.length} \u5DF2\u5B8C\u6210`
2767
- });
2768
- };
2769
- var MODE_LABELS = {
2770
- auto: "\u81EA\u52A8",
2771
- plan: "\u8BA1\u5212",
2772
- normal: "\u666E\u901A",
2773
- monitor: "\u76D1\u63A7"
2774
- };
2775
- var result = async (event, ctx) => {
2776
- ctx.state.success = event.success;
2777
- const lastText = ctx.streamer.getText();
2778
- const cost = event.costUsd.toFixed(4);
2779
- const duration = event.durationMs ? `${(event.durationMs / 1e3).toFixed(1)}s` : "unknown";
2780
- const turns = event.numTurns || 0;
2781
- const modeLabel = MODE_LABELS[ctx.mode] || "\u81EA\u52A8";
2782
- const statusLine = event.success ? `-# $${cost} | ${duration} | ${turns} turns | ${modeLabel}` : `-# Error | $${cost} | ${duration} | ${turns} turns`;
2783
- ctx.streamer.append(`
2784
- ${statusLine}`, { persist: false });
2785
- if (!event.success && event.errors.length) {
2786
- ctx.streamer.append(`
2787
- \`\`\`
2788
- ${event.errors.join("\n")}
2789
- \`\`\``, { persist: false });
2790
- }
2791
- await ctx.streamer.finalize();
2792
- const session = getSessionView(ctx.sessionId);
2793
- if (!session) {
2794
- ctx.state.pendingAttachments = [];
2795
- return;
2796
- }
2797
- if (ctx.mode === "monitor") {
2798
- await flushDigest(ctx.sessionId);
2799
- await updateSessionState(ctx.sessionId, {
2800
- type: "work_started",
2801
- sessionId: ctx.sessionId,
2802
- source: providerSource(ctx.sessionId),
2803
- confidence: "high",
2804
- timestamp: Date.now(),
2805
- metadata: {
2806
- phase: "\u7B49\u5F85\u76D1\u7763\u5224\u65AD",
2807
- summary: event.success ? "\u672C\u8F6E\u6267\u884C\u7ED3\u675F\uFF0C\u7B49\u5F85\u76D1\u7763\u5224\u65AD" : "\u672C\u8F6E\u6267\u884C\u5931\u8D25\uFF0C\u7B49\u5F85\u76D1\u7763\u5224\u65AD"
2808
- }
2809
- });
2810
- } else {
2811
- ctx.state.deferredResult = {
2812
- event,
2813
- text: lastText,
2814
- attachments: [...ctx.state.pendingAttachments]
2815
- };
2816
- }
2817
- ctx.state.pendingAttachments = [];
2818
- };
2819
- var errorEvent = async (event, ctx) => {
2820
- console.warn(`[OutputHandler] Session ${ctx.sessionId}: error event \u2014 ${event.message}`);
2821
- ctx.state.hadError = true;
2822
- await ctx.streamer.finalize();
2823
- queueDigest(ctx.sessionId, { kind: "error", text: `\u9519\u8BEF\uFF1A${truncate(event.message, 120)}` });
2824
- if (ctx.mode === "monitor") return;
2825
- const session = getSessionView(ctx.sessionId);
2826
- if (!session) return;
2827
- await flushDigest(ctx.sessionId);
2828
- await updateSessionState(ctx.sessionId, {
2829
- type: "errored",
2830
- sessionId: ctx.sessionId,
2831
- source: providerSource(ctx.sessionId),
2832
- confidence: "high",
2833
- timestamp: Date.now(),
2834
- metadata: { errorMessage: event.message }
2835
- });
2836
- };
2837
- var sessionInit = () => {
2838
- };
2839
- var EVENT_HANDLERS = {
2840
- text_delta: textDelta,
2841
- ask_user: askUser,
2842
- task,
2843
- task_started: taskStarted,
2844
- task_progress: taskProgress,
2845
- task_done: taskDone,
2846
- web_search: webSearch,
2847
- tool_start: toolStart,
2848
- tool_result: toolResult,
2849
- image_file: imageFile,
2850
- command_execution: commandExecution,
2851
- file_change: fileChange,
2852
- reasoning,
2853
- todo_list: todoList,
2854
- result,
2855
- error: errorEvent,
2856
- session_init: sessionInit
2857
- };
2858
- async function dispatchEvent(event, ctx) {
2859
- const handler = EVENT_HANDLERS[event.type];
2860
- if (!handler) return;
2861
- await handler(event, ctx);
2862
- }
2863
-
2864
2556
  // ../bot/src/output-handler.ts
2865
2557
  var DIGEST_FLUSH_INTERVAL_MS = 8e3;
2866
2558
  function createInitialState() {
@@ -3135,7 +2827,7 @@ function buildProjectCleanupPreview(input) {
3135
2827
  return preview;
3136
2828
  }
3137
2829
  async function archiveSessionsById(guild, sessionIds, summary = "Bulk cleanup from Discord command") {
3138
- const result2 = {
2830
+ const result = {
3139
2831
  archivedSessions: 0,
3140
2832
  skippedGenerating: 0,
3141
2833
  missingSessions: 0,
@@ -3144,27 +2836,27 @@ async function archiveSessionsById(guild, sessionIds, summary = "Bulk cleanup fr
3144
2836
  for (const sessionId of new Set(Array.from(sessionIds).filter(Boolean))) {
3145
2837
  const session = getSessionView(sessionId);
3146
2838
  if (!session || session.type !== "persistent") {
3147
- result2.missingSessions += 1;
2839
+ result.missingSessions += 1;
3148
2840
  continue;
3149
2841
  }
3150
2842
  if (session.isGenerating) {
3151
- result2.skippedGenerating += 1;
2843
+ result.skippedGenerating += 1;
3152
2844
  continue;
3153
2845
  }
3154
2846
  try {
3155
2847
  await archiveSession(session, guild, summary);
3156
- result2.archivedSessions += 1;
2848
+ result.archivedSessions += 1;
3157
2849
  } catch (error) {
3158
2850
  console.error(`[Housekeeping] Failed to archive session ${sessionId}: ${error instanceof Error ? error.message : String(error)}`);
3159
- result2.failed.push({
2851
+ result.failed.push({
3160
2852
  sessionId: session.id,
3161
2853
  channelId: session.channelId,
3162
2854
  message: error instanceof Error ? error.message : String(error)
3163
2855
  });
3164
2856
  }
3165
2857
  }
3166
- console.log(`[Housekeeping] Archive result: ${result2.archivedSessions} archived, ${result2.skippedGenerating} skipped, ${result2.missingSessions} missing, ${result2.failed.length} failed`);
3167
- return result2;
2858
+ console.log(`[Housekeeping] Archive result: ${result.archivedSessions} archived, ${result.skippedGenerating} skipped, ${result.missingSessions} missing, ${result.failed.length} failed`);
2859
+ return result;
3168
2860
  }
3169
2861
  async function reconcileSessionRecordsWithGuild(guild) {
3170
2862
  const sessions = getAllSessions();
@@ -3184,10 +2876,10 @@ async function reconcileSessionRecordsWithGuild(guild) {
3184
2876
  }
3185
2877
 
3186
2878
  // ../bot/src/session-sync.ts
3187
- import { ChannelType as ChannelType2 } from "discord.js";
2879
+ import { ChannelType } from "discord.js";
3188
2880
 
3189
2881
  // ../bot/src/codex-session-discovery.ts
3190
- import { existsSync as existsSync2 } from "fs";
2882
+ import { existsSync } from "fs";
3191
2883
  import { readFile, open } from "fs/promises";
3192
2884
  import { glob } from "fs/promises";
3193
2885
  import { join, resolve, sep } from "path";
@@ -3216,7 +2908,7 @@ function parseUpdatedAt(value) {
3216
2908
  }
3217
2909
  async function readSessionIndex(codexHome = join(homedir(), ".codex")) {
3218
2910
  const indexPath = join(codexHome, "session_index.jsonl");
3219
- if (!existsSync2(indexPath)) return [];
2911
+ if (!existsSync(indexPath)) return [];
3220
2912
  let content;
3221
2913
  try {
3222
2914
  content = await readFile(indexPath, "utf-8");
@@ -3286,7 +2978,7 @@ async function fileMatchesSessionId(file, id) {
3286
2978
  }
3287
2979
  async function findSessionFileById(id, codexHome = join(homedir(), ".codex")) {
3288
2980
  const sessionsDir = join(codexHome, "sessions");
3289
- if (!existsSync2(sessionsDir)) return null;
2981
+ if (!existsSync(sessionsDir)) return null;
3290
2982
  if (await isRipgrepAvailable()) {
3291
2983
  try {
3292
2984
  const { stdout } = await execFileAsync(
@@ -3460,12 +3152,12 @@ function stopSync() {
3460
3152
  }
3461
3153
  async function findOrCreateSessionChannel(guild, category, provider, providerSessionId, fallbackName) {
3462
3154
  const existing = category.children.cache.find(
3463
- (channel) => channel.type === ChannelType2.GuildText && typeof channel.topic === "string" && channel.topic.includes(`Provider Session: ${providerSessionId}`)
3155
+ (channel) => channel.type === ChannelType.GuildText && typeof channel.topic === "string" && channel.topic.includes(`Provider Session: ${providerSessionId}`)
3464
3156
  );
3465
3157
  if (existing) return existing;
3466
3158
  return guild.channels.create({
3467
3159
  name: fallbackName,
3468
- type: ChannelType2.GuildText,
3160
+ type: ChannelType.GuildText,
3469
3161
  parent: category.id,
3470
3162
  topic: `${provider} session (synced) | Provider Session: ${providerSessionId}`
3471
3163
  }).then((channel) => {
@@ -3516,11 +3208,11 @@ async function runSync(client2) {
3516
3208
  );
3517
3209
  let createdThisRun = 0;
3518
3210
  try {
3519
- const claudeSdk = await import("./sdk-V7A7IF7F.js");
3211
+ const claudeSdk = await import("./sdk-C3D6X4EB.js");
3520
3212
  for (const project of projects) {
3521
3213
  if (createdThisRun >= MAX_SESSIONS_PER_SYNC) break;
3522
3214
  const category = guild.channels.cache.get(project.discordCategoryId);
3523
- if (!category || category.type !== ChannelType2.GuildCategory) {
3215
+ if (!category || category.type !== ChannelType.GuildCategory) {
3524
3216
  recordSkip("categoryMissing");
3525
3217
  continue;
3526
3218
  }
@@ -3611,7 +3303,7 @@ async function runSync(client2) {
3611
3303
  continue;
3612
3304
  }
3613
3305
  const category = guild.channels.cache.get(project.discordCategoryId);
3614
- if (!category || category.type !== ChannelType2.GuildCategory) {
3306
+ if (!category || category.type !== ChannelType.GuildCategory) {
3615
3307
  recordSkip("categoryMissing");
3616
3308
  continue;
3617
3309
  }
@@ -4002,7 +3694,7 @@ async function handleCodexMonitorStateChange(resolveChannel2, monitorSessionId,
4002
3694
 
4003
3695
  // ../bot/src/ipc-server.ts
4004
3696
  import { createServer } from "net";
4005
- import { unlinkSync, existsSync as existsSync3, chmodSync } from "fs";
3697
+ import { unlinkSync, existsSync as existsSync2, chmodSync } from "fs";
4006
3698
 
4007
3699
  // ../bot/src/session-discovery.ts
4008
3700
  async function discoverAndRegisterSession(client2, params) {
@@ -4011,7 +3703,7 @@ async function discoverAndRegisterSession(client2, params) {
4011
3703
  console.warn("[Session Discovery] No guild found, cannot register local session");
4012
3704
  return null;
4013
3705
  }
4014
- const result2 = await registerLocalSession(
3706
+ const result = await registerLocalSession(
4015
3707
  {
4016
3708
  provider: params.provider,
4017
3709
  providerSessionId: params.providerSessionId,
@@ -4023,11 +3715,11 @@ async function discoverAndRegisterSession(client2, params) {
4023
3715
  },
4024
3716
  guild
4025
3717
  );
4026
- if (!result2) return null;
3718
+ if (!result) return null;
4027
3719
  return {
4028
- sessionId: result2.session.id,
4029
- channelId: result2.session.channelId,
4030
- isNew: result2.isNewlyCreated
3720
+ sessionId: result.session.id,
3721
+ channelId: result.session.channelId,
3722
+ isNew: result.isNewlyCreated
4031
3723
  };
4032
3724
  }
4033
3725
 
@@ -4049,7 +3741,7 @@ function startIpcServer(client2) {
4049
3741
  discordClient = client2;
4050
3742
  const socketPath = config.socketPath;
4051
3743
  activeSocketPath = socketPath;
4052
- if (existsSync3(socketPath)) {
3744
+ if (existsSync2(socketPath)) {
4053
3745
  try {
4054
3746
  unlinkSync(socketPath);
4055
3747
  } catch {
@@ -4112,7 +3804,7 @@ function stopIpcServer() {
4112
3804
  server.close();
4113
3805
  server = null;
4114
3806
  }
4115
- if (activeSocketPath && existsSync3(activeSocketPath)) {
3807
+ if (activeSocketPath && existsSync2(activeSocketPath)) {
4116
3808
  try {
4117
3809
  unlinkSync(activeSocketPath);
4118
3810
  } catch {
@@ -4187,9 +3879,9 @@ async function handleHookEvent(payload) {
4187
3879
  async function handleGateResolved(payload) {
4188
3880
  const data = payload;
4189
3881
  console.log(`[IpcServer] Terminal resolved gate ${data.gateId}: ${data.action}`);
4190
- const result2 = gateService.notifyTerminalResolved(data.gateId, data.action);
4191
- if (!result2.success) {
4192
- console.warn(`[IpcServer] Gate resolution failed: ${result2.message}`);
3882
+ const result = gateService.notifyTerminalResolved(data.gateId, data.action);
3883
+ if (!result.success) {
3884
+ console.warn(`[IpcServer] Gate resolution failed: ${result.message}`);
4193
3885
  return;
4194
3886
  }
4195
3887
  const gate = gateService.getGate(data.gateId);
@@ -4491,7 +4183,7 @@ function stopHealthMonitor() {
4491
4183
 
4492
4184
  // ../bot/src/message-handler.ts
4493
4185
  import {
4494
- ChannelType as ChannelType3
4186
+ ChannelType as ChannelType2
4495
4187
  } from "discord.js";
4496
4188
 
4497
4189
  // ../bot/src/discord/inbound-envelope.ts
@@ -4558,7 +4250,7 @@ function stopMessageHandler() {
4558
4250
  async function handleMessage(message) {
4559
4251
  if (message.author.bot) return;
4560
4252
  const channel = message.channel;
4561
- const isSessionChannel3 = channel.type === ChannelType3.GuildText;
4253
+ const isSessionChannel3 = channel.type === ChannelType2.GuildText;
4562
4254
  const isSubagentThread = channel.isThread();
4563
4255
  if (!isSessionChannel3 && !isSubagentThread) return;
4564
4256
  const session = getSessionByChannel(channel.id);
@@ -4647,7 +4339,7 @@ async function handleMessage(message) {
4647
4339
  // ../bot/src/commands.ts
4648
4340
  import { REST, Routes } from "discord.js";
4649
4341
  import { createHash } from "crypto";
4650
- import { existsSync as existsSync4, readFileSync as readFileSync2, writeFileSync } from "fs";
4342
+ import { existsSync as existsSync3, readFileSync as readFileSync2, writeFileSync } from "fs";
4651
4343
  import { join as join3 } from "path";
4652
4344
 
4653
4345
  // ../bot/src/command-definitions/project-command.ts
@@ -4774,7 +4466,16 @@ function buildAgentCommand() {
4774
4466
  { name: "\u5F00\u542F", value: "on" }
4775
4467
  )
4776
4468
  )
4777
- ).addSubcommand((sub) => sub.setName("continue").setDescription("\u7EE7\u7EED\u5F53\u524D\u4F1A\u8BDD\u7684\u751F\u6210"));
4469
+ ).addSubcommand((sub) => sub.setName("continue").setDescription("\u7EE7\u7EED\u5F53\u524D\u4F1A\u8BDD\u7684\u751F\u6210")).addSubcommand(
4470
+ (sub) => sub.setName("batch").setDescription("\u6279\u91CF\u5BA1\u6279\u6A21\u5F0F\uFF08\u5EF6\u540E\u6240\u6709\u5DE5\u5177\u5BA1\u6279\u81F3\u4E00\u6B21\u6027\u5904\u7406\uFF09").addStringOption(
4471
+ (opt) => opt.setName("action").setDescription("\u5F00\u5173 / \u4E00\u952E\u6279\u51C6 / \u4E00\u952E\u62D2\u7EDD").setRequired(true).addChoices(
4472
+ { name: "\u5F00\u542F\u6279\u91CF\u5BA1\u6279\u6A21\u5F0F", value: "on" },
4473
+ { name: "\u5173\u95ED\u6279\u91CF\u5BA1\u6279\u6A21\u5F0F", value: "off" },
4474
+ { name: "\u6279\u51C6\u961F\u5217\u4E2D\u7684\u5168\u90E8\u5DE5\u5177\u8C03\u7528", value: "approve-all" },
4475
+ { name: "\u62D2\u7EDD\u961F\u5217\u4E2D\u7684\u5168\u90E8\u5DE5\u5177\u8C03\u7528", value: "reject-all" }
4476
+ )
4477
+ )
4478
+ );
4778
4479
  }
4779
4480
 
4780
4481
  // ../bot/src/command-definitions/subagent-command.ts
@@ -4816,7 +4517,7 @@ function computeCommandsHash(body) {
4816
4517
  }
4817
4518
  function readStoredHash() {
4818
4519
  try {
4819
- if (existsSync4(HASH_FILE)) {
4520
+ if (existsSync3(HASH_FILE)) {
4820
4521
  return readFileSync2(HASH_FILE, "utf-8").trim();
4821
4522
  }
4822
4523
  } catch {
@@ -4851,13 +4552,13 @@ async function registerCommands() {
4851
4552
  // ../bot/src/bot-services-orchestrator.ts
4852
4553
  async function findOrCreateLogChannel(guild) {
4853
4554
  const existing = guild.channels.cache.find(
4854
- (ch) => ch.name === "bot-logs" && ch.type === ChannelType4.GuildText && !ch.parentId
4555
+ (ch) => ch.name === "bot-logs" && ch.type === ChannelType3.GuildText && !ch.parentId
4855
4556
  );
4856
4557
  if (existing) return existing;
4857
4558
  try {
4858
4559
  return await guild.channels.create({
4859
4560
  name: "bot-logs",
4860
- type: ChannelType4.GuildText,
4561
+ type: ChannelType3.GuildText,
4861
4562
  reason: "Auto-created by workspacecord for bot logs"
4862
4563
  });
4863
4564
  } catch {
@@ -4900,23 +4601,23 @@ var BotServicesOrchestrator = class {
4900
4601
  * 续跑采用 fire-and-forget:每个 session 独立异步运行,不阻塞启动。
4901
4602
  */
4902
4603
  async #resumeAbandonedMonitorRuns(client2, logBuffer2) {
4903
- let result2;
4604
+ let result;
4904
4605
  try {
4905
- result2 = await reconcileAndCollectAutoResumeCandidates(config.monitorAutoResumePolicy);
4606
+ result = await reconcileAndCollectAutoResumeCandidates(config.monitorAutoResumePolicy);
4906
4607
  } catch (err) {
4907
4608
  console.error("[MonitorAutoResume] reconcile failed:", err);
4908
4609
  return;
4909
4610
  }
4910
- if (result2.abandoned.length > 0) {
4611
+ if (result.abandoned.length > 0) {
4911
4612
  logBuffer2.log(
4912
- `Marked ${result2.abandoned.length} orphan monitor run(s) as abandoned on startup.`
4613
+ `Marked ${result.abandoned.length} orphan monitor run(s) as abandoned on startup.`
4913
4614
  );
4914
4615
  }
4915
- if (result2.candidates.length === 0) return;
4616
+ if (result.candidates.length === 0) return;
4916
4617
  logBuffer2.log(
4917
- `Auto-resuming ${result2.candidates.length} monitor session(s) (policy=${config.monitorAutoResumePolicy}).`
4618
+ `Auto-resuming ${result.candidates.length} monitor session(s) (policy=${config.monitorAutoResumePolicy}).`
4918
4619
  );
4919
- for (const candidate of result2.candidates) {
4620
+ for (const candidate of result.candidates) {
4920
4621
  const session = getSessionView(candidate.sessionId);
4921
4622
  if (!session) continue;
4922
4623
  const channel = client2.channels.cache.get(candidate.channelId);
@@ -4938,8 +4639,8 @@ var BotServicesOrchestrator = class {
4938
4639
  }
4939
4640
  }
4940
4641
  async #reconcilePendingGates(client2, logBuffer2) {
4941
- const result2 = gateService.reconcileOnStartup(config.gateRestartPolicy);
4942
- for (const { gateId, discordMessageId } of result2.invalidated) {
4642
+ const result = gateService.reconcileOnStartup(config.gateRestartPolicy);
4643
+ for (const { gateId, discordMessageId } of result.invalidated) {
4943
4644
  if (!discordMessageId) continue;
4944
4645
  const gate = gateService.getGate(gateId);
4945
4646
  if (!gate?.sessionId) continue;
@@ -4963,13 +4664,13 @@ var BotServicesOrchestrator = class {
4963
4664
  console.error(`[GateReconcile] Failed to update message for gate ${gateId}:`, err);
4964
4665
  }
4965
4666
  }
4966
- if (result2.resumed.length > 0) {
4667
+ if (result.resumed.length > 0) {
4967
4668
  logBuffer2.log(
4968
- `Resumed ${result2.resumed.length} pending gate(s) across restart (policy=resume-pending).`
4669
+ `Resumed ${result.resumed.length} pending gate(s) across restart (policy=resume-pending).`
4969
4670
  );
4970
4671
  }
4971
- if (result2.invalidated.length > 0) {
4972
- logBuffer2.log(`Closed ${result2.invalidated.length} orphan/overdue gate(s) on startup.`);
4672
+ if (result.invalidated.length > 0) {
4673
+ logBuffer2.log(`Closed ${result.invalidated.length} orphan/overdue gate(s) on startup.`);
4973
4674
  }
4974
4675
  }
4975
4676
  #registerServices(client2, logBuffer2, presence) {
@@ -4995,10 +4696,10 @@ var BotServicesOrchestrator = class {
4995
4696
  );
4996
4697
  },
4997
4698
  async (providerSessionId, cwd, remoteHumanControl, subagent) => {
4998
- const { registerLocalSession: registerLocalSession2 } = await import("./session-local-registration-MISPPGXF.js");
4699
+ const { registerLocalSession: registerLocalSession2 } = await import("./session-local-registration-RL2A3QZB.js");
4999
4700
  const g = client2.guilds.cache.first();
5000
4701
  if (!g) return false;
5001
- const result2 = await registerLocalSession2(
4702
+ const result = await registerLocalSession2(
5002
4703
  {
5003
4704
  provider: "codex",
5004
4705
  providerSessionId,
@@ -5010,10 +4711,10 @@ var BotServicesOrchestrator = class {
5010
4711
  },
5011
4712
  g
5012
4713
  );
5013
- if (result2?.isNewlyCreated && result2.session.remoteHumanControl === false) {
5014
- void notifyUnmanagedCodexHint(client2, result2.session.id, result2.session.channelId);
4714
+ if (result?.isNewlyCreated && result.session.remoteHumanControl === false) {
4715
+ void notifyUnmanagedCodexHint(client2, result.session.id, result.session.channelId);
5015
4716
  }
5016
- return result2 !== null;
4717
+ return result !== null;
5017
4718
  }
5018
4719
  );
5019
4720
  this.#serviceBus.register({
@@ -5071,7 +4772,7 @@ var BotServicesOrchestrator = class {
5071
4772
  };
5072
4773
 
5073
4774
  // ../engine/src/bot-locks.ts
5074
- import { existsSync as existsSync5, readFileSync as readFileSync3, writeFileSync as writeFileSync2, unlinkSync as unlinkSync2 } from "fs";
4775
+ import { existsSync as existsSync4, readFileSync as readFileSync3, writeFileSync as writeFileSync2, unlinkSync as unlinkSync2 } from "fs";
5075
4776
  import { join as join5 } from "path";
5076
4777
  var LOCK_FILE = join5(config.dataDir, "bot.lock");
5077
4778
  var STALE_THRESHOLD_MS = 5 * 60 * 1e3;
@@ -5084,7 +4785,7 @@ function isProcessRunning(pid) {
5084
4785
  }
5085
4786
  }
5086
4787
  function acquireLock() {
5087
- if (!existsSync5(LOCK_FILE)) {
4788
+ if (!existsSync4(LOCK_FILE)) {
5088
4789
  const data2 = { pid: process.pid, startedAt: Date.now() };
5089
4790
  writeFileSync2(LOCK_FILE, JSON.stringify(data2), "utf-8");
5090
4791
  return true;
@@ -5114,7 +4815,7 @@ function acquireLock() {
5114
4815
  }
5115
4816
  function releaseLock() {
5116
4817
  try {
5117
- if (!existsSync5(LOCK_FILE)) return;
4818
+ if (!existsSync4(LOCK_FILE)) return;
5118
4819
  const raw = readFileSync3(LOCK_FILE, "utf-8").trim();
5119
4820
  const data = JSON.parse(raw);
5120
4821
  if (data.pid === process.pid) {
@@ -5126,13 +4827,13 @@ function releaseLock() {
5126
4827
 
5127
4828
  // ../bot/src/command-handlers-modules/project-handlers.ts
5128
4829
  import {
5129
- ChannelType as ChannelType6,
5130
- EmbedBuilder as EmbedBuilder3
4830
+ ChannelType as ChannelType5,
4831
+ EmbedBuilder
5131
4832
  } from "discord.js";
5132
4833
 
5133
4834
  // ../bot/src/command-handlers-shared.ts
5134
4835
  import {
5135
- ChannelType as ChannelType5
4836
+ ChannelType as ChannelType4
5136
4837
  } from "discord.js";
5137
4838
  var logFn = console.log;
5138
4839
  function setLogger(fn) {
@@ -5149,7 +4850,7 @@ var PROVIDER_COLORS = {
5149
4850
  claude: 3447003,
5150
4851
  codex: 1090431
5151
4852
  };
5152
- var MODE_LABELS2 = {
4853
+ var MODE_LABELS = {
5153
4854
  auto: "\u26A1 \u81EA\u52A8\u6A21\u5F0F \u2014 \u5B8C\u5168\u81EA\u4E3B",
5154
4855
  plan: "\u{1F4CB} \u8BA1\u5212\u6A21\u5F0F \u2014 \u53D8\u66F4\u524D\u5148\u89C4\u5212",
5155
4856
  normal: "\u{1F6E1}\uFE0F \u666E\u901A\u6A21\u5F0F \u2014 \u7834\u574F\u6027\u64CD\u4F5C\u524D\u786E\u8BA4",
@@ -5159,7 +4860,7 @@ var CONTROL_CHANNEL_NAME = "control";
5159
4860
  var CLEANUP_PREVIEW_LIST_LIMIT = 10;
5160
4861
  var CLEANUP_PREVIEW_LABEL_LIMIT = 120;
5161
4862
  async function registerStatusCardWithPanelAdapter(sessionId, channel, statusCardMessageId) {
5162
- const { registerExistingStatusCard: registerExistingStatusCard2 } = await import("./panel-adapter-U75WXDLB.js");
4863
+ const { registerExistingStatusCard: registerExistingStatusCard2 } = await import("./panel-adapter-CLI4WDII.js");
5163
4864
  if (typeof registerExistingStatusCard2 !== "function") {
5164
4865
  log(`[panel-adapter] registerExistingStatusCard \u672A\u66B4\u9732\uFF0Csession=${sessionId}`);
5165
4866
  return false;
@@ -5279,7 +4980,7 @@ function resolveCleanupCurrentChannelId(interaction) {
5279
4980
  }
5280
4981
  function findControlChannel(guild, categoryId) {
5281
4982
  const existing = guild.channels.cache.find(
5282
- (channel) => channel.type === ChannelType5.GuildText && channel.parentId === categoryId && channel.name === CONTROL_CHANNEL_NAME
4983
+ (channel) => channel.type === ChannelType4.GuildText && channel.parentId === categoryId && channel.name === CONTROL_CHANNEL_NAME
5283
4984
  );
5284
4985
  return existing ?? null;
5285
4986
  }
@@ -5287,7 +4988,7 @@ async function resolveOrCreateControlChannel(interaction, guild, categoryId, sto
5287
4988
  const currentChannel = interaction.channel;
5288
4989
  if (storedControlChannelId) {
5289
4990
  const existing = guild.channels.cache.get(storedControlChannelId);
5290
- if (existing?.type === ChannelType5.GuildText) {
4991
+ if (existing?.type === ChannelType4.GuildText) {
5291
4992
  return existing;
5292
4993
  }
5293
4994
  }
@@ -5303,7 +5004,7 @@ async function resolveOrCreateControlChannel(interaction, guild, categoryId, sto
5303
5004
  }
5304
5005
  const created = await guild.channels.create({
5305
5006
  name: CONTROL_CHANNEL_NAME,
5306
- type: ChannelType5.GuildText,
5007
+ type: ChannelType4.GuildText,
5307
5008
  parent: categoryId,
5308
5009
  topic: "Use /agent spawn here to create new agent sessions",
5309
5010
  reason: `Project control channel created for ${interaction.user.tag}`
@@ -5376,7 +5077,7 @@ async function handleProjectSetup(interaction) {
5376
5077
  try {
5377
5078
  const historyForum = await guild.channels.create({
5378
5079
  name: "history",
5379
- type: ChannelType6.GuildForum,
5080
+ type: ChannelType5.GuildForum,
5380
5081
  parent: categoryId,
5381
5082
  topic: "Archived agent sessions for this project",
5382
5083
  reason: "Created by workspacecord for session archiving"
@@ -5394,7 +5095,7 @@ async function handleProjectSetup(interaction) {
5394
5095
  setControlChannelId(categoryId, interaction.channelId);
5395
5096
  const controlInfo = `
5396
5097
  \u2022 \u63A7\u5236\u9891\u9053\uFF1A<#${interaction.channelId}>`;
5397
- const embed = new EmbedBuilder3().setColor(3066993).setTitle(`\u2705 \u9879\u76EE\u5C31\u7EEA\uFF1A${project.name}`).addFields(
5098
+ const embed = new EmbedBuilder().setColor(3066993).setTitle(`\u2705 \u9879\u76EE\u5C31\u7EEA\uFF1A${project.name}`).addFields(
5398
5099
  { name: "\u5206\u7C7B", value: `**${categoryName}**`, inline: true },
5399
5100
  { name: "\u76EE\u5F55", value: `\`${project.directory}\``, inline: true }
5400
5101
  ).setDescription(
@@ -5422,7 +5123,7 @@ async function handleProjectInfo(interaction) {
5422
5123
  }
5423
5124
  const sessions = getSessionsByCategory(categoryId);
5424
5125
  const activeSessions = sessions.filter((s) => s.type === "persistent");
5425
- const embed = new EmbedBuilder3().setColor(3447003).setTitle(`\u{1F4C1} \u9879\u76EE\uFF1A${project.name}`).addFields(
5126
+ const embed = new EmbedBuilder().setColor(3447003).setTitle(`\u{1F4C1} \u9879\u76EE\uFF1A${project.name}`).addFields(
5426
5127
  { name: "\u76EE\u5F55", value: `\`${project.directory}\``, inline: false },
5427
5128
  { name: "\u6D3B\u8DC3\u4F1A\u8BDD", value: `${activeSessions.length}`, inline: true },
5428
5129
  { name: "\u6280\u80FD", value: `${project.skills.length}`, inline: true },
@@ -5599,11 +5300,11 @@ ${lines.join("\n")}`, ephemeral: true });
5599
5300
 
5600
5301
  // ../bot/src/command-handlers-modules/agent-handlers.ts
5601
5302
  import {
5602
- ActionRowBuilder as ActionRowBuilder2,
5603
- ButtonBuilder as ButtonBuilder2,
5604
- ButtonStyle as ButtonStyle2,
5605
- ChannelType as ChannelType7,
5606
- EmbedBuilder as EmbedBuilder4
5303
+ ActionRowBuilder,
5304
+ ButtonBuilder,
5305
+ ButtonStyle,
5306
+ ChannelType as ChannelType6,
5307
+ EmbedBuilder as EmbedBuilder2
5607
5308
  } from "discord.js";
5608
5309
 
5609
5310
  // ../engine/src/agent-cleanup-request-store.ts
@@ -5681,6 +5382,8 @@ async function handleAgent(interaction) {
5681
5382
  return handleAgentPermissions(interaction);
5682
5383
  case "continue":
5683
5384
  return handleAgentContinue(interaction);
5385
+ case "batch":
5386
+ return handleAgentBatch(interaction);
5684
5387
  default:
5685
5388
  await interaction.reply({ content: `\u672A\u77E5\u5B50\u547D\u4EE4\uFF1A${sub}`, ephemeral: true });
5686
5389
  }
@@ -5733,7 +5436,7 @@ async function handleAgentSpawn(interaction) {
5733
5436
  try {
5734
5437
  sessionChannel = await guild.channels.create({
5735
5438
  name: channelName,
5736
- type: ChannelType7.GuildText,
5439
+ type: ChannelType6.GuildText,
5737
5440
  parent: categoryId,
5738
5441
  topic: `[${PROVIDER_LABELS[provider]}] ${label}`,
5739
5442
  reason: `Agent session spawned by ${interaction.user.tag}`
@@ -5764,7 +5467,7 @@ async function handleAgentSpawn(interaction) {
5764
5467
  if (mode !== "auto") {
5765
5468
  setMode(session.id, mode);
5766
5469
  }
5767
- const statusEmbed = new EmbedBuilder4().setColor(PROVIDER_COLORS[provider]).setTitle("\u{1F4A4} \u5F85\u547D").setDescription("\u7B49\u5F85\u9996\u6761\u6D88\u606F").addFields({
5470
+ const statusEmbed = new EmbedBuilder2().setColor(PROVIDER_COLORS[provider]).setTitle("\u{1F4A4} \u5F85\u547D").setDescription("\u7B49\u5F85\u9996\u6761\u6D88\u606F").addFields({
5768
5471
  name: "\u6743\u9650",
5769
5472
  value: getSessionPermissionSummary(session),
5770
5473
  inline: false
@@ -5786,10 +5489,10 @@ async function handleAgentSpawn(interaction) {
5786
5489
  }
5787
5490
  setStatusCardBinding(session.id, { messageId: statusMessage.id });
5788
5491
  log(`[panel-adapter] \u72B6\u6001\u5361\u5DF2\u6CE8\u518C\uFF0Csession=${session.id}`);
5789
- const embed = new EmbedBuilder4().setColor(3066993).setTitle(`\u2705 Agent \u5DF2\u521B\u5EFA\uFF1A${label}`).addFields(
5492
+ const embed = new EmbedBuilder2().setColor(3066993).setTitle(`\u2705 Agent \u5DF2\u521B\u5EFA\uFF1A${label}`).addFields(
5790
5493
  { name: "\u9891\u9053", value: `<#${sessionChannel.id}>`, inline: true },
5791
5494
  { name: "\u63D0\u4F9B\u5546", value: PROVIDER_LABELS[provider], inline: true },
5792
- { name: "\u6A21\u5F0F", value: MODE_LABELS2?.[mode] ?? mode, inline: false },
5495
+ { name: "\u6A21\u5F0F", value: MODE_LABELS?.[mode] ?? mode, inline: false },
5793
5496
  { name: "\u76EE\u5F55", value: `\`${session.directory}\``, inline: false }
5794
5497
  );
5795
5498
  if (provider === "claude" && session.claudePermissionMode) {
@@ -5827,7 +5530,7 @@ async function handleAgentList(interaction) {
5827
5530
  const status = s.isGenerating ? "\u{1F504} \u6267\u884C\u4E2D" : "\u{1F4A4} \u7A7A\u95F2";
5828
5531
  return `${status} | \`${s.agentLabel}\` | ${s.provider} | <#${s.channelId}> | ${formatRelative(s.lastActivity)}`;
5829
5532
  });
5830
- const embed = new EmbedBuilder4().setColor(3447003).setTitle(`Agent \u4F1A\u8BDD\uFF08${sessions.length}\uFF09`).setDescription(lines.join("\n"));
5533
+ const embed = new EmbedBuilder2().setColor(3447003).setTitle(`Agent \u4F1A\u8BDD\uFF08${sessions.length}\uFF09`).setDescription(lines.join("\n"));
5831
5534
  await interaction.reply({ embeds: [embed], ephemeral: true });
5832
5535
  }
5833
5536
  async function handleAgentCleanup(interaction) {
@@ -5872,9 +5575,9 @@ async function handleAgentCleanup(interaction) {
5872
5575
  candidateSessionIds: preview.archiveCandidates.map((session) => session.id)
5873
5576
  });
5874
5577
  const components = [
5875
- new ActionRowBuilder2().addComponents(
5876
- new ButtonBuilder2().setCustomId(`cleanup:confirm:${request.id}`).setLabel("\u786E\u8BA4\u5F52\u6863").setStyle(ButtonStyle2.Danger),
5877
- new ButtonBuilder2().setCustomId(`cleanup:cancel:${request.id}`).setLabel("\u53D6\u6D88").setStyle(ButtonStyle2.Secondary)
5578
+ new ActionRowBuilder().addComponents(
5579
+ new ButtonBuilder().setCustomId(`cleanup:confirm:${request.id}`).setLabel("\u786E\u8BA4\u5F52\u6863").setStyle(ButtonStyle.Danger),
5580
+ new ButtonBuilder().setCustomId(`cleanup:cancel:${request.id}`).setLabel("\u53D6\u6D88").setStyle(ButtonStyle.Secondary)
5878
5581
  )
5879
5582
  ];
5880
5583
  await interaction.reply({
@@ -5957,7 +5660,7 @@ async function handleAgentMode(interaction) {
5957
5660
  }
5958
5661
  const mode = interaction.options.getString("mode", true);
5959
5662
  setMode(session.id, mode);
5960
- await interaction.reply({ content: `\u6A21\u5F0F\u5DF2\u8BBE\u4E3A **${MODE_LABELS2?.[mode] ?? mode}**\u3002`, ephemeral: true });
5663
+ await interaction.reply({ content: `\u6A21\u5F0F\u5DF2\u8BBE\u4E3A **${MODE_LABELS?.[mode] ?? mode}**\u3002`, ephemeral: true });
5961
5664
  }
5962
5665
  async function handleAgentGoal(interaction) {
5963
5666
  const session = getSessionByChannel(interaction.channelId);
@@ -6038,9 +5741,93 @@ async function handleAgentContinue(interaction) {
6038
5741
  await interaction.editReply("\u7EE7\u7EED\u4E2D...");
6039
5742
  await executeSessionContinue(session, channel);
6040
5743
  }
5744
+ async function handleAgentBatch(interaction) {
5745
+ const channel = interaction.channel;
5746
+ if (!channel) {
5747
+ await interaction.reply({ content: "\u65E0\u9891\u9053\u4E0A\u4E0B\u6587\u3002", ephemeral: true });
5748
+ return;
5749
+ }
5750
+ const session = getSessionByChannel(channel.id);
5751
+ if (!session) {
5752
+ await interaction.reply({ content: "\u6B64\u9891\u9053\u6CA1\u6709\u6D3B\u8DC3\u7684\u4F1A\u8BDD\u3002", ephemeral: true });
5753
+ return;
5754
+ }
5755
+ if (session.provider !== "claude") {
5756
+ await interaction.reply({
5757
+ content: "\u6279\u91CF\u5BA1\u6279\u6A21\u5F0F\u76EE\u524D\u4EC5\u652F\u6301 Claude \u4F1A\u8BDD\u3002Codex \u8BF7\u4F7F\u7528 `/agent permissions codex-approval` \u914D\u7F6E\u3002",
5758
+ ephemeral: true
5759
+ });
5760
+ return;
5761
+ }
5762
+ const action = interaction.options.getString("action", true);
5763
+ const source = "claude";
5764
+ if (action === "on") {
5765
+ if (!shouldUseClaudePermissionHandler(session)) {
5766
+ const hint = session.mode === "auto" ? "\u5F53\u524D\u4F1A\u8BDD\u662F `auto` \u6A21\u5F0F\uFF0C\u5DE5\u5177\u4E0D\u8D70\u5BA1\u6279 hook\u3002\u8BF7\u5148 `/agent mode mode:normal` \u518D\u5F00\u542F\u6279\u91CF\u5BA1\u6279\u3002" : "\u5F53\u524D\u4F1A\u8BDD\u7684 Claude \u6743\u9650\u6A21\u5F0F\u4E3A `bypass`\uFF0C\u5DE5\u5177\u4E0D\u8D70\u5BA1\u6279 hook\u3002\u8BF7\u5148 `/agent permissions claude-permissions:normal`\u3002";
5767
+ await interaction.reply({ content: `\u26A0\uFE0F \u65E0\u6CD5\u5F00\u542F\u6279\u91CF\u5BA1\u6279\uFF1A${hint}`, ephemeral: true });
5768
+ return;
5769
+ }
5770
+ await updateSessionState(session.id, {
5771
+ type: "batch_approval_changed",
5772
+ sessionId: session.id,
5773
+ source,
5774
+ confidence: "high",
5775
+ timestamp: Date.now(),
5776
+ metadata: { enabled: true }
5777
+ });
5778
+ await interaction.reply({
5779
+ content: "\u2705 \u5DF2\u5F00\u542F\u6279\u91CF\u5BA1\u6279\u6A21\u5F0F\u3002\u540E\u7EED\u6743\u9650\u8BF7\u6C42\u5C06\u6392\u961F\uFF0C\u4F7F\u7528 `/agent batch action:approve-all` \u6216 `reject-all` \u7EDF\u4E00\u5904\u7406\u3002",
5780
+ ephemeral: true
5781
+ });
5782
+ return;
5783
+ }
5784
+ if (action === "off") {
5785
+ const pending = getBatchApprovalCount(session.id);
5786
+ drainBatchApprovals(session.id, "reject");
5787
+ await updateSessionState(session.id, {
5788
+ type: "batch_approval_changed",
5789
+ sessionId: session.id,
5790
+ source,
5791
+ confidence: "high",
5792
+ timestamp: Date.now(),
5793
+ metadata: { enabled: false }
5794
+ });
5795
+ await interaction.reply({
5796
+ content: `\u2705 \u5DF2\u5173\u95ED\u6279\u91CF\u5BA1\u6279\u6A21\u5F0F${pending > 0 ? `\uFF0C\u961F\u5217\u4E2D ${pending} \u6761\u5F85\u6279\u8BF7\u6C42\u5DF2\u6309\u62D2\u7EDD\u5904\u7406\u3002` : "\u3002"}`,
5797
+ ephemeral: true
5798
+ });
5799
+ return;
5800
+ }
5801
+ if (action === "approve-all" || action === "reject-all") {
5802
+ const projection = stateMachine.getSnapshot(session.id);
5803
+ if (!projection.batchApprovalMode) {
5804
+ await interaction.reply({
5805
+ content: "\u6279\u91CF\u5BA1\u6279\u6A21\u5F0F\u672A\u542F\u7528\u3002\u5148\u7528 `/agent batch action:on` \u5F00\u542F\u3002",
5806
+ ephemeral: true
5807
+ });
5808
+ return;
5809
+ }
5810
+ const batchAction = action === "approve-all" ? "approve" : "reject";
5811
+ const count2 = drainBatchApprovals(session.id, batchAction);
5812
+ await updateSessionState(session.id, {
5813
+ type: "batch_approval_changed",
5814
+ sessionId: session.id,
5815
+ source,
5816
+ confidence: "high",
5817
+ timestamp: Date.now(),
5818
+ metadata: { enabled: true, pendingApprovals: [] }
5819
+ });
5820
+ await interaction.reply({
5821
+ content: count2 === 0 ? "\u961F\u5217\u4E2D\u6CA1\u6709\u5F85\u6279\u51C6\u7684\u8BF7\u6C42\u3002" : `\u2705 \u5DF2${batchAction === "approve" ? "\u6279\u51C6" : "\u62D2\u7EDD"} ${count2} \u6761\u5F85\u6279\u8BF7\u6C42\u3002`,
5822
+ ephemeral: true
5823
+ });
5824
+ return;
5825
+ }
5826
+ await interaction.reply({ content: `\u672A\u77E5\u52A8\u4F5C\uFF1A${action}`, ephemeral: true });
5827
+ }
6041
5828
 
6042
5829
  // ../bot/src/command-handlers-modules/subagent-handlers.ts
6043
- import { EmbedBuilder as EmbedBuilder5 } from "discord.js";
5830
+ import { EmbedBuilder as EmbedBuilder3 } from "discord.js";
6044
5831
  async function handleSubagent(interaction) {
6045
5832
  if (!assertUserAllowed(interaction)) return;
6046
5833
  const sub = interaction.options.getSubcommand();
@@ -6080,7 +5867,7 @@ async function handleSubagentRun(interaction) {
6080
5867
  }
6081
5868
  try {
6082
5869
  const subSession = await spawnSubagent(session, label, provider, sessionChannel);
6083
- const embed = new EmbedBuilder5().setColor(15965202).setTitle(`\u{1F916} \u5B50\u4EFB\u52A1\u5DF2\u521B\u5EFA\uFF1A${label}`).addFields(
5870
+ const embed = new EmbedBuilder3().setColor(15965202).setTitle(`\u{1F916} \u5B50\u4EFB\u52A1\u5DF2\u521B\u5EFA\uFF1A${label}`).addFields(
6084
5871
  { name: "\u5B50\u533A", value: `<#${subSession.channelId}>`, inline: true },
6085
5872
  { name: "\u63D0\u4F9B\u5546", value: PROVIDER_LABELS[provider], inline: true },
6086
5873
  { name: "\u5D4C\u5957\u6DF1\u5EA6", value: `${subSession.subagentDepth}`, inline: true }
@@ -6187,13 +5974,13 @@ var joinToUint8Array = (uint8ArraysOrStrings) => {
6187
5974
  };
6188
5975
  var stringsToUint8Arrays = (uint8ArraysOrStrings) => uint8ArraysOrStrings.map((uint8ArrayOrString) => typeof uint8ArrayOrString === "string" ? stringToUint8Array(uint8ArrayOrString) : uint8ArrayOrString);
6189
5976
  var concatUint8Arrays = (uint8Arrays) => {
6190
- const result2 = new Uint8Array(getJoinLength(uint8Arrays));
5977
+ const result = new Uint8Array(getJoinLength(uint8Arrays));
6191
5978
  let index = 0;
6192
5979
  for (const uint8Array of uint8Arrays) {
6193
- result2.set(uint8Array, index);
5980
+ result.set(uint8Array, index);
6194
5981
  index += uint8Array.length;
6195
5982
  }
6196
- return result2;
5983
+ return result;
6197
5984
  };
6198
5985
  var getJoinLength = (uint8Arrays) => {
6199
5986
  let joinLength = 0;
@@ -6748,17 +6535,17 @@ var format = (open2, close) => {
6748
6535
  if (index === -1) {
6749
6536
  return openCode + string + closeCode;
6750
6537
  }
6751
- let result2 = openCode;
6538
+ let result = openCode;
6752
6539
  let lastIndex = 0;
6753
6540
  const reopenOnNestedClose = close === 22;
6754
6541
  const replaceCode = (reopenOnNestedClose ? closeCode : "") + openCode;
6755
6542
  while (index !== -1) {
6756
- result2 += string.slice(lastIndex, index) + replaceCode;
6543
+ result += string.slice(lastIndex, index) + replaceCode;
6757
6544
  lastIndex = index + closeCode.length;
6758
6545
  index = string.indexOf(closeCode, lastIndex);
6759
6546
  }
6760
- result2 += string.slice(lastIndex) + closeCode;
6761
- return result2;
6547
+ result += string.slice(lastIndex) + closeCode;
6548
+ return result;
6762
6549
  };
6763
6550
  };
6764
6551
  var reset = format(0, 0);
@@ -6860,8 +6647,8 @@ var appendNewline = (printedLine) => printedLine.endsWith("\n") ? printedLine :
6860
6647
  `;
6861
6648
 
6862
6649
  // ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/verbose/log.js
6863
- var verboseLog = ({ type, verboseMessage, fdNumber, verboseInfo, result: result2 }) => {
6864
- const verboseObject = getVerboseObject({ type, result: result2, verboseInfo });
6650
+ var verboseLog = ({ type, verboseMessage, fdNumber, verboseInfo, result }) => {
6651
+ const verboseObject = getVerboseObject({ type, result, verboseInfo });
6865
6652
  const printedLines = getPrintedLines(verboseMessage, verboseObject);
6866
6653
  const finalLines = applyVerboseOnLines(printedLines, verboseInfo, fdNumber);
6867
6654
  if (finalLines !== "") {
@@ -6870,7 +6657,7 @@ var verboseLog = ({ type, verboseMessage, fdNumber, verboseInfo, result: result2
6870
6657
  };
6871
6658
  var getVerboseObject = ({
6872
6659
  type,
6873
- result: result2,
6660
+ result,
6874
6661
  verboseInfo: { escapedCommand, commandId, rawOptions: { piped = false, ...options } }
6875
6662
  }) => ({
6876
6663
  type,
@@ -6878,7 +6665,7 @@ var getVerboseObject = ({
6878
6665
  commandId: `${commandId}`,
6879
6666
  timestamp: /* @__PURE__ */ new Date(),
6880
6667
  piped,
6881
- result: result2,
6668
+ result,
6882
6669
  options
6883
6670
  });
6884
6671
  var getPrintedLines = (verboseMessage, verboseObject) => verboseMessage.split("\n").map((message) => getPrintedLine({ ...verboseObject, message }));
@@ -7007,28 +6794,28 @@ var npmRunPath = ({
7007
6794
  addExecPath = true
7008
6795
  } = {}) => {
7009
6796
  const cwdPath = path2.resolve(toPath(cwd));
7010
- const result2 = [];
6797
+ const result = [];
7011
6798
  const pathParts = pathOption.split(path2.delimiter);
7012
6799
  if (preferLocal) {
7013
- applyPreferLocal(result2, pathParts, cwdPath);
6800
+ applyPreferLocal(result, pathParts, cwdPath);
7014
6801
  }
7015
6802
  if (addExecPath) {
7016
- applyExecPath(result2, pathParts, execPath2, cwdPath);
6803
+ applyExecPath(result, pathParts, execPath2, cwdPath);
7017
6804
  }
7018
- return pathOption === "" || pathOption === path2.delimiter ? `${result2.join(path2.delimiter)}${pathOption}` : [...result2, pathOption].join(path2.delimiter);
6805
+ return pathOption === "" || pathOption === path2.delimiter ? `${result.join(path2.delimiter)}${pathOption}` : [...result, pathOption].join(path2.delimiter);
7019
6806
  };
7020
- var applyPreferLocal = (result2, pathParts, cwdPath) => {
6807
+ var applyPreferLocal = (result, pathParts, cwdPath) => {
7021
6808
  for (const directory of traversePathUp(cwdPath)) {
7022
6809
  const pathPart = path2.join(directory, "node_modules/.bin");
7023
6810
  if (!pathParts.includes(pathPart)) {
7024
- result2.push(pathPart);
6811
+ result.push(pathPart);
7025
6812
  }
7026
6813
  }
7027
6814
  };
7028
- var applyExecPath = (result2, pathParts, execPath2, cwdPath) => {
6815
+ var applyExecPath = (result, pathParts, execPath2, cwdPath) => {
7029
6816
  const pathPart = path2.resolve(cwdPath, toPath(execPath2), "..");
7030
6817
  if (!pathParts.includes(pathPart)) {
7031
- result2.push(pathPart);
6818
+ result.push(pathPart);
7032
6819
  }
7033
6820
  };
7034
6821
  var npmRunPathEnv = ({ env = process4.env, ...options } = {}) => {
@@ -8847,13 +8634,13 @@ var getMaxBufferInfo = (error, maxBuffer) => {
8847
8634
  }
8848
8635
  return { streamName: getStreamName(fdNumber), threshold, unit };
8849
8636
  };
8850
- var isMaxBufferSync = (resultError, output, maxBuffer) => resultError?.code === "ENOBUFS" && output !== null && output.some((result2) => result2 !== null && result2.length > getMaxBufferSync(maxBuffer));
8851
- var truncateMaxBufferSync = (result2, isMaxBuffer, maxBuffer) => {
8637
+ var isMaxBufferSync = (resultError, output, maxBuffer) => resultError?.code === "ENOBUFS" && output !== null && output.some((result) => result !== null && result.length > getMaxBufferSync(maxBuffer));
8638
+ var truncateMaxBufferSync = (result, isMaxBuffer, maxBuffer) => {
8852
8639
  if (!isMaxBuffer) {
8853
- return result2;
8640
+ return result;
8854
8641
  }
8855
8642
  const maxBufferValue = getMaxBufferSync(maxBuffer);
8856
- return result2.length > maxBufferValue ? result2.slice(0, maxBufferValue) : result2;
8643
+ return result.length > maxBufferValue ? result.slice(0, maxBufferValue) : result;
8857
8644
  };
8858
8645
  var getMaxBufferSync = ([, stdoutMaxBuffer]) => stdoutMaxBuffer;
8859
8646
 
@@ -9140,7 +8927,7 @@ var getErrorProperties = ({
9140
8927
  ipcOutput,
9141
8928
  pipedFrom: []
9142
8929
  });
9143
- var omitUndefinedProperties = (result2) => Object.fromEntries(Object.entries(result2).filter(([, value]) => value !== void 0));
8930
+ var omitUndefinedProperties = (result) => Object.fromEntries(Object.entries(result).filter(([, value]) => value !== void 0));
9144
8931
  var normalizeExitPayload = (rawExitCode, rawSignal) => {
9145
8932
  const exitCode = rawExitCode === null ? void 0 : rawExitCode;
9146
8933
  const signal = rawSignal === null ? void 0 : rawSignal;
@@ -9211,25 +8998,25 @@ function prettyMilliseconds(milliseconds, options) {
9211
8998
  options.secondsDecimalDigits = 0;
9212
8999
  options.millisecondsDecimalDigits = 0;
9213
9000
  }
9214
- let result2 = [];
9001
+ let result = [];
9215
9002
  const floorDecimals = (value, decimalDigits) => {
9216
9003
  const flooredInterimValue = Math.floor(value * 10 ** decimalDigits + SECOND_ROUNDING_EPSILON);
9217
9004
  const flooredValue = Math.round(flooredInterimValue) / 10 ** decimalDigits;
9218
9005
  return flooredValue.toFixed(decimalDigits);
9219
9006
  };
9220
9007
  const add = (value, long, short, valueString) => {
9221
- if ((result2.length === 0 || !options.colonNotation) && isZero(value) && !(options.colonNotation && short === "m")) {
9008
+ if ((result.length === 0 || !options.colonNotation) && isZero(value) && !(options.colonNotation && short === "m")) {
9222
9009
  return;
9223
9010
  }
9224
9011
  valueString ??= String(value);
9225
9012
  if (options.colonNotation) {
9226
9013
  const wholeDigits = valueString.includes(".") ? valueString.split(".")[0].length : valueString.length;
9227
- const minLength = result2.length > 0 ? 2 : 1;
9014
+ const minLength = result.length > 0 ? 2 : 1;
9228
9015
  valueString = "0".repeat(Math.max(0, minLength - wholeDigits)) + valueString;
9229
9016
  } else {
9230
9017
  valueString += options.verbose ? " " + pluralize(long, value) : short;
9231
9018
  }
9232
- result2.push(valueString);
9019
+ result.push(valueString);
9233
9020
  };
9234
9021
  const parsed = parseMilliseconds(milliseconds);
9235
9022
  const days = BigInt(parsed.days);
@@ -9276,53 +9063,53 @@ function prettyMilliseconds(milliseconds, options) {
9276
9063
  add(Number.parseFloat(secondsString), "second", "s", secondsString);
9277
9064
  }
9278
9065
  }
9279
- if (result2.length === 0) {
9066
+ if (result.length === 0) {
9280
9067
  return sign + "0" + (options.verbose ? " milliseconds" : "ms");
9281
9068
  }
9282
9069
  const separator = options.colonNotation ? ":" : " ";
9283
9070
  if (typeof options.unitCount === "number") {
9284
- result2 = result2.slice(0, Math.max(options.unitCount, 1));
9071
+ result = result.slice(0, Math.max(options.unitCount, 1));
9285
9072
  }
9286
- return sign + result2.join(separator);
9073
+ return sign + result.join(separator);
9287
9074
  }
9288
9075
 
9289
9076
  // ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/verbose/error.js
9290
- var logError = (result2, verboseInfo) => {
9291
- if (result2.failed) {
9077
+ var logError = (result, verboseInfo) => {
9078
+ if (result.failed) {
9292
9079
  verboseLog({
9293
9080
  type: "error",
9294
- verboseMessage: result2.shortMessage,
9081
+ verboseMessage: result.shortMessage,
9295
9082
  verboseInfo,
9296
- result: result2
9083
+ result
9297
9084
  });
9298
9085
  }
9299
9086
  };
9300
9087
 
9301
9088
  // ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/verbose/complete.js
9302
- var logResult = (result2, verboseInfo) => {
9089
+ var logResult = (result, verboseInfo) => {
9303
9090
  if (!isVerbose(verboseInfo)) {
9304
9091
  return;
9305
9092
  }
9306
- logError(result2, verboseInfo);
9307
- logDuration(result2, verboseInfo);
9093
+ logError(result, verboseInfo);
9094
+ logDuration(result, verboseInfo);
9308
9095
  };
9309
- var logDuration = (result2, verboseInfo) => {
9310
- const verboseMessage = `(done in ${prettyMilliseconds(result2.durationMs)})`;
9096
+ var logDuration = (result, verboseInfo) => {
9097
+ const verboseMessage = `(done in ${prettyMilliseconds(result.durationMs)})`;
9311
9098
  verboseLog({
9312
9099
  type: "duration",
9313
9100
  verboseMessage,
9314
9101
  verboseInfo,
9315
- result: result2
9102
+ result
9316
9103
  });
9317
9104
  };
9318
9105
 
9319
9106
  // ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/return/reject.js
9320
- var handleResult = (result2, verboseInfo, { reject }) => {
9321
- logResult(result2, verboseInfo);
9322
- if (result2.failed && reject) {
9323
- throw result2;
9107
+ var handleResult = (result, verboseInfo, { reject }) => {
9108
+ logResult(result, verboseInfo);
9109
+ if (result.failed && reject) {
9110
+ throw result;
9324
9111
  }
9325
- return result2;
9112
+ return result;
9326
9113
  };
9327
9114
 
9328
9115
  // ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/stdio/handle-sync.js
@@ -10406,8 +10193,8 @@ var transformOutputSync = ({ fileDescriptors, syncResult: { output }, options, i
10406
10193
  }
10407
10194
  const state = {};
10408
10195
  const outputFiles = /* @__PURE__ */ new Set([]);
10409
- const transformedOutput = output.map((result2, fdNumber) => transformOutputResultSync({
10410
- result: result2,
10196
+ const transformedOutput = output.map((result, fdNumber) => transformOutputResultSync({
10197
+ result,
10411
10198
  fileDescriptors,
10412
10199
  fdNumber,
10413
10200
  state,
@@ -10417,11 +10204,11 @@ var transformOutputSync = ({ fileDescriptors, syncResult: { output }, options, i
10417
10204
  }, options));
10418
10205
  return { output: transformedOutput, ...state };
10419
10206
  };
10420
- var transformOutputResultSync = ({ result: result2, fileDescriptors, fdNumber, state, outputFiles, isMaxBuffer, verboseInfo }, { buffer, encoding, lines, stripFinalNewline: stripFinalNewline2, maxBuffer }) => {
10421
- if (result2 === null) {
10207
+ var transformOutputResultSync = ({ result, fileDescriptors, fdNumber, state, outputFiles, isMaxBuffer, verboseInfo }, { buffer, encoding, lines, stripFinalNewline: stripFinalNewline2, maxBuffer }) => {
10208
+ if (result === null) {
10422
10209
  return;
10423
10210
  }
10424
- const truncatedResult = truncateMaxBufferSync(result2, isMaxBuffer, maxBuffer);
10211
+ const truncatedResult = truncateMaxBufferSync(result, isMaxBuffer, maxBuffer);
10425
10212
  const uint8ArrayResult = bufferToUint8Array(truncatedResult);
10426
10213
  const { stdioItems, objectMode } = fileDescriptors[fdNumber];
10427
10214
  const chunks = runOutputGeneratorsSync([uint8ArrayResult], stdioItems, encoding, state);
@@ -10582,7 +10369,7 @@ var getResultError = (error, exitCode, signal) => {
10582
10369
  // ../../node_modules/.pnpm/execa@9.6.1/node_modules/execa/lib/methods/main-sync.js
10583
10370
  var execaCoreSync = (rawFile, rawArguments, rawOptions) => {
10584
10371
  const { file, commandArguments, command, escapedCommand, startTime, verboseInfo, options, fileDescriptors } = handleSyncArguments(rawFile, rawArguments, rawOptions);
10585
- const result2 = spawnSubprocessSync({
10372
+ const result = spawnSubprocessSync({
10586
10373
  file,
10587
10374
  commandArguments,
10588
10375
  options,
@@ -10592,7 +10379,7 @@ var execaCoreSync = (rawFile, rawArguments, rawOptions) => {
10592
10379
  fileDescriptors,
10593
10380
  startTime
10594
10381
  });
10595
- return handleResult(result2, verboseInfo, options);
10382
+ return handleResult(result, verboseInfo, options);
10596
10383
  };
10597
10384
  var handleSyncArguments = (rawFile, rawArguments, rawOptions) => {
10598
10385
  const { command, escapedCommand, startTime, verboseInfo } = handleCommand(rawFile, rawArguments, rawOptions);
@@ -12728,7 +12515,7 @@ var handlePromise = async ({ subprocess, options, startTime, verboseInfo, fileDe
12728
12515
  onInternalError.resolve();
12729
12516
  const stdio = stdioResults.map((stdioResult, fdNumber) => stripNewline(stdioResult, options, fdNumber));
12730
12517
  const all = stripNewline(allResult, options, "all");
12731
- const result2 = getAsyncResult({
12518
+ const result = getAsyncResult({
12732
12519
  errorInfo,
12733
12520
  exitCode,
12734
12521
  signal,
@@ -12741,7 +12528,7 @@ var handlePromise = async ({ subprocess, options, startTime, verboseInfo, fileDe
12741
12528
  escapedCommand,
12742
12529
  startTime
12743
12530
  });
12744
- return handleResult(result2, verboseInfo, options);
12531
+ return handleResult(result, verboseInfo, options);
12745
12532
  };
12746
12533
  var getAsyncResult = ({ errorInfo, exitCode, signal, stdio, all, ipcOutput, context, options, command, escapedCommand, startTime }) => "error" in errorInfo ? makeError({
12747
12534
  error: errorInfo.error,
@@ -12939,28 +12726,28 @@ async function executeShellCommand(command, cwd, channel) {
12939
12726
  kind: "command",
12940
12727
  text: `\u6267\u884C\u547D\u4EE4\uFF1A${truncate(command, 120)}`
12941
12728
  });
12942
- const result2 = await child;
12729
+ const result = await child;
12943
12730
  const output = [
12944
- result2.all?.trim() || "",
12945
- result2.timedOut ? "[Timed out after 60s]" : "",
12946
- `[Exit code: ${result2.exitCode ?? "killed"}]`
12731
+ result.all?.trim() || "",
12732
+ result.timedOut ? "[Timed out after 60s]" : "",
12733
+ `[Exit code: ${result.exitCode ?? "killed"}]`
12947
12734
  ].filter(Boolean).join("\n");
12948
12735
  runningProcesses.delete(pid);
12949
12736
  execaProcesses.delete(pid);
12950
12737
  queueDigest(shellSessionId, {
12951
12738
  kind: "command",
12952
- text: `\u547D\u4EE4\u7ED3\u675F\uFF1A\u9000\u51FA\u7801 ${result2.exitCode ?? "killed"}`
12739
+ text: `\u547D\u4EE4\u7ED3\u675F\uFF1A\u9000\u51FA\u7801 ${result.exitCode ?? "killed"}`
12953
12740
  });
12954
12741
  await flushDigest(shellSessionId);
12955
12742
  await handleResultEvent(
12956
12743
  shellSessionId,
12957
12744
  {
12958
12745
  type: "result",
12959
- success: result2.exitCode === 0,
12746
+ success: result.exitCode === 0,
12960
12747
  costUsd: 0,
12961
12748
  durationMs: Date.now() - shellProcess.startedAt,
12962
12749
  numTurns: 1,
12963
- errors: result2.exitCode === 0 ? [] : [output],
12750
+ errors: result.exitCode === 0 ? [] : [output],
12964
12751
  metadata: { sessionEnd: false }
12965
12752
  },
12966
12753
  renderShellOutput(command, output)
@@ -13051,8 +12838,8 @@ async function handleShellKill(interaction) {
13051
12838
 
13052
12839
  // ../bot/src/button-handler-actions.ts
13053
12840
  import {
13054
- ActionRowBuilder as ActionRowBuilder3,
13055
- StringSelectMenuBuilder as StringSelectMenuBuilder2
12841
+ ActionRowBuilder as ActionRowBuilder2,
12842
+ StringSelectMenuBuilder
13056
12843
  } from "discord.js";
13057
12844
  function asComponentLike(component) {
13058
12845
  return component || {};
@@ -13074,19 +12861,19 @@ async function resolveAwaitingHumanIfNeeded(sessionId) {
13074
12861
  metadata: { source: "answer" }
13075
12862
  });
13076
12863
  }
13077
- function renderCleanupResultMessage(result2) {
12864
+ function renderCleanupResultMessage(result) {
13078
12865
  const lines = [
13079
12866
  "\u6279\u91CF\u6E05\u7406\u5B8C\u6210",
13080
12867
  "",
13081
- `- \u5DF2\u5F52\u6863\uFF1A${result2.archivedSessions}`,
13082
- `- \u8DF3\u8FC7\u8FDB\u884C\u4E2D\uFF1A${result2.skippedGenerating}`,
13083
- `- \u7F3A\u5931\uFF1A${result2.missingSessions}`,
13084
- `- \u5931\u8D25\uFF1A${result2.failed.length}`
12868
+ `- \u5DF2\u5F52\u6863\uFF1A${result.archivedSessions}`,
12869
+ `- \u8DF3\u8FC7\u8FDB\u884C\u4E2D\uFF1A${result.skippedGenerating}`,
12870
+ `- \u7F3A\u5931\uFF1A${result.missingSessions}`,
12871
+ `- \u5931\u8D25\uFF1A${result.failed.length}`
13085
12872
  ];
13086
- if (result2.failed.length > 0) {
12873
+ if (result.failed.length > 0) {
13087
12874
  lines.push("", "\u5931\u8D25\u660E\u7EC6\uFF1A");
13088
12875
  lines.push(
13089
- ...result2.failed.map((item) => `- ${item.channelId ? `<#${item.channelId}> ` : ""}${item.sessionId}\uFF1A${item.message}`)
12876
+ ...result.failed.map((item) => `- ${item.channelId ? `<#${item.channelId}> ` : ""}${item.sessionId}\uFF1A${item.message}`)
13090
12877
  );
13091
12878
  }
13092
12879
  return lines.join("\n");
@@ -13132,13 +12919,13 @@ async function handleAwaitingHumanButton(interaction) {
13132
12919
  await interaction.reply({ content: "\u672A\u627E\u5230\u6D3B\u8DC3\u7684\u95E8\u63A7\u8BB0\u5F55", ephemeral: true });
13133
12920
  return true;
13134
12921
  }
13135
- const result2 = await gateService.resolveFromDiscord(
12922
+ const result = await gateService.resolveFromDiscord(
13136
12923
  activeGate.id,
13137
12924
  action === "approve" ? "approve" : "reject"
13138
12925
  );
13139
- if (!result2.success) {
12926
+ if (!result.success) {
13140
12927
  await interaction.reply({
13141
- content: `\u5904\u7406\u5931\u8D25: ${result2.message || "\u672A\u77E5\u9519\u8BEF"}`,
12928
+ content: `\u5904\u7406\u5931\u8D25: ${result.message || "\u672A\u77E5\u9519\u8BEF"}`,
13142
12929
  ephemeral: true
13143
12930
  });
13144
12931
  return true;
@@ -13157,7 +12944,7 @@ async function handleAwaitingHumanButton(interaction) {
13157
12944
  }
13158
12945
  }))
13159
12946
  });
13160
- if (result2.handledByReceipt) {
12947
+ if (result.handledByReceipt) {
13161
12948
  return true;
13162
12949
  }
13163
12950
  if (action === "approve") {
@@ -13287,13 +13074,13 @@ async function handleCleanupButtons(interaction) {
13287
13074
  await interaction.deferUpdate();
13288
13075
  try {
13289
13076
  console.log(`[ButtonHandler] Cleanup confirmed by ${interaction.user.tag} \u2014 archiving ${request.candidateSessionIds.length} sessions`);
13290
- const result2 = await archiveSessionsById(
13077
+ const result = await archiveSessionsById(
13291
13078
  interaction.guild,
13292
13079
  request.candidateSessionIds,
13293
13080
  "Bulk cleanup from Discord command"
13294
13081
  );
13295
13082
  deleteCleanupRequest(requestId);
13296
- await interaction.editReply({ content: renderCleanupResultMessage(result2), components: [] });
13083
+ await interaction.editReply({ content: renderCleanupResultMessage(result), components: [] });
13297
13084
  } finally {
13298
13085
  releaseCleanupLock(request.categoryId);
13299
13086
  }
@@ -13360,7 +13147,7 @@ async function handleSelectMenuAction(interaction) {
13360
13147
  if (!("components" in row)) return row;
13361
13148
  const comp = asComponentLike(row.components?.[0]);
13362
13149
  if (comp?.customId !== customId) return row;
13363
- const menu = new StringSelectMenuBuilder2().setCustomId(customId).setPlaceholder(`\u5DF2\u9009\u62E9\uFF1A${selected.slice(0, 80)}`);
13150
+ const menu = new StringSelectMenuBuilder().setCustomId(customId).setPlaceholder(`\u5DF2\u9009\u62E9\uFF1A${selected.slice(0, 80)}`);
13364
13151
  for (const opt of comp.options || []) {
13365
13152
  menu.addOptions({
13366
13153
  label: opt.label,
@@ -13369,7 +13156,7 @@ async function handleSelectMenuAction(interaction) {
13369
13156
  default: opt.value === selected
13370
13157
  });
13371
13158
  }
13372
- return new ActionRowBuilder3().addComponents(menu);
13159
+ return new ActionRowBuilder2().addComponents(menu);
13373
13160
  });
13374
13161
  await original.edit({ components: updatedComponents });
13375
13162
  } catch {
@@ -13588,7 +13375,7 @@ async function startBot() {
13588
13375
  const guild = client.guilds.cache.first();
13589
13376
  if (guild) {
13590
13377
  serviceContainer.logChannel = guild.channels.cache.find(
13591
- (ch) => ch.name === "bot-logs" && ch.type === ChannelType8.GuildText && !ch.parentId
13378
+ (ch) => ch.name === "bot-logs" && ch.type === ChannelType7.GuildText && !ch.parentId
13592
13379
  ) ?? serviceContainer.logChannel;
13593
13380
  logBuffer.setChannel(serviceContainer.logChannel);
13594
13381
  }
@@ -13654,7 +13441,7 @@ async function runCli() {
13654
13441
  await startBot();
13655
13442
  });
13656
13443
  cli.command("config [action] [key] [value]", "Manage configuration").action(async (action, key, value) => {
13657
- const { handleConfig } = await import("./config-cli-7JEV3WYY.js");
13444
+ const { handleConfig } = await import("./config-cli-7G5YWKJU.js");
13658
13445
  const args = [action || "list"].filter(Boolean);
13659
13446
  if (key) args.push(key);
13660
13447
  if (value) args.push(value);
@@ -13662,12 +13449,12 @@ async function runCli() {
13662
13449
  await handleConfig(args);
13663
13450
  });
13664
13451
  cli.command("project [action] [...args]", "Manage mounted projects").action(async (action, args) => {
13665
- const { handleProject: handleProject2 } = await import("./project-cli-ZXMHOFUJ.js");
13452
+ const { handleProject: handleProject2 } = await import("./project-cli-ALKDLRMZ.js");
13666
13453
  const cmdArgs = [action || "help"].filter(Boolean).concat(args || []);
13667
13454
  await handleProject2(cmdArgs);
13668
13455
  });
13669
13456
  cli.command("attachment [action]", "Manage attachments").action(async (action) => {
13670
- const { handleAttachment } = await import("./attachment-cli-MF7XZ4WT.js");
13457
+ const { handleAttachment } = await import("./attachment-cli-AT4HXAGU.js");
13671
13458
  await handleAttachment([action || "fetch"]);
13672
13459
  });
13673
13460
  cli.command("daemon <action>", "Manage background service").action(async (action) => {
@@ -13675,7 +13462,7 @@ async function runCli() {
13675
13462
  await handleDaemon(action);
13676
13463
  });
13677
13464
  cli.command("codex [...options]", "Launch managed Codex session with remote approval").allowUnknownOptions().action(async function(options) {
13678
- const { handleCodexCommand } = await import("./codex-launcher-ZBQ5VL6L.js");
13465
+ const { handleCodexCommand } = await import("./codex-launcher-CLGG4CVY.js");
13679
13466
  const parsed = this.options;
13680
13467
  const rawArgs = [];
13681
13468
  for (const [key, value] of Object.entries(parsed)) {