Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ _Development cycle in progress — entries are added as work merges into `releas

### 🔧 Bug Fixes

- **fix(dashboard):** keep no-auth providers (opencode, duckduckgo-web, theoldllm, veoaifree-web) visible under the "Show configured only" filter — they never create a connection row (`stats.total === 0`) but are always usable and already appear in `/v1/models`, so the filter now treats `displayAuthType === "no-auth"` as configured. (#3290 — thanks @uniQta)
- **fix(sse):** harden the passthrough stream against empty upstream responses — emit a synthetic retry chunk on an empty `choices: []` (fixes a Copilot Chat crash) and log empty post-`tool_calls` completions; also registers **MiniMax M3** (1M context) across 8 provider tiers. ([#3297](https://github.com/diegosouzapw/OmniRoute/pull/3297), #3110 — thanks @wilsonicdev)
- **fix(opencode-provider):** extract `contextLength` from the live `/v1/models` catalog (live > `modelContextLengths` > static map) so passthrough models outside the legacy 8-model map no longer silently truncate to OpenCode's 128K default. ([#3298](https://github.com/diegosouzapw/OmniRoute/pull/3298) — thanks @herjarsa / @diegosouzapw)
- **fix(dev):** auto-rebuild `better-sqlite3` on a Node ABI mismatch at `npm run dev` startup (nvm 22↔24) — dev-only, no-op on the healthy path, unrelated errors not swallowed. ([#3301](https://github.com/diegosouzapw/OmniRoute/pull/3301) — thanks @zhiru)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,12 @@ export function filterConfiguredProviderEntries<TProvider>(
let filtered = entries;

if (showConfiguredOnly) {
filtered = filtered.filter((entry) => Number(entry.stats?.total || 0) > 0);
// no-auth providers never create a DB connection row (stats.total === 0) but
// are always usable and appear unconditionally in the /v1/models catalog, so
// they must not be hidden by the configured-only filter (#3290).
filtered = filtered.filter(
(entry) => entry.displayAuthType === "no-auth" || Number(entry.stats?.total || 0) > 0
);
}

if (showFreeOnly) {
Expand Down
34 changes: 34 additions & 0 deletions tests/unit/providers-page-utils.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,40 @@ test("configured-only filter keeps only providers with saved connections", () =>
assert.equal(providerPageUtils.filterConfiguredProviderEntries(entries, false).length, 3);
});

test("configured-only filter keeps no-auth providers even without a saved connection (#3290)", () => {
const entries = [
{
providerId: "claude",
provider: { id: "claude" },
stats: { total: 0 },
displayAuthType: "oauth",
toggleAuthType: "oauth",
},
{
providerId: "opencode",
provider: { id: "opencode" },
stats: { total: 0 },
displayAuthType: "no-auth",
toggleAuthType: "no-auth",
},
{
providerId: "duckduckgo-web",
provider: { id: "duckduckgo-web" },
stats: { total: 0 },
displayAuthType: "no-auth",
toggleAuthType: "no-auth",
},
];

// no-auth providers never create a DB connection row (total === 0) but are
// always usable and appear in /v1/models — they must survive the filter.
const visible = providerPageUtils.filterConfiguredProviderEntries(entries, true);
assert.deepEqual(
visible.map((entry) => entry.providerId),
["duckduckgo-web", "opencode"]
);
});

test("search filter matches provider name and id case-insensitively", () => {
const entries = [
{
Expand Down