Commit graph

5854 commits

Author SHA1 Message Date
CREDO23
704d1bf18f refactor(mcp): per-connector cache refresh on lifecycle events
Collapse the invalidate + warmup pair into a single
refresh_mcp_tools_cache_for_connector(connector_id, search_space_id)
helper and scope live discovery to the one connector that changed
instead of the whole search space.

- new mcp_tool.discover_single_mcp_connector: load one connector,
  refresh OAuth if needed, force live MCP discovery so its cached_tools
  row is rewritten; returned wrappers are discarded since the in-process
  LRU is rebuilt lazily on the next user query
- mcp_tools_cache.refresh_mcp_tools_cache_for_connector: synchronously
  evicts the per-space LRU (LRU keys cannot scope finer) and schedules
  the per-connector prefetch via loop.create_task
- routes (OAuth callback, MCP POST, MCP PUT) collapse their two
  back-to-back calls into a single refresh call; DELETE handlers keep
  using bare invalidate_mcp_tools_cache (nothing to prefetch)

No new automated tests: the new functions are I/O glue (DB + network)
where mocked unit tests would test implementation rather than behavior.
The existing 9 unit tests for the cached_tools data shape are unchanged.
2026-05-20 17:43:27 +02:00
CREDO23
c0aa4261ac perf(mcp): persist list_tools discovery in connector.config.cached_tools
Skip the ~1-3s MCP initialize + list_tools handshake on every cache miss
by reading tool definitions from the connector row we already load. Lazy
populate on first miss, self-heal on corrupt cache, zero schema migration.
2026-05-20 16:11:07 +02:00
CREDO23
db8bffab38 perf(prompt-cache): enable Azure prompt_cache_key routing hint
Splits the OpenAI-family gate into per-param predicates so AZURE and
AZURE_OPENAI configs now receive prompt_cache_key for backend routing
affinity (Microsoft auto-caches GPT-4o+ deployments at >=1024 tokens;
the key clusters same-prefix requests on the same GPU pool and raises
hit rate on turn 2+). prompt_cache_retention stays opted out for Azure
because litellm 1.83.14's Azure transformer would drop it silently;
revisit when Azure's supported params list is updated.
2026-05-20 11:58:15 +02:00
CREDO23
71dead0406 perf(kb-planner): route internal planner calls to dedicated small/fast LLM
Adds an optional planner LLM role wired through KnowledgePriorityMiddleware
so KB query rewriting, date extraction, and recency classification run on a
cheap model (e.g. gpt-4o-mini, Haiku, Azure nano) instead of the user's
chat LLM. Operators opt in by setting is_planner: true on exactly one
global config; without it, behavior is unchanged.
2026-05-20 11:42:52 +02:00
CREDO23
c3db25302b perf(chat): kill auto-pin preflight + speculative build, rely on reactive 429 recovery
The preflight pattern probed the LLM with a 1-token ping before each
cold turn (when requested_llm_config_id==0, llm_config_id<0, and the
45s healthy TTL had expired) to detect 429s before fanning out into
planner/classifier/title-gen. To absorb its ~1-5s RTT cost we built the
agent speculatively in parallel; on 429 we discarded the build and
repinned.

Three problems with that design:

1. False security. Provider rate limits are token-bucket. A 1-token
   ping consumes ~5 tokens; the real request consumes 10-50K. The
   probe can return 200 while the real call still 429s.
2. Pure overhead in the common case. On warm-agent-cache turns the
   probe dominates wall time: ~2.5s of TTFT pure tax for ~99% of users
   who never see a 429.
3. The in-stream recovery loop (catch of _is_provider_rate_limited
   gated by not _first_event_logged) already does the right thing
   reactively: mark_runtime_cooldown -> resolve_or_get_pinned_llm_config_id
   with exclude_config_ids={previous} -> rebuild agent -> retry the
   stream. Preflight was never the only safety net; it was a redundant
   probe in front of one.

