@provos/ironcurtain 0.5.0 → 0.6.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/README.md +66 -66
- package/dist/cli.js +9 -0
- package/dist/cli.js.map +1 -1
- package/dist/config/types.d.ts +6 -0
- package/dist/docker/adapters/claude-code.js +44 -19
- package/dist/docker/adapters/claude-code.js.map +1 -1
- package/dist/docker/agent-adapter.d.ts +6 -0
- package/dist/docker/agent-adapter.js +6 -1
- package/dist/docker/agent-adapter.js.map +1 -1
- package/dist/docker/docker-agent-session.d.ts +1 -1
- package/dist/docker/docker-agent-session.js +3 -2
- package/dist/docker/docker-agent-session.js.map +1 -1
- package/dist/docker/docker-infrastructure.js +10 -3
- package/dist/docker/docker-infrastructure.js.map +1 -1
- package/dist/docker/mitm-proxy.d.ts +5 -2
- package/dist/docker/mitm-proxy.js +169 -46
- package/dist/docker/mitm-proxy.js.map +1 -1
- package/dist/docker/oauth-credentials.d.ts +15 -2
- package/dist/docker/oauth-credentials.js +92 -8
- package/dist/docker/oauth-credentials.js.map +1 -1
- package/dist/docker/oauth-token-manager.d.ts +80 -0
- package/dist/docker/oauth-token-manager.js +133 -0
- package/dist/docker/oauth-token-manager.js.map +1 -0
- package/dist/docker/orientation.d.ts +1 -1
- package/dist/docker/orientation.js +2 -1
- package/dist/docker/orientation.js.map +1 -1
- package/dist/docker/pty-session.d.ts +2 -0
- package/dist/docker/pty-session.js +105 -9
- package/dist/docker/pty-session.js.map +1 -1
- package/dist/escalation/escalation-watcher.js +2 -0
- package/dist/escalation/escalation-watcher.js.map +1 -1
- package/dist/escalation/listener-command.js +9 -58
- package/dist/escalation/listener-command.js.map +1 -1
- package/dist/escalation/listener-lock.d.ts +20 -0
- package/dist/escalation/listener-lock.js +69 -0
- package/dist/escalation/listener-lock.js.map +1 -0
- package/dist/index.js +21 -1
- package/dist/index.js.map +1 -1
- package/dist/mux/mux-app.d.ts +24 -0
- package/dist/mux/mux-app.js +445 -0
- package/dist/mux/mux-app.js.map +1 -0
- package/dist/mux/mux-command.d.ts +7 -0
- package/dist/mux/mux-command.js +93 -0
- package/dist/mux/mux-command.js.map +1 -0
- package/dist/mux/mux-escalation-manager.d.ts +48 -0
- package/dist/mux/mux-escalation-manager.js +162 -0
- package/dist/mux/mux-escalation-manager.js.map +1 -0
- package/dist/mux/mux-input-handler.d.ts +49 -0
- package/dist/mux/mux-input-handler.js +457 -0
- package/dist/mux/mux-input-handler.js.map +1 -0
- package/dist/mux/mux-renderer.d.ts +86 -0
- package/dist/mux/mux-renderer.js +758 -0
- package/dist/mux/mux-renderer.js.map +1 -0
- package/dist/mux/mux-splash.d.ts +17 -0
- package/dist/mux/mux-splash.js +322 -0
- package/dist/mux/mux-splash.js.map +1 -0
- package/dist/mux/pty-bridge.d.ts +79 -0
- package/dist/mux/pty-bridge.js +151 -0
- package/dist/mux/pty-bridge.js.map +1 -0
- package/dist/mux/trusted-input.d.ts +27 -0
- package/dist/mux/trusted-input.js +27 -0
- package/dist/mux/trusted-input.js.map +1 -0
- package/dist/mux/types.d.ts +92 -0
- package/dist/mux/types.js +45 -0
- package/dist/mux/types.js.map +1 -0
- package/dist/sandbox/index.js +6 -0
- package/dist/sandbox/index.js.map +1 -1
- package/dist/session/agent-session.js +3 -0
- package/dist/session/agent-session.js.map +1 -1
- package/dist/session/index.js +14 -7
- package/dist/session/index.js.map +1 -1
- package/dist/session/types.d.ts +6 -0
- package/dist/session/workspace-validation.d.ts +17 -0
- package/dist/session/workspace-validation.js +65 -0
- package/dist/session/workspace-validation.js.map +1 -0
- package/dist/trusted-process/auto-approver.d.ts +13 -4
- package/dist/trusted-process/auto-approver.js +12 -5
- package/dist/trusted-process/auto-approver.js.map +1 -1
- package/dist/trusted-process/escalation.js +5 -0
- package/dist/trusted-process/escalation.js.map +1 -1
- package/dist/trusted-process/index.js +23 -0
- package/dist/trusted-process/index.js.map +1 -1
- package/dist/trusted-process/mcp-proxy-server.d.ts +0 -2
- package/dist/trusted-process/mcp-proxy-server.js +82 -26
- package/dist/trusted-process/mcp-proxy-server.js.map +1 -1
- package/dist/trusted-process/path-utils.d.ts +15 -0
- package/dist/trusted-process/path-utils.js +38 -0
- package/dist/trusted-process/path-utils.js.map +1 -1
- package/package.json +6 -1
|
@@ -0,0 +1,445 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MuxApp -- top-level orchestrator for the terminal multiplexer.
|
|
3
|
+
*
|
|
4
|
+
* Creates and owns all child components. Handles MuxAction dispatch,
|
|
5
|
+
* tab lifecycle, resize events, trusted input flow, and cleanup.
|
|
6
|
+
*/
|
|
7
|
+
/* eslint-disable @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-assignment */
|
|
8
|
+
import { createPtyBridge } from './pty-bridge.js';
|
|
9
|
+
import { createMuxInputHandler } from './mux-input-handler.js';
|
|
10
|
+
import { createMuxEscalationManager } from './mux-escalation-manager.js';
|
|
11
|
+
import { createMuxRenderer } from './mux-renderer.js';
|
|
12
|
+
import { writeTrustedUserContext } from './trusted-input.js';
|
|
13
|
+
import { validateWorkspacePath } from '../session/workspace-validation.js';
|
|
14
|
+
import * as logger from '../logger.js';
|
|
15
|
+
/**
|
|
16
|
+
* Creates and returns a MuxApp.
|
|
17
|
+
*/
|
|
18
|
+
export function createMuxApp(options) {
|
|
19
|
+
const agent = options.agent ?? 'claude-code';
|
|
20
|
+
const autoSpawn = options.autoSpawn ?? true;
|
|
21
|
+
const protectedPaths = options.protectedPaths ?? [];
|
|
22
|
+
const tabs = [];
|
|
23
|
+
let activeTabIndex = 0;
|
|
24
|
+
let nextTabNumber = 1;
|
|
25
|
+
let running = false;
|
|
26
|
+
// Mouse event constants
|
|
27
|
+
const MOUSE_WHEEL_UP = 'MOUSE_WHEEL_UP';
|
|
28
|
+
const MOUSE_WHEEL_DOWN = 'MOUSE_WHEEL_DOWN';
|
|
29
|
+
const SCROLL_LINES = 3;
|
|
30
|
+
// Components (initialized in start())
|
|
31
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
32
|
+
let term;
|
|
33
|
+
let inputHandler;
|
|
34
|
+
let escalationManager;
|
|
35
|
+
let renderer;
|
|
36
|
+
function getActiveTab() {
|
|
37
|
+
return tabs[activeTabIndex];
|
|
38
|
+
}
|
|
39
|
+
function resolveIroncurtainBin() {
|
|
40
|
+
const script = process.argv[1];
|
|
41
|
+
// If the entry point is a .ts file, we're running via tsx/ts-node --
|
|
42
|
+
// spawn the child through the same runtime. process.execArgv contains
|
|
43
|
+
// the loader flags (e.g. --import tsx/loader) that make .ts imports work.
|
|
44
|
+
if (script && script.endsWith('.ts')) {
|
|
45
|
+
return { bin: process.argv[0], prefixArgs: [...process.execArgv, script] };
|
|
46
|
+
}
|
|
47
|
+
// If running a compiled JS file or via an installed bin, use it directly
|
|
48
|
+
return { bin: script || 'ironcurtain', prefixArgs: [] };
|
|
49
|
+
}
|
|
50
|
+
async function spawnSession(workspacePath) {
|
|
51
|
+
const { columns } = process.stdout;
|
|
52
|
+
const ptyRows = renderer.layout.ptyViewportRows;
|
|
53
|
+
const ptyCols = columns || 80;
|
|
54
|
+
const { bin, prefixArgs } = resolveIroncurtainBin();
|
|
55
|
+
const bridge = await createPtyBridge({
|
|
56
|
+
cols: ptyCols,
|
|
57
|
+
rows: ptyRows,
|
|
58
|
+
ironcurtainBin: bin,
|
|
59
|
+
prefixArgs,
|
|
60
|
+
agent,
|
|
61
|
+
workspacePath,
|
|
62
|
+
});
|
|
63
|
+
const tab = {
|
|
64
|
+
number: nextTabNumber++,
|
|
65
|
+
bridge,
|
|
66
|
+
label: agent,
|
|
67
|
+
status: 'running',
|
|
68
|
+
escalationAvailable: false,
|
|
69
|
+
scrollOffset: null,
|
|
70
|
+
};
|
|
71
|
+
tabs.push(tab);
|
|
72
|
+
// Wire bridge events
|
|
73
|
+
bridge.onOutput(() => {
|
|
74
|
+
// Snap back to live when new output arrives
|
|
75
|
+
if (tab.scrollOffset !== null) {
|
|
76
|
+
tab.scrollOffset = null;
|
|
77
|
+
}
|
|
78
|
+
if (getActiveTab() === tab) {
|
|
79
|
+
renderer.scheduleRedraw();
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
bridge.onExit((exitCode) => {
|
|
83
|
+
tab.status = 'exited';
|
|
84
|
+
tab.exitCode = exitCode;
|
|
85
|
+
// Skip UI effects if the mux is shutting down or the tab was already removed
|
|
86
|
+
if (!running || !tabs.includes(tab))
|
|
87
|
+
return;
|
|
88
|
+
if (bridge.sessionId) {
|
|
89
|
+
escalationManager.removeSession(bridge.sessionId);
|
|
90
|
+
}
|
|
91
|
+
renderer.redrawTabBar();
|
|
92
|
+
if (getActiveTab() === tab) {
|
|
93
|
+
showMessage(`Session #${tab.number} exited with code ${exitCode}`);
|
|
94
|
+
}
|
|
95
|
+
process.stderr.write('\x07');
|
|
96
|
+
});
|
|
97
|
+
bridge.onSessionDiscovered((registration) => {
|
|
98
|
+
if (registration && tab.status === 'running') {
|
|
99
|
+
tab.escalationAvailable = true;
|
|
100
|
+
escalationManager.addSession(registration);
|
|
101
|
+
tab.label = registration.label;
|
|
102
|
+
renderer.redrawTabBar();
|
|
103
|
+
}
|
|
104
|
+
else if (!registration) {
|
|
105
|
+
logger.warn(`Could not discover session registration for tab #${tab.number}`);
|
|
106
|
+
tab.escalationAvailable = false;
|
|
107
|
+
}
|
|
108
|
+
});
|
|
109
|
+
return tab;
|
|
110
|
+
}
|
|
111
|
+
function switchTab(index) {
|
|
112
|
+
if (index < 0 || index >= tabs.length)
|
|
113
|
+
return;
|
|
114
|
+
activeTabIndex = index;
|
|
115
|
+
renderer.fullRedraw();
|
|
116
|
+
}
|
|
117
|
+
function closeTab(tabNumber) {
|
|
118
|
+
const index = tabs.findIndex((t) => t.number === tabNumber);
|
|
119
|
+
if (index === -1) {
|
|
120
|
+
showMessage(`No tab #${tabNumber}`);
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
const tab = tabs[index];
|
|
124
|
+
tab.bridge.kill();
|
|
125
|
+
if (tab.bridge.sessionId) {
|
|
126
|
+
escalationManager.removeSession(tab.bridge.sessionId);
|
|
127
|
+
}
|
|
128
|
+
tabs.splice(index, 1);
|
|
129
|
+
if (tabs.length === 0) {
|
|
130
|
+
doShutdown();
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
if (activeTabIndex >= tabs.length) {
|
|
134
|
+
activeTabIndex = tabs.length - 1;
|
|
135
|
+
}
|
|
136
|
+
renderer.fullRedraw();
|
|
137
|
+
}
|
|
138
|
+
/** Adjusts scroll offset by delta lines (negative = up, positive = down). */
|
|
139
|
+
function adjustScroll(tab, delta) {
|
|
140
|
+
const baseY = tab.bridge.terminal.buffer.active.baseY;
|
|
141
|
+
if (baseY === 0)
|
|
142
|
+
return; // no scrollback available
|
|
143
|
+
const current = tab.scrollOffset ?? baseY;
|
|
144
|
+
const newOffset = current + delta;
|
|
145
|
+
if (newOffset >= baseY) {
|
|
146
|
+
tab.scrollOffset = null; // snap to live
|
|
147
|
+
}
|
|
148
|
+
else {
|
|
149
|
+
tab.scrollOffset = Math.max(0, newOffset);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
function showMessage(message) {
|
|
153
|
+
logger.info(message);
|
|
154
|
+
renderer.showMessage(message);
|
|
155
|
+
}
|
|
156
|
+
async function handleAction(action) {
|
|
157
|
+
switch (action.kind) {
|
|
158
|
+
case 'none':
|
|
159
|
+
break;
|
|
160
|
+
case 'write-pty': {
|
|
161
|
+
const active = getActiveTab();
|
|
162
|
+
if (active && active.bridge.alive) {
|
|
163
|
+
active.bridge.write(action.data);
|
|
164
|
+
}
|
|
165
|
+
break;
|
|
166
|
+
}
|
|
167
|
+
case 'enter-command-mode':
|
|
168
|
+
case 'enter-pty-mode':
|
|
169
|
+
renderer.fullRedraw();
|
|
170
|
+
break;
|
|
171
|
+
case 'command':
|
|
172
|
+
handleCommand(action.command, action.args);
|
|
173
|
+
break;
|
|
174
|
+
case 'trusted-input': {
|
|
175
|
+
const active = getActiveTab();
|
|
176
|
+
if (active && active.bridge.alive) {
|
|
177
|
+
if (active.bridge.escalationDir) {
|
|
178
|
+
writeTrustedUserContext(active.bridge.escalationDir, action.text);
|
|
179
|
+
}
|
|
180
|
+
else {
|
|
181
|
+
logger.warn(`Tab #${active.number}: escalation dir not yet available, skipping user-context write`);
|
|
182
|
+
process.stderr.write('\x07');
|
|
183
|
+
}
|
|
184
|
+
// Write text first, then \r separately after a short delay so
|
|
185
|
+
// Claude Code's Ink UI processes them as distinct input events.
|
|
186
|
+
// A single write of "text\r" arrives as one chunk and Ink may
|
|
187
|
+
// not trigger Enter when \r is bundled with preceding text.
|
|
188
|
+
active.bridge.write(action.text);
|
|
189
|
+
const bridge = active.bridge;
|
|
190
|
+
setTimeout(() => {
|
|
191
|
+
if (bridge.alive)
|
|
192
|
+
bridge.write('\r');
|
|
193
|
+
}, 50);
|
|
194
|
+
}
|
|
195
|
+
// Return to PTY mode after sending trusted input
|
|
196
|
+
inputHandler.handleKey('CTRL_A');
|
|
197
|
+
renderer.fullRedraw();
|
|
198
|
+
break;
|
|
199
|
+
}
|
|
200
|
+
case 'redraw-input':
|
|
201
|
+
renderer.redrawCommandArea();
|
|
202
|
+
break;
|
|
203
|
+
case 'enter-picker-mode':
|
|
204
|
+
renderer.fullRedraw();
|
|
205
|
+
break;
|
|
206
|
+
case 'picker-spawn': {
|
|
207
|
+
let validatedPath;
|
|
208
|
+
if (action.workspacePath) {
|
|
209
|
+
try {
|
|
210
|
+
validatedPath = validateWorkspacePath(action.workspacePath, protectedPaths);
|
|
211
|
+
}
|
|
212
|
+
catch (err) {
|
|
213
|
+
inputHandler.enterBrowseWithError(action.workspacePath, err instanceof Error ? err.message : String(err));
|
|
214
|
+
renderer.fullRedraw();
|
|
215
|
+
break;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
const tab = await spawnSession(validatedPath);
|
|
219
|
+
activeTabIndex = tabs.length - 1;
|
|
220
|
+
const suffix = validatedPath ? ` in ${validatedPath}` : '';
|
|
221
|
+
showMessage(`Spawned session #${tab.number}${suffix}`);
|
|
222
|
+
inputHandler.exitPickerMode();
|
|
223
|
+
renderer.fullRedraw();
|
|
224
|
+
break;
|
|
225
|
+
}
|
|
226
|
+
case 'picker-cancel':
|
|
227
|
+
renderer.fullRedraw();
|
|
228
|
+
break;
|
|
229
|
+
case 'redraw-picker':
|
|
230
|
+
renderer.redrawCommandArea();
|
|
231
|
+
break;
|
|
232
|
+
case 'scroll-up':
|
|
233
|
+
case 'scroll-down': {
|
|
234
|
+
const active = getActiveTab();
|
|
235
|
+
if (!active)
|
|
236
|
+
break;
|
|
237
|
+
const delta = action.kind === 'scroll-up' ? -action.amount : action.amount;
|
|
238
|
+
adjustScroll(active, delta);
|
|
239
|
+
renderer.scheduleRedraw();
|
|
240
|
+
break;
|
|
241
|
+
}
|
|
242
|
+
case 'quit':
|
|
243
|
+
doShutdown();
|
|
244
|
+
break;
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
function handleCommand(command, args) {
|
|
248
|
+
switch (command) {
|
|
249
|
+
case 'approve':
|
|
250
|
+
case 'deny': {
|
|
251
|
+
const decision = command === 'approve' ? 'approved' : 'denied';
|
|
252
|
+
const arg = args[0];
|
|
253
|
+
if (!arg) {
|
|
254
|
+
showMessage(`Usage: /${command} <number> or /${command} all`);
|
|
255
|
+
break;
|
|
256
|
+
}
|
|
257
|
+
let message;
|
|
258
|
+
if (arg === 'all') {
|
|
259
|
+
message = escalationManager.resolveAll(decision);
|
|
260
|
+
}
|
|
261
|
+
else {
|
|
262
|
+
const num = parseInt(arg, 10);
|
|
263
|
+
if (isNaN(num)) {
|
|
264
|
+
showMessage('Invalid escalation number');
|
|
265
|
+
break;
|
|
266
|
+
}
|
|
267
|
+
message = escalationManager.resolve(num, decision);
|
|
268
|
+
}
|
|
269
|
+
showMessage(message);
|
|
270
|
+
renderer.redrawTabBar();
|
|
271
|
+
renderer.redrawCommandArea();
|
|
272
|
+
break;
|
|
273
|
+
}
|
|
274
|
+
case 'new': {
|
|
275
|
+
inputHandler.enterPickerMode();
|
|
276
|
+
renderer.fullRedraw();
|
|
277
|
+
break;
|
|
278
|
+
}
|
|
279
|
+
case 'tab': {
|
|
280
|
+
const num = parseInt(args[0], 10);
|
|
281
|
+
if (isNaN(num)) {
|
|
282
|
+
showMessage('Usage: /tab <number>');
|
|
283
|
+
break;
|
|
284
|
+
}
|
|
285
|
+
const index = tabs.findIndex((t) => t.number === num);
|
|
286
|
+
if (index === -1) {
|
|
287
|
+
showMessage(`No tab #${num}`);
|
|
288
|
+
break;
|
|
289
|
+
}
|
|
290
|
+
switchTab(index);
|
|
291
|
+
break;
|
|
292
|
+
}
|
|
293
|
+
case 'close': {
|
|
294
|
+
const num = args[0] ? parseInt(args[0], 10) : getActiveTab()?.number;
|
|
295
|
+
if (num === undefined || isNaN(num)) {
|
|
296
|
+
showMessage('Usage: /close [number]');
|
|
297
|
+
break;
|
|
298
|
+
}
|
|
299
|
+
closeTab(num);
|
|
300
|
+
break;
|
|
301
|
+
}
|
|
302
|
+
case 'sessions': {
|
|
303
|
+
const sessionInfo = [...escalationManager.state.sessions.values()]
|
|
304
|
+
.map((s) => ` [${s.displayNumber}] ${s.registration.sessionId.substring(0, 8)} ${s.registration.label}`)
|
|
305
|
+
.join('\n');
|
|
306
|
+
showMessage(sessionInfo || 'No active sessions');
|
|
307
|
+
break;
|
|
308
|
+
}
|
|
309
|
+
case 'quit':
|
|
310
|
+
case 'q':
|
|
311
|
+
doShutdown();
|
|
312
|
+
break;
|
|
313
|
+
default:
|
|
314
|
+
showMessage(`Unknown command: /${command}`);
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
function doShutdown() {
|
|
318
|
+
if (!running)
|
|
319
|
+
return;
|
|
320
|
+
running = false;
|
|
321
|
+
for (const tab of tabs) {
|
|
322
|
+
if (tab.bridge.alive) {
|
|
323
|
+
tab.bridge.kill();
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
escalationManager.stop();
|
|
327
|
+
if (term) {
|
|
328
|
+
term.grabInput(false);
|
|
329
|
+
term.hideCursor(false);
|
|
330
|
+
term.fullscreen(false);
|
|
331
|
+
term.styleReset();
|
|
332
|
+
}
|
|
333
|
+
renderer.destroy();
|
|
334
|
+
}
|
|
335
|
+
return {
|
|
336
|
+
async start() {
|
|
337
|
+
running = true;
|
|
338
|
+
const terminalKit = await import('terminal-kit');
|
|
339
|
+
// CJS interop: terminal lives on the default export object
|
|
340
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
341
|
+
term = terminalKit.default.terminal ?? terminalKit.terminal;
|
|
342
|
+
term.fullscreen(true);
|
|
343
|
+
term.hideCursor(true);
|
|
344
|
+
term.grabInput({ mouse: 'button' });
|
|
345
|
+
inputHandler = createMuxInputHandler({ initialMode: autoSpawn ? 'pty' : 'command' });
|
|
346
|
+
escalationManager = createMuxEscalationManager();
|
|
347
|
+
const { columns, rows } = process.stdout;
|
|
348
|
+
const cols = columns || 80;
|
|
349
|
+
const totalRows = rows || 24;
|
|
350
|
+
renderer = createMuxRenderer(term, cols, totalRows, {
|
|
351
|
+
getActiveTab,
|
|
352
|
+
getTabs: () => tabs,
|
|
353
|
+
getActiveTabIndex: () => activeTabIndex,
|
|
354
|
+
getMode: () => inputHandler.mode,
|
|
355
|
+
getInputBuffer: () => inputHandler.inputBuffer,
|
|
356
|
+
getCursorPos: () => inputHandler.cursorPos,
|
|
357
|
+
getEscalationState: () => escalationManager.state,
|
|
358
|
+
getPendingCount: () => escalationManager.pendingCount,
|
|
359
|
+
getPickerState: () => inputHandler.pickerState,
|
|
360
|
+
getScrollOffset: () => {
|
|
361
|
+
const active = getActiveTab();
|
|
362
|
+
return active?.scrollOffset ?? null;
|
|
363
|
+
},
|
|
364
|
+
});
|
|
365
|
+
term.on('key', (key) => {
|
|
366
|
+
if (!running)
|
|
367
|
+
return;
|
|
368
|
+
const action = inputHandler.handleKey(key);
|
|
369
|
+
void handleAction(action);
|
|
370
|
+
});
|
|
371
|
+
// Mouse events come through a separate 'mouse' emitter, not 'key'
|
|
372
|
+
term.on('mouse', (name) => {
|
|
373
|
+
if (!running)
|
|
374
|
+
return;
|
|
375
|
+
if (name === MOUSE_WHEEL_UP) {
|
|
376
|
+
void handleAction({ kind: 'scroll-up', amount: SCROLL_LINES });
|
|
377
|
+
}
|
|
378
|
+
else if (name === MOUSE_WHEEL_DOWN) {
|
|
379
|
+
void handleAction({ kind: 'scroll-down', amount: SCROLL_LINES });
|
|
380
|
+
}
|
|
381
|
+
});
|
|
382
|
+
process.stdout.on('resize', () => {
|
|
383
|
+
const { columns: newCols, rows: newRows } = process.stdout;
|
|
384
|
+
if (!newCols || !newRows)
|
|
385
|
+
return;
|
|
386
|
+
renderer.resize(newCols, newRows);
|
|
387
|
+
const layout = renderer.layout;
|
|
388
|
+
for (const tab of tabs) {
|
|
389
|
+
if (tab.bridge.alive) {
|
|
390
|
+
tab.bridge.resize(newCols, layout.ptyViewportRows);
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
renderer.fullRedraw();
|
|
394
|
+
});
|
|
395
|
+
escalationManager.onChange(() => {
|
|
396
|
+
renderer.redrawTabBar();
|
|
397
|
+
renderer.redrawCommandArea();
|
|
398
|
+
});
|
|
399
|
+
escalationManager.startRegistryPolling();
|
|
400
|
+
// Back-fill bridge registrations that timed out during initial
|
|
401
|
+
// discovery. When registry polling finds a session whose PID
|
|
402
|
+
// matches a bridge that still has no registration, push it in.
|
|
403
|
+
escalationManager.onSessionDiscovered((reg) => {
|
|
404
|
+
for (const tab of tabs) {
|
|
405
|
+
if (tab.bridge.pid === reg.pid && !tab.bridge.sessionId) {
|
|
406
|
+
tab.bridge.updateRegistration(reg);
|
|
407
|
+
tab.escalationAvailable = true;
|
|
408
|
+
tab.label = reg.label;
|
|
409
|
+
escalationManager.claimSession(reg.sessionId);
|
|
410
|
+
renderer.redrawTabBar();
|
|
411
|
+
break;
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
});
|
|
415
|
+
const handleSignal = () => {
|
|
416
|
+
doShutdown();
|
|
417
|
+
};
|
|
418
|
+
process.on('SIGINT', handleSignal);
|
|
419
|
+
process.on('SIGTERM', handleSignal);
|
|
420
|
+
process.on('SIGHUP', handleSignal);
|
|
421
|
+
process.on('exit', () => {
|
|
422
|
+
if (term) {
|
|
423
|
+
term.grabInput(false);
|
|
424
|
+
}
|
|
425
|
+
});
|
|
426
|
+
if (autoSpawn) {
|
|
427
|
+
await spawnSession();
|
|
428
|
+
}
|
|
429
|
+
renderer.fullRedraw();
|
|
430
|
+
await new Promise((resolve) => {
|
|
431
|
+
const checkInterval = setInterval(() => {
|
|
432
|
+
if (!running) {
|
|
433
|
+
clearInterval(checkInterval);
|
|
434
|
+
resolve();
|
|
435
|
+
}
|
|
436
|
+
}, 100);
|
|
437
|
+
});
|
|
438
|
+
},
|
|
439
|
+
// eslint-disable-next-line @typescript-eslint/require-await
|
|
440
|
+
async shutdown() {
|
|
441
|
+
doShutdown();
|
|
442
|
+
},
|
|
443
|
+
};
|
|
444
|
+
}
|
|
445
|
+
//# sourceMappingURL=mux-app.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mux-app.js","sourceRoot":"","sources":["../../src/mux/mux-app.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI entry point for `ironcurtain mux`.
|
|
3
|
+
*
|
|
4
|
+
* Parses command-line options, loads config, acquires the listener lock,
|
|
5
|
+
* creates the MuxApp, and runs until quit.
|
|
6
|
+
*/
|
|
7
|
+
import chalk from 'chalk';
|
|
8
|
+
import { mkdirSync } from 'node:fs';
|
|
9
|
+
import { getListenerLockPath, getPtyRegistryDir } from '../config/paths.js';
|
|
10
|
+
import { acquireLock, releaseLock } from '../escalation/listener-lock.js';
|
|
11
|
+
import { loadUserConfig } from '../config/user-config.js';
|
|
12
|
+
import { parseModelId, resolveApiKeyForProvider } from '../config/model-provider.js';
|
|
13
|
+
import { loadConfig } from '../config/index.js';
|
|
14
|
+
import { createMuxApp } from './mux-app.js';
|
|
15
|
+
export async function main(args) {
|
|
16
|
+
// Check for optional mux dependencies
|
|
17
|
+
try {
|
|
18
|
+
await import('node-pty');
|
|
19
|
+
}
|
|
20
|
+
catch {
|
|
21
|
+
process.stderr.write(chalk.red('Error: ironcurtain mux requires the node-pty package.\n') + 'Install it with: npm install node-pty\n');
|
|
22
|
+
process.exit(1);
|
|
23
|
+
}
|
|
24
|
+
try {
|
|
25
|
+
await import('terminal-kit');
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
process.stderr.write(chalk.red('Error: ironcurtain mux requires the terminal-kit package.\n') +
|
|
29
|
+
'Install it with: npm install terminal-kit\n');
|
|
30
|
+
process.exit(1);
|
|
31
|
+
}
|
|
32
|
+
// Parse args
|
|
33
|
+
let agent = 'claude-code';
|
|
34
|
+
if (args) {
|
|
35
|
+
for (let i = 0; i < args.length; i++) {
|
|
36
|
+
if ((args[i] === '--agent' || args[i] === '-a') && args[i + 1]) {
|
|
37
|
+
agent = args[i + 1];
|
|
38
|
+
i++;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
// Acquire single-instance lock
|
|
43
|
+
const lockPath = getListenerLockPath();
|
|
44
|
+
if (!acquireLock(lockPath)) {
|
|
45
|
+
process.stderr.write(chalk.red('Another escalation listener or mux is already running.\n') +
|
|
46
|
+
'Only one instance can run at a time to prevent escalation conflicts.\n');
|
|
47
|
+
process.exit(1);
|
|
48
|
+
}
|
|
49
|
+
// Ensure registry directory exists
|
|
50
|
+
const registryDir = getPtyRegistryDir();
|
|
51
|
+
mkdirSync(registryDir, { recursive: true, mode: 0o700 });
|
|
52
|
+
// Pre-flight warnings (shown before fullscreen takes over)
|
|
53
|
+
let hasWarnings = false;
|
|
54
|
+
try {
|
|
55
|
+
const userConfig = loadUserConfig({ readOnly: true });
|
|
56
|
+
if (userConfig.autoApprove.enabled) {
|
|
57
|
+
const { provider } = parseModelId(userConfig.autoApprove.modelId);
|
|
58
|
+
const apiKey = resolveApiKeyForProvider(provider, userConfig);
|
|
59
|
+
if (!apiKey) {
|
|
60
|
+
process.stderr.write(chalk.yellow(`Warning: auto-approve is enabled but no API key found for provider "${provider}".\n` +
|
|
61
|
+
'Auto-approve will be silently disabled. Set the API key in your environment or config.\n'));
|
|
62
|
+
hasWarnings = true;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
catch {
|
|
67
|
+
// Config load failure is not fatal here -- the child sessions will report it.
|
|
68
|
+
}
|
|
69
|
+
if (hasWarnings) {
|
|
70
|
+
process.stderr.write(chalk.dim('\nStarting in 3 seconds...\n'));
|
|
71
|
+
await new Promise((r) => setTimeout(r, 3000));
|
|
72
|
+
}
|
|
73
|
+
// Load config once for workspace validation
|
|
74
|
+
let protectedPaths = [];
|
|
75
|
+
try {
|
|
76
|
+
protectedPaths = loadConfig().protectedPaths;
|
|
77
|
+
}
|
|
78
|
+
catch {
|
|
79
|
+
// Config load failure is not fatal; child sessions will report it.
|
|
80
|
+
}
|
|
81
|
+
try {
|
|
82
|
+
const app = createMuxApp({
|
|
83
|
+
agent,
|
|
84
|
+
autoSpawn: false,
|
|
85
|
+
protectedPaths,
|
|
86
|
+
});
|
|
87
|
+
await app.start();
|
|
88
|
+
}
|
|
89
|
+
finally {
|
|
90
|
+
releaseLock(lockPath);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
//# sourceMappingURL=mux-command.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mux-command.js","sourceRoot":"","sources":["../../src/mux/mux-command.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MuxEscalationManager -- manages escalation watchers for all PTY sessions.
|
|
3
|
+
*
|
|
4
|
+
* Wraps the existing EscalationWatcher and ListenerState modules for the
|
|
5
|
+
* mux context. Creates watchers directly when sessions are spawned, and
|
|
6
|
+
* optionally polls the PTY registry for externally-spawned sessions.
|
|
7
|
+
*/
|
|
8
|
+
import type { PtySessionRegistration } from '../docker/pty-types.js';
|
|
9
|
+
import { type ListenerState } from '../escalation/listener-state.js';
|
|
10
|
+
export interface MuxEscalationManager {
|
|
11
|
+
/** Current state (sessions, pending escalations, history). */
|
|
12
|
+
readonly state: ListenerState;
|
|
13
|
+
/** Number of pending escalations across all sessions. */
|
|
14
|
+
readonly pendingCount: number;
|
|
15
|
+
/**
|
|
16
|
+
* Registers a session for escalation watching.
|
|
17
|
+
*/
|
|
18
|
+
addSession(registration: PtySessionRegistration): void;
|
|
19
|
+
/**
|
|
20
|
+
* Removes a session's watcher.
|
|
21
|
+
*/
|
|
22
|
+
removeSession(sessionId: string): void;
|
|
23
|
+
/** Resolves a pending escalation by display number. */
|
|
24
|
+
resolve(displayNumber: number, decision: 'approved' | 'denied'): string;
|
|
25
|
+
/** Resolves all pending escalations. */
|
|
26
|
+
resolveAll(decision: 'approved' | 'denied'): string;
|
|
27
|
+
/** Starts polling for externally-spawned sessions. */
|
|
28
|
+
startRegistryPolling(): void;
|
|
29
|
+
/** Stops all watchers and polling. */
|
|
30
|
+
stop(): void;
|
|
31
|
+
/** Register callback for state changes (triggers redraws). */
|
|
32
|
+
onChange(callback: () => void): void;
|
|
33
|
+
/**
|
|
34
|
+
* Registers a callback fired when registry polling discovers a new
|
|
35
|
+
* external session. Used to back-fill bridge registrations that
|
|
36
|
+
* timed out during initial discovery.
|
|
37
|
+
*/
|
|
38
|
+
onSessionDiscovered(callback: (reg: PtySessionRegistration) => void): void;
|
|
39
|
+
/**
|
|
40
|
+
* Marks a session ID as managed so registry polling treats it as
|
|
41
|
+
* owned by the mux (won't re-add after removal).
|
|
42
|
+
*/
|
|
43
|
+
claimSession(sessionId: string): void;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Creates a new MuxEscalationManager.
|
|
47
|
+
*/
|
|
48
|
+
export declare function createMuxEscalationManager(): MuxEscalationManager;
|