feat:/fix: - #61
Conversation
…ojectId persistence, DuckDuckGo browser profile - ModelRow: empty draft on Save now deletes the alias instead of silently no-op - allowedModels: isModelAllowed enforces global list even without apiKeyInfo; appendUserAliasEntries surfaces bare alias names; cache invalidated on alias/disabled mutations - v1/models: alias entries pass through with owned_by=alias - chat.js + chatCore + stream/nonStreaming: echo client-facing model id (alias) back in /v1/chat/completions response.model and SSE chunks - projectId: cache TTL 30d bound to Google account not OAuth token; skip re-fetch when DB already has projectId (seedProjectIdCache) - settingsRepo + systemInject + chatCore: injectDefaultSystemPrompt only when request has no system message yet - DuckDuckGo: undici Agent (HTTP/2) + stable Chrome 131 header set (Sec-CH-UA client hints, full Accept)、 replacing the bot UA - registry/index.js: register duckduckgo provider - duckduckgo.png icon
|
hi @elan40213-eng thanks for the pr, i will review it asap, please keep the pr open |
|
Found an issue while merging this locally: Suggested fix — move it to "dependencies": {
...
- "@tailwindcss/oxide-wasm32-wasi": "4.3.0",
...
},
"optionalDependencies": {
+ "@tailwindcss/oxide-wasm32-wasi": "4.3.0",
"better-sqlite3": "^12.6.2"
},Also worth double-checking on merge: this PR touches |
The wasm32 fallback was in the main dependencies block with a pinned 4.3.0 version, causing npm install to fail with EBADPLATFORM on x64 hosts (and any non-wasm32 CPU). Move it to optionalDependencies mirroring the better-sqlite3 pattern and bump the spec to ^4.3.3 to match the resolved @tailwindcss/oxide version. Drop the non-standard comment_better_sqlite3 metadata key while here.
Hardcoded dev origins forced every contributor into the same localhost setup. Read VANS_ALLOWED_DEV_ORIGINS (comma-separated) with the prior 127.0.0.1,localhost as the default. Prod is unaffected — Next 16 ignores allowedDevOrigins outside dev mode.
Race: resolvePrivilegedUserId().then(...) was scheduled without await in
transformRequest, so the first request always went out without the
x-gemini-api-privileged-user-id header (the .then microtask could not
drain before buildHeaders ran synchronously). Fix:
- Prewarm the cache at module load so it is ready before any request.
- Make transformRequest await resolvePrivilegedUserId() so the header
is present on the very first request. Await is safe because
BaseExecutor.execute now wraps transformRequest in
await Promise.resolve(...), keeping the sync-return contract for
every other executor.
Mutation: stripOpenAILeakFields/applyIncludeReasoningToGemini mutated the
input body in place, leaving loggers, error DB saves, and the 401/403
retry path reading a stripped body instead of the client's original.
Fix: structuredClone(body) at the start of transformRequest so the
original translatedBody stays pristine for downstream consumers.
…branch webSearchInject.js (125 lines) was never imported by chatCore, chat, or any executor — the live web-search path lives inline in chat.js. Drop the orphan module. Simplify the redundant provider.id === 'duckduckgo' check in search/index.js (registry already sets executor: 'duckduckgo'). Remove the unused bodyHasReasoning variable in chat.js that nothing read.
The /^[a-zA-Z0-9_.\-]+$/ regex and its hint strings were copied across two API routes and the dashboard page. Extract COMBO_NAME_REGEX, COMBO_NAME_HINT, COMBO_ALIAS_HINT into src/shared/constants/comboValidation.js. Behavior unchanged: same validation, same error messages, same status codes.
Catch-block console.log calls in API routes wrote errors to stdout
instead of stderr, mixing diagnostics with normal output. Convert them
to console.error across providers/[id]/models, v1beta/models
([GEMINI_NATIVE] telemetry), keys, models/alias, models/disabled,
proxy-pools/[id], and cli-tools/claude-settings. Remove the stray
console.log('Deno deployUrl:', deployUrl) in proxy-pools/deno-deploy
that leaked every freshly-minted relay URL to stdout.
When PUT /api/keys/[id] received an allowedModels/allowedProviders/ allowedCombos/allowedKinds value that was neither null nor an array (string, object, number), it silently coerced to null — meaning 'all allowed' — masking caller bugs as over-permissive defaults. Default unexpected types to [] (deny-all) for all four ACL fields, matching the documented contract: null = all, [] = none, [...] = specific.
The system-prompt save handler swallowed all failures silently (empty
catch), leaving users with no indication the save failed. Reuse the
file's existing {type, message} status pattern to surface errors next
to the Save button. Remove the unused isDark destructure from
useTheme() (never referenced in the file).
The chromium executablePath was pinned to /home/vanszs/.cache/ ms-playwright/chromium-1228/chrome-linux64/chrome — one contributor's absolute home path that fails on every other machine. Read VANS_ZCODE_CHROMIUM_PATH from the environment; pass undefined to let playwright-core use its own channel discovery when the env var is unset.
The dev prewarm script fell back to '123456' when VANS_PREWARM_PASSWORD was unset, silently authenticating with the default dashboard password in any environment that forgot to set the env var. Fail closed: if the env var is missing, print a clear error and exit non-zero so the operator sets it explicitly.
The per-process _binCache/_pyCache/_extrasCache never exposed an invalidation path, so installing headroom-ai while the server was running left the dashboard reporting 'not installed' until process restart. Export invalidateHeadroomCaches() so the install endpoint can reset the probes after a successful install.
Extend the shared COMBO_NAME_REGEX to ComboFormModal and the media-providers combo edit page, the two remaining copies of the /^[a-zA-Z0-9_.\-]+$/ regex that were protected by the first DRY pass. Behavior unchanged.
The /api/models response is always { models: [...] } by convention, so
the Array.isArray(data) fallback at line 526 was dead code reachable
only if the endpoint changed shape. Remove it. Restore 'No providers'
capitalization to match the adjacent 'No models' badge.
The commit that converted login-page strings from inline Bahasa to inline English left Indonesian-cookie users seeing English, because no corresponding keys existed in public/i18n/literals/id.json and the runtime DOM translator only matches known English source strings. Wrap the placeholder, dispatch error fallbacks, button label, and OIDC fallback in translate() from @/i18n/runtime (attributes and state-driven strings are not reached by the MutationObserver-driven DOM walker). Add the missing English keys to id.json, using the pre-commit Bahasa strings as the Indonesian translations.
Hi! I’ve tweaked a few features to suit my needs
Model aliases in
/v1/models. You can assign aliases to specific models; they are now displayed under their own name, without the provider prefix. When{"model": "my-alias"}is sent from any OpenAI-compatible client, the router will resolve it internally and then return the alias name in the response and in every stream fragment. Aliases pointing to disabled models are excluded from the list, and the cache is cleared immediately after any alias change, rather than after the TTL expires.Default system prompt. This new parameter contains text that is added to the system slot of any chat request if it does not already contain a prompt. It works with OpenAI, Claude and Gemini request formats and is triggered early enough to allow other system prompt features to be added after it. Disabled by default
Access Control List (ACL) for models at key level. API keys can now restrict which models they are permitted to call, in addition to existing restrictions by provider and combination. A selector is provided in the control panel for this purpose. The corresponding check is now applied universally, including on public endpoints without a configured key.
Caching of the Google project ID. The cached ID is now valid for 30 days instead of 1 hour, as it is tied to the account rather than the token. During a scheduled token refresh, the ID is retrieved from the database rather than being re-requested from the Google endpoint for registration.
Gemini CLI request handling. Fields rejected by the Cloud Code Assist API are removed before the request is sent. The ‘Thinking’ visibility is now mapped to a native configuration field rather than being ignored. Tool schemas are sent in a format that the API can actually read.
‘Thinking’ output formats for NVIDIA NIM. Each model family now uses its own native format for outputting reasoning results, rather than a single common format for all.
DuckDuckGo search. It has been registered, and request headers have been rewritten to match those of a real browser, so that DuckDuckGo no longer throttles its bandwidth.
Headroom detection. Checking for the presence of the Headroom binary previously blocked the control panel for over 20 seconds if it was not installed. The results are now cached, and the slow search path is only triggered when necessary.
Control Panel optimisation. The profile page has been rewritten to a smaller file, an ACL key selector has been added, and several user interface elements now support keyboard navigation.
Each new database column allows null values, and each new setting is disabled by default, so existing deployments will continue to work without any changes. Compiled and tested from start to finish on my VPS