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.
Files changed (201) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +195 -0
  3. package/dist/app.js +210 -0
  4. package/dist/app.js.map +1 -0
  5. package/dist/app.test.js +117 -0
  6. package/dist/app.test.js.map +1 -0
  7. package/dist/cli.js +63 -0
  8. package/dist/cli.js.map +1 -0
  9. package/dist/cli.test.js +91 -0
  10. package/dist/cli.test.js.map +1 -0
  11. package/dist/core/auditLog.js +65 -0
  12. package/dist/core/auditLog.js.map +1 -0
  13. package/dist/core/auditLog.test.js +124 -0
  14. package/dist/core/auditLog.test.js.map +1 -0
  15. package/dist/core/auth.js +106 -0
  16. package/dist/core/auth.js.map +1 -0
  17. package/dist/core/auth.test.js +216 -0
  18. package/dist/core/auth.test.js.map +1 -0
  19. package/dist/core/channelRegistry.js +119 -0
  20. package/dist/core/channelRegistry.js.map +1 -0
  21. package/dist/core/channelRegistry.test.js +114 -0
  22. package/dist/core/channelRegistry.test.js.map +1 -0
  23. package/dist/core/commandPolicy.js +6 -0
  24. package/dist/core/commandPolicy.js.map +1 -0
  25. package/dist/core/commandRouter.js +9 -0
  26. package/dist/core/commandRouter.js.map +1 -0
  27. package/dist/core/config.js +141 -0
  28. package/dist/core/config.js.map +1 -0
  29. package/dist/core/config.test.js +149 -0
  30. package/dist/core/config.test.js.map +1 -0
  31. package/dist/core/configResolver.js +90 -0
  32. package/dist/core/configResolver.js.map +1 -0
  33. package/dist/core/configResolver.test.js +138 -0
  34. package/dist/core/configResolver.test.js.map +1 -0
  35. package/dist/core/configSchema.js +164 -0
  36. package/dist/core/configSchema.js.map +1 -0
  37. package/dist/core/contracts.js +5 -0
  38. package/dist/core/contracts.js.map +1 -0
  39. package/dist/core/eventBus.js +42 -0
  40. package/dist/core/eventBus.js.map +1 -0
  41. package/dist/core/eventBus.test.js +72 -0
  42. package/dist/core/eventBus.test.js.map +1 -0
  43. package/dist/core/hookBridge.js +11 -0
  44. package/dist/core/hookBridge.js.map +1 -0
  45. package/dist/core/logger.js +116 -0
  46. package/dist/core/logger.js.map +1 -0
  47. package/dist/core/logger.test.js +88 -0
  48. package/dist/core/logger.test.js.map +1 -0
  49. package/dist/core/modeRegistry.js +33 -0
  50. package/dist/core/modeRegistry.js.map +1 -0
  51. package/dist/core/permissionResolver.js +43 -0
  52. package/dist/core/permissionResolver.js.map +1 -0
  53. package/dist/core/permissionResolver.test.js +136 -0
  54. package/dist/core/permissionResolver.test.js.map +1 -0
  55. package/dist/core/providerCatalog.js +240 -0
  56. package/dist/core/providerCatalog.js.map +1 -0
  57. package/dist/core/providerCatalog.test.js +230 -0
  58. package/dist/core/providerCatalog.test.js.map +1 -0
  59. package/dist/core/sessionOrchestrator.js +463 -0
  60. package/dist/core/sessionOrchestrator.js.map +1 -0
  61. package/dist/core/sessionOrchestrator.test.js +344 -0
  62. package/dist/core/sessionOrchestrator.test.js.map +1 -0
  63. package/dist/core/state/schema.js +49 -0
  64. package/dist/core/state/schema.js.map +1 -0
  65. package/dist/core/state/store.js +86 -0
  66. package/dist/core/state/store.js.map +1 -0
  67. package/dist/core/state/store.test.js +99 -0
  68. package/dist/core/state/store.test.js.map +1 -0
  69. package/dist/core/usageService.js +310 -0
  70. package/dist/core/usageService.js.map +1 -0
  71. package/dist/core/usageService.test.js +234 -0
  72. package/dist/core/usageService.test.js.map +1 -0
  73. package/dist/discord/alwaysAllow.test.js +181 -0
  74. package/dist/discord/alwaysAllow.test.js.map +1 -0
  75. package/dist/discord/client.js +666 -0
  76. package/dist/discord/client.js.map +1 -0
  77. package/dist/discord/client.test.js +256 -0
  78. package/dist/discord/client.test.js.map +1 -0
  79. package/dist/discord/configPanel.js +270 -0
  80. package/dist/discord/configPanel.js.map +1 -0
  81. package/dist/discord/configPanel.test.js +332 -0
  82. package/dist/discord/configPanel.test.js.map +1 -0
  83. package/dist/discord/directoryBrowser.js +151 -0
  84. package/dist/discord/directoryBrowser.js.map +1 -0
  85. package/dist/discord/directoryBrowser.test.js +163 -0
  86. package/dist/discord/directoryBrowser.test.js.map +1 -0
  87. package/dist/discord/favorites.js +10 -0
  88. package/dist/discord/favorites.js.map +1 -0
  89. package/dist/discord/fileDownload.js +94 -0
  90. package/dist/discord/fileDownload.js.map +1 -0
  91. package/dist/discord/fileDownload.test.js +59 -0
  92. package/dist/discord/fileDownload.test.js.map +1 -0
  93. package/dist/discord/format.js +104 -0
  94. package/dist/discord/format.js.map +1 -0
  95. package/dist/discord/format.test.js +40 -0
  96. package/dist/discord/format.test.js.map +1 -0
  97. package/dist/discord/guildChannels.js +97 -0
  98. package/dist/discord/guildChannels.js.map +1 -0
  99. package/dist/discord/guildChannels.test.js +231 -0
  100. package/dist/discord/guildChannels.test.js.map +1 -0
  101. package/dist/discord/i18n.js +207 -0
  102. package/dist/discord/i18n.js.map +1 -0
  103. package/dist/discord/i18n.test.js +31 -0
  104. package/dist/discord/i18n.test.js.map +1 -0
  105. package/dist/discord/interactionRouter.js +954 -0
  106. package/dist/discord/interactionRouter.js.map +1 -0
  107. package/dist/discord/interactionRouter.test.js +1245 -0
  108. package/dist/discord/interactionRouter.test.js.map +1 -0
  109. package/dist/discord/messageRouter.js +221 -0
  110. package/dist/discord/messageRouter.js.map +1 -0
  111. package/dist/discord/messageRouter.test.js +360 -0
  112. package/dist/discord/messageRouter.test.js.map +1 -0
  113. package/dist/discord/ports.js +12 -0
  114. package/dist/discord/ports.js.map +1 -0
  115. package/dist/discord/renderers/defaultSet.test.js +97 -0
  116. package/dist/discord/renderers/defaultSet.test.js.map +1 -0
  117. package/dist/discord/renderers/diffView.js +73 -0
  118. package/dist/discord/renderers/diffView.js.map +1 -0
  119. package/dist/discord/renderers/diffView.test.js +54 -0
  120. package/dist/discord/renderers/diffView.test.js.map +1 -0
  121. package/dist/discord/renderers/index.js +143 -0
  122. package/dist/discord/renderers/index.js.map +1 -0
  123. package/dist/discord/renderers/index.test.js +124 -0
  124. package/dist/discord/renderers/index.test.js.map +1 -0
  125. package/dist/discord/renderers/mentionOnComplete.js +19 -0
  126. package/dist/discord/renderers/mentionOnComplete.js.map +1 -0
  127. package/dist/discord/renderers/mentionOnComplete.test.js +35 -0
  128. package/dist/discord/renderers/mentionOnComplete.test.js.map +1 -0
  129. package/dist/discord/renderers/permissionButtons.js +150 -0
  130. package/dist/discord/renderers/permissionButtons.js.map +1 -0
  131. package/dist/discord/renderers/permissionButtons.test.js +108 -0
  132. package/dist/discord/renderers/permissionButtons.test.js.map +1 -0
  133. package/dist/discord/renderers/resultLine.js +25 -0
  134. package/dist/discord/renderers/resultLine.js.map +1 -0
  135. package/dist/discord/renderers/statusEmbed.js +20 -0
  136. package/dist/discord/renderers/statusEmbed.js.map +1 -0
  137. package/dist/discord/renderers/statusEmbed.test.js +32 -0
  138. package/dist/discord/renderers/statusEmbed.test.js.map +1 -0
  139. package/dist/discord/renderers/streamEmbed.js +134 -0
  140. package/dist/discord/renderers/streamEmbed.js.map +1 -0
  141. package/dist/discord/renderers/streamEmbed.test.js +97 -0
  142. package/dist/discord/renderers/streamEmbed.test.js.map +1 -0
  143. package/dist/discord/renderers/toolThread.js +65 -0
  144. package/dist/discord/renderers/toolThread.js.map +1 -0
  145. package/dist/discord/renderers/toolThread.test.js +54 -0
  146. package/dist/discord/renderers/toolThread.test.js.map +1 -0
  147. package/dist/discord/renderers/transcriptFeed.js +33 -0
  148. package/dist/discord/renderers/transcriptFeed.js.map +1 -0
  149. package/dist/discord/renderers/usageEmbed.js +78 -0
  150. package/dist/discord/renderers/usageEmbed.js.map +1 -0
  151. package/dist/discord/renderers/usageEmbed.test.js +42 -0
  152. package/dist/discord/renderers/usageEmbed.test.js.map +1 -0
  153. package/dist/discord/wiring.js +214 -0
  154. package/dist/discord/wiring.js.map +1 -0
  155. package/dist/discord/wiring.test.js +252 -0
  156. package/dist/discord/wiring.test.js.map +1 -0
  157. package/dist/discord/wizard/channelWizard.js +305 -0
  158. package/dist/discord/wizard/channelWizard.js.map +1 -0
  159. package/dist/discord/wizard/channelWizard.test.js +298 -0
  160. package/dist/discord/wizard/channelWizard.test.js.map +1 -0
  161. package/dist/discord/wizard/resumeWizard.js +123 -0
  162. package/dist/discord/wizard/resumeWizard.js.map +1 -0
  163. package/dist/modes/claude/index.js +80 -0
  164. package/dist/modes/claude/index.js.map +1 -0
  165. package/dist/modes/claude/listResumable.test.js +72 -0
  166. package/dist/modes/claude/listResumable.test.js.map +1 -0
  167. package/dist/modes/claude/mcpFileTool.js +82 -0
  168. package/dist/modes/claude/mcpFileTool.js.map +1 -0
  169. package/dist/modes/claude/permissions.js +35 -0
  170. package/dist/modes/claude/permissions.js.map +1 -0
  171. package/dist/modes/claude/plugins.js +56 -0
  172. package/dist/modes/claude/plugins.js.map +1 -0
  173. package/dist/modes/claude/session.js +324 -0
  174. package/dist/modes/claude/session.js.map +1 -0
  175. package/dist/modes/claude/session.test.js +415 -0
  176. package/dist/modes/claude/session.test.js.map +1 -0
  177. package/dist/modes/codex/discovery.js +221 -0
  178. package/dist/modes/codex/discovery.js.map +1 -0
  179. package/dist/modes/codex/discovery.test.js +213 -0
  180. package/dist/modes/codex/discovery.test.js.map +1 -0
  181. package/dist/modes/codex/eventMapper.js +262 -0
  182. package/dist/modes/codex/eventMapper.js.map +1 -0
  183. package/dist/modes/codex/index.js +132 -0
  184. package/dist/modes/codex/index.js.map +1 -0
  185. package/dist/modes/codex/index.test.js +170 -0
  186. package/dist/modes/codex/index.test.js.map +1 -0
  187. package/dist/modes/codex/runner.js +207 -0
  188. package/dist/modes/codex/runner.js.map +1 -0
  189. package/dist/modes/codex/runner.test.js +587 -0
  190. package/dist/modes/codex/runner.test.js.map +1 -0
  191. package/dist/modes/codex/sqliteReader.js +171 -0
  192. package/dist/modes/codex/sqliteReader.js.map +1 -0
  193. package/dist/modes/codex/sqliteReader.test.js +137 -0
  194. package/dist/modes/codex/sqliteReader.test.js.map +1 -0
  195. package/dist/setup/wizard.js +115 -0
  196. package/dist/setup/wizard.js.map +1 -0
  197. package/dist/setup/wizard.test.js +216 -0
  198. package/dist/setup/wizard.test.js.map +1 -0
  199. package/dist/startBot.test.js +78 -0
  200. package/dist/startBot.test.js.map +1 -0
  201. 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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"}