Changes:
- Delete _preflight_llm, _settle_speculative_agent_build, and the
  _PREFLIGHT_TIMEOUT_SEC / _PREFLIGHT_MAX_TOKENS constants.
- Drop the parallel agent_build_task / preflight_task plumbing in
  both stream_new_chat and stream_resume_chat; build the agent inline
  with await _build_main_agent_for_thread(...).
- Drop the unused is_recently_healthy / mark_healthy imports here
  (still exported from auto_model_pin_service since OpenRouter
  catalogue refresh and a few tests reference clear_healthy).
- Remove the obsolete preflight + settle-speculative tests from
  test_stream_new_chat_contract.py.

Net: -447 LOC. ~2.5s removed from TTFT on every cold preflight-eligible
turn. 429 recovery path is unchanged - same repin/rebuild/retry, just
not paid in advance on the healthy path.
2026-05-20 11:03:08 +02:00
CREDO23
1791241c0c perf(indexers): offload sync embed_text to thread across background workers
Connector kb_sync_services (gmail, onedrive, google_calendar, jira),
streaming indexers (discord, luma, teams) and the file-processor save
path all called embed_text inside async coroutines, blocking the
background worker's event loop for the duration of the embed. Wrap each
call site in asyncio.to_thread so concurrent indexing tasks stop
serialising on the embed.
2026-05-20 10:09:38 +02:00
CREDO23
a8de98895a perf(revert-service): offload sync embed_texts to thread
_restore_in_place_document and _reinsert_document_from_revision are
async helpers invoked by the synchronous-feeling POST /api/threads/.../revert
route; both ran embed_texts inline, blocking the event loop while the
HTTP client waited.
2026-05-20 10:04:26 +02:00
CREDO23
a3d6fa6196 perf(document-converters): offload sync embed_text/embed_texts to thread
generate_document_summary and create_document_chunks are async helpers
called from the chat path and from many connector indexers. Both wrapped
embed_text/embed_texts directly inside the coroutine, blocking the event
loop for the full duration of the embedding call.
2026-05-20 10:03:42 +02:00
CREDO23
52d425f170 perf(kb-persistence): offload sync embed_texts to thread
_create_document and _update_document run on the chat critical path
when the filesystem subagent writes via the user's chat turn. Both
called embed_texts synchronously inside an async coroutine, blocking
the event loop for the duration of the embed.
2026-05-20 10:03:14 +02:00
CREDO23
4fa85a9a94 perf(kb-search): offload sync embed_texts to thread
embed_texts holds a threading.Lock and runs a sync embedding call inside
search_knowledge_base, an async coroutine on the KB priority middleware
critical path. Blocking the event loop here stalls every other coroutine
on the worker (SSE keepalives, concurrent chat requests, background
tasks). Wrap in asyncio.to_thread so the embed runs on the default
executor pool while the loop keeps serving.
2026-05-20 10:02:38 +02:00
CREDO23
32f6766cb6 fix(tokens): use canonical prompt_tokens_details path for cache fields
LiteLLM normalizes every provider's cache fields onto
usage.prompt_tokens_details (cached_tokens + cache_creation_tokens).
The earlier fallback to usage.cache_read_input_tokens /
usage.cache_creation_input_tokens was wrong: Anthropic-shaped fields
only live there via a trailing setattr loop, and the canonical field
name on the wrapper is cache_creation_tokens (not _input_tokens).
2026-05-20 09:55:39 +02:00
CREDO23
6090980c5e obs(tokens): log prompt-cache read/write counts and hit ratio per LLM call 2026-05-20 09:51:44 +02:00
CREDO23
0cdda14922 perf(kb subagent, desktop): cap evidence.content_excerpt to 500 chars 2026-05-20 09:43:36 +02:00
CREDO23
5edf0520c4 perf(kb subagent, cloud): cap evidence.content_excerpt to 500 chars 2026-05-20 09:43:32 +02:00
CREDO23
b554c600bb perf(research subagent): cap evidence.findings and evidence.sources to bound output 2026-05-20 09:42:57 +02:00
CREDO23
6c173dc2a7 perf(teams subagent): stop echoing raw teams/channels/messages payload into evidence.items 2026-05-20 09:42:03 +02:00
CREDO23
20f7896a99 perf(luma subagent): stop echoing raw events list into evidence.items 2026-05-20 09:41:47 +02:00
CREDO23
f4e66718be perf(discord subagent): stop echoing raw channels/messages payload into evidence.items 2026-05-20 09:41:36 +02:00
CREDO23
56d8ff89e2 perf(airtable subagent): stop echoing raw records list into evidence.items 2026-05-20 09:41:18 +02:00
CREDO23
1b2f13e25c perf(clickup subagent): stop echoing raw tasks list into evidence.items 2026-05-20 09:41:04 +02:00
CREDO23
6be1b22ef6 perf(jira subagent): stop echoing raw issues list into evidence.items 2026-05-20 09:40:48 +02:00
CREDO23
6e5dd54bbf perf(slack subagent): stop echoing raw messages list into evidence.items 2026-05-20 09:40:33 +02:00
CREDO23
d3d396a473 perf(linear subagent): stop echoing raw issues list into evidence.items 2026-05-20 09:40:18 +02:00
CREDO23
553becea28 perf(gmail subagent): stop echoing raw emails array into evidence.items 2026-05-20 09:40:00 +02:00
CREDO23
1481394017 chore(scripts): add MCP session lifetime probe 2026-05-19 21:30:34 +02:00
CREDO23
3a5e16e868 perf(calendar): stop echoing raw events into evidence.items 2026-05-19 21:30:28 +02:00
CREDO23
581bbfb5c1 perf(tokens): add per-call latency to capture log 2026-05-19 21:30:25 +02:00
CREDO23
b3b66e4c48 perf(new-chat): add memory_injection middleware timing log 2026-05-19 21:30:19 +02:00
CREDO23
1df40fbe31 perf(new-chat): add knowledge_tree middleware timing log 2026-05-19 21:30:14 +02:00
CREDO23
bd153d3cdb perf(multi-agent): add kb_context_projection timing log 2026-05-19 21:30:09 +02:00
CREDO23
33bfce4406 perf(subagent): add atask EXIT breakdown timing log 2026-05-19 21:30:05 +02:00
CREDO23
9e81f2a35b perf(subagent): add subagent compile timing log 2026-05-19 21:30:01 +02:00
CREDO23
9bfba34e8e perf(mcp): add per-call, discovery, and oauth-refresh timing logs 2026-05-19 21:29:56 +02:00
Rohan Verma
d1d44dc4c5
Merge pull request #1407 from mvanhorn/fix/citation-panel-expanded-state-1367
fix(citation-panel): reset expanded state when chunkId changes
2026-05-18 21:00:46 -07:00
Matt Van Horn
047871c47a
fix(citation-panel): reset expanded state when chunkId changes
CitationPanelContent uses a single instance across different citations
(RightPanel.tsx:251 renders without a key), so when the user clicks a
new citation while the panel is open, the prior expanded state leaks
into the new citation. The reset effect had an empty dependency array,
so it only fired on mount.

