refactor(agents): move filesystem_selection to app/agents/shared (slice 3a)

Promote the filesystem mode contracts (FilesystemMode, FilesystemSelection,
ClientPlatform, LocalFilesystemMount) out of `new_chat` into the cross-agent
`app/agents/shared` kernel.

Pure leaf consumed across the whole multi-agent filesystem middleware/tool tree,
the chat flows/monolith, routes and tests. git mv (content unchanged) + flipped
all ~48 importers. A re-export shim remains at new_chat/filesystem_selection.py
only for the not-yet-retired single-agent (chat_deepagent).

Also updated the stream parity test's annotation normalizer to strip the new
app.agents.shared.filesystem_selection. prefix (the dataclasses' __module__
changed with the move), keeping monolith<->flows signature parity intact.

Behavior-preserving: only import paths change. 1326 tests green.
This commit is contained in:
CREDO23 2026-06-04 12:28:20 +02:00
parent a975754e7d
commit 1b536b8aee
51 changed files with 110 additions and 86 deletions

View file

@ -16,7 +16,7 @@ from app.agents.multi_agent_chat.middleware.stack import (
)
from app.agents.shared.context import SurfSenseContextSchema
from app.agents.shared.feature_flags import AgentFeatureFlags
from app.agents.new_chat.filesystem_selection import FilesystemMode
from app.agents.shared.filesystem_selection import FilesystemMode
from app.db import ChatVisibility

View file

@ -18,7 +18,7 @@ from app.agents.new_chat.agent_cache import (
tools_signature,
)
from app.agents.shared.feature_flags import AgentFeatureFlags
from app.agents.new_chat.filesystem_selection import FilesystemMode
from app.agents.shared.filesystem_selection import FilesystemMode
from app.db import ChatVisibility
from ..graph.compile_graph_sync import build_compiled_agent_graph_sync

View file

@ -24,7 +24,7 @@ from app.agents.new_chat.connector_searchable_types import (
)
from app.agents.shared.feature_flags import AgentFeatureFlags, get_flags
from app.agents.new_chat.filesystem_backends import build_backend_resolver
from app.agents.new_chat.filesystem_selection import FilesystemMode, FilesystemSelection
from app.agents.shared.filesystem_selection import FilesystemMode, FilesystemSelection
from app.agents.new_chat.llm_config import AgentConfig
from app.agents.new_chat.prompt_caching import apply_litellm_prompt_caching
from app.agents.new_chat.tools.invalid_tool import INVALID_TOOL_NAME, invalid_tool

View file

@ -2,7 +2,7 @@
from __future__ import annotations
from app.agents.new_chat.filesystem_selection import FilesystemMode
from app.agents.shared.filesystem_selection import FilesystemMode
from app.agents.new_chat.middleware import AnonymousDocumentMiddleware

View file

@ -2,7 +2,7 @@
from __future__ import annotations
from app.agents.new_chat.filesystem_selection import FilesystemMode
from app.agents.shared.filesystem_selection import FilesystemMode
from app.agents.new_chat.middleware import KnowledgeBasePersistenceMiddleware

View file

@ -4,7 +4,7 @@ from __future__ import annotations
from langchain_core.language_models import BaseChatModel
from app.agents.new_chat.filesystem_selection import FilesystemMode
from app.agents.shared.filesystem_selection import FilesystemMode
from app.agents.new_chat.middleware import KnowledgePriorityMiddleware
from app.services.llm_service import get_planner_llm

View file

@ -4,7 +4,7 @@ from __future__ import annotations
from langchain_core.language_models import BaseChatModel
from app.agents.new_chat.filesystem_selection import FilesystemMode
from app.agents.shared.filesystem_selection import FilesystemMode
from app.agents.new_chat.middleware import KnowledgeTreeMiddleware

View file

