mirror of
https://github.com/MODSetter/SurfSense.git
synced 2026-05-09 07:42:39 +02:00
feat: updated agent harness
This commit is contained in:
parent
9ec9b64348
commit
31a372bb84
139 changed files with 12583 additions and 1111 deletions
52
surfsense_backend/app/agents/new_chat/tools/invalid_tool.py
Normal file
52
surfsense_backend/app/agents/new_chat/tools/invalid_tool.py
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
"""
|
||||
The ``invalid`` fallback tool.
|
||||
|
||||
When the model emits a tool call whose name doesn't match any registered
|
||||
tool, :class:`ToolCallNameRepairMiddleware` rewrites the call to ``invalid``
|
||||
with the original name and a parser/validation error string. This tool's
|
||||
execution then returns that error to the model so it can self-correct.
|
||||
|
||||
Mirrors ``opencode/packages/opencode/src/tool/invalid.ts``. Tier 1.6 in
|
||||
the OpenCode-port plan.
|
||||
|
||||
Critically, the :class:`ToolDefinition` for this tool is **excluded** from
|
||||
the system-prompt tool list and from ``LLMToolSelectorMiddleware`` selection
|
||||
(see ``ToolDefinition.always_include`` filtering in the registry) — the
|
||||
model never advertises ``invalid`` as a callable. It only ever shows up
|
||||
in the tool registry so LangGraph can dispatch the rewritten call.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from langchain_core.tools import tool
|
||||
|
||||
INVALID_TOOL_NAME = "invalid"
|
||||
INVALID_TOOL_DESCRIPTION = "Do not use"
|
||||
|
||||
|
||||
def _format_invalid_message(tool: str | None, error: str | None) -> str:
|
||||
"""Return the user-visible error string. Mirrors ``invalid.ts``."""
|
||||
name = tool or "<unknown>"
|
||||
detail = error or "(no error message provided)"
|
||||
return (
|
||||
f"The arguments provided to the tool `{name}` are invalid: {detail}\n"
|
||||
f"Read the tool's docstring carefully and try again with valid arguments."
|
||||
)
|
||||
|
||||
|
||||
@tool(name_or_callable=INVALID_TOOL_NAME, description=INVALID_TOOL_DESCRIPTION)
|
||||
def invalid_tool(tool: str | None = None, error: str | None = None) -> str:
|
||||
"""Return a human-readable explanation of a tool-call validation failure.
|
||||
|
||||
Activated only when :class:`ToolCallNameRepairMiddleware` rewrites a
|
||||
failed tool call to ``invalid`` with the original tool name and the
|
||||
error message produced during validation.
|
||||
"""
|
||||
return _format_invalid_message(tool, error)
|
||||
|
||||
|
||||
__all__ = [
|
||||
"INVALID_TOOL_DESCRIPTION",
|
||||
"INVALID_TOOL_NAME",
|
||||
"invalid_tool",
|
||||
]
|
||||
|
|
@ -43,6 +43,9 @@ from typing import Any
|
|||
|
||||
from langchain_core.tools import BaseTool
|
||||
|
||||
from app.agents.new_chat.middleware.dedup_tool_calls import (
|
||||
wrap_dedup_key_by_arg_name,
|
||||
)
|
||||
from app.db import ChatVisibility
|
||||
|
||||
from .confluence import (
|
||||
|
|
@ -125,6 +128,14 @@ class ToolDefinition:
|
|||
enabled_by_default: Whether the tool is enabled when no explicit config is provided
|
||||
required_connector: Searchable type string (e.g. ``"LINEAR_CONNECTOR"``)
|
||||
that must be in ``available_connectors`` for the tool to be enabled.
|
||||
dedup_key: Optional callable that maps a tool's ``args`` dict to a
|
||||
string signature used by :class:`DedupHITLToolCallsMiddleware`
|
||||
to drop duplicate calls. Replaces the legacy hardcoded
|
||||
``_NATIVE_HITL_TOOL_DEDUP_KEYS`` map (Tier 2.3 in the
|
||||
OpenCode-port plan).
|
||||
reverse: Optional callable that, given the tool's ``(args, result)``,
|
||||
returns a ``ReverseDescriptor`` describing the inverse tool
|
||||
invocation. Consumed by the snapshot/revert pipeline (Tier 5).
|
||||
|
||||
"""
|
||||
|
||||
|
|
@ -135,6 +146,8 @@ class ToolDefinition:
|
|||
enabled_by_default: bool = True
|
||||
hidden: bool = False
|
||||
required_connector: str | None = None
|
||||
dedup_key: Callable[[dict[str, Any]], str] | None = None
|
||||
reverse: Callable[[dict[str, Any], Any], dict[str, Any]] | None = None
|
||||
|
||||
|
||||
# =============================================================================
|
||||
|
|
@ -288,6 +301,7 @@ BUILTIN_TOOLS: list[ToolDefinition] = [
|
|||
),
|
||||
requires=["db_session", "search_space_id", "user_id"],
|
||||
required_connector="NOTION_CONNECTOR",
|
||||
dedup_key=wrap_dedup_key_by_arg_name("title"),
|
||||
),
|
||||
ToolDefinition(
|
||||
name="update_notion_page",
|
||||
|
|
@ -299,6 +313,7 @@ BUILTIN_TOOLS: list[ToolDefinition] = [
|
|||
),
|
||||
requires=["db_session", "search_space_id", "user_id"],
|
||||
required_connector="NOTION_CONNECTOR",
|
||||
dedup_key=wrap_dedup_key_by_arg_name("page_title"),
|
||||
),
|
||||
ToolDefinition(
|
||||
name="delete_notion_page",
|
||||
|
|
@ -310,6 +325,7 @@ BUILTIN_TOOLS: list[ToolDefinition] = [
|
|||
),
|
||||
requires=["db_session", "search_space_id", "user_id"],
|
||||
required_connector="NOTION_CONNECTOR",
|
||||
dedup_key=wrap_dedup_key_by_arg_name("page_title"),
|
||||
),
|
||||
# =========================================================================
|
||||
# GOOGLE DRIVE TOOLS - create files, delete files
|
||||
|
|
@ -325,6 +341,7 @@ BUILTIN_TOOLS: list[ToolDefinition] = [
|
|||
),
|
||||
requires=["db_session", "search_space_id", "user_id"],
|
||||
required_connector="GOOGLE_DRIVE_FILE",
|
||||
dedup_key=wrap_dedup_key_by_arg_name("file_name"),
|
||||
),
|
||||
ToolDefinition(
|
||||
name="delete_google_drive_file",
|
||||
|
|
@ -336,6 +353,7 @@ BUILTIN_TOOLS: list[ToolDefinition] = [
|
|||
),
|
||||
requires=["db_session", "search_space_id", "user_id"],
|
||||
required_connector="GOOGLE_DRIVE_FILE",
|
||||
dedup_key=wrap_dedup_key_by_arg_name("file_name"),
|
||||
),
|
||||
# =========================================================================
|
||||
# DROPBOX TOOLS - create and trash files
|
||||
|
|
@ -351,6 +369,7 @@ BUILTIN_TOOLS: list[ToolDefinition] = [
|
|||
),
|
||||
requires=["db_session", "search_space_id", "user_id"],
|
||||
required_connector="DROPBOX_FILE",
|
||||
dedup_key=wrap_dedup_key_by_arg_name("file_name"),
|
||||
),
|
||||
ToolDefinition(
|
||||
name="delete_dropbox_file",
|
||||
|
|
@ -362,6 +381,7 @@ BUILTIN_TOOLS: list[ToolDefinition] = [
|
|||
),
|
||||
requires=["db_session", "search_space_id", "user_id"],
|
||||
required_connector="DROPBOX_FILE",
|
||||
dedup_key=wrap_dedup_key_by_arg_name("file_name"),
|
||||
),
|
||||
# =========================================================================
|
||||
# ONEDRIVE TOOLS - create and trash files
|
||||
|
|
@ -377,6 +397,7 @@ BUILTIN_TOOLS: list[ToolDefinition] = [
|
|||
),
|
||||
requires=["db_session", "search_space_id", "user_id"],
|
||||
required_connector="ONEDRIVE_FILE",
|
||||
dedup_key=wrap_dedup_key_by_arg_name("file_name"),
|
||||
),
|
||||
ToolDefinition(
|
||||
name="delete_onedrive_file",
|
||||
|
|
@ -388,6 +409,7 @@ BUILTIN_TOOLS: list[ToolDefinition] = [
|
|||
),
|
||||
requires=["db_session", "search_space_id", "user_id"],
|
||||
required_connector="ONEDRIVE_FILE",
|
||||
dedup_key=wrap_dedup_key_by_arg_name("file_name"),
|
||||
),
|
||||
# =========================================================================
|
||||
# GOOGLE CALENDAR TOOLS - search, create, update, delete events
|
||||
|
|
@ -414,6 +436,7 @@ BUILTIN_TOOLS: list[ToolDefinition] = [
|
|||
),
|
||||
requires=["db_session", "search_space_id", "user_id"],
|
||||
required_connector="GOOGLE_CALENDAR_CONNECTOR",
|
||||
dedup_key=wrap_dedup_key_by_arg_name("title"),
|
||||
),
|
||||
ToolDefinition(
|
||||
name="update_calendar_event",
|
||||
|
|
@ -425,6 +448,7 @@ BUILTIN_TOOLS: list[ToolDefinition] = [
|
|||
),
|
||||
requires=["db_session", "search_space_id", "user_id"],
|
||||
required_connector="GOOGLE_CALENDAR_CONNECTOR",
|
||||
dedup_key=wrap_dedup_key_by_arg_name("event_title_or_id"),
|
||||
),
|
||||
ToolDefinition(
|
||||
name="delete_calendar_event",
|
||||
|
|
@ -436,6 +460,7 @@ BUILTIN_TOOLS: list[ToolDefinition] = [
|
|||
),
|
||||
requires=["db_session", "search_space_id", "user_id"],
|
||||
required_connector="GOOGLE_CALENDAR_CONNECTOR",
|
||||
dedup_key=wrap_dedup_key_by_arg_name("event_title_or_id"),
|
||||
),
|
||||
# =========================================================================
|
||||
# GMAIL TOOLS - search, read, create drafts, update drafts, send, trash
|
||||
|
|
@ -473,6 +498,7 @@ BUILTIN_TOOLS: list[ToolDefinition] = [
|
|||
),
|
||||
requires=["db_session", "search_space_id", "user_id"],
|
||||
required_connector="GOOGLE_GMAIL_CONNECTOR",
|
||||
dedup_key=wrap_dedup_key_by_arg_name("subject"),
|
||||
),
|
||||
ToolDefinition(
|
||||
name="send_gmail_email",
|
||||
|
|
@ -484,6 +510,7 @@ BUILTIN_TOOLS: list[ToolDefinition] = [
|
|||
),
|
||||
requires=["db_session", "search_space_id", "user_id"],
|
||||
required_connector="GOOGLE_GMAIL_CONNECTOR",
|
||||
dedup_key=wrap_dedup_key_by_arg_name("subject"),
|
||||
),
|
||||
ToolDefinition(
|
||||
name="trash_gmail_email",
|
||||
|
|
@ -495,6 +522,7 @@ BUILTIN_TOOLS: list[ToolDefinition] = [
|
|||
),
|
||||
requires=["db_session", "search_space_id", "user_id"],
|
||||
required_connector="GOOGLE_GMAIL_CONNECTOR",
|
||||
dedup_key=wrap_dedup_key_by_arg_name("email_subject_or_id"),
|
||||
),
|
||||
ToolDefinition(
|
||||
name="update_gmail_draft",
|
||||
|
|
@ -506,6 +534,7 @@ BUILTIN_TOOLS: list[ToolDefinition] = [
|
|||
),
|
||||
requires=["db_session", "search_space_id", "user_id"],
|
||||
required_connector="GOOGLE_GMAIL_CONNECTOR",
|
||||
dedup_key=wrap_dedup_key_by_arg_name("draft_subject_or_id"),
|
||||
),
|
||||
# =========================================================================
|
||||
# CONFLUENCE TOOLS - create, update, delete pages
|
||||
|
|
@ -521,6 +550,7 @@ BUILTIN_TOOLS: list[ToolDefinition] = [
|
|||
),
|
||||
requires=["db_session", "search_space_id", "user_id"],
|
||||
required_connector="CONFLUENCE_CONNECTOR",
|
||||
dedup_key=wrap_dedup_key_by_arg_name("title"),
|
||||
),
|
||||
ToolDefinition(
|
||||
name="update_confluence_page",
|
||||
|
|
@ -532,6 +562,7 @@ BUILTIN_TOOLS: list[ToolDefinition] = [
|
|||
),
|
||||
requires=["db_session", "search_space_id", "user_id"],
|
||||
required_connector="CONFLUENCE_CONNECTOR",
|
||||
dedup_key=wrap_dedup_key_by_arg_name("page_title_or_id"),
|
||||
),
|
||||
ToolDefinition(
|
||||
name="delete_confluence_page",
|
||||
|
|
@ -543,6 +574,7 @@ BUILTIN_TOOLS: list[ToolDefinition] = [
|
|||
),
|
||||
requires=["db_session", "search_space_id", "user_id"],
|
||||
required_connector="CONFLUENCE_CONNECTOR",
|
||||
dedup_key=wrap_dedup_key_by_arg_name("page_title_or_id"),
|
||||
),
|
||||
# =========================================================================
|
||||
# DISCORD TOOLS - list channels, read messages, send messages
|
||||
|
|
@ -755,6 +787,24 @@ def build_tools(
|
|||
|
||||
# Create the tool
|
||||
tool = tool_def.factory(dependencies)
|
||||
# Propagate the registry-level metadata so middleware (e.g.
|
||||
# ``DedupHITLToolCallsMiddleware``) and the action-log/revert
|
||||
# pipeline can pick the resolvers up via ``tool.metadata`` without
|
||||
# re-importing :data:`BUILTIN_TOOLS`.
|
||||
if tool_def.dedup_key is not None or tool_def.reverse is not None:
|
||||
existing_meta = getattr(tool, "metadata", None) or {}
|
||||
merged_meta = dict(existing_meta)
|
||||
if tool_def.dedup_key is not None:
|
||||
merged_meta.setdefault("dedup_key", tool_def.dedup_key)
|
||||
if tool_def.reverse is not None:
|
||||
merged_meta.setdefault("reverse", tool_def.reverse)
|
||||
try:
|
||||
tool.metadata = merged_meta
|
||||
except Exception:
|
||||
logger.debug(
|
||||
"Tool %s rejected metadata mutation; relying on registry lookup",
|
||||
tool_def.name,
|
||||
)
|
||||
tools.append(tool)
|
||||
|
||||
# Add any additional custom tools
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue