✨ Minor Changes
- b41c0a2: Connect the Dockerized self-hosted version to local LLM servers on the host. The bundled
--profile ollamaservice is gone; the Manifest container now reaches host-installed Ollama, vLLM, LM Studio, llama.cpp, text-generation-webui, and any OpenAI-compatible server athost.docker.internal:<port>via ahost-gatewayalias. Custom providers accepthttp://and private/loopback URLs in the self-hosted version (cloud metadata endpoints stay blocked). Adds preset chips for local servers and a server-side/v1/modelsprobe that auto-populates the model list. Renames the deployment concept from "local" to "self-hosted" across the codebase (MANIFEST_MODE=selfhosted,isSelfHosted());MANIFEST_MODE=localis still honored as a legacy alias. - 7de07d2: Capture incoming request headers on every proxied chat completion and surface them in the message detail drawer, with a new App/SDK meta row sourced from the existing caller attribution. Sensitive headers (authorization, cookie, proxy-authorization, x-api-key) are stripped before storage, and the Request Headers section is collapsed by default.
- 30adc95: Fix web_browsing false positives that misrouted coding sessions. Pruned generic web-dev vocabulary (html, dom, url, http, link, page) from the webBrowsing keyword list, added weighted scoring, URL detection, code-fence/file-path signals, session stickiness across recent turns, a confidence gate, and a "Wrong category?" feedback control in the Messages log that dampens repeatedly-miscategorized categories.
🐛 Patch Changes
-
2051a74: Code quality audit cleanup across backend, frontend, and shared packages:
- Consolidate the provider registry into a single source of truth at
packages/shared/src/providers.tsthat the backendPROVIDER_REGISTRYand frontendPROVIDERSboth consume, eliminating drift. - Drop the vestigial
DbDialect/detectDialect/portableSqlhelpers and the_dialectparameter threaded through seven services; Manifest has been Postgres-only for some time. - Port
NotificationRulesServiceoff rawDataSource.query()onto TypeORM repositories + QueryBuilder. - Remove the unused
TokenUsageSnapshot/CostSnapshotentities (tables remain; no data migration). - Extract scattered
if (provider === 'xai' | 'copilot' | ...)branches into data-driven hooks (provider-hooks.ts). - Split
scoring/keywords.ts(949 lines) into one file per specificity category underscoring/keywords/. - Split
ProxyService.proxyRequest,ProxyController.chatCompletions,MessagesQueryService.getMessages, andProviderClient.forwardinto focused helpers (all previously 130+ lines). - Consolidate the frontend API layer:
fetchMutatenow takes a path, and aroutingPath(agentName, suffix)helper replaces 30+ duplicated${BASE_URL}/routing/${encodeURIComponent(...)}literals. - Add
recordSafely()andbuildMessageRow()helpers in the proxy write path to dedupe seven fire-and-forget.catch(logger.warn)blocks and five near-identical message inserts. - Remove the deprecated
subscriptionOAuthflag (usesubscriptionAuthMode === 'popup_oauth'). - Drop the identity
sql()wrapper inEmailProviderConfigServiceand helpers.
- Consolidate the provider registry into a single source of truth at
-
4599c47: Shrink the Docker image by switching the runtime stage to distroless Node 22 (
gcr.io/distroless/nodejs22-debian12:nonroot):- Runtime drops the shell,
apk, and the unused yarn toolchain thatnode:22-alpinebakes in. - Production dependencies are now staged on
node:22-slimso glibc matches the distroless debian12 runtime (all runtime deps are pure JS). - Prune
sql.jsfrom the runtime node_modules — it's an optional TypeORM peer only used by the legacy SQLite local mode, which is never active in Docker. - Add
--prefer-offline --no-audit --no-fundto all npm installs, and pin the two new base images by digest. - Result:
423MB → 362MBon disk (−14.4%),84.2MB → 71.9MBcompressed pull (−14.6%).
- Runtime drops the shell,
-
d5b23dc: Fix custom providers mangling upstream model IDs that contain
/characters (#1591, #1615). Multi-segment model names likeMiniMaxAI/MiniMax-2.7oraccounts/fireworks/routers/kimi-k2p5-turboare now forwarded to the upstream API unchanged instead of having a legitimate slash segment stripped. -
bb3dc29: Retire residual SQLite / sql.js / "local mode" references left behind after the local-mode path was removed:
- Drop the dead
isLocal()branch inRoutingInstructionModal(the/api/v1/healthendpoint never returnsmode, so the branch was unreachable) and the test that faked amode: "local"health response to exercise it. - Tighten the frontend
NotificationRule.is_activetype fromboolean | numbertoboolean, and drop thetypeof === 'number' ? !!x : xcoercion inLimits.tsxandLimitRuleTable.tsx(the integer boolean was a SQLite-era shape; the backend returns real booleans). - Remove the dead
connection: { options: { type: 'sqlite' } }mock inproxy.controller.spec.ts— no production code readsds.connection.options.type. - Remove the stale
vi.mock("../../src/services/local-mode.js", ...)inProviderSelectModal-opencode-go.test.tsx(module was deleted long ago). - Refresh the
packages/backend/src/common/utils/sql-dialect.tsheader (no dialect switching happens — the file is Postgres-only). - Fix comment/test-description rot: "dialect" wording in
query-helpers.ts+ spec, "local mode" inSidebar.test.tsx/session.guard.spec.ts/proxy-rate-limiter.ts, "PG & sql.js" incosts.e2e-spec.ts. - Update
CLAUDE.md: drop references to deleted files (local-bootstrap.service.ts,local-mode.ts,LocalAuthGuard), drop theMANIFEST_DB_PATH/MANIFEST_UPDATE_CHECK_OPTOUTenv vars (no-ops per the v2.x breaking changes), drop the "Local mode database uses sql.js" architecture note, and correct the "Better Auth database" section (Postgres always).
No behaviour change — all four test suites green (backend 4007, frontend 2267, e2e 123) and both packages typecheck clean.
- Drop the dead