Add chunkId to the effect deps so the expanded state resets each time
the citation changes.
2026-05-17 22:35:51 -07:00
Rohan Verma
8fc4b98593
Merge pull request #1402 from guangyang1206/fix/extract-domain-helper-1368
Fix/extract domain helper 1368
2026-05-17 18:17:25 -07:00
Rohan Verma
ac76d50ec7
Merge pull request #1400 from guangyang1206/fix/cachekeys-order-stable-1370
Fix/cachekeys order stable 1370
2026-05-17 18:16:30 -07:00
Rohan Verma
3c27fe688a
Merge pull request #1390 from AnishSarkar22/fix/backend-tests
fix: unit and integration tests
2026-05-17 18:15:53 -07:00
Rohan Verma
a065f94048
Merge pull request #1388 from AnishSarkar22/fix/zero-cache-stale-replica-1355
fix: zero cache stale replica & improved mentioned document chip handling
2026-05-17 18:15:36 -07:00
Anish Sarkar
cb9a0f327c test: refactor Gmail indexer tests to utilize ComposioService and hybrid chunking 2026-05-16 21:26:40 +05:30
Anish Sarkar
a0f2563dc3 test: update Stripe and Google Calendar integration tests to use ComposioService 2026-05-16 21:13:17 +05:30
Anish Sarkar
cc06cff4fb feat(tests): add mock response for file ownership in composio_module 2026-05-16 20:20:04 +05:30
Anish Sarkar
8de7d86d56 Merge remote-tracking branch 'upstream/dev' into fix/backend-tests 2026-05-16 19:40:01 +05:30
Anish Sarkar
af1d2fa430 Merge remote-tracking branch 'upstream/dev' into fix/zero-cache-stale-replica-1355 2026-05-16 19:30:09 +05:30
guangyang1206
f096548a16 fix(web): extract single tryGetHostname helper (DRY, unified fallback)
Fixes #1368

