discord-agent-bridge 0.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/LICENSE +21 -0
- package/README.md +195 -0
- package/dist/app.js +210 -0
- package/dist/app.js.map +1 -0
- package/dist/app.test.js +117 -0
- package/dist/app.test.js.map +1 -0
- package/dist/cli.js +63 -0
- package/dist/cli.js.map +1 -0
- package/dist/cli.test.js +91 -0
- package/dist/cli.test.js.map +1 -0
- package/dist/core/auditLog.js +65 -0
- package/dist/core/auditLog.js.map +1 -0
- package/dist/core/auditLog.test.js +124 -0
- package/dist/core/auditLog.test.js.map +1 -0
- package/dist/core/auth.js +106 -0
- package/dist/core/auth.js.map +1 -0
- package/dist/core/auth.test.js +216 -0
- package/dist/core/auth.test.js.map +1 -0
- package/dist/core/channelRegistry.js +119 -0
- package/dist/core/channelRegistry.js.map +1 -0
- package/dist/core/channelRegistry.test.js +114 -0
- package/dist/core/channelRegistry.test.js.map +1 -0
- package/dist/core/commandPolicy.js +6 -0
- package/dist/core/commandPolicy.js.map +1 -0
- package/dist/core/commandRouter.js +9 -0
- package/dist/core/commandRouter.js.map +1 -0
- package/dist/core/config.js +141 -0
- package/dist/core/config.js.map +1 -0
- package/dist/core/config.test.js +149 -0
- package/dist/core/config.test.js.map +1 -0
- package/dist/core/configResolver.js +90 -0
- package/dist/core/configResolver.js.map +1 -0
- package/dist/core/configResolver.test.js +138 -0
- package/dist/core/configResolver.test.js.map +1 -0
- package/dist/core/configSchema.js +164 -0
- package/dist/core/configSchema.js.map +1 -0
- package/dist/core/contracts.js +5 -0
- package/dist/core/contracts.js.map +1 -0
- package/dist/core/eventBus.js +42 -0
- package/dist/core/eventBus.js.map +1 -0
- package/dist/core/eventBus.test.js +72 -0
- package/dist/core/eventBus.test.js.map +1 -0
- package/dist/core/hookBridge.js +11 -0
- package/dist/core/hookBridge.js.map +1 -0
- package/dist/core/logger.js +116 -0
- package/dist/core/logger.js.map +1 -0
- package/dist/core/logger.test.js +88 -0
- package/dist/core/logger.test.js.map +1 -0
- package/dist/core/modeRegistry.js +33 -0
- package/dist/core/modeRegistry.js.map +1 -0
- package/dist/core/permissionResolver.js +43 -0
- package/dist/core/permissionResolver.js.map +1 -0
- package/dist/core/permissionResolver.test.js +136 -0
- package/dist/core/permissionResolver.test.js.map +1 -0
- package/dist/core/providerCatalog.js +240 -0
- package/dist/core/providerCatalog.js.map +1 -0
- package/dist/core/providerCatalog.test.js +230 -0
- package/dist/core/providerCatalog.test.js.map +1 -0
- package/dist/core/sessionOrchestrator.js +463 -0
- package/dist/core/sessionOrchestrator.js.map +1 -0
- package/dist/core/sessionOrchestrator.test.js +344 -0
- package/dist/core/sessionOrchestrator.test.js.map +1 -0
- package/dist/core/state/schema.js +49 -0
- package/dist/core/state/schema.js.map +1 -0
- package/dist/core/state/store.js +86 -0
- package/dist/core/state/store.js.map +1 -0
- package/dist/core/state/store.test.js +99 -0
- package/dist/core/state/store.test.js.map +1 -0
- package/dist/core/usageService.js +310 -0
- package/dist/core/usageService.js.map +1 -0
- package/dist/core/usageService.test.js +234 -0
- package/dist/core/usageService.test.js.map +1 -0
- package/dist/discord/alwaysAllow.test.js +181 -0
- package/dist/discord/alwaysAllow.test.js.map +1 -0
- package/dist/discord/client.js +666 -0
- package/dist/discord/client.js.map +1 -0
- package/dist/discord/client.test.js +256 -0
- package/dist/discord/client.test.js.map +1 -0
- package/dist/discord/configPanel.js +270 -0
- package/dist/discord/configPanel.js.map +1 -0
- package/dist/discord/configPanel.test.js +332 -0
- package/dist/discord/configPanel.test.js.map +1 -0
- package/dist/discord/directoryBrowser.js +151 -0
- package/dist/discord/directoryBrowser.js.map +1 -0
- package/dist/discord/directoryBrowser.test.js +163 -0
- package/dist/discord/directoryBrowser.test.js.map +1 -0
- package/dist/discord/favorites.js +10 -0
- package/dist/discord/favorites.js.map +1 -0
- package/dist/discord/fileDownload.js +94 -0
- package/dist/discord/fileDownload.js.map +1 -0
- package/dist/discord/fileDownload.test.js +59 -0
- package/dist/discord/fileDownload.test.js.map +1 -0
- package/dist/discord/format.js +104 -0
- package/dist/discord/format.js.map +1 -0
- package/dist/discord/format.test.js +40 -0
- package/dist/discord/format.test.js.map +1 -0
- package/dist/discord/guildChannels.js +97 -0
- package/dist/discord/guildChannels.js.map +1 -0
- package/dist/discord/guildChannels.test.js +231 -0
- package/dist/discord/guildChannels.test.js.map +1 -0
- package/dist/discord/i18n.js +207 -0
- package/dist/discord/i18n.js.map +1 -0
- package/dist/discord/i18n.test.js +31 -0
- package/dist/discord/i18n.test.js.map +1 -0
- package/dist/discord/interactionRouter.js +954 -0
- package/dist/discord/interactionRouter.js.map +1 -0
- package/dist/discord/interactionRouter.test.js +1245 -0
- package/dist/discord/interactionRouter.test.js.map +1 -0
- package/dist/discord/messageRouter.js +221 -0
- package/dist/discord/messageRouter.js.map +1 -0
- package/dist/discord/messageRouter.test.js +360 -0
- package/dist/discord/messageRouter.test.js.map +1 -0
- package/dist/discord/ports.js +12 -0
- package/dist/discord/ports.js.map +1 -0
- package/dist/discord/renderers/defaultSet.test.js +97 -0
- package/dist/discord/renderers/defaultSet.test.js.map +1 -0
- package/dist/discord/renderers/diffView.js +73 -0
- package/dist/discord/renderers/diffView.js.map +1 -0
- package/dist/discord/renderers/diffView.test.js +54 -0
- package/dist/discord/renderers/diffView.test.js.map +1 -0
- package/dist/discord/renderers/index.js +143 -0
- package/dist/discord/renderers/index.js.map +1 -0
- package/dist/discord/renderers/index.test.js +124 -0
- package/dist/discord/renderers/index.test.js.map +1 -0
- package/dist/discord/renderers/mentionOnComplete.js +19 -0
- package/dist/discord/renderers/mentionOnComplete.js.map +1 -0
- package/dist/discord/renderers/mentionOnComplete.test.js +35 -0
- package/dist/discord/renderers/mentionOnComplete.test.js.map +1 -0
- package/dist/discord/renderers/permissionButtons.js +150 -0
- package/dist/discord/renderers/permissionButtons.js.map +1 -0
- package/dist/discord/renderers/permissionButtons.test.js +108 -0
- package/dist/discord/renderers/permissionButtons.test.js.map +1 -0
- package/dist/discord/renderers/resultLine.js +25 -0
- package/dist/discord/renderers/resultLine.js.map +1 -0
- package/dist/discord/renderers/statusEmbed.js +20 -0
- package/dist/discord/renderers/statusEmbed.js.map +1 -0
- package/dist/discord/renderers/statusEmbed.test.js +32 -0
- package/dist/discord/renderers/statusEmbed.test.js.map +1 -0
- package/dist/discord/renderers/streamEmbed.js +134 -0
- package/dist/discord/renderers/streamEmbed.js.map +1 -0
- package/dist/discord/renderers/streamEmbed.test.js +97 -0
- package/dist/discord/renderers/streamEmbed.test.js.map +1 -0
- package/dist/discord/renderers/toolThread.js +65 -0
- package/dist/discord/renderers/toolThread.js.map +1 -0
- package/dist/discord/renderers/toolThread.test.js +54 -0
- package/dist/discord/renderers/toolThread.test.js.map +1 -0
- package/dist/discord/renderers/transcriptFeed.js +33 -0
- package/dist/discord/renderers/transcriptFeed.js.map +1 -0
- package/dist/discord/renderers/usageEmbed.js +78 -0
- package/dist/discord/renderers/usageEmbed.js.map +1 -0
- package/dist/discord/renderers/usageEmbed.test.js +42 -0
- package/dist/discord/renderers/usageEmbed.test.js.map +1 -0
- package/dist/discord/wiring.js +214 -0
- package/dist/discord/wiring.js.map +1 -0
- package/dist/discord/wiring.test.js +252 -0
- package/dist/discord/wiring.test.js.map +1 -0
- package/dist/discord/wizard/channelWizard.js +305 -0
- package/dist/discord/wizard/channelWizard.js.map +1 -0
- package/dist/discord/wizard/channelWizard.test.js +298 -0
- package/dist/discord/wizard/channelWizard.test.js.map +1 -0
- package/dist/discord/wizard/resumeWizard.js +123 -0
- package/dist/discord/wizard/resumeWizard.js.map +1 -0
- package/dist/modes/claude/index.js +80 -0
- package/dist/modes/claude/index.js.map +1 -0
- package/dist/modes/claude/listResumable.test.js +72 -0
- package/dist/modes/claude/listResumable.test.js.map +1 -0
- package/dist/modes/claude/mcpFileTool.js +82 -0
- package/dist/modes/claude/mcpFileTool.js.map +1 -0
- package/dist/modes/claude/permissions.js +35 -0
- package/dist/modes/claude/permissions.js.map +1 -0
- package/dist/modes/claude/plugins.js +56 -0
- package/dist/modes/claude/plugins.js.map +1 -0
- package/dist/modes/claude/session.js +324 -0
- package/dist/modes/claude/session.js.map +1 -0
- package/dist/modes/claude/session.test.js +415 -0
- package/dist/modes/claude/session.test.js.map +1 -0
- package/dist/modes/codex/discovery.js +221 -0
- package/dist/modes/codex/discovery.js.map +1 -0
- package/dist/modes/codex/discovery.test.js +213 -0
- package/dist/modes/codex/discovery.test.js.map +1 -0
- package/dist/modes/codex/eventMapper.js +262 -0
- package/dist/modes/codex/eventMapper.js.map +1 -0
- package/dist/modes/codex/index.js +132 -0
- package/dist/modes/codex/index.js.map +1 -0
- package/dist/modes/codex/index.test.js +170 -0
- package/dist/modes/codex/index.test.js.map +1 -0
- package/dist/modes/codex/runner.js +207 -0
- package/dist/modes/codex/runner.js.map +1 -0
- package/dist/modes/codex/runner.test.js +587 -0
- package/dist/modes/codex/runner.test.js.map +1 -0
- package/dist/modes/codex/sqliteReader.js +171 -0
- package/dist/modes/codex/sqliteReader.js.map +1 -0
- package/dist/modes/codex/sqliteReader.test.js +137 -0
- package/dist/modes/codex/sqliteReader.test.js.map +1 -0
- package/dist/setup/wizard.js +115 -0
- package/dist/setup/wizard.js.map +1 -0
- package/dist/setup/wizard.test.js +216 -0
- package/dist/setup/wizard.test.js.map +1 -0
- package/dist/startBot.test.js +78 -0
- package/dist/startBot.test.js.map +1 -0
- package/package.json +58 -0
|
@@ -0,0 +1,463 @@
|
|
|
1
|
+
import * as fs from 'node:fs';
|
|
2
|
+
import * as path from 'node:path';
|
|
3
|
+
// Default: deny, so an unwired permission prompt fails safe rather than
|
|
4
|
+
// auto-approving a tool the operator never saw (§7.5, deny-by-default).
|
|
5
|
+
const denyByDefault = async () => ({
|
|
6
|
+
behavior: 'deny',
|
|
7
|
+
message: 'Permission prompts are not wired yet; denying by default.',
|
|
8
|
+
});
|
|
9
|
+
function channelKey(guildId, channelId) {
|
|
10
|
+
return `${guildId}:${channelId}`;
|
|
11
|
+
}
|
|
12
|
+
export class SessionOrchestrator {
|
|
13
|
+
channelRegistry;
|
|
14
|
+
modeRegistry;
|
|
15
|
+
eventBus;
|
|
16
|
+
configResolver;
|
|
17
|
+
permissionResolver;
|
|
18
|
+
auditLog;
|
|
19
|
+
logger;
|
|
20
|
+
requestPermission;
|
|
21
|
+
// Live sessions keyed by "<guildId>:<channelId>". This is the in-memory
|
|
22
|
+
// counterpart to the persisted ChannelRegistry binding; resumeAll() rebuilds
|
|
23
|
+
// it on boot (fixes A2).
|
|
24
|
+
active = new Map();
|
|
25
|
+
constructor(deps) {
|
|
26
|
+
this.channelRegistry = deps.channelRegistry;
|
|
27
|
+
this.modeRegistry = deps.modeRegistry;
|
|
28
|
+
this.eventBus = deps.eventBus;
|
|
29
|
+
this.configResolver = deps.configResolver;
|
|
30
|
+
this.permissionResolver = deps.permissionResolver;
|
|
31
|
+
this.auditLog = deps.auditLog;
|
|
32
|
+
this.logger = deps.logger;
|
|
33
|
+
this.requestPermission = deps.requestPermission ?? denyByDefault;
|
|
34
|
+
}
|
|
35
|
+
// §9 step 1. Resolve effective config + permission, start a fresh mode
|
|
36
|
+
// session, persist the binding, and track it live. Returns the ModeSession.
|
|
37
|
+
async start(params) {
|
|
38
|
+
const { guildId, channelId, mode, cwd, ownerId } = params;
|
|
39
|
+
const perm = this.permissionResolver.resolve(guildId, channelId, {
|
|
40
|
+
...(params.permMode !== undefined ? { permMode: params.permMode } : {}),
|
|
41
|
+
...(params.profile !== undefined ? { profile: params.profile } : {}),
|
|
42
|
+
});
|
|
43
|
+
const agentMode = this.modeRegistry.get(mode);
|
|
44
|
+
const ctx = this.buildContext({
|
|
45
|
+
guildId,
|
|
46
|
+
channelId,
|
|
47
|
+
cwd,
|
|
48
|
+
ownerId,
|
|
49
|
+
mode,
|
|
50
|
+
permMode: perm.permMode,
|
|
51
|
+
allowedTools: perm.allowedTools,
|
|
52
|
+
...(params.effort !== undefined ? { effort: params.effort } : {}),
|
|
53
|
+
});
|
|
54
|
+
const session = await agentMode.start(ctx);
|
|
55
|
+
// Persist the binding (source of truth for resume-on-boot) then track live.
|
|
56
|
+
this.channelRegistry.set({
|
|
57
|
+
guildId,
|
|
58
|
+
channelId,
|
|
59
|
+
mode: mode,
|
|
60
|
+
sessionId: session.sessionId,
|
|
61
|
+
cwd,
|
|
62
|
+
ownerId,
|
|
63
|
+
permMode: perm.permMode,
|
|
64
|
+
profile: perm.profile,
|
|
65
|
+
});
|
|
66
|
+
this.active.set(channelKey(guildId, channelId), {
|
|
67
|
+
guildId,
|
|
68
|
+
channelId,
|
|
69
|
+
mode,
|
|
70
|
+
cwd,
|
|
71
|
+
ownerId,
|
|
72
|
+
permMode: perm.permMode,
|
|
73
|
+
session,
|
|
74
|
+
queue: [],
|
|
75
|
+
running: false,
|
|
76
|
+
});
|
|
77
|
+
this.auditLog.record({
|
|
78
|
+
actorId: ownerId,
|
|
79
|
+
roleTier: 'execute',
|
|
80
|
+
guildId,
|
|
81
|
+
channelId,
|
|
82
|
+
action: 'start',
|
|
83
|
+
mode,
|
|
84
|
+
permMode: perm.permMode,
|
|
85
|
+
cwd,
|
|
86
|
+
status: 'ok',
|
|
87
|
+
});
|
|
88
|
+
this.logger.info('session started', { guildId, channelId, mode, cwd });
|
|
89
|
+
return session;
|
|
90
|
+
}
|
|
91
|
+
// §9 on-demand resume. Rebind a channel to an EXISTING backend session id (chosen
|
|
92
|
+
// in the resume UX), mirroring start() but calling agentMode.resume(ctx, sessionId)
|
|
93
|
+
// instead of start(ctx). Resolves the layered config + permission, persists the
|
|
94
|
+
// binding (source of truth for resume-on-boot), tracks it live, and audits. Used by
|
|
95
|
+
// the Discord layer's "Resume Session" flow (distinct from resumeAll(), which
|
|
96
|
+
// rebinds every persisted channel on boot). Returns the ModeSession.
|
|
97
|
+
async resume(params, sessionId) {
|
|
98
|
+
const { guildId, channelId, mode, cwd, ownerId } = params;
|
|
99
|
+
const perm = this.permissionResolver.resolve(guildId, channelId, {
|
|
100
|
+
...(params.permMode !== undefined ? { permMode: params.permMode } : {}),
|
|
101
|
+
...(params.profile !== undefined ? { profile: params.profile } : {}),
|
|
102
|
+
});
|
|
103
|
+
const agentMode = this.modeRegistry.get(mode);
|
|
104
|
+
const ctx = this.buildContext({
|
|
105
|
+
guildId,
|
|
106
|
+
channelId,
|
|
107
|
+
cwd,
|
|
108
|
+
ownerId,
|
|
109
|
+
mode,
|
|
110
|
+
permMode: perm.permMode,
|
|
111
|
+
allowedTools: perm.allowedTools,
|
|
112
|
+
...(params.effort !== undefined ? { effort: params.effort } : {}),
|
|
113
|
+
});
|
|
114
|
+
const session = await agentMode.resume(ctx, sessionId);
|
|
115
|
+
this.channelRegistry.set({
|
|
116
|
+
guildId,
|
|
117
|
+
channelId,
|
|
118
|
+
mode: mode,
|
|
119
|
+
sessionId: session.sessionId ?? sessionId,
|
|
120
|
+
cwd,
|
|
121
|
+
ownerId,
|
|
122
|
+
permMode: perm.permMode,
|
|
123
|
+
profile: perm.profile,
|
|
124
|
+
});
|
|
125
|
+
this.active.set(channelKey(guildId, channelId), {
|
|
126
|
+
guildId,
|
|
127
|
+
channelId,
|
|
128
|
+
mode,
|
|
129
|
+
cwd,
|
|
130
|
+
ownerId,
|
|
131
|
+
permMode: perm.permMode,
|
|
132
|
+
session,
|
|
133
|
+
queue: [],
|
|
134
|
+
running: false,
|
|
135
|
+
});
|
|
136
|
+
this.auditLog.record({
|
|
137
|
+
actorId: ownerId,
|
|
138
|
+
roleTier: 'execute',
|
|
139
|
+
guildId,
|
|
140
|
+
channelId,
|
|
141
|
+
action: 'resume',
|
|
142
|
+
mode,
|
|
143
|
+
permMode: perm.permMode,
|
|
144
|
+
cwd,
|
|
145
|
+
status: 'ok',
|
|
146
|
+
});
|
|
147
|
+
this.logger.info('session resumed', { guildId, channelId, mode, sessionId });
|
|
148
|
+
return session;
|
|
149
|
+
}
|
|
150
|
+
// §9 step 2. Enqueue a user turn. If a turn is already in flight for this
|
|
151
|
+
// channel it is queued (never dropped, fixing A4) and processed strictly in
|
|
152
|
+
// arrival order once the current turn completes. Files are realpath-confined
|
|
153
|
+
// to the session workspace before the turn reaches the mode (§7.5); a turn
|
|
154
|
+
// whose file escapes the workspace is rejected outright (an error event is
|
|
155
|
+
// emitted and the turn is not sent).
|
|
156
|
+
async send(guildId, channelId, turn) {
|
|
157
|
+
const key = channelKey(guildId, channelId);
|
|
158
|
+
const channel = this.active.get(key);
|
|
159
|
+
if (!channel) {
|
|
160
|
+
throw new Error(`No active session for channel ${key}. Run /agent start first.`);
|
|
161
|
+
}
|
|
162
|
+
const violation = this.findConfinementViolation(channel.cwd, turn);
|
|
163
|
+
if (violation) {
|
|
164
|
+
this.emit(guildId, channelId, {
|
|
165
|
+
kind: 'error',
|
|
166
|
+
message: `File path escapes the workspace and was rejected: ${violation}`,
|
|
167
|
+
retryable: false,
|
|
168
|
+
});
|
|
169
|
+
this.auditLog.record({
|
|
170
|
+
actorId: channel.ownerId,
|
|
171
|
+
roleTier: 'execute',
|
|
172
|
+
guildId,
|
|
173
|
+
channelId,
|
|
174
|
+
action: 'turn',
|
|
175
|
+
mode: channel.mode,
|
|
176
|
+
permMode: channel.permMode,
|
|
177
|
+
cwd: channel.cwd,
|
|
178
|
+
outcome: `path confinement rejected: ${violation}`,
|
|
179
|
+
status: 'denied',
|
|
180
|
+
});
|
|
181
|
+
throw new Error(`File path escapes the workspace: ${violation}`);
|
|
182
|
+
}
|
|
183
|
+
channel.queue.push(turn);
|
|
184
|
+
const wasIdle = !channel.running;
|
|
185
|
+
// If a turn is in flight we simply leave ours queued; the running drain
|
|
186
|
+
// loop will pick it up in order. Otherwise we kick off the drain.
|
|
187
|
+
if (wasIdle) {
|
|
188
|
+
// Fire-and-forget: the drain loop owns error handling and audit per turn.
|
|
189
|
+
void this.drain(key);
|
|
190
|
+
}
|
|
191
|
+
return {
|
|
192
|
+
status: wasIdle ? 'started' : 'queued',
|
|
193
|
+
queueDepth: channel.queue.length,
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
// §9 step 5 / §7.5 kill switch. Abort the running session, drain (clear) the
|
|
197
|
+
// channel's queue, archive the binding, and drop the live tracking. Audited.
|
|
198
|
+
async stop(guildId, channelId) {
|
|
199
|
+
const key = channelKey(guildId, channelId);
|
|
200
|
+
const channel = this.active.get(key);
|
|
201
|
+
if (!channel)
|
|
202
|
+
return;
|
|
203
|
+
channel.queue.length = 0;
|
|
204
|
+
try {
|
|
205
|
+
await channel.session.stop();
|
|
206
|
+
}
|
|
207
|
+
catch (err) {
|
|
208
|
+
this.logger.error('session stop failed', { guildId, channelId, err: String(err) });
|
|
209
|
+
}
|
|
210
|
+
this.active.delete(key);
|
|
211
|
+
this.channelRegistry.markArchived(guildId, channelId);
|
|
212
|
+
this.auditLog.record({
|
|
213
|
+
actorId: channel.ownerId,
|
|
214
|
+
roleTier: 'execute',
|
|
215
|
+
guildId,
|
|
216
|
+
channelId,
|
|
217
|
+
action: 'stop',
|
|
218
|
+
mode: channel.mode,
|
|
219
|
+
permMode: channel.permMode,
|
|
220
|
+
cwd: channel.cwd,
|
|
221
|
+
status: 'ok',
|
|
222
|
+
});
|
|
223
|
+
this.logger.info('session stopped', { guildId, channelId });
|
|
224
|
+
}
|
|
225
|
+
// §7.5 admin kill switch. Stop every active session across all guilds. The
|
|
226
|
+
// tier check happens at the router; the orchestrator just executes. Each stop
|
|
227
|
+
// is isolated so one failure does not abort the rest.
|
|
228
|
+
async stopAll() {
|
|
229
|
+
const keys = [...this.active.keys()];
|
|
230
|
+
for (const key of keys) {
|
|
231
|
+
const channel = this.active.get(key);
|
|
232
|
+
if (!channel)
|
|
233
|
+
continue;
|
|
234
|
+
await this.stop(channel.guildId, channel.channelId);
|
|
235
|
+
}
|
|
236
|
+
this.logger.info('all sessions stopped', { count: keys.length });
|
|
237
|
+
}
|
|
238
|
+
// §9 step 4 (fixes A2). Boot recovery: re-bind every non-archived channel from
|
|
239
|
+
// persisted state via mode.resume(ctx, sessionId). A mode/session that fails
|
|
240
|
+
// to resume is logged and skipped so one bad binding never crashes boot.
|
|
241
|
+
async resumeAll() {
|
|
242
|
+
const bindings = this.channelRegistry.list().filter((b) => !b.archived);
|
|
243
|
+
let resumed = 0;
|
|
244
|
+
for (const binding of bindings) {
|
|
245
|
+
const { guildId, channelId, mode, cwd, ownerId, permMode, sessionId } = binding;
|
|
246
|
+
try {
|
|
247
|
+
const agentMode = this.modeRegistry.get(mode);
|
|
248
|
+
// Re-resolve the layered tool allowlist for the resumed channel (no live
|
|
249
|
+
// session override on boot — the persisted profile/mode drive it) so a
|
|
250
|
+
// resumed session gets the same allowlist a fresh start() would.
|
|
251
|
+
const perm = this.permissionResolver.resolve(guildId, channelId);
|
|
252
|
+
const ctx = this.buildContext({
|
|
253
|
+
guildId,
|
|
254
|
+
channelId,
|
|
255
|
+
cwd,
|
|
256
|
+
ownerId,
|
|
257
|
+
mode,
|
|
258
|
+
permMode,
|
|
259
|
+
allowedTools: perm.allowedTools,
|
|
260
|
+
});
|
|
261
|
+
// A binding with no backend sessionId cannot be resumed against a
|
|
262
|
+
// specific id; skip it (the channel starts fresh on its next turn).
|
|
263
|
+
if (sessionId === null) {
|
|
264
|
+
this.logger.warn('skipping resume: no sessionId', { guildId, channelId, mode });
|
|
265
|
+
continue;
|
|
266
|
+
}
|
|
267
|
+
const session = await agentMode.resume(ctx, sessionId);
|
|
268
|
+
this.active.set(channelKey(guildId, channelId), {
|
|
269
|
+
guildId,
|
|
270
|
+
channelId,
|
|
271
|
+
mode,
|
|
272
|
+
cwd,
|
|
273
|
+
ownerId,
|
|
274
|
+
permMode,
|
|
275
|
+
session,
|
|
276
|
+
queue: [],
|
|
277
|
+
running: false,
|
|
278
|
+
});
|
|
279
|
+
this.auditLog.record({
|
|
280
|
+
actorId: ownerId,
|
|
281
|
+
roleTier: 'execute',
|
|
282
|
+
guildId,
|
|
283
|
+
channelId,
|
|
284
|
+
action: 'resume',
|
|
285
|
+
mode,
|
|
286
|
+
permMode,
|
|
287
|
+
cwd,
|
|
288
|
+
status: 'ok',
|
|
289
|
+
});
|
|
290
|
+
resumed++;
|
|
291
|
+
}
|
|
292
|
+
catch (err) {
|
|
293
|
+
// Tolerate a mode/session that fails to resume: log + skip, never crash.
|
|
294
|
+
this.logger.error('resume failed; skipping channel', {
|
|
295
|
+
guildId,
|
|
296
|
+
channelId,
|
|
297
|
+
mode,
|
|
298
|
+
err: String(err),
|
|
299
|
+
});
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
this.logger.info('resume-on-boot complete', { resumed, total: bindings.length });
|
|
303
|
+
}
|
|
304
|
+
// Drain a channel's queue one turn at a time, strictly in FIFO order. Marked
|
|
305
|
+
// running for the whole drain so a concurrent send() cannot start a second
|
|
306
|
+
// drain (single-threaded JS + this flag = no interleaving). Each turn is
|
|
307
|
+
// audited; a send() failure is surfaced as an error event but does not stop
|
|
308
|
+
// the queue (the next turn still runs).
|
|
309
|
+
async drain(key) {
|
|
310
|
+
const channel = this.active.get(key);
|
|
311
|
+
if (!channel || channel.running)
|
|
312
|
+
return;
|
|
313
|
+
channel.running = true;
|
|
314
|
+
try {
|
|
315
|
+
while (channel.queue.length > 0) {
|
|
316
|
+
const turn = channel.queue.shift();
|
|
317
|
+
try {
|
|
318
|
+
await channel.session.send(turn);
|
|
319
|
+
this.auditLog.record({
|
|
320
|
+
actorId: channel.ownerId,
|
|
321
|
+
roleTier: 'execute',
|
|
322
|
+
guildId: channel.guildId,
|
|
323
|
+
channelId: channel.channelId,
|
|
324
|
+
action: 'turn',
|
|
325
|
+
mode: channel.mode,
|
|
326
|
+
permMode: channel.permMode,
|
|
327
|
+
cwd: channel.cwd,
|
|
328
|
+
status: 'ok',
|
|
329
|
+
});
|
|
330
|
+
}
|
|
331
|
+
catch (err) {
|
|
332
|
+
this.logger.error('turn failed', {
|
|
333
|
+
guildId: channel.guildId,
|
|
334
|
+
channelId: channel.channelId,
|
|
335
|
+
err: String(err),
|
|
336
|
+
});
|
|
337
|
+
this.emit(channel.guildId, channel.channelId, {
|
|
338
|
+
kind: 'error',
|
|
339
|
+
message: `Turn failed: ${String(err)}`,
|
|
340
|
+
retryable: true,
|
|
341
|
+
});
|
|
342
|
+
this.auditLog.record({
|
|
343
|
+
actorId: channel.ownerId,
|
|
344
|
+
roleTier: 'execute',
|
|
345
|
+
guildId: channel.guildId,
|
|
346
|
+
channelId: channel.channelId,
|
|
347
|
+
action: 'turn',
|
|
348
|
+
mode: channel.mode,
|
|
349
|
+
permMode: channel.permMode,
|
|
350
|
+
cwd: channel.cwd,
|
|
351
|
+
outcome: String(err),
|
|
352
|
+
status: 'error',
|
|
353
|
+
});
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
finally {
|
|
358
|
+
channel.running = false;
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
// Build the ModeContext handed to a mode's start()/resume(): emit → EventBus,
|
|
362
|
+
// requestPermission → the injectable resolver, config → the resolved layered
|
|
363
|
+
// view, audit → AuditLog. guildId/channelId/cwd/ownerId/permMode are carried.
|
|
364
|
+
// The resolved tool allowlist (from PermissionResolver: the global auto-allow
|
|
365
|
+
// set, narrowed by any active profile) is threaded onto the config view so the
|
|
366
|
+
// Claude mode reads the layered allowlist instead of re-hardcoding one (A8).
|
|
367
|
+
buildContext(args) {
|
|
368
|
+
const { guildId, channelId, cwd, ownerId, permMode, allowedTools, effort } = args;
|
|
369
|
+
const modeConfig = this.configResolver.resolveModeConfig(guildId, channelId);
|
|
370
|
+
modeConfig.allowedTools = allowedTools;
|
|
371
|
+
modeConfig.autoAllowClaudeTools = allowedTools;
|
|
372
|
+
return {
|
|
373
|
+
guildId,
|
|
374
|
+
channelId,
|
|
375
|
+
cwd,
|
|
376
|
+
ownerId,
|
|
377
|
+
...(modeConfig.model !== undefined ? { model: modeConfig.model } : {}),
|
|
378
|
+
...(effort !== undefined && effort.length > 0 ? { effort } : {}),
|
|
379
|
+
permMode,
|
|
380
|
+
emit: (ev) => this.emit(guildId, channelId, ev),
|
|
381
|
+
requestPermission: (req) => this.requestPermission({ guildId, channelId, ownerId }, req),
|
|
382
|
+
config: modeConfig,
|
|
383
|
+
logger: this.logger,
|
|
384
|
+
audit: (entry) => {
|
|
385
|
+
this.auditLog.record(entry);
|
|
386
|
+
},
|
|
387
|
+
};
|
|
388
|
+
}
|
|
389
|
+
// Build a MINIMAL read-only ModeContext for a mode's listResumable (resume UX): it
|
|
390
|
+
// carries the browsed cwd + the mode's resolved config view (codexHome etc.) + the
|
|
391
|
+
// logger, but its emit/requestPermission/audit are inert no-ops — listResumable only
|
|
392
|
+
// reads cwd/config/logger and must never start a session or emit events. Not bound to
|
|
393
|
+
// a live channel (no guildId/channelId semantics beyond placeholders): nothing is
|
|
394
|
+
// persisted or tracked. Used by the Discord layer's resume flow before any channel is
|
|
395
|
+
// created for the resumed session.
|
|
396
|
+
buildListContext(mode, cwd) {
|
|
397
|
+
const modeConfig = this.configResolver.resolveModeConfig('', '');
|
|
398
|
+
return {
|
|
399
|
+
guildId: '',
|
|
400
|
+
channelId: '',
|
|
401
|
+
cwd,
|
|
402
|
+
ownerId: '',
|
|
403
|
+
...(modeConfig.model !== undefined ? { model: modeConfig.model } : {}),
|
|
404
|
+
permMode: 'default',
|
|
405
|
+
emit: () => { },
|
|
406
|
+
requestPermission: async () => ({ behavior: 'deny' }),
|
|
407
|
+
config: modeConfig,
|
|
408
|
+
logger: this.logger,
|
|
409
|
+
audit: () => { },
|
|
410
|
+
};
|
|
411
|
+
}
|
|
412
|
+
emit(guildId, channelId, ev) {
|
|
413
|
+
this.eventBus.emit(guildId, channelId, ev);
|
|
414
|
+
}
|
|
415
|
+
// Return the first TurnInput file whose realpath escapes the workspace root,
|
|
416
|
+
// or null if every file is confined. Resolves symlinks by realpath-ing the
|
|
417
|
+
// deepest existing ancestor of each path (a file need not exist yet), so a
|
|
418
|
+
// symlink pointing outside the workspace is caught, not just a literal `..`.
|
|
419
|
+
// NOTE: this is a pre-filter only and is subject to TOCTOU (a tail component
|
|
420
|
+
// could be swapped for a symlink after this check). The authoritative guard
|
|
421
|
+
// belongs at the mode's file-open site (Phase 2); do not treat this as the
|
|
422
|
+
// sole confinement enforcement.
|
|
423
|
+
findConfinementViolation(cwd, turn) {
|
|
424
|
+
if (!turn.files || turn.files.length === 0)
|
|
425
|
+
return null;
|
|
426
|
+
const root = realpathOrResolve(cwd);
|
|
427
|
+
for (const file of turn.files) {
|
|
428
|
+
const resolved = realpathOrResolve(path.resolve(cwd, file.path));
|
|
429
|
+
if (!isWithin(root, resolved))
|
|
430
|
+
return file.path;
|
|
431
|
+
}
|
|
432
|
+
return null;
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
// Realpath a path, falling back to the realpath of its deepest existing ancestor
|
|
436
|
+
// joined with the non-existent tail — so confinement holds for paths that do not
|
|
437
|
+
// exist yet while still resolving symlinks in the part that does.
|
|
438
|
+
function realpathOrResolve(target) {
|
|
439
|
+
const abs = path.resolve(target);
|
|
440
|
+
let existing = abs;
|
|
441
|
+
const tail = [];
|
|
442
|
+
while (!fs.existsSync(existing)) {
|
|
443
|
+
const parent = path.dirname(existing);
|
|
444
|
+
if (parent === existing)
|
|
445
|
+
break; // reached the filesystem root
|
|
446
|
+
tail.unshift(path.basename(existing));
|
|
447
|
+
existing = parent;
|
|
448
|
+
}
|
|
449
|
+
try {
|
|
450
|
+
const realExisting = fs.realpathSync(existing);
|
|
451
|
+
return tail.length > 0 ? path.join(realExisting, ...tail) : realExisting;
|
|
452
|
+
}
|
|
453
|
+
catch {
|
|
454
|
+
return abs;
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
// True when `child` is the same as, or nested under, `root`. Uses path.relative
|
|
458
|
+
// so it is not fooled by shared string prefixes (e.g. /ws vs /ws-evil).
|
|
459
|
+
function isWithin(root, child) {
|
|
460
|
+
const rel = path.relative(root, child);
|
|
461
|
+
return rel === '' || (!rel.startsWith('..') && !path.isAbsolute(rel));
|
|
462
|
+
}
|
|
463
|
+
//# sourceMappingURL=sessionOrchestrator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sessionOrchestrator.js","sourceRoot":"","sources":["../../src/core/sessionOrchestrator.ts"],"names":[],"mappings":"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"}
|