feat: voice assistant integration, PiP window fixes, widget improvements and pixel art scrollbar

- Android voice assistant: RecognitionService, VoiceInteractionSession with startAssistantActivity, es-HN speech recognition
- Voice transcript sent to first alive terminal via WebSocket, opens FloatingTranscriptDebug on correct session
- PiP window: fix close button using getCurrentWebviewWindow(), add mini/restore toggle, remove alwaysOnTop
- Add webview-close and window-destroy permissions to capabilities
- Pixel art ocean scrollbar on /transcript-debug respecting scroll nav mode settings
- Widget improvements: terminal list service, input widget provider, updated layouts
This commit is contained in:
2026-02-23 22:35:58 -06:00
parent f6ec5ba5de
commit c46b1283d1
14 changed files with 837 additions and 252 deletions

View File

@@ -7,10 +7,13 @@ import { PORT_TERMINAL } from '../config'
* so external clients (Android widget) get everything in one call.
*/
export async function handleSessionStateProxy(url: URL): Promise<Response> {
const controller = new AbortController()
const timeout = setTimeout(() => controller.abort(), 6000)
try {
const [stateResp, registryResp] = await Promise.all([
fetch(`http://localhost:${PORT_TERMINAL}/session-state`),
fetch(`http://localhost:${PORT_TERMINAL}/terminal-registry`)
fetch(`http://localhost:${PORT_TERMINAL}/session-state`, { signal: controller.signal }),
fetch(`http://localhost:${PORT_TERMINAL}/terminal-registry`, { signal: controller.signal })
])
const stateData = stateResp.ok ? await stateResp.json() : { agents: {} }
@@ -21,6 +24,11 @@ export async function handleSessionStateProxy(url: URL): Promise<Response> {
registry: registryData.registry ?? []
})
} catch (e: any) {
return errorResponse(`Failed to reach terminal server: ${e.message}`, 502)
const msg = e.name === 'AbortError'
? 'Terminal server timeout (6s)'
: `Failed to reach terminal server: ${e.message}`
return errorResponse(msg, 502)
} finally {
clearTimeout(timeout)
}
}