refactor(agents): consolidate chat runtime infra under chat/runtime

Move the lower-level runtime/infra modules out of multi_agent_chat/shared/
(they were never used by subagents, so they failed the shared-by-all-siblings
rule) and unify them with the already-relocated checkpointer:

  agents/runtime/                      -> agents/chat/runtime/
  mac/shared/errors.py                 -> chat/runtime/errors.py
  mac/shared/llm_config.py             -> chat/runtime/llm_config.py
  mac/shared/prompt_caching.py         -> chat/runtime/prompt_caching.py
  mac/shared/mention_resolver.py       -> chat/runtime/mention_resolver.py
  mac/shared/path_resolver.py          -> chat/runtime/path_resolver.py

These sit below the agent packages: the boundary + agent factory + shared
middleware depend on them, and they import no agent code (acyclic).
This commit is contained in:
CREDO23 2026-06-05 13:19:24 +02:00
parent 7d866a2279
commit f2a61bc0ef
52 changed files with 97 additions and 87 deletions

View file

@ -24,13 +24,13 @@ from typing import Any
from langchain.agents.middleware import AgentMiddleware, AgentState
from langgraph.runtime import Runtime
from app.agents.chat.multi_agent_chat.shared.path_resolver import (
DOCUMENTS_ROOT,
safe_filename,
)
from app.agents.chat.multi_agent_chat.shared.state.filesystem_state import (
SurfSenseFilesystemState,
)
from app.agents.chat.runtime.path_resolver import (
DOCUMENTS_ROOT,
safe_filename,
)
logger = logging.getLogger(__name__)

View file

