- Normalize Responses API tool format ({name, parameters} at top level)
to Chat Completions format ({function: {name, parameters}})
- Handle 'developer' role as system prompt (OpenAI's newer equivalent)
- Add null/non-array guards to convertOpenAIPartsToAnthropicContent and
extractOpenAITextContent to prevent 'content is not iterable' crashes
- Support input_text, output_text, and reasoning item types in Responses
API input parsing
- Forward reasoning.effort to Claude adaptive thinking config
- Extend JSON schema sanitization blacklist with draft-2020 keywords
(patternProperties, , unevaluatedProperties, etc.)
- Add fallback for untyped items with role/content in Responses API input
- Add diagnostic logging for /v1/responses input conversion
Backend fixes:
- Fix totalTokens defaulting to 0 when API omits totalTokenCount (now computes prompt+completion)
- Fix streaming metadata extraction: unwrap response wrapper in Anthropic/Gemini handlers
- Fix Zod schemas: handle SQL SUM(null) with nullable().transform()
- Add is_estimated column migration to token_usage table
Frontend redesign:
- Rewrite Usage page with area charts (nivo/line), horizontal bar model ranking
- StatCard: add trend indicators (% vs previous period) and inline SVG sparklines
- Premium color palette, prompt/completion ratio bar, top models mini-list
- Live indicator with 15s auto-refresh
Design system migration:
- Standardize all components on Gemini Nexus tokens (rounded-xl, border-white/[0.06])
- Refine UI components, proxy tabs, cloud account list, provider groups
- Emit tool call id+name in first SSE delta and arguments in subsequent deltas
- Split large tool arguments into 1000-char chunks to prevent framing issues
- Set FastifyAdapter bodyLimit to 10MB to handle large payloads
- Add TDD tests for tool call streaming verification
- Add cacheHitRate to ProxyMetricsService, handler, and router schema
- Fix StatCard to support string values and purple accent
- Fix duplicate tabs keys in i18n translations (EN/ZH/RU)
- Add missing cacheStatus translations across all languages
The initial role chunk (role:'assistant', content:'') added in a3eabc2
was causing the OpenCode TUI to receive an empty first delta and
discard all subsequent content, showing only the completion time with
no text output.
Restored to the exact streaming behavior from e524a340 that worked:
- Remove the pre-emptive initial chunk entirely
- Move hasEmittedChunk=true back inside pushChunk (original position)
- Use reasoning_content delta field for thought parts instead of
wrapping in <think> tags (which corrupts plain text responses)
- Remove streamOptions/include_usage/lastUsageMetadata tracking
(not present in the working version)
- Remove isThinking state machine (was adding </think> noise to output)
Kept from the spec compliance work (a3eabc2):
- toolCallIndex counter for correct finish_reason:'tool_calls' mapping
- Comment explaining why we override Gemini's STOP finish reason
Route fixes:
- Add POST /v1/messages/chat/completions alias so OpenCode clients
misconfigured with baseURL ending in /v1/messages no longer get 404
Session affinity:
- Extract x-session-affinity HTTP header (sent by OpenCode) and use it
as the session key for token stickiness, falling back to body-level
session_id fields if the header is absent
Tool calling (streaming):
- finish_reason is now 'tool_calls' when function calls were emitted in
the stream (Gemini always sends STOP, so we check toolCallIndex > 0)
- createSyntheticOpenAIStream (stream fallback path) now emits all
tool_call deltas before the finish chunk instead of silently dropping
them when content is null
Tool calling (non-streaming):
- content is now always null when tool_calls are present, satisfying
strict clients that reject non-null content alongside tool_calls
- system_fingerprint field added to OpenAIChatResponse interface and
response builder for OpenAI spec compliance
Usage accounting:
- thoughtsTokenCount is now included in completion_tokens and
total_tokens for the streaming usage chunk, fixing undercount for
thinking/reasoning model runs
* feat: Implement provider groupings with account calculator and comprehensive fixes
- Add provider detection utilities (detectProvider, PROVIDER_REGISTRY) for Claude/Gemini/Others categorization
- Implement grouping logic (groupModelsByProvider, calculateProviderStats, calculateAccountStats) with health status calculation
- Create useProviderGrouping hook for collapsible state management and persistence
- Add ProviderGroup component with health indicators, progress bars, and model visibility integration
- Enhance CloudAccountList with account-level calculator showing overall percentage and earliest reset time
- Implement grid layout selector (auto/2-col/3-col/list) with config persistence and tooltips
- Add global quota aggregate bar across all accounts in top statistics
- Fix model visibility settings regression by accessing account.quota.models instead of account.quota
- Show 'Rate Limited' instead of '0%' for exhausted quotas with consistent getQuotaLabel function
- Add comprehensive i18n translations for layout selector and rate limited labels (en, zh-CN, ru)
- Disable batch operations when provider groupings are enabled to prevent conflicts
- Include unit tests for provider detection logic and grouping functionality
Addresses critical issues: model list regression, rate limited display, layout control, global quota visibility, and consistent quota labeling across all components.
* fix: resolve ESLint no-ex-assign violations in proxy service
- Fix exception parameter reassignment in catch blocks
- Rename catch parameters to avoid no-ex-assign rule violations
- Maintain same error handling logic while complying with linting rules
* fix: add missing Models tab to settings page
- Add Models tab between General and Proxy tabs
- Import and integrate ModelVisibilitySettings component
- Fix critical regression where model visibility settings were inaccessible
* fix: add missing React hook imports in settings route
* test: remove obsolete tests for removed controller APIs
---------
Co-authored-by: Draculabo <[email protected]>