mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-09-21 22:32:22 +03:00
Re-land of #12630 by @BillyOutlast (their commits carried with authorship intact), merged via /merge-batch (2026-09-19) on top of the current `release/v3.8.51` tip. **Reconciled before landing — `c2709ea7`.** The re-land had only run its own 78 tests; against the existing suites of the modules it touches it introduced **15 regressions** (all green on the pure tip, reproduced red with the PR). Root causes and fixes: - **Vector layer was on by default** (`semanticCacheConfig.ts` `enabled: true`, bridged from the legacy `semanticCacheEnabled` toggle) and its default embedding client called `http://localhost:13305/v1/embeddings` on every cacheable lookup *and* store — `chat-combo-live-test` ×2 and `issue-agent-route-execution` saw 3 fetches instead of 1. The layer is now **opt-in** via a new `semanticCacheVectorEnabled` setting (default `false`; sub-toggle in the Cache settings tab; `OMNIROUTE_SEMANTIC_CACHE_ENABLED=true` still works). With it off, `chatCore` behaves exactly like the legacy SQLite exact-match cache. - **`X-OmniRoute-Cache` changed from `HIT` to `HIT (exact)`/`HIT (semantic)`** — 5 chat-route/chatCore contract tests. Restored the legacy `HIT` value (similarity hits keep `X-OmniRoute-Cache-Similarity`); `cacheSource: "semantic_similarity"` also fell through `attemptLogging`'s narrowing as `"upstream"` and is now `"semantic"`. - **`normalizeDiscoveredModels` stamped `modelType: "chat"` + `supportedInputTypes: ["text"]` on every model** — kimi/vertex/reasoning-levels/provider-models/model-sync snapshots churned. Chat models keep the tip's exact shape; only non-chat modalities (or explicit `supportedInputTypes`) are stamped. - **`detectModelModality` classified `supportedEndpoints: ["chat","embeddings"]` as embedding** and dropped the model from the chat catalog. An explicit chat endpoint is now authoritative over the embedding/rerank/image heuristics. - Extras found on the way: `chatCore` now passes `provider` to both stores (the manager filters by provider on lookup, so writes without it could never hit); `test-embedding/route.ts` returned `undefined` on invalid payloads (`validateBody()` has no `.response`) → 400. - Tests: `chatcore-semantic-cache.test.ts` restored to the tip's contract; `semantic-cache-no-truncated-writes.test.ts` restored to the tip + the PR's two object-shaped streaming cases appended (with `isTruncatedStreamBody` now delegating to `isTruncatedCompletion` for object bodies — on the tip that guard was a no-op in production); new guard `semantic-cache-vector-layer-opt-in.test.ts`. **Evidence on the merged tree:** the 9 previously-red files + the PR's 7 test files: 270 pass / 0 fail / 2 skipped (Lemonade live, self-skip); `typecheck:core` exit 0; `check:open-sse-typecheck` 0 errors; `check-api-typecheck` only the two inherited errors (`rerankProviderNodes.ts`, `antigravity.ts`); file-size, changelog-integrity, docs-counts, complexity, cognitive-complexity, vitest-exclusions OK; the 5 removed eslint suppressions verified clean. **Owner decisions surfaced by the rework:** the PR wanted the hit type in the `X-OmniRoute-Cache` value — kept the legacy value; a separate header would be the non-breaking way. `modelDiscovery.ts` now considers `record.max_tokens` as an `inputTokenLimit` candidate (on several providers that is the *output* limit) — left as submitted, untested. The contributor's `/review/` `.gitignore` + eslint ignore entries were left as submitted. **Inherited, not from this PR:** the fast-path unit shard reds shared with every PR of this wave (vi locale parity, pack-artifact allowlists, `.env.example` sync, casing, budget fallback), `hard-session-lease-bypass-inventory`, the 5 `no-unused-vars` lint errors, the `omni-version-manager` generated-skill drift. Supersedes #12630.