diff --git a/surfsense_backend/app/agents/new_chat/chat_deepagent.py b/surfsense_backend/app/agents/new_chat/chat_deepagent.py index ab47b49ce..a901a7519 100644 --- a/surfsense_backend/app/agents/new_chat/chat_deepagent.py +++ b/surfsense_backend/app/agents/new_chat/chat_deepagent.py @@ -24,7 +24,6 @@ from deepagents.backends import StateBackend from deepagents.graph import BASE_AGENT_PROMPT from deepagents.middleware.patch_tool_calls import PatchToolCallsMiddleware from deepagents.middleware.subagents import GENERAL_PURPOSE_SUBAGENT -from deepagents.middleware.summarization import create_summarization_middleware from langchain.agents import create_agent from langchain.agents.middleware import TodoListMiddleware from langchain_anthropic.middleware import AnthropicPromptCachingMiddleware @@ -41,6 +40,9 @@ from app.agents.new_chat.middleware import ( MemoryInjectionMiddleware, SurfSenseFilesystemMiddleware, ) +from app.agents.new_chat.middleware.safe_summarization import ( + create_safe_summarization_middleware, +) from app.agents.new_chat.system_prompt import ( build_configurable_system_prompt, build_surfsense_system_prompt, @@ -442,7 +444,7 @@ async def create_surfsense_deep_agent( created_by_id=user_id, thread_id=thread_id, ), - create_summarization_middleware(llm, StateBackend), + create_safe_summarization_middleware(llm, StateBackend), PatchToolCallsMiddleware(), AnthropicPromptCachingMiddleware(unsupported_model_behavior="ignore"), ] @@ -472,7 +474,7 @@ async def create_surfsense_deep_agent( thread_id=thread_id, ), SubAgentMiddleware(backend=StateBackend, subagents=[general_purpose_spec]), - create_summarization_middleware(llm, StateBackend), + create_safe_summarization_middleware(llm, StateBackend), PatchToolCallsMiddleware(), DedupHITLToolCallsMiddleware(agent_tools=tools), AnthropicPromptCachingMiddleware(unsupported_model_behavior="ignore"), diff --git a/surfsense_backend/app/agents/new_chat/middleware/safe_summarization.py b/surfsense_backend/app/agents/new_chat/middleware/safe_summarization.py new file mode 100644 index 000000000..8248f5c8c --- /dev/null +++ b/surfsense_backend/app/agents/new_chat/middleware/safe_summarization.py @@ -0,0 +1,125 @@ +"""Safe wrapper around deepagents' SummarizationMiddleware. + +Upstream issue +-------------- +`deepagents.middleware.summarization.SummarizationMiddleware._aoffload_to_backend` +(and its sync counterpart) call +``get_buffer_string(filtered_messages)`` before writing the evicted history +to the backend file. In recent ``langchain-core`` versions, ``get_buffer_string`` +accesses ``m.text`` which iterates ``self.content`` — this raises +``TypeError: 'NoneType' object is not iterable`` whenever an ``AIMessage`` +has ``content=None`` (common when a model returns *only* tool_calls, seen +frequently with Azure OpenAI ``gpt-5.x`` responses streamed through +LiteLLM). + +The exception aborts the whole agent turn, so the user just sees "Error during +chat" with no assistant response. + +Fix +--- +We subclass ``SummarizationMiddleware`` and override +``_filter_summary_messages`` — the only call site that feeds messages into +``get_buffer_string`` — to return *copies* of messages whose ``content`` is +``None`` with ``content=""``. The originals flowing through the rest of the +agent state are untouched. + +We also expose a drop-in ``create_safe_summarization_middleware`` factory +that mirrors ``deepagents.middleware.summarization.create_summarization_middleware`` +but instantiates our safe subclass. +""" + +from __future__ import annotations + +import logging +from typing import TYPE_CHECKING + +from deepagents.middleware.summarization import ( + SummarizationMiddleware, + compute_summarization_defaults, +) + +if TYPE_CHECKING: + from deepagents.backends.protocol import BACKEND_TYPES + from langchain_core.language_models import BaseChatModel + from langchain_core.messages import AnyMessage + +logger = logging.getLogger(__name__) + + +def _sanitize_message_content(msg: "AnyMessage") -> "AnyMessage": + """Return ``msg`` with ``content`` coerced to a non-``None`` value. + + ``get_buffer_string`` reads ``m.text`` which iterates ``self.content``; + when a provider streams back an ``AIMessage`` with only tool_calls and + no text, ``content`` can be ``None`` and the iteration explodes. We + replace ``None`` with an empty string so downstream consumers that only + care about text see an empty body. + + The original message is left untouched — we return a copy via + pydantic's ``model_copy`` when available, otherwise we fall back to + re-setting the attribute on a shallow copy. + """ + + if getattr(msg, "content", "not-missing") is not None: + return msg + + try: + return msg.model_copy(update={"content": ""}) + except AttributeError: + import copy + + new_msg = copy.copy(msg) + try: + new_msg.content = "" + except Exception: # pragma: no cover - defensive + logger.debug( + "Could not sanitize content=None on message of type %s", + type(msg).__name__, + ) + return msg + return new_msg + + +class SafeSummarizationMiddleware(SummarizationMiddleware): + """`SummarizationMiddleware` that tolerates messages with ``content=None``. + + Only ``_filter_summary_messages`` is overridden — this is the single + helper invoked by both the sync and async offload paths immediately + before ``get_buffer_string``. Normalising here means we get coverage + for both without having to copy the (long, rapidly-changing) offload + implementations from upstream. + """ + + def _filter_summary_messages( + self, messages: "list[AnyMessage]" + ) -> "list[AnyMessage]": + filtered = super()._filter_summary_messages(messages) + return [_sanitize_message_content(m) for m in filtered] + + +def create_safe_summarization_middleware( + model: "BaseChatModel", + backend: "BACKEND_TYPES", +) -> SafeSummarizationMiddleware: + """Drop-in replacement for ``create_summarization_middleware``. + + Mirrors the defaults computed by ``deepagents`` but returns our + ``SafeSummarizationMiddleware`` subclass so the + ``content=None`` crash in ``get_buffer_string`` is avoided. + """ + + defaults = compute_summarization_defaults(model) + return SafeSummarizationMiddleware( + model=model, + backend=backend, + trigger=defaults["trigger"], + keep=defaults["keep"], + trim_tokens_to_summarize=None, + truncate_args_settings=defaults["truncate_args_settings"], + ) + + +__all__ = [ + "SafeSummarizationMiddleware", + "create_safe_summarization_middleware", +] diff --git a/surfsense_backend/app/services/llm_router_service.py b/surfsense_backend/app/services/llm_router_service.py index 35dfdd44e..c9eeff01b 100644 --- a/surfsense_backend/app/services/llm_router_service.py +++ b/surfsense_backend/app/services/llm_router_service.py @@ -133,6 +133,44 @@ PROVIDER_MAP = { } +# Default ``api_base`` per LiteLLM provider prefix. Used as a safety net when +# a global LLM config does *not* specify ``api_base``: without this, LiteLLM +# happily picks up provider-agnostic env vars (e.g. ``AZURE_API_BASE``, +# ``OPENAI_API_BASE``) and routes, say, an ``openrouter/anthropic/claude-3-haiku`` +# request to an Azure endpoint, which then 404s with ``Resource not found``. +# Only providers with a well-known, stable public base URL are listed here — +# self-hosted / BYO-endpoint providers (ollama, custom, bedrock, vertex_ai, +# huggingface, databricks, cloudflare, replicate) are intentionally omitted +# so their existing config-driven behaviour is preserved. +PROVIDER_DEFAULT_API_BASE = { + "openrouter": "https://openrouter.ai/api/v1", + "groq": "https://api.groq.com/openai/v1", + "mistral": "https://api.mistral.ai/v1", + "perplexity": "https://api.perplexity.ai", + "xai": "https://api.x.ai/v1", + "cerebras": "https://api.cerebras.ai/v1", + "deepinfra": "https://api.deepinfra.com/v1/openai", + "fireworks_ai": "https://api.fireworks.ai/inference/v1", + "together_ai": "https://api.together.xyz/v1", + "anyscale": "https://api.endpoints.anyscale.com/v1", + "cometapi": "https://api.cometapi.com/v1", + "sambanova": "https://api.sambanova.ai/v1", +} + + +# Canonical provider → base URL when a config uses a generic ``openai``-style +# prefix but the ``provider`` field tells us which API it really is +# (e.g. DeepSeek/Alibaba/Moonshot/Zhipu/MiniMax all use ``openai`` compat but +# each has its own base URL). +PROVIDER_KEY_DEFAULT_API_BASE = { + "DEEPSEEK": "https://api.deepseek.com/v1", + "ALIBABA_QWEN": "https://dashscope-intl.aliyuncs.com/compatible-mode/v1", + "MOONSHOT": "https://api.moonshot.ai/v1", + "ZHIPU": "https://open.bigmodel.cn/api/paas/v4", + "MINIMAX": "https://api.minimax.io/v1", +} + + class LLMRouterService: """ Singleton service for managing LiteLLM Router. @@ -224,6 +262,16 @@ class LLMRouterService: # hits ContextWindowExceededError. full_model_list, ctx_fallbacks = cls._build_context_fallback_groups(model_list) + # Build a general-purpose fallback list so NotFound/timeout/rate-limit + # style failures on one deployment don't bubble up as hard errors — + # the router retries with a sibling deployment in ``auto-large``. + # ``auto-large`` is the large-context subset of ``auto``; if it is + # empty we fall back to ``auto`` itself so the router at least picks a + # different deployment in the same group. + fallbacks: list[dict[str, list[str]]] | None = None + if ctx_fallbacks: + fallbacks = [{"auto": ["auto-large"]}] + try: router_kwargs: dict[str, Any] = { "model_list": full_model_list, @@ -237,15 +285,18 @@ class LLMRouterService: } if ctx_fallbacks: router_kwargs["context_window_fallbacks"] = ctx_fallbacks + if fallbacks: + router_kwargs["fallbacks"] = fallbacks instance._router = Router(**router_kwargs) instance._initialized = True logger.info( "LLM Router initialized with %d deployments, " - "strategy: %s, context_window_fallbacks: %s", + "strategy: %s, context_window_fallbacks: %s, fallbacks: %s", len(model_list), final_settings.get("routing_strategy"), ctx_fallbacks or "none", + fallbacks or "none", ) except Exception as e: logger.error(f"Failed to initialize LLM Router: {e}") @@ -348,10 +399,11 @@ class LLMRouterService: return None # Build model string + provider = config.get("provider", "").upper() if config.get("custom_provider"): - model_string = f"{config['custom_provider']}/{config['model_name']}" + provider_prefix = config["custom_provider"] + model_string = f"{provider_prefix}/{config['model_name']}" else: - provider = config.get("provider", "").upper() provider_prefix = PROVIDER_MAP.get(provider, provider.lower()) model_string = f"{provider_prefix}/{config['model_name']}" @@ -361,9 +413,19 @@ class LLMRouterService: "api_key": config.get("api_key"), } - # Add optional api_base - if config.get("api_base"): - litellm_params["api_base"] = config["api_base"] + # Resolve ``api_base``. Config value wins; otherwise apply a + # provider-aware default so the deployment does not silently + # inherit unrelated env vars (e.g. ``AZURE_API_BASE``) and route + # requests to the wrong endpoint. See ``PROVIDER_DEFAULT_API_BASE`` + # docstring for the motivating bug (OpenRouter models 404-ing + # against an Azure endpoint). + api_base = config.get("api_base") + if not api_base: + api_base = PROVIDER_KEY_DEFAULT_API_BASE.get(provider) + if not api_base: + api_base = PROVIDER_DEFAULT_API_BASE.get(provider_prefix) + if api_base: + litellm_params["api_base"] = api_base # Add any additional litellm parameters if config.get("litellm_params"): diff --git a/surfsense_backend/pyproject.toml b/surfsense_backend/pyproject.toml index 01f5ddc1b..131627386 100644 --- a/surfsense_backend/pyproject.toml +++ b/surfsense_backend/pyproject.toml @@ -74,7 +74,7 @@ dependencies = [ "deepagents>=0.4.12", "stripe>=15.0.0", "azure-ai-documentintelligence>=1.0.2", - "litellm>=1.83.0", + "litellm>=1.83.4", "langchain-litellm>=0.6.4", ] diff --git a/surfsense_backend/uv.lock b/surfsense_backend/uv.lock index ac2784668..209c42a9c 100644 --- a/surfsense_backend/uv.lock +++ b/surfsense_backend/uv.lock @@ -8070,7 +8070,7 @@ requires-dist = [ { name = "langgraph", specifier = ">=1.1.3" }, { name = "langgraph-checkpoint-postgres", specifier = ">=3.0.2" }, { name = "linkup-sdk", specifier = ">=0.2.4" }, - { name = "litellm", specifier = ">=1.83.0" }, + { name = "litellm", specifier = ">=1.83.4" }, { name = "llama-cloud-services", specifier = ">=0.6.25" }, { name = "markdown", specifier = ">=3.7" }, { name = "markdownify", specifier = ">=0.14.1" }, diff --git a/surfsense_web/pnpm-lock.yaml b/surfsense_web/pnpm-lock.yaml index 7cb492a05..1c3dd61e0 100644 --- a/surfsense_web/pnpm-lock.yaml +++ b/surfsense_web/pnpm-lock.yaml @@ -1088,10 +1088,6 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/runtime@7.28.6': - resolution: {integrity: sha512-05WQkdpL9COIMz4LjTxGpPNCdlpyimKppYNoJ5Di5EUObifl8t4tuLuUBBZEpoLYOmfvIWrsp9fCl0HoPRVTdA==} - engines: {node: '>=6.9.0'} - '@babel/runtime@7.29.2': resolution: {integrity: sha512-JiDShH45zKHWyGe4ZNVRrCjBz8Nh9TMmZG1kh4QTK8hCBTWBi8Da+i7s1fJw7/lYpM4ccepSNfqzZ/QvABBi5g==} engines: {node: '>=6.9.0'} @@ -2188,12 +2184,6 @@ packages: peerDependencies: '@opentelemetry/api': '>=1.0.0 <1.10.0' - '@opentelemetry/core@2.5.1': - resolution: {integrity: sha512-Dwlc+3HAZqpgTYq0MUyZABjFkcrKTePwuiFVLjahGD8cx3enqihmpAmdgNFO1R4m/sIe5afjJrA25Prqy4NXlA==} - engines: {node: ^18.19.0 || >=20.6.0} - peerDependencies: - '@opentelemetry/api': '>=1.0.0 <1.10.0' - '@opentelemetry/core@2.6.0': resolution: {integrity: sha512-HLM1v2cbZ4TgYN6KEOj+Bbj8rAKriOdkF9Ed3tG25FoprSiQl7kYc+RRT6fUZGOvx0oMi5U67GoFdT+XUn8zEg==} engines: {node: ^18.19.0 || >=20.6.0} @@ -2606,12 +2596,6 @@ packages: peerDependencies: '@opentelemetry/api': '>=1.3.0 <1.10.0' - '@opentelemetry/resources@2.5.1': - resolution: {integrity: sha512-BViBCdE/GuXRlp9k7nS1w6wJvY5fnFX5XvuEtWsTAOQFIO89Eru7lGW3WbfbxtCuZ/GbrJfAziXG0w0dpxL7eQ==} - engines: {node: ^18.19.0 || >=20.6.0} - peerDependencies: - '@opentelemetry/api': '>=1.3.0 <1.10.0' - '@opentelemetry/resources@2.6.0': resolution: {integrity: sha512-D4y/+OGe3JSuYUCBxtH5T9DSAWNcvCb/nQWIga8HNtXTVPQn59j0nTBAgaAXxUVBDl40mG3Tc76b46wPlZaiJQ==} engines: {node: ^18.19.0 || >=20.6.0} @@ -4372,8 +4356,8 @@ packages: peerDependencies: react: '>= 16' - '@tabler/icons@3.37.1': - resolution: {integrity: sha512-neLCWkuyNHEPXCyYu6nbN4S3g/59BTa4qyITAugYVpq1YzYNDOZooW7/vRWH98ZItXAudxdKU8muFT7y1PqzuA==} + '@tabler/icons@3.41.1': + resolution: {integrity: sha512-OaRnVbRmH2nHtFeg+RmMJ/7m2oBIF9XCJAUD5gQnMrpK9f05ydj8MZrAf3NZQqOXyxGN1UBL0D5IKLLEUfr74Q==} '@tailwindcss/node@4.2.1': resolution: {integrity: sha512-jlx6sLk4EOwO6hHe1oCGm1Q4AN/s0rSrTTPBGPM0/RQ6Uylwq17FuU8IeJJKEjtc6K6O07zsvP+gDO6MMWo7pg==} @@ -4814,6 +4798,7 @@ packages: '@xmldom/xmldom@0.8.11': resolution: {integrity: sha512-cQzWCtO6C8TQiYl1ruKNn2U6Ao4o4WBBcbL61yJl84x+j5sOWWFU9X7DpND8XZG3daDppSsigMdfAIl2upQBRw==} engines: {node: '>=10.0.0'} + deprecated: this version has critical issues, please update to the latest version abstract-logging@2.0.1: resolution: {integrity: sha512-2BjRTZxTPvheOvGbBslFSYOUkr+SjPtOnrLP33f+VIWLzezQpZcqVg7ja3L4dBXmzzgwT+a029jRx5PCi3JuiA==} @@ -7012,11 +6997,6 @@ packages: engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true - nanoid@5.1.6: - resolution: {integrity: sha512-c7+7RQ+dMB5dPwwCp4ee1/iV/q2P6aK1mTZcfr1BTuVlyW9hJYiMPybJCcnBlQtuSmTIWNeazm/zqNoZSSElBg==} - engines: {node: ^18 || >=20} - hasBin: true - nanoid@5.1.7: resolution: {integrity: sha512-ua3NDgISf6jdwezAheMOk4mbE1LXjm1DfMUDMuJf4AqxLFK3ccGpgWizwa5YV7Yz9EpXwEaWoRXSb/BnV0t5dQ==} engines: {node: ^18 || >=20} @@ -7421,8 +7401,8 @@ packages: property-information@7.1.0: resolution: {integrity: sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ==} - protobufjs@7.5.4: - resolution: {integrity: sha512-CvexbZtbov6jW2eXAvLukXjXUW1TzFaivC46BpWc/3BpcCysb5Vffu+B3XHMm8lVEuy2Mm4XGex8hBSg1yapPg==} + protobufjs@7.5.5: + resolution: {integrity: sha512-3wY1AxV+VBNW8Yypfd1yQY9pXnqTAN+KwQxL8iYm3/BjKYMNg4i0owhEe26PWDOMaIrzeeF98Lqd5NGz4omiIg==} engines: {node: '>=12.0.0'} proxy-compare@2.6.0: @@ -9387,8 +9367,6 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/runtime@7.28.6': {} - '@babel/runtime@7.29.2': {} '@babel/standalone@7.29.2': {} @@ -9886,7 +9864,7 @@ snapshots: dependencies: lodash.camelcase: 4.3.0 long: 5.3.2 - protobufjs: 7.5.4 + protobufjs: 7.5.5 yargs: 17.7.2 '@hookform/resolvers@5.2.2(react-hook-form@7.71.2(react@19.2.4))': @@ -10246,7 +10224,7 @@ snapshots: '@opentelemetry/resource-detector-azure': 0.10.0(@opentelemetry/api@1.9.0) '@opentelemetry/resource-detector-container': 0.7.11(@opentelemetry/api@1.9.0) '@opentelemetry/resource-detector-gcp': 0.37.0(@opentelemetry/api@1.9.0) - '@opentelemetry/resources': 2.5.1(@opentelemetry/api@1.9.0) + '@opentelemetry/resources': 2.6.0(@opentelemetry/api@1.9.0) '@opentelemetry/sdk-node': 0.203.0(@opentelemetry/api@1.9.0) transitivePeerDependencies: - encoding @@ -10270,11 +10248,6 @@ snapshots: '@opentelemetry/api': 1.9.0 '@opentelemetry/semantic-conventions': 1.39.0 - '@opentelemetry/core@2.5.1(@opentelemetry/api@1.9.0)': - dependencies: - '@opentelemetry/api': 1.9.0 - '@opentelemetry/semantic-conventions': 1.39.0 - '@opentelemetry/core@2.6.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 @@ -10397,7 +10370,7 @@ snapshots: '@opentelemetry/instrumentation-amqplib@0.50.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.5.1(@opentelemetry/api@1.9.0) + '@opentelemetry/core': 2.6.0(@opentelemetry/api@1.9.0) '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) '@opentelemetry/semantic-conventions': 1.39.0 transitivePeerDependencies: @@ -10415,7 +10388,7 @@ snapshots: '@opentelemetry/instrumentation-aws-sdk@0.58.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.5.1(@opentelemetry/api@1.9.0) + '@opentelemetry/core': 2.6.0(@opentelemetry/api@1.9.0) '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) '@opentelemetry/semantic-conventions': 1.39.0 transitivePeerDependencies: @@ -10441,7 +10414,7 @@ snapshots: '@opentelemetry/instrumentation-connect@0.47.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.5.1(@opentelemetry/api@1.9.0) + '@opentelemetry/core': 2.6.0(@opentelemetry/api@1.9.0) '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) '@opentelemetry/semantic-conventions': 1.39.0 '@types/connect': 3.4.38 @@ -10473,7 +10446,7 @@ snapshots: '@opentelemetry/instrumentation-express@0.52.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.5.1(@opentelemetry/api@1.9.0) + '@opentelemetry/core': 2.6.0(@opentelemetry/api@1.9.0) '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) '@opentelemetry/semantic-conventions': 1.39.0 transitivePeerDependencies: @@ -10482,7 +10455,7 @@ snapshots: '@opentelemetry/instrumentation-fastify@0.48.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.5.1(@opentelemetry/api@1.9.0) + '@opentelemetry/core': 2.6.0(@opentelemetry/api@1.9.0) '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) '@opentelemetry/semantic-conventions': 1.39.0 transitivePeerDependencies: @@ -10491,7 +10464,7 @@ snapshots: '@opentelemetry/instrumentation-fs@0.23.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.5.1(@opentelemetry/api@1.9.0) + '@opentelemetry/core': 2.6.0(@opentelemetry/api@1.9.0) '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) transitivePeerDependencies: - supports-color @@ -10521,7 +10494,7 @@ snapshots: '@opentelemetry/instrumentation-hapi@0.50.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.5.1(@opentelemetry/api@1.9.0) + '@opentelemetry/core': 2.6.0(@opentelemetry/api@1.9.0) '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) '@opentelemetry/semantic-conventions': 1.39.0 transitivePeerDependencies: @@ -10565,7 +10538,7 @@ snapshots: '@opentelemetry/instrumentation-koa@0.51.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.5.1(@opentelemetry/api@1.9.0) + '@opentelemetry/core': 2.6.0(@opentelemetry/api@1.9.0) '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) '@opentelemetry/semantic-conventions': 1.39.0 transitivePeerDependencies: @@ -10598,7 +10571,7 @@ snapshots: '@opentelemetry/instrumentation-mongoose@0.50.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.5.1(@opentelemetry/api@1.9.0) + '@opentelemetry/core': 2.6.0(@opentelemetry/api@1.9.0) '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) '@opentelemetry/semantic-conventions': 1.39.0 transitivePeerDependencies: @@ -10650,7 +10623,7 @@ snapshots: '@opentelemetry/instrumentation-pg@0.56.1(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.5.1(@opentelemetry/api@1.9.0) + '@opentelemetry/core': 2.6.0(@opentelemetry/api@1.9.0) '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) '@opentelemetry/semantic-conventions': 1.39.0 '@opentelemetry/sql-common': 0.41.2(@opentelemetry/api@1.9.0) @@ -10663,7 +10636,7 @@ snapshots: dependencies: '@opentelemetry/api': 1.9.0 '@opentelemetry/api-logs': 0.203.0 - '@opentelemetry/core': 2.5.1(@opentelemetry/api@1.9.0) + '@opentelemetry/core': 2.6.0(@opentelemetry/api@1.9.0) '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) transitivePeerDependencies: - supports-color @@ -10680,7 +10653,7 @@ snapshots: '@opentelemetry/instrumentation-restify@0.49.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.5.1(@opentelemetry/api@1.9.0) + '@opentelemetry/core': 2.6.0(@opentelemetry/api@1.9.0) '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) '@opentelemetry/semantic-conventions': 1.39.0 transitivePeerDependencies: @@ -10721,7 +10694,7 @@ snapshots: '@opentelemetry/instrumentation-undici@0.14.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.5.1(@opentelemetry/api@1.9.0) + '@opentelemetry/core': 2.6.0(@opentelemetry/api@1.9.0) '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) transitivePeerDependencies: - supports-color @@ -10772,7 +10745,7 @@ snapshots: '@opentelemetry/sdk-logs': 0.203.0(@opentelemetry/api@1.9.0) '@opentelemetry/sdk-metrics': 2.0.1(@opentelemetry/api@1.9.0) '@opentelemetry/sdk-trace-base': 2.0.1(@opentelemetry/api@1.9.0) - protobufjs: 7.5.4 + protobufjs: 7.5.5 '@opentelemetry/otlp-transformer@0.208.0(@opentelemetry/api@1.9.0)': dependencies: @@ -10783,7 +10756,7 @@ snapshots: '@opentelemetry/sdk-logs': 0.208.0(@opentelemetry/api@1.9.0) '@opentelemetry/sdk-metrics': 2.2.0(@opentelemetry/api@1.9.0) '@opentelemetry/sdk-trace-base': 2.2.0(@opentelemetry/api@1.9.0) - protobufjs: 7.5.4 + protobufjs: 7.5.5 '@opentelemetry/propagator-b3@2.0.1(@opentelemetry/api@1.9.0)': dependencies: @@ -10800,34 +10773,34 @@ snapshots: '@opentelemetry/resource-detector-alibaba-cloud@0.31.11(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.5.1(@opentelemetry/api@1.9.0) - '@opentelemetry/resources': 2.5.1(@opentelemetry/api@1.9.0) + '@opentelemetry/core': 2.6.0(@opentelemetry/api@1.9.0) + '@opentelemetry/resources': 2.6.0(@opentelemetry/api@1.9.0) '@opentelemetry/resource-detector-aws@2.13.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.5.1(@opentelemetry/api@1.9.0) - '@opentelemetry/resources': 2.5.1(@opentelemetry/api@1.9.0) + '@opentelemetry/core': 2.6.0(@opentelemetry/api@1.9.0) + '@opentelemetry/resources': 2.6.0(@opentelemetry/api@1.9.0) '@opentelemetry/semantic-conventions': 1.39.0 '@opentelemetry/resource-detector-azure@0.10.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.5.1(@opentelemetry/api@1.9.0) - '@opentelemetry/resources': 2.5.1(@opentelemetry/api@1.9.0) + '@opentelemetry/core': 2.6.0(@opentelemetry/api@1.9.0) + '@opentelemetry/resources': 2.6.0(@opentelemetry/api@1.9.0) '@opentelemetry/semantic-conventions': 1.39.0 '@opentelemetry/resource-detector-container@0.7.11(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.5.1(@opentelemetry/api@1.9.0) - '@opentelemetry/resources': 2.5.1(@opentelemetry/api@1.9.0) + '@opentelemetry/core': 2.6.0(@opentelemetry/api@1.9.0) + '@opentelemetry/resources': 2.6.0(@opentelemetry/api@1.9.0) '@opentelemetry/resource-detector-gcp@0.37.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.5.1(@opentelemetry/api@1.9.0) - '@opentelemetry/resources': 2.5.1(@opentelemetry/api@1.9.0) + '@opentelemetry/core': 2.6.0(@opentelemetry/api@1.9.0) + '@opentelemetry/resources': 2.6.0(@opentelemetry/api@1.9.0) '@opentelemetry/semantic-conventions': 1.39.0 gcp-metadata: 6.1.1 transitivePeerDependencies: @@ -10846,12 +10819,6 @@ snapshots: '@opentelemetry/core': 2.2.0(@opentelemetry/api@1.9.0) '@opentelemetry/semantic-conventions': 1.39.0 - '@opentelemetry/resources@2.5.1(@opentelemetry/api@1.9.0)': - dependencies: - '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.5.1(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.39.0 - '@opentelemetry/resources@2.6.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 @@ -10952,7 +10919,7 @@ snapshots: '@opentelemetry/sql-common@0.41.2(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.5.1(@opentelemetry/api@1.9.0) + '@opentelemetry/core': 2.6.0(@opentelemetry/api@1.9.0) '@orama/orama@3.1.18': {} @@ -11067,7 +11034,7 @@ snapshots: jotai-optics: 0.4.0(jotai@2.8.4(@types/react@19.2.14)(react@19.2.4))(optics-ts@2.4.1) jotai-x: 2.3.3(@types/react@19.2.14)(jotai@2.8.4(@types/react@19.2.14)(react@19.2.4))(react@19.2.4) lodash: 4.17.23 - nanoid: 5.1.6 + nanoid: 5.1.7 optics-ts: 2.4.1 react: 19.2.4 react-compiler-runtime: 1.0.0(react@19.2.4) @@ -11265,11 +11232,11 @@ snapshots: '@radix-ui/primitive@1.0.0': dependencies: - '@babel/runtime': 7.28.6 + '@babel/runtime': 7.29.2 '@radix-ui/primitive@1.0.1': dependencies: - '@babel/runtime': 7.28.6 + '@babel/runtime': 7.29.2 '@radix-ui/primitive@1.1.3': {} @@ -11403,12 +11370,12 @@ snapshots: '@radix-ui/react-compose-refs@1.0.0(react@19.2.4)': dependencies: - '@babel/runtime': 7.28.6 + '@babel/runtime': 7.29.2 react: 19.2.4 '@radix-ui/react-compose-refs@1.0.1(@types/react@19.2.14)(react@19.2.4)': dependencies: - '@babel/runtime': 7.28.6 + '@babel/runtime': 7.29.2 react: 19.2.4 optionalDependencies: '@types/react': 19.2.14 @@ -11435,12 +11402,12 @@ snapshots: '@radix-ui/react-context@1.0.0(react@19.2.4)': dependencies: - '@babel/runtime': 7.28.6 + '@babel/runtime': 7.29.2 react: 19.2.4 '@radix-ui/react-context@1.0.1(@types/react@19.2.14)(react@19.2.4)': dependencies: - '@babel/runtime': 7.28.6 + '@babel/runtime': 7.29.2 react: 19.2.4 optionalDependencies: '@types/react': 19.2.14 @@ -11459,7 +11426,7 @@ snapshots: '@radix-ui/react-dialog@1.0.0(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': dependencies: - '@babel/runtime': 7.28.6 + '@babel/runtime': 7.29.2 '@radix-ui/primitive': 1.0.0 '@radix-ui/react-compose-refs': 1.0.0(react@19.2.4) '@radix-ui/react-context': 1.0.0(react@19.2.4) @@ -11481,7 +11448,7 @@ snapshots: '@radix-ui/react-dialog@1.0.4(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': dependencies: - '@babel/runtime': 7.28.6 + '@babel/runtime': 7.29.2 '@radix-ui/primitive': 1.0.1 '@radix-ui/react-compose-refs': 1.0.1(@types/react@19.2.14)(react@19.2.4) '@radix-ui/react-context': 1.0.1(@types/react@19.2.14)(react@19.2.4) @@ -11532,7 +11499,7 @@ snapshots: '@radix-ui/react-dismissable-layer@1.0.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': dependencies: - '@babel/runtime': 7.28.6 + '@babel/runtime': 7.29.2 '@radix-ui/primitive': 1.0.0 '@radix-ui/react-compose-refs': 1.0.0(react@19.2.4) '@radix-ui/react-primitive': 1.0.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4) @@ -11543,7 +11510,7 @@ snapshots: '@radix-ui/react-dismissable-layer@1.0.4(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': dependencies: - '@babel/runtime': 7.28.6 + '@babel/runtime': 7.29.2 '@radix-ui/primitive': 1.0.1 '@radix-ui/react-compose-refs': 1.0.1(@types/react@19.2.14)(react@19.2.4) '@radix-ui/react-primitive': 1.0.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) @@ -11585,12 +11552,12 @@ snapshots: '@radix-ui/react-focus-guards@1.0.0(react@19.2.4)': dependencies: - '@babel/runtime': 7.28.6 + '@babel/runtime': 7.29.2 react: 19.2.4 '@radix-ui/react-focus-guards@1.0.1(@types/react@19.2.14)(react@19.2.4)': dependencies: - '@babel/runtime': 7.28.6 + '@babel/runtime': 7.29.2 react: 19.2.4 optionalDependencies: '@types/react': 19.2.14 @@ -11603,7 +11570,7 @@ snapshots: '@radix-ui/react-focus-scope@1.0.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': dependencies: - '@babel/runtime': 7.28.6 + '@babel/runtime': 7.29.2 '@radix-ui/react-compose-refs': 1.0.0(react@19.2.4) '@radix-ui/react-primitive': 1.0.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4) '@radix-ui/react-use-callback-ref': 1.0.0(react@19.2.4) @@ -11612,7 +11579,7 @@ snapshots: '@radix-ui/react-focus-scope@1.0.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': dependencies: - '@babel/runtime': 7.28.6 + '@babel/runtime': 7.29.2 '@radix-ui/react-compose-refs': 1.0.1(@types/react@19.2.14)(react@19.2.4) '@radix-ui/react-primitive': 1.0.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@19.2.14)(react@19.2.4) @@ -11666,13 +11633,13 @@ snapshots: '@radix-ui/react-id@1.0.0(react@19.2.4)': dependencies: - '@babel/runtime': 7.28.6 + '@babel/runtime': 7.29.2 '@radix-ui/react-use-layout-effect': 1.0.0(react@19.2.4) react: 19.2.4 '@radix-ui/react-id@1.0.1(@types/react@19.2.14)(react@19.2.4)': dependencies: - '@babel/runtime': 7.28.6 + '@babel/runtime': 7.29.2 '@radix-ui/react-use-layout-effect': 1.0.1(@types/react@19.2.14)(react@19.2.4) react: 19.2.4 optionalDependencies: @@ -11848,14 +11815,14 @@ snapshots: '@radix-ui/react-portal@1.0.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': dependencies: - '@babel/runtime': 7.28.6 + '@babel/runtime': 7.29.2 '@radix-ui/react-primitive': 1.0.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4) react: 19.2.4 react-dom: 19.2.4(react@19.2.4) '@radix-ui/react-portal@1.0.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': dependencies: - '@babel/runtime': 7.28.6 + '@babel/runtime': 7.29.2 '@radix-ui/react-primitive': 1.0.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) react: 19.2.4 react-dom: 19.2.4(react@19.2.4) @@ -11875,7 +11842,7 @@ snapshots: '@radix-ui/react-presence@1.0.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': dependencies: - '@babel/runtime': 7.28.6 + '@babel/runtime': 7.29.2 '@radix-ui/react-compose-refs': 1.0.0(react@19.2.4) '@radix-ui/react-use-layout-effect': 1.0.0(react@19.2.4) react: 19.2.4 @@ -11883,7 +11850,7 @@ snapshots: '@radix-ui/react-presence@1.0.1(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': dependencies: - '@babel/runtime': 7.28.6 + '@babel/runtime': 7.29.2 '@radix-ui/react-compose-refs': 1.0.1(@types/react@19.2.14)(react@19.2.4) '@radix-ui/react-use-layout-effect': 1.0.1(@types/react@19.2.14)(react@19.2.4) react: 19.2.4 @@ -11904,14 +11871,14 @@ snapshots: '@radix-ui/react-primitive@1.0.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': dependencies: - '@babel/runtime': 7.28.6 + '@babel/runtime': 7.29.2 '@radix-ui/react-slot': 1.0.0(react@19.2.4) react: 19.2.4 react-dom: 19.2.4(react@19.2.4) '@radix-ui/react-primitive@1.0.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': dependencies: - '@babel/runtime': 7.28.6 + '@babel/runtime': 7.29.2 '@radix-ui/react-slot': 1.0.2(@types/react@19.2.14)(react@19.2.4) react: 19.2.4 react-dom: 19.2.4(react@19.2.4) @@ -12067,13 +12034,13 @@ snapshots: '@radix-ui/react-slot@1.0.0(react@19.2.4)': dependencies: - '@babel/runtime': 7.28.6 + '@babel/runtime': 7.29.2 '@radix-ui/react-compose-refs': 1.0.0(react@19.2.4) react: 19.2.4 '@radix-ui/react-slot@1.0.2(@types/react@19.2.14)(react@19.2.4)': dependencies: - '@babel/runtime': 7.28.6 + '@babel/runtime': 7.29.2 '@radix-ui/react-compose-refs': 1.0.1(@types/react@19.2.14)(react@19.2.4) react: 19.2.4 optionalDependencies: @@ -12207,12 +12174,12 @@ snapshots: '@radix-ui/react-use-callback-ref@1.0.0(react@19.2.4)': dependencies: - '@babel/runtime': 7.28.6 + '@babel/runtime': 7.29.2 react: 19.2.4 '@radix-ui/react-use-callback-ref@1.0.1(@types/react@19.2.14)(react@19.2.4)': dependencies: - '@babel/runtime': 7.28.6 + '@babel/runtime': 7.29.2 react: 19.2.4 optionalDependencies: '@types/react': 19.2.14 @@ -12225,13 +12192,13 @@ snapshots: '@radix-ui/react-use-controllable-state@1.0.0(react@19.2.4)': dependencies: - '@babel/runtime': 7.28.6 + '@babel/runtime': 7.29.2 '@radix-ui/react-use-callback-ref': 1.0.0(react@19.2.4) react: 19.2.4 '@radix-ui/react-use-controllable-state@1.0.1(@types/react@19.2.14)(react@19.2.4)': dependencies: - '@babel/runtime': 7.28.6 + '@babel/runtime': 7.29.2 '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@19.2.14)(react@19.2.4) react: 19.2.4 optionalDependencies: @@ -12254,13 +12221,13 @@ snapshots: '@radix-ui/react-use-escape-keydown@1.0.0(react@19.2.4)': dependencies: - '@babel/runtime': 7.28.6 + '@babel/runtime': 7.29.2 '@radix-ui/react-use-callback-ref': 1.0.0(react@19.2.4) react: 19.2.4 '@radix-ui/react-use-escape-keydown@1.0.3(@types/react@19.2.14)(react@19.2.4)': dependencies: - '@babel/runtime': 7.28.6 + '@babel/runtime': 7.29.2 '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@19.2.14)(react@19.2.4) react: 19.2.4 optionalDependencies: @@ -12282,12 +12249,12 @@ snapshots: '@radix-ui/react-use-layout-effect@1.0.0(react@19.2.4)': dependencies: - '@babel/runtime': 7.28.6 + '@babel/runtime': 7.29.2 react: 19.2.4 '@radix-ui/react-use-layout-effect@1.0.1(@types/react@19.2.14)(react@19.2.4)': dependencies: - '@babel/runtime': 7.28.6 + '@babel/runtime': 7.29.2 react: 19.2.4 optionalDependencies: '@types/react': 19.2.14 @@ -12389,7 +12356,7 @@ snapshots: '@opentelemetry/api-logs': 0.203.0 '@opentelemetry/auto-instrumentations-node': 0.62.2(@opentelemetry/api@1.9.0)(@opentelemetry/core@2.6.0(@opentelemetry/api@1.9.0)) '@opentelemetry/exporter-metrics-otlp-http': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/resources': 2.5.1(@opentelemetry/api@1.9.0) + '@opentelemetry/resources': 2.6.0(@opentelemetry/api@1.9.0) '@opentelemetry/sdk-metrics': 2.2.0(@opentelemetry/api@1.9.0) '@opentelemetry/sdk-node': 0.203.0(@opentelemetry/api@1.9.0) '@opentelemetry/sdk-trace-node': 2.6.0(@opentelemetry/api@1.9.0) @@ -12417,7 +12384,7 @@ snapshots: js-xxhash: 4.0.0 json-custom-numbers: 3.1.1 kasi: 1.1.2 - nanoid: 5.1.6 + nanoid: 5.1.7 parse-prometheus-text-format: 1.1.1 pg-format: pg-format-fix@1.0.5 postgres: 3.4.7 @@ -12756,10 +12723,10 @@ snapshots: '@tabler/icons-react@3.37.1(react@19.2.4)': dependencies: - '@tabler/icons': 3.37.1 + '@tabler/icons': 3.41.1 react: 19.2.4 - '@tabler/icons@3.37.1': {} + '@tabler/icons@3.41.1': {} '@tailwindcss/node@4.2.1': dependencies: @@ -15875,8 +15842,6 @@ snapshots: nanoid@3.3.11: {} - nanoid@5.1.6: {} - nanoid@5.1.7: {} napi-build-utils@2.0.0: {} @@ -16256,7 +16221,7 @@ snapshots: '@opentelemetry/api': 1.9.0 '@opentelemetry/api-logs': 0.208.0 '@opentelemetry/exporter-logs-otlp-http': 0.208.0(@opentelemetry/api@1.9.0) - '@opentelemetry/resources': 2.5.1(@opentelemetry/api@1.9.0) + '@opentelemetry/resources': 2.6.0(@opentelemetry/api@1.9.0) '@opentelemetry/sdk-logs': 0.208.0(@opentelemetry/api@1.9.0) '@posthog/core': 1.23.1 '@posthog/types': 1.352.1 @@ -16323,7 +16288,7 @@ snapshots: property-information@7.1.0: {} - protobufjs@7.5.4: + protobufjs@7.5.5: dependencies: '@protobufjs/aspromise': 1.1.2 '@protobufjs/base64': 1.1.2 @@ -16560,7 +16525,7 @@ snapshots: react-syntax-highlighter@15.6.6(react@19.2.4): dependencies: - '@babel/runtime': 7.28.6 + '@babel/runtime': 7.29.2 highlight.js: 10.7.3 highlightjs-vue: 1.0.0 lowlight: 1.20.0 @@ -16645,7 +16610,7 @@ snapshots: redux@4.2.1: dependencies: - '@babel/runtime': 7.28.6 + '@babel/runtime': 7.29.2 reflect.getprototypeof@1.0.10: dependencies: