mirror of
https://github.com/MODSetter/SurfSense.git
synced 2026-05-19 18:45:15 +02:00
subagents/knowledge_base: wire KB specialist into orchestrator (renderer/projector split, FS middleware stack, cloud-mode gating)
This commit is contained in:
parent
09fc99c435
commit
df2afed18d
10 changed files with 230 additions and 41 deletions
|
|
@ -24,4 +24,5 @@ def build_knowledge_priority_mw(
|
|||
available_connectors=available_connectors,
|
||||
available_document_types=available_document_types,
|
||||
mentioned_document_ids=mentioned_document_ids,
|
||||
inject_system_message=False,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -20,4 +20,5 @@ def build_knowledge_tree_mw(
|
|||
search_space_id=search_space_id,
|
||||
filesystem_mode=filesystem_mode,
|
||||
llm=llm,
|
||||
inject_system_message=False,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,54 @@
|
|||
"""Project ``workspace_tree_text`` + ``kb_priority`` from state into SystemMessages."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
|
||||
from langchain.agents.middleware import AgentMiddleware, AgentState
|
||||
from langchain_core.messages import SystemMessage
|
||||
from langgraph.runtime import Runtime
|
||||
|
||||
from app.agents.new_chat.filesystem_state import SurfSenseFilesystemState
|
||||
from app.agents.new_chat.middleware.knowledge_search import _render_priority_message
|
||||
|
||||
|
||||
class KbContextProjectionMiddleware(AgentMiddleware): # type: ignore[type-arg]
|
||||
"""Emit ``<workspace_tree>`` + ``<priority_documents>`` from shared state.
|
||||
|
||||
Read-only consumer: no DB, no LLM, no state writes. The orchestrator's
|
||||
renderer middlewares populate the source fields; this projection lets any
|
||||
agent (orchestrator or subagent) put the same content in front of its
|
||||
own LLM call.
|
||||
"""
|
||||
|
||||
tools = ()
|
||||
state_schema = SurfSenseFilesystemState
|
||||
|
||||
def before_agent( # type: ignore[override]
|
||||
self,
|
||||
state: AgentState,
|
||||
runtime: Runtime[Any],
|
||||
) -> dict[str, Any] | None:
|
||||
del runtime
|
||||
tree_text = state.get("workspace_tree_text")
|
||||
priority = state.get("kb_priority")
|
||||
if not tree_text and not priority:
|
||||
return None
|
||||
|
||||
messages = list(state.get("messages") or [])
|
||||
insert_at = max(len(messages) - 1, 0)
|
||||
if tree_text:
|
||||
messages.insert(insert_at, SystemMessage(content=tree_text))
|
||||
if priority:
|
||||
messages.insert(insert_at, _render_priority_message(priority))
|
||||
return {"messages": messages}
|
||||
|
||||
|
||||
def build_kb_context_projection_mw() -> KbContextProjectionMiddleware:
|
||||
return KbContextProjectionMiddleware()
|
||||
|
||||
|
||||
__all__ = [
|
||||
"KbContextProjectionMiddleware",
|
||||
"build_kb_context_projection_mw",
|
||||
]
|
||||
|
|
@ -19,6 +19,9 @@ from app.agents.multi_agent_chat.subagents import (
|
|||
from app.agents.multi_agent_chat.subagents.builtins.general_purpose.agent import (
|
||||
build_subagent as build_general_purpose_subagent,
|
||||
)
|
||||
from app.agents.multi_agent_chat.subagents.builtins.knowledge_base.agent import (
|
||||
build_subagent as build_knowledge_base_subagent,
|
||||
)
|
||||
from app.agents.multi_agent_chat.subagents.shared.permissions import ToolsPermissions
|
||||
from app.agents.new_chat.feature_flags import AgentFeatureFlags
|
||||
from app.agents.new_chat.filesystem_selection import FilesystemMode
|
||||
|
|
@ -45,6 +48,7 @@ from .shared.anthropic_cache import build_anthropic_cache_mw
|
|||
from .shared.compaction import build_compaction_mw
|
||||
from .shared.file_intent import build_file_intent_mw
|
||||
from .shared.filesystem import build_filesystem_mw
|
||||
from .shared.kb_context_projection import build_kb_context_projection_mw
|
||||
from .shared.memory import build_memory_mw
|
||||
from .shared.patch_tool_calls import build_patch_tool_calls_mw
|
||||
from .shared.permissions import (
|
||||
|
|
@ -106,6 +110,21 @@ def build_main_agent_deepagent_middleware(
|
|||
memory_mw=memory_mw,
|
||||
)
|
||||
|
||||
# Cloud-only: KB filesystem operations are delegated to a specialist subagent.
|
||||
# Desktop mode keeps FS on the main agent (see kb_main_strip).
|
||||
knowledge_base_subagent: SubAgent | None = None
|
||||
if filesystem_mode == FilesystemMode.CLOUD:
|
||||
knowledge_base_subagent = build_knowledge_base_subagent(
|
||||
llm=llm,
|
||||
backend_resolver=backend_resolver,
|
||||
filesystem_mode=filesystem_mode,
|
||||
search_space_id=search_space_id,
|
||||
user_id=user_id,
|
||||
thread_id=thread_id,
|
||||
permissions=permissions,
|
||||
resilience=resilience,
|
||||
)
|
||||
|
||||
subagents_registry: list[SubAgent] = []
|
||||
try:
|
||||
subagent_extras = build_subagent_extras(
|
||||
|
|
@ -132,7 +151,10 @@ def build_main_agent_deepagent_middleware(
|
|||
)
|
||||
subagents_registry = []
|
||||
|
||||
subagents: list[SubAgent] = [general_purpose_subagent, *subagents_registry]
|
||||
subagents: list[SubAgent] = [general_purpose_subagent]
|
||||
if knowledge_base_subagent is not None:
|
||||
subagents.append(knowledge_base_subagent)
|
||||
subagents.extend(subagents_registry)
|
||||
|
||||
stack: list[Any] = [
|
||||
build_busy_mutex_mw(flags),
|
||||
|
|
@ -155,6 +177,7 @@ def build_main_agent_deepagent_middleware(
|
|||
available_document_types=available_document_types,
|
||||
mentioned_document_ids=mentioned_document_ids,
|
||||
),
|
||||
build_kb_context_projection_mw(),
|
||||
build_file_intent_mw(llm),
|
||||
build_filesystem_mw(
|
||||
backend_resolver=backend_resolver,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue