workspacecord 1.0.2 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/archive-manager-KMNAWQIN.js +21 -0
- package/dist/attachment-cli-QEF7IZBI.js +62 -0
- package/dist/{chunk-OKI4UVGY.js → chunk-52OOARML.js} +65 -2
- package/dist/{chunk-NIXZJTOZ.js → chunk-7KESUGJP.js} +3 -46
- package/dist/chunk-CBNENUW6.js +55 -0
- package/dist/{chunk-2LBNM64L.js → chunk-D6J3X35H.js} +23 -11
- package/dist/{bot-B5HN4ZW6.js → chunk-G6CCOBUY.js} +6556 -5956
- package/dist/{chunk-TSBM3BNT.js → chunk-IFSOU4XI.js} +393 -140
- package/dist/chunk-PUKMHDXS.js +196 -0
- package/dist/chunk-Q2AJ4UEK.js +199 -0
- package/dist/cli-framework-KMQXM2PO.js +17 -0
- package/dist/cli.js +20 -68
- package/dist/{codex-launcher-IF2IPLBP.js → codex-launcher-OOF2WYQF.js} +1 -1
- package/dist/{codex-provider-7CI5W34X.js → codex-provider-P7TDYK6B.js} +2 -2
- package/dist/{config-cli-F2B5SYHJ.js → config-cli-YSKOXADF.js} +2 -2
- package/dist/{project-cli-FEMPZIRQ.js → project-cli-QW5QYT6A.js} +2 -1
- package/dist/{project-registry-DQT5ORUU.js → project-registry-LL75XEUV.js} +2 -1
- package/dist/{setup-TKOVXSME.js → setup-QJ4HVVCU.js} +1 -1
- package/dist/{thread-manager-5T46QTZF.js → thread-manager-DRWNFXXY.js} +17 -7
- package/package.json +7 -2
- package/dist/chunk-WE4X3JB3.js +0 -130
- package/dist/utils-72GMT2X5.js +0 -36
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
config
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-D6J3X35H.js";
|
|
5
5
|
import {
|
|
6
|
-
Store,
|
|
7
6
|
bindProjectCategory,
|
|
8
7
|
getProjectByCategoryId,
|
|
9
8
|
getProjectByName,
|
|
@@ -11,16 +10,14 @@ import {
|
|
|
11
10
|
setProjectControlChannel,
|
|
12
11
|
setProjectHistoryChannel,
|
|
13
12
|
updateProject
|
|
14
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-7KESUGJP.js";
|
|
15
14
|
import {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
sanitizeName
|
|
19
|
-
} from "./chunk-WE4X3JB3.js";
|
|
15
|
+
Store
|
|
16
|
+
} from "./chunk-CBNENUW6.js";
|
|
20
17
|
|
|
21
18
|
// src/thread-manager.ts
|
|
22
|
-
import
|
|
23
|
-
import { sep } from "path";
|
|
19
|
+
import "fs";
|
|
20
|
+
import { sep as sep2 } from "path";
|
|
24
21
|
|
|
25
22
|
// src/providers/claude-provider.ts
|
|
26
23
|
import { query } from "@anthropic-ai/claude-agent-sdk";
|
|
@@ -253,7 +250,7 @@ providers.set("claude", new ClaudeProvider());
|
|
|
253
250
|
var codexLoadAttempted = false;
|
|
254
251
|
async function loadCodexProvider() {
|
|
255
252
|
try {
|
|
256
|
-
const { CodexProvider } = await import("./codex-provider-
|
|
253
|
+
const { CodexProvider } = await import("./codex-provider-P7TDYK6B.js");
|
|
257
254
|
providers.set("codex", new CodexProvider());
|
|
258
255
|
codexLoadAttempted = true;
|
|
259
256
|
} catch (err) {
|
|
@@ -396,18 +393,24 @@ async function bindMountedProjectToCategory(projectName, categoryId, categoryNam
|
|
|
396
393
|
function setHistoryChannelId(categoryId, channelId) {
|
|
397
394
|
const project = getProjectByCategoryId(categoryId);
|
|
398
395
|
if (!project) return;
|
|
399
|
-
|
|
396
|
+
setProjectHistoryChannel(project.name, channelId).catch(
|
|
397
|
+
(err) => console.error(`Failed to set history channel for project "${project.name}": ${err.message}`)
|
|
398
|
+
);
|
|
400
399
|
}
|
|
401
400
|
function setControlChannelId(categoryId, channelId) {
|
|
402
401
|
const project = getProjectByCategoryId(categoryId);
|
|
403
402
|
if (!project) return;
|
|
404
|
-
|
|
403
|
+
setProjectControlChannel(project.name, channelId).catch(
|
|
404
|
+
(err) => console.error(`Failed to set control channel for project "${project.name}": ${err.message}`)
|
|
405
|
+
);
|
|
405
406
|
}
|
|
406
407
|
function setPersonality(categoryId, personality) {
|
|
407
408
|
const project = getProjectByCategoryId(categoryId);
|
|
408
409
|
if (!project) return;
|
|
409
410
|
project.personality = personality;
|
|
410
|
-
|
|
411
|
+
updateProject(project).catch(
|
|
412
|
+
(err) => console.error(`Failed to update personality for project "${project.name}": ${err.message}`)
|
|
413
|
+
);
|
|
411
414
|
}
|
|
412
415
|
function getPersonality(categoryId) {
|
|
413
416
|
return getProjectByCategoryId(categoryId)?.personality;
|
|
@@ -416,19 +419,25 @@ function clearPersonality(categoryId) {
|
|
|
416
419
|
const project = getProjectByCategoryId(categoryId);
|
|
417
420
|
if (!project) return;
|
|
418
421
|
delete project.personality;
|
|
419
|
-
|
|
422
|
+
updateProject(project).catch(
|
|
423
|
+
(err) => console.error(`Failed to clear personality for project "${project.name}": ${err.message}`)
|
|
424
|
+
);
|
|
420
425
|
}
|
|
421
426
|
function addSkill(categoryId, name, prompt) {
|
|
422
427
|
const project = getProjectByCategoryId(categoryId);
|
|
423
428
|
if (!project) return;
|
|
424
429
|
project.skills[name] = prompt;
|
|
425
|
-
|
|
430
|
+
updateProject(project).catch(
|
|
431
|
+
(err) => console.error(`Failed to add skill "${name}" for project "${project.name}": ${err.message}`)
|
|
432
|
+
);
|
|
426
433
|
}
|
|
427
434
|
function removeSkill(categoryId, name) {
|
|
428
435
|
const project = getProjectByCategoryId(categoryId);
|
|
429
436
|
if (!project || !project.skills[name]) return false;
|
|
430
437
|
delete project.skills[name];
|
|
431
|
-
|
|
438
|
+
updateProject(project).catch(
|
|
439
|
+
(err) => console.error(`Failed to remove skill "${name}" for project "${project.name}": ${err.message}`)
|
|
440
|
+
);
|
|
432
441
|
return true;
|
|
433
442
|
}
|
|
434
443
|
function getSkills(categoryId) {
|
|
@@ -494,33 +503,75 @@ async function writeMcpJson(projectDir, servers) {
|
|
|
494
503
|
await writeFile(mcpPath, JSON.stringify(mcpConfig, null, 2), "utf-8");
|
|
495
504
|
}
|
|
496
505
|
|
|
497
|
-
// src/
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
506
|
+
// src/utils.ts
|
|
507
|
+
import { resolve, isAbsolute } from "path";
|
|
508
|
+
import { homedir } from "os";
|
|
509
|
+
function sanitizeName(name) {
|
|
510
|
+
return name.toLowerCase().replace(/[^a-z0-9-]/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "").slice(0, 50) || "session";
|
|
511
|
+
}
|
|
512
|
+
function resolvePath(p) {
|
|
513
|
+
if (p.startsWith("~/") || p === "~") {
|
|
514
|
+
return p.replace("~", homedir());
|
|
515
|
+
}
|
|
516
|
+
return isAbsolute(p) ? p : resolve(process.cwd(), p);
|
|
517
|
+
}
|
|
518
|
+
function formatDuration(ms) {
|
|
519
|
+
const s = Math.floor(ms / 1e3);
|
|
520
|
+
if (s < 60) return `${s}s`;
|
|
521
|
+
const m = Math.floor(s / 60);
|
|
522
|
+
if (m < 60) return `${m}m ${s % 60}s`;
|
|
523
|
+
const h = Math.floor(m / 60);
|
|
524
|
+
return `${h}h ${m % 60}m`;
|
|
525
|
+
}
|
|
526
|
+
function formatRelative(ts) {
|
|
527
|
+
const diff = Date.now() - ts;
|
|
528
|
+
if (diff < 6e4) return "just now";
|
|
529
|
+
if (diff < 36e5) return `${Math.floor(diff / 6e4)}m ago`;
|
|
530
|
+
if (diff < 864e5) return `${Math.floor(diff / 36e5)}h ago`;
|
|
531
|
+
return `${Math.floor(diff / 864e5)}d ago`;
|
|
532
|
+
}
|
|
533
|
+
function truncate(s, max) {
|
|
534
|
+
if (s.length <= max) return s;
|
|
535
|
+
return s.slice(0, max - 1) + "\u2026";
|
|
536
|
+
}
|
|
537
|
+
function isUserAllowed(userId, allowedUsers, allowAll) {
|
|
538
|
+
if (allowAll) return true;
|
|
539
|
+
if (allowedUsers.length === 0) return false;
|
|
540
|
+
return allowedUsers.includes(userId);
|
|
541
|
+
}
|
|
542
|
+
var ABORT_PATTERNS = ["abort", "cancel", "interrupt", "killed", "signal"];
|
|
543
|
+
function isAbortError(err) {
|
|
544
|
+
if (err instanceof Error && err.name === "AbortError") return true;
|
|
545
|
+
const msg = (err.message || "").toLowerCase();
|
|
546
|
+
return ABORT_PATTERNS.some((p) => msg.includes(p));
|
|
547
|
+
}
|
|
548
|
+
function formatUptime(startTime) {
|
|
549
|
+
const ms = Date.now() - startTime;
|
|
550
|
+
const seconds = Math.floor(ms / 1e3);
|
|
551
|
+
const minutes = Math.floor(seconds / 60);
|
|
552
|
+
const hours = Math.floor(minutes / 60);
|
|
553
|
+
const days = Math.floor(hours / 24);
|
|
554
|
+
if (days > 0) return `${days}d ${hours % 24}h`;
|
|
555
|
+
if (hours > 0) return `${hours}h ${minutes % 60}m`;
|
|
556
|
+
if (minutes > 0) return `${minutes}m`;
|
|
557
|
+
return `${seconds}s`;
|
|
558
|
+
}
|
|
507
559
|
|
|
508
|
-
|
|
509
|
-
{
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
560
|
+
// src/discord/session-message-context.ts
|
|
561
|
+
function buildDiscordSessionMessageContext() {
|
|
562
|
+
return [
|
|
563
|
+
"\u5F53\u524D\u4F1A\u8BDD\u4E2D\u7684\u6D88\u606F\u6765\u81EA Discord\u3002",
|
|
564
|
+
"\u6D88\u606F\u5305\u4E2D\u7684 [attachments] \u5757\u4F1A\u66B4\u9732 session_id\u3001message_id \u4E0E attachment_id\uFF0C\u8DB3\u4EE5\u6784\u6210 `workspacecord attachment fetch --session <session-id> --message <message-id> --attachment <attachment-id>` \u6216 `workspacecord attachment fetch --session <session-id> --message <message-id> --all`\u3002",
|
|
565
|
+
"\u9644\u4EF6\u9ED8\u8BA4\u4E0D\u81EA\u52A8\u4E0B\u8F7D\uFF0C\u4F60\u9996\u5148\u53EA\u4F1A\u770B\u5230\u9644\u4EF6\u6458\u8981\u3002",
|
|
566
|
+
"\u5982\u679C\u4F60\u9700\u8981\u67E5\u770B\u9644\u4EF6\u5185\u5BB9\uFF0C\u8BF7\u901A\u8FC7\u4E0A\u8FF0\u672C\u5730\u547D\u4EE4\u83B7\u53D6\u3002",
|
|
567
|
+
"\u6B63\u5E38\u56DE\u590D\u65F6\u4E0D\u9700\u8981\u53CD\u590D\u5F15\u7528\u6700\u65B0\u4E00\u6761 Discord \u6D88\u606F\u3002",
|
|
568
|
+
"\u957F\u4EFB\u52A1\u5B8C\u6210\u540E\uFF0C\u5FC5\u987B\u53D1\u9001\u65B0\u7684\u53EF\u89C1\u6D88\u606F\uFF0C\u4E0D\u8981\u53EA\u4F9D\u8D56\u7F16\u8F91\u65E7\u7684\u8FDB\u5EA6\u6D88\u606F\u3002"
|
|
569
|
+
].join(" ");
|
|
515
570
|
}
|
|
516
571
|
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
- If the worker stopped early, ask for the next concrete step instead of accepting the output.
|
|
521
|
-
- Use "blocked" only for true blockers the worker cannot resolve autonomously.
|
|
522
|
-
- Never ask the human for optional next steps.
|
|
523
|
-
- Output valid JSON and nothing else.`;
|
|
572
|
+
// src/session-registry.ts
|
|
573
|
+
import { existsSync as existsSync2 } from "fs";
|
|
574
|
+
import { sep } from "path";
|
|
524
575
|
var sessionStore = new Store("sessions.json");
|
|
525
576
|
var sessions = /* @__PURE__ */ new Map();
|
|
526
577
|
var idToChannelId = /* @__PURE__ */ new Map();
|
|
@@ -566,11 +617,17 @@ async function loadSessions() {
|
|
|
566
617
|
mode: s.mode ?? "auto",
|
|
567
618
|
subagentDepth: s.subagentDepth ?? 0,
|
|
568
619
|
type: s.type ?? "persistent",
|
|
620
|
+
codexSandboxMode: s.codexSandboxMode,
|
|
621
|
+
codexApprovalPolicy: s.codexApprovalPolicy,
|
|
622
|
+
codexBypass: s.codexBypass,
|
|
623
|
+
codexNetworkAccessEnabled: s.codexNetworkAccessEnabled,
|
|
624
|
+
codexWebSearchMode: s.codexWebSearchMode,
|
|
569
625
|
workflowState: s.workflowState ?? createDefaultWorkflowState(),
|
|
570
626
|
currentTurn: s.currentTurn ?? 0,
|
|
571
627
|
humanResolved: s.humanResolved ?? false,
|
|
572
628
|
currentInteractionMessageId: s.currentInteractionMessageId,
|
|
573
629
|
statusCardMessageId: s.statusCardMessageId,
|
|
630
|
+
lastInboundMessageId: s.lastInboundMessageId,
|
|
574
631
|
discoverySource: s.discoverySource ?? "discord",
|
|
575
632
|
lastObservedState: s.lastObservedState,
|
|
576
633
|
lastObservedEventKey: s.lastObservedEventKey,
|
|
@@ -611,6 +668,11 @@ async function persistSessionsNow() {
|
|
|
611
668
|
agentPersona: s.agentPersona,
|
|
612
669
|
verbose: s.verbose || false,
|
|
613
670
|
claudePermissionMode: s.claudePermissionMode,
|
|
671
|
+
codexSandboxMode: s.codexSandboxMode,
|
|
672
|
+
codexApprovalPolicy: s.codexApprovalPolicy,
|
|
673
|
+
codexBypass: s.codexBypass,
|
|
674
|
+
codexNetworkAccessEnabled: s.codexNetworkAccessEnabled,
|
|
675
|
+
codexWebSearchMode: s.codexWebSearchMode,
|
|
614
676
|
monitorGoal: s.monitorGoal,
|
|
615
677
|
monitorProviderSessionId: s.monitorProviderSessionId,
|
|
616
678
|
workflowState: s.workflowState,
|
|
@@ -622,6 +684,7 @@ async function persistSessionsNow() {
|
|
|
622
684
|
humanResolved: s.humanResolved,
|
|
623
685
|
currentInteractionMessageId: s.currentInteractionMessageId,
|
|
624
686
|
statusCardMessageId: s.statusCardMessageId,
|
|
687
|
+
lastInboundMessageId: s.lastInboundMessageId,
|
|
625
688
|
discoverySource: s.discoverySource,
|
|
626
689
|
lastObservedState: s.lastObservedState,
|
|
627
690
|
lastObservedEventKey: s.lastObservedEventKey,
|
|
@@ -672,6 +735,11 @@ async function createSession(params) {
|
|
|
672
735
|
subagentDepth = 0,
|
|
673
736
|
mode = config.defaultMode,
|
|
674
737
|
claudePermissionMode,
|
|
738
|
+
codexSandboxMode,
|
|
739
|
+
codexApprovalPolicy,
|
|
740
|
+
codexBypass,
|
|
741
|
+
codexNetworkAccessEnabled,
|
|
742
|
+
codexWebSearchMode,
|
|
675
743
|
discoverySource = "discord",
|
|
676
744
|
remoteHumanControl
|
|
677
745
|
} = params;
|
|
@@ -679,7 +747,6 @@ async function createSession(params) {
|
|
|
679
747
|
if (!existsSync2(resolvedDir)) {
|
|
680
748
|
throw new Error(`Directory does not exist: ${resolvedDir}`);
|
|
681
749
|
}
|
|
682
|
-
await ensureProvider(provider);
|
|
683
750
|
if (sessions.has(channelId)) {
|
|
684
751
|
throw new Error(`Session for channelId "${channelId}" already exists`);
|
|
685
752
|
}
|
|
@@ -706,6 +773,11 @@ async function createSession(params) {
|
|
|
706
773
|
agentPersona: void 0,
|
|
707
774
|
verbose: false,
|
|
708
775
|
claudePermissionMode,
|
|
776
|
+
codexSandboxMode,
|
|
777
|
+
codexApprovalPolicy,
|
|
778
|
+
codexBypass,
|
|
779
|
+
codexNetworkAccessEnabled,
|
|
780
|
+
codexWebSearchMode,
|
|
709
781
|
monitorGoal: void 0,
|
|
710
782
|
monitorProviderSessionId: void 0,
|
|
711
783
|
workflowState: createDefaultWorkflowState(),
|
|
@@ -718,6 +790,7 @@ async function createSession(params) {
|
|
|
718
790
|
humanResolved: false,
|
|
719
791
|
currentInteractionMessageId: void 0,
|
|
720
792
|
statusCardMessageId: void 0,
|
|
793
|
+
lastInboundMessageId: void 0,
|
|
721
794
|
discoverySource,
|
|
722
795
|
remoteHumanControl
|
|
723
796
|
};
|
|
@@ -767,17 +840,9 @@ function getSessionsByCategory(categoryId) {
|
|
|
767
840
|
function getAllSessions() {
|
|
768
841
|
return Array.from(sessions.values());
|
|
769
842
|
}
|
|
770
|
-
function getSessionByProviderSessionId(provider, providerSessionId) {
|
|
771
|
-
for (const session of sessions.values()) {
|
|
772
|
-
if (session.provider !== provider) continue;
|
|
773
|
-
if (!session.providerSessionId) continue;
|
|
774
|
-
if (session.providerSessionId === providerSessionId) return session;
|
|
775
|
-
}
|
|
776
|
-
return void 0;
|
|
777
|
-
}
|
|
778
843
|
function findCodexSessionForMonitor(providerSessionId, cwd) {
|
|
779
844
|
if (providerSessionId) {
|
|
780
|
-
const byProviderId =
|
|
845
|
+
const byProviderId = getSessionByProviderSession("codex", providerSessionId);
|
|
781
846
|
if (byProviderId) return byProviderId;
|
|
782
847
|
}
|
|
783
848
|
if (!cwd) return void 0;
|
|
@@ -837,6 +902,58 @@ function updateSession(sessionId, patch) {
|
|
|
837
902
|
Object.assign(session, patch);
|
|
838
903
|
debouncedSave();
|
|
839
904
|
}
|
|
905
|
+
async function updateSessionPermissions(sessionId, patch) {
|
|
906
|
+
const session = getSession(sessionId);
|
|
907
|
+
if (!session) {
|
|
908
|
+
throw new Error(`Session "${sessionId}" not found`);
|
|
909
|
+
}
|
|
910
|
+
Object.assign(session, patch);
|
|
911
|
+
session.lastActivity = Date.now();
|
|
912
|
+
await saveSessionsImmediate();
|
|
913
|
+
}
|
|
914
|
+
function resolveEffectiveClaudePermissionMode(session) {
|
|
915
|
+
return session.mode === "auto" ? "bypass" : session.claudePermissionMode ?? config.claudePermissionMode;
|
|
916
|
+
}
|
|
917
|
+
function resolveEffectiveCodexOptions(session) {
|
|
918
|
+
const bypass = session.codexBypass === true;
|
|
919
|
+
if (bypass) {
|
|
920
|
+
return {
|
|
921
|
+
sandboxMode: "danger-full-access",
|
|
922
|
+
approvalPolicy: "never",
|
|
923
|
+
networkAccessEnabled: true,
|
|
924
|
+
webSearchMode: "live",
|
|
925
|
+
bypass: true
|
|
926
|
+
};
|
|
927
|
+
}
|
|
928
|
+
return {
|
|
929
|
+
sandboxMode: session.codexSandboxMode ?? config.codexSandboxMode,
|
|
930
|
+
approvalPolicy: session.mode === "auto" ? "never" : session.codexApprovalPolicy ?? config.codexApprovalPolicy,
|
|
931
|
+
networkAccessEnabled: session.codexNetworkAccessEnabled ?? config.codexNetworkAccessEnabled,
|
|
932
|
+
webSearchMode: session.codexWebSearchMode ?? config.codexWebSearchMode,
|
|
933
|
+
bypass: false
|
|
934
|
+
};
|
|
935
|
+
}
|
|
936
|
+
function getSessionPermissionSummary(session) {
|
|
937
|
+
if (session.provider === "claude") {
|
|
938
|
+
return resolveEffectiveClaudePermissionMode(session);
|
|
939
|
+
}
|
|
940
|
+
const codex = resolveEffectiveCodexOptions(session);
|
|
941
|
+
if (codex.bypass) return "bypass";
|
|
942
|
+
return `${codex.sandboxMode} | ${codex.approvalPolicy} | net:${codex.networkAccessEnabled ? "on" : "off"} | search:${codex.webSearchMode}`;
|
|
943
|
+
}
|
|
944
|
+
function getSessionPermissionDetails(session) {
|
|
945
|
+
if (session.provider === "claude") {
|
|
946
|
+
return `Claude: ${resolveEffectiveClaudePermissionMode(session)}`;
|
|
947
|
+
}
|
|
948
|
+
const codex = resolveEffectiveCodexOptions(session);
|
|
949
|
+
return [
|
|
950
|
+
`sandbox=${codex.sandboxMode}`,
|
|
951
|
+
`approval=${codex.approvalPolicy}`,
|
|
952
|
+
`bypass=${codex.bypass ? "on" : "off"}`,
|
|
953
|
+
`network=${codex.networkAccessEnabled ? "on" : "off"}`,
|
|
954
|
+
`search=${codex.webSearchMode}`
|
|
955
|
+
].join(" | ");
|
|
956
|
+
}
|
|
840
957
|
function setStatusCardBinding(sessionId, binding) {
|
|
841
958
|
const session = getSession(sessionId);
|
|
842
959
|
if (!session) return;
|
|
@@ -928,6 +1045,81 @@ function resetWorkflowState(sessionId) {
|
|
|
928
1045
|
session.workflowState = createDefaultWorkflowState();
|
|
929
1046
|
debouncedSave();
|
|
930
1047
|
}
|
|
1048
|
+
function abortSession(sessionId) {
|
|
1049
|
+
return abortSessionWithReason(sessionId, "user");
|
|
1050
|
+
}
|
|
1051
|
+
function abortSessionWithReason(sessionId, reason) {
|
|
1052
|
+
const session = getSession(sessionId);
|
|
1053
|
+
if (!session) return false;
|
|
1054
|
+
const controller = sessionControllers.get(session.id);
|
|
1055
|
+
sessionAbortReasons.set(session.id, reason);
|
|
1056
|
+
if (controller) {
|
|
1057
|
+
controller.abort();
|
|
1058
|
+
}
|
|
1059
|
+
if (session.isGenerating) {
|
|
1060
|
+
session.isGenerating = false;
|
|
1061
|
+
sessionControllers.delete(session.id);
|
|
1062
|
+
debouncedSave();
|
|
1063
|
+
return true;
|
|
1064
|
+
}
|
|
1065
|
+
return !!controller;
|
|
1066
|
+
}
|
|
1067
|
+
function consumeAbortReason(sessionId) {
|
|
1068
|
+
const session = getSession(sessionId);
|
|
1069
|
+
if (!session) return void 0;
|
|
1070
|
+
const reason = sessionAbortReasons.get(session.id);
|
|
1071
|
+
sessionAbortReasons.delete(session.id);
|
|
1072
|
+
return reason;
|
|
1073
|
+
}
|
|
1074
|
+
function setSessionController(sessionId, controller) {
|
|
1075
|
+
sessionControllers.set(sessionId, controller);
|
|
1076
|
+
}
|
|
1077
|
+
function clearSessionController(sessionId) {
|
|
1078
|
+
sessionControllers.delete(sessionId);
|
|
1079
|
+
}
|
|
1080
|
+
function markSessionGenerating(sessionId, generating) {
|
|
1081
|
+
const session = getSession(sessionId);
|
|
1082
|
+
if (!session) return;
|
|
1083
|
+
session.isGenerating = generating;
|
|
1084
|
+
session.lastActivity = Date.now();
|
|
1085
|
+
if (!generating) {
|
|
1086
|
+
void saveSessionsImmediate();
|
|
1087
|
+
}
|
|
1088
|
+
}
|
|
1089
|
+
function saveSessionImmediate() {
|
|
1090
|
+
return saveSessionsImmediate();
|
|
1091
|
+
}
|
|
1092
|
+
function debouncedSaveSession() {
|
|
1093
|
+
debouncedSave();
|
|
1094
|
+
}
|
|
1095
|
+
|
|
1096
|
+
// src/thread-manager.ts
|
|
1097
|
+
var MODE_PROMPTS = {
|
|
1098
|
+
auto: "",
|
|
1099
|
+
plan: "You MUST use EnterPlanMode at the start of every task. Present your plan for user approval before making any code changes. Do not write or edit files until the user approves the plan.",
|
|
1100
|
+
normal: "Before performing destructive or significant operations (deleting files, running dangerous commands, making large refactors, writing to many files), use AskUserQuestion to confirm with the user first. Ask for explicit approval before proceeding with changes.",
|
|
1101
|
+
monitor: "This session is running in monitored autonomy mode. Treat the active user request as the task objective and keep working until it is fully satisfied. Do not stop at a partial implementation or ask the user for follow-up direction unless you are truly blocked by missing permissions, credentials, or required external information that you cannot obtain yourself. When you believe the task is complete, explain concisely what was finished and why it satisfies the request."
|
|
1102
|
+
};
|
|
1103
|
+
var MONITOR_SYSTEM_PROMPT = `You are a monitor agent supervising another coding agent.
|
|
1104
|
+
|
|
1105
|
+
Your job is to judge progress against the user's original request and decide whether the worker should continue.
|
|
1106
|
+
|
|
1107
|
+
Return JSON only in this schema:
|
|
1108
|
+
{
|
|
1109
|
+
"status": "complete" | "continue" | "blocked",
|
|
1110
|
+
"confidence": "high" | "medium" | "low",
|
|
1111
|
+
"rationale": "Short explanation tied to the original request",
|
|
1112
|
+
"steering": "Concrete next instructions for the worker. Empty string only when status is complete.",
|
|
1113
|
+
"completionSummary": "Short summary of what is complete. Empty string unless status is complete."
|
|
1114
|
+
}
|
|
1115
|
+
|
|
1116
|
+
Rules:
|
|
1117
|
+
- Favor continuing unless the task clearly satisfies the original request.
|
|
1118
|
+
- Judge against robustness, completeness, and the user's stated quality bar, not just whether some code changed.
|
|
1119
|
+
- If the worker stopped early, ask for the next concrete step instead of accepting the output.
|
|
1120
|
+
- Use "blocked" only for true blockers the worker cannot resolve autonomously.
|
|
1121
|
+
- Never ask the human for optional next steps.
|
|
1122
|
+
- Output valid JSON and nothing else.`;
|
|
931
1123
|
function buildSystemPromptParts(session) {
|
|
932
1124
|
const parts = [];
|
|
933
1125
|
const personality = getPersonality(session.categoryId);
|
|
@@ -938,6 +1130,7 @@ function buildSystemPromptParts(session) {
|
|
|
938
1130
|
}
|
|
939
1131
|
const modePrompt = MODE_PROMPTS[session.mode];
|
|
940
1132
|
if (modePrompt) parts.push(modePrompt);
|
|
1133
|
+
parts.push(buildDiscordSessionMessageContext());
|
|
941
1134
|
return parts;
|
|
942
1135
|
}
|
|
943
1136
|
function buildMonitorSystemPromptParts(session) {
|
|
@@ -945,20 +1138,21 @@ function buildMonitorSystemPromptParts(session) {
|
|
|
945
1138
|
const personality = getPersonality(session.categoryId);
|
|
946
1139
|
if (personality) parts.push(personality);
|
|
947
1140
|
parts.push(MONITOR_SYSTEM_PROMPT);
|
|
1141
|
+
parts.push(buildDiscordSessionMessageContext());
|
|
948
1142
|
return parts;
|
|
949
1143
|
}
|
|
950
1144
|
function buildProviderOptions(session, controller, isMonitor = false, runtimeOverrides = {}) {
|
|
951
|
-
const
|
|
1145
|
+
const effectiveCodex = resolveEffectiveCodexOptions(session);
|
|
952
1146
|
return {
|
|
953
1147
|
directory: session.directory,
|
|
954
1148
|
providerSessionId: isMonitor ? session.monitorProviderSessionId : session.providerSessionId,
|
|
955
1149
|
model: session.model,
|
|
956
|
-
sandboxMode:
|
|
957
|
-
approvalPolicy:
|
|
958
|
-
networkAccessEnabled:
|
|
959
|
-
webSearchMode:
|
|
1150
|
+
sandboxMode: effectiveCodex.sandboxMode,
|
|
1151
|
+
approvalPolicy: effectiveCodex.approvalPolicy,
|
|
1152
|
+
networkAccessEnabled: effectiveCodex.networkAccessEnabled,
|
|
1153
|
+
webSearchMode: effectiveCodex.webSearchMode,
|
|
960
1154
|
modelReasoningEffort: config.codexReasoningEffort || void 0,
|
|
961
|
-
claudePermissionMode:
|
|
1155
|
+
claudePermissionMode: resolveEffectiveClaudePermissionMode(session),
|
|
962
1156
|
systemPromptParts: isMonitor ? buildMonitorSystemPromptParts(session) : buildSystemPromptParts(session),
|
|
963
1157
|
abortController: controller,
|
|
964
1158
|
canUseTool: runtimeOverrides.canUseTool
|
|
@@ -969,33 +1163,39 @@ async function* sendPrompt(sessionId, prompt, runtimeOverrides = {}) {
|
|
|
969
1163
|
if (!session) throw new Error(`Session "${sessionId}" not found`);
|
|
970
1164
|
if (session.isGenerating) throw new Error("Session is already generating");
|
|
971
1165
|
const controller = new AbortController();
|
|
972
|
-
|
|
973
|
-
session.
|
|
974
|
-
session.lastActivity = Date.now();
|
|
1166
|
+
setSessionController(session.id, controller);
|
|
1167
|
+
markSessionGenerating(session.id, true);
|
|
975
1168
|
const provider = await ensureProvider(session.provider);
|
|
976
1169
|
try {
|
|
977
|
-
const stream = provider.sendPrompt(
|
|
1170
|
+
const stream = provider.sendPrompt(
|
|
1171
|
+
prompt,
|
|
1172
|
+
buildProviderOptions(session, controller, false, runtimeOverrides)
|
|
1173
|
+
);
|
|
978
1174
|
for await (const event of stream) {
|
|
979
1175
|
if (event.type === "session_init") {
|
|
980
|
-
|
|
981
|
-
|
|
1176
|
+
const s2 = getSession(sessionId);
|
|
1177
|
+
if (s2) {
|
|
1178
|
+
s2.providerSessionId = event.providerSessionId || void 0;
|
|
1179
|
+
debouncedSaveSession();
|
|
1180
|
+
}
|
|
982
1181
|
}
|
|
983
1182
|
if (event.type === "result") {
|
|
984
|
-
|
|
1183
|
+
const s2 = getSession(sessionId);
|
|
1184
|
+
if (s2) s2.totalCost += event.costUsd;
|
|
985
1185
|
}
|
|
986
1186
|
yield event;
|
|
987
1187
|
}
|
|
988
|
-
|
|
1188
|
+
const s = getSession(sessionId);
|
|
1189
|
+
if (s) s.messageCount++;
|
|
989
1190
|
} catch (err) {
|
|
990
1191
|
if (isAbortError(err)) {
|
|
991
1192
|
} else {
|
|
992
1193
|
throw err;
|
|
993
1194
|
}
|
|
994
1195
|
} finally {
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
await saveSessionsImmediate();
|
|
1196
|
+
markSessionGenerating(sessionId, false);
|
|
1197
|
+
clearSessionController(sessionId);
|
|
1198
|
+
await saveSessionImmediate();
|
|
999
1199
|
}
|
|
1000
1200
|
}
|
|
1001
1201
|
async function* continueSession(sessionId) {
|
|
@@ -1006,9 +1206,8 @@ async function* continueSessionWithOverrides(sessionId, runtimeOverrides = {}) {
|
|
|
1006
1206
|
if (!session) throw new Error(`Session "${sessionId}" not found`);
|
|
1007
1207
|
if (session.isGenerating) throw new Error("Session is already generating");
|
|
1008
1208
|
const controller = new AbortController();
|
|
1009
|
-
|
|
1010
|
-
session.
|
|
1011
|
-
session.lastActivity = Date.now();
|
|
1209
|
+
setSessionController(session.id, controller);
|
|
1210
|
+
markSessionGenerating(session.id, true);
|
|
1012
1211
|
const provider = await ensureProvider(session.provider);
|
|
1013
1212
|
try {
|
|
1014
1213
|
const stream = provider.continueSession(
|
|
@@ -1016,106 +1215,103 @@ async function* continueSessionWithOverrides(sessionId, runtimeOverrides = {}) {
|
|
|
1016
1215
|
);
|
|
1017
1216
|
for await (const event of stream) {
|
|
1018
1217
|
if (event.type === "session_init") {
|
|
1019
|
-
|
|
1020
|
-
|
|
1218
|
+
const s2 = getSession(sessionId);
|
|
1219
|
+
if (s2) {
|
|
1220
|
+
s2.providerSessionId = event.providerSessionId || void 0;
|
|
1221
|
+
debouncedSaveSession();
|
|
1222
|
+
}
|
|
1021
1223
|
}
|
|
1022
1224
|
if (event.type === "result") {
|
|
1023
|
-
|
|
1225
|
+
const s2 = getSession(sessionId);
|
|
1226
|
+
if (s2) s2.totalCost += event.costUsd;
|
|
1024
1227
|
}
|
|
1025
1228
|
yield event;
|
|
1026
1229
|
}
|
|
1027
|
-
|
|
1230
|
+
const s = getSession(sessionId);
|
|
1231
|
+
if (s) s.messageCount++;
|
|
1028
1232
|
} catch (err) {
|
|
1029
1233
|
if (isAbortError(err)) {
|
|
1030
1234
|
} else {
|
|
1031
1235
|
throw err;
|
|
1032
1236
|
}
|
|
1033
1237
|
} finally {
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
await saveSessionsImmediate();
|
|
1238
|
+
markSessionGenerating(sessionId, false);
|
|
1239
|
+
clearSessionController(sessionId);
|
|
1240
|
+
await saveSessionImmediate();
|
|
1038
1241
|
}
|
|
1039
1242
|
}
|
|
1040
1243
|
async function* sendMonitorPrompt(sessionId, prompt) {
|
|
1041
1244
|
const session = getSession(sessionId);
|
|
1042
1245
|
if (!session) throw new Error(`Session "${sessionId}" not found`);
|
|
1043
1246
|
const provider = await ensureProvider(session.provider);
|
|
1044
|
-
|
|
1247
|
+
const s = getSession(sessionId);
|
|
1248
|
+
if (s) s.lastActivity = Date.now();
|
|
1045
1249
|
const controller = new AbortController();
|
|
1046
1250
|
const stream = provider.sendPrompt(prompt, buildProviderOptions(session, controller, true));
|
|
1047
1251
|
for await (const event of stream) {
|
|
1048
1252
|
if (event.type === "session_init") {
|
|
1049
|
-
|
|
1050
|
-
|
|
1253
|
+
const cur2 = getSession(sessionId);
|
|
1254
|
+
if (cur2) {
|
|
1255
|
+
cur2.monitorProviderSessionId = event.providerSessionId || void 0;
|
|
1256
|
+
debouncedSaveSession();
|
|
1257
|
+
}
|
|
1051
1258
|
}
|
|
1052
1259
|
if (event.type === "result") {
|
|
1053
|
-
|
|
1260
|
+
const cur2 = getSession(sessionId);
|
|
1261
|
+
if (cur2) cur2.totalCost += event.costUsd;
|
|
1054
1262
|
}
|
|
1055
1263
|
yield event;
|
|
1056
1264
|
}
|
|
1057
|
-
|
|
1058
|
-
|
|
1265
|
+
const cur = getSession(sessionId);
|
|
1266
|
+
if (cur) cur.lastActivity = Date.now();
|
|
1267
|
+
debouncedSaveSession();
|
|
1059
1268
|
}
|
|
1060
|
-
function
|
|
1061
|
-
return
|
|
1062
|
-
}
|
|
1063
|
-
function abortSessionWithReason(sessionId, reason) {
|
|
1064
|
-
const session = getSession(sessionId);
|
|
1065
|
-
if (!session) return false;
|
|
1066
|
-
const controller = sessionControllers.get(session.id);
|
|
1067
|
-
sessionAbortReasons.set(session.id, reason);
|
|
1068
|
-
if (controller) {
|
|
1069
|
-
controller.abort();
|
|
1070
|
-
}
|
|
1071
|
-
if (session.isGenerating) {
|
|
1072
|
-
session.isGenerating = false;
|
|
1073
|
-
sessionControllers.delete(session.id);
|
|
1074
|
-
debouncedSave();
|
|
1075
|
-
return true;
|
|
1076
|
-
}
|
|
1077
|
-
return !!controller;
|
|
1078
|
-
}
|
|
1079
|
-
function consumeAbortReason(sessionId) {
|
|
1080
|
-
const session = getSession(sessionId);
|
|
1081
|
-
if (!session) return void 0;
|
|
1082
|
-
const reason = sessionAbortReasons.get(session.id);
|
|
1083
|
-
sessionAbortReasons.delete(session.id);
|
|
1084
|
-
return reason;
|
|
1269
|
+
function buildClaudeSubagentProviderSessionId(parentProviderSessionId, agentId) {
|
|
1270
|
+
return `subagent:${parentProviderSessionId}:${agentId}`;
|
|
1085
1271
|
}
|
|
1086
1272
|
function updateLocalObservation(sessionId, patch) {
|
|
1087
|
-
|
|
1273
|
+
updateSession(sessionId, {
|
|
1088
1274
|
discoverySource: patch.discoverySource,
|
|
1089
1275
|
lastObservedAt: Date.now(),
|
|
1090
|
-
lastObservedCwd: resolvePath(patch.cwd)
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
observationPatch.remoteHumanControl = patch.remoteHumanControl;
|
|
1094
|
-
}
|
|
1095
|
-
updateSession(sessionId, observationPatch);
|
|
1276
|
+
lastObservedCwd: resolvePath(patch.cwd),
|
|
1277
|
+
...patch.remoteHumanControl !== void 0 ? { remoteHumanControl: patch.remoteHumanControl } : {}
|
|
1278
|
+
});
|
|
1096
1279
|
}
|
|
1097
1280
|
async function registerLocalSession(params, guild) {
|
|
1098
|
-
const {
|
|
1099
|
-
|
|
1281
|
+
const {
|
|
1282
|
+
provider,
|
|
1283
|
+
providerSessionId,
|
|
1284
|
+
cwd,
|
|
1285
|
+
discoverySource,
|
|
1286
|
+
labelHint,
|
|
1287
|
+
remoteHumanControl,
|
|
1288
|
+
subagent
|
|
1289
|
+
} = params;
|
|
1290
|
+
const effectiveProviderSessionId = provider === "claude" && subagent?.parentProviderSessionId && subagent.agentId ? buildClaudeSubagentProviderSessionId(subagent.parentProviderSessionId, subagent.agentId) : providerSessionId;
|
|
1291
|
+
const effectiveAgentLabel = subagent?.agentType || labelHint || effectiveProviderSessionId.slice(0, 12);
|
|
1292
|
+
const { isArchivedProviderSession } = await import("./archive-manager-KMNAWQIN.js");
|
|
1293
|
+
if (isArchivedProviderSession(provider, effectiveProviderSessionId)) {
|
|
1294
|
+
console.log(
|
|
1295
|
+
`[registerLocalSession] Skip archived ${provider} session ${effectiveProviderSessionId} (source: ${discoverySource})`
|
|
1296
|
+
);
|
|
1297
|
+
return null;
|
|
1298
|
+
}
|
|
1299
|
+
const existing = getSessionByProviderSession(provider, effectiveProviderSessionId);
|
|
1100
1300
|
if (existing) {
|
|
1101
|
-
updateLocalObservation(existing.id, {
|
|
1102
|
-
discoverySource,
|
|
1103
|
-
cwd,
|
|
1104
|
-
remoteHumanControl
|
|
1105
|
-
});
|
|
1301
|
+
updateLocalObservation(existing.id, { discoverySource, cwd, remoteHumanControl });
|
|
1106
1302
|
return { session: existing, isNewlyCreated: false };
|
|
1107
1303
|
}
|
|
1108
|
-
const { getProjectByPath, getAllRegisteredProjects: getAllRegisteredProjects2 } = await import("./project-registry-
|
|
1109
|
-
const {
|
|
1110
|
-
const normalizedCwd =
|
|
1304
|
+
const { getProjectByPath, getAllRegisteredProjects: getAllRegisteredProjects2 } = await import("./project-registry-LL75XEUV.js");
|
|
1305
|
+
const { ChannelType, ThreadAutoArchiveDuration } = await import("discord.js");
|
|
1306
|
+
const normalizedCwd = resolvePath(cwd);
|
|
1111
1307
|
let project = getProjectByPath(normalizedCwd);
|
|
1112
1308
|
if (!project) {
|
|
1113
1309
|
const allProjects = getAllRegisteredProjects2();
|
|
1114
1310
|
let bestMatch;
|
|
1115
1311
|
let bestMatchPathLength = -1;
|
|
1116
1312
|
for (const p of allProjects) {
|
|
1117
|
-
const projectPath =
|
|
1118
|
-
if (normalizedCwd.startsWith(projectPath +
|
|
1313
|
+
const projectPath = resolvePath(p.path);
|
|
1314
|
+
if (normalizedCwd.startsWith(projectPath + sep2) && projectPath.length > bestMatchPathLength) {
|
|
1119
1315
|
bestMatch = p;
|
|
1120
1316
|
bestMatchPathLength = projectPath.length;
|
|
1121
1317
|
}
|
|
@@ -1128,7 +1324,6 @@ async function registerLocalSession(params, guild) {
|
|
|
1128
1324
|
);
|
|
1129
1325
|
return null;
|
|
1130
1326
|
}
|
|
1131
|
-
const { ChannelType } = await import("discord.js");
|
|
1132
1327
|
const category = guild.channels.cache.get(project.discordCategoryId);
|
|
1133
1328
|
if (!category || category.type !== ChannelType.GuildCategory) {
|
|
1134
1329
|
console.warn(
|
|
@@ -1136,26 +1331,73 @@ async function registerLocalSession(params, guild) {
|
|
|
1136
1331
|
);
|
|
1137
1332
|
return null;
|
|
1138
1333
|
}
|
|
1139
|
-
|
|
1334
|
+
if (subagent?.parentProviderSessionId) {
|
|
1335
|
+
const parentSession = getSessionByProviderSession(provider, subagent.parentProviderSessionId);
|
|
1336
|
+
if (!parentSession) {
|
|
1337
|
+
console.warn(
|
|
1338
|
+
`[registerLocalSession] Delaying subagent ${provider} session ${providerSessionId}: parent provider session ${subagent.parentProviderSessionId} not registered yet`
|
|
1339
|
+
);
|
|
1340
|
+
return null;
|
|
1341
|
+
}
|
|
1342
|
+
const parentChannel = guild.channels.cache.get(parentSession.channelId);
|
|
1343
|
+
const threadHostChannel = parentChannel?.type === ChannelType.GuildText ? parentChannel : parentChannel?.isThread?.() || parentChannel?.type === ChannelType.PublicThread ? parentChannel.parent : void 0;
|
|
1344
|
+
if (threadHostChannel?.type !== ChannelType.GuildText) {
|
|
1345
|
+
console.warn(
|
|
1346
|
+
`[registerLocalSession] Delaying subagent ${provider} session ${providerSessionId}: parent channel ${parentSession.channelId} is unavailable`
|
|
1347
|
+
);
|
|
1348
|
+
return null;
|
|
1349
|
+
}
|
|
1350
|
+
const normalizedThreadName = `[sub:${provider}] ${effectiveAgentLabel}`.slice(0, 100);
|
|
1351
|
+
const thread = await threadHostChannel.threads.create({
|
|
1352
|
+
name: normalizedThreadName,
|
|
1353
|
+
type: ChannelType.PublicThread,
|
|
1354
|
+
autoArchiveDuration: ThreadAutoArchiveDuration.OneHour,
|
|
1355
|
+
reason: `Auto-registered subagent session ${effectiveProviderSessionId}`
|
|
1356
|
+
});
|
|
1357
|
+
const session2 = await createSession({
|
|
1358
|
+
channelId: thread.id,
|
|
1359
|
+
categoryId: parentSession.categoryId,
|
|
1360
|
+
projectName: parentSession.projectName,
|
|
1361
|
+
agentLabel: effectiveAgentLabel,
|
|
1362
|
+
provider,
|
|
1363
|
+
providerSessionId: effectiveProviderSessionId,
|
|
1364
|
+
directory: normalizedCwd,
|
|
1365
|
+
type: "subagent",
|
|
1366
|
+
parentChannelId: parentSession.type === "subagent" ? parentSession.parentChannelId ?? threadHostChannel.id : parentSession.channelId,
|
|
1367
|
+
subagentDepth: Math.max(1, subagent.depth ?? parentSession.subagentDepth + 1),
|
|
1368
|
+
discoverySource,
|
|
1369
|
+
remoteHumanControl: remoteHumanControl ?? false
|
|
1370
|
+
});
|
|
1371
|
+
updateLocalObservation(session2.id, {
|
|
1372
|
+
discoverySource,
|
|
1373
|
+
cwd: normalizedCwd,
|
|
1374
|
+
remoteHumanControl: remoteHumanControl ?? false
|
|
1375
|
+
});
|
|
1376
|
+
console.log(
|
|
1377
|
+
`[registerLocalSession] Registered subagent ${provider} session ${effectiveProviderSessionId} (source: ${discoverySource}, parent: ${parentSession.channelId}, thread: ${thread.id})`
|
|
1378
|
+
);
|
|
1379
|
+
return { session: session2, isNewlyCreated: true };
|
|
1380
|
+
}
|
|
1381
|
+
const base = labelHint ? labelHint.toLowerCase().replace(/[^a-z0-9-]/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "").slice(0, 60) : effectiveProviderSessionId.slice(0, 12);
|
|
1140
1382
|
const channelName = `${provider}-${base}`.slice(0, 100);
|
|
1141
1383
|
let channel = category.children.cache.find(
|
|
1142
|
-
(ch) => ch.type === ChannelType.GuildText && typeof ch.topic === "string" && ch.topic.includes(`Provider Session: ${
|
|
1384
|
+
(ch) => ch.type === ChannelType.GuildText && typeof ch.topic === "string" && ch.topic.includes(`Provider Session: ${effectiveProviderSessionId}`)
|
|
1143
1385
|
);
|
|
1144
1386
|
if (!channel) {
|
|
1145
1387
|
channel = await guild.channels.create({
|
|
1146
1388
|
name: channelName,
|
|
1147
1389
|
type: ChannelType.GuildText,
|
|
1148
1390
|
parent: category.id,
|
|
1149
|
-
topic: `${provider} session (local) | Provider Session: ${
|
|
1391
|
+
topic: `${provider} session (local) | Provider Session: ${effectiveProviderSessionId}`
|
|
1150
1392
|
});
|
|
1151
1393
|
}
|
|
1152
1394
|
const session = await createSession({
|
|
1153
1395
|
channelId: channel.id,
|
|
1154
1396
|
categoryId: project.discordCategoryId,
|
|
1155
1397
|
projectName: project.name,
|
|
1156
|
-
agentLabel:
|
|
1398
|
+
agentLabel: effectiveAgentLabel,
|
|
1157
1399
|
provider,
|
|
1158
|
-
providerSessionId,
|
|
1400
|
+
providerSessionId: effectiveProviderSessionId,
|
|
1159
1401
|
directory: normalizedCwd,
|
|
1160
1402
|
type: "persistent",
|
|
1161
1403
|
discoverySource,
|
|
@@ -1167,7 +1409,7 @@ async function registerLocalSession(params, guild) {
|
|
|
1167
1409
|
remoteHumanControl: remoteHumanControl ?? false
|
|
1168
1410
|
});
|
|
1169
1411
|
console.log(
|
|
1170
|
-
`[registerLocalSession] Registered ${provider} session ${
|
|
1412
|
+
`[registerLocalSession] Registered ${provider} session ${effectiveProviderSessionId} (source: ${discoverySource}, channel: ${channel.id})`
|
|
1171
1413
|
);
|
|
1172
1414
|
return { session, isNewlyCreated: true };
|
|
1173
1415
|
}
|
|
@@ -1187,6 +1429,12 @@ export {
|
|
|
1187
1429
|
addMcpServer,
|
|
1188
1430
|
removeMcpServer,
|
|
1189
1431
|
getMcpServers,
|
|
1432
|
+
formatDuration,
|
|
1433
|
+
formatRelative,
|
|
1434
|
+
truncate,
|
|
1435
|
+
isUserAllowed,
|
|
1436
|
+
isAbortError,
|
|
1437
|
+
formatUptime,
|
|
1190
1438
|
loadSessions,
|
|
1191
1439
|
createSession,
|
|
1192
1440
|
getSession,
|
|
@@ -1196,12 +1444,16 @@ export {
|
|
|
1196
1444
|
getSessionByProviderSession,
|
|
1197
1445
|
getSessionsByCategory,
|
|
1198
1446
|
getAllSessions,
|
|
1199
|
-
getSessionByProviderSessionId,
|
|
1200
1447
|
findCodexSessionForMonitor,
|
|
1201
1448
|
findCodexSessionByProviderSessionId,
|
|
1202
1449
|
findCodexSessionByCwd,
|
|
1203
1450
|
resolveCodexSessionFromMonitor,
|
|
1204
1451
|
updateSession,
|
|
1452
|
+
updateSessionPermissions,
|
|
1453
|
+
resolveEffectiveClaudePermissionMode,
|
|
1454
|
+
resolveEffectiveCodexOptions,
|
|
1455
|
+
getSessionPermissionSummary,
|
|
1456
|
+
getSessionPermissionDetails,
|
|
1205
1457
|
setStatusCardBinding,
|
|
1206
1458
|
setCurrentInteractionMessage,
|
|
1207
1459
|
endSession,
|
|
@@ -1212,13 +1464,14 @@ export {
|
|
|
1212
1464
|
setMonitorGoal,
|
|
1213
1465
|
updateWorkflowState,
|
|
1214
1466
|
resetWorkflowState,
|
|
1467
|
+
abortSession,
|
|
1468
|
+
abortSessionWithReason,
|
|
1469
|
+
consumeAbortReason,
|
|
1215
1470
|
sendPrompt,
|
|
1216
1471
|
continueSession,
|
|
1217
1472
|
continueSessionWithOverrides,
|
|
1218
1473
|
sendMonitorPrompt,
|
|
1219
|
-
|
|
1220
|
-
abortSessionWithReason,
|
|
1221
|
-
consumeAbortReason,
|
|
1474
|
+
buildClaudeSubagentProviderSessionId,
|
|
1222
1475
|
updateLocalObservation,
|
|
1223
1476
|
registerLocalSession
|
|
1224
1477
|
};
|