mirror of
https://github.com/onyx-dot-app/onyx.git
synced 2026-02-16 23:35:46 +00:00
Compare commits
15 Commits
experiment
...
tool_name_
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1c5d6b88e3 | ||
|
|
2c881c8b61 | ||
|
|
3725e3485c | ||
|
|
d72fd84bcd | ||
|
|
6b7d560b0c | ||
|
|
2af27ba1f5 | ||
|
|
75ac128836 | ||
|
|
a688f4ee81 | ||
|
|
ca54a85929 | ||
|
|
3571a8d39a | ||
|
|
08ac2f2e20 | ||
|
|
9b47267d48 | ||
|
|
c57ee34a33 | ||
|
|
318a66a189 | ||
|
|
edf9e68abf |
@@ -7,7 +7,6 @@ Create Date: 2025-12-18 16:00:00.000000
|
||||
"""
|
||||
|
||||
from alembic import op
|
||||
from onyx.deep_research.dr_mock_tools import RESEARCH_AGENT_DB_NAME
|
||||
import sqlalchemy as sa
|
||||
|
||||
|
||||
@@ -19,7 +18,7 @@ depends_on = None
|
||||
|
||||
|
||||
DEEP_RESEARCH_TOOL = {
|
||||
"name": RESEARCH_AGENT_DB_NAME,
|
||||
"name": "ResearchAgent",
|
||||
"display_name": "Research Agent",
|
||||
"description": "The Research Agent is a sub-agent that conducts research on a specific topic.",
|
||||
"in_code_tool_id": "ResearchAgent",
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
"""tool_name_consistency
|
||||
|
||||
Revision ID: d25168c2beee
|
||||
Revises: 8405ca81cc83
|
||||
Create Date: 2026-01-11 17:54:40.135777
|
||||
|
||||
"""
|
||||
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = "d25168c2beee"
|
||||
down_revision = "8405ca81cc83"
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
|
||||
# Currently the seeded tools have the in_code_tool_id == name
|
||||
CURRENT_TOOL_NAME_MAPPING = [
|
||||
"SearchTool",
|
||||
"WebSearchTool",
|
||||
"ImageGenerationTool",
|
||||
"PythonTool",
|
||||
"OpenURLTool",
|
||||
"KnowledgeGraphTool",
|
||||
"ResearchAgent",
|
||||
]
|
||||
|
||||
# Mapping of in_code_tool_id -> name
|
||||
# These are the expected names that we want in the database
|
||||
EXPECTED_TOOL_NAME_MAPPING = {
|
||||
"SearchTool": "internal_search",
|
||||
"WebSearchTool": "web_search",
|
||||
"ImageGenerationTool": "generate_image",
|
||||
"PythonTool": "python",
|
||||
"OpenURLTool": "open_url",
|
||||
"KnowledgeGraphTool": "run_kg_search",
|
||||
"ResearchAgent": "research_agent",
|
||||
}
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
conn = op.get_bind()
|
||||
|
||||
# Mapping of in_code_tool_id to the NAME constant from each tool class
|
||||
# These match the .name property of each tool implementation
|
||||
tool_name_mapping = EXPECTED_TOOL_NAME_MAPPING
|
||||
|
||||
# Update the name column for each tool based on its in_code_tool_id
|
||||
for in_code_tool_id, expected_name in tool_name_mapping.items():
|
||||
conn.execute(
|
||||
sa.text(
|
||||
"""
|
||||
UPDATE tool
|
||||
SET name = :expected_name
|
||||
WHERE in_code_tool_id = :in_code_tool_id
|
||||
"""
|
||||
),
|
||||
{
|
||||
"expected_name": expected_name,
|
||||
"in_code_tool_id": in_code_tool_id,
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
conn = op.get_bind()
|
||||
|
||||
# Reverse the migration by setting name back to in_code_tool_id
|
||||
# This matches the original pattern where name was the class name
|
||||
for in_code_tool_id in CURRENT_TOOL_NAME_MAPPING:
|
||||
conn.execute(
|
||||
sa.text(
|
||||
"""
|
||||
UPDATE tool
|
||||
SET name = :current_name
|
||||
WHERE in_code_tool_id = :in_code_tool_id
|
||||
"""
|
||||
),
|
||||
{
|
||||
"current_name": in_code_tool_id,
|
||||
"in_code_tool_id": in_code_tool_id,
|
||||
},
|
||||
)
|
||||
@@ -2616,6 +2616,7 @@ class Tool(Base):
|
||||
__tablename__ = "tool"
|
||||
|
||||
id: Mapped[int] = mapped_column(Integer, primary_key=True)
|
||||
# The name of the tool that the LLM will see
|
||||
name: Mapped[str] = mapped_column(String, nullable=False)
|
||||
description: Mapped[str] = mapped_column(Text, nullable=True)
|
||||
# ID of the tool in the codebase, only applies for in-code tools.
|
||||
|
||||
@@ -21,7 +21,6 @@ from onyx.configs.constants import MessageType
|
||||
from onyx.db.tools import get_tool_by_name
|
||||
from onyx.deep_research.dr_mock_tools import get_clarification_tool_definitions
|
||||
from onyx.deep_research.dr_mock_tools import get_orchestrator_tools
|
||||
from onyx.deep_research.dr_mock_tools import RESEARCH_AGENT_DB_NAME
|
||||
from onyx.deep_research.dr_mock_tools import RESEARCH_AGENT_TOOL_NAME
|
||||
from onyx.deep_research.dr_mock_tools import THINK_TOOL_RESPONSE_MESSAGE
|
||||
from onyx.deep_research.dr_mock_tools import THINK_TOOL_RESPONSE_TOKEN_COUNT
|
||||
@@ -634,7 +633,8 @@ def run_deep_research_llm_loop(
|
||||
tool_name=current_tool_call.tool_name,
|
||||
tool_call_id=current_tool_call.tool_call_id,
|
||||
tool_id=get_tool_by_name(
|
||||
tool_name=RESEARCH_AGENT_DB_NAME, db_session=db_session
|
||||
tool_name=RESEARCH_AGENT_TOOL_NAME,
|
||||
db_session=db_session,
|
||||
).id,
|
||||
reasoning_tokens=llm_step_result.reasoning
|
||||
or most_recent_reasoning,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
GENERATE_PLAN_TOOL_NAME = "generate_plan"
|
||||
|
||||
RESEARCH_AGENT_DB_NAME = "ResearchAgent"
|
||||
RESEARCH_AGENT_IN_CODE_ID = "ResearchAgent"
|
||||
RESEARCH_AGENT_TOOL_NAME = "research_agent"
|
||||
RESEARCH_AGENT_TASK_KEY = "task"
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ from onyx.db.chat import get_db_search_doc_by_id
|
||||
from onyx.db.chat import translate_db_search_doc_to_saved_search_doc
|
||||
from onyx.db.models import ChatMessage
|
||||
from onyx.db.tools import get_tool_by_id
|
||||
from onyx.deep_research.dr_mock_tools import RESEARCH_AGENT_DB_NAME
|
||||
from onyx.deep_research.dr_mock_tools import RESEARCH_AGENT_IN_CODE_ID
|
||||
from onyx.deep_research.dr_mock_tools import RESEARCH_AGENT_TASK_KEY
|
||||
from onyx.server.query_and_chat.placement import Placement
|
||||
from onyx.server.query_and_chat.streaming_models import AgentResponseDelta
|
||||
@@ -401,7 +401,7 @@ def translate_assistant_message_to_packets(
|
||||
# Here we do a try because some tools may get deleted before the session is reloaded.
|
||||
try:
|
||||
tool = get_tool_by_id(tool_call.tool_id, db_session)
|
||||
if tool.in_code_tool_id == RESEARCH_AGENT_DB_NAME:
|
||||
if tool.in_code_tool_id == RESEARCH_AGENT_IN_CODE_ID:
|
||||
research_agent_count += 1
|
||||
|
||||
# Handle different tool types
|
||||
@@ -457,7 +457,7 @@ def translate_assistant_message_to_packets(
|
||||
)
|
||||
)
|
||||
|
||||
elif tool.in_code_tool_id == RESEARCH_AGENT_DB_NAME:
|
||||
elif tool.in_code_tool_id == RESEARCH_AGENT_IN_CODE_ID:
|
||||
# Not ideal but not a huge issue if the research task is lost.
|
||||
research_task = cast(
|
||||
str,
|
||||
|
||||
@@ -61,13 +61,13 @@ def test_cold_startup_default_assistant() -> None:
|
||||
|
||||
# Verify all three main tools are attached
|
||||
assert (
|
||||
"SearchTool" in tool_names
|
||||
"internal_search" in tool_names
|
||||
), "Default assistant should have SearchTool attached"
|
||||
assert (
|
||||
"ImageGenerationTool" in tool_names
|
||||
"generate_image" in tool_names
|
||||
), "Default assistant should have ImageGenerationTool attached"
|
||||
assert (
|
||||
"WebSearchTool" in tool_names
|
||||
"web_search" in tool_names
|
||||
), "Default assistant should have WebSearchTool attached"
|
||||
|
||||
# Also verify by display names for clarity
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
from pydantic import BaseModel
|
||||
from sqlalchemy import text
|
||||
|
||||
from onyx.db.engine.sql_engine import get_session_with_current_tenant
|
||||
@@ -5,6 +6,53 @@ from tests.integration.common_utils.reset import downgrade_postgres
|
||||
from tests.integration.common_utils.reset import upgrade_postgres
|
||||
|
||||
|
||||
class ToolSeedingExpectedResult(BaseModel):
|
||||
name: str
|
||||
display_name: str
|
||||
in_code_tool_id: str
|
||||
user_id: str | None
|
||||
|
||||
|
||||
EXPECTED_TOOLS = {
|
||||
"SearchTool": ToolSeedingExpectedResult(
|
||||
name="internal_search",
|
||||
display_name="Internal Search",
|
||||
in_code_tool_id="SearchTool",
|
||||
user_id=None,
|
||||
),
|
||||
"ImageGenerationTool": ToolSeedingExpectedResult(
|
||||
name="generate_image",
|
||||
display_name="Image Generation",
|
||||
in_code_tool_id="ImageGenerationTool",
|
||||
user_id=None,
|
||||
),
|
||||
"WebSearchTool": ToolSeedingExpectedResult(
|
||||
name="web_search",
|
||||
display_name="Web Search",
|
||||
in_code_tool_id="WebSearchTool",
|
||||
user_id=None,
|
||||
),
|
||||
"KnowledgeGraphTool": ToolSeedingExpectedResult(
|
||||
name="run_kg_search",
|
||||
display_name="Knowledge Graph Search",
|
||||
in_code_tool_id="KnowledgeGraphTool",
|
||||
user_id=None,
|
||||
),
|
||||
"PythonTool": ToolSeedingExpectedResult(
|
||||
name="python",
|
||||
display_name="Code Interpreter",
|
||||
in_code_tool_id="PythonTool",
|
||||
user_id=None,
|
||||
),
|
||||
"ResearchAgent": ToolSeedingExpectedResult(
|
||||
name="research_agent",
|
||||
display_name="Research Agent",
|
||||
in_code_tool_id="ResearchAgent",
|
||||
user_id=None,
|
||||
),
|
||||
}
|
||||
|
||||
|
||||
def test_tool_seeding_migration() -> None:
|
||||
"""Test that migration from base to head correctly seeds builtin tools."""
|
||||
# Start from base and upgrade to just before tool seeding
|
||||
@@ -49,56 +97,33 @@ def test_tool_seeding_migration() -> None:
|
||||
len(tools) == 8
|
||||
), f"Should have created exactly 8 builtin tools, got {len(tools)}"
|
||||
|
||||
def validate_tool(expected: ToolSeedingExpectedResult) -> None:
|
||||
tool = next((t for t in tools if t[1] == expected.name), None)
|
||||
assert tool is not None, f"{expected.name} should exist"
|
||||
assert (
|
||||
tool[2] == expected.display_name
|
||||
), f"{expected.name} display name should be '{expected.display_name}'"
|
||||
assert (
|
||||
tool[4] == expected.in_code_tool_id
|
||||
), f"{expected.name} in_code_tool_id should be '{expected.in_code_tool_id}'"
|
||||
assert (
|
||||
tool[5] is None
|
||||
), f"{expected.name} should not have a user_id (builtin)"
|
||||
|
||||
# Check SearchTool
|
||||
search_tool = next((t for t in tools if t[1] == "SearchTool"), None)
|
||||
assert search_tool is not None, "SearchTool should exist"
|
||||
assert (
|
||||
search_tool[2] == "Internal Search"
|
||||
), "SearchTool display name should be 'Internal Search'"
|
||||
assert search_tool[5] is None, "SearchTool should not have a user_id (builtin)"
|
||||
validate_tool(EXPECTED_TOOLS["SearchTool"])
|
||||
|
||||
# Check ImageGenerationTool
|
||||
img_tool = next((t for t in tools if t[1] == "ImageGenerationTool"), None)
|
||||
assert img_tool is not None, "ImageGenerationTool should exist"
|
||||
assert (
|
||||
img_tool[2] == "Image Generation"
|
||||
), "ImageGenerationTool display name should be 'Image Generation'"
|
||||
assert (
|
||||
img_tool[5] is None
|
||||
), "ImageGenerationTool should not have a user_id (builtin)"
|
||||
validate_tool(EXPECTED_TOOLS["ImageGenerationTool"])
|
||||
|
||||
# Check WebSearchTool
|
||||
web_tool = next((t for t in tools if t[1] == "WebSearchTool"), None)
|
||||
assert web_tool is not None, "WebSearchTool should exist"
|
||||
assert (
|
||||
web_tool[2] == "Web Search"
|
||||
), "WebSearchTool display name should be 'Web Search'"
|
||||
assert web_tool[5] is None, "WebSearchTool should not have a user_id (builtin)"
|
||||
validate_tool(EXPECTED_TOOLS["WebSearchTool"])
|
||||
|
||||
# Check KnowledgeGraphTool
|
||||
kg_tool = next((t for t in tools if t[1] == "KnowledgeGraphTool"), None)
|
||||
assert kg_tool is not None, "KnowledgeGraphTool should exist"
|
||||
assert (
|
||||
kg_tool[2] == "Knowledge Graph Search"
|
||||
), "KnowledgeGraphTool display name should be 'Knowledge Graph Search'"
|
||||
assert (
|
||||
kg_tool[5] is None
|
||||
), "KnowledgeGraphTool should not have a user_id (builtin)"
|
||||
validate_tool(EXPECTED_TOOLS["KnowledgeGraphTool"])
|
||||
|
||||
# Check PythonTool
|
||||
python_tool = next((t for t in tools if t[1] == "PythonTool"), None)
|
||||
assert python_tool is not None, "PythonTool should exist"
|
||||
assert (
|
||||
python_tool[2] == "Code Interpreter"
|
||||
), "PythonTool display name should be 'Code Interpreter'"
|
||||
assert python_tool[5] is None, "PythonTool should not have a user_id (builtin)"
|
||||
validate_tool(EXPECTED_TOOLS["PythonTool"])
|
||||
|
||||
# Check ResearchAgent (Deep Research as a tool)
|
||||
research_agent = next((t for t in tools if t[1] == "ResearchAgent"), None)
|
||||
assert research_agent is not None, "ResearchAgent should exist"
|
||||
assert (
|
||||
research_agent[2] == "Research Agent"
|
||||
), "ResearchAgent display name should be 'Research Agent'"
|
||||
assert (
|
||||
research_agent[5] is None
|
||||
), "ResearchAgent should not have a user_id (builtin)"
|
||||
validate_tool(EXPECTED_TOOLS["ResearchAgent"])
|
||||
|
||||
@@ -38,11 +38,11 @@ def test_unified_assistant(reset: None, admin_user: DATestUser) -> None:
|
||||
# Verify tools
|
||||
tools = unified_assistant.tools
|
||||
tool_names = [tool.name for tool in tools]
|
||||
assert "SearchTool" in tool_names, "SearchTool not found in unified assistant"
|
||||
assert "internal_search" in tool_names, "SearchTool not found in unified assistant"
|
||||
assert (
|
||||
"ImageGenerationTool" in tool_names
|
||||
"generate_image" in tool_names
|
||||
), "ImageGenerationTool not found in unified assistant"
|
||||
assert "WebSearchTool" in tool_names, "WebSearchTool not found in unified assistant"
|
||||
assert "web_search" in tool_names, "WebSearchTool not found in unified assistant"
|
||||
|
||||
# Verify no starter messages
|
||||
starter_messages = unified_assistant.starter_messages or []
|
||||
|
||||
@@ -6,9 +6,9 @@ export const TOOL_IDS = {
|
||||
actionToggle: '[data-testid="action-management-toggle"]',
|
||||
options: '[data-testid="tool-options"]',
|
||||
// These IDs are derived from tool.name in the app
|
||||
searchOption: '[data-testid="tool-option-SearchTool"]',
|
||||
webSearchOption: '[data-testid="tool-option-WebSearchTool"]',
|
||||
imageGenerationOption: '[data-testid="tool-option-ImageGenerationTool"]',
|
||||
searchOption: '[data-testid="tool-option-internal_search"]',
|
||||
webSearchOption: '[data-testid="tool-option-web_search"]',
|
||||
imageGenerationOption: '[data-testid="tool-option-generate_image"]',
|
||||
// Generic toggle selector used inside tool options
|
||||
toggleInput: 'input[type="checkbox"], input[type="radio"], [role="switch"]',
|
||||
} as const;
|
||||
|
||||
Reference in New Issue
Block a user