hexdag 0.5.0.dev1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- hexdag/__init__.py +116 -0
- hexdag/__main__.py +30 -0
- hexdag/adapters/executors/__init__.py +5 -0
- hexdag/adapters/executors/local_executor.py +316 -0
- hexdag/builtin/__init__.py +6 -0
- hexdag/builtin/adapters/__init__.py +51 -0
- hexdag/builtin/adapters/anthropic/__init__.py +5 -0
- hexdag/builtin/adapters/anthropic/anthropic_adapter.py +151 -0
- hexdag/builtin/adapters/database/__init__.py +6 -0
- hexdag/builtin/adapters/database/csv/csv_adapter.py +249 -0
- hexdag/builtin/adapters/database/pgvector/__init__.py +5 -0
- hexdag/builtin/adapters/database/pgvector/pgvector_adapter.py +478 -0
- hexdag/builtin/adapters/database/sqlalchemy/sqlalchemy_adapter.py +252 -0
- hexdag/builtin/adapters/database/sqlite/__init__.py +5 -0
- hexdag/builtin/adapters/database/sqlite/sqlite_adapter.py +410 -0
- hexdag/builtin/adapters/local/README.md +59 -0
- hexdag/builtin/adapters/local/__init__.py +7 -0
- hexdag/builtin/adapters/local/local_observer_manager.py +696 -0
- hexdag/builtin/adapters/memory/__init__.py +47 -0
- hexdag/builtin/adapters/memory/file_memory_adapter.py +297 -0
- hexdag/builtin/adapters/memory/in_memory_memory.py +216 -0
- hexdag/builtin/adapters/memory/schemas.py +57 -0
- hexdag/builtin/adapters/memory/session_memory.py +178 -0
- hexdag/builtin/adapters/memory/sqlite_memory_adapter.py +215 -0
- hexdag/builtin/adapters/memory/state_memory.py +280 -0
- hexdag/builtin/adapters/mock/README.md +89 -0
- hexdag/builtin/adapters/mock/__init__.py +15 -0
- hexdag/builtin/adapters/mock/hexdag.toml +50 -0
- hexdag/builtin/adapters/mock/mock_database.py +225 -0
- hexdag/builtin/adapters/mock/mock_embedding.py +223 -0
- hexdag/builtin/adapters/mock/mock_llm.py +177 -0
- hexdag/builtin/adapters/mock/mock_tool_adapter.py +192 -0
- hexdag/builtin/adapters/mock/mock_tool_router.py +232 -0
- hexdag/builtin/adapters/openai/__init__.py +5 -0
- hexdag/builtin/adapters/openai/openai_adapter.py +634 -0
- hexdag/builtin/adapters/secret/__init__.py +7 -0
- hexdag/builtin/adapters/secret/local_secret_adapter.py +248 -0
- hexdag/builtin/adapters/unified_tool_router.py +280 -0
- hexdag/builtin/macros/__init__.py +17 -0
- hexdag/builtin/macros/conversation_agent.py +390 -0
- hexdag/builtin/macros/llm_macro.py +151 -0
- hexdag/builtin/macros/reasoning_agent.py +423 -0
- hexdag/builtin/macros/tool_macro.py +380 -0
- hexdag/builtin/nodes/__init__.py +38 -0
- hexdag/builtin/nodes/_discovery.py +123 -0
- hexdag/builtin/nodes/agent_node.py +696 -0
- hexdag/builtin/nodes/base_node_factory.py +242 -0
- hexdag/builtin/nodes/composite_node.py +926 -0
- hexdag/builtin/nodes/data_node.py +201 -0
- hexdag/builtin/nodes/expression_node.py +487 -0
- hexdag/builtin/nodes/function_node.py +454 -0
- hexdag/builtin/nodes/llm_node.py +491 -0
- hexdag/builtin/nodes/loop_node.py +920 -0
- hexdag/builtin/nodes/mapped_input.py +518 -0
- hexdag/builtin/nodes/port_call_node.py +269 -0
- hexdag/builtin/nodes/tool_call_node.py +195 -0
- hexdag/builtin/nodes/tool_utils.py +390 -0
- hexdag/builtin/prompts/__init__.py +68 -0
- hexdag/builtin/prompts/base.py +422 -0
- hexdag/builtin/prompts/chat_prompts.py +303 -0
- hexdag/builtin/prompts/error_correction_prompts.py +320 -0
- hexdag/builtin/prompts/tool_prompts.py +160 -0
- hexdag/builtin/tools/builtin_tools.py +84 -0
- hexdag/builtin/tools/database_tools.py +164 -0
- hexdag/cli/__init__.py +17 -0
- hexdag/cli/__main__.py +7 -0
- hexdag/cli/commands/__init__.py +27 -0
- hexdag/cli/commands/build_cmd.py +812 -0
- hexdag/cli/commands/create_cmd.py +208 -0
- hexdag/cli/commands/docs_cmd.py +293 -0
- hexdag/cli/commands/generate_types_cmd.py +252 -0
- hexdag/cli/commands/init_cmd.py +188 -0
- hexdag/cli/commands/pipeline_cmd.py +494 -0
- hexdag/cli/commands/plugin_dev_cmd.py +529 -0
- hexdag/cli/commands/plugins_cmd.py +441 -0
- hexdag/cli/commands/studio_cmd.py +101 -0
- hexdag/cli/commands/validate_cmd.py +221 -0
- hexdag/cli/main.py +84 -0
- hexdag/core/__init__.py +83 -0
- hexdag/core/config/__init__.py +20 -0
- hexdag/core/config/loader.py +479 -0
- hexdag/core/config/models.py +150 -0
- hexdag/core/configurable.py +294 -0
- hexdag/core/context/__init__.py +37 -0
- hexdag/core/context/execution_context.py +378 -0
- hexdag/core/docs/__init__.py +26 -0
- hexdag/core/docs/extractors.py +678 -0
- hexdag/core/docs/generators.py +890 -0
- hexdag/core/docs/models.py +120 -0
- hexdag/core/domain/__init__.py +10 -0
- hexdag/core/domain/dag.py +1225 -0
- hexdag/core/exceptions.py +234 -0
- hexdag/core/expression_parser.py +569 -0
- hexdag/core/logging.py +449 -0
- hexdag/core/models/__init__.py +17 -0
- hexdag/core/models/base.py +138 -0
- hexdag/core/orchestration/__init__.py +46 -0
- hexdag/core/orchestration/body_executor.py +481 -0
- hexdag/core/orchestration/components/__init__.py +97 -0
- hexdag/core/orchestration/components/adapter_lifecycle_manager.py +113 -0
- hexdag/core/orchestration/components/checkpoint_manager.py +134 -0
- hexdag/core/orchestration/components/execution_coordinator.py +360 -0
- hexdag/core/orchestration/components/health_check_manager.py +176 -0
- hexdag/core/orchestration/components/input_mapper.py +143 -0
- hexdag/core/orchestration/components/lifecycle_manager.py +583 -0
- hexdag/core/orchestration/components/node_executor.py +377 -0
- hexdag/core/orchestration/components/secret_manager.py +202 -0
- hexdag/core/orchestration/components/wave_executor.py +158 -0
- hexdag/core/orchestration/constants.py +17 -0
- hexdag/core/orchestration/events/README.md +312 -0
- hexdag/core/orchestration/events/__init__.py +104 -0
- hexdag/core/orchestration/events/batching.py +330 -0
- hexdag/core/orchestration/events/decorators.py +139 -0
- hexdag/core/orchestration/events/events.py +573 -0
- hexdag/core/orchestration/events/observers/__init__.py +30 -0
- hexdag/core/orchestration/events/observers/core_observers.py +690 -0
- hexdag/core/orchestration/events/observers/models.py +111 -0
- hexdag/core/orchestration/events/taxonomy.py +269 -0
- hexdag/core/orchestration/hook_context.py +237 -0
- hexdag/core/orchestration/hooks.py +437 -0
- hexdag/core/orchestration/models.py +418 -0
- hexdag/core/orchestration/orchestrator.py +910 -0
- hexdag/core/orchestration/orchestrator_factory.py +275 -0
- hexdag/core/orchestration/port_wrappers.py +327 -0
- hexdag/core/orchestration/prompt/__init__.py +32 -0
- hexdag/core/orchestration/prompt/template.py +332 -0
- hexdag/core/pipeline_builder/__init__.py +21 -0
- hexdag/core/pipeline_builder/component_instantiator.py +386 -0
- hexdag/core/pipeline_builder/include_tag.py +265 -0
- hexdag/core/pipeline_builder/pipeline_config.py +133 -0
- hexdag/core/pipeline_builder/py_tag.py +223 -0
- hexdag/core/pipeline_builder/tag_discovery.py +268 -0
- hexdag/core/pipeline_builder/yaml_builder.py +1196 -0
- hexdag/core/pipeline_builder/yaml_validator.py +569 -0
- hexdag/core/ports/__init__.py +65 -0
- hexdag/core/ports/api_call.py +133 -0
- hexdag/core/ports/database.py +489 -0
- hexdag/core/ports/embedding.py +215 -0
- hexdag/core/ports/executor.py +237 -0
- hexdag/core/ports/file_storage.py +117 -0
- hexdag/core/ports/healthcheck.py +87 -0
- hexdag/core/ports/llm.py +551 -0
- hexdag/core/ports/memory.py +70 -0
- hexdag/core/ports/observer_manager.py +130 -0
- hexdag/core/ports/secret.py +145 -0
- hexdag/core/ports/tool_router.py +94 -0
- hexdag/core/ports_builder.py +623 -0
- hexdag/core/protocols.py +273 -0
- hexdag/core/resolver.py +304 -0
- hexdag/core/schema/__init__.py +9 -0
- hexdag/core/schema/generator.py +742 -0
- hexdag/core/secrets.py +242 -0
- hexdag/core/types.py +413 -0
- hexdag/core/utils/async_warnings.py +206 -0
- hexdag/core/utils/schema_conversion.py +78 -0
- hexdag/core/utils/sql_validation.py +86 -0
- hexdag/core/validation/secure_json.py +148 -0
- hexdag/core/yaml_macro.py +517 -0
- hexdag/mcp_server.py +3120 -0
- hexdag/studio/__init__.py +10 -0
- hexdag/studio/build_ui.py +92 -0
- hexdag/studio/server/__init__.py +1 -0
- hexdag/studio/server/main.py +100 -0
- hexdag/studio/server/routes/__init__.py +9 -0
- hexdag/studio/server/routes/execute.py +208 -0
- hexdag/studio/server/routes/export.py +558 -0
- hexdag/studio/server/routes/files.py +207 -0
- hexdag/studio/server/routes/plugins.py +419 -0
- hexdag/studio/server/routes/validate.py +220 -0
- hexdag/studio/ui/index.html +13 -0
- hexdag/studio/ui/package-lock.json +2992 -0
- hexdag/studio/ui/package.json +31 -0
- hexdag/studio/ui/postcss.config.js +6 -0
- hexdag/studio/ui/public/hexdag.svg +5 -0
- hexdag/studio/ui/src/App.tsx +251 -0
- hexdag/studio/ui/src/components/Canvas.tsx +408 -0
- hexdag/studio/ui/src/components/ContextMenu.tsx +187 -0
- hexdag/studio/ui/src/components/FileBrowser.tsx +123 -0
- hexdag/studio/ui/src/components/Header.tsx +181 -0
- hexdag/studio/ui/src/components/HexdagNode.tsx +193 -0
- hexdag/studio/ui/src/components/NodeInspector.tsx +512 -0
- hexdag/studio/ui/src/components/NodePalette.tsx +262 -0
- hexdag/studio/ui/src/components/NodePortsSection.tsx +403 -0
- hexdag/studio/ui/src/components/PluginManager.tsx +347 -0
- hexdag/studio/ui/src/components/PortsEditor.tsx +481 -0
- hexdag/studio/ui/src/components/PythonEditor.tsx +195 -0
- hexdag/studio/ui/src/components/ValidationPanel.tsx +105 -0
- hexdag/studio/ui/src/components/YamlEditor.tsx +196 -0
- hexdag/studio/ui/src/components/index.ts +8 -0
- hexdag/studio/ui/src/index.css +92 -0
- hexdag/studio/ui/src/main.tsx +10 -0
- hexdag/studio/ui/src/types/index.ts +123 -0
- hexdag/studio/ui/src/vite-env.d.ts +1 -0
- hexdag/studio/ui/tailwind.config.js +29 -0
- hexdag/studio/ui/tsconfig.json +37 -0
- hexdag/studio/ui/tsconfig.node.json +13 -0
- hexdag/studio/ui/vite.config.ts +35 -0
- hexdag/visualization/__init__.py +69 -0
- hexdag/visualization/dag_visualizer.py +1020 -0
- hexdag-0.5.0.dev1.dist-info/METADATA +369 -0
- hexdag-0.5.0.dev1.dist-info/RECORD +261 -0
- hexdag-0.5.0.dev1.dist-info/WHEEL +4 -0
- hexdag-0.5.0.dev1.dist-info/entry_points.txt +4 -0
- hexdag-0.5.0.dev1.dist-info/licenses/LICENSE +190 -0
- hexdag_plugins/.gitignore +43 -0
- hexdag_plugins/README.md +73 -0
- hexdag_plugins/__init__.py +1 -0
- hexdag_plugins/azure/LICENSE +21 -0
- hexdag_plugins/azure/README.md +414 -0
- hexdag_plugins/azure/__init__.py +21 -0
- hexdag_plugins/azure/azure_blob_adapter.py +450 -0
- hexdag_plugins/azure/azure_cosmos_adapter.py +383 -0
- hexdag_plugins/azure/azure_keyvault_adapter.py +314 -0
- hexdag_plugins/azure/azure_openai_adapter.py +415 -0
- hexdag_plugins/azure/pyproject.toml +107 -0
- hexdag_plugins/azure/tests/__init__.py +1 -0
- hexdag_plugins/azure/tests/test_azure_blob_adapter.py +350 -0
- hexdag_plugins/azure/tests/test_azure_cosmos_adapter.py +323 -0
- hexdag_plugins/azure/tests/test_azure_keyvault_adapter.py +330 -0
- hexdag_plugins/azure/tests/test_azure_openai_adapter.py +329 -0
- hexdag_plugins/hexdag_etl/README.md +168 -0
- hexdag_plugins/hexdag_etl/__init__.py +53 -0
- hexdag_plugins/hexdag_etl/examples/01_simple_pandas_transform.py +270 -0
- hexdag_plugins/hexdag_etl/examples/02_simple_pandas_only.py +149 -0
- hexdag_plugins/hexdag_etl/examples/03_file_io_pipeline.py +109 -0
- hexdag_plugins/hexdag_etl/examples/test_pandas_transform.py +84 -0
- hexdag_plugins/hexdag_etl/hexdag.toml +25 -0
- hexdag_plugins/hexdag_etl/hexdag_etl/__init__.py +48 -0
- hexdag_plugins/hexdag_etl/hexdag_etl/nodes/__init__.py +13 -0
- hexdag_plugins/hexdag_etl/hexdag_etl/nodes/api_extract.py +230 -0
- hexdag_plugins/hexdag_etl/hexdag_etl/nodes/base_node_factory.py +181 -0
- hexdag_plugins/hexdag_etl/hexdag_etl/nodes/file_io.py +415 -0
- hexdag_plugins/hexdag_etl/hexdag_etl/nodes/outlook.py +492 -0
- hexdag_plugins/hexdag_etl/hexdag_etl/nodes/pandas_transform.py +563 -0
- hexdag_plugins/hexdag_etl/hexdag_etl/nodes/sql_extract_load.py +112 -0
- hexdag_plugins/hexdag_etl/pyproject.toml +82 -0
- hexdag_plugins/hexdag_etl/test_transform.py +54 -0
- hexdag_plugins/hexdag_etl/tests/test_plugin_integration.py +62 -0
- hexdag_plugins/mysql_adapter/LICENSE +21 -0
- hexdag_plugins/mysql_adapter/README.md +224 -0
- hexdag_plugins/mysql_adapter/__init__.py +6 -0
- hexdag_plugins/mysql_adapter/mysql_adapter.py +408 -0
- hexdag_plugins/mysql_adapter/pyproject.toml +93 -0
- hexdag_plugins/mysql_adapter/tests/test_mysql_adapter.py +259 -0
- hexdag_plugins/storage/README.md +184 -0
- hexdag_plugins/storage/__init__.py +19 -0
- hexdag_plugins/storage/file/__init__.py +5 -0
- hexdag_plugins/storage/file/local.py +325 -0
- hexdag_plugins/storage/ports/__init__.py +5 -0
- hexdag_plugins/storage/ports/vector_store.py +236 -0
- hexdag_plugins/storage/sql/__init__.py +7 -0
- hexdag_plugins/storage/sql/base.py +187 -0
- hexdag_plugins/storage/sql/mysql.py +27 -0
- hexdag_plugins/storage/sql/postgresql.py +27 -0
- hexdag_plugins/storage/tests/__init__.py +1 -0
- hexdag_plugins/storage/tests/test_local_file_storage.py +161 -0
- hexdag_plugins/storage/tests/test_sql_adapters.py +212 -0
- hexdag_plugins/storage/vector/__init__.py +7 -0
- hexdag_plugins/storage/vector/chromadb.py +223 -0
- hexdag_plugins/storage/vector/in_memory.py +285 -0
- hexdag_plugins/storage/vector/pgvector.py +502 -0
|
@@ -0,0 +1,390 @@
|
|
|
1
|
+
"""Enhanced tool utilities for agent nodes.
|
|
2
|
+
|
|
3
|
+
Supports multiple tool calling formats and tool description management.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
import json
|
|
7
|
+
import re
|
|
8
|
+
from dataclasses import dataclass
|
|
9
|
+
from enum import StrEnum
|
|
10
|
+
from typing import Any
|
|
11
|
+
|
|
12
|
+
from pydantic import BaseModel, Field
|
|
13
|
+
|
|
14
|
+
from hexdag.core.validation.secure_json import SafeJSON
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class ToolCallFormat(StrEnum):
|
|
18
|
+
"""Tool calling formats supported by INVOKE_TOOL: prefix."""
|
|
19
|
+
|
|
20
|
+
FUNCTION_CALL = "function_call" # INVOKE_TOOL: tool_name(param1='value1')
|
|
21
|
+
JSON = "json" # INVOKE_TOOL: {"tool": "tool_name", "params": {...}}
|
|
22
|
+
MIXED = "mixed" # Support both formats
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class ToolParameter(BaseModel):
|
|
26
|
+
"""Definition of a tool parameter."""
|
|
27
|
+
|
|
28
|
+
name: str = Field(..., description="Parameter name")
|
|
29
|
+
description: str = Field(..., description="Parameter description")
|
|
30
|
+
param_type: str = Field(default="str", description="Parameter type")
|
|
31
|
+
required: bool = Field(default=True, description="Whether parameter is required")
|
|
32
|
+
default: Any = Field(default=None, description="Default value if not required")
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class ToolDefinition(BaseModel):
|
|
36
|
+
"""Complete tool definition with descriptions and parameters."""
|
|
37
|
+
|
|
38
|
+
name: str = Field(..., description="Tool name")
|
|
39
|
+
simplified_description: str = Field(..., description="Brief tool description")
|
|
40
|
+
detailed_description: str = Field(..., description="Detailed tool description")
|
|
41
|
+
parameters: list[ToolParameter] = Field(default_factory=list, description="Tool parameters")
|
|
42
|
+
examples: list[str] = Field(default_factory=list, description="Usage examples")
|
|
43
|
+
|
|
44
|
+
def to_simplified_string(self) -> str:
|
|
45
|
+
"""Convert to simplified string format.
|
|
46
|
+
|
|
47
|
+
Returns
|
|
48
|
+
-------
|
|
49
|
+
str
|
|
50
|
+
Simplified string representation of the tool
|
|
51
|
+
"""
|
|
52
|
+
return f"{self.name}: {self.simplified_description}"
|
|
53
|
+
|
|
54
|
+
def to_detailed_string(self) -> str:
|
|
55
|
+
"""Convert to detailed string format.
|
|
56
|
+
|
|
57
|
+
Returns
|
|
58
|
+
-------
|
|
59
|
+
str
|
|
60
|
+
Detailed string representation of the tool with parameters and examples
|
|
61
|
+
"""
|
|
62
|
+
lines = [f"Tool: {self.name}", f"Description: {self.detailed_description}", "Parameters:"]
|
|
63
|
+
|
|
64
|
+
for param in self.parameters:
|
|
65
|
+
req_str = "required" if param.required else "optional"
|
|
66
|
+
lines.append(f" - {param.name} ({param.param_type}, {req_str}): {param.description}")
|
|
67
|
+
|
|
68
|
+
if self.examples:
|
|
69
|
+
lines.append("Examples:")
|
|
70
|
+
lines.extend(f" {example}" for example in self.examples)
|
|
71
|
+
|
|
72
|
+
return "\n".join(lines)
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
@dataclass(frozen=True, slots=True)
|
|
76
|
+
class ToolCall:
|
|
77
|
+
"""Parsed tool call information."""
|
|
78
|
+
|
|
79
|
+
name: str
|
|
80
|
+
params: dict[str, Any]
|
|
81
|
+
format: ToolCallFormat
|
|
82
|
+
raw_text: str
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
class ToolParser:
|
|
86
|
+
"""Parse tool calls with INVOKE_TOOL: prefix for clear identification."""
|
|
87
|
+
|
|
88
|
+
# Function call pattern with INVOKE_TOOL: prefix (supports namespace:tool_name)
|
|
89
|
+
INVOKE_TOOL_PATTERN = re.compile(
|
|
90
|
+
r"INVOKE_TOOL:\s*([\w:]+)\s*\(\s*((?:[^()]*(?:\([^()]*\)[^()]*)*)*)\s*\)"
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
# JSON pattern with INVOKE_TOOL: prefix
|
|
94
|
+
INVOKE_TOOL_JSON_PATTERN = re.compile(r"INVOKE_TOOL:\s*(\{[^{}]*(?:\{[^{}]*\}[^{}]*)*\})")
|
|
95
|
+
|
|
96
|
+
# Parameter parsing pattern
|
|
97
|
+
PARAM_PATTERN = re.compile(r"(\w+)\s*=\s*(?:'([^']*)'|\"([^\"]*)\"|([^,\s\)]+))")
|
|
98
|
+
|
|
99
|
+
@classmethod
|
|
100
|
+
def parse_tool_calls(
|
|
101
|
+
cls, text: str, format: ToolCallFormat = ToolCallFormat.MIXED
|
|
102
|
+
) -> list[ToolCall]:
|
|
103
|
+
"""Extract all tool calls from text using INVOKE_TOOL: prefix.
|
|
104
|
+
|
|
105
|
+
Returns
|
|
106
|
+
-------
|
|
107
|
+
list[ToolCall]
|
|
108
|
+
List of parsed tool calls found in the text
|
|
109
|
+
"""
|
|
110
|
+
calls = []
|
|
111
|
+
|
|
112
|
+
if format in (ToolCallFormat.FUNCTION_CALL, ToolCallFormat.MIXED):
|
|
113
|
+
calls.extend(cls._parse_function_calls(text))
|
|
114
|
+
|
|
115
|
+
if format in (ToolCallFormat.JSON, ToolCallFormat.MIXED):
|
|
116
|
+
calls.extend(cls._parse_json_calls(text))
|
|
117
|
+
|
|
118
|
+
return calls
|
|
119
|
+
|
|
120
|
+
@classmethod
|
|
121
|
+
def _parse_function_calls(cls, text: str) -> list[ToolCall]:
|
|
122
|
+
"""Parse function calls with INVOKE_TOOL: prefix.
|
|
123
|
+
|
|
124
|
+
Returns
|
|
125
|
+
-------
|
|
126
|
+
list[ToolCall]
|
|
127
|
+
List of parsed function-style tool calls
|
|
128
|
+
"""
|
|
129
|
+
calls = []
|
|
130
|
+
|
|
131
|
+
for match in cls.INVOKE_TOOL_PATTERN.finditer(text):
|
|
132
|
+
tool_name = match.group(1)
|
|
133
|
+
args_str = match.group(2)
|
|
134
|
+
params = cls._parse_parameters(args_str)
|
|
135
|
+
|
|
136
|
+
calls.append(
|
|
137
|
+
ToolCall(
|
|
138
|
+
name=tool_name,
|
|
139
|
+
params=params,
|
|
140
|
+
format=ToolCallFormat.FUNCTION_CALL,
|
|
141
|
+
raw_text=match.group(0),
|
|
142
|
+
)
|
|
143
|
+
)
|
|
144
|
+
|
|
145
|
+
return calls
|
|
146
|
+
|
|
147
|
+
@classmethod
|
|
148
|
+
def _parse_json_calls(cls, text: str) -> list[ToolCall]:
|
|
149
|
+
"""Parse JSON calls with INVOKE_TOOL: prefix.
|
|
150
|
+
|
|
151
|
+
Returns
|
|
152
|
+
-------
|
|
153
|
+
list[ToolCall]
|
|
154
|
+
List of parsed JSON-style tool calls
|
|
155
|
+
"""
|
|
156
|
+
calls = []
|
|
157
|
+
|
|
158
|
+
for match in cls.INVOKE_TOOL_JSON_PATTERN.finditer(text):
|
|
159
|
+
try:
|
|
160
|
+
json_str = match.group(1)
|
|
161
|
+
data = SafeJSON().loads(json_str)
|
|
162
|
+
|
|
163
|
+
if isinstance(data, dict) and "tool" in data:
|
|
164
|
+
calls.append(
|
|
165
|
+
ToolCall(
|
|
166
|
+
name=data["tool"],
|
|
167
|
+
params=data.get("params", {}),
|
|
168
|
+
format=ToolCallFormat.JSON,
|
|
169
|
+
raw_text=match.group(0),
|
|
170
|
+
)
|
|
171
|
+
)
|
|
172
|
+
|
|
173
|
+
except json.JSONDecodeError:
|
|
174
|
+
continue
|
|
175
|
+
|
|
176
|
+
return calls
|
|
177
|
+
|
|
178
|
+
@classmethod
|
|
179
|
+
def _parse_parameters(cls, args_str: str) -> dict[str, Any]:
|
|
180
|
+
"""Parse function parameters from argument string.
|
|
181
|
+
|
|
182
|
+
Returns
|
|
183
|
+
-------
|
|
184
|
+
dict[str, Any]
|
|
185
|
+
Dictionary of parsed parameter names and values
|
|
186
|
+
"""
|
|
187
|
+
params = {}
|
|
188
|
+
|
|
189
|
+
for match in cls.PARAM_PATTERN.finditer(args_str):
|
|
190
|
+
key = match.group(1)
|
|
191
|
+
value = match.group(2) or match.group(3) or match.group(4)
|
|
192
|
+
|
|
193
|
+
# Try to parse as JSON for complex types
|
|
194
|
+
try:
|
|
195
|
+
params[key] = json.loads(value)
|
|
196
|
+
except (json.JSONDecodeError, TypeError):
|
|
197
|
+
params[key] = value
|
|
198
|
+
|
|
199
|
+
return params
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
class ToolSchemaConverter:
|
|
203
|
+
"""Convert ToolDefinition to various LLM provider formats."""
|
|
204
|
+
|
|
205
|
+
@staticmethod
|
|
206
|
+
def to_openai_schema(tool_def: ToolDefinition) -> dict[str, Any]:
|
|
207
|
+
"""Convert ToolDefinition to OpenAI function calling format.
|
|
208
|
+
|
|
209
|
+
Args
|
|
210
|
+
----
|
|
211
|
+
tool_def: Tool definition to convert
|
|
212
|
+
|
|
213
|
+
Returns
|
|
214
|
+
-------
|
|
215
|
+
dict[str, Any]
|
|
216
|
+
OpenAI-compatible tool schema
|
|
217
|
+
"""
|
|
218
|
+
properties = {}
|
|
219
|
+
required = []
|
|
220
|
+
|
|
221
|
+
for param in tool_def.parameters:
|
|
222
|
+
# Map Python types to JSON Schema types
|
|
223
|
+
json_type = ToolSchemaConverter._python_type_to_json_type(param.param_type)
|
|
224
|
+
|
|
225
|
+
properties[param.name] = {"type": json_type, "description": param.description}
|
|
226
|
+
|
|
227
|
+
if param.required:
|
|
228
|
+
required.append(param.name)
|
|
229
|
+
|
|
230
|
+
return {
|
|
231
|
+
"type": "function",
|
|
232
|
+
"function": {
|
|
233
|
+
"name": tool_def.name,
|
|
234
|
+
"description": tool_def.detailed_description,
|
|
235
|
+
"parameters": {
|
|
236
|
+
"type": "object",
|
|
237
|
+
"properties": properties,
|
|
238
|
+
"required": required,
|
|
239
|
+
},
|
|
240
|
+
},
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
@staticmethod
|
|
244
|
+
def to_anthropic_schema(tool_def: ToolDefinition) -> dict[str, Any]:
|
|
245
|
+
"""Convert ToolDefinition to Anthropic tool use format.
|
|
246
|
+
|
|
247
|
+
Args
|
|
248
|
+
----
|
|
249
|
+
tool_def: Tool definition to convert
|
|
250
|
+
|
|
251
|
+
Returns
|
|
252
|
+
-------
|
|
253
|
+
dict[str, Any]
|
|
254
|
+
Anthropic-compatible tool schema
|
|
255
|
+
"""
|
|
256
|
+
properties = {}
|
|
257
|
+
required = []
|
|
258
|
+
|
|
259
|
+
for param in tool_def.parameters:
|
|
260
|
+
json_type = ToolSchemaConverter._python_type_to_json_type(param.param_type)
|
|
261
|
+
|
|
262
|
+
properties[param.name] = {"type": json_type, "description": param.description}
|
|
263
|
+
|
|
264
|
+
if param.required:
|
|
265
|
+
required.append(param.name)
|
|
266
|
+
|
|
267
|
+
return {
|
|
268
|
+
"name": tool_def.name,
|
|
269
|
+
"description": tool_def.detailed_description,
|
|
270
|
+
"input_schema": {
|
|
271
|
+
"type": "object",
|
|
272
|
+
"properties": properties,
|
|
273
|
+
"required": required,
|
|
274
|
+
},
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
@staticmethod
|
|
278
|
+
def _python_type_to_json_type(python_type: str) -> str:
|
|
279
|
+
"""Map Python type strings to JSON Schema types.
|
|
280
|
+
|
|
281
|
+
Args
|
|
282
|
+
----
|
|
283
|
+
python_type: Python type as string (e.g., "str", "int")
|
|
284
|
+
|
|
285
|
+
Returns
|
|
286
|
+
-------
|
|
287
|
+
str
|
|
288
|
+
JSON Schema type
|
|
289
|
+
"""
|
|
290
|
+
type_mapping = {
|
|
291
|
+
"str": "string",
|
|
292
|
+
"int": "integer",
|
|
293
|
+
"float": "number",
|
|
294
|
+
"bool": "boolean",
|
|
295
|
+
"list": "array",
|
|
296
|
+
"dict": "object",
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
# Handle generic types like list[str], dict[str, int]
|
|
300
|
+
base_type = python_type.split("[")[0].strip()
|
|
301
|
+
|
|
302
|
+
return type_mapping.get(base_type, "string")
|
|
303
|
+
|
|
304
|
+
|
|
305
|
+
class ToolDescriptionManager:
|
|
306
|
+
"""Manage tool descriptions with simplified/detailed views."""
|
|
307
|
+
|
|
308
|
+
def __init__(self) -> None:
|
|
309
|
+
"""Initialize tool description manager."""
|
|
310
|
+
self.tools: dict[str, ToolDefinition] = {}
|
|
311
|
+
|
|
312
|
+
def register_tool(self, tool_def: ToolDefinition) -> None:
|
|
313
|
+
"""Register a tool definition.
|
|
314
|
+
|
|
315
|
+
Parameters
|
|
316
|
+
----------
|
|
317
|
+
tool_def : ToolDefinition
|
|
318
|
+
The tool definition to register
|
|
319
|
+
"""
|
|
320
|
+
self.tools[tool_def.name] = tool_def
|
|
321
|
+
|
|
322
|
+
def register_tools(self, tool_defs: list[ToolDefinition]) -> None:
|
|
323
|
+
"""Register multiple tool definitions.
|
|
324
|
+
|
|
325
|
+
Parameters
|
|
326
|
+
----------
|
|
327
|
+
tool_defs : list[ToolDefinition]
|
|
328
|
+
List of tool definitions to register
|
|
329
|
+
"""
|
|
330
|
+
for tool_def in tool_defs:
|
|
331
|
+
self.register_tool(tool_def)
|
|
332
|
+
|
|
333
|
+
def get_simplified_descriptions(self) -> str:
|
|
334
|
+
"""Get simplified tool descriptions for prompt.
|
|
335
|
+
|
|
336
|
+
Returns
|
|
337
|
+
-------
|
|
338
|
+
str
|
|
339
|
+
Formatted string with simplified tool descriptions
|
|
340
|
+
"""
|
|
341
|
+
lines = ["Available tools:"]
|
|
342
|
+
|
|
343
|
+
lines.extend(f"- {tool.to_simplified_string()}" for tool in self.tools.values())
|
|
344
|
+
|
|
345
|
+
return "\n".join(lines)
|
|
346
|
+
|
|
347
|
+
def get_detailed_descriptions(self) -> str:
|
|
348
|
+
"""Get detailed tool descriptions for prompt.
|
|
349
|
+
|
|
350
|
+
Returns
|
|
351
|
+
-------
|
|
352
|
+
str
|
|
353
|
+
Formatted string with detailed tool descriptions
|
|
354
|
+
"""
|
|
355
|
+
lines = ["Available tools (detailed):"]
|
|
356
|
+
|
|
357
|
+
for tool in self.tools.values():
|
|
358
|
+
lines.append(tool.to_detailed_string())
|
|
359
|
+
lines.append("") # Add spacing between tools
|
|
360
|
+
|
|
361
|
+
return "\n".join(lines)
|
|
362
|
+
|
|
363
|
+
def get_detailed_description(self, tool_name: str) -> str:
|
|
364
|
+
"""Get detailed description for a specific tool.
|
|
365
|
+
|
|
366
|
+
Returns
|
|
367
|
+
-------
|
|
368
|
+
str
|
|
369
|
+
Detailed description of the specified tool
|
|
370
|
+
"""
|
|
371
|
+
tool = self.tools.get(tool_name)
|
|
372
|
+
if not tool:
|
|
373
|
+
return f"No description available for tool: {tool_name}"
|
|
374
|
+
|
|
375
|
+
return tool.to_detailed_string()
|
|
376
|
+
|
|
377
|
+
def create_tool_check_function(self) -> Any:
|
|
378
|
+
"""Create a function that returns detailed tool descriptions.
|
|
379
|
+
|
|
380
|
+
Returns
|
|
381
|
+
-------
|
|
382
|
+
Callable[[str], str]
|
|
383
|
+
Async function that takes a tool name and returns its detailed description
|
|
384
|
+
"""
|
|
385
|
+
|
|
386
|
+
async def check_tool_description(tool_name: str) -> str:
|
|
387
|
+
"""Get detailed description for a tool."""
|
|
388
|
+
return self.get_detailed_description(tool_name)
|
|
389
|
+
|
|
390
|
+
return check_tool_description
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"""Builtin composable prompt templates for hexDAG.
|
|
2
|
+
|
|
3
|
+
This module provides reusable, registry-based prompt templates that can be
|
|
4
|
+
composed using the builder pattern:
|
|
5
|
+
|
|
6
|
+
main_prompt + tool_prompt + fewshot_prompt
|
|
7
|
+
|
|
8
|
+
All prompts are registered in the component registry and can be referenced
|
|
9
|
+
in YAML configurations or composed programmatically.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
from hexdag.builtin.prompts.base import (
|
|
13
|
+
ChatFewShotTemplate,
|
|
14
|
+
ChatPromptTemplate,
|
|
15
|
+
FewShotPromptTemplate,
|
|
16
|
+
)
|
|
17
|
+
from hexdag.builtin.prompts.chat_prompts import (
|
|
18
|
+
ChatAnalysisPrompt,
|
|
19
|
+
ChatConversationalPrompt,
|
|
20
|
+
ChatFewShotQAPrompt,
|
|
21
|
+
ChatQAPrompt,
|
|
22
|
+
FewShotClassificationPrompt,
|
|
23
|
+
FewShotExtractionPrompt,
|
|
24
|
+
create_chat_prompt,
|
|
25
|
+
create_fewshot_prompt,
|
|
26
|
+
)
|
|
27
|
+
from hexdag.builtin.prompts.error_correction_prompts import (
|
|
28
|
+
GenericParseErrorPrompt,
|
|
29
|
+
JsonParseErrorPrompt,
|
|
30
|
+
JsonValidationErrorPrompt,
|
|
31
|
+
MarkdownJsonErrorPrompt,
|
|
32
|
+
SafeJsonInstructionsPrompt,
|
|
33
|
+
get_error_correction_prompt,
|
|
34
|
+
)
|
|
35
|
+
from hexdag.builtin.prompts.tool_prompts import (
|
|
36
|
+
FunctionToolPrompt,
|
|
37
|
+
JsonToolPrompt,
|
|
38
|
+
MixedToolPrompt,
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
__all__ = [
|
|
42
|
+
# Base template classes
|
|
43
|
+
"ChatPromptTemplate",
|
|
44
|
+
"FewShotPromptTemplate",
|
|
45
|
+
"ChatFewShotTemplate",
|
|
46
|
+
# Tool prompts
|
|
47
|
+
"FunctionToolPrompt",
|
|
48
|
+
"JsonToolPrompt",
|
|
49
|
+
"MixedToolPrompt",
|
|
50
|
+
# Chat prompts
|
|
51
|
+
"ChatQAPrompt",
|
|
52
|
+
"ChatAnalysisPrompt",
|
|
53
|
+
"ChatConversationalPrompt",
|
|
54
|
+
"ChatFewShotQAPrompt",
|
|
55
|
+
# Few-shot prompts
|
|
56
|
+
"FewShotClassificationPrompt",
|
|
57
|
+
"FewShotExtractionPrompt",
|
|
58
|
+
# Error correction prompts
|
|
59
|
+
"JsonParseErrorPrompt",
|
|
60
|
+
"JsonValidationErrorPrompt",
|
|
61
|
+
"MarkdownJsonErrorPrompt",
|
|
62
|
+
"SafeJsonInstructionsPrompt",
|
|
63
|
+
"GenericParseErrorPrompt",
|
|
64
|
+
"get_error_correction_prompt",
|
|
65
|
+
# Factories
|
|
66
|
+
"create_chat_prompt",
|
|
67
|
+
"create_fewshot_prompt",
|
|
68
|
+
]
|