-
-
Notifications
You must be signed in to change notification settings - Fork 10.4k
feat(providers): filter GitHub combo members against live catalog #12473
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
diegosouzapw
merged 4 commits into
diegosouzapw:release/v3.8.51
from
RaviTharuma:fix/12137-github-live-catalog-filter
Sep 4, 2026
Merged
Changes from all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
99cd70e
feat(providers): filter GitHub combo members against live catalog
RaviTharuma 1119630
fix: address Copilot review on live-catalog filter
RaviTharuma f65ee55
Merge remote-tracking branch 'origin/release/v3.8.51' into fix/12137-…
diegosouzapw 79ca134
fix(sse): extract GitHub live-catalog combo gate from frozen chat.ts
RaviTharuma File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| - **feat(providers):** skip GitHub combo members missing from the live synced catalog, and drop Copilot models that are policy-disabled or hidden from the model picker ([#12473](https://github.com/diegosouzapw/OmniRoute/pull/12473)) — thanks @RaviTharuma |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,71 @@ | ||
| /** | ||
| * GitHub live-catalog combo gate (#12137). | ||
| * | ||
| * Extracted from chat.ts so the frozen handler does not grow. Explicit combo | ||
| * members missing from an authoritative GitHub catalog are skipped; a catalog | ||
| * that is not synced yet fails open (same pattern as providerWildcard). | ||
| * | ||
| * The catalog promise is memoized per request-scope object so combo candidates | ||
| * share one getActiveSyncedCatalog fetch instead of re-hitting the DB. | ||
| */ | ||
| import { | ||
| catalogContainsModel, | ||
| getActiveSyncedCatalog, | ||
| type ActiveSyncedCatalog, | ||
| } from "@/lib/db/models/activeSyncedCatalog"; | ||
|
|
||
| const catalogByScope = new WeakMap<object, Map<string, Promise<ActiveSyncedCatalog>>>(); | ||
|
|
||
| /** Prefix-override guard used by combo pre-check (same as handleSingleModelChat). */ | ||
| export function comboCheckProvider( | ||
| modelString: string, | ||
| modelInfo: { provider?: string }, | ||
| providerId?: string | null | ||
| ): string | undefined { | ||
| if (!providerId) return modelInfo.provider; | ||
| if (providerId === modelInfo.provider) return modelInfo.provider; | ||
| if (modelString.startsWith(providerId + "/")) return modelInfo.provider; | ||
| return providerId; | ||
| } | ||
|
|
||
| function loadGithubLiveCatalog( | ||
| scope: object, | ||
| providerId: string, | ||
| loadCatalog: (id: string) => Promise<ActiveSyncedCatalog> = getActiveSyncedCatalog | ||
| ): Promise<ActiveSyncedCatalog> { | ||
| let byProvider = catalogByScope.get(scope); | ||
| if (!byProvider) { | ||
| byProvider = new Map(); | ||
| catalogByScope.set(scope, byProvider); | ||
| } | ||
| let pending = byProvider.get(providerId); | ||
| if (!pending) { | ||
| pending = loadCatalog(providerId); | ||
| byProvider.set(providerId, pending); | ||
| } | ||
| return pending; | ||
| } | ||
|
|
||
| /** | ||
| * Combo pre-check for GitHub live-catalog membership. | ||
| * | ||
| * Returns: | ||
| * - `true` — allow immediately (provider could not be determined) | ||
| * - `false` — skip this combo member | ||
| * - `null` — not a GitHub skip; continue the remaining credential checks | ||
| */ | ||
| export async function ghComboGate( | ||
| scope: object, | ||
| provider: string | null | undefined, | ||
| resolvedModel: string, | ||
| loadCatalog?: (id: string) => Promise<ActiveSyncedCatalog> | ||
| ): Promise<boolean | null> { | ||
| if (!provider) return true; | ||
| if (provider !== "github" && provider !== "gh") return null; | ||
| const inLiveCatalog = catalogContainsModel( | ||
| await loadGithubLiveCatalog(scope, provider, loadCatalog), | ||
| resolvedModel | ||
| ); | ||
| if (inLiveCatalog === false) return false; | ||
| return null; | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,86 @@ | ||
| /** | ||
| * #12137 — explicit GitHub combo members vs live synced catalog. | ||
| */ | ||
| import test from "node:test"; | ||
| import assert from "node:assert/strict"; | ||
| import { catalogContainsModel } from "../../src/lib/db/models/activeSyncedCatalog.ts"; | ||
| import { | ||
| comboCheckProvider, | ||
| ghComboGate, | ||
| } from "../../src/sse/handlers/chat/githubLiveCatalogFilter.ts"; | ||
|
|
||
| test("fail-open when the GitHub catalog is not authoritative yet", () => { | ||
| assert.equal( | ||
| catalogContainsModel( | ||
| { | ||
| authoritative: false, | ||
| models: [{ id: "claude-sonnet-5", name: "Claude Sonnet 5", source: "imported" }], | ||
| }, | ||
| "claude-sonnet-5" | ||
| ), | ||
| null | ||
| ); | ||
| }); | ||
|
|
||
| test("rejects explicit members missing from an authoritative GitHub catalog", () => { | ||
| assert.equal( | ||
| catalogContainsModel( | ||
| { | ||
| authoritative: true, | ||
| models: [{ id: "claude-sonnet-5", name: "Claude Sonnet 5", source: "imported" }], | ||
| }, | ||
| "github/claude-fable-5" | ||
| ), | ||
| false | ||
| ); | ||
| }); | ||
|
|
||
| test("accepts prefixed and bare ids that are in the live catalog", () => { | ||
| const catalog = { | ||
| authoritative: true, | ||
| models: [{ id: "claude-sonnet-5", name: "Claude Sonnet 5", source: "imported" }], | ||
| }; | ||
| assert.equal(catalogContainsModel(catalog, "claude-sonnet-5"), true); | ||
| assert.equal(catalogContainsModel(catalog, "github/claude-sonnet-5"), true); | ||
| }); | ||
|
|
||
| test("comboCheckProvider applies the prefix-override guard", () => { | ||
| assert.equal(comboCheckProvider("github/claude-sonnet-5", { provider: "github" }), "github"); | ||
| assert.equal( | ||
| comboCheckProvider("github/claude-sonnet-5", { provider: "github" }, "github"), | ||
| "github" | ||
| ); | ||
| assert.equal( | ||
| comboCheckProvider("xiaomi/mimo-v2-flash", { provider: "xiaomi" }, "opengate"), | ||
| "opengate" | ||
| ); | ||
| assert.equal(comboCheckProvider("gh/claude-sonnet-5", { provider: "github" }, "gh"), "github"); | ||
| }); | ||
|
|
||
| test("ghComboGate allows undetermined providers and fail-opens unsynced catalogs", async () => { | ||
| const scope = {}; | ||
| const unsynced = async () => ({ | ||
| authoritative: false, | ||
| models: [{ id: "claude-sonnet-5", name: "Claude Sonnet 5", source: "imported" as const }], | ||
| }); | ||
| assert.equal(await ghComboGate(scope, "", "claude-sonnet-5", unsynced), true); | ||
| assert.equal(await ghComboGate(scope, "openai", "gpt-4", unsynced), null); | ||
| assert.equal(await ghComboGate(scope, "github", "claude-sonnet-5", unsynced), null); | ||
| }); | ||
|
|
||
| test("ghComboGate skips GitHub members missing from an authoritative catalog", async () => { | ||
| const scope = {}; | ||
| let loads = 0; | ||
| const load = async () => { | ||
| loads += 1; | ||
| return { | ||
| authoritative: true, | ||
| models: [{ id: "claude-sonnet-5", name: "Claude Sonnet 5", source: "imported" as const }], | ||
| }; | ||
| }; | ||
| assert.equal(await ghComboGate(scope, "github", "claude-fable-5", load), false); | ||
| assert.equal(await ghComboGate(scope, "github", "claude-sonnet-5", load), null); | ||
| assert.equal(await ghComboGate(scope, "github", "github/claude-sonnet-5", load), null); | ||
| assert.equal(loads, 1, "catalog fetch is memoized per request scope"); | ||
| assert.equal(await ghComboGate({}, "gh", "claude-fable-5", load), false); | ||
| }); | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.