diff --git a/.env.example b/.env.example index d0d3ee8576..85967b6d58 100644 --- a/.env.example +++ b/.env.example @@ -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 diff --git a/docs/reference/ENVIRONMENT.md b/docs/reference/ENVIRONMENT.md index b782e53607..6349719a85 100644 --- a/docs/reference/ENVIRONMENT.md +++ b/docs/reference/ENVIRONMENT.md @@ -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). | diff --git a/src/lib/tokenHealthCheck.ts b/src/lib/tokenHealthCheck.ts index 7607b6cb5b..432b57d088 100644 --- a/src/lib/tokenHealthCheck.ts +++ b/src/lib/tokenHealthCheck.ts @@ -132,9 +132,7 @@ function withExpiredRetry( return { ...psd, expiredRetry: { count, at } }; } -function withClearedExpiredRetry( - psd: Record -): Record { +function withClearedExpiredRetry(psd: Record): Record { const next = { ...psd }; delete next.expiredRetry; return next; @@ -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 ( diff --git a/src/server/authz/routeGuard.ts b/src/server/authz/routeGuard.ts index 942fe6d8fe..ee5b5232c5 100644 --- a/src/server/authz/routeGuard.ts +++ b/src/server/authz/routeGuard.ts @@ -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 = new Set([ "/api/system/version", diff --git a/tests/unit/bun-support.test.ts b/tests/unit/bun-support.test.ts index c8edb70f1f..74fae16f9a 100644 --- a/tests/unit/bun-support.test.ts +++ b/tests/unit/bun-support.test.ts @@ -27,14 +27,22 @@ test("createSyncDriverFactory prefers bun:sqlite built-in driver when running un (process.versions as Record).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}`); }; diff --git a/tests/unit/ts7-executor-shared-shapes.test.ts b/tests/unit/ts7-executor-shared-shapes.test.ts index 5e3c348ee3..3009e86136 100644 --- a/tests/unit/ts7-executor-shared-shapes.test.ts +++ b/tests/unit/ts7-executor-shared-shapes.test.ts @@ -90,4 +90,3 @@ describe("OpencodeExecutor — tools truncation survives the narrowing fix", () assert.equal((out as unknown[]).length, 1); }); }); -