Skip to content

feat: Unified start command, analytics dashboard, OpenRouter support, and dual release channels - #116

Merged
samueltuyizere merged 59 commits into
mainfrom
86-anthropic-path-502s-when-the-system-field-contains-a-newline-jsonrawmessage-marshal-error
Jul 12, 2026
Merged

samueltuyizere merged 59 commits into
mainfrom
86-anthropic-path-502s-when-the-system-field-contains-a-newline-jsonrawmessage-marshal-error

Conversation

@samueltuyizere

Copy link
Copy Markdown
Collaborator

Summary

This PR consolidates multiple enhancements to routatic-proxy:

Unified Startup (routatic-proxy start)

  • New start command runs both proxy server and GUI dashboard together
  • Proxy on 127.0.0.1:3456, Dashboard on 127.0.0.1:3445
  • Supports --background flag for daemon mode
  • Removed separate ui command (superseded by start)
  • Updated autostart (Linux, macOS, Windows) to use start --background

Analytics Dashboard

  • Added SQLite-based analytics storage layer
  • Dashboard reads from persisted data (no in-memory interception)
  • New API endpoints:
    • GET /api/analytics/summary - Token counts, request totals, success rate
    • GET /api/analytics/tokens/trend - Daily token usage over time
    • GET /api/analytics/latency - Latency statistics by model
  • GUI server binds to fixed port 3445 with single-instance management
  • Analytics tab with KPI cards, donut charts, and token trend line

OpenRouter Integration

  • Added OpenRouter as a supported provider
  • Enhanced AWS Bedrock integration with proper endpoint routing

Dual Release Channel System

  • Beta channel (automatic on push to main)
  • Production channel (manual workflow_dispatch)
  • New update-channel command to switch between stable/beta
  • Version detection script for CI

Build Info Enhancements

  • Added PID() and BinaryPath() functions
  • Tests for build info validation

Breaking Changes

  • routatic-proxy ui command removed - use routatic-proxy start instead
  • routatic-proxy serve --background autostart now uses start --background

Commands Changed

Before After
routatic-proxy ui routatic-proxy start
routatic-proxy serve routatic-proxy serve (unchanged)
routatic-proxy serve --background routatic-proxy start --background

Checklist

  • Tests pass locally
  • Lint checks pass
  • Documentation updated (CLAUDE.md)

…add endpoint handling for AWS Bedrock models
…ling

- Added comprehensive documentation for OpenRouter models, including key benefits, model naming conventions, and popular models.
- Updated README to include OpenRouter setup instructions and environment variable configurations.
- Implemented content detection in SSE responses to improve error handling during streaming.
- Introduced new error type for empty streams and updated streaming logic to handle empty responses gracefully.
- Added test cases for AWS Bedrock provider to ensure correct endpoint resolution for various model IDs.
- Introduced OpenRouter models documentation detailing supported models, context windows, and pricing.
- Created a new OpenRouter provider configuration guide for seamless integration.
- Enhanced AWS Bedrock provider to support OpenAI Responses API for models prefixed with "openai.gpt-".
- Implemented request handling for OpenAI Responses in AWS Bedrock, including streaming capabilities.
- Updated tests to validate new OpenAI path handling and ensure correct endpoint usage for OpenAI models.
…rd and refactor update channel command for clarity
Comment thread Dockerfile
Comment thread .github/workflows/release.yml
Comment thread .github/workflows/release.yml Outdated
Comment thread internal/update/update.go Outdated
Comment thread internal/gui/server.go Outdated
Comment thread internal/gui/server.go Outdated
Comment thread internal/handlers/messages.go
@kilo-code-bot

kilo-code-bot Bot commented Jul 12, 2026 •

Copy link
Copy Markdown
Contributor

Code Review Roast 🔥

Verdict: No New Issues Found | Recommendation: Prior findings remain — see inline comments

Incremental note: This run reviewed the diff 5e9f7ad..afe958c, which is a documentation-only commit (REVIEW.md, +283 lines). Zero code changed, so no new changed-code issues were found. The 22 prior findings are still active on unchanged files.

📊 Overall: This incremental was one commit of pure docs — zero code, zero fixes. Like repainting a car while it's still leaking oil from the engine block.

Files Reviewed (incremental)
  • REVIEW.md - 0 issues

Fix these issues in Kilo Cloud

Previous Review Summary (commit 5e9f7ad)

Current summary above is authoritative. Previous snapshots are kept for context only.

Previous review (commit 5e9f7ad)

Verdict: 2 Issues Found | Recommendation: Address before merge

Incremental note: This run reviewed the diff 5e9f7ad..43c502a, which is a documentation-only commit (REVIEW.md, +270 lines). No code changed, so no new changed-code issues were found. The previously reported code findings below are still unresolved — the new commit politely walked around them without fixing a single one.

Overview

Severity Count
🚨 critical 1
⚠️ warning 1
💡 suggestion 0
🤏 nitpick 0
Issue Details (click to expand)
File Line Roast
internal/gui/assets/index.html 7 Replaced self-contained local dashboard with external Tailwind CDN dependency
internal/gui/server.go 759 CSP comment claims same-origin only but explicitly allows external CDN

🏆 Best part: The new REVIEW.md is thorough and well-structured — a genuinely nice addition. Too bad it documents a dashboard that now phones home to a CDN for styling it used to ship locally.

💀 Worst part: The cdn.tailwindcss.com dependency in a local-only proxy dashboard is still sitting there untouched, like a smoke detector with the battery removed — technically present, functionally asleep. A local proxy that requires the internet is like a privacy VPN that logs everything: technically functional, spiritually bankrupt.

📊 Overall: This incremental was one commit of pure docs — zero code, zero fixes. The Tailwind supply-chain issue remains wide open. Like painting the walls of a house while leaving the front door unlocked.

Files Reviewed (incremental)
  • REVIEW.md - docs only, 0 issues
  • internal/gui/assets/index.html - re-verified, unchanged, prior finding still open
  • internal/gui/server.go - re-verified, unchanged, prior finding still open

Fix these issues in Kilo Cloud


Reviewed by step-3.7-flash-20260528 · Input: 73.2K · Output: 2.4K · Cached: 199.6K