@ -34,15 +34,15 @@ from langgraph.runtime import Runtime
from sqlalchemy import select
from app.agents.chat.multi_agent_chat.shared.filesystem_selection import FilesystemMode
from app.agents.chat.multi_agent_chat.shared.path_resolver import (
from app.agents.chat.multi_agent_chat.shared.state.filesystem_state import (
SurfSenseFilesystemState,
)
from app.agents.chat.runtime.path_resolver import (
DOCUMENTS_ROOT,
PathIndex,
build_path_index,
doc_to_virtual_path,
)
from app.agents.chat.multi_agent_chat.shared.state.filesystem_state import (
SurfSenseFilesystemState,
)
from app.db import Document, shielded_async_session
from app.utils.perf import get_perf_logger

View file

@ -20,13 +20,9 @@ from app.agents.chat.multi_agent_chat.shared.filesystem_selection import (
FilesystemMode,
FilesystemSelection,
)
from app.agents.chat.multi_agent_chat.shared.llm_config import AgentConfig
from app.agents.chat.multi_agent_chat.shared.middleware.filesystem.backends.resolver import (
build_backend_resolver,
)
from app.agents.chat.multi_agent_chat.shared.prompt_caching import (
apply_litellm_prompt_caching,
)
from app.agents.chat.multi_agent_chat.subagents import (
get_subagents_to_exclude,
main_prompt_registry_subagent_lines,
@ -34,6 +30,10 @@ from app.agents.chat.multi_agent_chat.subagents import (
from app.agents.chat.multi_agent_chat.subagents.mcp_tools.index import (
load_mcp_tools_by_connector,
)
from app.agents.chat.runtime.llm_config import AgentConfig
from app.agents.chat.runtime.prompt_caching import (
apply_litellm_prompt_caching,
)
from app.db import ChatVisibility
from app.services.connector_service import ConnectorService
from app.services.user_tool_allowlist import (

View file

@ -20,7 +20,7 @@ What this provides:
tools can poll to abort cooperatively. The event is reset between
turns. Tools should check ``runtime.context.cancel_event.is_set()``
in tight inner loops.
- A typed :class:`~app.agents.chat.multi_agent_chat.shared.errors.BusyError` raised when a
- A typed :class:`~app.agents.chat.runtime.errors.BusyError` raised when a
second turn arrives while the lock is held.
Note: SurfSense's ``stream_new_chat`` is the call site that should
@ -46,7 +46,7 @@ from langchain.agents.middleware.types import (
from langgraph.config import get_config
from langgraph.runtime import Runtime
from app.agents.chat.multi_agent_chat.shared.errors import BusyError
from app.agents.chat.runtime.errors import BusyError
logger = logging.getLogger(__name__)

View file

@ -45,7 +45,7 @@ from sqlalchemy.ext.asyncio import AsyncSession
from app.agents.chat.multi_agent_chat.shared.middleware.filesystem.backends.document_xml import (
build_document_xml,
)
from app.agents.chat.multi_agent_chat.shared.path_resolver import (
from app.agents.chat.runtime.path_resolver import (
DOCUMENTS_ROOT,
build_path_index,
doc_to_virtual_path,

View file

@ -3,7 +3,7 @@
from __future__ import annotations
from app.agents.chat.multi_agent_chat.shared.filesystem_selection import FilesystemMode
from app.agents.chat.multi_agent_chat.shared.path_resolver import DOCUMENTS_ROOT
from app.agents.chat.runtime.path_resolver import DOCUMENTS_ROOT
def is_cloud(mode: FilesystemMode) -> bool:

View file

@ -11,10 +11,10 @@ from typing import TYPE_CHECKING
from langchain.tools import ToolRuntime
from app.agents.chat.multi_agent_chat.shared.path_resolver import DOCUMENTS_ROOT
from app.agents.chat.multi_agent_chat.shared.state.filesystem_state import (
SurfSenseFilesystemState,
)
from app.agents.chat.runtime.path_resolver import DOCUMENTS_ROOT
from ..shared.paths import TEMP_PREFIX, basename
from .mode import is_cloud

View file

@ -10,10 +10,10 @@ from langchain_core.messages import ToolMessage
from langchain_core.tools import BaseTool, StructuredTool
from langgraph.types import Command
from app.agents.chat.multi_agent_chat.shared.path_resolver import DOCUMENTS_ROOT
from app.agents.chat.multi_agent_chat.shared.state.filesystem_state import (
SurfSenseFilesystemState,
)
from app.agents.chat.runtime.path_resolver import DOCUMENTS_ROOT
from ...middleware.async_dispatch import run_async_blocking
from ...middleware.path_resolution import resolve_relative

View file

@ -11,10 +11,10 @@ from langchain_core.messages import ToolMessage
from langchain_core.tools import BaseTool, StructuredTool
from langgraph.types import Command
from app.agents.chat.multi_agent_chat.shared.path_resolver import DOCUMENTS_ROOT
from app.agents.chat.multi_agent_chat.shared.state.filesystem_state import (
SurfSenseFilesystemState,
)
from app.agents.chat.runtime.path_resolver import DOCUMENTS_ROOT
from ...middleware.async_dispatch import run_async_blocking
from ...middleware.mode import is_cloud

View file

@ -11,11 +11,11 @@ from langgraph.types import Command
from app.agents.chat.multi_agent_chat.shared.middleware.filesystem.backends.kb_postgres import (
KBPostgresBackend,
)
from app.agents.chat.multi_agent_chat.shared.path_resolver import DOCUMENTS_ROOT
from app.agents.chat.multi_agent_chat.shared.state.filesystem_state import (
SurfSenseFilesystemState,
)
from app.agents.chat.multi_agent_chat.shared.state.reducers import _CLEAR
from app.agents.chat.runtime.path_resolver import DOCUMENTS_ROOT
if TYPE_CHECKING:
from ...middleware import SurfSenseFilesystemMiddleware

View file

@ -15,11 +15,11 @@ from langgraph.types import Command
from app.agents.chat.multi_agent_chat.shared.middleware.filesystem.backends.kb_postgres import (
KBPostgresBackend,
)
from app.agents.chat.multi_agent_chat.shared.path_resolver import DOCUMENTS_ROOT
from app.agents.chat.multi_agent_chat.shared.state.filesystem_state import (
SurfSenseFilesystemState,
)
from app.agents.chat.multi_agent_chat.shared.state.reducers import _CLEAR
from app.agents.chat.runtime.path_resolver import DOCUMENTS_ROOT
if TYPE_CHECKING:
from ...middleware import SurfSenseFilesystemMiddleware

View file

@ -16,11 +16,11 @@ from langgraph.types import Command
from app.agents.chat.multi_agent_chat.shared.middleware.filesystem.backends.kb_postgres import (
KBPostgresBackend,
)
from app.agents.chat.multi_agent_chat.shared.path_resolver import DOCUMENTS_ROOT
from app.agents.chat.multi_agent_chat.shared.state.filesystem_state import (
SurfSenseFilesystemState,
)
from app.agents.chat.multi_agent_chat.shared.state.reducers import _CLEAR
from app.agents.chat.runtime.path_resolver import DOCUMENTS_ROOT
from ...middleware.path_resolution import current_cwd
from ...shared.paths import is_ancestor_of

View file

@ -47,12 +47,6 @@ from sqlalchemy.ext.asyncio import AsyncSession
from app.agents.chat.multi_agent_chat.shared.feature_flags import get_flags
from app.agents.chat.multi_agent_chat.shared.filesystem_selection import FilesystemMode
from app.agents.chat.multi_agent_chat.shared.path_resolver import (
DOCUMENTS_ROOT,
parse_documents_path,
safe_folder_segment,
virtual_path_to_doc,
)
from app.agents.chat.multi_agent_chat.shared.receipts.receipt import (
Receipt,
make_receipt,
@ -61,6 +55,12 @@ from app.agents.chat.multi_agent_chat.shared.state.filesystem_state import (
SurfSenseFilesystemState,
)
from app.agents.chat.multi_agent_chat.shared.state.reducers import _CLEAR
from app.agents.chat.runtime.path_resolver import (
DOCUMENTS_ROOT,
parse_documents_path,
safe_folder_segment,
virtual_path_to_doc,
)
from app.db import (
AgentActionLog,
Chunk,

View file

@ -47,14 +47,14 @@ from app.agents.chat.multi_agent_chat.shared.date_filters import (
)
from app.agents.chat.multi_agent_chat.shared.feature_flags import get_flags
from app.agents.chat.multi_agent_chat.shared.filesystem_selection import FilesystemMode
from app.agents.chat.multi_agent_chat.shared.path_resolver import (
from app.agents.chat.multi_agent_chat.shared.state.filesystem_state import (
SurfSenseFilesystemState,
)
from app.agents.chat.runtime.path_resolver import (
PathIndex,
build_path_index,
doc_to_virtual_path,
)
from app.agents.chat.multi_agent_chat.shared.state.filesystem_state import (
SurfSenseFilesystemState,
)
from app.db import (
NATIVE_TO_LEGACY_DOCTYPE,
Chunk,

View file

@ -11,8 +11,8 @@ from typing import Any
from langchain_core.messages import ToolMessage
from app.agents.chat.multi_agent_chat.shared.errors import StreamingError
from app.agents.chat.multi_agent_chat.shared.permissions import Rule
from app.agents.chat.runtime.errors import StreamingError
def build_deny_message(tool_call: dict[str, Any], rule: Rule) -> ToolMessage:

View file

@ -26,8 +26,8 @@ from langchain_core.messages import AIMessage, ToolMessage
from langchain_core.tools import BaseTool
from langgraph.runtime import Runtime
from app.agents.chat.multi_agent_chat.shared.errors import CorrectedError, RejectedError
from app.agents.chat.multi_agent_chat.shared.permissions import Ruleset
from app.agents.chat.runtime.errors import CorrectedError, RejectedError
from app.services.user_tool_allowlist import TrustedToolSaver
from ..ask.edit import merge_edited_args

View file

@ -0,0 +1,16 @@
"""Lower-level runtime infrastructure for the chat agents.
Modules here are the foundation layer used to *run* chat agents: wired by the
boundary (routes/tasks) and/or imported by the agent factory + shared
middleware, but never part of any single agent's domain logic. Because they sit
below the agent packages, both the boundary and the agents may depend on them
(forward dependency), while they never import agent code.
Contents:
- ``checkpointer`` LangGraph Postgres checkpoint saver (boundary lifespan)
- ``llm_config`` LLM provider/model configuration resolution
- ``prompt_caching`` LiteLLM prompt-caching configuration
- ``errors`` agent-runtime error contracts (raised by MW, caught at boundary)
- ``path_resolver`` filesystem path resolution helpers
- ``mention_resolver`` @-mention resolution helpers
"""

View file

@ -27,7 +27,7 @@ from litellm import get_model_info
from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession
from app.agents.chat.multi_agent_chat.shared.prompt_caching import (
from app.agents.chat.runtime.prompt_caching import (
apply_litellm_prompt_caching,
)
from app.services.llm_router_service import (

View file

@ -36,7 +36,7 @@ from dataclasses import dataclass, field
from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession
from app.agents.chat.multi_agent_chat.shared.path_resolver import (
from app.agents.chat.runtime.path_resolver import (
DOCUMENTS_ROOT,
build_path_index,
doc_to_virtual_path,

View file

@ -68,7 +68,7 @@ from typing import TYPE_CHECKING, Any
from langchain_core.language_models import BaseChatModel
if TYPE_CHECKING:
from app.agents.chat.multi_agent_chat.shared.llm_config import AgentConfig
from app.agents.chat.runtime.llm_config import AgentConfig
logger = logging.getLogger(__name__)

View file

@ -1,6 +0,0 @@
"""Agent runtime infrastructure wired by the boundary (not agent code).
Modules here are cross-agent infra used to *run* agents (e.g. the LangGraph
Postgres checkpointer), as opposed to ``app/agents/shared/`` which holds code
imported by 2+ sibling agent packages.
"""

View file

@ -23,7 +23,7 @@ from starlette.requests import Request as StarletteRequest
from starlette.responses import Response as StarletteResponse
from uvicorn.middleware.proxy_headers import ProxyHeadersMiddleware
from app.agents.runtime.checkpointer import (
from app.agents.chat.runtime.checkpointer import (
close_checkpointer,
setup_checkpointer_tables,
)

View file

@ -11,7 +11,7 @@ from langgraph.types import Command
from sqlalchemy.ext.asyncio import AsyncSession
from app.agents.chat.multi_agent_chat import create_multi_agent_chat_deep_agent
from app.agents.chat.multi_agent_chat.shared.mention_resolver import (
from app.agents.chat.runtime.mention_resolver import (
resolve_mentions,
substitute_in_text,
)

View file

@ -39,7 +39,7 @@ def _is_premium_global(kind: ModelKind, config_id: int) -> bool:
cfg: dict | None = None
if kind == "llm":
from app.agents.chat.multi_agent_chat.shared.llm_config import (
from app.agents.chat.runtime.llm_config import (
load_global_llm_config_by_id,
)

View file

@ -236,7 +236,7 @@ async def stream_anonymous_chat(
detail="No-login mode is not enabled.",
)
from app.agents.chat.multi_agent_chat.shared.llm_config import (
from app.agents.chat.runtime.llm_config import (
AgentConfig,
create_chat_litellm_from_agent_config,
)
@ -352,7 +352,7 @@ async def stream_anonymous_chat(
from langchain_core.messages import AIMessage, HumanMessage
from app.agents.chat.anonymous_chat import create_anonymous_chat_agent
from app.agents.runtime.checkpointer import get_checkpointer
from app.agents.chat.runtime.checkpointer import get_checkpointer
from app.db import shielded_async_session
from app.services.new_streaming_service import VercelStreamingService
from app.services.token_tracking_service import start_turn

View file

@ -7,7 +7,7 @@ from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy.future import select
from sqlalchemy.orm import selectinload
from app.agents.chat.multi_agent_chat.shared.path_resolver import virtual_path_to_doc
from app.agents.chat.runtime.path_resolver import virtual_path_to_doc
from app.db import (
Chunk,
Document,

View file

@ -1934,7 +1934,7 @@ async def regenerate_response(
"""
from langchain_core.messages import HumanMessage
from app.agents.runtime.checkpointer import get_checkpointer
from app.agents.chat.runtime.checkpointer import get_checkpointer
try:
# Verify thread exists and user has permission

View file

@ -204,7 +204,7 @@ async def validate_llm_config(
if litellm_params:
litellm_kwargs.update(litellm_params)
from app.agents.chat.multi_agent_chat.shared.llm_config import (
from app.agents.chat.runtime.llm_config import (
SanitizedChatLiteLLM,
)
@ -381,7 +381,7 @@ async def get_search_space_llm_instance(
if disable_streaming:
litellm_kwargs["disable_streaming"] = True
from app.agents.chat.multi_agent_chat.shared.llm_config import (
from app.agents.chat.runtime.llm_config import (
SanitizedChatLiteLLM,
)
@ -462,7 +462,7 @@ async def get_search_space_llm_instance(
if disable_streaming:
litellm_kwargs["disable_streaming"] = True
from app.agents.chat.multi_agent_chat.shared.llm_config import (
from app.agents.chat.runtime.llm_config import (
SanitizedChatLiteLLM,
)
@ -586,7 +586,7 @@ async def get_vision_llm(
if global_cfg.get("litellm_params"):
litellm_kwargs.update(global_cfg["litellm_params"])
from app.agents.chat.multi_agent_chat.shared.llm_config import (
from app.agents.chat.runtime.llm_config import (
SanitizedChatLiteLLM,
)
@ -642,7 +642,7 @@ async def get_vision_llm(
if vision_cfg.litellm_params:
litellm_kwargs.update(vision_cfg.litellm_params)
from app.agents.chat.multi_agent_chat.shared.llm_config import (
from app.agents.chat.runtime.llm_config import (
SanitizedChatLiteLLM,
)
@ -689,7 +689,7 @@ def get_planner_llm() -> ChatLiteLLM | None:
Callers MUST fall back to their chat LLM when this returns ``None`` so
deployments without a planner config keep working unchanged.
"""
from app.agents.chat.multi_agent_chat.shared.llm_config import (
from app.agents.chat.runtime.llm_config import (
create_chat_litellm_from_config,
)

View file

@ -53,7 +53,7 @@ logger = logging.getLogger(__name__)
#
# Owned here because ``app.services.provider_capabilities`` is the
# only edge that's safe to call from ``app.config``'s YAML loader at
# class-body init time. ``app.agents.chat.multi_agent_chat.shared.llm_config`` re-exports
# class-body init time. ``app.agents.chat.runtime.llm_config`` re-exports
# this constant under the historical ``PROVIDER_MAP`` name; placing the
# map there directly would re-introduce the
# ``app.config -> ... -> deliverables/tools/generate_image ->

View file

@ -38,7 +38,7 @@ from typing import Any, Literal
from sqlalchemy import delete, select
from sqlalchemy.ext.asyncio import AsyncSession
from app.agents.chat.multi_agent_chat.shared.path_resolver import (
from app.agents.chat.runtime.path_resolver import (
DOCUMENTS_ROOT,
safe_filename,
safe_folder_segment,

View file

@ -12,7 +12,7 @@ from typing import Any
from app.agents.chat.multi_agent_chat.shared.filesystem_selection import (
FilesystemSelection,
)
from app.agents.chat.multi_agent_chat.shared.llm_config import AgentConfig
from app.agents.chat.runtime.llm_config import AgentConfig
from app.db import ChatVisibility
from app.services.connector_service import ConnectorService

View file

@ -7,11 +7,11 @@ import logging
import time
from typing import Any, Literal
from app.agents.chat.multi_agent_chat.shared.errors import BusyError
from app.agents.chat.multi_agent_chat.shared.middleware.busy_mutex import (
get_cancel_state,
is_cancel_requested,
)
from app.agents.chat.runtime.errors import BusyError
TURN_CANCELLING_INITIAL_DELAY_MS = 200
TURN_CANCELLING_BACKOFF_FACTOR = 2

View file

@ -29,7 +29,7 @@ from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy.future import select
from app.agents.chat.multi_agent_chat.shared.filesystem_selection import FilesystemMode
from app.agents.chat.multi_agent_chat.shared.mention_resolver import (
from app.agents.chat.runtime.mention_resolver import (
resolve_mentions,
substitute_in_text,
)

View file

@ -15,7 +15,7 @@ tells the user what to change.
from __future__ import annotations
from app.agents.chat.multi_agent_chat.shared.llm_config import AgentConfig
from app.agents.chat.runtime.llm_config import AgentConfig
from app.observability import otel as ot

View file

@ -30,7 +30,7 @@ from app.prompts import TITLE_GENERATION_PROMPT
from app.services.new_streaming_service import VercelStreamingService
if TYPE_CHECKING:
from app.agents.chat.multi_agent_chat.shared.llm_config import AgentConfig
from app.agents.chat.runtime.llm_config import AgentConfig
from app.services.token_tracking_service import TokenAccumulator

View file

@ -14,7 +14,7 @@ from typing import Any
from sqlalchemy.ext.asyncio import AsyncSession
from app.agents.chat.multi_agent_chat.shared.llm_config import (
from app.agents.chat.runtime.llm_config import (
AgentConfig,
create_chat_litellm_from_agent_config,
create_chat_litellm_from_config,

View file

@ -4,7 +4,7 @@ from __future__ import annotations
from sqlalchemy.ext.asyncio import AsyncSession
from app.agents.runtime.checkpointer import get_checkpointer
from app.agents.chat.runtime.checkpointer import get_checkpointer
from app.db import SearchSourceConnectorType
from app.services.connector_service import ConnectorService
@ -33,7 +33,7 @@ async def setup_connector_and_firecrawl(
async def get_chat_checkpointer():
"""Resolve the PostgreSQL checkpointer for persistent conversation memory.
Thin wrapper around ``app.agents.runtime.checkpointer.get_checkpointer`` so
Thin wrapper around ``app.agents.chat.runtime.checkpointer.get_checkpointer`` so
flow orchestrators can rely on a streaming-local symbol and we have a hook
point if the checkpointer source ever needs to vary per flow.
"""

View file

@ -19,7 +19,7 @@ from dataclasses import dataclass
from typing import TYPE_CHECKING
from uuid import UUID
from app.agents.chat.multi_agent_chat.shared.llm_config import AgentConfig
from app.agents.chat.runtime.llm_config import AgentConfig
from app.db import shielded_async_session
if TYPE_CHECKING:

View file

@ -14,7 +14,7 @@ import traceback
from collections.abc import Iterator
from typing import Any, Literal
from app.agents.chat.multi_agent_chat.shared.errors import BusyError
from app.agents.chat.runtime.errors import BusyError
from app.observability import metrics as ot_metrics, otel as ot
from app.services.new_streaming_service import VercelStreamingService
from app.tasks.chat.streaming.errors.classifier import classify_stream_exception

View file

@ -239,11 +239,11 @@ def _patch_llm_bindings() -> None:
chat_targets = [
(
"app.agents.chat.multi_agent_chat.shared.llm_config.create_chat_litellm_from_agent_config",
"app.agents.chat.runtime.llm_config.create_chat_litellm_from_agent_config",
fake_create_chat_litellm_from_agent_config,
),
(
"app.agents.chat.multi_agent_chat.shared.llm_config.create_chat_litellm_from_config",
"app.agents.chat.runtime.llm_config.create_chat_litellm_from_config",
fake_create_chat_litellm_from_config,
),
(

View file

@ -212,11 +212,11 @@ def _patch_llm_bindings() -> None:
chat_targets = [
(
"app.agents.chat.multi_agent_chat.shared.llm_config.create_chat_litellm_from_agent_config",
"app.agents.chat.runtime.llm_config.create_chat_litellm_from_agent_config",
fake_create_chat_litellm_from_agent_config,
),
(
"app.agents.chat.multi_agent_chat.shared.llm_config.create_chat_litellm_from_config",
"app.agents.chat.runtime.llm_config.create_chat_litellm_from_config",
fake_create_chat_litellm_from_config,
),
(

View file

@ -4,7 +4,6 @@ from __future__ import annotations
import pytest
from app.agents.chat.multi_agent_chat.shared.errors import BusyError
from app.agents.chat.multi_agent_chat.shared.middleware.busy_mutex import (
BusyMutexMiddleware,
end_turn,
@ -14,6 +13,7 @@ from app.agents.chat.multi_agent_chat.shared.middleware.busy_mutex import (
request_cancel,
reset_cancel,
)
from app.agents.chat.runtime.errors import BusyError
pytestmark = pytest.mark.unit

View file

@ -15,14 +15,14 @@ from unittest.mock import AsyncMock, MagicMock
import pytest
from app.agents.chat.multi_agent_chat.shared import mention_resolver
from app.agents.chat.multi_agent_chat.shared.mention_resolver import (
from app.agents.chat.runtime import mention_resolver
from app.agents.chat.runtime.mention_resolver import (
ResolvedMention,
ResolvedMentionSet,
resolve_mentions,
substitute_in_text,
)
from app.agents.chat.multi_agent_chat.shared.path_resolver import (
from app.agents.chat.runtime.path_resolver import (
DOCUMENTS_ROOT,
PathIndex,
)

View file

@ -7,7 +7,7 @@ from unittest.mock import AsyncMock, MagicMock
import pytest
from app.agents.chat.multi_agent_chat.shared.path_resolver import (
from app.agents.chat.runtime.path_resolver import (
DOCUMENTS_ROOT,
PathIndex,
doc_to_virtual_path,

View file

@ -1,5 +1,5 @@
r"""Tests for ``apply_litellm_prompt_caching`` in
:mod:`app.agents.chat.multi_agent_chat.shared.prompt_caching`.
:mod:`app.agents.chat.runtime.prompt_caching`.
The helper replaces the legacy ``AnthropicPromptCachingMiddleware`` (which
never activated for our LiteLLM stack) with LiteLLM-native multi-provider
@ -34,8 +34,8 @@ from typing import Any
import pytest
from app.agents.chat.multi_agent_chat.shared.llm_config import AgentConfig
from app.agents.chat.multi_agent_chat.shared.prompt_caching import (
from app.agents.chat.runtime.llm_config import AgentConfig
from app.agents.chat.runtime.prompt_caching import (
apply_litellm_prompt_caching,
)

View file

@ -44,7 +44,7 @@ def patched_globals(monkeypatch: pytest.MonkeyPatch):
-2: {"id": -2, "billing_tier": "free"},
}
monkeypatch.setattr(
"app.agents.chat.multi_agent_chat.shared.llm_config.load_global_llm_config_by_id",
"app.agents.chat.runtime.llm_config.load_global_llm_config_by_id",
lambda cid: llm_configs.get(cid),
)

View file

@ -12,7 +12,7 @@ from __future__ import annotations
from app.agents.chat.multi_agent_chat.main_agent.middleware.knowledge_tree.middleware import (
KnowledgeTreeMiddleware,
)
from app.agents.chat.multi_agent_chat.shared.path_resolver import DOCUMENTS_ROOT
from app.agents.chat.runtime.path_resolver import DOCUMENTS_ROOT
def _compute(folder_paths: list[str], doc_paths: list[str]) -> set[str]:
@ -88,7 +88,7 @@ class TestFormatTreeRendering:
folder_paths: list[str],
doc_specs: list[dict],
) -> str:
from app.agents.chat.multi_agent_chat.shared.path_resolver import PathIndex
from app.agents.chat.runtime.path_resolver import PathIndex
index = PathIndex(
folder_paths={i + 1: p for i, p in enumerate(folder_paths)},

View file

@ -227,7 +227,7 @@ global_llm_configs:
def test_agent_config_from_yaml_explicit_overrides_resolver():
from app.agents.chat.multi_agent_chat.shared.llm_config import AgentConfig
from app.agents.chat.runtime.llm_config import AgentConfig
cfg_text_only = AgentConfig.from_yaml_config(
{
@ -256,7 +256,7 @@ def test_agent_config_from_yaml_explicit_overrides_resolver():
def test_agent_config_from_yaml_unannotated_uses_resolver():
"""Without an explicit YAML key, AgentConfig defers to the catalog
resolver for ``gpt-4o`` LiteLLM's map says supports_vision=True."""
from app.agents.chat.multi_agent_chat.shared.llm_config import AgentConfig
from app.agents.chat.runtime.llm_config import AgentConfig
cfg = AgentConfig.from_yaml_config(
{
@ -275,7 +275,7 @@ def test_agent_config_auto_mode_supports_image_input():
so users can keep their selection on Auto with a vision-capable
deployment somewhere in the pool. The router's own `allowed_fails`
handles non-vision deployments via fallback."""
from app.agents.chat.multi_agent_chat.shared.llm_config import AgentConfig
from app.agents.chat.runtime.llm_config import AgentConfig
auto = AgentConfig.from_auto_mode()
assert auto.supports_image_input is True

View file

@ -61,7 +61,7 @@ async def test_get_vision_llm_global_openrouter_sets_api_base():
return_value=cfg,
),
patch(
"app.agents.chat.multi_agent_chat.shared.llm_config.SanitizedChatLiteLLM",
"app.agents.chat.runtime.llm_config.SanitizedChatLiteLLM",
new=FakeSanitized,
),
):