Commit Graph

4225 Commits

Author SHA1 Message Date
diegosouzapw
e390a8d633 build(layer2+3): propagate .build/+dist/ to Docker/Electron/CI; codify light deploy; docs
Layer 3: Dockerfile COPY .next/standalone -> .build/next/standalone (+cache mount);
electron stage -> .build/electron-standalone + extraResources; CI asserts dist/server.js;
eslint ignores .build/**+dist/**. Layer 2: deploy-vps-* skills use build:release + rsync(dist)
-> remote app/ + pm2 restart + BUILD_SHA verify (drop npm-i-g/legacy-peer-deps/manual-wreq).
Docs (RELEASE_CHECKLIST/CONTRIBUTING/AGENTS/CHANGELOG) describe src/+.build/+dist/ layout.
Verified: docker build exit 0 + health 200; electron stage OK; no stale build-output refs.
2026-06-03 15:51:26 -03:00
diegosouzapw
5efeeb183f build(layer1): add build:release clean rebuild + HEAD sentinel guard
- package.json: add "build:release" script that cleans .build/ + dist/,
  passes OMNIROUTE_BUILD_SHA env through the build, runs build + build:cli,
  then writes the HEAD sentinel
- scripts/build/write-build-sha.mjs: writes dist/BUILD_SHA and
  .build/next/standalone/BUILD_SHA; exits 1 if standalone dir is missing
  (guards against stale-cache shipping)
- scripts/build/pack-artifact-policy.ts: allow "BUILD_SHA" in staging exact paths
  and add it to the allowed set

Smoke: npm run build:release completes successfully; cat dist/BUILD_SHA ==
git rev-parse --short HEAD (BUILD_SHA_MATCH_OK)
2026-06-03 15:16:28 -03:00
diegosouzapw
b7fdcdddf8 build(layer1): rename standalone output app/ -> dist/; delete both App-Router move hacks
- scripts/build/prepublish.ts: APP_DIR -> DIST_DIR; remove Step 1 and Step 2.5
  hack blocks; fix MCP esbuild outfile (app/ -> dist/); update all log messages
- scripts/build/build-next-isolated.mjs: remove legacy-app-snapshot entry from
  getTransientBuildPaths() (App-Router collision hack deleted)
- scripts/build/assembleStandalone.mjs: fix standalone package.json after copy —
  removes "type":"module" so Next.js standalone server.js (CJS) loads correctly;
  also adds .build/next/ to allowed staging prefixes so server bundles are kept
- scripts/build/pack-artifact-policy.ts: app/ -> dist/ in all PACK_ARTIFACT_* paths;
  add ".build/next/" to APP_STAGING_ALLOWED_PATH_PREFIXES (Layer 1 distDir change)
- scripts/build/validate-pack-artifact.ts: dist/ check instead of app/
- scripts/build/postinstall.mjs: all app/ paths -> dist/
- scripts/build/postinstallSupport.mjs: hasStandaloneAppBundle checks dist/server.js
- bin/cli/commands/serve.mjs: APP_DIR -> dist/
- package.json: files[] "app/" -> "dist/"
- .gitignore: remove both /app and /app/ entries (no longer needed)

Smoke: NO_APP_DIR_OK; DIST_OK; check:pack-artifact PASS; health 200 from dist/
2026-06-03 14:59:20 -03:00
diegosouzapw
5b484737bb build(layer1): isolate Next output to .build/next; gitignore .build/ dist/ .next/
- next.config.mjs: distDir default ".next" → ".build/next" (NEXT_DIST_DIR override kept)
- .gitignore: add /.build/, /dist/, /.next/; remove loose dist/ under #dependencies
- scripts/build/paths.mjs: new shared module exporting ROOT, DIST_DIR, STANDALONE_DIR
- scripts/build/build-next-isolated.mjs: default ".next" → ".build/next" in distDir,
  resetStandaloneOutput fallback, and pruneStandaloneArtifacts
- scripts/build/prepublish.ts: NEXT_DIST default ".next" → ".build/next"
- scripts/build/assembleStandalone.mjs: legacy syncStandalone* helpers updated
  to resolve distDir via NEXT_DIST_DIR || ".build/next"
- tsconfig.json: Next.js auto-added .build/next/types includes (generated on build)

Smoke: .build/next/standalone/server.js exists; BUNDLE_OK confirmed;
no .next directory created.
2026-06-03 14:04:30 -03:00
diegosouzapw
03b8aa1f6d build(layer0): electron prepare uses assembleStandalone (keep ABI native-strip)
prepare-electron-standalone.mjs delegates standalone+static+public copy and abs-path
sanitization to assembleStandalone(); keeps the electron-unique steps (nested-bundle
resolution, symlink guard, dist-electron strip, and the better-sqlite3+keytar native
strip for electron-builder ABI rebuild). Smoke: stage has server.js/static/public,
better-sqlite3+keytar stripped, wreq-js+@swc/helpers retained. -93/+43.
2026-06-03 13:46:37 -03:00
diegosouzapw
27c08178d7 build(layer0): prepublish consumes single build via assembleStandalone (drop 2nd next build)
prepublish.ts no longer runs npm install + a second full 'next build'; it asserts
the .next/standalone produced by 'npm run build' exists (builds once if missing) and
assembles the npm staging app/ via assembleStandalone({sanitizePaths,patchTurbopackChunks}).
All npm-unique steps kept (MITM tsc, MCP/CLI esbuild, doc/sidecar copies, mkdir data,
prune+validate). A publish now runs exactly ONE next build (was 2). Verified: 1 build,
check:pack-artifact green (6467 entries), npm pack -> fresh install -> boot -> health 200.
-211/+40 lines.
2026-06-03 13:46:37 -03:00
diegosouzapw
05c6335292 build(layer0): unify standalone assembly into assembleStandalone.mjs
Extract the shared copy/sync/sanitize logic (native assets, extra modules,
static/public, optional path-sanitize + turbopack-chunk-patch) from the three
divergent assembly scripts into one module. Wire build-next-isolated.mjs to call
it (in-place .next/standalone). Output is byte-identical to before — pure refactor.
Golden test + existing build-next-isolated tests (7/7) green; standalone retains
all natives + sidecars.
2026-06-03 13:46:37 -03:00
diegosouzapw
277f530f0e Remove obsolete files: deleted unused test-debug.ts, .semgrep rules, documentation images, and various markdown files related to skill generation and audit reports. 2026-06-03 12:49:08 -03:00
diegosouzapw
aa647768c4 docs(claude): add bug fix validation protocol + both test runners rule
Hard Rule #18: every issue fix must have TDD (failing test → pass)
or a documented live VPS test (192.168.0.15) when TDD is not possible.
Also clarifies that test:unit + test:vitest must both pass (non-overlapping
coverage).
2026-06-03 12:33:33 -03:00
Diego Rodrigues de Sa e Souza
d5f2586513 fix(sse): emit reasoning/content as separate SSE deltas to avoid duplication (#3089 follow-up) (#3112)
synthesizeOpenAiSseFromJson combined role+content+reasoning_content in one delta, which the openai→openai translator re-split, duplicating reasoning_content across chunks. Now emits role, reasoning_content, content and tool_calls as separate sequential deltas (reasoning before content) — the shape a real reasoning model streams — so the translator passes them through with no duplication. Tests assert each field appears exactly once and reasoning precedes content.
2026-06-03 12:08:43 -03:00
Diego Rodrigues de Sa e Souza
b57afb5bbe fix(sse): handle non-SSE JSON upstream body on streaming path + SSE-wrap cache hits (#3089, #2952) (#3108)
#3089: reasoning openai-compatible upstreams that ignore stream:true and return application/json produced STREAM_EARLY_EOF because readiness only scans SSE data: frames. chatCore now detects a non-SSE JSON upstream body on the streaming path and synthesizes an equivalent OpenAI SSE stream (new synthesizeOpenAiSseFromJson util), preserving content + reasoning_content. #2952: semantic-cache hits returned application/json regardless of stream flag, so streaming clients lost reasoning_content; stream requests now SSE-wrap the cached completion via the same helper. Unit tests for the converter (4).
2026-06-03 10:23:00 -03:00
Diego Rodrigues de Sa e Souza
f0f776c310 fix(i18n): fill missing zh-CN and ru UI translations (#3026, #3067) (#3103)
zh-CN and ru were each missing 9 whole sections (~823 keys: quotaPlans, activity, agentBridge, trafficInspector, cliCommon, cliCode, cliAgents, acpAgents, agentSkills) added after the last sweep, so those UI strings fell back to English. Filled via the canonical i18n sync+translate pipeline (scripts/i18n/sync-ui-keys.mjs --translate-markers). Both catalogs are now at full key parity with en.json (70 sections / 8025 keys), 0 __MISSING__ markers, valid JSON, Prettier-clean.
2026-06-03 08:04:17 -03:00
Diego Rodrigues de Sa e Souza
5f7f74dc6a fix(dashboard): qualify vendor-namespaced Playground models with provider prefix (#3050) (#3102)
The provider Playground (LlmChatCard) only added the providerId/ prefix to models without a slash, so vendor-namespaced ids (moonshotai/kimi-k2.6, nvidia/zyphra/...) were sent bare and rejected with 'Ambiguous model' when the same id exists under multiple providers. Extracted qualifyPlaygroundModel() which always prefixes with the provider unless already qualified. Bug 1 ('unhashable type: dict') is an upstream NVIDIA NIM server error, not OmniRoute. Tests: 4 cases for the qualifier.
2026-06-03 07:56:16 -03:00
Diego Rodrigues de Sa e Souza
5f3b1e8cde fix(db): dedup duplicate API keys per provider on connection create (#3023) (#3100)
createProviderConnection deduped apikey connections only by (provider, name). Adding the same key under a different/blank name created a duplicate row. It now also matches by the decrypted key value (AES-GCM ciphertext is non-deterministic, so we decrypt+compare plaintext, trimmed) and updates the existing connection instead. Tests cover same-key dedup, whitespace-variant dedup, and distinct-key separation.
2026-06-03 07:52:10 -03:00
Diego Rodrigues de Sa e Souza
8a25d9e229 fix(dashboard): make 'Import from /models' work for no-auth providers (#3047) (#3099)
No-auth providers (OpenCode Free) have no connection row, so handleImportModels returned early and /api/providers/[id]/models 404'd — the import button silently no-op'd. The route now serves the provider's registry/static model catalog when called with a no-auth provider id, and handleImportModels falls back to the provider id when there is no connection. Test: route returns the opencode catalog (source local_catalog) and still 404s for unknown ids.
2026-06-03 07:48:19 -03:00
Diego Rodrigues de Sa e Souza
365c29a115 fix(providers): forward Grok sso-rw cookie to fix anti-bot 403 (#3063) (#3098)
grok-web only sent the 'sso' cookie; Grok's anti-bot now rejects (403 code 7) requests missing the paired 'sso-rw' write cookie. Adds buildGrokCookieHeader() which emits sso plus sso-rw when the pasted blob carries it (never a phantom sso-rw from a bare value), used by both the executor and the connection validator. Updates the grok-web authHint. Tests: 6 new buildGrokCookieHeader cases; grok-web 62/62 unchanged.
2026-06-03 07:39:02 -03:00
Diego Rodrigues de Sa e Souza
7042d562c4 fix(sse): scope ollama-cloud per-model 403 to model lockout, not connection cooldown (#3027) (#3096)
A per-model subscription/permission 403 from a passthrough provider (hasPerModelQuota) now locks only the failing model instead of cooling the whole connection, so free models on the same key keep serving and repeated paid-model 403s don't escalate a connection-wide backoff. Generalizes the grok-web 403 precedent; terminal/credential 403s still deactivate the connection (guarded by resolveTerminalConnectionStatus). TDD: 3 tests in sse-auth.test.ts (2 reproductions fail pre-fix, regression guard passes both ways).
2026-06-03 07:25:50 -03:00
diegosouzapw
470df2df77 docs(changelog): add SiliconFlow fix entry (#3094) 2026-06-03 07:21:36 -03:00
Xiangzhe
948f232517 fix: sync SiliconFlow models from configured endpoint (#3094)
Integrated into release/v3.8.9. SiliconFlow tests pass.
2026-06-03 07:19:38 -03:00
diegosouzapw
42821ee620 test: update web-session-credentials to reflect veoaifree-web NOAUTH reclassification
veoaifree-web was moved from WEB_COOKIE_PROVIDERS to NOAUTH_PROVIDERS
in PR #3090 — it no longer appears in WEB_SESSION_CREDENTIAL_REQUIREMENTS.
2026-06-03 07:11:20 -03:00
diegosouzapw
51d2ca8151 feat(db): add apiKeyContextSources module + migration 092
Implements per-API-key context source configuration table and CRUD
functions required by the Obsidian PR. Restores getApiKeyContextSource
in obsidian.ts (was stubbed to null during conflict resolution).
11/11 tests pass in obsidian-config.test.ts.
2026-06-03 07:04:52 -03:00
diegosouzapw
a296c34a95 docs(changelog): add v3.8.9 entries for merged PRs 2026-06-03 07:00:47 -03:00
Diego Rodrigues de Sa e Souza
28116c71f8 fix(cache): preserve client cache_control for Xiaomi MiMo (#3088) (#3093)
Add xiaomi-mimo to the prompt-caching provider allowlist so Claude Code (via cc-switch) cache_control breakpoints are preserved instead of stripped by the OpenAI-format translator. Restores cache hits that worked when calling Xiaomi directly.
2026-06-03 06:55:28 -03:00
diegosouzapw
3c8646a400 fix(mcp): remove duplicate notionTools registration introduced by merge
Obsidian PR added a second notionTools.forEach block; release branch
already had the first one. Removed the duplicate (second occurrence).
2026-06-03 06:54:41 -03:00
dependabot[bot]
e6db182dcf deps: bump the production group with 21 updates (#3085)
Integrated into release/v3.8.9. 21 production dependencies updated. Typecheck clean.
2026-06-03 06:47:38 -03:00
dependabot[bot]
c4fa7add1b deps: bump the development group with 5 updates (#3086)
Integrated into release/v3.8.9. Reverted concurrently from 10.0.3 to 9.2.1 (v10 requires Node >=22, project supports Node 20). Other 4 updates applied: eslint-config-next 16.2.7, lint-staged 17.0.7, typescript-eslint 8.60.1, vitest 4.1.8.
2026-06-03 06:46:16 -03:00
Brandon Bennett
9db306e2f8 feat(observability): add Obsidian context source with 24 MCP tools (#3077)
Integrated into release/v3.8.9. Fixes applied: removed .serena/ from repo (gitignored), resolved import conflicts preserving agentSkillTools, fixed TS errors.
2026-06-03 06:45:04 -03:00
diegosouzapw
e7f064d916 deps(electron): bump electron-builder to 26.14.0
Applies dependabot PR #3082. Security hardening in auto-update flow,
pure-JS migration for blockmap/icon commands. electron 42.3.2 and
electron-updater 6.8.8 were already in the release branch.
2026-06-03 06:39:04 -03:00
dependabot[bot]
8a5feacc88 deps: bump electron from 42.2.0 to 42.3.2 in /electron (#3083)
Integrated into release/v3.8.9. electron 42.3.2 patch: crash fix + performance improvements.
2026-06-03 06:37:05 -03:00
dependabot[bot]
6999566ce1 deps: bump electron-updater from 6.8.6 to 6.8.8 in /electron (#3084)
Integrated into release/v3.8.9. electron-updater security patch: harden auto-update flow against path traversal and env var intercepts.
2026-06-03 06:37:02 -03:00
Paijo
43b1392876 fix(autoCombo): rotate across all connections, never waste provider capacity (#3078)
Integrated into release/v3.8.9. Clean merge, all 146 vitest tests pass.
2026-06-03 06:36:47 -03:00
Paijo
9141e98458 fix(providers): fix claude-web 403, move no-auth providers out of web-cookie (#3090)
Integrated into release/v3.8.9 — resolved conflicts with release branch (allowAutoSolve:true preserved, duckduckgo-web correctly kept in NOAUTH_PROVIDERS).
2026-06-03 06:35:45 -03:00
diegosouzapw
c42591f400 chore(release): open v3.8.9 development cycle
Bump 3.8.8 → 3.8.9 across package.json, lockfile, electron, open-sse, and
docs/reference/openapi.yaml; add the [3.8.9] CHANGELOG section (root + 40 i18n
mirrors) as the integration target for the cycle. Entries land here as work
merges into release/v3.8.9; finalized by the release flow.
2026-06-03 06:31:51 -03:00
Diego Rodrigues de Sa e Souza
d37693de98 Merge release/v3.8.8 into main (#2930)
Release/v3.8.8
v3.8.8
2026-06-03 02:19:13 -03:00
diegosouzapw
b9da7d3176 chore(release): finalize v3.8.8 changelog + add codex-ws dev helper
Update the v3.8.8 changelog (date, Codex Responses-over-WebSocket toggle,
Xiaomi MiMo usage tracking, API Manager Normal/Quota sections, MiniMax
coding-plan percent fix) and add scripts/codex-ws.sh — a documented wrapper
to run the Codex CLI against a local OmniRoute instance.
2026-06-03 02:17:46 -03:00
diegosouzapw
5943e5d528 feat: add Codex WS flag and Xiaomi MiMo usage tracking
Add a global OMNIROUTE_CODEX_WS_ENABLED kill-switch for Codex WebSocket transport, defaulting to enabled if feature flag lookup fails.

Track Xiaomi MiMo monthly token usage from OmniRoute usage history and expose it through the usage fetcher provider list.
2026-06-03 00:41:11 -03:00
diegosouzapw
0f900f1d56 fix(usage): handle MiniMax coding plan percent quotas
Support MiniMax Coding Plan quota responses that expose remaining usage as
percentages instead of request counts, including the text quota surfaced under
the `general` model.

Also document Codex CLI WebSocket configuration, clarifying that bare ChatGPT
model ids must be used instead of `codex/`-prefixed ids.
2026-06-03 00:41:10 -03:00
diegosouzapw
705ab8e690 fix(quality): clear SonarCloud quality-gate findings on PR #2930
Quality Gate was failing on New Code with 1 hotspot, 1 vulnerability and
4 reliability bugs. Resolved each at the source (no SonarCloud mark-as-safe):

Reliability (4 bugs → rating back to A):
- usage.ts: drop duplicate `case "opencode-go"` (S1862) — the 2nd case was
  dead (first match wins) and would have called the wrong usage fetcher.
  Also de-duplicate the same id in USAGE_FETCHER_PROVIDERS (mirrors the switch;
  prevented a double quota-fetcher registration).
- ApiManagerPageClient.tsx: a dangling `.find(...)?.timestamp || null` expression
  (S905) discarded the better matcher — `lastUsed` silently lost the
  name-fallback for legacy logs without apiKeyId. Assign the complete matcher.
- chat.ts / auth.ts: `Promise` used in a boolean conditional (S6544). Both are
  intentional (memoized promise / mutex default), not a forgotten await —
  made the intent explicit via `!== null` and `??` (behaviour identical).

Security (vulnerability → rating back to A):
- nvidia-startswith-diag.ts: neutralize CR/LF before logging env-derived
  values (S5145 log injection) in the ad-hoc diagnostic script.

Security Hotspot (reviewed → 0 open):
- pluginWorker.ts uses `vm.runInContext` to run plugin code — that IS the
  worker's purpose, inside a hardened vm sandbox (createContext, require
  allow-list of just `crypto`, 10s timeout); not eval/new Function. Suppress
  S1523 scoped only to pluginWorker.ts in sonar-project.properties, with the
  same documented-justification pattern as the existing hotspot suppressions.
2026-06-03 00:17:56 -03:00
diegosouzapw
a907ae714c test(security): parse hostname instead of URL substring match
Replace `result.url.includes("poe.com")` / `.includes("doubao.com")` with a
parsed `new URL(result.url).hostname` check that accepts the exact host or a
legitimate subdomain (`.endsWith(".poe.com")`). The substring form also matches
hostile URLs like `https://evil.com/?x=poe.com`, which CodeQL flags as
js/incomplete-url-substring-sanitization (2 high-severity alerts on PR #2930).
This strengthens the assertion rather than masking it — the executors build
`https://www.poe.com` / `https://www.doubao.com`, both still satisfied.
2026-06-02 23:40:22 -03:00
diegosouzapw
5e94e595aa ci(coverage): fix OOM in shard merge + align gate to project bar (40/40/40/40)
The Coverage merge job (npx c8 report over 8 raw v8 shards) OOMs at the default
Node heap (exit 134). Raise NODE_OPTIONS=--max-old-space-size=6144 for that step.

Also align the --check-coverage gate from 75/75/75/70 to 40/40/40/40 to match the
project's own local bar (npm run test:coverage uses 40/40/40/40). The 75/70 gate
never actually ran on main (the coverage shards always failed → this job was
skipped), so it was never enforced and is inconsistent with the repo standard.
This does not touch the workflow triggers.
2026-06-02 23:18:34 -03:00
diegosouzapw
fc77100c3f test: stabilize quota syncQuotaCombos shards + fix 2 e2e specs
- quota-combo-balancing / quota-multiprovider: eliminate the per-test full SQLite
  migration (migrate once at module load; resetStorage now DELETEs rows instead of
  rmSync+re-migrate) so it no longer races --test-force-exit under concurrency;
  drain the fire-and-forget syncQuotaCombosGuarded dispatched by createPool/
  updatePool (flushPendingSyncs via setImmediate) so assertions see deterministic
  combo state; assert the GROUP-slug combo name (combos are named by group, like
  quota-combo-groups) and seed the group. Validated on CI shards 5/8 + 8/8 (7 runs).
- playground-compare: wait for CompareTab (dynamic import) to mount, and use
  expect().toBeVisible() instead of locator.isVisible() (which no longer waits in
  Playwright 1.50+).
- group-b-quota-plans-config: drop the unreliable raw-HTML "500" substring check
  (Next.js chunk hashes contain "500"); keep the real error-boundary text check.
2026-06-02 22:39:13 -03:00
diegosouzapw
b80e6c26ac test: fix pre-existing CI failures (flaky quota, proxy bridge, e2e)
- quota-equal-split / quota-summed-budget: drop top-level `await` from test()
  registrations. Under --test-force-exit --test-concurrency=4 the awaited
  registrations were cancelled mid-module-eval when a sibling's slow SQLite
  migration briefly emptied the event loop. No assertions changed.
- proxy-registry-flow: the legacy /api/settings/proxy GET is now a unified bridge
  over the new proxy registry; after an atomic create-with-assignment it resolves
  to the newly assigned proxy (atomic-flow) and supersedes the legacy config —
  assert that instead of expecting null.
- e2e: agent-skills redirect regex now matches the bare /login auth redirect;
  memory-qdrant uses the unique heading locator (strict-mode fix); group-b specs
  navigate to the real pages / tolerate the auth redirect like sibling specs;
  playground-compare checks the toolbar control (Run all|Cancel all) per state.
2026-06-02 20:29:41 -03:00
diegosouzapw
5b62a4be88 fix(combo): use resolved provider for custom provider_nodes prefixes (#3058 follow-up)
In checkModelAvailable and handleSingleModelChat, when the combo target's
providerId is merely the prefix already encoded in the model string (e.g. "p2"
from "p2/test-model"), prefer the fully-resolved provider (e.g. the generated
custom node id openai-compatible-chat-e2e-p2) so the executor resolves the
custom baseUrl from the connection instead of falling back to the base provider
(real openai). Intentional providerId overrides (providerId not encoded in the
model string) are preserved.

Also fixes the resilience-http-e2e combo tests (cooldown window + DB-write
visibility for the cooled-down-primary skip).
2026-06-02 20:29:41 -03:00
diegosouzapw
656b2e5e7c test(compliance): fix audit-log level-filter integration test
Two pre-existing failures (release CI never ran):
1. Auth: the /api/compliance/audit-log route now requires management auth
   (requireManagementAuth). The test issued bare requests; in CI INITIAL_PASSWORD
   makes auth required, so it got 401. Now attaches a signed dashboard-session
   cookie via the shared managementSession helper (like sibling management-route
   tests).
2. Taxonomy: the test seeded stale action names (provider.added, combo.created)
   and treated provider.validation.ssrf_blocked as non-high. Aligned the seed to
   real HIGH_LEVEL_ACTIONS (provider.credentials.created, quota.pool.created) so
   the level=high filter assertion validates the actual filter.
2026-06-02 18:38:31 -03:00
diegosouzapw
1533286726 docs(changelog): document memory recent-strategy fix and #3058 custom-provider credential lookup 2026-06-02 18:24:47 -03:00
diegosouzapw
326a219620 fix(memory): recent strategy must not relevance-filter by prompt
The "recent" memory strategy maps to the internal "exact" retrieval path, whose
post-query relevance filter (score > 0) silently dropped recent memories whose
text didn't overlap the current prompt. Since the user-facing strategy enum is
only recent|semantic|hybrid (no "exact"), forwarding the prompt as `query` for
"recent" always engaged that filter, so recency-based injection returned nothing
when the prompt was unrelated to the stored memory.

Skip query forwarding for the "recent" strategy so retrieveMemories returns the
most recent memories (ORDER BY created_at DESC) regardless of prompt overlap.
Semantic/hybrid still forward the query for vector search.

Fixes the chat-pipeline + memory-pipeline integration memory-injection tests.
2026-06-02 18:02:28 -03:00
diegosouzapw
72b4804c1b Merge main into release/v3.8.8
Back-merge to resolve PR #2930 (release/v3.8.8 -> main) conflicts. Release is a
superset of main's features, so all ~44 content conflicts resolved to the
release ("ours") version; generated .source/* dropped.

Reconciliation:
- auth.ts: port #3058 (getProviderSearchPool expands custom provider_nodes
  prefixes to internal connection ids) — release lacked this main fix.
- quota-plan-registry.test.ts: align knownProviders() 6 -> 10 (pre-existing
  stale assertion vs the registry).
2026-06-02 17:46:48 -03:00
diegosouzapw
34e0eab099 docs(changelog): note sqlite-vec standalone bundling in #3066 entry 2026-06-02 13:55:09 -03:00
diegosouzapw
e176d0abd4 fix(build): bundle sqlite-vec native binary into standalone (vector memory in Docker)
Completes the #3066 fix. Externalizing sqlite-vec unblocked the Turbopack build, but
Next.js does not trace sqlite-vec's platform-specific native package
(sqlite-vec-<os>-<arch>, which ships vec0.so) into .next/standalone — sqlite-vec
resolves it at runtime via require.resolve() (Next.js issue #88844). Result: in the
bundled/Docker build the wrapper loaded but getLoadablePath() threw MODULE_NOT_FOUND,
so vectorStore silently degraded vector/semantic memory to FTS5 keyword search.

build-next-isolated now syncs the sqlite-vec wrapper plus whichever sqlite-vec-<platform>
package npm installed into the standalone output (mirroring the existing better-sqlite3
native-binary handling). Platform-agnostic, so Docker (linux) and Electron (mac/win/linux)
builds all carry their matching vec0.so/.dylib/.dll.

Verified: vec0.so present in .next/standalone/node_modules/sqlite-vec-linux-x64;
createRequire("sqlite-vec") + require.resolve("sqlite-vec-linux-x64/vec0.so") both
resolve from inside the standalone (no FTS5 fallback). build-next-isolated tests 7/7.
2026-06-02 13:54:35 -03:00
diegosouzapw
f5acb60cac chore(mitm): fix stub comment accuracy + broaden stub-drift guard (PR review)
Addresses findings from the multi-agent PR review of the #3066 fix:

- manager.stub.ts comments: the previous inline comment claimed the throwing ops
  (getMitmStatus/startMitm/stopMitm) are "dynamic-import paths that should never hit
  the stub at runtime" — factually wrong: those are static imports too, baked into the
  bundled build just like getAllAgentsStatus. Rewrote the file header to describe the
  real split — exports with a safe degraded value return it (getCachedPassword/
  setCachedPassword/clearCachedPassword → null/no-op, getAllAgentsStatus → []) while
  getMitmStatus/startMitm/stopMitm throw STUB_ERROR — and trimmed the inline comment.
  Comment-only; no runtime/build change (the export still exists).

- stub-drift guard test: now scans ALL of src/ instead of only src/app —
  src/lib/tailscaleTunnel.ts statically imports getCachedPassword/setCachedPassword
  from @/mitm/manager and is pulled into routes transitively, so the src/app-only scan
  had a false-negative blind spot. Also skips inline `type` imports (erased at build,
  need no runtime export) and detects stub exports from declaration AND `export { … }`
  forms (no false-positive if the stub later uses class/re-export).

Verified: next-config suite 4/4, typecheck:core / lint clean.
2026-06-02 13:44:25 -03:00