Comment thread cmd/routatic-proxy/start_gui_darwin.go
Comment thread cmd/routatic-proxy/start_gui_darwin.go
Comment thread internal/gui/assets/index.html Outdated
Comment thread internal/gui/assets/index.html Outdated
Comment thread internal/gui/assets/style.css Outdated
Comment thread internal/gui/assets/style.css Outdated
samueltuyizere and others added 6 commits July 12, 2026 21:49
Co-authored-by: kilo-code-bot[bot] <240665456+kilo-code-bot[bot]@users.noreply.github.com>
Signed-off-by: TUYIZERE Samuel <tuyizeres0@gmail.com>
Co-authored-by: kilo-code-bot[bot] <240665456+kilo-code-bot[bot]@users.noreply.github.com>
Signed-off-by: TUYIZERE Samuel <tuyizeres0@gmail.com>
Co-authored-by: kilo-code-bot[bot] <240665456+kilo-code-bot[bot]@users.noreply.github.com>
Signed-off-by: TUYIZERE Samuel <tuyizeres0@gmail.com>
Co-authored-by: kilo-code-bot[bot] <240665456+kilo-code-bot[bot]@users.noreply.github.com>
Signed-off-by: TUYIZERE Samuel <tuyizeres0@gmail.com>
Comment thread internal/storage/analytics.go Outdated
Comment thread internal/storage/analytics.go
Comment thread internal/gui/assets/index.html Outdated
Comment thread internal/gui/server.go Outdated
@samueltuyizere
samueltuyizere merged commit b5c713a into main Jul 12, 2026
3 checks passed
@samueltuyizere
samueltuyizere deleted the 86-anthropic-path-502s-when-the-system-field-contains-a-newline-jsonrawmessage-marshal-error branch July 12, 2026 23:19
samueltuyizere added a commit that referenced this pull request Aug 22, 2026
…correctness pass (#140)

* chore: fix flaky watcher test, patch npm advisories, add Fedora RPM builds

Four pieces of maintenance and one new deliverable.

Flaky test — TestWatchConfig_DetectsFileChange failed roughly 1 in 4
full-suite race runs and blocked pushes via the pre-push hook. Two races
were involved: WatchConfig registers its fsnotify watch asynchronously, so
the test's sleep-then-write could lose the write entirely; and
AtomicConfig.Reload runs reload callbacks before publishing the new pointer,
so asserting via Get() could read the old config. Adds
WatchConfigWithReady, which signals once the watch is registered, letting
the test wait for readiness, write once, and assert on the config handed to
the callback. WatchConfig keeps its signature and delegates, so both
production call sites are unchanged. OnReload now documents the
callback-before-publish ordering.

Dependency advisories — postcss 8.5.18 to 8.5.26 (GHSA-fxqj-rqcc-2cmp,
Dependabot alert #2) and nanoid to 3.3.18 (GHSA-2v37-7h3g-55p8, high
severity, never alerted on). Both were in range of the existing
tailwindcss constraint, so no breaking upgrade. npm audit is clean and the
checked-in compiled-tailwind.css is byte-identical after a rebuild. Adds
.github/dependabot.yml covering gomod, npm and github-actions, since the
unreported nanoid advisory showed the gap.

Fedora packaging — builds x86_64 and aarch64 RPMs with nfpm (pinned
v2.47.0) and attaches them to both release channels. The RPMs are produced
inside the existing release job and passed to the single gh release create
call: this repo publishes immutable releases, so assets added afterwards
would be rejected. A verification step reads the ELF header directly
(magic, class, e_machine) rather than grepping file output, which words
things differently on macOS and would silently always pass. Package layout
follows Fedora conventions: binary in /usr/bin, config in /etc marked
noreplace so upgrades keep local edits, license in /usr/share/licenses,
and an opt-in systemd *user* unit in /usr/lib/systemd/user — a system unit
would wrongly imply a machine-level daemon for a loopback developer proxy.
Adds a make rpm target for local inspection, since rpm -qip is unavailable
on the macOS runner.

Docs — corrections found by auditing every doc against the source:
the long-context threshold is 100K not 80K, the vision tier was missing
from the documented scenario priority, there are four endpoint types not
two, the Anthropic endpoint covers Qwen as well as MiniMax, model tables
now match modelMetadata, the scenario defaults now match the shipped
default_config.json, OpenRouter's API-key env vars were undocumented, and
config.example.json gained the six real config blocks it was missing.
Removes a documented request_dedup option that does not exist in the code
and documents the three analytics routes that do. Fixes stale beta-version
formats and broken links, and flags the zh translations that lag.

* chore: dynamic routing reasons, strict lint, Linux RPM job, doc sync

Follow-ups on the four decisions taken after the previous commit.

Routing reasons now read the resolved model from config. The Reason strings
in scenarios.go hardcoded model names that had drifted (GLM-5.1, Kimi K2.6)
because ScenarioResult.Reason had zero production consumers — nothing ever
displayed them, so nobody noticed. DetectScenario now explains only why a
scenario matched, and ModelRouter appends the model at the point it is
actually resolved, covering scenario, cost-based catalog selection,
respect_requested_model and both override paths. The routing log line now
carries it, and a test fails if a detector reason ever names a model again.
Also fixes ScenarioPolicy.Evaluate, which was formatting the scenario name
twice as a placeholder instead of using the reason.

golangci-lint is now configured rather than implied. Adds a .golangci.yml
in v2 schema that passes with zero issues on the current tree: the standard
set plus bodyclose, copyloopvar, misspell, nolintlint, whitespace, and
revive with an explicit 23-rule list. gosec, errorlint and gocritic were
evaluated and rejected — their findings are either inherent to a local CLI
or need code changes, and suppressing them wholesale would make the linter
meaningless. Adds make lint-strict, pins the CI lint action by SHA, and the
committed pre-push hook now picks the config up with no change. make lint
stays as the fast gofmt+vet check.

RPM packaging moves to a dedicated Linux job so CI can actually inspect the
packages. rpm runs on ubuntu-latest before release and hands over the
rpm-packages artifact, which still enters the single atomic gh release
create — immutable releases forbid adding assets afterwards. Verification
asserts name, version, architecture, license, every payload path, the
noreplace flag on the config, and that the packaged binary is an executable
ELF of the right machine type; it collects all failures before exiting. The
same scripts run in ci.yml on every PR, so packaging breaks at review time
rather than at release time.

Documentation. docs/models.md was a second, thinner copy of MODELS.md
introduced by #116; it is now a pointer, because the duplication had already
caused real drift — an earlier pass corrected the capability numbers in one
file and left the same errors in the other. Those errors are fixed: MiniMax
M2.5 is 200K not 1M (so long-context advice now points at MiniMax M3, which
is what the shipped config uses), all four Qwen3.x models are 1M not 128K
and are vision-capable, Kimi vision was undocumented, gpt-5.5-mini/nano were
missing, and a documented fallback chain routed long context through a 200K
model. The Chinese translations of CONFIGURATION, MODELS and INSTALLATION
are brought up to date with their English originals, and English
TROUBLESHOOTING gains the sections that only existed in Chinese.

* docs: resolve Kimi K2.6 cost contradiction, document RPM and macOS GUI installs

The Kimi K2.6 row in the cost comparison table said ~1,150 requests per $12
while its own profile, the decision tree and the quick reference all said
1,850. Nothing in the repo can settle it — the model catalog carries no rate
data for any of its 353 models — but the row duplicated GLM-5's figure
exactly, which reads as a copy-paste, and 1,850 is what the other three
places and the model's value rating agree on. Both files now say 1,850, and
the table gained a note that these figures are indicative estimates rather
than a machine-readable price list, so the next reader knows not to budget
against them.

INSTALLATION.md documented Homebrew, Scoop, source, raw binaries and Docker
but never mentioned the RPMs, even though it is the canonical install doc
that README points at. It now covers dnf installation, the noreplace config
template, the opt-in systemd user unit, the missing GPG signature, and the
fact that `routatic-proxy update` is for standalone binaries rather than RPM
installs.

The macOS DMG was documented only in Chinese. Ported to English, describing
what the menu bar item actually offers per internal/tray/tray_darwin.go —
status, Open Console, start/stop, and Start on Boot — with the CLI
equivalents. The Chinese install guide gained the RPM section in turn, so
the two stay in sync.

* fix(ci): extract RPM payloads with relative paths in verification

The RPM Packaging job failed on ubuntu-latest with "cpio: cannot make
directory '/etc/routatic-proxy': Permission denied". RPM payload members are
absolute paths, and whether cpio strips the leading "/" by default differs
between distributions — Fedora's does, Ubuntu's does not, so the extraction
step aimed at the runner's real /usr and /etc instead of the temp dir.

Passing --no-absolute-filenames makes it explicit rather than relying on the
local default. This is why the job exists: the same script passed on a Fedora
workstation and only failed on a real Linux CI runner.

* fix(ci): judge cpio's status, not rpm2cpio's, when verifying RPMs

Ubuntu's rpm2cpio exits 1 even when it has written the payload in full, while
Fedora's exits 0. Under `set -o pipefail` that sank the whole extraction
pipeline, so the RPM job failed on ubuntu-latest immediately after the
previous fix let cpio run at all.

The status we care about is cpio's, so the pipeline runs with pipefail off and
its subshell status is captured instead. Because that means neither exit code
is fully trusted, the script now also compares the extracted binary's size
against the size recorded in the RPM header — a mid-stream extraction failure
would otherwise leave a truncated binary whose ELF header still looks valid.

Reproduced and fixed against ubuntu:24.04 in a container rather than guessing:
both arches now pass on Ubuntu and Fedora, and the wrong-arch and
wrong-version negative controls still exit 1.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Anthropic path 502s when the system field contains a newline (json.RawMessage marshal error)

1 participant