@provos/ironcurtain 0.4.1 → 0.5.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 (140) hide show
  1. package/README.md +219 -248
  2. package/dist/cli.js +10 -0
  3. package/dist/cli.js.map +1 -1
  4. package/dist/config/config-command.js +144 -6
  5. package/dist/config/config-command.js.map +1 -1
  6. package/dist/config/constitution-user-base.md +2 -0
  7. package/dist/config/first-start.js +77 -12
  8. package/dist/config/first-start.js.map +1 -1
  9. package/dist/config/generated/compiled-policy.json +199 -72
  10. package/dist/config/generated/tool-annotations.json +1018 -36
  11. package/dist/config/mcp-servers.json +10 -0
  12. package/dist/config/paths.d.ts +31 -0
  13. package/dist/config/paths.js +52 -2
  14. package/dist/config/paths.js.map +1 -1
  15. package/dist/config/types.d.ts +8 -0
  16. package/dist/config/user-config.d.ts +21 -3
  17. package/dist/config/user-config.js +34 -3
  18. package/dist/config/user-config.js.map +1 -1
  19. package/dist/docker/adapters/claude-code.js +64 -8
  20. package/dist/docker/adapters/claude-code.js.map +1 -1
  21. package/dist/docker/agent-adapter.d.ts +18 -1
  22. package/dist/docker/docker-agent-session.d.ts +15 -8
  23. package/dist/docker/docker-agent-session.js +61 -88
  24. package/dist/docker/docker-agent-session.js.map +1 -1
  25. package/dist/docker/docker-infrastructure.d.ts +51 -0
  26. package/dist/docker/docker-infrastructure.js +261 -0
  27. package/dist/docker/docker-infrastructure.js.map +1 -0
  28. package/dist/docker/docker-manager.js +3 -0
  29. package/dist/docker/docker-manager.js.map +1 -1
  30. package/dist/docker/mitm-proxy.js +4 -0
  31. package/dist/docker/mitm-proxy.js.map +1 -1
  32. package/dist/docker/oauth-credentials.d.ts +81 -0
  33. package/dist/docker/oauth-credentials.js +178 -0
  34. package/dist/docker/oauth-credentials.js.map +1 -0
  35. package/dist/docker/orientation.js +1 -1
  36. package/dist/docker/orientation.js.map +1 -1
  37. package/dist/docker/provider-config.d.ts +3 -0
  38. package/dist/docker/provider-config.js +28 -0
  39. package/dist/docker/provider-config.js.map +1 -1
  40. package/dist/docker/pty-session.d.ts +27 -0
  41. package/dist/docker/pty-session.js +420 -0
  42. package/dist/docker/pty-session.js.map +1 -0
  43. package/dist/docker/pty-types.d.ts +24 -0
  44. package/dist/docker/pty-types.js +12 -0
  45. package/dist/docker/pty-types.js.map +1 -0
  46. package/dist/docker/types.d.ts +6 -0
  47. package/dist/escalation/escalation-watcher.d.ts +44 -0
  48. package/dist/escalation/escalation-watcher.js +92 -0
  49. package/dist/escalation/escalation-watcher.js.map +1 -0
  50. package/dist/escalation/listener-command.d.ts +10 -0
  51. package/dist/escalation/listener-command.js +407 -0
  52. package/dist/escalation/listener-command.js.map +1 -0
  53. package/dist/escalation/listener-state.d.ts +49 -0
  54. package/dist/escalation/listener-state.js +104 -0
  55. package/dist/escalation/listener-state.js.map +1 -0
  56. package/dist/escalation/session-registry.d.ts +17 -0
  57. package/dist/escalation/session-registry.js +98 -0
  58. package/dist/escalation/session-registry.js.map +1 -0
  59. package/dist/index.js +15 -0
  60. package/dist/index.js.map +1 -1
  61. package/dist/logger.js +2 -3
  62. package/dist/logger.js.map +1 -1
  63. package/dist/pipeline/annotate.js +35 -15
  64. package/dist/pipeline/annotate.js.map +1 -1
  65. package/dist/pipeline/constitution-customizer.d.ts +2 -1
  66. package/dist/pipeline/constitution-customizer.js +36 -3
  67. package/dist/pipeline/constitution-customizer.js.map +1 -1
  68. package/dist/pipeline/github-identity.d.ts +38 -0
  69. package/dist/pipeline/github-identity.js +64 -0
  70. package/dist/pipeline/github-identity.js.map +1 -0
  71. package/dist/pipeline/handwritten-scenarios.js +34 -0
  72. package/dist/pipeline/handwritten-scenarios.js.map +1 -1
  73. package/dist/sandbox/index.js +12 -3
  74. package/dist/sandbox/index.js.map +1 -1
  75. package/dist/servers/fetch-server.js +2 -2
  76. package/dist/session/base-transport.d.ts +19 -0
  77. package/dist/session/base-transport.js +36 -0
  78. package/dist/session/base-transport.js.map +1 -0
  79. package/dist/session/cli-transport.d.ts +3 -3
  80. package/dist/session/cli-transport.js +7 -4
  81. package/dist/session/cli-transport.js.map +1 -1
  82. package/dist/session/index.js +24 -78
  83. package/dist/session/index.js.map +1 -1
  84. package/dist/session/interaction-log.d.ts +13 -0
  85. package/dist/session/interaction-log.js +28 -0
  86. package/dist/session/interaction-log.js.map +1 -0
  87. package/dist/session/preflight.d.ts +3 -0
  88. package/dist/session/preflight.js +39 -18
  89. package/dist/session/preflight.js.map +1 -1
  90. package/dist/session/types.d.ts +2 -0
  91. package/dist/signal/bot-command.js +5 -0
  92. package/dist/signal/bot-command.js.map +1 -1
  93. package/dist/signal/format.d.ts +21 -1
  94. package/dist/signal/format.js +41 -3
  95. package/dist/signal/format.js.map +1 -1
  96. package/dist/signal/signal-bot-daemon.d.ts +53 -18
  97. package/dist/signal/signal-bot-daemon.js +344 -106
  98. package/dist/signal/signal-bot-daemon.js.map +1 -1
  99. package/dist/signal/signal-config.d.ts +4 -0
  100. package/dist/signal/signal-config.js +2 -0
  101. package/dist/signal/signal-config.js.map +1 -1
  102. package/dist/signal/signal-transport.d.ts +13 -7
  103. package/dist/signal/signal-transport.js +36 -12
  104. package/dist/signal/signal-transport.js.map +1 -1
  105. package/dist/trusted-process/audit-log.d.ts +6 -1
  106. package/dist/trusted-process/audit-log.js +22 -2
  107. package/dist/trusted-process/audit-log.js.map +1 -1
  108. package/dist/trusted-process/audit-redactor.d.ts +25 -0
  109. package/dist/trusted-process/audit-redactor.js +121 -0
  110. package/dist/trusted-process/audit-redactor.js.map +1 -0
  111. package/dist/trusted-process/escalation.d.ts +1 -1
  112. package/dist/trusted-process/escalation.js +6 -1
  113. package/dist/trusted-process/escalation.js.map +1 -1
  114. package/dist/trusted-process/index.d.ts +2 -1
  115. package/dist/trusted-process/index.js +24 -6
  116. package/dist/trusted-process/index.js.map +1 -1
  117. package/dist/trusted-process/mcp-client-manager.js +14 -2
  118. package/dist/trusted-process/mcp-client-manager.js.map +1 -1
  119. package/dist/trusted-process/mcp-error-utils.d.ts +11 -0
  120. package/dist/trusted-process/mcp-error-utils.js +50 -0
  121. package/dist/trusted-process/mcp-error-utils.js.map +1 -0
  122. package/dist/trusted-process/mcp-proxy-server.d.ts +4 -0
  123. package/dist/trusted-process/mcp-proxy-server.js +14 -4
  124. package/dist/trusted-process/mcp-proxy-server.js.map +1 -1
  125. package/dist/trusted-process/sandbox-integration.d.ts +5 -0
  126. package/dist/trusted-process/sandbox-integration.js +1 -1
  127. package/dist/trusted-process/sandbox-integration.js.map +1 -1
  128. package/dist/trusted-process/server-context.d.ts +21 -0
  129. package/dist/trusted-process/server-context.js +42 -0
  130. package/dist/trusted-process/server-context.js.map +1 -0
  131. package/dist/types/argument-roles.d.ts +5 -2
  132. package/dist/types/argument-roles.js +25 -2
  133. package/dist/types/argument-roles.js.map +1 -1
  134. package/docker/Dockerfile.claude-code +8 -3
  135. package/docker/entrypoint-claude-code.sh +64 -4
  136. package/package.json +16 -8
  137. package/src/config/constitution-user-base.md +2 -0
  138. package/src/config/generated/compiled-policy.json +199 -72
  139. package/src/config/generated/tool-annotations.json +1018 -36
  140. package/src/config/mcp-servers.json +10 -0
@@ -0,0 +1,407 @@
1
+ /**
2
+ * Escalation listener CLI command.
3
+ *
4
+ * Polls the PTY session registry directory for active sessions, watches
5
+ * each session's escalation directory for new requests, and presents
6
+ * a terminal dashboard where the user can approve or deny escalations.
7
+ *
8
+ * Usage: ironcurtain escalation-listener
9
+ */
10
+ import { createInterface } from 'node:readline';
11
+ import { existsSync, mkdirSync, writeSync, readFileSync, unlinkSync, openSync, closeSync, constants } from 'node:fs';
12
+ import chalk from 'chalk';
13
+ import { getPtyRegistryDir, getListenerLockPath } from '../config/paths.js';
14
+ import { readActiveRegistrations } from './session-registry.js';
15
+ import { createEscalationWatcher } from './escalation-watcher.js';
16
+ import { createInitialState, addSession, removeSession, addEscalation, resolveEscalation, expireEscalation, } from './listener-state.js';
17
+ /** Poll interval for the session registry directory (ms). */
18
+ const REGISTRY_POLL_INTERVAL_MS = 1000;
19
+ export async function main() {
20
+ // Single-instance enforcement
21
+ const lockPath = getListenerLockPath();
22
+ if (!acquireLock(lockPath)) {
23
+ process.stderr.write(chalk.red('Another escalation listener is already running.\n'));
24
+ process.exit(1);
25
+ }
26
+ const registryDir = getPtyRegistryDir();
27
+ mkdirSync(registryDir, { recursive: true, mode: 0o700 });
28
+ let state = createInitialState();
29
+ let running = true;
30
+ let lastRenderedContent = '';
31
+ // Set up readline for command input
32
+ const rl = createInterface({
33
+ input: process.stdin,
34
+ output: process.stderr,
35
+ terminal: true,
36
+ });
37
+ /**
38
+ * Renders the dashboard only if the content has actually changed.
39
+ * Uses cursor repositioning (move to home) instead of screen clear
40
+ * to avoid destroying readline's input buffer.
41
+ */
42
+ const render = () => {
43
+ const content = buildDashboard(state);
44
+ if (content === lastRenderedContent)
45
+ return;
46
+ lastRenderedContent = content;
47
+ // Move cursor to home position, write content with per-line clearing,
48
+ // then clear any remaining lines below. The per-line \x1b[K (clear to
49
+ // end of line) is needed because shorter new lines would otherwise leave
50
+ // leftover characters from the previous (longer) dashboard render.
51
+ process.stderr.write('\x1b[H\x1b[K' + content.replace(/\n/g, '\x1b[K\n') + '\x1b[J');
52
+ // Force readline to redisplay its prompt + current input buffer
53
+ rl.prompt(true);
54
+ };
55
+ // Poll for new/removed sessions
56
+ const registryPollInterval = setInterval(() => {
57
+ const registrations = readActiveRegistrations(registryDir);
58
+ const currentIds = new Set(registrations.map((r) => r.sessionId));
59
+ const stateIds = new Set(state.sessions.keys());
60
+ let changed = false;
61
+ // Add new sessions
62
+ for (const reg of registrations) {
63
+ if (!stateIds.has(reg.sessionId)) {
64
+ const watcher = createWatcherForSession(reg, (newState) => {
65
+ state = newState;
66
+ render();
67
+ }, () => state);
68
+ state = addSession(state, reg, watcher);
69
+ watcher.start();
70
+ changed = true;
71
+ }
72
+ }
73
+ // Remove gone sessions
74
+ for (const id of stateIds) {
75
+ if (!currentIds.has(id)) {
76
+ const session = state.sessions.get(id);
77
+ session?.watcher.stop();
78
+ state = removeSession(state, id);
79
+ changed = true;
80
+ }
81
+ }
82
+ if (changed)
83
+ render();
84
+ }, REGISTRY_POLL_INTERVAL_MS);
85
+ // Initial render: clear screen once, then use repositioning from now on
86
+ rl.setPrompt(' > ');
87
+ process.stderr.write('\x1b[2J');
88
+ render();
89
+ // Handle commands
90
+ rl.on('line', (line) => {
91
+ const trimmed = line.trim();
92
+ if (!trimmed) {
93
+ render();
94
+ return;
95
+ }
96
+ const result = handleCommand(trimmed, state);
97
+ state = result.state;
98
+ if (result.quit) {
99
+ if (result.message) {
100
+ process.stderr.write(result.message + '\n');
101
+ }
102
+ running = false;
103
+ rl.close();
104
+ return;
105
+ }
106
+ // Force a re-render by invalidating the cache
107
+ lastRenderedContent = '';
108
+ if (result.message) {
109
+ // Render first so the message appears below the dashboard
110
+ render();
111
+ process.stderr.write(result.message + '\n');
112
+ rl.prompt(true);
113
+ }
114
+ else {
115
+ render();
116
+ }
117
+ });
118
+ rl.on('close', () => {
119
+ running = false;
120
+ });
121
+ // Wait until quit
122
+ await new Promise((resolve) => {
123
+ const checkInterval = setInterval(() => {
124
+ if (!running) {
125
+ clearInterval(checkInterval);
126
+ resolve();
127
+ }
128
+ }, 100);
129
+ });
130
+ // Cleanup
131
+ clearInterval(registryPollInterval);
132
+ for (const session of state.sessions.values()) {
133
+ session.watcher.stop();
134
+ }
135
+ releaseLock(lockPath);
136
+ }
137
+ // --- Lock management ---
138
+ /**
139
+ * Acquires the listener lock file using O_EXCL for atomicity.
140
+ * Returns true if the lock was acquired, false if another instance holds it.
141
+ */
142
+ function acquireLock(lockPath) {
143
+ if (existsSync(lockPath)) {
144
+ // Check if the PID in the lock file is still alive
145
+ try {
146
+ const content = readFileSync(lockPath, 'utf-8');
147
+ const pid = parseInt(content.trim(), 10);
148
+ if (!isNaN(pid) && isPidAlive(pid)) {
149
+ return false; // Another instance is running
150
+ }
151
+ // Stale lock -- remove and try again
152
+ unlinkSync(lockPath);
153
+ }
154
+ catch {
155
+ // If we can't read the lock, try to recreate it
156
+ try {
157
+ unlinkSync(lockPath);
158
+ }
159
+ catch {
160
+ return false;
161
+ }
162
+ }
163
+ }
164
+ try {
165
+ const fd = openSync(lockPath, constants.O_WRONLY | constants.O_CREAT | constants.O_EXCL, 0o600);
166
+ const content = Buffer.from(String(process.pid));
167
+ writeSync(fd, content);
168
+ closeSync(fd);
169
+ return true;
170
+ }
171
+ catch {
172
+ return false;
173
+ }
174
+ }
175
+ function releaseLock(lockPath) {
176
+ try {
177
+ unlinkSync(lockPath);
178
+ }
179
+ catch {
180
+ /* best effort */
181
+ }
182
+ }
183
+ function isPidAlive(pid) {
184
+ try {
185
+ process.kill(pid, 0);
186
+ return true;
187
+ }
188
+ catch {
189
+ return false;
190
+ }
191
+ }
192
+ // --- Watcher creation ---
193
+ function createWatcherForSession(registration, onStateChange, getState) {
194
+ return createEscalationWatcher(registration.escalationDir, {
195
+ onEscalation: (request) => {
196
+ const newState = addEscalation(getState(), registration.sessionId, request);
197
+ onStateChange(newState);
198
+ // BEL character alerts the user
199
+ process.stderr.write('\x07');
200
+ },
201
+ onEscalationExpired: (escalationId) => {
202
+ const newState = expireEscalation(getState(), registration.sessionId, escalationId);
203
+ onStateChange(newState);
204
+ },
205
+ }, { pollIntervalMs: 300 });
206
+ }
207
+ function handleCommand(input, state) {
208
+ const parts = input.split(/\s+/);
209
+ const command = parts[0].toLowerCase();
210
+ switch (command) {
211
+ case '/approve': {
212
+ const arg = parts[1];
213
+ if (!arg)
214
+ return { state, message: chalk.yellow('Usage: /approve <number> or /approve all') };
215
+ if (arg === 'all') {
216
+ return approveOrDenyAll(state, 'approved');
217
+ }
218
+ const num = parseInt(arg, 10);
219
+ if (isNaN(num))
220
+ return { state, message: chalk.yellow('Invalid escalation number') };
221
+ return approveOrDeny(state, num, 'approved');
222
+ }
223
+ case '/deny': {
224
+ const arg = parts[1];
225
+ if (!arg)
226
+ return { state, message: chalk.yellow('Usage: /deny <number> or /deny all') };
227
+ if (arg === 'all') {
228
+ return approveOrDenyAll(state, 'denied');
229
+ }
230
+ const num = parseInt(arg, 10);
231
+ if (isNaN(num))
232
+ return { state, message: chalk.yellow('Invalid escalation number') };
233
+ return approveOrDeny(state, num, 'denied');
234
+ }
235
+ case '/sessions':
236
+ return { state, message: formatSessionDetails(state) };
237
+ case '/quit':
238
+ case '/q':
239
+ return { state, quit: true };
240
+ default:
241
+ return {
242
+ state,
243
+ message: chalk.yellow('Unknown command. Available: /approve <N>, /deny <N>, /approve all, /deny all, /sessions, /quit'),
244
+ };
245
+ }
246
+ }
247
+ function approveOrDeny(state, displayNumber, decision) {
248
+ const escalation = state.pendingEscalations.get(displayNumber);
249
+ if (!escalation) {
250
+ return { state, message: chalk.yellow(`No pending escalation #${displayNumber}`) };
251
+ }
252
+ const session = state.sessions.get(escalation.sessionId);
253
+ if (!session) {
254
+ return { state, message: chalk.yellow(`Session for escalation #${displayNumber} no longer active`) };
255
+ }
256
+ try {
257
+ const accepted = session.watcher.resolve(escalation.request.escalationId, decision);
258
+ const newState = resolveEscalation(state, displayNumber, decision);
259
+ if (!accepted) {
260
+ return {
261
+ state: newState,
262
+ message: chalk.yellow(`Escalation #${displayNumber} expired (response was too late)`),
263
+ };
264
+ }
265
+ const label = decision === 'approved' ? chalk.green('APPROVED') : chalk.red('DENIED');
266
+ return {
267
+ state: newState,
268
+ message: `Escalation #${displayNumber} ${label}`,
269
+ };
270
+ }
271
+ catch (err) {
272
+ return { state, message: chalk.red(`Error: ${err instanceof Error ? err.message : String(err)}`) };
273
+ }
274
+ }
275
+ function approveOrDenyAll(state, decision) {
276
+ if (state.pendingEscalations.size === 0) {
277
+ return { state, message: chalk.yellow('No pending escalations') };
278
+ }
279
+ let currentState = state;
280
+ const messages = [];
281
+ const nums = [...state.pendingEscalations.keys()].sort((a, b) => a - b);
282
+ for (const num of nums) {
283
+ const result = approveOrDeny(currentState, num, decision);
284
+ currentState = result.state;
285
+ if (result.message)
286
+ messages.push(result.message);
287
+ }
288
+ return { state: currentState, message: messages.join('\n') };
289
+ }
290
+ function formatSessionDetails(state) {
291
+ if (state.sessions.size === 0) {
292
+ return chalk.dim('No active sessions');
293
+ }
294
+ const lines = [];
295
+ for (const session of state.sessions.values()) {
296
+ const reg = session.registration;
297
+ const ago = formatTimeAgo(new Date(reg.startedAt));
298
+ lines.push(` [${session.displayNumber}] ${reg.sessionId.substring(0, 8)} ${reg.label} ${chalk.dim(ago)}`);
299
+ }
300
+ return lines.join('\n');
301
+ }
302
+ // --- Rendering ---
303
+ /**
304
+ * Builds the dashboard content as a string.
305
+ * Pure function — no side effects. The caller handles writing to the terminal
306
+ * and coordinating with readline's prompt.
307
+ */
308
+ function buildDashboard(state) {
309
+ const lines = [];
310
+ const sessionCount = state.sessions.size;
311
+ const pendingCount = state.pendingEscalations.size;
312
+ // Header
313
+ lines.push(chalk.bold.cyan(' IronCurtain Escalation Listener') +
314
+ chalk.dim(` ${sessionCount} session${sessionCount !== 1 ? 's' : ''} active`));
315
+ lines.push(chalk.dim(' ' + '\u2500'.repeat(60)));
316
+ // Active Sessions
317
+ lines.push('');
318
+ lines.push(chalk.bold(' Active Sessions:'));
319
+ if (sessionCount === 0) {
320
+ lines.push(chalk.dim(' Waiting for PTY sessions...'));
321
+ }
322
+ else {
323
+ for (const session of state.sessions.values()) {
324
+ const reg = session.registration;
325
+ const ago = formatTimeAgo(new Date(reg.startedAt));
326
+ const sessionPending = countPendingForSession(state, reg.sessionId);
327
+ const pendingLabel = sessionPending > 0 ? chalk.yellow(` ${sessionPending} pending`) : chalk.dim(' 0 pending');
328
+ lines.push(` [${chalk.bold(String(session.displayNumber))}] ` +
329
+ `${reg.sessionId.substring(0, 8)} ` +
330
+ `${reg.label.substring(0, 40)} ` +
331
+ chalk.dim(ago) +
332
+ pendingLabel);
333
+ }
334
+ }
335
+ // Pending Escalations
336
+ lines.push('');
337
+ lines.push(chalk.dim(' ' + '\u2500'.repeat(60)));
338
+ lines.push('');
339
+ lines.push(chalk.bold(' Pending Escalations:') + (pendingCount === 0 ? chalk.dim(' (none)') : ''));
340
+ if (pendingCount > 0) {
341
+ const sorted = [...state.pendingEscalations.values()].sort((a, b) => a.displayNumber - b.displayNumber);
342
+ for (const esc of sorted) {
343
+ lines.push('');
344
+ lines.push(` [${chalk.bold.yellow(String(esc.displayNumber))}] ` +
345
+ `Session #${esc.sessionDisplayNumber} (${esc.sessionId.substring(0, 8)})`);
346
+ lines.push(` Tool: ${chalk.cyan(esc.request.serverName + '/' + esc.request.toolName)}`);
347
+ const argPreview = formatArgPreview(esc.request.arguments);
348
+ if (argPreview) {
349
+ lines.push(` Args: ${argPreview}`);
350
+ }
351
+ lines.push(` Reason: ${esc.request.reason}`);
352
+ if (esc.request.context) {
353
+ for (const [k, v] of Object.entries(esc.request.context)) {
354
+ lines.push(` ${k}: ${chalk.yellow(v)}`);
355
+ }
356
+ }
357
+ }
358
+ }
359
+ // History
360
+ if (state.history.length > 0) {
361
+ lines.push('');
362
+ lines.push(chalk.dim(' ' + '\u2500'.repeat(60)));
363
+ lines.push('');
364
+ lines.push(chalk.bold(' History (last 10):'));
365
+ const recent = state.history.slice(0, 10);
366
+ for (const entry of recent) {
367
+ const time = entry.resolvedAt.toLocaleTimeString();
368
+ const decisionLabel = entry.decision === 'approved' ? chalk.green('APPROVED') : chalk.red('DENIED');
369
+ lines.push(` [${chalk.dim(time)}] ` + `${entry.serverName}/${entry.toolName} ` + decisionLabel);
370
+ }
371
+ }
372
+ // Command hint (prompt itself is handled by readline)
373
+ lines.push('');
374
+ lines.push(chalk.dim(' ' + '\u2500'.repeat(60)));
375
+ lines.push(chalk.dim(' /approve N | /deny N | /approve all | /deny all | /quit'));
376
+ return lines.join('\n') + '\n';
377
+ }
378
+ // --- Helpers ---
379
+ function countPendingForSession(state, sessionId) {
380
+ let count = 0;
381
+ for (const esc of state.pendingEscalations.values()) {
382
+ if (esc.sessionId === sessionId)
383
+ count++;
384
+ }
385
+ return count;
386
+ }
387
+ function formatTimeAgo(date) {
388
+ const seconds = Math.floor((Date.now() - date.getTime()) / 1000);
389
+ if (seconds < 60)
390
+ return `${seconds}s ago`;
391
+ const minutes = Math.floor(seconds / 60);
392
+ if (minutes < 60)
393
+ return `${minutes}m ago`;
394
+ const hours = Math.floor(minutes / 60);
395
+ return `${hours}h ago`;
396
+ }
397
+ function formatArgPreview(args) {
398
+ const parts = [];
399
+ for (const [key, value] of Object.entries(args)) {
400
+ if (typeof value === 'string') {
401
+ const display = value.length > 60 ? value.substring(0, 57) + '...' : value;
402
+ parts.push(`${key}: ${display}`);
403
+ }
404
+ }
405
+ return parts.slice(0, 3).join(', ');
406
+ }
407
+ //# sourceMappingURL=listener-command.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"listener-command.js","sourceRoot":"","sources":["../../src/escalation/listener-command.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,SAAS,EAAE,YAAY,EAAE,UAAU,EAAE,QAAQ,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACrH,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAC5E,OAAO,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AAChE,OAAO,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AAGlE,OAAO,EACL,kBAAkB,EAClB,UAAU,EACV,aAAa,EACb,aAAa,EACb,iBAAiB,EACjB,gBAAgB,GAEjB,MAAM,qBAAqB,CAAC;AAE7B,6DAA6D;AAC7D,MAAM,yBAAyB,GAAG,IAAI,CAAC;AAEvC,MAAM,CAAC,KAAK,UAAU,IAAI;IACxB,8BAA8B;IAC9B,MAAM,QAAQ,GAAG,mBAAmB,EAAE,CAAC;IACvC,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC3B,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,mDAAmD,CAAC,CAAC,CAAC;QACrF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,WAAW,GAAG,iBAAiB,EAAE,CAAC;IACxC,SAAS,CAAC,WAAW,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IAEzD,IAAI,KAAK,GAAG,kBAAkB,EAAE,CAAC;IACjC,IAAI,OAAO,GAAG,IAAI,CAAC;IACnB,IAAI,mBAAmB,GAAG,EAAE,CAAC;IAE7B,oCAAoC;IACpC,MAAM,EAAE,GAAG,eAAe,CAAC;QACzB,KAAK,EAAE,OAAO,CAAC,KAAK;QACpB,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,QAAQ,EAAE,IAAI;KACf,CAAC,CAAC;IAEH;;;;OAIG;IACH,MAAM,MAAM,GAAG,GAAS,EAAE;QACxB,MAAM,OAAO,GAAG,cAAc,CAAC,KAAK,CAAC,CAAC;QACtC,IAAI,OAAO,KAAK,mBAAmB;YAAE,OAAO;QAC5C,mBAAmB,GAAG,OAAO,CAAC;QAE9B,sEAAsE;QACtE,sEAAsE;QACtE,yEAAyE;QACzE,mEAAmE;QACnE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,cAAc,GAAG,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,UAAU,CAAC,GAAG,QAAQ,CAAC,CAAC;QAErF,gEAAgE;QAChE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAClB,CAAC,CAAC;IAEF,gCAAgC;IAChC,MAAM,oBAAoB,GAAG,WAAW,CAAC,GAAG,EAAE;QAC5C,MAAM,aAAa,GAAG,uBAAuB,CAAC,WAAW,CAAC,CAAC;QAC3D,MAAM,UAAU,GAAG,IAAI,GAAG,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC;QAClE,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC;QAEhD,IAAI,OAAO,GAAG,KAAK,CAAC;QAEpB,mBAAmB;QACnB,KAAK,MAAM,GAAG,IAAI,aAAa,EAAE,CAAC;YAChC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC;gBACjC,MAAM,OAAO,GAAG,uBAAuB,CACrC,GAAG,EACH,CAAC,QAAQ,EAAE,EAAE;oBACX,KAAK,GAAG,QAAQ,CAAC;oBACjB,MAAM,EAAE,CAAC;gBACX,CAAC,EACD,GAAG,EAAE,CAAC,KAAK,CACZ,CAAC;gBACF,KAAK,GAAG,UAAU,CAAC,KAAK,EAAE,GAAG,EAAE,OAAO,CAAC,CAAC;gBACxC,OAAO,CAAC,KAAK,EAAE,CAAC;gBAChB,OAAO,GAAG,IAAI,CAAC;YACjB,CAAC;QACH,CAAC;QAED,uBAAuB;QACvB,KAAK,MAAM,EAAE,IAAI,QAAQ,EAAE,CAAC;YAC1B,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC;gBACxB,MAAM,OAAO,GAAG,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;gBACvC,OAAO,EAAE,OAAO,CAAC,IAAI,EAAE,CAAC;gBACxB,KAAK,GAAG,aAAa,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;gBACjC,OAAO,GAAG,IAAI,CAAC;YACjB,CAAC;QACH,CAAC;QAED,IAAI,OAAO;YAAE,MAAM,EAAE,CAAC;IACxB,CAAC,EAAE,yBAAyB,CAAC,CAAC;IAE9B,wEAAwE;IACxE,EAAE,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;IACrB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;IAChC,MAAM,EAAE,CAAC;IAET,kBAAkB;IAClB,EAAE,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,IAAY,EAAE,EAAE;QAC7B,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;QAC5B,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,EAAE,CAAC;YACT,OAAO;QACT,CAAC;QAED,MAAM,MAAM,GAAG,aAAa,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;QAC7C,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC;QAErB,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC;YAChB,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;gBACnB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC;YAC9C,CAAC;YACD,OAAO,GAAG,KAAK,CAAC;YAChB,EAAE,CAAC,KAAK,EAAE,CAAC;YACX,OAAO;QACT,CAAC;QAED,8CAA8C;QAC9C,mBAAmB,GAAG,EAAE,CAAC;QAEzB,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;YACnB,0DAA0D;YAC1D,MAAM,EAAE,CAAC;YACT,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC;YAC5C,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAClB,CAAC;aAAM,CAAC;YACN,MAAM,EAAE,CAAC;QACX,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE;QAClB,OAAO,GAAG,KAAK,CAAC;IAClB,CAAC,CAAC,CAAC;IAEH,kBAAkB;IAClB,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;QAClC,MAAM,aAAa,GAAG,WAAW,CAAC,GAAG,EAAE;YACrC,IAAI,CAAC,OAAO,EAAE,CAAC;gBACb,aAAa,CAAC,aAAa,CAAC,CAAC;gBAC7B,OAAO,EAAE,CAAC;YACZ,CAAC;QACH,CAAC,EAAE,GAAG,CAAC,CAAC;IACV,CAAC,CAAC,CAAC;IAEH,UAAU;IACV,aAAa,CAAC,oBAAoB,CAAC,CAAC;IACpC,KAAK,MAAM,OAAO,IAAI,KAAK,CAAC,QAAQ,CAAC,MAAM,EAAE,EAAE,CAAC;QAC9C,OAAO,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;IACzB,CAAC;IACD,WAAW,CAAC,QAAQ,CAAC,CAAC;AACxB,CAAC;AAED,0BAA0B;AAE1B;;;GAGG;AACH,SAAS,WAAW,CAAC,QAAgB;IACnC,IAAI,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QACzB,mDAAmD;QACnD,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;YAChD,MAAM,GAAG,GAAG,QAAQ,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC;YACzC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;gBACnC,OAAO,KAAK,CAAC,CAAC,8BAA8B;YAC9C,CAAC;YACD,qCAAqC;YACrC,UAAU,CAAC,QAAQ,CAAC,CAAC;QACvB,CAAC;QAAC,MAAM,CAAC;YACP,gDAAgD;YAChD,IAAI,CAAC;gBACH,UAAU,CAAC,QAAQ,CAAC,CAAC;YACvB,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,KAAK,CAAC;YACf,CAAC;QACH,CAAC;IACH,CAAC;IAED,IAAI,CAAC;QACH,MAAM,EAAE,GAAG,QAAQ,CAAC,QAAQ,EAAE,SAAS,CAAC,QAAQ,GAAG,SAAS,CAAC,OAAO,GAAG,SAAS,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;QAChG,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC;QACjD,SAAS,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;QACvB,SAAS,CAAC,EAAE,CAAC,CAAC;QACd,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,SAAS,WAAW,CAAC,QAAgB;IACnC,IAAI,CAAC;QACH,UAAU,CAAC,QAAQ,CAAC,CAAC;IACvB,CAAC;IAAC,MAAM,CAAC;QACP,iBAAiB;IACnB,CAAC;AACH,CAAC;AAED,SAAS,UAAU,CAAC,GAAW;IAC7B,IAAI,CAAC;QACH,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;QACrB,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,2BAA2B;AAE3B,SAAS,uBAAuB,CAC9B,YAAoC,EACpC,aAA6C,EAC7C,QAA6B;IAE7B,OAAO,uBAAuB,CAC5B,YAAY,CAAC,aAAa,EAC1B;QACE,YAAY,EAAE,CAAC,OAAO,EAAE,EAAE;YACxB,MAAM,QAAQ,GAAG,aAAa,CAAC,QAAQ,EAAE,EAAE,YAAY,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;YAC5E,aAAa,CAAC,QAAQ,CAAC,CAAC;YACxB,gCAAgC;YAChC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QAC/B,CAAC;QACD,mBAAmB,EAAE,CAAC,YAAY,EAAE,EAAE;YACpC,MAAM,QAAQ,GAAG,gBAAgB,CAAC,QAAQ,EAAE,EAAE,YAAY,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC;YACpF,aAAa,CAAC,QAAQ,CAAC,CAAC;QAC1B,CAAC;KACF,EACD,EAAE,cAAc,EAAE,GAAG,EAAE,CACxB,CAAC;AACJ,CAAC;AAUD,SAAS,aAAa,CAAC,KAAa,EAAE,KAAoB;IACxD,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IACjC,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;IAEvC,QAAQ,OAAO,EAAE,CAAC;QAChB,KAAK,UAAU,CAAC,CAAC,CAAC;YAChB,MAAM,GAAG,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;YACrB,IAAI,CAAC,GAAG;gBAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,CAAC,MAAM,CAAC,0CAA0C,CAAC,EAAE,CAAC;YAE9F,IAAI,GAAG,KAAK,KAAK,EAAE,CAAC;gBAClB,OAAO,gBAAgB,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC;YAC7C,CAAC;YACD,MAAM,GAAG,GAAG,QAAQ,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;YAC9B,IAAI,KAAK,CAAC,GAAG,CAAC;gBAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,CAAC,MAAM,CAAC,2BAA2B,CAAC,EAAE,CAAC;YACrF,OAAO,aAAa,CAAC,KAAK,EAAE,GAAG,EAAE,UAAU,CAAC,CAAC;QAC/C,CAAC;QAED,KAAK,OAAO,CAAC,CAAC,CAAC;YACb,MAAM,GAAG,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;YACrB,IAAI,CAAC,GAAG;gBAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,CAAC,MAAM,CAAC,oCAAoC,CAAC,EAAE,CAAC;YAExF,IAAI,GAAG,KAAK,KAAK,EAAE,CAAC;gBAClB,OAAO,gBAAgB,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;YAC3C,CAAC;YACD,MAAM,GAAG,GAAG,QAAQ,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;YAC9B,IAAI,KAAK,CAAC,GAAG,CAAC;gBAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,CAAC,MAAM,CAAC,2BAA2B,CAAC,EAAE,CAAC;YACrF,OAAO,aAAa,CAAC,KAAK,EAAE,GAAG,EAAE,QAAQ,CAAC,CAAC;QAC7C,CAAC;QAED,KAAK,WAAW;YACd,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,oBAAoB,CAAC,KAAK,CAAC,EAAE,CAAC;QAEzD,KAAK,OAAO,CAAC;QACb,KAAK,IAAI;YACP,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;QAE/B;YACE,OAAO;gBACL,KAAK;gBACL,OAAO,EAAE,KAAK,CAAC,MAAM,CACnB,gGAAgG,CACjG;aACF,CAAC;IACN,CAAC;AACH,CAAC;AAED,SAAS,aAAa,CAAC,KAAoB,EAAE,aAAqB,EAAE,QAA+B;IACjG,MAAM,UAAU,GAAG,KAAK,CAAC,kBAAkB,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;IAC/D,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,CAAC,MAAM,CAAC,0BAA0B,aAAa,EAAE,CAAC,EAAE,CAAC;IACrF,CAAC;IAED,MAAM,OAAO,GAAG,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;IACzD,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,CAAC,MAAM,CAAC,2BAA2B,aAAa,mBAAmB,CAAC,EAAE,CAAC;IACvG,CAAC;IAED,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAC;QACpF,MAAM,QAAQ,GAAG,iBAAiB,CAAC,KAAK,EAAE,aAAa,EAAE,QAAQ,CAAC,CAAC;QAEnE,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,OAAO;gBACL,KAAK,EAAE,QAAQ;gBACf,OAAO,EAAE,KAAK,CAAC,MAAM,CAAC,eAAe,aAAa,kCAAkC,CAAC;aACtF,CAAC;QACJ,CAAC;QAED,MAAM,KAAK,GAAG,QAAQ,KAAK,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QACtF,OAAO;YACL,KAAK,EAAE,QAAQ;YACf,OAAO,EAAE,eAAe,aAAa,IAAI,KAAK,EAAE;SACjD,CAAC;IACJ,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,CAAC,GAAG,CAAC,UAAU,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC;IACrG,CAAC;AACH,CAAC;AAED,SAAS,gBAAgB,CAAC,KAAoB,EAAE,QAA+B;IAC7E,IAAI,KAAK,CAAC,kBAAkB,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;QACxC,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,CAAC,MAAM,CAAC,wBAAwB,CAAC,EAAE,CAAC;IACpE,CAAC;IAED,IAAI,YAAY,GAAG,KAAK,CAAC;IACzB,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,MAAM,IAAI,GAAG,CAAC,GAAG,KAAK,CAAC,kBAAkB,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IAExE,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,MAAM,MAAM,GAAG,aAAa,CAAC,YAAY,EAAE,GAAG,EAAE,QAAQ,CAAC,CAAC;QAC1D,YAAY,GAAG,MAAM,CAAC,KAAK,CAAC;QAC5B,IAAI,MAAM,CAAC,OAAO;YAAE,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IACpD,CAAC;IAED,OAAO,EAAE,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;AAC/D,CAAC;AAED,SAAS,oBAAoB,CAAC,KAAoB;IAChD,IAAI,KAAK,CAAC,QAAQ,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;QAC9B,OAAO,KAAK,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC;IACzC,CAAC;IAED,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,MAAM,OAAO,IAAI,KAAK,CAAC,QAAQ,CAAC,MAAM,EAAE,EAAE,CAAC;QAC9C,MAAM,GAAG,GAAG,OAAO,CAAC,YAAY,CAAC;QACjC,MAAM,GAAG,GAAG,aAAa,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC;QACnD,KAAK,CAAC,IAAI,CAAC,MAAM,OAAO,CAAC,aAAa,KAAK,GAAG,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,GAAG,CAAC,KAAK,KAAK,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAC/G,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED,oBAAoB;AAEpB;;;;GAIG;AACH,SAAS,cAAc,CAAC,KAAoB;IAC1C,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,MAAM,YAAY,GAAG,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC;IACzC,MAAM,YAAY,GAAG,KAAK,CAAC,kBAAkB,CAAC,IAAI,CAAC;IAEnD,SAAS;IACT,KAAK,CAAC,IAAI,CACR,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,mCAAmC,CAAC;QAClD,KAAK,CAAC,GAAG,CAAC,iBAAiB,YAAY,WAAW,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,SAAS,CAAC,CAC5F,CAAC;IACF,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,GAAG,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IAElD,kBAAkB;IAClB,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACf,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC,CAAC;IAC7C,IAAI,YAAY,KAAK,CAAC,EAAE,CAAC;QACvB,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,iCAAiC,CAAC,CAAC,CAAC;IAC3D,CAAC;SAAM,CAAC;QACN,KAAK,MAAM,OAAO,IAAI,KAAK,CAAC,QAAQ,CAAC,MAAM,EAAE,EAAE,CAAC;YAC9C,MAAM,GAAG,GAAG,OAAO,CAAC,YAAY,CAAC;YACjC,MAAM,GAAG,GAAG,aAAa,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC;YACnD,MAAM,cAAc,GAAG,sBAAsB,CAAC,KAAK,EAAE,GAAG,CAAC,SAAS,CAAC,CAAC;YACpE,MAAM,YAAY,GAAG,cAAc,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,cAAc,UAAU,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;YAC/G,KAAK,CAAC,IAAI,CACR,QAAQ,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC,IAAI;gBACnD,GAAG,GAAG,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI;gBACpC,GAAG,GAAG,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI;gBACjC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC;gBACd,YAAY,CACf,CAAC;QACJ,CAAC;IACH,CAAC;IAED,sBAAsB;IACtB,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACf,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,GAAG,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IAClD,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACf,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,wBAAwB,CAAC,GAAG,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAEpG,IAAI,YAAY,GAAG,CAAC,EAAE,CAAC;QACrB,MAAM,MAAM,GAAG,CAAC,GAAG,KAAK,CAAC,kBAAkB,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,aAAa,GAAG,CAAC,CAAC,aAAa,CAAC,CAAC;QACxG,KAAK,MAAM,GAAG,IAAI,MAAM,EAAE,CAAC;YACzB,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACf,KAAK,CAAC,IAAI,CACR,QAAQ,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC,IAAI;gBACtD,YAAY,GAAG,CAAC,oBAAoB,KAAK,GAAG,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,CAC5E,CAAC;YACF,KAAK,CAAC,IAAI,CAAC,oBAAoB,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,UAAU,GAAG,GAAG,GAAG,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;YAElG,MAAM,UAAU,GAAG,gBAAgB,CAAC,GAAG,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;YAC3D,IAAI,UAAU,EAAE,CAAC;gBACf,KAAK,CAAC,IAAI,CAAC,oBAAoB,UAAU,EAAE,CAAC,CAAC;YAC/C,CAAC;YACD,KAAK,CAAC,IAAI,CAAC,oBAAoB,GAAG,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;YAErD,IAAI,GAAG,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;gBACxB,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;oBACzD,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,KAAK,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;gBACjD,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED,UAAU;IACV,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC7B,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACf,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,GAAG,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QAClD,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACf,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAC,CAAC;QAC/C,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QAC1C,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YAC3B,MAAM,IAAI,GAAG,KAAK,CAAC,UAAU,CAAC,kBAAkB,EAAE,CAAC;YACnD,MAAM,aAAa,GAAG,KAAK,CAAC,QAAQ,KAAK,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;YACpG,KAAK,CAAC,IAAI,CAAC,QAAQ,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,GAAG,GAAG,KAAK,CAAC,UAAU,IAAI,KAAK,CAAC,QAAQ,IAAI,GAAG,aAAa,CAAC,CAAC;QACtG,CAAC;IACH,CAAC;IAED,sDAAsD;IACtD,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACf,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,GAAG,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IAClD,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,2DAA2D,CAAC,CAAC,CAAC;IAEnF,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;AACjC,CAAC;AAED,kBAAkB;AAElB,SAAS,sBAAsB,CAAC,KAAoB,EAAE,SAAiB;IACrE,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,KAAK,MAAM,GAAG,IAAI,KAAK,CAAC,kBAAkB,CAAC,MAAM,EAAE,EAAE,CAAC;QACpD,IAAI,GAAG,CAAC,SAAS,KAAK,SAAS;YAAE,KAAK,EAAE,CAAC;IAC3C,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,aAAa,CAAC,IAAU;IAC/B,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,OAAO,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC;IACjE,IAAI,OAAO,GAAG,EAAE;QAAE,OAAO,GAAG,OAAO,OAAO,CAAC;IAC3C,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,EAAE,CAAC,CAAC;IACzC,IAAI,OAAO,GAAG,EAAE;QAAE,OAAO,GAAG,OAAO,OAAO,CAAC;IAC3C,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,EAAE,CAAC,CAAC;IACvC,OAAO,GAAG,KAAK,OAAO,CAAC;AACzB,CAAC;AAED,SAAS,gBAAgB,CAAC,IAA6B;IACrD,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;QAChD,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;YAC9B,MAAM,OAAO,GAAG,KAAK,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC;YAC3E,KAAK,CAAC,IAAI,CAAC,GAAG,GAAG,KAAK,OAAO,EAAE,CAAC,CAAC;QACnC,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACtC,CAAC"}
@@ -0,0 +1,49 @@
1
+ /**
2
+ * State management for the escalation listener TUI.
3
+ *
4
+ * Immutable state updates -- each mutation returns a new state object.
5
+ * The rendering layer reads state and redraws on change.
6
+ */
7
+ import type { PtySessionRegistration } from '../docker/pty-types.js';
8
+ import type { EscalationWatcher } from './escalation-watcher.js';
9
+ import type { EscalationRequest } from '../session/types.js';
10
+ export interface ActiveSession {
11
+ readonly registration: PtySessionRegistration;
12
+ readonly watcher: EscalationWatcher;
13
+ /** Sequential display number assigned when the session was first detected. */
14
+ readonly displayNumber: number;
15
+ }
16
+ export interface PendingEscalation {
17
+ readonly sessionId: string;
18
+ readonly sessionDisplayNumber: number;
19
+ readonly request: EscalationRequest;
20
+ /** Monotonically increasing display number for /approve and /deny commands. */
21
+ readonly displayNumber: number;
22
+ readonly receivedAt: Date;
23
+ }
24
+ export interface ResolvedEscalation {
25
+ readonly sessionId: string;
26
+ readonly toolName: string;
27
+ readonly serverName: string;
28
+ readonly decision: 'approved' | 'denied';
29
+ readonly resolvedAt: Date;
30
+ }
31
+ export interface ListenerState {
32
+ readonly sessions: ReadonlyMap<string, ActiveSession>;
33
+ readonly pendingEscalations: ReadonlyMap<number, PendingEscalation>;
34
+ readonly history: readonly ResolvedEscalation[];
35
+ readonly nextEscalationNumber: number;
36
+ readonly nextSessionNumber: number;
37
+ }
38
+ /** Creates an empty initial state. */
39
+ export declare function createInitialState(): ListenerState;
40
+ /** Adds a new session to the state. */
41
+ export declare function addSession(state: ListenerState, registration: PtySessionRegistration, watcher: EscalationWatcher): ListenerState;
42
+ /** Removes a session and its pending escalations from the state. */
43
+ export declare function removeSession(state: ListenerState, sessionId: string): ListenerState;
44
+ /** Adds a new pending escalation to the state. */
45
+ export declare function addEscalation(state: ListenerState, sessionId: string, request: EscalationRequest): ListenerState;
46
+ /** Resolves a pending escalation and moves it to history. */
47
+ export declare function resolveEscalation(state: ListenerState, displayNumber: number, decision: 'approved' | 'denied'): ListenerState;
48
+ /** Removes a pending escalation that expired. */
49
+ export declare function expireEscalation(state: ListenerState, sessionId: string, escalationId: string): ListenerState;
@@ -0,0 +1,104 @@
1
+ /**
2
+ * State management for the escalation listener TUI.
3
+ *
4
+ * Immutable state updates -- each mutation returns a new state object.
5
+ * The rendering layer reads state and redraws on change.
6
+ */
7
+ /** Maximum number of resolved escalations to keep in history. */
8
+ const MAX_HISTORY = 20;
9
+ /** Creates an empty initial state. */
10
+ export function createInitialState() {
11
+ return {
12
+ sessions: new Map(),
13
+ pendingEscalations: new Map(),
14
+ history: [],
15
+ nextEscalationNumber: 1,
16
+ nextSessionNumber: 1,
17
+ };
18
+ }
19
+ /** Adds a new session to the state. */
20
+ export function addSession(state, registration, watcher) {
21
+ const sessions = new Map(state.sessions);
22
+ sessions.set(registration.sessionId, {
23
+ registration,
24
+ watcher,
25
+ displayNumber: state.nextSessionNumber,
26
+ });
27
+ return {
28
+ ...state,
29
+ sessions,
30
+ nextSessionNumber: state.nextSessionNumber + 1,
31
+ };
32
+ }
33
+ /** Removes a session and its pending escalations from the state. */
34
+ export function removeSession(state, sessionId) {
35
+ const sessions = new Map(state.sessions);
36
+ sessions.delete(sessionId);
37
+ // Remove any pending escalations for this session
38
+ const pendingEscalations = new Map(state.pendingEscalations);
39
+ for (const [num, esc] of pendingEscalations) {
40
+ if (esc.sessionId === sessionId) {
41
+ pendingEscalations.delete(num);
42
+ }
43
+ }
44
+ return { ...state, sessions, pendingEscalations };
45
+ }
46
+ /** Adds a new pending escalation to the state. */
47
+ export function addEscalation(state, sessionId, request) {
48
+ const session = state.sessions.get(sessionId);
49
+ if (!session)
50
+ return state;
51
+ const displayNumber = state.nextEscalationNumber;
52
+ const pendingEscalations = new Map(state.pendingEscalations);
53
+ pendingEscalations.set(displayNumber, {
54
+ sessionId,
55
+ sessionDisplayNumber: session.displayNumber,
56
+ request,
57
+ displayNumber,
58
+ receivedAt: new Date(),
59
+ });
60
+ return {
61
+ ...state,
62
+ pendingEscalations,
63
+ nextEscalationNumber: displayNumber + 1,
64
+ };
65
+ }
66
+ /** Resolves a pending escalation and moves it to history. */
67
+ export function resolveEscalation(state, displayNumber, decision) {
68
+ const escalation = state.pendingEscalations.get(displayNumber);
69
+ if (!escalation)
70
+ return state;
71
+ const pendingEscalations = new Map(state.pendingEscalations);
72
+ pendingEscalations.delete(displayNumber);
73
+ const resolved = {
74
+ sessionId: escalation.sessionId,
75
+ toolName: escalation.request.toolName,
76
+ serverName: escalation.request.serverName,
77
+ decision,
78
+ resolvedAt: new Date(),
79
+ };
80
+ // Prepend to history and trim to MAX_HISTORY
81
+ const history = [resolved, ...state.history].slice(0, MAX_HISTORY);
82
+ return { ...state, pendingEscalations, history };
83
+ }
84
+ /** Removes a pending escalation that expired. */
85
+ export function expireEscalation(state, sessionId, escalationId) {
86
+ const pendingEscalations = new Map(state.pendingEscalations);
87
+ for (const [num, esc] of pendingEscalations) {
88
+ if (esc.sessionId === sessionId && esc.request.escalationId === escalationId) {
89
+ pendingEscalations.delete(num);
90
+ // Add to history as expired
91
+ const resolved = {
92
+ sessionId: esc.sessionId,
93
+ toolName: esc.request.toolName,
94
+ serverName: esc.request.serverName,
95
+ decision: 'denied',
96
+ resolvedAt: new Date(),
97
+ };
98
+ const history = [resolved, ...state.history].slice(0, MAX_HISTORY);
99
+ return { ...state, pendingEscalations, history };
100
+ }
101
+ }
102
+ return state;
103
+ }
104
+ //# sourceMappingURL=listener-state.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"listener-state.js","sourceRoot":"","sources":["../../src/escalation/listener-state.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Session registry -- reads and validates PTY session registration files.
3
+ *
4
+ * PTY sessions write registration files to ~/.ironcurtain/pty-registry/
5
+ * when they start, and delete them on shutdown. The escalation listener
6
+ * polls this directory to discover active sessions.
7
+ *
8
+ * Stale session detection: if a registration file exists but the PID
9
+ * is no longer alive, the session crashed without cleanup. The registry
10
+ * removes stale registrations.
11
+ */
12
+ import type { PtySessionRegistration } from '../docker/pty-types.js';
13
+ /**
14
+ * Reads all valid, non-stale session registrations from the registry directory.
15
+ * Removes stale registrations (PID no longer alive) as a side effect.
16
+ */
17
+ export declare function readActiveRegistrations(registryDir: string): PtySessionRegistration[];