mirror of
https://github.com/MODSetter/SurfSense.git
synced 2026-06-06 20:15:17 +02:00
refactor(agents): colocate 8 main-agent-only middleware as per-concept folders
Each main-agent-only middleware now lives in its own folder under main_agent/middleware/<concept>/ with builder.py (flag-gated construction) + middleware.py (the impl), re-exported via __init__.py. This kills the cross-folder hop into agents/shared/middleware and keeps each middleware's two responsibilities (build vs behavior) as colocated siblings. Moved (impl from shared/middleware, builder from main_agent/middleware): action_log, anonymous_document, context_editing, doom_loop, knowledge_tree, noop_injection, otel_span, tool_call_repair. Impls moved verbatim (git rename, no body edits) so behavior is unchanged. Builders now import from the local .middleware sibling. stack.py import paths updated for the 3 renamed folders; shared middleware barrel trimmed; tests repointed (imports + patch targets).
This commit is contained in:
parent
fbd5ccc35a
commit
9493519c61
33 changed files with 149 additions and 83 deletions
|
|
@ -0,0 +1,10 @@
|
|||
"""Action-log middleware: audit row per tool call (impl + builder)."""
|
||||
|
||||
from .builder import build_action_log_mw
|
||||
from .middleware import ActionLogMiddleware, ToolDefinition
|
||||
|
||||
__all__ = [
|
||||
"ActionLogMiddleware",
|
||||
"ToolDefinition",
|
||||
"build_action_log_mw",
|
||||
]
|
||||
|
|
@ -4,10 +4,10 @@ from __future__ import annotations
|
|||
|
||||
import logging
|
||||
|
||||
from app.agents.shared.feature_flags import AgentFeatureFlags
|
||||
from app.agents.shared.middleware import ActionLogMiddleware
|
||||
|
||||
from app.agents.multi_agent_chat.shared.middleware.flags import enabled
|
||||
from app.agents.shared.feature_flags import AgentFeatureFlags
|
||||
|
||||
from .middleware import ActionLogMiddleware
|
||||
|
||||
|
||||
def build_action_log_mw(
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
"""Anonymous-document middleware: Redis hydration, cloud only (impl + builder)."""
|
||||
|
||||
from .builder import build_anonymous_doc_mw
|
||||
from .middleware import AnonymousDocumentMiddleware
|
||||
|
||||
__all__ = [
|
||||
"AnonymousDocumentMiddleware",
|
||||
"build_anonymous_doc_mw",
|
||||
]
|
||||
|
|
@ -3,7 +3,8 @@
|
|||
from __future__ import annotations
|
||||
|
||||
from app.agents.shared.filesystem_selection import FilesystemMode
|
||||
from app.agents.shared.middleware import AnonymousDocumentMiddleware
|
||||
|
||||
from .middleware import AnonymousDocumentMiddleware
|
||||
|
||||
|
||||
def build_anonymous_doc_mw(
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
"""Context-editing middleware: spill + clear-tool-uses passes (impl + builder)."""
|
||||
|
||||
from .builder import build_context_editing_mw
|
||||
from .middleware import (
|
||||
ClearToolUsesEdit,
|
||||
SpillingContextEditingMiddleware,
|
||||
SpillToBackendEdit,
|
||||
)
|
||||
|
||||
__all__ = [
|
||||
"ClearToolUsesEdit",
|
||||
"SpillToBackendEdit",
|
||||
"SpillingContextEditingMiddleware",
|
||||
"build_context_editing_mw",
|
||||
]
|
||||
|
|
@ -10,15 +10,15 @@ from langchain_core.tools import BaseTool
|
|||
from app.agents.multi_agent_chat.main_agent.context_prune.prune_tool_names import (
|
||||
safe_exclude_tools,
|
||||
)
|
||||
from app.agents.multi_agent_chat.shared.middleware.flags import enabled
|
||||
from app.agents.shared.feature_flags import AgentFeatureFlags
|
||||
from app.agents.shared.middleware import (
|
||||
|
||||
from .middleware import (
|
||||
ClearToolUsesEdit,
|
||||
SpillingContextEditingMiddleware,
|
||||
SpillToBackendEdit,
|
||||
)
|
||||
|
||||
from app.agents.multi_agent_chat.shared.middleware.flags import enabled
|
||||
|
||||
|
||||
def build_context_editing_mw(
|
||||
*,
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
"""Doom-loop middleware: detect repeated identical tool calls (impl + builder)."""
|
||||
|
||||
from .builder import build_doom_loop_mw
|
||||
from .middleware import DoomLoopMiddleware
|
||||
|
||||
__all__ = [
|
||||
"DoomLoopMiddleware",
|
||||
"build_doom_loop_mw",
|
||||
]
|
||||
|
|
@ -2,10 +2,10 @@
|
|||
|
||||
from __future__ import annotations
|
||||
|
||||
from app.agents.shared.feature_flags import AgentFeatureFlags
|
||||
from app.agents.shared.middleware import DoomLoopMiddleware
|
||||
|
||||
from app.agents.multi_agent_chat.shared.middleware.flags import enabled
|
||||
from app.agents.shared.feature_flags import AgentFeatureFlags
|
||||
|
||||
from .middleware import DoomLoopMiddleware
|
||||
|
||||
|
||||
def build_doom_loop_mw(flags: AgentFeatureFlags) -> DoomLoopMiddleware | None:
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
"""Knowledge-tree middleware: <workspace_tree> injection, cloud only (impl + builder)."""
|
||||
|
||||
from .builder import build_knowledge_tree_mw
|
||||
from .middleware import KnowledgeTreeMiddleware
|
||||
|
||||
__all__ = [
|
||||
"KnowledgeTreeMiddleware",
|
||||
"build_knowledge_tree_mw",
|
||||
]
|
||||
|
|
@ -5,7 +5,8 @@ from __future__ import annotations
|
|||
from langchain_core.language_models import BaseChatModel
|
||||
|
||||
from app.agents.shared.filesystem_selection import FilesystemMode
|
||||
from app.agents.shared.middleware import KnowledgeTreeMiddleware
|
||||
|
||||
from .middleware import KnowledgeTreeMiddleware
|
||||
|
||||
|
||||
def build_knowledge_tree_mw(
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
"""Noop-injection middleware: provider-compat _noop tool (impl + builder)."""
|
||||
|
||||
from .builder import build_noop_injection_mw
|
||||
from .middleware import NoopInjectionMiddleware
|
||||
|
||||
__all__ = [
|
||||
"NoopInjectionMiddleware",
|
||||
"build_noop_injection_mw",
|
||||
]
|
||||
|
|
@ -2,10 +2,10 @@
|
|||
|
||||
from __future__ import annotations
|
||||
|
||||
from app.agents.shared.feature_flags import AgentFeatureFlags
|
||||
from app.agents.shared.middleware import NoopInjectionMiddleware
|
||||
|
||||
from app.agents.multi_agent_chat.shared.middleware.flags import enabled
|
||||
from app.agents.shared.feature_flags import AgentFeatureFlags
|
||||
|
||||
from .middleware import NoopInjectionMiddleware
|
||||
|
||||
|
||||
def build_noop_injection_mw(flags: AgentFeatureFlags) -> NoopInjectionMiddleware | None:
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
"""OTel-span middleware: spans on model and tool calls (impl + builder)."""
|
||||
|
||||
from .builder import build_otel_mw
|
||||
from .middleware import OtelSpanMiddleware
|
||||
|
||||
__all__ = [
|
||||
"OtelSpanMiddleware",
|
||||
"build_otel_mw",
|
||||
]
|
||||
|
|
@ -2,10 +2,10 @@
|
|||
|
||||
from __future__ import annotations
|
||||
|
||||
from app.agents.shared.feature_flags import AgentFeatureFlags
|
||||
from app.agents.shared.middleware import OtelSpanMiddleware
|
||||
|
||||
from app.agents.multi_agent_chat.shared.middleware.flags import enabled
|
||||
from app.agents.shared.feature_flags import AgentFeatureFlags
|
||||
|
||||
from .middleware import OtelSpanMiddleware
|
||||
|
||||
|
||||
def build_otel_mw(flags: AgentFeatureFlags) -> OtelSpanMiddleware | None:
|
||||
|
|
@ -20,6 +20,24 @@ from langchain_core.language_models import BaseChatModel
|
|||
from langchain_core.tools import BaseTool
|
||||
from langgraph.types import Checkpointer
|
||||
|
||||
from app.agents.multi_agent_chat.shared.middleware.anthropic_cache import (
|
||||
build_anthropic_cache_mw,
|
||||
)
|
||||
from app.agents.multi_agent_chat.shared.middleware.compaction import build_compaction_mw
|
||||
from app.agents.multi_agent_chat.shared.middleware.kb_context_projection import (
|
||||
build_kb_context_projection_mw,
|
||||
)
|
||||
from app.agents.multi_agent_chat.shared.middleware.memory import build_memory_mw
|
||||
from app.agents.multi_agent_chat.shared.middleware.patch_tool_calls import (
|
||||
build_patch_tool_calls_mw,
|
||||
)
|
||||
from app.agents.multi_agent_chat.shared.middleware.permissions import (
|
||||
build_permission_mw,
|
||||
)
|
||||
from app.agents.multi_agent_chat.shared.middleware.resilience import (
|
||||
build_resilience_middlewares,
|
||||
)
|
||||
from app.agents.multi_agent_chat.shared.middleware.todos import build_todos_mw
|
||||
from app.agents.multi_agent_chat.subagents import (
|
||||
build_subagents,
|
||||
get_subagents_to_exclude,
|
||||
|
|
@ -31,12 +49,15 @@ from app.agents.multi_agent_chat.subagents.builtins.knowledge_base.agent import
|
|||
from app.agents.multi_agent_chat.subagents.builtins.knowledge_base.ask_knowledge_base_tool import (
|
||||
build_ask_knowledge_base_tool,
|
||||
)
|
||||
from app.agents.multi_agent_chat.subagents.shared.middleware.middleware_stack import (
|
||||
build_subagent_middleware_stack,
|
||||
)
|
||||
from app.agents.shared.feature_flags import AgentFeatureFlags
|
||||
from app.agents.shared.filesystem_selection import FilesystemMode
|
||||
from app.db import ChatVisibility
|
||||
|
||||
from .action_log import build_action_log_mw
|
||||
from .anonymous_doc import build_anonymous_doc_mw
|
||||
from .anonymous_document import build_anonymous_doc_mw
|
||||
from .busy_mutex import build_busy_mutex_mw
|
||||
from .checkpointed_subagent_middleware import (
|
||||
SurfSenseCheckpointedSubAgentMiddleware,
|
||||
|
|
@ -51,21 +72,10 @@ from .kb_persistence import build_kb_persistence_mw
|
|||
from .knowledge_priority import build_knowledge_priority_mw
|
||||
from .knowledge_tree import build_knowledge_tree_mw
|
||||
from .noop_injection import build_noop_injection_mw
|
||||
from .otel import build_otel_mw
|
||||
from .otel_span import build_otel_mw
|
||||
from .plugins import build_plugin_middlewares
|
||||
from .repair import build_repair_mw
|
||||
from .skills import build_skills_mw
|
||||
from app.agents.multi_agent_chat.shared.middleware.anthropic_cache import build_anthropic_cache_mw
|
||||
from app.agents.multi_agent_chat.shared.middleware.compaction import build_compaction_mw
|
||||
from app.agents.multi_agent_chat.shared.middleware.kb_context_projection import build_kb_context_projection_mw
|
||||
from app.agents.multi_agent_chat.shared.middleware.memory import build_memory_mw
|
||||
from app.agents.multi_agent_chat.shared.middleware.patch_tool_calls import build_patch_tool_calls_mw
|
||||
from app.agents.multi_agent_chat.shared.middleware.permissions import build_permission_mw
|
||||
from app.agents.multi_agent_chat.shared.middleware.resilience import build_resilience_middlewares
|
||||
from app.agents.multi_agent_chat.shared.middleware.todos import build_todos_mw
|
||||
from app.agents.multi_agent_chat.subagents.shared.middleware.middleware_stack import (
|
||||
build_subagent_middleware_stack,
|
||||
)
|
||||
from .tool_call_repair import build_repair_mw
|
||||
|
||||
|
||||
def build_main_agent_deepagent_middleware(
|
||||
|
|
|
|||
|
|
@ -0,0 +1,9 @@
|
|||
"""Tool-call-repair middleware: fix miscased/unknown tool names (impl + builder)."""
|
||||
|
||||
from .builder import build_repair_mw
|
||||
from .middleware import ToolCallNameRepairMiddleware
|
||||
|
||||
__all__ = [
|
||||
"ToolCallNameRepairMiddleware",
|
||||
"build_repair_mw",
|
||||
]
|
||||
|
|
@ -6,10 +6,10 @@ from collections.abc import Sequence
|
|||
|
||||
from langchain_core.tools import BaseTool
|
||||
|
||||
from app.agents.shared.feature_flags import AgentFeatureFlags
|
||||
from app.agents.shared.middleware import ToolCallNameRepairMiddleware
|
||||
|
||||
from app.agents.multi_agent_chat.shared.middleware.flags import enabled
|
||||
from app.agents.shared.feature_flags import AgentFeatureFlags
|
||||
|
||||
from .middleware import ToolCallNameRepairMiddleware
|
||||
|
||||
# deepagents-built-in tool names the repair pass treats as known.
|
||||
_DEEPAGENT_BUILTIN_TOOL_NAMES: frozenset[str] = frozenset(
|
||||
|
|
@ -1,23 +1,10 @@
|
|||
"""Middleware components for the SurfSense new chat agent."""
|
||||
"""Shared middleware components for the SurfSense chat agents."""
|
||||
|
||||
from app.agents.shared.middleware.action_log import (
|
||||
ActionLogMiddleware,
|
||||
ToolDefinition,
|
||||
)
|
||||
from app.agents.shared.middleware.anonymous_document import (
|
||||
AnonymousDocumentMiddleware,
|
||||
)
|
||||
from app.agents.shared.middleware.busy_mutex import BusyMutexMiddleware
|
||||
from app.agents.shared.middleware.compaction import (
|
||||
SurfSenseCompactionMiddleware,
|
||||
create_surfsense_compaction_middleware,
|
||||
)
|
||||
from app.agents.shared.middleware.context_editing import (
|
||||
ClearToolUsesEdit,
|
||||
SpillingContextEditingMiddleware,
|
||||
SpillToBackendEdit,
|
||||
)
|
||||
from app.agents.shared.middleware.doom_loop import DoomLoopMiddleware
|
||||
from app.agents.shared.middleware.kb_persistence import (
|
||||
KnowledgeBasePersistenceMiddleware,
|
||||
commit_staged_filesystem_state,
|
||||
|
|
@ -25,39 +12,20 @@ from app.agents.shared.middleware.kb_persistence import (
|
|||
from app.agents.shared.middleware.knowledge_search import (
|
||||
KnowledgePriorityMiddleware,
|
||||
)
|
||||
from app.agents.shared.middleware.knowledge_tree import (
|
||||
KnowledgeTreeMiddleware,
|
||||
)
|
||||
from app.agents.shared.middleware.memory_injection import (
|
||||
MemoryInjectionMiddleware,
|
||||
)
|
||||
from app.agents.shared.middleware.noop_injection import NoopInjectionMiddleware
|
||||
from app.agents.shared.middleware.otel_span import OtelSpanMiddleware
|
||||
from app.agents.shared.middleware.permission import PermissionMiddleware
|
||||
from app.agents.shared.middleware.retry_after import RetryAfterMiddleware
|
||||
from app.agents.shared.middleware.tool_call_repair import (
|
||||
ToolCallNameRepairMiddleware,
|
||||
)
|
||||
|
||||
__all__ = [
|
||||
"ActionLogMiddleware",
|
||||
"AnonymousDocumentMiddleware",
|
||||
"BusyMutexMiddleware",
|
||||
"ClearToolUsesEdit",
|
||||
"DoomLoopMiddleware",
|
||||
"KnowledgeBasePersistenceMiddleware",
|
||||
"KnowledgePriorityMiddleware",
|
||||
"KnowledgeTreeMiddleware",
|
||||
"MemoryInjectionMiddleware",
|
||||
"NoopInjectionMiddleware",
|
||||
"OtelSpanMiddleware",
|
||||
"PermissionMiddleware",
|
||||
"RetryAfterMiddleware",
|
||||
"SpillToBackendEdit",
|
||||
"SpillingContextEditingMiddleware",
|
||||
"SurfSenseCompactionMiddleware",
|
||||
"ToolCallNameRepairMiddleware",
|
||||
"ToolDefinition",
|
||||
"commit_staged_filesystem_state",
|
||||
"create_surfsense_compaction_middleware",
|
||||
]
|
||||
|
|
|
|||
|
|
@ -10,9 +10,11 @@ import pytest
|
|||
from langchain_core.messages import ToolMessage
|
||||
from langchain_core.tools import tool
|
||||
|
||||
from app.agents.multi_agent_chat.main_agent.middleware.action_log.middleware import (
|
||||
ActionLogMiddleware,
|
||||
ToolDefinition,
|
||||
)
|
||||
from app.agents.shared.feature_flags import AgentFeatureFlags
|
||||
from app.agents.shared.middleware.action_log import ActionLogMiddleware
|
||||
from app.agents.shared.middleware.action_log import ToolDefinition
|
||||
|
||||
|
||||
@dataclass
|
||||
|
|
@ -58,7 +60,7 @@ def _disabled_flags() -> AgentFeatureFlags:
|
|||
def patch_get_flags():
|
||||
def _patch(flags: AgentFeatureFlags):
|
||||
return patch(
|
||||
"app.agents.shared.middleware.action_log.get_flags",
|
||||
"app.agents.multi_agent_chat.main_agent.middleware.action_log.middleware.get_flags",
|
||||
return_value=flags,
|
||||
)
|
||||
|
||||
|
|
@ -360,7 +362,7 @@ class TestActionLogDispatch:
|
|||
patch_get_flags(_enabled_flags()),
|
||||
patch("app.db.shielded_async_session", side_effect=lambda: factory()),
|
||||
patch(
|
||||
"app.agents.shared.middleware.action_log.adispatch_custom_event",
|
||||
"app.agents.multi_agent_chat.main_agent.middleware.action_log.middleware.adispatch_custom_event",
|
||||
dispatch_mock,
|
||||
),
|
||||
):
|
||||
|
|
@ -395,7 +397,7 @@ class TestActionLogDispatch:
|
|||
patch_get_flags(_enabled_flags()),
|
||||
patch("app.db.shielded_async_session", side_effect=_exploding_session),
|
||||
patch(
|
||||
"app.agents.shared.middleware.action_log.adispatch_custom_event",
|
||||
"app.agents.multi_agent_chat.main_agent.middleware.action_log.middleware.adispatch_custom_event",
|
||||
dispatch_mock,
|
||||
),
|
||||
):
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ from typing import Any
|
|||
import pytest
|
||||
from langchain_core.messages import AIMessage, HumanMessage, ToolMessage
|
||||
|
||||
from app.agents.shared.middleware.context_editing import (
|
||||
from app.agents.multi_agent_chat.main_agent.middleware.context_editing.middleware import (
|
||||
SpillToBackendEdit,
|
||||
_build_spill_placeholder,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -5,7 +5,10 @@ from __future__ import annotations
|
|||
import pytest
|
||||
from langchain_core.messages import AIMessage
|
||||
|
||||
from app.agents.shared.middleware.doom_loop import DoomLoopMiddleware, _signature
|
||||
from app.agents.multi_agent_chat.main_agent.middleware.doom_loop.middleware import (
|
||||
DoomLoopMiddleware,
|
||||
_signature,
|
||||
)
|
||||
|
||||
pytestmark = pytest.mark.unit
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ from __future__ import annotations
|
|||
import pytest
|
||||
from langchain_core.messages import AIMessage, HumanMessage
|
||||
|
||||
from app.agents.shared.middleware.noop_injection import (
|
||||
from app.agents.multi_agent_chat.main_agent.middleware.noop_injection.middleware import (
|
||||
NOOP_TOOL_NAME,
|
||||
NoopInjectionMiddleware,
|
||||
_last_ai_has_tool_calls,
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ from unittest.mock import MagicMock
|
|||
import pytest
|
||||
from langchain_core.messages import AIMessage, ToolMessage
|
||||
|
||||
from app.agents.shared.middleware.otel_span import (
|
||||
from app.agents.multi_agent_chat.main_agent.middleware.otel_span.middleware import (
|
||||
OtelSpanMiddleware,
|
||||
_annotate_model_response,
|
||||
_annotate_tool_result,
|
||||
|
|
@ -206,13 +206,13 @@ class TestMiddlewareIntegration:
|
|||
duration_calls: list[dict[str, Any]] = []
|
||||
token_calls: list[dict[str, Any]] = []
|
||||
monkeypatch.setattr(
|
||||
"app.agents.shared.middleware.otel_span.ot_metrics.record_model_call_duration",
|
||||
"app.agents.multi_agent_chat.main_agent.middleware.otel_span.middleware.ot_metrics.record_model_call_duration",
|
||||
lambda duration_ms, **attrs: duration_calls.append(
|
||||
{"duration_ms": duration_ms, **attrs}
|
||||
),
|
||||
)
|
||||
monkeypatch.setattr(
|
||||
"app.agents.shared.middleware.otel_span.ot_metrics.record_model_token_usage",
|
||||
"app.agents.multi_agent_chat.main_agent.middleware.otel_span.middleware.ot_metrics.record_model_token_usage",
|
||||
lambda **attrs: token_calls.append(attrs),
|
||||
)
|
||||
|
||||
|
|
@ -257,11 +257,11 @@ class TestMiddlewareIntegration:
|
|||
|
||||
errors: list[str] = []
|
||||
monkeypatch.setattr(
|
||||
"app.agents.shared.middleware.otel_span.ot_metrics.record_tool_call_error",
|
||||
"app.agents.multi_agent_chat.main_agent.middleware.otel_span.middleware.ot_metrics.record_tool_call_error",
|
||||
lambda *, tool_name: errors.append(tool_name),
|
||||
)
|
||||
monkeypatch.setattr(
|
||||
"app.agents.shared.middleware.otel_span.ot_metrics.record_tool_call_duration",
|
||||
"app.agents.multi_agent_chat.main_agent.middleware.otel_span.middleware.ot_metrics.record_tool_call_duration",
|
||||
lambda *args, **kwargs: None,
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -5,10 +5,10 @@ from __future__ import annotations
|
|||
import pytest
|
||||
from langchain_core.messages import AIMessage
|
||||
|
||||
from app.agents.multi_agent_chat.main_agent.tools.invalid_tool import INVALID_TOOL_NAME
|
||||
from app.agents.shared.middleware.tool_call_repair import (
|
||||
from app.agents.multi_agent_chat.main_agent.middleware.tool_call_repair.middleware import (
|
||||
ToolCallNameRepairMiddleware,
|
||||
)
|
||||
from app.agents.multi_agent_chat.main_agent.tools.invalid_tool import INVALID_TOOL_NAME
|
||||
|
||||
pytestmark = pytest.mark.unit
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,9 @@ contract cannot silently regress.
|
|||
|
||||
from __future__ import annotations
|
||||
|
||||
from app.agents.shared.middleware.knowledge_tree import KnowledgeTreeMiddleware
|
||||
from app.agents.multi_agent_chat.main_agent.middleware.knowledge_tree.middleware import (
|
||||
KnowledgeTreeMiddleware,
|
||||
)
|
||||
from app.agents.shared.path_resolver import DOCUMENTS_ROOT
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue