- New CONTRIBUTORS.md: full ranked credit roll for all 66 contributors
(5+ tiers), with first/latest release versions, single-PR roll, and
attribution methodology. Generated from git log + gh pulls API +
CHANGELOG mention parsing.
- README.md: stack-ranked top-10 contributors table at the top of the
Contributors section, link to CONTRIBUTORS.md for the full list.
Updated test count (1898 → 3309). Refreshed @franksong2702 and
@bergeouss entries to reflect their broader bodies of work (now
the #1 and #2 external contributors).
- ARCHITECTURE.md: removed stale 'tracks upstream v0.50.36' header;
bumped current shipped build to v0.50.245 with current architecture
state notes (streaming-markdown vendoring, byte-range streaming,
configurable-model-badges).
- ROADMAP.md / SPRINTS.md / TESTING.md: header/last-updated bumps to
v0.50.245 and 3309 tests. SPRINTS.md 'Where we are now' section
refreshed for current CLI/Claude parity (~95% Claude parity now).
Generated by aggregating CHANGELOG attribution lines, gh PR API
authors, and CHANGELOG version-section walks. Internal/bot accounts
filtered out.
Per Opus pre-release review (SHOULD-FIX #1): the CHANGELOG claimed both
filter sites exempt 'active_stream_id OR pending_user_message', but the
index path operates on compact() output which doesn't include
pending_user_message. The behavior is correct in both paths because both
fields are set/cleared in lockstep during streaming, but the wording was
stronger than what the code does. Tightened to describe what each path
actually checks.
release: v0.50.243
Batch release of 2 PRs.
- #1301 — fix: remove PRIMARY chip badge + add Claude Opus 4.7 label
Drops the chip-projected configured-model badge added in #1287 (chip
width 235px → 164px). Adds Claude Opus 4.7 label entries so the picker
no longer renders "Claude Opus 4 7" (missing dot).
Independently reviewed and approved by nesquena (commit c0bbd23).
- #1297 (@franksong2702) — fix: preserve cron output response snippets
Fixes#1295. /api/crons/output now preserves the ## Response section
when a large skill dump appears in the prompt section; falls back to
file tail when no marker exists.
Tests: 3254 passed, 2 skipped, 3 xpassed.
Independently reviewed and approved by nesquena (commit b262e4d).
Reverts the global assistant serif rule and removes the Calm theme that were shipped in v0.50.240 PR #1282. Pure deletion; 3252 tests passing. Override on independent review per Nathan.
When the user explicitly selects @provider:model from the picker,
_resolve_compatible_session_model() was stripping the prefix because
the hint matched the active provider (hint_matches_active=True → return bare_model, True).
This caused:
- The picker to snap back to the first duplicate entry on next render
- resolve_model_provider() to use the default provider instead of the
explicitly selected one, running the agent on the wrong backend
The hint_matches_active branch was intended for normalizing stale cross-
provider session models. But an @provider:model where the hint IS the
active provider is not stale — it is the user's deliberate selection.
Fix: return (model, False) so the full @provider:model survives to
resolve_model_provider() in config.py, which already handles it correctly.
Updates test_active_at_provider_session_model_preserved_with_hint and
adds test_issue1253_duplicate_model_id_active_provider_hint_preserved.
Closes#1253
The post-stream renderMd() in static/ui.js only handled #, ##, ### — lines starting with #### through ###### fell through and emitted as literal text after streaming finalized.
Extend the heading replacer chain to cover h4-h6, ordered longest-first, so ###### cannot be partially captured by the shorter ### rule. Add the matching .msg-body h4/h5/h6 CSS rules (and data-font-size variants) so the new tags inherit the same visual rhythm as h1-h3.
Adds 3 node-driven tests in test_renderer_js_behaviour.py pinning all six heading levels and the longest-first replacer order.
Closes#1258
All LRU cache operations (get, set, move_to_end, popitem) are already
protected by SESSION_AGENT_CACHE_LOCK. This addresses the reviewer's
concern about thread safety in multi-threaded ASGI servers.
Problem:
- GET /api/mcp/servers returned 404 error
- MCP servers management UI could not load server list
- Root cause: route was placed outside handle_get(), in unreachable code
Root Cause:
- The MCP servers GET route was incorrectly placed after handle_get() returned False (404)
- handle_get() function returns False at line ~1224, so any code after it won't execute
- The route was also in handle_post() area but without proper method checking
Solution:
- Moved GET /api/mcp/servers route inside handle_get() before the return False statement
- Removed the misplaced route from the old location (originally around line 1636)
- Also updated /api/profiles response format to include full profiles list
Testing:
- After restart: curl http://localhost:8787/api/mcp/servers returns {"servers": []}
- No more 404 errors
- WebUI can now properly load MCP servers list
The agent cache stores full AIAgent instances (each holding complete
conversation history) without size limit. Long-running servers with
many sessions can accumulate unbounded memory usage.
Changes:
- Replace dict with OrderedDict for LRU tracking
- Add SESSION_AGENT_CACHE_MAX = 50 limit
- Evict least-recently-used entries when cache exceeds limit
- Call move_to_end() on cache hits to maintain LRU order
This prevents memory exhaustion on servers with many active sessions.