fix: Per-agent terminal isolation, floating terminal z-index, and char-by-char input

- Add :key to PromptBar to force remount on agent switch, fixing shared terminal session bug
- Raise AgentTerminal z-index above PromptBar backdrop so floating terminal is visible/clickable
- Send prompt text char-by-char (15ms delay) matching FloatingVoice pattern for Claude Code compat
- Guard xterm dispose against unloaded addons to prevent errors on agent switch
- Widen PromptBar panel from 360px to 420px to fit all ChatInput buttons
This commit is contained in:
2026-02-16 00:41:38 -06:00
parent 59cc8ee87e
commit 55265d5145
18 changed files with 2308 additions and 96 deletions

View File

@@ -1,12 +1,44 @@
import { jsonResponse, errorResponse } from '../utils/cors'
import { getTranscriptAnalysis, listSessions } from '../services/transcript-engine'
import { getTranscriptAnalysis, listSessions, getActiveSession, resetSessionOffset, getClaudeStats, getClaudeUsage } from '../services/transcript-engine'
import type { TranscriptAnalysis } from '../services/transcript-engine'
export function handleClaudeUsage(): Response {
const usage = getClaudeUsage()
if (!usage) return errorResponse('Usage data not available', 404)
return jsonResponse(usage)
}
export function handleClaudeStats(): Response {
const stats = getClaudeStats()
if (!stats) return errorResponse('Stats not available', 404)
return jsonResponse(stats)
}
export function handleTranscriptSessions(): Response {
const sessions = listSessions()
return jsonResponse(sessions)
}
export function handleTranscriptActive(req: Request, url: URL): Response {
if (req.method !== 'GET') return errorResponse('Method not allowed', 405)
const agent = url.searchParams.get('agent') || 'main'
const activeSession = getActiveSession(agent)
const sessionId = activeSession?.sessionId
const analysis = getTranscriptAnalysis(sessionId, activeSession?.transcriptPath)
if (!analysis) return errorResponse('No active session found', 404)
// Reset offset so future incrementals start from here
resetSessionOffset(analysis.sessionId)
return jsonResponse({
...analysis,
messages: analysis.messages.filter(m => !m.isMeta)
})
}
export function handleTranscript(req: Request, url: URL, sessionId: string): Response {
if (req.method !== 'GET') return errorResponse('Method not allowed', 405)
@@ -63,7 +95,8 @@ function handleSection(analysis: TranscriptAnalysis, section: string): Response
version: analysis.version,
duration: analysis.duration,
startTime: analysis.startTime,
endTime: analysis.endTime
endTime: analysis.endTime,
lastStopReason: analysis.lastStopReason
})
case 'files':
return jsonResponse({