Commit Graph

8 Commits

Author SHA1 Message Date
2378bc00ba docs: replace invented memory figures with measured ones, ship the tuning knobs
The README claimed "~15 MB RSS" and, after the log-loading work, "~10 MB idle /
~19 MB with a 29 MB audit log". Those were TEST-INSTANCE numbers: one mock source
and one adapter. The real production config on this host (16 sources, 13
adapters, 59 models) sits at ~37-42 MB, and sat at ~105 MB before this series.
Quoting the single-source figure as the headline was misleading.

Both READMEs now state that memory scales with the number of configured sources
rather than with uptime, give a three-row measurement table (1 source / 1 source
with a 29 MB audit history / the 16-source production instance), and break the
production RSS down per region (Go heap, thread stacks + LuaJIT, mapped binary,
Go reservations, shared libs) so an operator can tell which part their own
deployment will grow.

Two runtime knobs are documented and now shipped by default in the desktop
build's core spawn (cmd/gui/main.js, overridable by exporting either variable):

  * MALLOC_ARENA_MAX=2 — LuaJIT allocates through cgo into glibc malloc, and
    glibc keeps up to 8*nproc per-thread arenas of ~1 MB that are never returned.
    Measured 8-15 arenas (7-12 MB) -> 0.
  * GOGC=50 — halves the Go heap target. Documented explicitly as useless ALONE
    (measured 20.3 -> 21.5 MB, i.e. worse, because the saved heap is eaten by
    more glibc arenas); only the pair cuts settled RSS, by ~19%.

Also corrects the binary size (8-12 MB, ~8 MB after the deploy script's -s -w)
and adds the elastic-pool / on-demand-log / self-healing-cooldown bullets that
README.md already had to README_EN.md.
2026-08-30 09:09:21 +08:00
dev
334b984c25 fix(webui,gui): repair dead export button + wire chat clear; prune UI redundancy
WebUI (internal/gateway/ui):
- BUG: the export modal's custom-range button called
  downloadStatsCsvFromForm() which was never defined — clicking it threw a
  ReferenceError and nothing downloaded. Implement it: reads #exp-from /
  #exp-to date inputs and forwards to downloadStatsCsv.
- BUG-adjacent: clearChat() existed but was reachable from no control —
  add a Clear button to the chat composer so conversation reset is actually
  possible (+ cClear i18n zh/en).
- remove byte-identical duplicate html[data-theme=dark] CSS block (15 lines)
- remove 8 dead CSS rules (.keys-grid .m-model-row .scope-add/.scope-box/
  .scope-chips .scr-blocks .tag-warn .twrap) and the never-consumed
  --accent custom property
- remove 3 dead JS functions (activeTab/findSlots/scopeUncomb; lastTab decl kept)
- remove 24 dead i18n keys x zh/en (~55 lines) — legacy of the replaced
  key-scope editor, matching the removed .scope-* styles

GUI (cmd/gui/main.js):
- BUG: stopCore() set app.isQuitting=true and nothing reset it — after using
  tray 'stop core', closing the window quit the whole app instead of hiding
  to tray, and core crash auto-restart stayed disabled. isQuitting now only
  flips in restartCore (scoped) and before-quit.

Verified: go vet/test green; node --check on all three GUI js files and the
WebUI inline script.
2026-08-24 23:13:54 +08:00
98c08d51c4 fix(gui): re-enable hardware acceleration — remove blanket disableHardwareAcceleration() 2026-08-17 23:02:49 +08:00
b9f2486037 fix(gui): strip host LD_LIBRARY_PATH from packaging + defensive GPU/icon fixes
Root cause of the packaged GUI crashing with SIGSEGV inside ld.so on user
machines (segfault at fixed +0x1ff36, undefined symbols nspr_use_zone_allocator
/ localtime64): the build host had LD_LIBRARY_PATH polluted by a third-party
runtime (/opt/cangjie), which electron-builder baked into the produced binary's
dependency resolution. Clean machines without that library then fail in the
dynamic loader before any app code runs.

- Makefile: every gui-* pack target now runs under `env -u LD_LIBRARY_PATH`
- main.js: app.disableHardwareAcceleration() before ready (avoids the common
  Chromium GPU-process SIGSEGV on hybrid-GPU/Wayland Linux hosts)
- main.js: window icon reads from process.resourcesPath (real file, not asar)
  — asar-path icons are a known GTK segfault source on Linux
2026-08-17 19:50:34 +08:00
8c5279b416 fix(status): source column reflects real traffic + theme-aware tray menu
- api/status sources now carry recent_ok/recent_err (last 300s real gateway
  requests via Stats.SourceRecent) so a source actually serving traffic is
  never shown as down just because probe /models got rate-limited
- WebUI source status column repaints every 5s (no more frozen-at-first-
  render) with a manual refresh button; shows success rate + probe + cooldown
- tray menu status rows were enabled:false (GTK fixed light-grey, invisible
  on light themes) — now enabled with no-op click and nativeTheme listener
  rebuilds the menu on dark/light switches
- ignore local ops scripts (scripts/, machine-specific)
2026-08-17 17:37:04 +08:00
23bd9e5552 fix(gui): resolve GNOME taskbar icon via WM_CLASS/StartupWMClass match
Window/taskbar icon never showed because the packaged .desktop had
StartupWMClass=ModelRouter while the live window WM_CLASS is the lowercase
app class 'modelrouter-gui' — no match, so GNOME fell back to the default
Electron icon.

- main.js: set BrowserWindow icon asset + backgroundColor (window paints
  correctly with frameless titlebar and provides the taskbar's default icon)
- package.json: build.linux.desktop.entry.StartupWMClass now equals the real
  WM_CLASS so packaged installs match too
- local integration: user-level .desktop installed at
  ~/.local/share/applications/modelrouter-gui.desktop (points at the unpacked
  binary) so GNOME resolves the icon immediately
2026-08-17 10:33:10 +08:00
f67831c3c2 fix(gui): desktop shell stability — gated ready state, iframe retry with backoff, theme toggle
- coreReady now only flips after the embedded core actually answers HTTP
  (fixes blank-screen race where the iframe loaded before the listener)
- renderer probes reachability, retries frame load with exponential backoff,
  and recovers via onerror instead of giving up forever
- keep per-user theme in localStorage
- embedded profile no longer preconfigures a zen source (desktop users add
  their own upstreams on the sources page)
2026-08-17 08:53:28 +08:00
47f3b44d92 feat(gui): Electron desktop with embedded core, tray, autostart, win/linux packaging
- cmd/gui: Electron shell (Clash-Verge style) embedding the full WebUI 1:1
  - embedded llmsproxy core (luajit) with auto-generated profile
  - key stored in keys[] (non-seed) so no replace-the-key warning
  - gw_key cookie injection: web UI works without login
  - side-rail toggles for autostart / silent start
  - system tray with status + controls, silent start (--silent)
  - win cross-build (mingw luajit exe + dll) / deb / AppImage via electron-builder
- Makefile: build / gui / gui-dist / gui-deb / gui-win targets
- README: desktop GUI section
- lua(adapter): opencode normalizes non-whitelisted roles to system
2026-08-16 09:53:05 +08:00