diff --git a/CLAUDE.md b/CLAUDE.md index d16361b7..f6f349ae 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -16,7 +16,7 @@ When user says "COM": 1. Increment version in BOTH `package.json` AND `CLAUDE.md` 2. Run: `git add -A && git commit -m "chore: bump version to X.XXXX" && git push && npm run build && systemctl --user restart claudeman-web` -**Version**: 0.1438 (must match `package.json`) +**Version**: 0.1439 (must match `package.json`) ## Project Overview diff --git a/package.json b/package.json index 15e974f8..c8fccbaf 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "claudeman", - "version": "0.1438", + "version": "0.1439", "description": "The missing control plane for Claude Code - run 20 autonomous agents with real-time monitoring and session persistence", "type": "module", "main": "dist/index.js", diff --git a/src/session.ts b/src/session.ts index 521c57e1..fc3eb467 100644 --- a/src/session.ts +++ b/src/session.ts @@ -338,6 +338,9 @@ export class Session extends EventEmitter { // Image watcher setting (per-session toggle) private _imageWatcherEnabled: boolean = true; + // Flicker filter setting (per-session toggle, applied on frontend) + private _flickerFilterEnabled: boolean = false; + // Timer tracking for cleanup (prevents memory leaks) private _autoCompactTimer: NodeJS.Timeout | null = null; private _autoClearTimer: NodeJS.Timeout | null = null; @@ -694,6 +697,14 @@ export class Session extends EventEmitter { this._imageWatcherEnabled = enabled; } + get flickerFilterEnabled(): boolean { + return this._flickerFilterEnabled; + } + + set flickerFilterEnabled(enabled: boolean) { + this._flickerFilterEnabled = enabled; + } + isIdle(): boolean { return this._status === 'idle'; } @@ -734,6 +745,7 @@ export class Session extends EventEmitter { niceEnabled: this._niceConfig.enabled, niceValue: this._niceConfig.niceValue, color: this._color, + flickerFilterEnabled: this._flickerFilterEnabled, }; } diff --git a/src/types.ts b/src/types.ts index f31b37c4..ecd02027 100644 --- a/src/types.ts +++ b/src/types.ts @@ -180,6 +180,8 @@ export interface SessionState { niceValue?: number; /** User-assigned color for visual differentiation */ color?: SessionColor; + /** Flicker filter enabled (buffers output after screen clears) */ + flickerFilterEnabled?: boolean; } // ========== Global Stats Types ========== diff --git a/src/web/public/app.js b/src/web/public/app.js index 317a75eb..00c6f6e8 100644 --- a/src/web/public/app.js +++ b/src/web/public/app.js @@ -631,6 +631,7 @@ class ClaudemanApp { // Once set, never recalculated. Persisted to localStorage and server. this.subagentParentMap = new Map(); this.ralphStatePanelCollapsed = true; // Default to collapsed + this.ralphClosedSessions = new Set(); // Sessions where user explicitly closed Ralph panel // Plan subagent windows (visible agents during plan generation) this.planSubagents = new Map(); // Map @@ -667,6 +668,11 @@ class ClaudemanApp { this._wasAtBottomBeforeWrite = true; // Default to true for sticky scroll this.syncWaitTimeout = null; // Timeout for incomplete sync blocks + // Flicker filter state (buffers output after screen clears) + this.flickerFilterBuffer = ''; + this.flickerFilterActive = false; + this.flickerFilterTimeout = null; + // Render debouncing this.renderSessionTabsTimeout = null; this.renderRalphStatePanelTimeout = null; @@ -1053,6 +1059,44 @@ class ClaudemanApp { this._wasAtBottomBeforeWrite = this.isTerminalAtBottom(); } + // Check if flicker filter is enabled for current session + const session = this.activeSessionId ? this.sessions.get(this.activeSessionId) : null; + const flickerFilterEnabled = session?.flickerFilterEnabled ?? false; + + // Flicker filter: detect screen clear patterns and buffer output + if (flickerFilterEnabled) { + // Detect Ink's screen clear patterns: + // - ESC[2J (clear entire screen) + // - ESC[H ESC[J (cursor home + clear to end) + // - ESC[?25l ESC[H (hide cursor + home - common Ink pattern) + const hasScreenClear = data.includes('\x1b[2J') || + data.includes('\x1b[H\x1b[J') || + (data.includes('\x1b[H') && data.includes('\x1b[?25l')); + + if (hasScreenClear) { + // Screen clear detected - activate flicker filter + this.flickerFilterActive = true; + this.flickerFilterBuffer += data; + + // Clear any existing timeout and set a new one + if (this.flickerFilterTimeout) { + clearTimeout(this.flickerFilterTimeout); + } + this.flickerFilterTimeout = setTimeout(() => { + this.flickerFilterTimeout = null; + this.flushFlickerBuffer(); + }, SYNC_WAIT_TIMEOUT_MS); // 50ms buffer window + + return; // Don't process normally, wait for buffer window + } + + if (this.flickerFilterActive) { + // Filter is active, accumulate data + this.flickerFilterBuffer += data; + return; // Continue buffering + } + } + // Accumulate raw data (may contain DEC 2026 markers) this.pendingWrites += data; @@ -1090,6 +1134,28 @@ class ClaudemanApp { } } + /** + * Flush the flicker filter buffer to the terminal. + * Called after the buffer window expires. + */ + flushFlickerBuffer() { + if (!this.flickerFilterBuffer) return; + + // Transfer buffered data to normal pending writes + this.pendingWrites += this.flickerFilterBuffer; + this.flickerFilterBuffer = ''; + this.flickerFilterActive = false; + + // Trigger a normal flush + if (!this.writeFrameScheduled) { + this.writeFrameScheduled = true; + requestAnimationFrame(() => { + this.flushPendingWrites(); + this.writeFrameScheduled = false; + }); + } + } + /** * Flush pending writes to terminal, processing DEC 2026 sync markers. * Strips markers and writes content atomically within a single frame. @@ -1366,6 +1432,7 @@ class ClaudemanApp { } this.terminalBuffers.delete(data.id); this.ralphStates.delete(data.id); // Clean up ralph state for this session + this.ralphClosedSessions.delete(data.id); // Clean up closed tracking for this session this.projectInsights.delete(data.id); // Clean up project insights for this session this.closeSessionLogViewerWindows(data.id); // Close log viewer windows for this session this.closeSessionImagePopups(data.id); // Close image popup windows for this session @@ -1803,16 +1870,22 @@ class ClaudemanApp { // Ralph loop/todo events addListener('session:ralphLoopUpdate', (e) => { const data = JSON.parse(e.data); + // Skip if user explicitly closed this session's Ralph panel + if (this.ralphClosedSessions.has(data.sessionId)) return; this.updateRalphState(data.sessionId, { loop: data.state }); }); addListener('session:ralphTodoUpdate', (e) => { const data = JSON.parse(e.data); + // Skip if user explicitly closed this session's Ralph panel + if (this.ralphClosedSessions.has(data.sessionId)) return; this.updateRalphState(data.sessionId, { todos: data.todos }); }); addListener('session:ralphCompletionDetected', (e) => { const data = JSON.parse(e.data); + // Skip if user explicitly closed this session's Ralph panel + if (this.ralphClosedSessions.has(data.sessionId)) return; // Prevent duplicate notifications for the same completion const completionKey = `${data.sessionId}:${data.phrase}`; if (this._shownCompletions?.has(completionKey)) { @@ -1846,11 +1919,15 @@ class ClaudemanApp { // RALPH_STATUS block and circuit breaker events addListener('session:ralphStatusUpdate', (e) => { const data = JSON.parse(e.data); + // Skip if user explicitly closed this session's Ralph panel + if (this.ralphClosedSessions.has(data.sessionId)) return; this.updateRalphState(data.sessionId, { statusBlock: data.block }); }); addListener('session:circuitBreakerUpdate', (e) => { const data = JSON.parse(e.data); + // Skip if user explicitly closed this session's Ralph panel + if (this.ralphClosedSessions.has(data.sessionId)) return; this.updateRalphState(data.sessionId, { circuitBreaker: data.status }); // Notify if circuit breaker opens if (data.status.state === 'OPEN') { @@ -2222,6 +2299,13 @@ class ClaudemanApp { clearTimeout(timer); } this.idleTimers.clear(); + // Clear flicker filter state + if (this.flickerFilterTimeout) { + clearTimeout(this.flickerFilterTimeout); + this.flickerFilterTimeout = null; + } + this.flickerFilterBuffer = ''; + this.flickerFilterActive = false; // Clear pending hooks this.pendingHooks.clear(); // Clear tab alerts @@ -2250,8 +2334,8 @@ class ClaudemanApp { } data.sessions.forEach(s => { this.sessions.set(s.id, s); - // Load ralph state from session data - if (s.ralphLoop || s.ralphTodos) { + // Load ralph state from session data (only if not explicitly closed by user) + if ((s.ralphLoop || s.ralphTodos) && !this.ralphClosedSessions.has(s.id)) { this.ralphStates.set(s.id, { loop: s.ralphLoop || null, todos: s.ralphTodos || [] @@ -2842,6 +2926,14 @@ class ClaudemanApp { async selectSession(sessionId) { if (this.activeSessionId === sessionId) return; + // Clean up flicker filter state when switching sessions + if (this.flickerFilterTimeout) { + clearTimeout(this.flickerFilterTimeout); + this.flickerFilterTimeout = null; + } + this.flickerFilterBuffer = ''; + this.flickerFilterActive = false; + this.activeSessionId = sessionId; this.hideWelcome(); // Clear idle hooks on view, but keep action hooks until user interacts @@ -5754,6 +5846,9 @@ class ClaudemanApp { const sessionId = data.sessionId; + // Clear from closed set in case user previously closed Ralph for this session + this.ralphClosedSessions.delete(sessionId); + // Step 2: Configure Ralph tracker for this session await fetch(`/api/sessions/${sessionId}/ralph-config`, { method: 'POST', @@ -6932,6 +7027,7 @@ class ClaudemanApp { document.getElementById('modalAutoClearEnabled').checked = session.autoClearEnabled ?? false; document.getElementById('modalAutoClearThreshold').value = session.autoClearThreshold ?? 140000; document.getElementById('modalImageWatcherEnabled').checked = session.imageWatcherEnabled ?? true; + document.getElementById('modalFlickerFilterEnabled').checked = session.flickerFilterEnabled ?? false; // Initialize color picker with current session color const currentColor = session.color || 'default'; @@ -7010,6 +7106,26 @@ class ClaudemanApp { } } + async toggleFlickerFilter() { + if (!this.editingSessionId) return; + const enabled = document.getElementById('modalFlickerFilterEnabled').checked; + try { + await fetch(`/api/sessions/${this.editingSessionId}/flicker-filter`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ enabled }) + }); + // Update local session state + const session = this.sessions.get(this.editingSessionId); + if (session) { + session.flickerFilterEnabled = enabled; + } + this.showToast(`Flicker filter ${enabled ? 'enabled' : 'disabled'}`, 'success'); + } catch (err) { + this.showToast('Failed to toggle flicker filter', 'error'); + } + } + async autoSaveRespawnConfig() { if (!this.editingSessionId) return; const config = { @@ -7715,6 +7831,11 @@ class ClaudemanApp { const config = this.getRalphConfig(); + // If user is enabling Ralph, clear from closed set + if (config.enabled) { + this.ralphClosedSessions.delete(this.editingSessionId); + } + try { const res = await fetch(`/api/sessions/${this.editingSessionId}/ralph-config`, { method: 'POST', @@ -9045,6 +9166,9 @@ class ClaudemanApp { async closeRalphTracker() { if (!this.activeSessionId) return; + // Mark this session as explicitly closed - will stay hidden until user re-enables + this.ralphClosedSessions.add(this.activeSessionId); + // Disable tracker via API await fetch(`/api/sessions/${this.activeSessionId}/ralph-config`, { method: 'POST', @@ -9343,6 +9467,12 @@ class ClaudemanApp { if (!panel) return; + // If user explicitly closed this session's Ralph panel, keep it hidden + if (this.ralphClosedSessions.has(this.activeSessionId)) { + panel.style.display = 'none'; + return; + } + const state = this.ralphStates.get(this.activeSessionId); // Check if there's anything to show diff --git a/src/web/public/index.html b/src/web/public/index.html index b65f6896..49b5e213 100644 --- a/src/web/public/index.html +++ b/src/web/public/index.html @@ -583,6 +583,16 @@ Auto-popup new images (screenshots, generated files) in this session's directory + +
Performance
+
+ + + Buffers output after screen clears to reduce Ink UI flickering (adds ~50ms latency) +
diff --git a/src/web/server.ts b/src/web/server.ts index 2ccc9642..2a81c6d0 100644 --- a/src/web/server.ts +++ b/src/web/server.ts @@ -280,6 +280,7 @@ export class WebServer extends EventEmitter { private store = getStore(); private port: number; private https: boolean; + private testMode: boolean; private screenManager: ScreenManager; // Terminal batching for performance private terminalBatches: Map = new Map(); @@ -325,10 +326,11 @@ export class WebServer extends EventEmitter { error: (error: Error, sessionId?: string) => void; } | null = null; - constructor(port: number = 3000, https: boolean = false) { + constructor(port: number = 3000, https: boolean = false, testMode: boolean = false) { super(); this.port = port; this.https = https; + this.testMode = testMode; if (https) { const { key, cert } = getOrCreateSelfSignedCert(); @@ -1879,6 +1881,32 @@ export class WebServer extends EventEmitter { }; }); + // Toggle flicker filter for a session + this.app.post('/api/sessions/:id/flicker-filter', async (req) => { + const { id } = req.params as { id: string }; + const body = req.body as { enabled: boolean }; + const session = this.sessions.get(id); + + if (!session) { + return createErrorResponse(ApiErrorCode.NOT_FOUND, 'Session not found'); + } + + if (body.enabled === undefined) { + return createErrorResponse(ApiErrorCode.INVALID_INPUT, 'enabled field is required'); + } + + session.flickerFilterEnabled = body.enabled; + this.persistSessionState(session); + this.broadcast('session:updated', this.getSessionStateWithRespawn(session)); + + return { + success: true, + data: { + flickerFilterEnabled: body.enabled, + }, + }; + }); + // Quick run (create session, run prompt, return result, then cleanup) this.app.post('/api/run', async (req) => { // Prevent unbounded session creation @@ -4414,7 +4442,10 @@ NOW: Generate the implementation plan for the task above. Think step by step.`; // Restore screen sessions BEFORE accepting connections // This prevents race conditions where clients connect before state is ready - await this.restoreScreenSessions(); + // CRITICAL: Skip in test mode to prevent tests from picking up user sessions + if (!this.testMode) { + await this.restoreScreenSessions(); + } // Clean up stale sessions from state file that don't have active screens this.cleanupStaleSessions(); @@ -4587,6 +4618,10 @@ NOW: Generate the implementation plan for the task above. Think step by step.`; niceValue: savedState.niceValue, }); } + // Flicker filter (frontend-applied but persisted) + if (savedState.flickerFilterEnabled !== undefined) { + session.flickerFilterEnabled = savedState.flickerFilterEnabled; + } // Respawn controller if (savedState.respawnEnabled && savedState.respawnConfig) { try { @@ -4751,8 +4786,8 @@ NOW: Generate the implementation plan for the task above. Think step by step.`; } } -export async function startWebServer(port: number = 3000, https: boolean = false): Promise { - const server = new WebServer(port, https); +export async function startWebServer(port: number = 3000, https: boolean = false, testMode: boolean = false): Promise { + const server = new WebServer(port, https, testMode); await server.start(); return server; } diff --git a/test/browser-agent.test.ts b/test/browser-agent.test.ts index b4e58208..6b3ce377 100644 --- a/test/browser-agent.test.ts +++ b/test/browser-agent.test.ts @@ -171,7 +171,7 @@ describe('Agent-Browser Enhanced Tests', () => { closeBrowser(); // Start web server - server = new WebServer(TEST_PORT); + server = new WebServer(TEST_PORT, false, true); await server.start(); await new Promise(r => setTimeout(r, 1000)); diff --git a/test/browser-comparison.test.ts b/test/browser-comparison.test.ts index 001cbd94..b2113c35 100644 --- a/test/browser-comparison.test.ts +++ b/test/browser-comparison.test.ts @@ -135,7 +135,7 @@ describe('Browser Framework Comparison Benchmark', () => { // Start web servers for each framework for (const [name, port] of Object.entries(PORTS)) { - const server = new WebServer(port); + const server = new WebServer(port, false, true); await server.start(); servers.push(server); console.log(`✅ Started server for ${name} on port ${port}`); diff --git a/test/browser-e2e.test.ts b/test/browser-e2e.test.ts index b7b37f0a..a4bab805 100644 --- a/test/browser-e2e.test.ts +++ b/test/browser-e2e.test.ts @@ -92,7 +92,7 @@ describe('Browser E2E Tests', () => { beforeAll(async () => { closeBrowser(); - server = new WebServer(TEST_PORT_BROWSER); + server = new WebServer(TEST_PORT_BROWSER, false, true); await server.start(); await new Promise(r => setTimeout(r, 1000)); @@ -211,7 +211,7 @@ describe('SSE Events API', () => { let createdSessions: string[] = []; beforeAll(async () => { - server = new WebServer(TEST_PORT_SSE); + server = new WebServer(TEST_PORT_SSE, false, true); await server.start(); await new Promise(r => setTimeout(r, 1000)); }, 30000); @@ -280,7 +280,7 @@ describe('Hook Events API', () => { let createdSessions: string[] = []; beforeAll(async () => { - server = new WebServer(TEST_PORT_HOOK); + server = new WebServer(TEST_PORT_HOOK, false, true); await server.start(); await new Promise(r => setTimeout(r, 1000)); }, 30000); @@ -345,7 +345,7 @@ describe('Ralph API', () => { let createdSessions: string[] = []; beforeAll(async () => { - server = new WebServer(TEST_PORT_RALPH); + server = new WebServer(TEST_PORT_RALPH, false, true); await server.start(); await new Promise(r => setTimeout(r, 1000)); }, 30000); diff --git a/test/browser-playwright.test.ts b/test/browser-playwright.test.ts index 0abb4ed7..829bde2d 100644 --- a/test/browser-playwright.test.ts +++ b/test/browser-playwright.test.ts @@ -32,7 +32,7 @@ let setupComplete = false; describe('Playwright Direct API Tests', () => { beforeAll(async () => { // Start web server - server = new WebServer(TEST_PORT); + server = new WebServer(TEST_PORT, false, true); await server.start(); await new Promise(r => setTimeout(r, 1000)); diff --git a/test/browser-puppeteer.test.ts b/test/browser-puppeteer.test.ts index 85071b0d..a26dad96 100644 --- a/test/browser-puppeteer.test.ts +++ b/test/browser-puppeteer.test.ts @@ -34,7 +34,7 @@ describe('Puppeteer/Chrome Tests', () => { beforeAll(async () => { // Start web server - server = new WebServer(TEST_PORT); + server = new WebServer(TEST_PORT, false, true); await server.start(); await new Promise(r => setTimeout(r, 1000)); diff --git a/test/e2e/fixtures/server.fixture.ts b/test/e2e/fixtures/server.fixture.ts index 83218209..dcb65755 100644 --- a/test/e2e/fixtures/server.fixture.ts +++ b/test/e2e/fixtures/server.fixture.ts @@ -17,7 +17,7 @@ export interface ServerFixture { * @returns ServerFixture with server instance and connection info */ export async function createServerFixture(port: number): Promise { - const server = new WebServer(port); + const server = new WebServer(port, false, true); await server.start(); // Wait for server to be fully ready diff --git a/test/edge-cases.test.ts b/test/edge-cases.test.ts index 6bef992c..38de6e8f 100644 --- a/test/edge-cases.test.ts +++ b/test/edge-cases.test.ts @@ -13,7 +13,7 @@ describe('Edge Cases and Error Handling', () => { const createdCases: string[] = []; beforeAll(async () => { - server = new WebServer(TEST_PORT); + server = new WebServer(TEST_PORT, false, true); await server.start(); baseUrl = `http://localhost:${TEST_PORT}`; }); @@ -261,7 +261,7 @@ describe('Concurrent Session Handling', () => { let baseUrl: string; beforeAll(async () => { - server = new WebServer(TEST_PORT + 1); + server = new WebServer(TEST_PORT + 1, false, true); await server.start(); baseUrl = `http://localhost:${TEST_PORT + 1}`; }); @@ -362,7 +362,7 @@ describe('API Request Validation', () => { let baseUrl: string; beforeAll(async () => { - server = new WebServer(TEST_PORT + 2); + server = new WebServer(TEST_PORT + 2, false, true); await server.start(); baseUrl = `http://localhost:${TEST_PORT + 2}`; }); diff --git a/test/file-link-click.test.ts b/test/file-link-click.test.ts index a5e753f7..57065ed4 100644 --- a/test/file-link-click.test.ts +++ b/test/file-link-click.test.ts @@ -93,7 +93,7 @@ describe('File Link Click Tests', () => { testLogFile = join(testDir, 'test.log'); writeFileSync(testLogFile, '=== Test Log Started ===\n'); - server = new WebServer(TEST_PORT); + server = new WebServer(TEST_PORT, false, true); await server.start(); await new Promise(r => setTimeout(r, 1000)); diff --git a/test/hooks-config.test.ts b/test/hooks-config.test.ts index 59dd5df4..f569fc21 100644 --- a/test/hooks-config.test.ts +++ b/test/hooks-config.test.ts @@ -200,7 +200,7 @@ describe('Hook Event API', () => { let testSessionId: string; beforeAll(async () => { - server = new WebServer(TEST_PORT); + server = new WebServer(TEST_PORT, false, true); await server.start(); baseUrl = `http://localhost:${TEST_PORT}`; @@ -382,7 +382,7 @@ describe('Hook Data Sanitization', () => { let testSessionId: string; beforeAll(async () => { - server = new WebServer(TEST_PORT + 1); // Port 3131 + server = new WebServer(TEST_PORT + 1, false, true); // Port 3131 await server.start(); baseUrl = `http://localhost:${TEST_PORT + 1}`; diff --git a/test/integration-flows.test.ts b/test/integration-flows.test.ts index 6a2c3a4e..594ff55c 100644 --- a/test/integration-flows.test.ts +++ b/test/integration-flows.test.ts @@ -18,7 +18,7 @@ describe('Integration Flows', () => { const createdSessions: string[] = []; beforeAll(async () => { - server = new WebServer(TEST_PORT); + server = new WebServer(TEST_PORT, false, true); await server.start(); baseUrl = `http://localhost:${TEST_PORT}`; }); @@ -278,7 +278,7 @@ describe('SSE Event Flow', () => { const createdSessions: string[] = []; beforeAll(async () => { - server = new WebServer(TEST_PORT + 1); + server = new WebServer(TEST_PORT + 1, false, true); await server.start(); baseUrl = `http://localhost:${TEST_PORT + 1}`; }); diff --git a/test/quick-start.test.ts b/test/quick-start.test.ts index 099fb146..7c7182fd 100644 --- a/test/quick-start.test.ts +++ b/test/quick-start.test.ts @@ -13,7 +13,7 @@ describe('Quick Start API', () => { const createdCases: string[] = []; beforeAll(async () => { - server = new WebServer(TEST_PORT); + server = new WebServer(TEST_PORT, false, true); await server.start(); baseUrl = `http://localhost:${TEST_PORT}`; }); @@ -147,7 +147,7 @@ describe('Session Management', () => { let baseUrl: string; beforeAll(async () => { - server = new WebServer(TEST_PORT + 1); + server = new WebServer(TEST_PORT + 1, false, true); await server.start(); baseUrl = `http://localhost:${TEST_PORT + 1}`; }); @@ -204,7 +204,7 @@ describe('Case Management', () => { const createdCases: string[] = []; beforeAll(async () => { - server = new WebServer(TEST_PORT + 2); + server = new WebServer(TEST_PORT + 2, false, true); await server.start(); baseUrl = `http://localhost:${TEST_PORT + 2}`; }); diff --git a/test/ralph-integration.test.ts b/test/ralph-integration.test.ts index b80334fa..44161dbd 100644 --- a/test/ralph-integration.test.ts +++ b/test/ralph-integration.test.ts @@ -27,7 +27,7 @@ describe('Ralph Integration Tests', () => { const createdSessions: string[] = []; beforeAll(async () => { - server = new WebServer(TEST_PORT); + server = new WebServer(TEST_PORT, false, true); await server.start(); baseUrl = `http://localhost:${TEST_PORT}`; }); diff --git a/test/scheduled-runs.test.ts b/test/scheduled-runs.test.ts index 3d246459..b4c93484 100644 --- a/test/scheduled-runs.test.ts +++ b/test/scheduled-runs.test.ts @@ -9,7 +9,7 @@ describe('Scheduled Runs API', () => { const createdRuns: string[] = []; beforeAll(async () => { - server = new WebServer(TEST_PORT); + server = new WebServer(TEST_PORT, false, true); await server.start(); baseUrl = `http://localhost:${TEST_PORT}`; }); @@ -181,7 +181,7 @@ describe('Quick Run API', () => { let baseUrl: string; beforeAll(async () => { - server = new WebServer(TEST_PORT + 1); + server = new WebServer(TEST_PORT + 1, false, true); await server.start(); baseUrl = `http://localhost:${TEST_PORT + 1}`; }); diff --git a/test/session-cleanup.test.ts b/test/session-cleanup.test.ts index f1e7a07d..446137a7 100644 --- a/test/session-cleanup.test.ts +++ b/test/session-cleanup.test.ts @@ -19,7 +19,7 @@ describe('Session Cleanup', () => { const createdSessions: string[] = []; beforeAll(async () => { - server = new WebServer(TEST_PORT); + server = new WebServer(TEST_PORT, false, true); await server.start(); baseUrl = `http://localhost:${TEST_PORT}`; }); @@ -186,7 +186,7 @@ describe('Resource Management', () => { const createdCases: string[] = []; beforeAll(async () => { - server = new WebServer(TEST_PORT + 1); + server = new WebServer(TEST_PORT + 1, false, true); await server.start(); baseUrl = `http://localhost:${TEST_PORT + 1}`; }); diff --git a/test/session.test.ts b/test/session.test.ts index aac2a292..6795860c 100644 --- a/test/session.test.ts +++ b/test/session.test.ts @@ -8,7 +8,7 @@ describe('Interactive Session Lifecycle', () => { let baseUrl: string; beforeAll(async () => { - server = new WebServer(TEST_PORT); + server = new WebServer(TEST_PORT, false, true); await server.start(); baseUrl = `http://localhost:${TEST_PORT}`; }); diff --git a/test/sse-events.test.ts b/test/sse-events.test.ts index 2ce82b99..04b084c7 100644 --- a/test/sse-events.test.ts +++ b/test/sse-events.test.ts @@ -37,7 +37,7 @@ describe('SSE Events', () => { let baseUrl: string; beforeAll(async () => { - server = new WebServer(TEST_PORT); + server = new WebServer(TEST_PORT, false, true); await server.start(); baseUrl = `http://localhost:${TEST_PORT}`; }); @@ -180,7 +180,7 @@ describe('SSE Event Types', () => { let baseUrl: string; beforeAll(async () => { - server = new WebServer(TEST_PORT + 1); + server = new WebServer(TEST_PORT + 1, false, true); await server.start(); baseUrl = `http://localhost:${TEST_PORT + 1}`; });