## Summary - Wraps store-proxied array iteration in `untrack()` in two `createEffect` blocks and one `createMemo` in `message-section.tsx` to prevent SolidJS from creating O(n) per-element reactive subscriptions on every run - Replaces `ids.includes()` with `Set.has()` for O(1) cleanup lookups in the part-count tracking effect ## Problem Two `createEffect` blocks in `message-section.tsx` iterate the `messageIds()` store proxy array inside a tracked reactive context. This causes SolidJS to create **O(n) per-element subscriptions** on every run. When any element changes, all n subscriptions fire, re-running the entire effect — resulting in **O(n²) total work**. Additionally, the cleanup loop in the part-count tracking effect uses `ids.includes(trackedId)` which is O(n) per tracked ID, compounding to O(n²). For long-running sessions with large message history (e.g. 7569 messages), this caused **~4.8 seconds of input latency** when sending a new prompt. ## Fix 1. **Timeline sync effect (~line 738):** Wrap entire body in `untrack()`, replace `ids.slice()` with `[...ids]` to snapshot without proxy tracking 2. **Part-count tracking effect (~line 891):** Wrap iteration in `untrack()`, replace `ids.includes()` with `new Set(ids).has()` for O(1) lookups 3. **`lastAssistantIndex` memo:** Read message records via `untrack()` to avoid O(n) subscriptions on part-level updates ## Result On a 7569-message session: prompt input latency reduced from **~4.8s to ~42ms** (114x improvement).
CodeNomad UI
This package contains the frontend user interface for CodeNomad, built with SolidJS and Tailwind CSS.
Overview
The UI is designed to be a high-performance, low-latency cockpit for managing OpenCode sessions. It connects to the CodeNomad server (either running locally via CLI or embedded in the Electron app).
Features
- SolidJS: Fine-grained reactivity for high performance.
- Tailwind CSS: Utility-first styling for rapid development.
- Vite: Fast build tool and dev server.
Development
To run the UI in standalone mode (connected to a running server):
npm run dev
This starts the Vite dev server at http://localhost:3000.
Building
To build the production assets:
npm run build
The output will be generated in the dist directory, which is then consumed by the Server or Electron app.
Debug Logging
The UI now routes all logging through a lightweight wrapper around debug. The logger exposes four namespaces that can be toggled at runtime:
sse– Server-sent event transport and handlersapi– HTTP/API calls and workspace lifecyclesession– Session/model state, prompt handling, tool callsactions– User-driven interactions in UI components
You can enable or disable namespaces from DevTools (in dev or production builds) via the global window.codenomadLogger helpers:
window.codenomadLogger?.listLoggerNamespaces() // => [{ name: "sse", enabled: false }, ...]
window.codenomadLogger?.enableLogger("sse") // turn on SSE logs
window.codenomadLogger?.disableLogger("sse") // turn them off again
window.codenomadLogger?.enableAllLoggers() // optional helper
Enabled namespaces are persisted in localStorage under opencode:logger:namespaces, so your preference survives reloads.