@ -7,7 +7,7 @@ import logging
from deepagents.middleware.skills import SkillsMiddleware
from app.agents.shared.feature_flags import AgentFeatureFlags
from app.agents.new_chat.filesystem_selection import FilesystemMode
from app.agents.shared.filesystem_selection import FilesystemMode
from app.agents.new_chat.middleware import (
build_skills_backend_factory,
default_skills_sources,

View file

@ -4,7 +4,7 @@ from __future__ import annotations
from typing import Any
from app.agents.new_chat.filesystem_selection import FilesystemMode
from app.agents.shared.filesystem_selection import FilesystemMode
from .middleware import SurfSenseFilesystemMiddleware

View file

@ -7,7 +7,7 @@ from typing import Any
from deepagents import FilesystemMiddleware
from langchain_core.tools import BaseTool
from app.agents.new_chat.filesystem_selection import FilesystemMode
from app.agents.shared.filesystem_selection import FilesystemMode
from app.agents.new_chat.filesystem_state import SurfSenseFilesystemState
from app.agents.new_chat.sandbox import is_sandbox_enabled

View file

@ -2,7 +2,7 @@
from __future__ import annotations
from app.agents.new_chat.filesystem_selection import FilesystemMode
from app.agents.shared.filesystem_selection import FilesystemMode
from app.agents.new_chat.path_resolver import DOCUMENTS_ROOT

View file

@ -7,7 +7,7 @@ from typing import TYPE_CHECKING
from langchain.tools import ToolRuntime
from app.agents.new_chat.filesystem_selection import FilesystemMode
from app.agents.shared.filesystem_selection import FilesystemMode
from app.agents.new_chat.filesystem_state import SurfSenseFilesystemState
from app.agents.new_chat.middleware.multi_root_local_folder_backend import (
MultiRootLocalFolderBackend,

View file

@ -2,7 +2,7 @@
from __future__ import annotations
from app.agents.new_chat.filesystem_selection import FilesystemMode
from app.agents.shared.filesystem_selection import FilesystemMode
from .cloud import BODY as CLOUD_BODY
from .common import HEADER, SANDBOX_ADDENDUM

View file

@ -2,7 +2,7 @@
from __future__ import annotations
from app.agents.new_chat.filesystem_selection import FilesystemMode
from app.agents.shared.filesystem_selection import FilesystemMode
_DESCRIPTION = """Changes the current working directory (cwd).

View file

@ -2,7 +2,7 @@
from __future__ import annotations
from app.agents.new_chat.filesystem_selection import FilesystemMode
from app.agents.shared.filesystem_selection import FilesystemMode
_CLOUD_DESCRIPTION = """Performs exact string replacements in files.

View file

@ -2,7 +2,7 @@
from __future__ import annotations
from app.agents.new_chat.filesystem_selection import FilesystemMode
from app.agents.shared.filesystem_selection import FilesystemMode
_DESCRIPTION = """Executes Python code in an isolated sandbox environment.

View file

@ -2,7 +2,7 @@
from __future__ import annotations
from app.agents.new_chat.filesystem_selection import FilesystemMode
from app.agents.shared.filesystem_selection import FilesystemMode
_DESCRIPTION = """Find files matching a glob pattern.

View file

@ -2,7 +2,7 @@
from __future__ import annotations
from app.agents.new_chat.filesystem_selection import FilesystemMode
from app.agents.shared.filesystem_selection import FilesystemMode
_CLOUD_DESCRIPTION = """Search for a literal text pattern across files.

View file

@ -2,7 +2,7 @@
from __future__ import annotations
from app.agents.new_chat.filesystem_selection import FilesystemMode
from app.agents.shared.filesystem_selection import FilesystemMode
_CLOUD_DESCRIPTION = """Lists files/folders recursively in a single bounded call.

View file

@ -2,7 +2,7 @@
from __future__ import annotations
from app.agents.new_chat.filesystem_selection import FilesystemMode
from app.agents.shared.filesystem_selection import FilesystemMode
_CLOUD_DESCRIPTION = """Lists files and directories at the given path.

View file

@ -2,7 +2,7 @@
from __future__ import annotations
from app.agents.new_chat.filesystem_selection import FilesystemMode
from app.agents.shared.filesystem_selection import FilesystemMode
_CLOUD_DESCRIPTION = """Creates a directory under `/documents/`.

View file

@ -2,7 +2,7 @@
from __future__ import annotations
from app.agents.new_chat.filesystem_selection import FilesystemMode
from app.agents.shared.filesystem_selection import FilesystemMode
_CLOUD_DESCRIPTION = """Moves or renames a file or folder.

View file

@ -2,7 +2,7 @@
from __future__ import annotations
from app.agents.new_chat.filesystem_selection import FilesystemMode
from app.agents.shared.filesystem_selection import FilesystemMode
_DESCRIPTION = """Prints the current working directory."""

View file

@ -2,7 +2,7 @@
from __future__ import annotations
from app.agents.new_chat.filesystem_selection import FilesystemMode
from app.agents.shared.filesystem_selection import FilesystemMode
_DESCRIPTION = """Reads a file from the filesystem.

View file

@ -2,7 +2,7 @@
from __future__ import annotations
from app.agents.new_chat.filesystem_selection import FilesystemMode
from app.agents.shared.filesystem_selection import FilesystemMode
_CLOUD_DESCRIPTION = """Deletes a single file under `/documents/`.

View file

@ -2,7 +2,7 @@
from __future__ import annotations
from app.agents.new_chat.filesystem_selection import FilesystemMode
from app.agents.shared.filesystem_selection import FilesystemMode
_CLOUD_DESCRIPTION = """Deletes an empty directory under `/documents/`.

View file

@ -2,7 +2,7 @@
from __future__ import annotations
from app.agents.new_chat.filesystem_selection import FilesystemMode
from app.agents.shared.filesystem_selection import FilesystemMode
_CLOUD_DESCRIPTION = """Writes a new text file to the workspace.

View file

@ -32,7 +32,7 @@ from app.agents.multi_agent_chat.subagents.builtins.knowledge_base.ask_knowledge
build_ask_knowledge_base_tool,
)
from app.agents.shared.feature_flags import AgentFeatureFlags
from app.agents.new_chat.filesystem_selection import FilesystemMode
from app.agents.shared.filesystem_selection import FilesystemMode
from app.db import ChatVisibility
from .main_agent.action_log import build_action_log_mw

View file

@ -14,7 +14,7 @@ from langchain_core.language_models import BaseChatModel
from langchain_core.tools import BaseTool
from app.agents.multi_agent_chat.subagents.shared.spec import SurfSenseSubagentSpec
from app.agents.new_chat.filesystem_selection import FilesystemMode
from app.agents.shared.filesystem_selection import FilesystemMode
from app.agents.new_chat.permissions import Rule, Ruleset
from .middleware_stack import build_kb_middleware

View file

@ -29,7 +29,7 @@ from app.agents.multi_agent_chat.middleware.shared.permissions import (
build_permission_mw,
)
from app.agents.shared.feature_flags import AgentFeatureFlags
from app.agents.new_chat.filesystem_selection import FilesystemMode
from app.agents.shared.filesystem_selection import FilesystemMode
from app.agents.new_chat.permissions import Ruleset

View file

@ -3,7 +3,7 @@
from __future__ import annotations
from app.agents.multi_agent_chat.subagents.shared.md_file_reader import read_md_file
from app.agents.new_chat.filesystem_selection import FilesystemMode
from app.agents.shared.filesystem_selection import FilesystemMode
def load_system_prompt(filesystem_mode: FilesystemMode) -> str:

View file

@ -9,7 +9,7 @@ from deepagents.backends.protocol import BackendProtocol
from deepagents.backends.state import StateBackend
from langgraph.prebuilt.tool_node import ToolRuntime
from app.agents.new_chat.filesystem_selection import FilesystemMode, FilesystemSelection
from app.agents.shared.filesystem_selection import FilesystemMode, FilesystemSelection
from app.agents.new_chat.middleware.kb_postgres_backend import KBPostgresBackend
from app.agents.new_chat.middleware.multi_root_local_folder_backend import (
MultiRootLocalFolderBackend,

View file

@ -1,41 +1,24 @@
"""Filesystem mode contracts and selection helpers for chat sessions."""
"""Backward-compatible shim.
The filesystem mode contracts moved to :mod:`app.agents.shared.filesystem_selection`
as part of promoting the shared agent toolkit out of ``new_chat`` into the
cross-agent kernel. Import from there directly; this re-export keeps the
not-yet-retired single-agent stack working during the migration and will be
removed with it.
"""
from __future__ import annotations
from dataclasses import dataclass
from enum import StrEnum
from app.agents.shared.filesystem_selection import (
ClientPlatform,
FilesystemMode,
FilesystemSelection,
LocalFilesystemMount,
)
class FilesystemMode(StrEnum):
"""Supported filesystem backends for agent tool execution."""
CLOUD = "cloud"
DESKTOP_LOCAL_FOLDER = "desktop_local_folder"
class ClientPlatform(StrEnum):
"""Client runtime reported by the caller."""
WEB = "web"
DESKTOP = "desktop"
@dataclass(slots=True)
class LocalFilesystemMount:
"""Canonical mount mapping provided by desktop runtime."""
mount_id: str
root_path: str
@dataclass(slots=True)
class FilesystemSelection:
"""Resolved filesystem selection for a single chat request."""
mode: FilesystemMode = FilesystemMode.CLOUD
client_platform: ClientPlatform = ClientPlatform.WEB
local_mounts: tuple[LocalFilesystemMount, ...] = ()
@property
def is_local_mode(self) -> bool:
return self.mode == FilesystemMode.DESKTOP_LOCAL_FOLDER
__all__ = [
"ClientPlatform",
"FilesystemMode",
"FilesystemSelection",
"LocalFilesystemMount",
]

View file

@ -46,7 +46,7 @@ from langchain_core.messages import ToolMessage
from langchain_core.tools import BaseTool, StructuredTool
from langgraph.types import Command
from app.agents.new_chat.filesystem_selection import FilesystemMode
from app.agents.shared.filesystem_selection import FilesystemMode
from app.agents.new_chat.filesystem_state import SurfSenseFilesystemState
from app.agents.new_chat.middleware.kb_postgres_backend import (
KBPostgresBackend,

View file

@ -46,7 +46,7 @@ from sqlalchemy.exc import IntegrityError
from sqlalchemy.ext.asyncio import AsyncSession
from app.agents.shared.feature_flags import get_flags
from app.agents.new_chat.filesystem_selection import FilesystemMode
from app.agents.shared.filesystem_selection import FilesystemMode
from app.agents.new_chat.filesystem_state import SurfSenseFilesystemState
from app.agents.new_chat.path_resolver import (
DOCUMENTS_ROOT,

View file

@ -42,7 +42,7 @@ from pydantic import BaseModel, Field, ValidationError
from sqlalchemy import select
from app.agents.shared.feature_flags import get_flags
from app.agents.new_chat.filesystem_selection import FilesystemMode
from app.agents.shared.filesystem_selection import FilesystemMode
from app.agents.new_chat.filesystem_state import SurfSenseFilesystemState
from app.agents.new_chat.path_resolver import (
PathIndex,

View file

@ -33,7 +33,7 @@ from langchain_core.messages import SystemMessage
from langgraph.runtime import Runtime
from sqlalchemy import select
from app.agents.new_chat.filesystem_selection import FilesystemMode
from app.agents.shared.filesystem_selection import FilesystemMode
from app.agents.new_chat.filesystem_state import SurfSenseFilesystemState
from app.agents.new_chat.path_resolver import (
DOCUMENTS_ROOT,

View file

@ -0,0 +1,41 @@
"""Filesystem mode contracts and selection helpers for chat sessions."""
from __future__ import annotations
from dataclasses import dataclass
from enum import StrEnum
class FilesystemMode(StrEnum):
"""Supported filesystem backends for agent tool execution."""
CLOUD = "cloud"
DESKTOP_LOCAL_FOLDER = "desktop_local_folder"
class ClientPlatform(StrEnum):
"""Client runtime reported by the caller."""
WEB = "web"
DESKTOP = "desktop"
@dataclass(slots=True)
class LocalFilesystemMount:
"""Canonical mount mapping provided by desktop runtime."""
mount_id: str
root_path: str
@dataclass(slots=True)
class FilesystemSelection:
"""Resolved filesystem selection for a single chat request."""
mode: FilesystemMode = FilesystemMode.CLOUD
client_platform: ClientPlatform = ClientPlatform.WEB
local_mounts: tuple[LocalFilesystemMount, ...] = ()
@property
def is_local_mode(self) -> bool:
return self.mode == FilesystemMode.DESKTOP_LOCAL_FOLDER

View file

@ -24,7 +24,7 @@ from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy.future import select
from sqlalchemy.orm import selectinload
from app.agents.new_chat.filesystem_selection import (
from app.agents.shared.filesystem_selection import (
ClientPlatform,
FilesystemMode,
FilesystemSelection,

View file

@ -31,7 +31,7 @@ from app.agents.new_chat.chat_deepagent import create_surfsense_deep_agent
from app.agents.new_chat.checkpointer import get_checkpointer
from app.agents.shared.context import SurfSenseContextSchema
from app.agents.shared.errors import BusyError
from app.agents.new_chat.filesystem_selection import FilesystemMode, FilesystemSelection
from app.agents.shared.filesystem_selection import FilesystemMode, FilesystemSelection
from app.agents.new_chat.llm_config import (
AgentConfig,
create_chat_litellm_from_agent_config,

View file

@ -9,7 +9,7 @@ from __future__ import annotations
from typing import Any
from app.agents.new_chat.filesystem_selection import FilesystemSelection
from app.agents.shared.filesystem_selection import FilesystemSelection
from app.agents.new_chat.llm_config import AgentConfig
from app.db import ChatVisibility
from app.services.connector_service import ConnectorService

View file

@ -11,7 +11,7 @@ from __future__ import annotations
from collections.abc import AsyncGenerator
from typing import Any
from app.agents.new_chat.filesystem_selection import FilesystemMode
from app.agents.shared.filesystem_selection import FilesystemMode
from app.agents.new_chat.middleware.kb_persistence import (
commit_staged_filesystem_state,
)

View file

@ -28,7 +28,7 @@ from langchain_core.messages import HumanMessage
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy.future import select
from app.agents.new_chat.filesystem_selection import FilesystemMode
from app.agents.shared.filesystem_selection import FilesystemMode
from app.agents.new_chat.mention_resolver import resolve_mentions, substitute_in_text
from app.db import (
ChatVisibility,

View file

@ -31,7 +31,7 @@ import anyio
from app.agents.multi_agent_chat import create_multi_agent_chat_deep_agent
from app.agents.new_chat.chat_deepagent import create_surfsense_deep_agent
from app.agents.new_chat.filesystem_selection import FilesystemMode, FilesystemSelection
from app.agents.shared.filesystem_selection import FilesystemMode, FilesystemSelection
from app.agents.new_chat.middleware.busy_mutex import end_turn
from app.config import config as _app_config
from app.db import ChatVisibility, async_session_maker

View file

@ -25,7 +25,7 @@ import anyio
from app.agents.multi_agent_chat import create_multi_agent_chat_deep_agent
from app.agents.new_chat.chat_deepagent import create_surfsense_deep_agent
from app.agents.new_chat.filesystem_selection import FilesystemMode, FilesystemSelection
from app.agents.shared.filesystem_selection import FilesystemMode, FilesystemSelection
from app.agents.new_chat.middleware.busy_mutex import end_turn
from app.config import config as _app_config
from app.db import ChatVisibility, async_session_maker

View file

@ -15,7 +15,7 @@ from __future__ import annotations
from collections.abc import AsyncGenerator, Awaitable, Callable
from typing import Any
from app.agents.new_chat.filesystem_selection import FilesystemMode
from app.agents.shared.filesystem_selection import FilesystemMode
from app.services.new_streaming_service import VercelStreamingService
from app.tasks.chat.streaming.agent.event_loop import stream_agent_events
from app.tasks.chat.streaming.shared.stream_result import StreamResult