Previously,  was duplicated in 4 places with 3 subtly different fallback behaviors:
1. inline-citation.tsx: returned  on error
2. markdown-text.tsx: returned  on error
3. assistant-message.tsx: returned  on error
4. citation.tsx: returned  on error

Created canonical  in  that:
- Returns
- Strips  prefix from hostname
- Returns  on invalid URL (safest contract)

Updated all 4 call sites:
- inline-citation.tsx:  (preserves original fallback)
- markdown-text.tsx:  (preserves original fallback)
- assistant-message.tsx:  (drop-in, both return )
- citation.tsx:  (drop-in, both return )

Co-authored-by: guangyang1206 <guangyang1206@users.noreply.github.com>
2026-05-16 12:15:16 +08:00
guangyang1206
3504be3413 fix(web): make cacheKeys.*.withQueryParams order-stable (sort entries)
Fixes #1370

Object.values() produces order-dependent cache keys because the order of values depends on the order of keys in the object. This causes the same logical query to produce different cache keys when the parameter object has keys in different orders.

Added stableEntries() helper that:
1. Filters out undefined values
2. Sorts entries by key name
3. Returns flat array of [key, value] pairs

This ensures cache key identity is stable regardless of parameter object key order.

Co-authored-by: guangyang1206 <guangyang1206@users.noreply.github.com>
2026-05-16 12:10:04 +08:00
Rohan Verma
1119f557df
Merge pull request #1399 from MODSetter/dev
feat: multi-agent chat architecture, streaming runtime rewrite, and full E2E test harness
2026-05-15 18:08:04 -07:00
DESKTOP-RTLN3BA\$punk
9fb9778bd0 test: enhance index batch parallel tests to include hybrid chunker
Updated the test for the indexing pipeline to verify that both the standard and hybrid chunkers are called via asyncio.to_thread, ensuring non-blocking behavior. This change reflects the routing of non-code documents through the hybrid chunker, maintaining the event loop contract.
2026-05-15 18:02:04 -07:00
DESKTOP-RTLN3BA\$punk
c187b04e82 chore: linting 2026-05-15 17:33:44 -07:00
DESKTOP-RTLN3BA\$punk
219a5977b7 fix: update URLs to use the "www" subdomain across the application
This commit modifies various metadata and canonical URLs in the SurfSense application to ensure consistency by using "https://www.surfsense.com" instead of "https://surfsense.com". Changes were made in layout files, blog posts, and SEO components to reflect this update.
2026-05-15 12:35:15 -07:00