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.
- package/dist/{archive-manager-RW36JGUV.js → archive-manager-FJU7YEEH.js} +4 -4
- package/dist/{attachment-cli-MF7XZ4WT.js → attachment-cli-AT4HXAGU.js} +2 -2
- package/dist/{chunk-ZO62NAYX.js → chunk-5EMN2IL5.js} +1 -1
- package/dist/{chunk-BFINJJYL.js → chunk-66B64WL3.js} +1 -1
- package/dist/{chunk-QWPKAUSV.js → chunk-C4L34VJK.js} +8287 -7421
- package/dist/{chunk-WON3DPE4.js → chunk-JR4B4L7I.js} +213 -4
- package/dist/{chunk-IVXCJA5I.js → chunk-MJ5JKFGS.js} +9 -0
- package/dist/{chunk-7GTUWAQR.js → chunk-NNTMVOTM.js} +876 -315
- package/dist/{chunk-WP6YJVAE.js → chunk-PWMEOBXG.js} +4 -4
- package/dist/{chunk-AGB4GP4G.js → chunk-SNPFYUQ3.js} +441 -654
- package/dist/{chunk-4KQ7OSK7.js → chunk-SV7EHL3B.js} +3 -3
- package/dist/cli-framework-YF3LPLMT.js +18 -0
- package/dist/cli.js +10 -10
- package/dist/{codex-launcher-ZBQ5VL6L.js → codex-launcher-CLGG4CVY.js} +1 -1
- package/dist/{codex-provider-Q4Z6UKO6.js → codex-provider-VLOS5QB6.js} +18 -4
- package/dist/{config-cli-7JEV3WYY.js → config-cli-7G5YWKJU.js} +2 -2
- package/dist/{panel-adapter-U75WXDLB.js → panel-adapter-CLI4WDII.js} +4 -4
- package/dist/{project-cli-ZXMHOFUJ.js → project-cli-ALKDLRMZ.js} +2 -2
- package/dist/{project-registry-ED6P5ZTM.js → project-registry-ZO3KSS25.js} +2 -2
- package/dist/sdk-C3D6X4EB.js +55 -0
- package/dist/{session-local-registration-MISPPGXF.js → session-local-registration-RL2A3QZB.js} +3 -3
- package/dist/{setup-ZFVMMNT2.js → setup-GP3MML2R.js} +1 -1
- package/package.json +3 -3
- package/dist/cli-framework-7E5MKPMM.js +0 -18
- package/dist/sdk-V7A7IF7F.js +0 -43
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
|
-
|
|
4
|
-
} from "./chunk-
|
|
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-
|
|
37
|
+
} from "./chunk-NNTMVOTM.js";
|
|
31
38
|
import {
|
|
32
39
|
registerMessageAttachments
|
|
33
|
-
} from "./chunk-
|
|
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-
|
|
61
|
+
} from "./chunk-SV7EHL3B.js";
|
|
55
62
|
import {
|
|
56
63
|
getAllRegisteredProjects
|
|
57
|
-
} from "./chunk-
|
|
64
|
+
} from "./chunk-5EMN2IL5.js";
|
|
58
65
|
import {
|
|
59
66
|
buildClaudeSubagentProviderSessionId,
|
|
60
67
|
registerLocalSession
|
|
61
|
-
} from "./chunk-
|
|
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-
|
|
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-
|
|
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
|
|
611
|
-
|
|
612
|
-
return
|
|
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
|
|
640
|
+
ChannelType as ChannelType7
|
|
630
641
|
} from "discord.js";
|
|
631
642
|
|
|
632
643
|
// ../bot/src/bot-services-orchestrator.ts
|
|
633
|
-
import { ChannelType as
|
|
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 =
|
|
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 =
|
|
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
|
|
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-
|
|
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
|
|
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 = (
|
|
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=${
|
|
1222
|
+
`[SessionExecutor] gate:resolved sessionId=${session.id} gateId=${gateId} action=${result.action} source=${result.source}`
|
|
1165
1223
|
);
|
|
1166
|
-
resolve2(
|
|
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:
|
|
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,
|
|
1303
|
-
const changedFiles =
|
|
1304
|
-
const 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 =
|
|
1311
|
-
const blockers =
|
|
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(
|
|
1315
|
-
commandCount:
|
|
1316
|
-
fileChangeCount:
|
|
1448
|
+
textualResponse: summarizeWorkerText(result.text),
|
|
1449
|
+
commandCount: result.commandCount,
|
|
1450
|
+
fileChangeCount: result.fileChangeCount,
|
|
1317
1451
|
meaningfulExecutionEvidence: meaningfulExecution,
|
|
1318
|
-
providerReportedSuccess:
|
|
1319
|
-
workerErrorsObserved:
|
|
1320
|
-
askedForHumanInput:
|
|
1321
|
-
claimedCompletedOutcomes: extractClaimedCompletedOutcomes(
|
|
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:
|
|
1325
|
-
remainingGaps: extractRemainingGaps(
|
|
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
|
|
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
|
-
...
|
|
2244
|
+
...result,
|
|
2111
2245
|
hadError: true,
|
|
2112
2246
|
abortReason,
|
|
2113
|
-
text: annotateInactivityAbort(
|
|
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("",
|
|
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=${
|
|
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
|
-
...
|
|
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
|
|
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
|
-
|
|
2839
|
+
result.missingSessions += 1;
|
|
3148
2840
|
continue;
|
|
3149
2841
|
}
|
|
3150
2842
|
if (session.isGenerating) {
|
|
3151
|
-
|
|
2843
|
+
result.skippedGenerating += 1;
|
|
3152
2844
|
continue;
|
|
3153
2845
|
}
|
|
3154
2846
|
try {
|
|
3155
2847
|
await archiveSession(session, guild, summary);
|
|
3156
|
-
|
|
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
|
-
|
|
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: ${
|
|
3167
|
-
return
|
|
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
|
|
2879
|
+
import { ChannelType } from "discord.js";
|
|
3188
2880
|
|
|
3189
2881
|
// ../bot/src/codex-session-discovery.ts
|
|
3190
|
-
import { existsSync
|
|
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 (!
|
|
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 (!
|
|
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 ===
|
|
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:
|
|
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-
|
|
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 !==
|
|
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 !==
|
|
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
|
|
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
|
|
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 (!
|
|
3718
|
+
if (!result) return null;
|
|
4027
3719
|
return {
|
|
4028
|
-
sessionId:
|
|
4029
|
-
channelId:
|
|
4030
|
-
isNew:
|
|
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 (
|
|
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 &&
|
|
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
|
|
4191
|
-
if (!
|
|
4192
|
-
console.warn(`[IpcServer] Gate resolution failed: ${
|
|
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
|
|
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 ===
|
|
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
|
|
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 (
|
|
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 ===
|
|
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:
|
|
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
|
|
4604
|
+
let result;
|
|
4904
4605
|
try {
|
|
4905
|
-
|
|
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 (
|
|
4611
|
+
if (result.abandoned.length > 0) {
|
|
4911
4612
|
logBuffer2.log(
|
|
4912
|
-
`Marked ${
|
|
4613
|
+
`Marked ${result.abandoned.length} orphan monitor run(s) as abandoned on startup.`
|
|
4913
4614
|
);
|
|
4914
4615
|
}
|
|
4915
|
-
if (
|
|
4616
|
+
if (result.candidates.length === 0) return;
|
|
4916
4617
|
logBuffer2.log(
|
|
4917
|
-
`Auto-resuming ${
|
|
4618
|
+
`Auto-resuming ${result.candidates.length} monitor session(s) (policy=${config.monitorAutoResumePolicy}).`
|
|
4918
4619
|
);
|
|
4919
|
-
for (const candidate of
|
|
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
|
|
4942
|
-
for (const { gateId, discordMessageId } of
|
|
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 (
|
|
4667
|
+
if (result.resumed.length > 0) {
|
|
4967
4668
|
logBuffer2.log(
|
|
4968
|
-
`Resumed ${
|
|
4669
|
+
`Resumed ${result.resumed.length} pending gate(s) across restart (policy=resume-pending).`
|
|
4969
4670
|
);
|
|
4970
4671
|
}
|
|
4971
|
-
if (
|
|
4972
|
-
logBuffer2.log(`Closed ${
|
|
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-
|
|
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
|
|
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 (
|
|
5014
|
-
void notifyUnmanagedCodexHint(client2,
|
|
4714
|
+
if (result?.isNewlyCreated && result.session.remoteHumanControl === false) {
|
|
4715
|
+
void notifyUnmanagedCodexHint(client2, result.session.id, result.session.channelId);
|
|
5015
4716
|
}
|
|
5016
|
-
return
|
|
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
|
|
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 (!
|
|
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 (!
|
|
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
|
|
5130
|
-
EmbedBuilder
|
|
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
|
|
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
|
|
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-
|
|
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 ===
|
|
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 ===
|
|
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:
|
|
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:
|
|
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
|
|
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
|
|
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
|
|
5603
|
-
ButtonBuilder
|
|
5604
|
-
ButtonStyle
|
|
5605
|
-
ChannelType as
|
|
5606
|
-
EmbedBuilder as
|
|
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:
|
|
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
|
|
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
|
|
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:
|
|
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
|
|
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
|
|
5876
|
-
new
|
|
5877
|
-
new
|
|
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 **${
|
|
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
|
|
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
|
|
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
|
|
5977
|
+
const result = new Uint8Array(getJoinLength(uint8Arrays));
|
|
6191
5978
|
let index = 0;
|
|
6192
5979
|
for (const uint8Array of uint8Arrays) {
|
|
6193
|
-
|
|
5980
|
+
result.set(uint8Array, index);
|
|
6194
5981
|
index += uint8Array.length;
|
|
6195
5982
|
}
|
|
6196
|
-
return
|
|
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
|
|
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
|
-
|
|
6543
|
+
result += string.slice(lastIndex, index) + replaceCode;
|
|
6757
6544
|
lastIndex = index + closeCode.length;
|
|
6758
6545
|
index = string.indexOf(closeCode, lastIndex);
|
|
6759
6546
|
}
|
|
6760
|
-
|
|
6761
|
-
return
|
|
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
|
|
6864
|
-
const verboseObject = getVerboseObject({ type, result
|
|
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
|
|
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
|
|
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
|
|
6797
|
+
const result = [];
|
|
7011
6798
|
const pathParts = pathOption.split(path2.delimiter);
|
|
7012
6799
|
if (preferLocal) {
|
|
7013
|
-
applyPreferLocal(
|
|
6800
|
+
applyPreferLocal(result, pathParts, cwdPath);
|
|
7014
6801
|
}
|
|
7015
6802
|
if (addExecPath) {
|
|
7016
|
-
applyExecPath(
|
|
6803
|
+
applyExecPath(result, pathParts, execPath2, cwdPath);
|
|
7017
6804
|
}
|
|
7018
|
-
return pathOption === "" || pathOption === path2.delimiter ? `${
|
|
6805
|
+
return pathOption === "" || pathOption === path2.delimiter ? `${result.join(path2.delimiter)}${pathOption}` : [...result, pathOption].join(path2.delimiter);
|
|
7019
6806
|
};
|
|
7020
|
-
var applyPreferLocal = (
|
|
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
|
-
|
|
6811
|
+
result.push(pathPart);
|
|
7025
6812
|
}
|
|
7026
6813
|
}
|
|
7027
6814
|
};
|
|
7028
|
-
var applyExecPath = (
|
|
6815
|
+
var applyExecPath = (result, pathParts, execPath2, cwdPath) => {
|
|
7029
6816
|
const pathPart = path2.resolve(cwdPath, toPath(execPath2), "..");
|
|
7030
6817
|
if (!pathParts.includes(pathPart)) {
|
|
7031
|
-
|
|
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((
|
|
8851
|
-
var truncateMaxBufferSync = (
|
|
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
|
|
8640
|
+
return result;
|
|
8854
8641
|
}
|
|
8855
8642
|
const maxBufferValue = getMaxBufferSync(maxBuffer);
|
|
8856
|
-
return
|
|
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 = (
|
|
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
|
|
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 ((
|
|
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 =
|
|
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
|
-
|
|
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 (
|
|
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
|
-
|
|
9071
|
+
result = result.slice(0, Math.max(options.unitCount, 1));
|
|
9285
9072
|
}
|
|
9286
|
-
return sign +
|
|
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 = (
|
|
9291
|
-
if (
|
|
9077
|
+
var logError = (result, verboseInfo) => {
|
|
9078
|
+
if (result.failed) {
|
|
9292
9079
|
verboseLog({
|
|
9293
9080
|
type: "error",
|
|
9294
|
-
verboseMessage:
|
|
9081
|
+
verboseMessage: result.shortMessage,
|
|
9295
9082
|
verboseInfo,
|
|
9296
|
-
result
|
|
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 = (
|
|
9089
|
+
var logResult = (result, verboseInfo) => {
|
|
9303
9090
|
if (!isVerbose(verboseInfo)) {
|
|
9304
9091
|
return;
|
|
9305
9092
|
}
|
|
9306
|
-
logError(
|
|
9307
|
-
logDuration(
|
|
9093
|
+
logError(result, verboseInfo);
|
|
9094
|
+
logDuration(result, verboseInfo);
|
|
9308
9095
|
};
|
|
9309
|
-
var logDuration = (
|
|
9310
|
-
const verboseMessage = `(done in ${prettyMilliseconds(
|
|
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
|
|
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 = (
|
|
9321
|
-
logResult(
|
|
9322
|
-
if (
|
|
9323
|
-
throw
|
|
9107
|
+
var handleResult = (result, verboseInfo, { reject }) => {
|
|
9108
|
+
logResult(result, verboseInfo);
|
|
9109
|
+
if (result.failed && reject) {
|
|
9110
|
+
throw result;
|
|
9324
9111
|
}
|
|
9325
|
-
return
|
|
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((
|
|
10410
|
-
result
|
|
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
|
|
10421
|
-
if (
|
|
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(
|
|
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
|
|
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(
|
|
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
|
|
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(
|
|
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
|
|
12729
|
+
const result = await child;
|
|
12943
12730
|
const output = [
|
|
12944
|
-
|
|
12945
|
-
|
|
12946
|
-
`[Exit code: ${
|
|
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 ${
|
|
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:
|
|
12746
|
+
success: result.exitCode === 0,
|
|
12960
12747
|
costUsd: 0,
|
|
12961
12748
|
durationMs: Date.now() - shellProcess.startedAt,
|
|
12962
12749
|
numTurns: 1,
|
|
12963
|
-
errors:
|
|
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
|
|
13055
|
-
StringSelectMenuBuilder
|
|
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(
|
|
12864
|
+
function renderCleanupResultMessage(result) {
|
|
13078
12865
|
const lines = [
|
|
13079
12866
|
"\u6279\u91CF\u6E05\u7406\u5B8C\u6210",
|
|
13080
12867
|
"",
|
|
13081
|
-
`- \u5DF2\u5F52\u6863\uFF1A${
|
|
13082
|
-
`- \u8DF3\u8FC7\u8FDB\u884C\u4E2D\uFF1A${
|
|
13083
|
-
`- \u7F3A\u5931\uFF1A${
|
|
13084
|
-
`- \u5931\u8D25\uFF1A${
|
|
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 (
|
|
12873
|
+
if (result.failed.length > 0) {
|
|
13087
12874
|
lines.push("", "\u5931\u8D25\u660E\u7EC6\uFF1A");
|
|
13088
12875
|
lines.push(
|
|
13089
|
-
...
|
|
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
|
|
12922
|
+
const result = await gateService.resolveFromDiscord(
|
|
13136
12923
|
activeGate.id,
|
|
13137
12924
|
action === "approve" ? "approve" : "reject"
|
|
13138
12925
|
);
|
|
13139
|
-
if (!
|
|
12926
|
+
if (!result.success) {
|
|
13140
12927
|
await interaction.reply({
|
|
13141
|
-
content: `\u5904\u7406\u5931\u8D25: ${
|
|
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 (
|
|
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
|
|
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(
|
|
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
|
|
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
|
|
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 ===
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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)) {
|