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
5 changes: 5 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -925,6 +925,11 @@ NEXT_PUBLIC_ENABLE_SOCKS5_PROXY=true
# web_fetch). Default: 60000. Used by: open-sse/mcp-server/fetchTimeout.ts
# OMNIROUTE_MCP_UPSTREAM_TIMEOUT_MS=60000

# Maximum number of local-corpus index instances cached in memory.
# Used by: src/lib/localCorpus/configured.ts — bounds the LRU cache of
# LocalCorpusIndex objects (one per indexed root directory). Default: 5.
# OMNIROUTE_CORPUS_CACHE_SIZE=5

# Model catalog sync interval in hours.
# Used by: src/shared/services/modelSyncScheduler.ts — periodic model refresh.
# Default: 24
Expand Down
1 change: 1 addition & 0 deletions docs/reference/ENVIRONMENT.md
Original file line number Diff line number Diff line change
Expand Up @@ -512,6 +512,7 @@ detection above).
| `OMNIROUTE_MCP_DESCRIPTION_COMPRESSION` | `rtk` | `open-sse/mcp-server/descriptionCompressor.ts` | Compression algorithm/profile. Disable values: `0`, `false`, `off`. |
| `OMNIROUTE_MCP_FETCH_TIMEOUT_MS` | `10000` | `open-sse/mcp-server/fetchTimeout.ts` | Abort budget (ms) for MCP-server internal management reads (health, resilience, combos, quota, usage). |
| `OMNIROUTE_MCP_UPSTREAM_TIMEOUT_MS` | `60000` | `open-sse/mcp-server/fetchTimeout.ts` | Abort budget (ms) for MCP hops that wait on a provider (`route_request`, `web_search`, `web_fetch`). |
| `OMNIROUTE_CORPUS_CACHE_SIZE` | `5` | `src/lib/localCorpus/configured.ts` | Maximum number of local-corpus index instances cached in memory (LRU, one per indexed root directory). Clamped to a minimum of `1`. |
| `MODEL_SYNC_INTERVAL_HOURS` | `24` | `src/shared/services/modelSyncScheduler.ts` | Model catalog sync interval in hours. |
| `PROVIDER_LIMITS_SYNC_INTERVAL_MINUTES` | `70` | `src/lib/usage/providerLimits.ts` | Provider rate-limit and quota polling interval. |
| `PROVIDER_LIMITS_SYNC_SPACING_MS` | `1500` | `src/lib/usage/providerLimits.ts` | Gap (ms) between consecutive OAuth quota fetches in a bulk sync; OAuth connections are fetched one at a time to avoid bursting an upstream. `0` opts out (concurrent). |
Expand Down
11 changes: 8 additions & 3 deletions src/lib/tokenHealthCheck.ts
Original file line number Diff line number Diff line change
Expand Up @@ -132,9 +132,7 @@ function withExpiredRetry(
return { ...psd, expiredRetry: { count, at } };
}

function withClearedExpiredRetry(
psd: Record<string, unknown>
): Record<string, unknown> {
function withClearedExpiredRetry(psd: Record<string, unknown>): Record<string, unknown> {
const next = { ...psd };
delete next.expiredRetry;
return next;
Expand Down Expand Up @@ -601,6 +599,13 @@ export async function checkConnection(conn) {
const isRecoverableExpiredWithRetryBudget =
conn.testStatus === "expired" &&
conn.lastErrorType !== "account_deactivated" &&
// GitHub access-token-only connections have their own dedicated exemption
// (isRecoverableGithubCopilotNoRefresh above): ONLY the exact
// "no_refresh_token" shape self-heals. An "expired" GitHub connection for a
// different reason (e.g. invalid_grant) is genuinely terminal and must stay
// skipped, otherwise the generic retry-budget exemption below reopens #8182's
// wasted-probe fix for every "expired" GitHub connection.
!isGitHubAccessTokenOnlyConnection(conn) &&
getExpiredRetryCount(conn) < EXPIRED_RETRY_MAX;
const terminalStatuses = new Set(["credits_exhausted", "banned", "expired"]);
if (
Expand Down
2 changes: 2 additions & 0 deletions src/server/authz/routeGuard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,8 @@ export function isPrivateLanHost(hostHeader: string | null): boolean {
* /api/system/version — GET reads package.json + npm registry; only POST
* triggers the auto-update flow (spawns git checkout + npm install + pm2).
* Hard Rules #15/#17 still apply to POST.
* /api/tunnels/cloudflared — GET reads tunnel status only; only POST
* spawns the cloudflared process (#11531).
*/
export const LOCAL_ONLY_API_GET_EXEMPTIONS: ReadonlySet<string> = new Set([
"/api/system/version",
Expand Down
12 changes: 10 additions & 2 deletions tests/unit/bun-support.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,22 @@ test("createSyncDriverFactory prefers bun:sqlite built-in driver when running un
(process.versions as Record<string, string>).bun = "1.1.20";

const dummyBunDb = {
query: () => ({ run: () => ({ changes: 1, lastInsertRowid: 1 }), get: () => null, all: () => [] }),
query: () => ({
run: () => ({ changes: 1, lastInsertRowid: 1 }),
get: () => null,
all: () => [],
}),
exec: () => {},
close: () => {},
};

const loader = (modName: string) => {
if (modName === "bun:sqlite") {
return { Database: function DummyBunDatabase() { return dummyBunDb; } };
return {
Database: function DummyBunDatabase() {
return dummyBunDb;
},
};
}
throw new Error(`Unexpected module ${modName}`);
};
Expand Down
1 change: 0 additions & 1 deletion tests/unit/ts7-executor-shared-shapes.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,4 +90,3 @@ describe("OpencodeExecutor — tools truncation survives the narrowing fix", ()
assert.equal((out as unknown[]).length, 1);
});
});

Loading