Commit Graph

3952 Commits

Author SHA1 Message Date
diegosouzapw
00e19f3941 refactor(dashboard): remover card de intro do api-manager e mover botão para Registered Keys 2026-05-16 03:45:57 -03:00
diegosouzapw
dc6e7b00d0 refactor(dashboard): mover toggle/transport para páginas MCP e A2A, limpar abas duplicadas
- /dashboard/mcp: adiciona ServiceToggle (ON/OFF), TransportSelector (stdio/SSE/streamable-http) e DisabledPanel
- /dashboard/a2a: adiciona ServiceToggle (ON/OFF) e DisabledPanel
- /dashboard/endpoint: remove abas MCP, A2A e API Endpoints (agora têm páginas próprias), renderiza só EndpointPageClient
- ApiEndpointsTab: remove sub-aba Webhooks (migrada para /dashboard/webhooks)
2026-05-16 00:37:03 -03:00
diegosouzapw
5c41961351 feat(deepseek-web): full DeepSeek web API executor with PoW solver (#2295)
- DeepSeekWebExecutor with ds_session_id cookie auth
- DeepSeekWebWithAutoRefreshExecutor for session management
- Keccak-based PoW solver (DeepSeekHashV1)
- SSE stream transformation to OpenAI format
- Provider constant and alias (ds-web)
- 23 unit tests + live integration test

Authored-by: Paijo <oyi77@users.noreply.github.com>
2026-05-16 00:27:56 -03:00
diegosouzapw
72afecffeb fix(migrations): resolve version collisions and add batch deletion API (#2294)
- Rename 056_provider_connection_quota_window_thresholds.sql to 057
- Add LEGACY_VERSION_SLOT_MIGRATIONS entries for backward compatibility
- Add deleteBatch/deleteCompletedBatches to batches.ts
- Add DELETE routes for batches (single + bulk)
- Add batch deletion buttons to dashboard
- Broaden dashboard session auth to all client API routes
- Add quota_window_thresholds_json column repair

Authored-by: Markus Hartung <hartmark@users.noreply.github.com>
2026-05-16 00:27:20 -03:00
diegosouzapw
5221a81a75 feat(cc-bridge): config-driven per-provider system-block transform DSL (#2286, closes #2260)
Authored-by: Paijo <oyi77@users.noreply.github.com>
2026-05-16 00:26:25 -03:00
diegosouzapw
8db3fec05a build(deps): bump actions/checkout from 4 to 6 (#2288)
Authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-16 00:25:54 -03:00
diegosouzapw
baefcd06f0 fix: remove implicit API key request caps (#2289)
Removes default daily/weekly/monthly request caps (1K/5K/20K) that were
silently applied to API keys without explicit rate limits, causing
surprise 429s in production aggregator deployments.

Authored-by: josephvoxone <josephvoxone@users.noreply.github.com>
2026-05-16 00:25:35 -03:00
diegosouzapw
b060ebb05b fix(sse): remove dead-code flag leak in claudeCodeToolRemapper (#2290)
Authored-by: thepigdestroyer <thepigdestroyer@users.noreply.github.com>
2026-05-16 00:25:04 -03:00
diegosouzapw
acc9a8780d fix(sse): strip stale content-encoding/length/transfer-encoding from upstream responses (#2291)
Authored-by: Paijo <oyi77@users.noreply.github.com>
2026-05-16 00:24:13 -03:00
diegosouzapw
cfc6be6a12 feat(home): remove Providers Overview card; rename API Manager → API Key Manager
- HomePageClient: remove tier coverage card (free/oauth/apikey breakdown)
- i18n: update apiManager label to "API Key Manager" in 13 locales (EN + placeholders)
2026-05-16 00:11:52 -03:00
Markus Hartung
15d20b7b59 Fix so we have delete on batches instead of files and fix so delete works 2026-05-16 04:57:56 +02:00
Markus Hartung
35cb91c3a9 More permissive cookie auth so /dashboard/batch works with REQUIRE_API_KEY=true 2026-05-16 03:56:13 +02:00
diegosouzapw
da8218856b refactor(dashboard): reestruturação completa do sidebar — 9 seções, sub-grupos visuais, abas → páginas
- sidebarVisibility: novo tipo SidebarItemGroup para sub-grupos; SidebarSectionDefinition usa children[] (flat items + grupos); getSectionItems() helper; 9 seções (home, omni-proxy, analytics, monitoring, devtools, agentic-features, other-features, configuration, help); 8 sub-grupos (Compression Context, Tools, Integrations, Proxy, Costs Parameters, Audit, Batch); novos itens mitm-proxy e 1proxy
- Sidebar: OmniProxy pinada por default na primeira visita; home sem cabeçalho de seção; sub-grupos renderizados como separadores visuais (não colapsáveis); collapsed mode achata grupos corretamente
- Header: getSectionItems para lookup de hrefs; descrições para mitm-proxy, 1proxy
- Páginas convertidas (tabs → conteúdo direto): analytics, costs, audit, batch, logs, system/proxy
- Páginas com redirect: settings/page → /settings/general; settings/pricing → /costs/pricing
- McpAuditTab extraído para componente compartilhado (elimina duplicação audit/page + audit/mcp/page)
- Novas páginas: system/mitm-proxy e system/1proxy (wrappers das abas existentes)
- i18n: 17 novas chaves em 41 locales (sub-grupos, seções renomeadas, novos itens)
- AppearanceTab: usa getSectionItems para visibilidade do sidebar
2026-05-15 22:48:35 -03:00
oyi77
523f674fff feat(deepseek-web): full DeepSeek web API executor with PoW solver
Adds a complete executor for DeepSeek's native web API with:

- Authentication via ds_session_id cookie → Bearer token from /users/current
- Proof-of-Work (DeepSeekHashV1) solver using custom Keccak sponge
- SSE stream response parsing with OpenAI-compatible output
- Web search toggle (search_enabled)
- Deep thinking toggle (thinking_enabled + x-thinking-enabled header)
- File attachment support (ref_file_ids)
- Auto-refresh executor for session management
- 23 unit tests covering all features + live integration test

API flow: /users/current → /chat_session/create → /create_pow_challenge
→ PoW solve → /chat/completion with native DeepSeek body format

Co-Authored-By: OpenClaude (mimo-v2.5-pro) <openclaude@gitlawb.com>
2026-05-16 08:20:59 +07:00
Markus Hartung
7b73ac47da fix(db): add quota_window_thresholds_json to SCHEMA_SQL and in-memory path
- Add missing column to provider_connections CREATE TABLE baseline so
  fresh/in-memory databases include it from the start
- Call ensureProviderConnectionsColumns for in-memory instances to match
  the file-backed path
2026-05-16 01:31:23 +02:00
Mrinal Joshi
07f3b71fc9 style(sse): condense flag-removal NOTE comment (review feedback)
Compresses the explanatory NOTE in claudeCodeToolRemapper.ts from 6 lines
to 4 while keeping the actionable why: the flag has no readers, would
leak into the Anthropic request body causing HTTP 400 (Extra inputs are
not permitted), and the response-side remap is unconditional.

Addresses gemini-code-assist review feedback on PR #2290.
2026-05-16 00:31:03 +01:00
diegosouzapw
a5f33017fd feat(dashboard): accordion sidebar + OmniProxy section + pin behavior
- Rename first section from "Routing" to "OmniProxy" with collapsible header
- Accordion behavior: opening a section closes all non-pinned sections
- Pin button (push_pin) on section headers — visible on hover, always visible when pinned
- Pinned sections stay open regardless of accordion toggle
- Both expanded + pinned state persisted to localStorage
- i18n: add omniProxySection key to all 41 locales
2026-05-15 20:26:45 -03:00
Markus Hartung
8e5c1d9ead fix(migrations): resolve version collisions and add schema repair for quota thresholds 2026-05-16 01:19:39 +02:00
diegosouzapw
a045ddca56 feat(dashboard): tabs → pages, collapsible sidebar, narrower width, tooltips
- Sidebar: w-80 → w-[220px], 12 collapsible sections (default: routing open),
  localStorage persistence, auto-expand active section, styled JS tooltip on mini mode
- sidebarVisibility: restructure from 6 to 12 sections, add 22 new item IDs
- Header: add HEADER_DESCRIPTIONS for all 22 new routes
- i18n: add 23 sidebar + 20 header keys to all 41 locale files
- New pages (Proposal A — tabs become dedicated routes):
  /dashboard/mcp, /dashboard/a2a, /dashboard/api-endpoints
  /dashboard/analytics/{evals,search,utilization,combo-health,compression}
  /dashboard/costs/{budget,pricing}
  /dashboard/batch/files
  /dashboard/logs/{proxy,console,activity}
  /dashboard/audit/mcp
  /dashboard/settings/{general,appearance,ai,security,routing,resilience,advanced}
2026-05-15 19:53:02 -03:00
Mourad Maatoug
1daf15efbd feat(ui): optimistic save + per-op descriptions + per-field hints
Fixes 'first-time save silently dropped' when adding a fresh op with
required-but-empty fields (e.g. replace_regex.pattern). Server returns 400
with field-level zod errors; previously the UI never applied the local
edit because setSettings was gated on res.ok. Now:

- updateSetting applies the patch to local state FIRST (optimistic).
- On 400 it surfaces a 'Server rejected save:' banner per provider listing
  each failing field, with copy telling the user their edit is kept.
- Next valid PATCH clears the banner.

Also: every op kind gets an italic description paragraph above its editor,
and every field gets a plain-English hint underneath explaining what it
does and when to use it. Drift-prone refs softened (no 'v1.7.5 ex-machina'
internal jargon, no false 'server validates regex compiles' claim).

59/59 unit tests green; tsc clean.
2026-05-15 23:57:31 +02:00
diegosouzapw
93526e3d9c refactor(dashboard): remove remaining redundant padding/max-width across all pages
Complete the width standardization pass — DashboardLayout provides p-4 sm:p-6 lg:p-10
and max-w-7xl mx-auto, so page-level containers must not add their own padding or width
constraints.

- analytics/loading, providers/loading, settings/loading: remove p-6 from loading skeletons
- providers/error, settings/error: remove p-6 from error boundary pages
- endpoint/ApiEndpointsTab: remove p-6 max-w-6xl mx-auto (loading + main return); collapse
  redundant wrapper div in loading state
- endpoint/components/A2ADashboard, MCPDashboard: remove p-6 max-w-7xl mx-auto (both states);
  collapse loading wrapper div to single element
- settings/pricing: remove max-w-6xl mx-auto p-6
- system/proxy: remove max-w-6xl mx-auto
2026-05-15 18:47:58 -03:00
Mourad Maatoug
b653cfd160 feat(ui): collapsible provider tiles + ops + move Add provider to top
Reduces vertical footprint of the System-block Transform Pipeline card so
long pipelines (cc-bridge ships 9 ops) do not dominate the Routing tab.

- New Collapsible component (src/shared/components/Collapsible.tsx) used as
  a shared primitive. Open/closed state lives in local component state; does
  NOT persist across reloads (per UX brief: always-collapsed default).
- Each provider tile is now collapsible (closed by default).
- Each pipeline op inside a provider is collapsible (closed by default) —
  click to expand the per-kind editor.
- 'Add provider' Select+Button moved from BOTTOM to TOP of the card with a
  dashed border, so it is the first thing the user sees.
- Trailing controls (Toggle, Button) render as siblings of the toggle button
  (not nested), avoiding invalid <button> inside <button> HTML.

59/59 unit tests green.
2026-05-15 23:47:36 +02:00
Mourad Maatoug
79e19b5466 test(system-transforms): UI ↔ server defaults parity snapshot
Hand-maintained DEFAULT_SYSTEM_TRANSFORMS_CLIENT mirror in RoutingTab.tsx
drifts silently from server DEFAULT_SYSTEM_TRANSFORMS_CONFIG. New test asserts
deepEqual against the JSON-shape of the server export and points at the UI
file in the failure message so contributors update both in the same commit.

23/23 green.
2026-05-15 23:43:06 +02:00
diegosouzapw
b39d0d8861 refactor(dashboard): fix dark theme + two-column layout on agent-skills, standardize page widths
- agent-skills: replace all inline style={{ color: "var(--color-xxx, #fallback)" }} with
  Tailwind semantic classes (text-text-main, text-text-muted, bg-bg-subtle, border-border,
  text-primary, bg-primary/10, bg-emerald-500/10, bg-amber-500/10) — fixes dark mode
- agent-skills: full-width "How to use" card + two-column grid (API Skills | CLI Skills)
  on lg+ screens; remove internal p-6 and max-w-3xl (layout already provides padding/max-w)
- audit, webhooks: remove redundant p-6 + mx-auto max-w-7xl (DashboardLayout already wraps
  content in max-w-7xl with p-4 sm:p-6 lg:p-10)
- memory: remove extra p-6
- agents: remove p-6 + max-w-5xl mx-auto
- cloud-agents: remove p-6 + max-w-6xl mx-auto
- changelog: remove max-w-5xl mx-auto w-full
- health: remove outer p-6 + max-w-6xl mx-auto; strip redundant p-6 from loading/error states
- translator: remove p-4 sm:p-8 (layout provides padding)
- context/caveman, context/rtk, context/combos: remove mx-auto max-w-6xl
2026-05-15 18:31:24 -03:00
diegosouzapw
3975d2c10f feat(dashboard): complete header descriptions for all sidebar pages
- Add header descriptions for 13 remaining pages (agents, cloud-agents, memory,
  skills/omniSkills, agent-skills, translator, playground, search-tools, logs,
  audit, webhooks, health, proxy) across all 41 locale files
- Update HEADER_DESCRIPTIONS map in Header.tsx to cover all 30 sidebar pages
- Remove page-body title block from agent-skills page (cherry-picked from feat/v3.8.0-features)
2026-05-15 17:26:42 -03:00
diegosouzapw
58c2cfccd9 fix(skills): use useCopyToClipboard hook in AgentSkills for HTTP fallback 2026-05-15 17:23:50 -03:00
diegosouzapw
291c1ffaf8 feat(skills): add 5 CLI skills + split AgentSkills / OmniSkills pages
- Add skills/omniroute-cli/SKILL.md — CLI entry point (install, global flags, output formats, env vars)
- Add skills/omniroute-cli-admin/SKILL.md — server lifecycle, setup, doctor, backup, autostart, tunnels
- Add skills/omniroute-cli-providers/SKILL.md — provider connections, keys, OAuth, models, combos, quota
- Add skills/omniroute-cli-cloud/SKILL.md — Codex / Devin / Jules cloud agent task workflow
- Add skills/omniroute-cli-eval/SKILL.md — eval suites, run + watch, scorecard, CI integration
- Update agentSkills.ts: add category field (api | cli), add 5 new CLI skills (18 total)
- Create /dashboard/agent-skills page (AgentSkills) with API + CLI sections and copy-URL buttons
- Remove AI Skills tab from /dashboard/skills (OmniSkills) — now a separate page
- Add agent-skills to sidebar (CLI section) with i18n keys omniSkills + agentSkills
- Update skills/README.md and omniroute/SKILL.md index tables
2026-05-15 17:23:42 -03:00
diegosouzapw
68ca8bf1e9 refactor(dashboard): remove page-body headers, add topology multi-ring, icon+title header
- ProviderTopology: replace single-ring ellipse with multi-ring concentric layout (6 rings)
  - Providers sorted active → error → last-used → rest; compact node design (text-xs, 16px icon)
- Header: derive icon/title from SIDEBAR_SECTIONS auto-mapping, remove breadcrumbs logic
  - Add HEADER_DESCRIPTIONS map for all pages with known descriptions
  - Use sidebar i18n namespace for titles (covers all 42 locales)
- DashboardLayout: remove <Breadcrumbs /> component
- Add header descriptions for 9 new pages (costs, cache, limits, api-manager, batch,
  context-caveman/rtk/combos, changelog) across all 41 locale files
- Remove duplicate page-body title+description from 16 pages: costs, analytics, cache,
  cache/media, context/caveman/rtk/combos, changelog, agents, cloud-agents, skills,
  audit, translator, webhooks, memory, health — preserving action buttons in each
- Rename sidebar "Limits & Quotas" → "Quota Limits" (en.json)
- run-next.mjs: pre-read DATA_DIR from .env before bootstrap (zero-config dev start)
2026-05-15 17:20:48 -03:00
Mrinal Joshi
4f01a8995b fix(sse): strip stale content-encoding/length/transfer-encoding from upstream responses
`fetch()` always transparently decompresses the upstream body before
exposing it via `.text()` or the stream reader, so forwarding the
upstream `content-encoding` header (e.g. `gzip`) to the downstream
OpenAI/Anthropic-compatible client makes the client attempt to gunzip
plain text and fail with `ZlibError: incorrect header check`.

Similarly, `content-length` becomes stale once we transform the response
body (non-stream path repacks via `new Response()`; stream path
re-streams through our SSE heartbeat / shape transforms), and
`transfer-encoding` is owned by the Node/Next runtime, not us.

This patch adds `open-sse/utils/upstreamResponseHeaders.ts` exporting:

- `stripStaleEncodingHeaders(input: Headers)` — returns a new `Headers`
  with content-encoding, content-length, transfer-encoding removed
  (case-insensitive, does not mutate input).
- `filterUpstreamResponseHeaderEntries(entries, extraToStrip)` — same
  semantics for the entries-array path used by the streaming response
  builder, plus user-supplied additional names (case-insensitive).
- `STRIP_UPSTREAM_HEADER_NAMES` — the canonical set, exported for tests.

`open-sse/handlers/chatCore.ts` now uses these helpers in two places:

1. Non-stream path (~L3211): replaces `new Headers(rawResult.response.headers)`
   with `stripStaleEncodingHeaders(...)` so the repacked Response below
   doesn't claim a stale encoding/length.
2. Stream path (~L4371): replaces an inline IIFE+filter that only
   removed `content-type` with `filterUpstreamResponseHeaderEntries(...,
   ["content-type"])` so the stale encoding/length are also stripped
   before we set our own `text/event-stream` content-type.

Both call sites carry a comment explaining the underlying fetch
decompression behavior.

Tests
-----

New `tests/unit/upstream-response-headers-strip.test.ts` adds 10 cases
covering: lowercase strip, mixed-case strip, input non-mutation, empty
input, default-set filter, case-insensitive extraToStrip, empty
extraToStrip preservation, empty entries, mixed-case default names, and
canonical set identity.

Verified locally
----------------

- `npx eslint open-sse/utils/upstreamResponseHeaders.ts open-sse/handlers/chatCore.ts tests/unit/upstream-response-headers-strip.test.ts` — clean.
- `npm run typecheck:core` — clean.
- `node --import tsx/esm --test tests/unit/upstream-response-headers-strip.test.ts tests/unit/upstream-headers-sanitize.test.ts tests/unit/chatcore-sanitization.test.ts tests/unit/chat-route-edge-cases.test.ts tests/unit/chatcore-translation-paths.test.ts tests/unit/chatcore-compression-integration.test.ts` — 95/95 pass.
- Full `npm run test:unit` / `test:coverage` deferred to upstream CI
  (122 test files, exceeds local timeout window).
2026-05-15 20:23:53 +01:00
Mrinal Joshi
fa1d1fe7eb fix(sse): remove dead-code flag leak in claudeCodeToolRemapper
remapToolNamesInRequest() set body._claudeCodeRequiresLowercaseToolNames = true
when a request contained only lowercase tool names. The flag had no readers in
src/ or open-sse/ (verified by repo-wide grep) and leaked into the outgoing
Anthropic /v1/messages payload, causing HTTP 400:

  "_claudeCodeRequiresLowercaseToolNames: Extra inputs are not permitted"

The response-side lowercase remap via remapToolNamesInResponse(text, true) is
unconditional and does not depend on this flag, so removing it is a no-op for
the response path while fixing the request path.

Adds tests/unit/claude-code-tool-remapper-flag-leak.test.ts as a regression
guard with 5 cases covering all-lowercase, all-TitleCase, mixed-case, and a
flag-leak sweep across all input shapes.
2026-05-15 20:13:43 +01:00
Mourad Maatoug
a6af54a047 fix(ui): provider dropdown from AI_PROVIDERS catalog + shared Button for op controls
Caveman-review iteration on commit 4fde71a4:

1. Provider selection uses Select dropdown populated from AI_PROVIDERS
   registry (the canonical provider catalog) instead of free-text Input.
   Filters out providers already configured under systemTransforms.providers.
   Drops PROVIDER_ID_PATTERN regex + newProviderError state — dropdown
   makes invalid input impossible.

2. Per-op move-up / move-down / delete buttons now use the shared Button
   component with material icons (keyboard_arrow_up, keyboard_arrow_down,
   delete) + i18n titles, instead of raw <button> with emoji glyphs.
   Matches the rest of the OmniRoute UI.

3. BUILTIN_PROVIDERS Set was being recreated every render inside the
   component body. Moved to module scope.

i18n: added systemTransformsAddProviderAllConfigured, systemTransformsOpMoveUp,
systemTransformsOpMoveDown, systemTransformsOpDelete. Re-purposed
systemTransformsAddProviderPlaceholder as the dropdown's empty-state label
('Select a provider…').

Tests: 58/58 green (cc-bridge-transforms + system-transforms +
claude-code-compatible-helpers).

Refs PR #2286.
2026-05-15 19:05:50 +02:00
Mourad Maatoug
4fde71a4b1 feat(ui): separate system-block transforms into own Card + add/remove any provider
- System-block transform pipeline is now a dedicated Card (was nested
  subsection inside the CLI Fingerprint Matching Card).
- Any provider ID can be added via the 'Add provider' input at the
  bottom of the transforms Card; the new provider starts with
  enabled=false and an empty pipeline.
- Custom (non-builtin) providers have a delete button to remove them.
- Builtin providers (claude, anthropic-compatible-cc) are protected from
  deletion (removeProvider guard).
- Add systemTransforms i18n keys for the new section title, description,
  add-provider label/placeholder, remove label, empty state.
- The CLI Fingerprint Matching Card is now a clean standalone Card.
2026-05-15 18:54:41 +02:00
Mourad Maatoug
149e901514 fix(ui): Claude tile disablable + strip issue refs + clean provider tile copy
- Remove forced=true lock on Claude tile in CLI Fingerprint Matching —
  all providers now equally toggleable.
- Replace hardcoded GitHub issue link (#2260) and 'no local CLI binary
  required' note in card header with clean i18n-keyed description.
- Remove forcedFingerprintTitle + forcedFingerprintBadge i18n keys
  (now unused).
- Clean provider tile descriptions (PROVIDER_TILE_DISPLAY) to remove
  internal implementation detail language.
- Replace internal-jargon system-transforms footnote with user-facing
  note about idempotency.
2026-05-15 18:51:02 +02:00
Mourad Maatoug
69f0735c7a fix(cc-bridge): use idempotencyKey in prepend/append block ops
applyPrependSystemBlock and applyAppendSystemBlock were not using the
idempotencyKey when set — the old check used op.text as the idempotency
prefix and only examined the first/last block.

Fix: scan ALL existing text blocks; use idempotencyKey as prefix when set,
fall back to op.text (prepend) / exact match (append).
2026-05-15 18:39:21 +02:00
Mourad Maatoug
0f656571d5 refactor(system-transforms): use shared UI primitives + drop dead i18n keys
- Replace raw <input>/<select>/<textarea>/<label> in OpEditor with shared
  Input, Select, Toggle components — matches the pattern used by every
  other settings tab in the app.
- New StringListEditor helper consolidates the three list-of-strings
  forms (needles, prefixes, words) into one consistent component.
- Replace the peer-checkbox custom provider-enable toggle with the
  shared Toggle component (same look as Adaptive Volume, LKGP, etc).
- Replace the raw add-op <select> with shared Select.
- Drop nine unused 'ccBridgeTransforms*' i18n keys left over from the
  Phase 2 v1 UI — current UI uses inline strings under the
  'CLI Fingerprint Matching' card.
- Document why systemTransforms keeps its own looser RequestBody shape
  (legacy ccBridgeTransforms RequestBody is stricter; cast at boundary).
2026-05-15 18:32:02 +02:00
Mourad Maatoug
875c8f77c1 feat(system-transforms): per-op UI editor + claude opt-in default + restore section name
- claude provider enabled:false by default (opt-in; was incorrectly true)
- add OpEditor component: per-op form editor for all 9 DSL kinds
  (add/move-up/move-down/delete via UI buttons, JSON editor collapsed)
- rename card back to 'CLI Fingerprint Matching' per user feedback
- JSON import/export now collapsible under '▸ Import / export JSON'
- tests updated to explicitly enable claude provider where pipeline behavior
  is under test (not the opt-in default)
2026-05-15 18:19:48 +02:00
Diego Rodrigues de Sa e Souza
79d03575ee feat(cli): suporte i18n completo — 42 locales, --lang flag, config lang get/set/list (#2285)
feat(cli): suporte i18n completo — 42 locales, --lang flag, config lang get/set/list

- 42 locale files in bin/cli/locales/ (en + pt-BR fully translated, 29 with common/program, 11 scaffolds)
- --lang <code> global flag for per-execution override
- config lang get/set/list subcommands
- Locale persistence via ~/.omniroute/.env
- Path traversal protection via regex validation in normalize()
- Script generate-locales.mjs for scaffolding new locales
- Unit tests for lang commands + normalization security

Integrated into release/v3.8.0
2026-05-15 13:14:14 -03:00
Mourad Maatoug
4d000f1eb0 fix: strip _claudeCodeRequiresLowercaseToolNames before serialization
The sentinel field set by remapToolNamesInRequest() was being included in
the JSON body sent to Anthropic, which rejects unknown top-level fields
with 400 invalid_request_error. Stripped before JSON.stringify in both
code paths:
- buildAndSignClaudeCodeRequest (CC bridge / anthropic-compatible-cc-*)
- base executor serialization path (native claude/ provider)

Pre-existing bug, not introduced by issue #2260 changes.
2026-05-15 18:07:57 +02:00
Mourad Maatoug
d0d8638a02 refactor(system-transforms): caveman-review cleanup + logging
- Remove dead setWordsForOp function (unused, acknowledged in comment)
- Remove unused obfuscateSensitiveWords import and re-export from systemTransforms
- Increase textarea rows cap from 20→40 for long CC-bridge pipelines (~100 lines JSON)
- Add [SystemTransforms] console.log at both call sites (cc-bridge step 5b + claude native path)

Tests: 58/58 green
2026-05-15 17:57:40 +02:00
diegosouzapw
0d09858526 chore: remove junk files from PR #2283 squash merge
- Remove .playwright-mcp/ debug artifacts (accidentally committed)
- Remove duplicate docs/routing/CLI-TOOLS.md (canonical at docs/reference/)
2026-05-15 12:51:28 -03:00
Paijo
855eeb3d2d feat(claude-web): implement session-based executor with auto-refresh (#2283)
feat(claude-web): implement session-based executor with auto-refresh

Adds ClaudeWebExecutor for Claude.ai web cookie-based access:
- Session cookie auth (sessionKey, cf_clearance, etc.)
- TLS fingerprint spoofing via tls-client-node (Chrome 124)
- Auto-refresh cf_clearance via headless Turnstile solving
- SSE streaming support
- Unit tests for executor + TLS client
- Provider documentation

Integrated into release/v3.8.0

Co-authored-by: oyi77 <oyi77@users.noreply.github.com>
2026-05-15 12:51:07 -03:00
Diego Rodrigues de Sa e Souza
0edf90bb5a feat(skills): add 5 CLI skills + AgentSkills / OmniSkills dashboard pages (#2284)
feat(skills): add 5 CLI skills + AgentSkills / OmniSkills dashboard pages

Integrated into release/v3.8.0
2026-05-15 12:48:54 -03:00
Mourad Maatoug
634b4fe0ce feat(system-transforms): generic per-provider DSL closing OpenWebUI bypass
v2 of the CC bridge body transforms (issue #2260). Generalizes the
single-provider `ccBridgeTransforms` config (commit e3e962db) into a
per-provider registry keyed by OmniRoute provider id, and wires the
native `claude` OAuth path into the same DSL so raw `claude/<model>`
requests no longer bypass the sanitization layer.

Reference: comment 4459544580 reported a 429 on raw `claude/<model>`
from Open WebUI; CC-bridge-only v1 didn't help that path. v2 closes
three gaps named in the comment:

  1. `openwebui` / `open-webui` added to the default obfuscation
     word list (new `obfuscate_words` op kind, configurable).
  2. Native `claude` provider path now runs the per-provider pipeline
     after its existing billing+sentinel prepend (executors/base.ts).
     Its default pipeline is cosmetic only (Open WebUI paragraph
     anchors + identity-prefix drop + ZWJ obfuscation); it deliberately
     omits `inject_billing_header` so it never collides with the native
     prepend.
  3. Open WebUI paragraph anchors (github.com/open-webui/open-webui,
     openwebui.com, docs.openwebui.com) and identity prefix
     ("You are Open WebUI") added to both `claude` and CC bridge
     default pipelines.

API surface:

  - New module: open-sse/services/systemTransforms.ts
    * `SystemTransformsConfig { providers: Record<id, { enabled, pipeline }> }`
    * `TransformOp` extends the base CC bridge op set with
      `obfuscate_words { words[], targets[] }`.
    * `applySystemTransformPipeline(providerId, body, config?)`
      routes to the right per-provider pipeline (with CC bridge prefix
      match so `anthropic-compatible-cc-*` all share one config).
    * `setSystemTransformsConfig` accepts both legacy single-provider
      shape (migrates into providers[anthropic-compatible-cc]) and the
      new per-provider shape (merges with defaults for unset providers).

  - Native claude wedge: executors/base.ts now calls
    `applySystemTransformPipeline(PROVIDER_CLAUDE, tb)` after the
    existing billing+sentinel prepend (line ~789).

  - CC bridge step 5b: claudeCodeCompatible.ts step 5b switched from
    `applyCcBridgeTransformPipeline` (single-config) to
    `applySystemTransformPipeline(PROVIDER_CC_BRIDGE, body)`. The
    underlying ccBridgeTransforms.ts module remains the base executor
    that systemTransforms.ts delegates to for the shared op kinds —
    no rename to keep the diff reviewable, and all 30 base-op tests
    stay green.

  - Settings:
    * Zod schema gains `systemTransforms.providers[*]` with full
      discriminated union over the 9 op kinds (including
      obfuscate_words).
    * Legacy `ccBridgeTransforms` zod field kept for back-compat read;
      runtime now feeds it through `setSystemTransformsConfig` migration
      shim so persisted Phase-2 data keeps working. v2 `systemTransforms`
      wins on conflict (applied last).
    * Runtime settings registry gains `systemTransforms` reload section
      next to legacy `ccBridgeTransforms`.

  - UI rewrite (RoutingTab.tsx): the two standalone cards (CLI
    Fingerprint + CC Bridge Transforms) collapse into one
    "Provider Upstream Compatibility" card. Per-provider tiles render
    the pipeline summary + JSON editor with client-side shape
    validation + Apply / Reset. Copy clarifies that no local Claude
    Code binary is required (the lock badge on the Claude tile means
    the fingerprint is force-applied for OAuth account safety, not
    that the user must install the CLI).

Tests:

  - tests/unit/system-transforms.test.ts (22 new tests covering
    defaults, per-op semantics, ordering, per-provider routing, opt-in
    pass-through, Open WebUI fixture, migration shim, idempotency).
  - tests/unit/cc-bridge-transforms.test.ts (30 base-op tests
    unchanged, still green).
  - tests/unit/claude-code-compatible-{helpers,request}.test.ts and
    8 related claude/cc/executor test files all green (140 tests).

Closes #2260.
2026-05-15 17:36:21 +02:00
diegosouzapw
bb0ec76f24 fix(machineToken): use require() for node-machine-id to survive webpack bundling
The default import + destructuring pattern was being mangled by webpack's
static analysis during Next.js standalone builds, causing 'Cannot destructure
property machineIdSync of undefined' errors in production.

Using require() bypasses webpack's interop wrapper (c.n(...)) and loads the
module's exports directly at runtime.
2026-05-15 12:10:36 -03:00
diegosouzapw
1c949c248b fix(build): add node-machine-id to serverExternalPackages
Prevents webpack from bundling node-machine-id which breaks
destructuring of machineIdSync in standalone mode
2026-05-15 11:38:59 -03:00
diegosouzapw
9a9561f630 fix(build): add next-themes + sql.js deps and mark sql.js as webpack external
- next-themes: required by TierFlowDiagram.tsx (onboarding)
- sql.js: required by CLI runtime sqliteRuntime.mjs
- Add sql.js to serverExternalPackages in next.config.mjs to prevent
  webpack static resolution failures during build
2026-05-15 11:15:45 -03:00
diegosouzapw
0cc6fec85e Merge PR #2280: feat(cli): CLI v4 — Commander.js, 50+ commands, TUI, i18n, plugins (Phases 0-9)
Complete rewrite of the OmniRoute CLI:
- Commander.js-based modular architecture (50+ command files)
- Full i18n support (en + pt-BR, 1222 keys each)
- TUI interactive interface (OAuthFlow, EvalWatch, ProvidersTestAll)
- Plugin system (omniroute-cmd-*)
- OpenAPI codegen (omniroute api <tag> <op>)
- Commands: serve, combo, compression, keys, tunnel, backup, test-provider,
  health, memory, MCP, A2A, oauth, skills, webhooks, usage, cost, eval,
  context-eng, dashboard, doctor, env, files, logs, models, nodes, oneproxy,
  open, openapi, plugin, policy, pricing, providers, quota, registry, repl,
  reset-encrypted-columns, resilience, restart, runtime, sessions, setup,
  simulate, status, stop, stream, sync, tags, telemetry, translator, tray, update
- Code review fixes: C1-C3, I1-I5, M1-M4 applied

# Conflicts:
#	bin/cli/commands/config.mjs
#	bin/omniroute.mjs
#	package-lock.json
#	package.json
2026-05-15 10:50:54 -03:00
backryun
eba07d8918 chore: tidy up deprecated models from windsurf provider (#2279)
Integrated into release/v3.8.0 — removes deprecated Windsurf models and adds gemini-3.1-pro-low to Cascade list
2026-05-15 10:47:39 -03:00
diegosouzapw
f320caa724 fix(cli): code-review-2 — I1/I2/M1/M2
I1 (logs): implementar filtragem runtime das 7 flags registradas mas ignoradas:
  --request-id, --api-key, --combo, --status, --duration-min, --duration-max,
  --export. Filtragem client-side via buildLogFilter(); --export grava jsonl.
I2 (keys): adicionar isServerUp() check + try/catch nos 8 comandos que chamavam
  apiFetch diretamente sem proteção: regenerate/revoke/reveal/usage/policy-show/
  policy-set/expiration-list/rotate. Garante exit code 1 com mensagem amigável
  quando servidor offline.
M1 (tunnel): substituir string hardcoded inglesa em runTunnelStopCommand linha 151
  por t("tunnel.typeRequired").
M2 (logs): substituir "Log stream stopped." e "Log stream error: ..." por t()
  calls; adicionar logs.stopped / logs.streamError / logs.exported a en.json e
  pt-BR.json.
2026-05-15 10:24:30 -03:00
diegosouzapw
5e949276d4 fix(authz/clientApi): fall through to anonymous on invalid bearer when REQUIRE_API_KEY=false (#2257)
There was an asymmetry in the CLIENT_API policy: with REQUIRE_API_KEY
off, a request with no bearer was allowed as anonymous, but a request
with an *invalid* bearer was rejected with 401 "Invalid API key". That
surprises CLI integrations (Codex Desktop auto-config, Hermes Agent)
that ship a stale Bearer in their saved config — they'd see a 401 even
though the operator explicitly opted out of auth.

Fix: when validateApiKey fails and REQUIRE_API_KEY != "true", log a
single warning carrying the masked key id (last-4) and fall through to
anonymous. When REQUIRE_API_KEY is "true", the strict 401 path is
preserved.

The warning preserves observability:
  [clientApiPolicy] invalid bearer presented to /api/v1/responses
    but REQUIRE_API_KEY=false — falling through to anonymous
    (key_id=key_XYZW)

Tests are added in a standalone file because the existing
client-api-policy.test.ts shares a DB-backed setup with a pre-existing
SQLite migration race (5/7 of its tests already failed on baseline).
The new file mocks validateApiKey via a require-resolve interceptor so
the policy's invalid-bearer branch is exercised without touching SQLite.

Reported by @k00shi on the Codex Desktop auto-config path.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-15 10:15:57 -03:00