Commit Graph

85 Commits

Author SHA1 Message Date
oyi77
ad676af3f0 fix(cliproxyapi): address remaining Kilo review issues
- Wrap JSON.parse in try/catch in rowToConfig (upstreamProxy.ts)
- Add error logging to empty catch blocks in CliproxyapiToolCard
- Pin Docker image to v6.9.7 instead of :latest
2026-04-02 15:58:52 +07:00
oyi77
8fc97a7f91 feat(cliproxyapi): add DB schema, upstream proxy config & settings UI
Part 1 of CLIProxyAPI integration (#902).

- DB migration for version_manager + upstream_proxy_config tables
- DB modules: versionManager.ts (tool lifecycle CRUD), upstreamProxy.ts (proxy config CRUD + SSRF guard)
- localDb.ts re-exports for new modules
- Provider registration: UPSTREAM_PROXY_PROVIDERS in providers.ts
- Zod validation schemas for version-manager API routes
- Settings UI: CliproxyapiSettingsTab (Advanced tab)
- 47 unit tests for DB modules
2026-04-02 13:27:51 +07:00
R.D.
69bbc0a2a1 flush sqlite wal on graceful shutdown 2026-04-01 20:14:31 -04:00
diegosouzapw
d10e70a77b Merge PR #899: fix(model-sync) into release/v3.4.2 2026-04-01 19:28:59 -03:00
tombii
c214c6c120 refactor(model-sync): move empty-list guard to early return
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-01 23:18:30 +02:00
diegosouzapw
485eb60dde Merge Pull Request #888 2026-04-01 18:05:45 -03:00
tombii
557509ef84 fix(model-sync): skip replace when auto-sync returns empty model list
Prevent auto-sync from wiping manually-imported models when the upstream
/models endpoint fails, times out, or returns an empty list. Added
`allowEmpty` option (default false) to replaceCustomModels — callers that
intentionally clear all models (DELETE ?all=true) pass `allowEmpty: true`.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-01 23:01:30 +02:00
R.D.
aa2027f1b5 fix provider limits sync cadence 2026-04-01 02:24:53 -04:00
diegosouzapw
f4fc0e17da Merge branch 'feat/memory-skill-injection-v2' into release/v3.4.2
# Conflicts:
#	src/app/(dashboard)/dashboard/settings/page.tsx
2026-04-01 02:20:40 -03:00
diegosouzapw
906ad8c7c1 Merge PR #881 feat/cache-page-dynamic-v2 into release/v3.4.2 2026-04-01 02:18:34 -03:00
diegosouzapw
60968a926f fix: implement missing memory and skills api routes, wire MCP tools, fix migration numbers 2026-04-01 00:34:06 -03:00
oyi77
e6e54822f5 feat: add Memory & Skill Injection from Proxy (Network Level)
Implements transparent memory and skill injection at the proxy layer,
enabling AI agents connecting through OmniRoute to automatically inherit
memory and tool capabilities without client-side code changes.

Memory System:
- SQLite-backed memory store with 4 types: factual, episodic, procedural, semantic
- Token budget retrieval with configurable max tokens (default 2000)
- Memory injection into chat requests (system message + message prefix)
- Memory fact extraction from responses
- Dashboard page: /dashboard/memory
- MCP tools: omniroute_memory_search, omniroute_memory_add, omniroute_memory_clear

Skills System:
- Skill registry with semver resolution (^, ~, >=, etc.)
- Docker sandbox runner with resource constraints (CPU 100ms, RAM 256MB)
- Skill executor with timeout handling
- Built-in skills: file_read, file_write, http_request, web_search, eval_code, execute_command
- Skill schema injection for OpenAI, Claude, Gemini formats
- Tool call interception and execution
- Dashboard page: /dashboard/skills
- MCP tools: omniroute_skills_list, omniroute_skills_enable, omniroute_skills_execute

Advanced Features:
- Browser automation skill (Playwright-based)
- A2A memory-aware routing skill
- Hybrid execution mode (direct/sandbox/auto-upgrade)
- Custom skill registration API
- Integration tests
- Memory caching layer
- Memory summarization
- Performance benchmarks

Resolves: GitHub Issue #812
2026-04-01 09:26:37 +07:00
oyi77
3f7765fdc8 feat(cache): implement dynamic cache components with TDD
- Add MemoryCards, CachePerformance, CacheTrends, IdempotencyLayer components
- Add loading states, error handling, empty state messages
- Add auth guard to /api/cache/stats endpoint (returns 401 unauthenticated)
- Add idempotencyWindowMs to settings (configurable via UI)
- Update getIdempotencyStats() to read window from settings
- Add vitest config for component testing
- Add TDD tests for all 4 components (30 tests passing)

Wave 1-3 complete. Tests pass, build passes.
2026-04-01 08:45:39 +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
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
Randi
cf6056cede Add env flag to disable automatic SQLite backups (#846)
* feat(db): allow disabling sqlite auto backups

* chore(db): rename sqlite auto backup env flag
2026-03-31 00:12:23 -03:00
oyi77
5437d691b5 fix(cache): address code review issues
- Add authentication to /api/cache/entries (GET and DELETE)
- Add authentication to /api/cache (GET and DELETE)
- Validate trendHours: clamp to 1-720 range
- Fix estimatedCostSaved bug: use calculated value instead of hardcoded 0
2026-03-31 04:50:50 +07:00
diegosouzapw
76e135077b Resolve merge conflicts with main natively built Prompt Cache UI 2026-03-30 18:20:19 -03:00
oyi77
d043e7a242 feat(cache): fix cache page to display prompt cache metrics and trend data
Closes #813
2026-03-30 17:32:45 -03:00
tombii
c6eadc504b fix(usage): include cache tokens in input token counts
- Fix getLoggedInputTokens to return full prompt_tokens (input + cache_read + cache_creation)
- Fix usageExtractor for non-streaming Claude responses to calculate total correctly
- Add formatUsageLog helper to show CR=<cache_read> in logs
- Add migration 012 to fix historical token counts in usage_history
- Move prompt cache metrics from Settings to /dashboard/cache page

Per Claude API docs:
Total input tokens = input_tokens + cache_creation_input_tokens + cache_read_input_tokens

Fixes issue where totalInputTokens (71k) was less than totalCacheCreationTokens (1.35M).

Tested:
- All 1134 unit tests pass
- Cache metrics API returns correct totals
- Migration is idempotent and tracked in _omniroute_migrations
- Logs show cache read tokens: 'in=6055 | out=211 | CR=22399'

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-30 19:24:26 +02:00
tombii
319018f055 test: fix cache metrics tests with usage_history table
- Add usage_history table creation in test setup
- Simplify byStrategy query to avoid non-existent combo_strategy column
- Update test assertions to work with existing test data
2026-03-29 16:05:32 +02:00
tombii
26f7b36ce4 feat: add cache control settings and token-based metrics
Settings:
- Add `alwaysPreserveClientCache` setting with modes: auto/always/never
- UI toggle in Dashboard > Settings > Routing tab
- Auto mode preserves cache_control for Claude Code clients with deterministic routing

Metrics:
- Track prompt cache token usage (input, cached, creation)
- Display cache reuse ratio (cached/input tokens)
- Breakdown by provider and routing strategy
- Shows tokens saved and estimated cost savings

API Endpoints:
- GET /api/settings/cache-metrics - retrieve metrics
- DELETE /api/settings/cache-metrics - reset metrics

Files:
- open-sse/utils/cacheControlPolicy.ts: CacheControlMetrics interface, trackCacheMetrics, updateCacheTokenMetrics
- open-sse/handlers/chatCore.ts: Track cache tokens from provider responses
- src/lib/db/settings.ts: Database functions for metrics persistence
- src/lib/cacheControlSettings.ts: Cached settings accessor
- src/app/(dashboard)/dashboard/settings/components/CacheStatsCard.tsx: Metrics dashboard UI
- tests/unit/*.test.mjs: Unit tests (41 tests pass)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-29 14:37:55 +02:00
Randi
fcc48cc738 Add full sidebar visibility controls (#739) 2026-03-29 04:30:08 -03:00
Randi
7690b364e7 fix detailed log summaries for streamed responses (#734) 2026-03-29 04:30:03 -03:00
R.D.
04de492019 fix: add four-stage request log payloads 2026-03-28 22:09:27 -03:00
diegosouzapw
f380d44697 fix(core): hidden models flag, antigravity streaming, and i18n translation sync (#681, #684, #685) 2026-03-27 16:17:28 -03:00
diegosouzapw
2602cd9ab2 chore(release): v3.0.8 — fix translation failures for OpenAI-format providers (#632) 2026-03-25 23:30:35 -03:00
R.D.
6eda0f4d00 feat: add per-provider auto-sync for model lists
- Add POST /api/providers/[id]/sync-models endpoint that fetches models
  from a provider's /models API and replaces the full custom models list,
  preserving per-model compatibility overrides
- Rewrite modelSyncScheduler to dynamically discover connections with
  autoSync enabled in providerSpecificData instead of a hardcoded list
- Add replaceCustomModels() to db/models.ts for full list replacement
  while preserving existing compat flags
- Log each model sync operation to call_logs for visibility in the
  Logs page
- Add Auto-Sync toggle button next to "Import from /models" in the
  provider detail page UI
- Add en/zh-CN i18n translations for auto-sync strings

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 21:16:09 -04:00
diegosouzapw
d68143e63d Merge PR #575: feat(dashboard,sse,api) — per-model upstream headers, compat PATCH, chat alignment (by @zhangqiang8vip) 2026-03-24 09:46:59 -03:00
zhang-qiang
a8ca88797a feat(dashboard,sse,api): per-model upstream headers, compat PATCH, chat alignment
- Store/sanitize upstreamHeaders; shared forbidden header names (upstreamHeaders.ts)

- chatCore: buildUpstreamHeadersForExecute; T5 recomputes; 401 retry uses translatedBody.model

- Dashboard compat popover + i18n; Zod partialRecord + header value newline guard

- Executors merge upstreamExtraHeaders; sanitize unit tests

- Dev: bootstrap env in run-next, instrumentation-node import, credentialLoader dedupe

Made-with: Cursor
2026-03-24 17:24:11 +08:00
diegosouzapw
80cc7340ac feat: API Endpoints dashboard — interactive catalog, webhooks, OpenAPI viewer
Phase 1: Interactive REST API Catalog
- GET /api/openapi/spec: serves parsed openapi.yaml as JSON catalog
- POST /api/openapi/try: Try It proxy for inline endpoint testing
- Endpoint catalog with tag grouping, search, method badges
- Expand: schemas, auth, curl examples, Try It panel

Phase 2: OpenAPI Spec Viewer
- Spec info header with version, download YAML/JSON, schema browser

Phase 3: Webhooks & Event Subscriptions
- Migration 011: webhooks table
- src/lib/db/webhooks.ts: CRUD + delivery tracking + auto-disable
- src/lib/webhookDispatcher.ts: HMAC-SHA256, retries
- API: CRUD /api/webhooks + test delivery
- Dashboard: add/edit/toggle/test/delete webhook UI

923 tests pass, tsc clean
2026-03-23 22:07:10 -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
92e0f242c7 fix(build): resolve all TypeScript compilation errors and Next.js 15 dynamic route slug conflicts
- Fix Next.js 15 async params in 4 API route handlers (accounts, providers, registered-keys)
- Move providers/[id]/limits → providers/[provider]/limits to resolve slug name conflict
- Add keytar to serverExternalPackages and KNOWN_EXTERNALS in next.config.mjs
- Fix Zod z.record() arity across a2a.ts and issues/report/route.ts
- Fix SearchResponse interface (optional answer property) in SearchTools and ResultsPanel
- Fix ProviderLimits implicit any types in index.tsx and utils.tsx
- Fix better-sqlite3 prepare<T> generic usage in secrets.ts
- Remove duplicate pricing keys (gemini-3-flash-preview)
- Cast analytics result, ApiErrorType import, TaskRoutingConfig type
- Remove rogue app/ duplicate directory from project root

Resolves: #560
2026-03-23 18:23:08 -03:00
diegosouzapw
e47740e02e feat: sub2api T05/T08/T09/T13/T14 + bump to 3.0.0-rc.7 2026-03-22 23:17:52 -03:00
diegosouzapw
7a7f3be0d2 feat(sub2api): implement T01-T15 gap analysis tasks (3.0.0-rc.6)
T01 (P1): requested_model column in call_logs
- Migration 009_requested_model.sql: ALTER TABLE call_logs ADD COLUMN requested_model
- callLogs.ts: INSERT + SELECT updated to include requestedModel field

T02 (P1): Strip empty text blocks from nested tool_result.content
- New stripEmptyTextBlocks() recursive helper in openai-to-claude.ts
- Applied on tool_result content before forwarding to Anthropic
- Prevents 400 'text content blocks must be non-empty' errors

T03 (P1): Parse x-codex-5h-*/x-codex-7d-* headers for precise quota reset
- parseCodexQuotaHeaders() in codex.ts extracts usage/limit/resetAt
- getCodexResetTime() returns furthest-out reset timestamp for safe unblocking

T04 (P1): X-Session-Id header for external sticky routing
- extractExternalSessionId() in sessionManager.ts reads x-session-id,
  x-omniroute-session, session-id headers with 'ext:' prefix to avoid collisions

T06 (P2): account_deactivated permanent expired status on 401
- ACCOUNT_DEACTIVATED_SIGNALS constant + isAccountDeactivated() in accountFallback.ts
- Returns 1-year cooldown (effectively permanent) to prevent retrying dead accounts

T07 (P2): X-Forwarded-For IP validation
- New src/lib/ipUtils.ts with extractClientIp() and getClientIpFromRequest()
- Skips 'unknown'/non-IP entries in X-Forwarded-For chain

T10 (P2): credits_exhausted distinct account status
- CREDITS_EXHAUSTED_SIGNALS + isCreditsExhausted() in accountFallback.ts
- Returns 1h cooldown with creditsExhausted flag, distinct from rate_limit 429

T11 (P1): max reasoning_effort -> budget_tokens: 131072
- EFFORT_BUDGETS and THINKING_LEVEL_MAP updated with max: 131072, xhigh: 131072
- Reverse mapping now returns 'max' for full-budget responses
- Unit test updated to expect 'max' (was 'high')

T12 (P3): Model pricing updates
- MiniMax M2.7 / MiniMax-M2.7 / minimax-m2.7-highspeed pricing added

T15 (P1): Array content normalization for system/tool messages
- normalizeContentToString() helper exported from openai-to-claude.ts
- System messages with array content now correctly collapsed to string
2026-03-22 20:55:35 -03:00
diegosouzapw
95ffc21b60 feat(3.0.0-rc.5): Registered Keys Provisioning API (#464)
Complete implementation of auto-provisioning API:
- DB migration 008: registered_keys, provider_key_limits, account_key_limits
- src/lib/db/registeredKeys.ts: full quota enforcement, idempotency, sha256
  hashing, budget tracking, window auto-reset
- POST /api/v1/registered-keys — issue with quota check
- GET /api/v1/registered-keys — list (masked)
- GET|DELETE /api/v1/registered-keys/[id] — get/revoke
- POST /api/v1/registered-keys/[id]/revoke — explicit revoke
- GET /api/v1/quotas/check — pre-validate without issuing
- GET|PUT /api/v1/providers/[id]/limits — provider limits CRUD
- GET|PUT /api/v1/accounts/[id]/limits — account limits CRUD
- POST /api/v1/issues/report — optional GitHub issue reporting
  (requires GITHUB_ISSUES_REPO + GITHUB_ISSUES_TOKEN env vars)
- Exported all from localDb.ts
2026-03-22 15:33:45 -03:00
zhang-qiang
33b6c58087 fix(compat): store explicit false for per-protocol normalizeToolCallId
The truthy check treated false as falsy and deleted the property, preventing users from explicitly disabling normalization for a specific protocol when the top-level flag was true. Now stores both true and false values, consistent with preserveOpenAIDeveloperRole handling.

Made-with: Cursor
2026-03-21 16:38:46 +08:00
zhang-qiang
7ac1d4621b Merge remote-tracking branch 'upstream/main' into feat/zws-v6 2026-03-21 16:32:57 +08:00
zhang-qiang
a2d7cbe8fe feat(compat): per-protocol model compatibility config (V5)
Add per-protocol compatibility options (compatByProtocol) allowing users to configure normalizeToolCallId and preserveOpenAIDeveloperRole per client request protocol (OpenAI Chat, Responses API, Anthropic Messages) instead of globally. Includes frontend Map lookup optimization, type safety improvements, and client-safe constant extraction.

Made-with: Cursor
2026-03-21 15:23:42 +08:00
diegosouzapw
0a5b005ce5 fix: resolve multiple issues (#493, #490, #452)
- #493: Fix custom provider model naming — removed incorrect prefix
  stripping in DefaultExecutor.transformRequest() that broke org-scoped
  model IDs like 'zai-org/GLM-5-FP8'

- #490: Enable context cache protection for streaming responses using
  TransformStream to inject omniModel tag as final SSE content delta
  before [DONE] marker

- #452: Add per-API-key request-count limits (max_requests_per_day,
  max_requests_per_minute) with in-memory sliding window counter,
  schema auto-migration, and Check 5 in enforceApiKeyPolicy()
2026-03-20 19:26:21 -03:00
zhang-qiang
aae2399631 fix(perf): resolve HMR singleton leaks, Edge warnings, and test stability
- Use globalThis singleton guards for DB connection, HealthCheck timers, console interceptor, and graceful shutdown to survive Webpack HMR re-evaluation (fixes 485+ leaked DB connections per session)

- Split instrumentation.ts into instrumentation-node.ts with computed import path to prevent Turbopack Edge bundler from tracing Node.js modules (eliminates 10+ spurious warnings per hot compile)

- Parallelize startup imports in instrumentation-node.ts (3 batch Promise.all instead of 9 serial awaits)

- Add OMNIROUTE_USE_TURBOPACK=1 env switch in run-next.mjs (default behavior unchanged)

- Replace node:crypto with crypto in proxies.ts and errorResponse.ts to fix UnhandledSchemeError

- Add unlinkFileWithRetry with EBUSY/EPERM retry for Windows file handle timing in backup restore

- Fix pre-restore backup to await completion before closing DB

- Fix bootstrap-env, domain-persistence, and fixes-p1 test stability on Windows

Made-with: Cursor
2026-03-21 00:50:07 +08:00
zhang-qiang
1a099ea2f2 feat(zws-v2): model compat, provider-models hardening, provider page types
- roleNormalizer/translator: ZWS v2 role handling and comments

- models + schemas: compat overrides, nullable preserveOpenAIDeveloperRole

- provider-models API: generic GET 500; compatOnly validates known provider

- providers [id] page: typed props; minimal saveModelCompatFlags PATCH

Made-with: Cursor
2026-03-20 23:03:52 +08:00
zhang-qiang
13c45807ef feat: protocol-scoped model compat (V3)
- compatByProtocol per openai/openai-responses/claude

- getters take sourceFormat; chatCore passes it

- UI: protocol selector in compat popover, dark mode select

- shared/constants/modelCompat for client-safe import (fix node:crypto build)

- ZWS_README_V3.md

Made-with: Cursor
2026-03-20 22:06:03 +08:00
zhang-qiang
a7fe369ea0 fix: resolve role param error for Responses API + MiniMax (developer→system)
- Add preserveDeveloperRole option and model compat override

- Normalize developer→system in roleNormalizer when not preserving

- Translator runs normalizeRoles for Responses API with option

- UI: ModelCompatPopover with do not preserve developer toggle

- Add ZWS_README_V2 documenting cause and fix

Made-with: Cursor
2026-03-20 21:06:10 +08: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
Regis
564e983c68 feat(search): add unified web search routing with 5 providers
Add POST /v1/search — a unified search endpoint routing queries across
5 providers (Serper, Brave, Perplexity Search, Exa, Tavily) with
automatic failover, in-memory caching, and request coalescing.

No open-source AI gateway offers unified search routing. This chains
free tiers for 5,500+ searches/month with zero downtime.

Providers: Serper ($0.001/q, 2500/mo free), Brave ($0.005/q, 1000/mo),
Perplexity Search ($0.005/q), Exa ($0.007/q, 1000/mo), Tavily
($0.008/q, 1000/mo). Auto-select picks cheapest with credentials.

Architecture follows existing patterns:
- searchRegistry.ts (same as embeddingRegistry.ts)
- search.ts handler (same as embeddings.ts)
- route.ts (same as /v1/embeddings/route.ts)
- searchCache.ts (bounded TTL cache + request coalescing)

Schema finalized — all future fields defined as optional with safe
defaults. No breaking changes when implementing content extraction,
answer synthesis, or ranking.

Key features:
- Per-provider request builders and response normalizers
- Enriched response: display_url, score, favicon_url, content block,
  metadata, answer block, errors array, upstream_latency_ms metrics
- Cost-sorted auto-select with failover on 429/5xx/timeout
- Credential fallback (perplexity-search reuses perplexity chat key)
- Cache key includes all result-affecting parameters
- max_results clamped to provider limits, sanitized error responses
- Factored validators (validateSearchProvider factory)
- CORS headers on all responses
- Dashboard: Search & Discovery section, search provider template
- DB migration 007: request_type column in call_logs
- 28 unit tests (registry, cache, coalescing, validation)
2026-03-17 18:28:35 +01:00
diegosouzapw
095c84ac16 fix(providerRegistry): remove duplicate claude-haiku-4-5-20251001 from anthropic provider to prevent ambiguous model resolution 2026-03-17 13:10:23 -03:00
diegosouzapw
d56fae0a7b feat: combo agents, auto-update UI, detailed logs, MITM Kiro (#399 #401 #320 #378 #336)
DB Migrations (zero-breaking, ADD COLUMN DEFAULT NULL + new table):
- 005_combo_agent_fields.sql: system_message, tool_filter_regex, context_cache_protection on combos
- 006_detailed_request_logs.sql: ring-buffer table (500 entries) for full pipeline body capture

Features:
- #399 System Message Override + Tool Filter Regex per Combo
  - applyComboAgentMiddleware() injected into handleComboChat/handleRoundRobinCombo
  - Supports both OpenAI and Anthropic tool name formats
- #401 Context Caching Protection (Stateless)
  - injectModelTag() appends <omniModel>provider/model</omniModel> to responses
  - extractPinnedModel() reads tag from history and pins model for session
- #320 Auto-Update via Settings
  - GET /api/system/version — current vs latest npm
  - POST /api/system/update — fire-and-forget npm install + pm2 restart
- #378 Detailed Request Logs
  - saveRequestDetailLog() captures bodies at 4 pipeline stages (opt-in toggle)
  - GET/POST /api/logs/detail — list logs + enable/disable toggle
- #336 MITM Kiro IDE
  - src/mitm/targets/kiro.ts: MitmTarget profile for api.anthropic.com interception
2026-03-17 08:53:41 -03:00
diegosouzapw
e9f31f7394 Merge pull request #429 from contributor branch 2026-03-17 08:14:05 -03:00