Commit Graph

80 Commits

Author SHA1 Message Date
diegosouzapw
c1f363fde2 fix(desktop-ui): improve macOS sidebar layout (PR #1001) 2026-04-07 23:28:50 -03:00
Randi
eb704d6420 feat: detailed token tracking in call logs + fix Anthropic input undercount (#1017)
Fixes critical Anthropic streaming input token undercount + adds detailed token tracking with DB migration 018. Includes 18 new unit tests. Integrated into release/v3.5.4.
2026-04-07 17:26:46 -03:00
diegosouzapw
592ca9b5c4 fix: remove hardcoded localhost default arg from GET /api/keys, unify coverage to single coverage/ dir, fix test to pass explicit Request
- Remove `new Request('http://localhost/api/keys')` default arg from GET handler in src/app/api/keys/route.ts (line 26)
- Fix api-key-reveal-route.test.mjs to pass explicit Request instead of calling GET() with no args
- Add --output-dir coverage to all c8 scripts in package.json
- Add coverage.reportsDirectory: 'coverage' to vitest.config.ts and vitest.mcp.config.ts
- Fix CHANGELOG.md structure (# Changelog + [Unreleased] to top)
- Remove 30+ stale coverage-* directories from project root
- Coverage: Statements 78.76% | Branches 72.75% | Functions 80.93% | Lines 78.76% (all thresholds passed)
2026-04-05 23:21:08 -03:00
diegosouzapw
d46e3f07c3 chore(release): v3.4.8 — security compliance and fix algorithms 2026-04-03 00:15:35 -03:00
R.D.
bcc374eb31 fix claude oauth and cc-compatible regressions 2026-04-02 20:54:19 -04:00
carmim777
5789c1ae7d feat(qoder): support PAT via qodercli 2026-04-02 01:35:23 -03:00
diegosouzapw
7e5e029559 Merge Pull Request #891
# Conflicts:
#	open-sse/handlers/chatCore.ts
2026-04-01 18:05:44 -03:00
R.D.
190f02a939 feat: add hidden Claude Code compatible provider 2026-04-01 04:35:16 -04:00
diegosouzapw
fe77e05aff Merge PR #880 coder/log-rotation-clean-followup into release/v3.4.2 2026-04-01 02:18:38 -03:00
R.D.
e00a95bf02 Refine pipeline logging and add retention caps 2026-03-31 20:53:25 -04:00
oyi77
47cb9e8e44 feat(sidebar): wire whitelabeling settings to sidebar
- Add state for custom app name and logo
- Fetch whitelabeling settings from /api/settings
- Listen for whitelabeling changes via settings event
- Display custom app name when set
- Display custom logo (Base64 or URL) when set
- Fall back to default OmniRoute logo and name
2026-04-01 03:44:54 +07:00
Diego Rodrigues de Sa e Souza
70a4d38d04 Release v3.4.0 (Integration) (#861)
* test(settings): add unit tests for debugMode and hiddenSidebarItems

Tests cover:
- PATCH debugMode=true/false
- PATCH hiddenSidebarItems with array values
- Combined updates with both fields

* test(e2e): add Playwright tests for settings toggles

Tests cover:
- Debug mode toggle on/off
- Sidebar visibility toggle
- Settings persistence after page reload

* fix(tests): address code review issues

- Unit tests: fix async/await for getSettings, use direct db functions
- E2E tests: remove conditional logic, use Playwright auto-waiting assertions

* feat(logging): unify request log retention and artifacts

* docs: add dashboard settings toggles to CONTRIBUTING

Add section documenting:
- Debug Mode toggle (Settings → Advanced)
- Sidebar Visibility toggle (Settings → General)

* fix(cache): only inject prompt_cache_key for supported providers

Only inject prompt_cache_key for providers that support prompt caching
(Claude, Anthropic, ZAI, Qwen, DeepSeek). This fixes issue #848 where
NVIDIA API rejected the parameter.

* fix(model-sync): log only channel-level model changes

* feat(providers): add 4 free models to opencode-zen

* feat(providers): add explicit contextLength for opencode-zen free models

* feat(providers): add contextLength for all opencode-zen models

* feat: Improve the Chinese translation

* fix: preserve client cache_control for all Claude-protocol providers

Previously, the cache control preservation logic only recognized a
hardcoded list of providers (claude, anthropic, zai, qwen, deepseek).
This caused OmniRoute to inject its own cache_control markers for
Claude-protocol providers not in that list (bailian-coding-plan, glm,
minimax, minimax-cn, etc.), overwriting the client's cache markers.

The fix checks both:
1. Known caching providers list (existing behavior)
2. Whether targetFormat === 'claude' (all Claude-protocol providers)

This ensures all Claude-compatible providers properly preserve client
cache_control headers when appropriate (Claude Code client, deterministic
routing, etc.).

Also removes unused CacheStatsCard from settings/components (duplicate
of the one in cache/ page).

Fixes cache token calculation for GLM, Minimax, and other Claude-compatible providers.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix: pure passthrough for Claude→Claude when cache_control preserved

The Claude passthrough path round-trips through OpenAI format
(claude→openai→claude) for structural normalization. This strips
cache_control markers from every content block since OpenAI format
has no equivalent, causing ~42k cache creation tokens per request
with zero cache reads.

When preserveCacheControl is true (Claude Code client, "always"
setting, or deterministic combo), skip the round-trip entirely and
forward the body as-is. Claude Code sends well-formed Messages API
payloads — the normalization was only needed for non-Code clients.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix: restore CacheStatsCard — was not a duplicate

The first commit incorrectly deleted CacheStatsCard from
settings/components/ as a "duplicate". It's the only copy — both
settings/page.tsx and cache/page.tsx import from this location.

Restored the i18n-ized version from main.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(429): parse long quota reset times from error body

- Parse XhYmZs format from antigravity error messages (e.g., 27h41m36s)
- Dynamic retry-after threshold (60s default) instead of hardcoded 10s
- Add parseRetryFromErrorText() in accountFallback.ts for body parsing
- Fix 403 'verify your account' to trigger permanent deactivation
- Add keyword matching for 'quota will reset', 'exhausted capacity'
- Add unit tests for retry parsing and keyword matching

Fixes #858 (Antigravity 429 handling)
Fixes #832 (Qwen quota 429 - same underlying bug)

* chore: bump version to v3.4.0-dev

* fix(migrations): rename 013 to 014 to avoid collision with v3.3.11

* chore(docs): update CHANGELOG for v3.4.0 integrations

* fix: Claude token refresh, Antigravity quota, and 429 rate-limit handling

- Fix Claude OAuth token refresh to use form-urlencoded format (standard OAuth2)
- Add anthropic-beta header required by Claude OAuth API
- Switch Antigravity quota to use retrieveUserQuota API (same as Gemini CLI)
- Parse quota reset time for all providers (not just Antigravity)
- Add quota reset keywords to error classifier
- Cap maximum retry time at 24 hours to prevent infinite wait

Closes #836, #857, #858, #832

* fix(dashboard): resolve /dashboard/limits hanging UI with 70+ accounts via chunk parallelization (#784)

---------

Co-authored-by: oyi77 <oyi77@users.noreply.github.com>
Co-authored-by: R.D. <rogerproself@gmail.com>
Co-authored-by: kang-heewon <heewon.dev@gmail.com>
Co-authored-by: gmw <rorschach1167@qq.com>
Co-authored-by: tombii <github@tombii.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: diegosouzapw <diegosouzapw@users.noreply.github.com>
2026-03-31 10:22:52 -03:00
diegosouzapw
afc0bc9323 fix: resolve CLI detection regression and model catalog tests 2026-03-31 07:57:43 -03:00
Diego Rodrigues de Sa e Souza
6f9fec658f chore(release): v3.3.10 — merge Analytics and SQLite fixes (#849)
Co-authored-by: diegosouzapw <diegosouzapw@users.noreply.github.com>
2026-03-31 00:15:20 -03:00
Owen
9227964cb6 feat(analytics): add subscription utilization analytics (#847)
- Add quota_snapshots table for time-series quota tracking
- Add QuotaSnapshot DB module with CRUD + cleanup (6h gate)
- Add snapshot save hook in quotaCache.setQuotaCache()
- Add Provider Utilization API: GET /api/usage/utilization
- Add Combo Health API: GET /api/usage/combo-health
- Add ProviderUtilizationTab with recharts LineChart
- Add ComboHealthTab with quota/skew/performance metrics
- Add TimeRangeSelector component (1h/24h/7d/30d)
- Integrate tabs into /dashboard/analytics
- Add unit tests for quotaSnapshots module
- Add E2E tests for analytics tabs
- Add i18n keys for 33 languages
2026-03-31 00:12:27 -03:00
diegosouzapw
23e47a74ee Merge remote main 2026-03-30 20:48:25 -03:00
diegosouzapw
28123355b4 Merge branch 'feat/issue-660-qoder' into main
# Conflicts:
#	docs/i18n/ar/README.md
#	docs/i18n/bg/README.md
#	docs/i18n/da/README.md
#	docs/i18n/de/README.md
#	docs/i18n/es/README.md
#	docs/i18n/fi/README.md
#	docs/i18n/fr/README.md
#	docs/i18n/he/README.md
#	docs/i18n/hu/README.md
#	docs/i18n/id/README.md
#	docs/i18n/in/README.md
#	docs/i18n/it/README.md
#	docs/i18n/ja/README.md
#	docs/i18n/ko/README.md
#	docs/i18n/ms/README.md
#	docs/i18n/nl/README.md
#	docs/i18n/no/README.md
#	docs/i18n/phi/README.md
#	docs/i18n/pl/README.md
#	docs/i18n/pt-BR/README.md
#	docs/i18n/pt/README.md
#	docs/i18n/ro/README.md
#	docs/i18n/ru/README.md
#	docs/i18n/sk/README.md
#	docs/i18n/sv/README.md
#	docs/i18n/th/README.md
#	docs/i18n/uk-UA/README.md
#	docs/i18n/vi/README.md
#	docs/i18n/zh-CN/README.md
2026-03-30 20:39:31 -03:00
oyi77
a315ab29bc fix(debug/sidebar): make debug toggle control debug section visibility and fix sidebar hidden items tracking
- Sync debugMode with showDebug in Sidebar (was using enableRequestLogs env var)
- Only render debug-section sidebar toggles in AppearanceTab when debugMode=true
- Sidebar filters debug-section items based on debugMode (was already correct)
- Debug toggle now triggers omniroute:settings-updated event for instant sidebar update
EOF
2026-03-31 04:50:50 +07:00
diegosouzapw
a864258cb8 feat(ui): integrate FSM, adaptive routing, and provider diversity 2026-03-30 12:58:45 -03:00
diegosouzapw
f810b13bca fix: complete bugfixes for UI, OAuth fallbacks, cliRuntime Windows constraints and Codex non-streaming integration 2026-03-30 11:01:55 -03:00
diegosouzapw
5ad687c6d8 fix(ui/ci): use ProviderIcon for Provider header breadcrumbs and add permissions to electron-release.yml (#745, #761)
- Use ProviderIcon for internal .png paths solving SVG provider 404 images (#745).
- Add id-token: write and packages: write permissions to .github/workflows/electron-release.yml to fix permissions denied failure when calling the reusable workflow npm-publish.yml (#761).
- Fix tests and ESM resolution for autoUpdate.ts override logic.
2026-03-30 07:38:30 -03:00
diegosouzapw
d69e7ec850 chore(release): v3.3.3 — Core UI bugfixes and AutoUpdate repairs 2026-03-29 21:18:07 -03:00
Randi
fcc48cc738 Add full sidebar visibility controls (#739) 2026-03-29 04:30:08 -03:00
diegosouzapw
a5393a3ec4 feat: migrate iFlow provider to Qoder AI (#660) 2026-03-28 23:35:59 -03:00
diegosouzapw
11a8adc71c Merge branch 'feat/issue-659-mobile-ui' 2026-03-28 23:12:26 -03:00
R.D.
04de492019 fix: add four-stage request log payloads 2026-03-28 22:09:27 -03:00
diegosouzapw
94a00cb6d6 feat: improve dashboard layout for smaller screens (#659) 2026-03-28 21:53:07 -03:00
Paijo
e6f0a780b7 feat(dashboard): add Cache Management page with stats, hit rate, and targeted invalidation (#701)
Adds a new /dashboard/cache page that surfaces the existing but UI-less
semantic cache infrastructure.

Changes:
- New page: src/app/(dashboard)/dashboard/cache/page.tsx
  - Live stats: memory entries, DB entries, cache hits, tokens saved
  - Hit rate progress bar with color coding (green/yellow/red)
  - Hits/Misses/Total breakdown
  - Idempotency layer stats (active dedup keys + window)
  - Cache behavior info panel
  - Clear All button
  - Auto-refresh every 10s
- Enhanced API: src/app/api/cache/route.ts
  - DELETE ?model=<name> — invalidate by model
  - DELETE ?signature=<hex> — invalidate single entry
  - DELETE ?staleMs=<ms> — invalidate entries older than N ms
  - DELETE (no params) — clear all (existing behavior)
- Sidebar: added Cache nav item (icon: cached)
- i18n: added cache + sidebar.cache keys for all 31 supported locales

No new dependencies. All functionality builds on existing semanticCache.ts,
cacheLayer.ts, and idempotencyLayer.ts modules.

Co-authored-by: oyi77 <oyi77@users.noreply.github.com>
2026-03-28 20:39:20 -03:00
diegosouzapw
5907296d36 fix: proxy UI bugs, connection tag grouping, and function_call prefix stripping
## Proxy UI Bug Fixes
- fix: proxy badge on connection cards now uses resolveProxyForConnection()
  per-connection (covers registry + config-file assignments)
- fix: Test Connection button now works in 'saved' proxy mode by resolving
  proxy config from savedProxies list
- fix: ProxyConfigModal now calls onClose() after save/clear (fixes UI freeze)
- fix: ProxyRegistryManager loads usage eagerly on mount with deduplication
  by scope+scopeId to prevent double-counting; adds per-row Test button

## Connection Tag Grouping (new feature)
- feat: add Tag/Group field to EditConnectionModal (stored in
  providerSpecificData.tag, no DB schema change)
- feat: connections list groups by tag with visual dividers when any account
  has a tag; untagged accounts appear first without header

## Post-merge fix from PR #607 review
- fix: function_call blocks in translateNonStreamingResponse now also strip
  Claude OAuth proxy_ prefix via toolNameMap (kilo-code-bot #607 warning)
  Affects OpenAI Responses API format path — tool_use was fixed in PR #607
  but function_call was missed
2026-03-25 08:54:46 -03:00
diegosouzapw
3218563f32 chore: merge PRs #581, #582 + local improvements for rc16
Merged PRs:
- #582 — model prefix stripping option (closes #568)
- #581 — npm publish workflow fix (refs #579)

Local changes:
- Restored stashed i18n, CLI tools, and maintenance banner updates
- 926 tests passing
2026-03-24 13:32:05 -03:00
diegosouzapw
fe033cd0b3 fix: add SVG fallback to ProviderIcon component
ProviderIcon now tries: Lobehub → PNG → SVG → GenericIcon.
This resolves 11 providers that only have SVG icons
(comfyui, sdwebui, vertex, cartesia, zai, synthetic,
opencode-go/zen, puter, apikey, oauth).
2026-03-24 07:52:07 -03:00
diegosouzapw
5dc3fd2ec0 feat: per-model combo routing support (#563)
Add model-pattern → combo mapping feature that automatically routes requests
to specific combos based on model name patterns (glob matching).

Implementation:
- New migration 010: model_combo_mappings table with pattern, combo_id, priority
- DB module with CRUD + resolveComboForModel() using glob-to-regex matching
- getComboForModel() in model.ts: augments getCombo() with pattern fallback
- chat.ts: replaced getCombo() → getComboForModel() at routing decision point
- API endpoints: GET/POST /api/model-combo-mappings, GET/PUT/DELETE by [id]
- ModelRoutingSection.tsx: dashboard UI with inline add/edit/toggle/delete
- Integrated into Combos page
- 15 new unit tests (glob matching, priority ordering, disabled filtering)
- Full test suite: 923/923 pass

Examples:
  claude-sonnet* → code-combo
  claude-*-opus* → frontier-combo
  gpt-4o*       → openai-combo
  gemini-*      → google-combo

Resolves: #563
2026-03-23 20:36:00 -03:00
diegosouzapw
18258b9b0d fix: merge PR #562 — MCP session management, Claude passthrough, OAuth modal, detectFormat fixes
Cherry-pick from codex/omniroute-fixes-20260324:
- Replace MCP singleton transport with per-session architecture for Streamable HTTP
- Fix Claude passthrough via OpenAI round-trip normalization
- Add detectFormatFromEndpoint() for endpoint-aware format detection
- Support raw code#state in OAuth modal for Claude Code remote auth
- Expose cloudConfigured/cloudUrl/machineId in settings API
- Switch docker-compose.prod.yml target to runner-cli
- Add 3 new tests for round-trip and detectFormat

PR: #562
2026-03-23 19:53:02 -03:00
diegosouzapw
3912734498 fix: cherry-pick PR #542 (light mode contrast) + fix TDZ in cliRuntime.ts
- Add missing CSS theme variables (bg-primary, bg-subtle, text-primary)
- Fix hardcoded dark-mode-only colors with proper dark: variants
- Fix ReferenceError: move validateEnvPath before getExpectedParentPaths
2026-03-23 15:10:19 -03:00
diegosouzapw
c34b3f41bd feat: Add requested model to logs, enhance background task detection, and introduce AI SDK compatibility utilities. 2026-03-23 11:08:14 -03:00
diegosouzapw
0546d06c0a fix(types): cast extracted usage to Record<string,number> in stream.ts to resolve TS property errors
Also fix syntax error in openai-to-claude-strip-empty.test.mjs (tool/assistant messages were incorrectly nested)
2026-03-23 09:21:03 -03:00
diegosouzapw
aa93a3f2e2 feat(3.0.0-rc.3): provider icons, model auto-sync, Gemini OAuth fix
feat(ui): ProviderIcon component with @lobehub/icons + PNG fallback (#529)
  - 130+ providers covered by Lobehub SVG components via LobehubErrorBoundary
  - Falls back to existing /providers/{id}.png, then generic icon
  - Replaces manual img state machine in ProviderCard + ApiKeyProviderCard

feat(scheduler): modelSyncScheduler — 24h model list auto-update (#488)
  - Syncs 16 major providers every 24h (MODEL_SYNC_INTERVAL_HOURS configurable)
  - Wired into POST /api/sync/initialize startup hook

fix(oauth): Gemini CLI — clear error when client_secret missing in Docker (#537)
2026-03-22 15:01:38 -03:00
diegosouzapw
601cc21a44 feat: call log response content, per-model tool call ID, key PATCH & validation (#470) 2026-03-19 08:41:01 -03:00
Diego Rodrigues de Sa e Souza
4f32da57fd Merge pull request #443 from Regis-RCR/feat/search-playground
feat(search): add search playground, search tools, and local rerank routing
2026-03-18 12:09:51 -03:00
Jack Cowey
bd39e01ee1 fix(analytics): localize most active day and weekly labels
Use the active app locale for analytics weekday and date formatting so the dashboard no longer shows hardcoded Portuguese labels.

Made-with: Cursor
2026-03-18 12:17:56 +00:00
Regis
e3ed29aab6 feat(search): add search playground, search tools, and local rerank routing
Search Playground (Phase 1):
- Web Search as 10th endpoint in Playground with isolated SearchPlayground component
- Endpoint selector moved first; Provider/Model/Send hidden when search selected
- Provider dropdown via GET /api/search/providers, formatted results with cache indicator

Search Tools page (Phase 2) at /dashboard/search-tools:
- Split panel: SearchForm (left) with query, provider, filters + ResultsPanel (right)
- Compare Providers: parallel queries with latency, cost, response size, URL overlap
- Rerank Pipeline: model selector from /v1/models, results with position delta
- Search History: last 10 searches from call_logs with replay
- Sidebar entry under Debug section

Backend:
- GET /api/search/providers — list providers with auth guard + SEARCH_CREDENTIAL_FALLBACKS
- GET /api/search/stats — cache stats, provider aggregates, recent searches (auth guard)
- Add local provider_nodes routing for /v1/rerank (oMLX, vLLM support)

Bug fixes (from F-27 PR #432):
- Fix Brave news normalizer: data.results directly, not data.news.results
- Enforce max_results truncation after normalization for all providers
- Fix EndpointPageClient: use /api/search/providers instead of /api/v1/search
- Add isAuthenticated() guards on /api/search/providers and /api/search/stats

Response size metric in results meta bar and compare table.
i18n: 30+ keys in search namespace (en.json)
2026-03-18 12:43:24 +01:00
diegosouzapw
448c8a29e1 fix(logs): fix light mode contrast in filter buttons and combo badge (#378)
- text-red-400 → text-red-700 dark:text-red-400 (error filter, recording button)
- text-emerald-400 → text-emerald-700 dark:text-emerald-400 (ok filter)
- text-violet-300 → text-violet-700 dark:text-violet-300 (combo filter)
- combo row badge: violet-700 → violet-800 dark:violet-300, stronger border

Fixes #378
2026-03-17 16:46:27 -03:00
rexname
04b50329fc fix(proxy): address PR review findings for auth, credentials, and health stats 2026-03-17 16:58:44 +07:00
rexname
8091b6b508 feat: implement proxy registry, management APIs, docs, and test hardening 2026-03-17 13:05:27 +07:00
diegosouzapw
44478c36a3 chore(release): v2.6.0 — issue resolution sprint (#390 #340 #344 #377 #378 #337) 2026-03-15 19:15:38 -03:00
diegosouzapw
91015b6499 fix(media,auth,oauth): hide unconfigured local providers, improve round-robin, fix OAuth popup (#390 #340 #344) 2026-03-15 18:48:40 -03:00
diegosouzapw
75a6d850fc chore: release v2.4.3
- fix: Codex/GitHub limits page HTTP 500 → graceful 401/403 messages
- fix: MaintenanceBanner false-positive on page load (stale closure)
- fix: add title tooltips to edit/delete buttons in ConnectionCard
- feat: add fill-first and p2c routing strategies to combo picker
- feat: Free Stack template pre-fills 7 free provider models
- feat: combo create/edit modal wider (max-w-4xl)
2026-03-14 12:49:36 -03:00
Diego Rodrigues de Sa e Souza
eaddb6f0fa feat: improvements from 9router analysis (T01/T08-T13) (#351)
* fix: tool description null sanitization, clipboard HTTP fallback fixes

T10 - Sanitize tool.description null in claude-to-openai translator
- claude-to-openai.ts: tool.description defaults to empty string when null/undefined
- claude-to-openai.ts: filter out tools with empty/missing names
- Prevents 400 validation errors on providers like NVIDIA NIM (issue #276)

T11 - Fix copy buttons to work on HTTP/non-HTTPS deployments
- Add src/shared/utils/clipboard.ts with HTTPS+HTTP (execCommand) dual fallback
- Migrate useCopyToClipboard.ts to use shared utility
- Migrate ConsoleLogViewer.tsx, RequestLoggerV2.tsx to shared utility
- Migrate HomePageClient.tsx, endpoint/page.tsx, GetStarted.tsx
- Migrate DefaultToolCard.tsx to shared utility
- Fixes copy buttons when OmniRoute runs behind HTTP proxy (issue #296)

T02 - Verified SSE [DONE] sentinel handling already correct
- sseParser.ts filters [DONE] on line 13 (no change needed)
- stream.ts uses doneSent flag to prevent duplicate sentinel
- bypassHandler.ts correctly separates streaming/non-streaming responses

Issue triage comments posted to #340, #341, #344

* feat: DB read cache + Accept header stream negotiation (T09/T01)

T09 - In-memory TTL cache for hot DB read paths
- Add src/lib/db/readCache.ts with TTL cache (5s settings/connections, 30s pricing)
- Eliminates redundant SQLite reads on concurrent requests
- Integrate invalidation in settings.ts updateSettings() and updatePricing()
- Integrate invalidation in providers.ts create/update/delete operations
- Export getCachedSettings, getCachedPricing, getCachedProviderConnections,
  invalidateDbCache via localDb.ts for consumer migration
- Cache auto-busts on any write, preserving data consistency

T01 - Accept header stream negotiation
- src/sse/handlers/chat.ts: detect Accept: text/event-stream header
- Override body.stream=true when Accept header indicates streaming client
- Enables curl, httpx and SDK clients that use HTTP headers instead of JSON
  body field to trigger streaming responses
- Logs Accept override at DEBUG level for observability

* fix: auto-advance quota window on expiry to prevent stale blocking (T08)

T08 - Quota Window Rolling Auto-Advance
- quotaCache.ts: add windowDurationMs field to QuotaCacheEntry interface
  (optional field that callers can set when they know the window duration)
- Add advancedWindowResetAt() helper: if entry.nextResetAt is in the past,
  eagerly returns { exhausted: false } so requests are unblocked immediately
- isAccountQuotaExhausted() now uses advancedWindowResetAt() instead of
  the previous inline date check, and optimistically clears entry.exhausted
  flag to avoid re-checking the same stale entry on the next request

Before: exhausted accounts with an expired resetAt would wait up to 5
minutes for the background refresh before accepting new requests.
After:  the first request after resetAt passes will be immediately accepted
and will trigger a quota refresh on the next background tick.

* feat: manual OAuth token refresh UI (T12)

T12 - Manual Token Refresh UI
- Add POST /api/providers/[id]/refresh endpoint
  - Validates connection exists and is OAuth type
  - Calls getAccessToken() (same helper used in auto-refresh)
  - Persists new credentials via updateProviderCredentials()
  - Returns { success, expiresAt, refreshedAt } on success

- Update providers/[id]/page.tsx
  - handleRefreshToken() with loading state (refreshingId)
  - Pass onRefreshToken + isRefreshing props to ConnectionRow
  - ConnectionRow: add optional onRefreshToken/isRefreshing props
  - ConnectionRow: tokenMinsLeft state via lazy init (Date.now() in
    getter fn, not in render body - satisfies react-hooks/purity)
  - Token expiry badge: red 'expired' | amber '~Xm' (<30min) | hidden
  - 'Token' button (amber) next to 'Retest' for OAuth connections

- Add en.json i18n: tokenRefreshed, tokenRefreshFailed

* Initial plan

* feat: integrate wildcardRouter into model alias resolution (T13)

T13 - Wildcard Model Routing
- Import resolveWildcardAlias from wildcardRouter.ts into model.ts
- In getModelInfoCore(), after exact alias check fails, try glob wildcard
  alias matching (e.g., 'claude-sonnet-*' alias → 'anthropic/claude-sonnet-4')
- Returns { provider, model, extendedContext, wildcardPattern } on match
- Falls back to MODEL_TO_PROVIDERS lookup and openai default as before

* fix: clipboard cleanup and tool validation

* feat: media page UX + T04 playground uploads + T03 HuggingFace/Vertex AI

Media Page (MediaPageClient.tsx):
- Render images inline (img tags from b64_json or url)
- Show transcription as plain readable text (not raw JSON)
- Amber banner for credential errors with link to /dashboard/providers
- Detect empty transcription result and show credentials hint
- Provider credential hint below selector for non-local providers
- Extended provider/model lists: HuggingFace, Qwen TTS, Inworld, Cartesia, PlayHT, AssemblyAI

T04 - Playground File Uploads (playground/page.tsx):
- Audio file upload panel for transcription endpoint (multipart/form-data)
- Image upload panel for vision models (gpt-4o, claude-3, gemini, pixtral, llava...)
- Auto-detect vision models by name heuristic
- Inject uploaded images as base64 image_url in chat messages
- Inline image rendering for image generation results
- Readable text view for transcription results with copy button
- Preview thumbnails for attached images with individual remove

T03 - HuggingFace + Vertex AI Providers:
- HuggingFace: frontend providers.ts + backend providerRegistry.ts
  Uses HuggingFace Router OpenAI-compatible endpoint
- Vertex AI: frontend providers.ts + backend providerRegistry.ts
  Uses gemini format with generateContent API (urlBuilder fallback)

T07 - API Key Round-Robin: VERIFIED already implemented in auth.ts
  fill-first, round-robin, p2c, random, least-used, cost-optimized strategies

* feat: T05 task-aware routing + fix #302 stream override + fix #73 claude provider fallback

T05 - Task-Aware Smart Routing:
- New open-sse/services/taskAwareRouter.ts:
  Detects 7 task types: coding, creative, analysis, vision, summarization,
  background, chat from system/user message content and images
  Configurable taskModelMap per task type, stats tracking
  applyTaskAwareRouting() integrates with existing chat pipeline
- New src/app/api/settings/task-routing/route.ts:
  GET/PUT/POST API for task routing config + reset-stats + detect action
  Persists config via updateSettings('taskRouting')
- Integration in src/sse/handlers/chat.ts:
  applyTaskAwareRouting() called after policy enforcement, before combo resolve
  Logs task type detection and model overrides

Fix #302 - OpenAI SDK stream=False drops tool_calls:
- src/sse/handlers/chat.ts T01 Accept header negotiation:
  Changed condition from 'body.stream !== true' to 'body.stream === undefined'
  OpenAI Python SDK sends 'Accept: application/json, text/event-stream' in every
  request, even stream=False — the old code was incorrectly forcing stream=true,
  causing tool_calls to be dropped from non-streaming responses

Fix #73 - Claude Haiku routed to OpenAI provider instead of Antigravity:
- open-sse/services/model.ts getModelInfoCore():
  Added heuristic prefix detection before the blind 'openai' fallback:
  claude-* models → antigravity (Anthropic) provider
  gemini-*/gemma-* models → gemini provider
  Closes: #73, partially addresses #302

* fix: token counts 0 (#74), model import dup (#180), model route fallback (#73)

fix #74 - Token counts always 0 for Antigravity/Claude streaming:
- open-sse/utils/usageTracking.ts extractUsage():
  Add handler for 'message_start' SSE event which carries INPUT tokens in
  Antigravity/Claude streaming:
  { type: 'message_start', message: { usage: { input_tokens: N } } }
  This event was completely unhandled, causing ALL input token counts to be
  dropped for every Antigravity/Claude streaming request

fix #180 - Model import shows duplicates with no visual feedback:
- src/shared/components/ModelSelectModal.tsx:
  Added addedModelValues prop (string[]) to receive already-added model values
  Models already in the combo now shown with ✓ indicator + green highlight
  Makes it visually clear which models are already added vs new
- src/app/(dashboard)/dashboard/combos/page.tsx:
  Pass addedModelValues={models.map(m => m.model)} to ModelSelectModal

* Harden clipboard UX and Claude tool normalization (#360)

* Initial plan

* chore: plan updates for clipboard and translator fixes

* fix: clipboard cleanup, copy feedback, and claude tool validation

---------

Co-authored-by: openai-code-agent[bot] <242516109+Codex@users.noreply.github.com>
Co-authored-by: diegosouzapw <diegosouzapw@users.noreply.github.com>

---------

Co-authored-by: diegosouzapw <diegosouzapw@users.noreply.github.com>
Co-authored-by: openai-code-agent[bot] <242516109+Codex@users.noreply.github.com>
2026-03-14 10:59:15 -03:00
diegosouzapw
1c10cfe4bc fix(lint): replace as any with Record<string,unknown> in OAuthModal — passes check:any-budget:t11
Also bump version to 2.3.10
2026-03-12 13:48:30 -03:00
diegosouzapw
82314562e7 fix: OAuthModal [object Object] - extract message from error objects
All 3 throw new Error(data.error) replaced with proper extraction:
  typeof error === object ? error.message : error
Fixes Cline and other OAuth providers showing [object Object] on connection failure
2026-03-12 12:39:42 -03:00