hanzo-mcp 0.6.12__py3-none-any.whl → 0.7.0__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.
Potentially problematic release.
This version of hanzo-mcp might be problematic. Click here for more details.
- hanzo_mcp/__init__.py +2 -2
- hanzo_mcp/analytics/__init__.py +5 -0
- hanzo_mcp/analytics/posthog_analytics.py +364 -0
- hanzo_mcp/cli.py +5 -5
- hanzo_mcp/cli_enhanced.py +7 -7
- hanzo_mcp/cli_plugin.py +91 -0
- hanzo_mcp/config/__init__.py +1 -1
- hanzo_mcp/config/settings.py +70 -7
- hanzo_mcp/config/tool_config.py +20 -6
- hanzo_mcp/dev_server.py +3 -3
- hanzo_mcp/prompts/project_system.py +1 -1
- hanzo_mcp/server.py +40 -3
- hanzo_mcp/server_enhanced.py +69 -0
- hanzo_mcp/tools/__init__.py +140 -31
- hanzo_mcp/tools/agent/__init__.py +85 -4
- hanzo_mcp/tools/agent/agent_tool.py +104 -6
- hanzo_mcp/tools/agent/agent_tool_v2.py +459 -0
- hanzo_mcp/tools/agent/clarification_protocol.py +220 -0
- hanzo_mcp/tools/agent/clarification_tool.py +68 -0
- hanzo_mcp/tools/agent/claude_cli_tool.py +125 -0
- hanzo_mcp/tools/agent/claude_desktop_auth.py +508 -0
- hanzo_mcp/tools/agent/cli_agent_base.py +191 -0
- hanzo_mcp/tools/agent/code_auth.py +436 -0
- hanzo_mcp/tools/agent/code_auth_tool.py +194 -0
- hanzo_mcp/tools/agent/codex_cli_tool.py +123 -0
- hanzo_mcp/tools/agent/critic_tool.py +376 -0
- hanzo_mcp/tools/agent/gemini_cli_tool.py +128 -0
- hanzo_mcp/tools/agent/grok_cli_tool.py +128 -0
- hanzo_mcp/tools/agent/iching_tool.py +380 -0
- hanzo_mcp/tools/agent/network_tool.py +273 -0
- hanzo_mcp/tools/agent/prompt.py +62 -20
- hanzo_mcp/tools/agent/review_tool.py +433 -0
- hanzo_mcp/tools/agent/swarm_tool.py +535 -0
- hanzo_mcp/tools/agent/swarm_tool_v2.py +594 -0
- hanzo_mcp/tools/common/__init__.py +15 -1
- hanzo_mcp/tools/common/base.py +5 -4
- hanzo_mcp/tools/common/batch_tool.py +103 -11
- hanzo_mcp/tools/common/config_tool.py +2 -2
- hanzo_mcp/tools/common/context.py +2 -2
- hanzo_mcp/tools/common/context_fix.py +26 -0
- hanzo_mcp/tools/common/critic_tool.py +196 -0
- hanzo_mcp/tools/common/decorators.py +208 -0
- hanzo_mcp/tools/common/enhanced_base.py +106 -0
- hanzo_mcp/tools/common/fastmcp_pagination.py +369 -0
- hanzo_mcp/tools/common/forgiving_edit.py +243 -0
- hanzo_mcp/tools/common/mode.py +116 -0
- hanzo_mcp/tools/common/mode_loader.py +105 -0
- hanzo_mcp/tools/common/paginated_base.py +230 -0
- hanzo_mcp/tools/common/paginated_response.py +307 -0
- hanzo_mcp/tools/common/pagination.py +226 -0
- hanzo_mcp/tools/common/permissions.py +1 -1
- hanzo_mcp/tools/common/personality.py +936 -0
- hanzo_mcp/tools/common/plugin_loader.py +287 -0
- hanzo_mcp/tools/common/stats.py +4 -4
- hanzo_mcp/tools/common/tool_list.py +4 -1
- hanzo_mcp/tools/common/truncate.py +101 -0
- hanzo_mcp/tools/common/validation.py +1 -1
- hanzo_mcp/tools/config/__init__.py +3 -1
- hanzo_mcp/tools/config/config_tool.py +1 -1
- hanzo_mcp/tools/config/mode_tool.py +209 -0
- hanzo_mcp/tools/database/__init__.py +1 -1
- hanzo_mcp/tools/editor/__init__.py +1 -1
- hanzo_mcp/tools/filesystem/__init__.py +48 -14
- hanzo_mcp/tools/filesystem/ast_multi_edit.py +562 -0
- hanzo_mcp/tools/filesystem/batch_search.py +3 -3
- hanzo_mcp/tools/filesystem/diff.py +2 -2
- hanzo_mcp/tools/filesystem/directory_tree_paginated.py +338 -0
- hanzo_mcp/tools/filesystem/rules_tool.py +235 -0
- hanzo_mcp/tools/filesystem/{unified_search.py → search_tool.py} +12 -12
- hanzo_mcp/tools/filesystem/{symbols_unified.py → symbols_tool.py} +104 -5
- hanzo_mcp/tools/filesystem/watch.py +3 -2
- hanzo_mcp/tools/jupyter/__init__.py +2 -2
- hanzo_mcp/tools/jupyter/jupyter.py +1 -1
- hanzo_mcp/tools/llm/__init__.py +3 -3
- hanzo_mcp/tools/llm/llm_tool.py +648 -143
- hanzo_mcp/tools/lsp/__init__.py +5 -0
- hanzo_mcp/tools/lsp/lsp_tool.py +512 -0
- hanzo_mcp/tools/mcp/__init__.py +2 -2
- hanzo_mcp/tools/mcp/{mcp_unified.py → mcp_tool.py} +3 -3
- hanzo_mcp/tools/memory/__init__.py +76 -0
- hanzo_mcp/tools/memory/knowledge_tools.py +518 -0
- hanzo_mcp/tools/memory/memory_tools.py +456 -0
- hanzo_mcp/tools/search/__init__.py +6 -0
- hanzo_mcp/tools/search/find_tool.py +581 -0
- hanzo_mcp/tools/search/unified_search.py +953 -0
- hanzo_mcp/tools/shell/__init__.py +11 -6
- hanzo_mcp/tools/shell/auto_background.py +203 -0
- hanzo_mcp/tools/shell/base_process.py +57 -29
- hanzo_mcp/tools/shell/bash_session_executor.py +1 -1
- hanzo_mcp/tools/shell/{bash_unified.py → bash_tool.py} +18 -34
- hanzo_mcp/tools/shell/command_executor.py +2 -2
- hanzo_mcp/tools/shell/{npx_unified.py → npx_tool.py} +16 -33
- hanzo_mcp/tools/shell/open.py +2 -2
- hanzo_mcp/tools/shell/{process_unified.py → process_tool.py} +1 -1
- hanzo_mcp/tools/shell/run_command_windows.py +1 -1
- hanzo_mcp/tools/shell/streaming_command.py +594 -0
- hanzo_mcp/tools/shell/uvx.py +47 -2
- hanzo_mcp/tools/shell/uvx_background.py +47 -2
- hanzo_mcp/tools/shell/{uvx_unified.py → uvx_tool.py} +16 -33
- hanzo_mcp/tools/todo/__init__.py +14 -19
- hanzo_mcp/tools/todo/todo.py +22 -1
- hanzo_mcp/tools/vector/__init__.py +1 -1
- hanzo_mcp/tools/vector/infinity_store.py +2 -2
- hanzo_mcp/tools/vector/project_manager.py +1 -1
- hanzo_mcp/types.py +23 -0
- hanzo_mcp-0.7.0.dist-info/METADATA +516 -0
- hanzo_mcp-0.7.0.dist-info/RECORD +180 -0
- {hanzo_mcp-0.6.12.dist-info → hanzo_mcp-0.7.0.dist-info}/entry_points.txt +1 -0
- hanzo_mcp/tools/common/palette.py +0 -344
- hanzo_mcp/tools/common/palette_loader.py +0 -108
- hanzo_mcp/tools/config/palette_tool.py +0 -179
- hanzo_mcp/tools/llm/llm_unified.py +0 -851
- hanzo_mcp-0.6.12.dist-info/METADATA +0 -339
- hanzo_mcp-0.6.12.dist-info/RECORD +0 -135
- hanzo_mcp-0.6.12.dist-info/licenses/LICENSE +0 -21
- {hanzo_mcp-0.6.12.dist-info → hanzo_mcp-0.7.0.dist-info}/WHEEL +0 -0
- {hanzo_mcp-0.6.12.dist-info → hanzo_mcp-0.7.0.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
"""Network tool for dispatching work to agent networks.
|
|
2
|
+
|
|
3
|
+
This tool enables distributed AI workloads across local and remote agent networks,
|
|
4
|
+
with support for both local-only execution (via hanzo-miner) and cloud fallback.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import asyncio
|
|
8
|
+
import json
|
|
9
|
+
import os
|
|
10
|
+
from typing import Annotated, TypedDict, Unpack, final, override, Optional, Dict, Any, List
|
|
11
|
+
|
|
12
|
+
from mcp.server.fastmcp import Context as MCPContext
|
|
13
|
+
from mcp.server import FastMCP
|
|
14
|
+
from pydantic import Field
|
|
15
|
+
|
|
16
|
+
from hanzo_mcp.tools.common.base import BaseTool
|
|
17
|
+
from hanzo_mcp.tools.common.context import ToolContext, create_tool_context
|
|
18
|
+
from hanzo_mcp.tools.common.permissions import PermissionManager
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
# Import hanzo cluster if available
|
|
22
|
+
try:
|
|
23
|
+
from hanzoai import cluster
|
|
24
|
+
CLUSTER_AVAILABLE = True
|
|
25
|
+
except ImportError:
|
|
26
|
+
CLUSTER_AVAILABLE = False
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class NetworkToolParams(TypedDict, total=False):
|
|
30
|
+
"""Parameters for the network tool."""
|
|
31
|
+
task: str
|
|
32
|
+
agents: Optional[List[str]]
|
|
33
|
+
mode: Optional[str] # "local", "distributed", "hybrid"
|
|
34
|
+
model: Optional[str]
|
|
35
|
+
routing: Optional[str] # "sequential", "parallel", "consensus"
|
|
36
|
+
require_local: Optional[bool]
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
@final
|
|
40
|
+
class NetworkTool(BaseTool):
|
|
41
|
+
"""Dispatch work to agent networks for distributed AI processing.
|
|
42
|
+
|
|
43
|
+
Modes:
|
|
44
|
+
- local: Use only local compute (via hanzo-cluster/miner)
|
|
45
|
+
- distributed: Use available network resources
|
|
46
|
+
- hybrid: Prefer local, fallback to cloud
|
|
47
|
+
|
|
48
|
+
This tool is the evolution of the swarm tool, providing:
|
|
49
|
+
- True distributed execution across devices
|
|
50
|
+
- Local-first privacy-preserving AI
|
|
51
|
+
- Automatic routing and load balancing
|
|
52
|
+
- Integration with hanzo-miner for compute contribution
|
|
53
|
+
"""
|
|
54
|
+
|
|
55
|
+
name = "network"
|
|
56
|
+
description = "Dispatch tasks to agent networks for distributed AI processing"
|
|
57
|
+
|
|
58
|
+
def __init__(
|
|
59
|
+
self,
|
|
60
|
+
permission_manager: PermissionManager,
|
|
61
|
+
default_mode: str = "hybrid",
|
|
62
|
+
cluster_endpoint: str = None,
|
|
63
|
+
):
|
|
64
|
+
"""Initialize the network tool.
|
|
65
|
+
|
|
66
|
+
Args:
|
|
67
|
+
permission_manager: Permission manager
|
|
68
|
+
default_mode: Default execution mode
|
|
69
|
+
cluster_endpoint: Optional cluster endpoint
|
|
70
|
+
"""
|
|
71
|
+
super().__init__(permission_manager)
|
|
72
|
+
self.default_mode = default_mode
|
|
73
|
+
self.cluster_endpoint = cluster_endpoint or os.environ.get(
|
|
74
|
+
"HANZO_CLUSTER_ENDPOINT",
|
|
75
|
+
"http://localhost:8000"
|
|
76
|
+
)
|
|
77
|
+
self._cluster = None
|
|
78
|
+
|
|
79
|
+
async def _ensure_cluster(self):
|
|
80
|
+
"""Ensure we have a cluster connection."""
|
|
81
|
+
if not CLUSTER_AVAILABLE:
|
|
82
|
+
return None
|
|
83
|
+
|
|
84
|
+
if not self._cluster:
|
|
85
|
+
try:
|
|
86
|
+
# Try to connect to existing cluster
|
|
87
|
+
self._cluster = cluster.HanzoCluster()
|
|
88
|
+
# Check if cluster is running
|
|
89
|
+
import httpx
|
|
90
|
+
async with httpx.AsyncClient() as client:
|
|
91
|
+
response = await client.get(f"{self.cluster_endpoint}/health")
|
|
92
|
+
if response.status_code != 200:
|
|
93
|
+
# Start local cluster if not running
|
|
94
|
+
await self._cluster.start()
|
|
95
|
+
except Exception:
|
|
96
|
+
# Cluster not available
|
|
97
|
+
self._cluster = None
|
|
98
|
+
|
|
99
|
+
return self._cluster
|
|
100
|
+
|
|
101
|
+
@override
|
|
102
|
+
async def call(
|
|
103
|
+
self, ctx: MCPContext, **params: Unpack[NetworkToolParams]
|
|
104
|
+
) -> str:
|
|
105
|
+
"""Execute a task on the agent network.
|
|
106
|
+
|
|
107
|
+
Args:
|
|
108
|
+
ctx: MCP context
|
|
109
|
+
task: Task description to execute
|
|
110
|
+
agents: Optional list of specific agents to use
|
|
111
|
+
mode: Execution mode (local/distributed/hybrid)
|
|
112
|
+
model: Optional model preference
|
|
113
|
+
routing: Routing strategy
|
|
114
|
+
require_local: Require local-only execution
|
|
115
|
+
|
|
116
|
+
Returns:
|
|
117
|
+
JSON string with results
|
|
118
|
+
"""
|
|
119
|
+
task = params.get("task", "")
|
|
120
|
+
if not task:
|
|
121
|
+
return json.dumps({
|
|
122
|
+
"error": "Task description required",
|
|
123
|
+
"success": False
|
|
124
|
+
})
|
|
125
|
+
|
|
126
|
+
mode = params.get("mode", self.default_mode)
|
|
127
|
+
agents_list = params.get("agents", [])
|
|
128
|
+
model_pref = params.get("model")
|
|
129
|
+
routing = params.get("routing", "sequential")
|
|
130
|
+
require_local = params.get("require_local", False)
|
|
131
|
+
|
|
132
|
+
# Check if we should use local cluster
|
|
133
|
+
use_local = mode in ["local", "hybrid"] or require_local
|
|
134
|
+
|
|
135
|
+
results = {
|
|
136
|
+
"task": task,
|
|
137
|
+
"mode": mode,
|
|
138
|
+
"routing": routing,
|
|
139
|
+
"agents_used": [],
|
|
140
|
+
"results": [],
|
|
141
|
+
"success": False
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
try:
|
|
145
|
+
# Try local execution first if requested
|
|
146
|
+
if use_local:
|
|
147
|
+
cluster = await self._ensure_cluster()
|
|
148
|
+
if cluster:
|
|
149
|
+
try:
|
|
150
|
+
# Execute on local cluster
|
|
151
|
+
local_result = await cluster.inference(
|
|
152
|
+
prompt=task,
|
|
153
|
+
model=model_pref or "llama-3.2-3b",
|
|
154
|
+
max_tokens=4000
|
|
155
|
+
)
|
|
156
|
+
|
|
157
|
+
results["agents_used"].append("local-cluster")
|
|
158
|
+
results["results"].append({
|
|
159
|
+
"agent": "local-cluster",
|
|
160
|
+
"response": local_result.get("choices", [{}])[0].get("text", ""),
|
|
161
|
+
"local": True
|
|
162
|
+
})
|
|
163
|
+
results["success"] = True
|
|
164
|
+
|
|
165
|
+
# If local succeeded and not hybrid, return
|
|
166
|
+
if mode == "local" or (mode == "hybrid" and results["results"]):
|
|
167
|
+
return json.dumps(results, indent=2)
|
|
168
|
+
|
|
169
|
+
except Exception as e:
|
|
170
|
+
if require_local:
|
|
171
|
+
results["error"] = f"Local execution failed: {str(e)}"
|
|
172
|
+
return json.dumps(results, indent=2)
|
|
173
|
+
|
|
174
|
+
# Fallback to agent-based execution
|
|
175
|
+
# This would use hanzo-agents or the existing swarm implementation
|
|
176
|
+
if not results["success"] or mode in ["distributed", "hybrid"]:
|
|
177
|
+
# Import swarm tool as fallback
|
|
178
|
+
from hanzo_mcp.tools.agent.swarm_tool import SwarmTool
|
|
179
|
+
|
|
180
|
+
# Create temporary swarm tool
|
|
181
|
+
swarm = SwarmTool(
|
|
182
|
+
permission_manager=self.permission_manager,
|
|
183
|
+
model=model_pref
|
|
184
|
+
)
|
|
185
|
+
|
|
186
|
+
# Convert network params to swarm params
|
|
187
|
+
swarm_params = {
|
|
188
|
+
"prompts": [task] if not agents_list else agents_list,
|
|
189
|
+
"consensus": routing == "consensus",
|
|
190
|
+
"parallel": routing == "parallel",
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
# Execute via swarm
|
|
194
|
+
swarm_result = await swarm.call(ctx, **swarm_params)
|
|
195
|
+
swarm_data = json.loads(swarm_result)
|
|
196
|
+
|
|
197
|
+
# Merge results
|
|
198
|
+
if swarm_data.get("success"):
|
|
199
|
+
results["agents_used"].extend([r["agent"] for r in swarm_data.get("results", [])])
|
|
200
|
+
results["results"].extend(swarm_data.get("results", []))
|
|
201
|
+
results["success"] = True
|
|
202
|
+
else:
|
|
203
|
+
results["error"] = swarm_data.get("error", "Unknown error")
|
|
204
|
+
|
|
205
|
+
except Exception as e:
|
|
206
|
+
results["error"] = str(e)
|
|
207
|
+
|
|
208
|
+
return json.dumps(results, indent=2)
|
|
209
|
+
|
|
210
|
+
@classmethod
|
|
211
|
+
def register(cls, server: FastMCP, permission_manager: PermissionManager):
|
|
212
|
+
"""Register the network tool with the server.
|
|
213
|
+
|
|
214
|
+
Args:
|
|
215
|
+
server: FastMCP server instance
|
|
216
|
+
permission_manager: Permission manager
|
|
217
|
+
"""
|
|
218
|
+
tool = cls(permission_manager=permission_manager)
|
|
219
|
+
|
|
220
|
+
@server.tool(
|
|
221
|
+
name=tool.name,
|
|
222
|
+
description=tool.description
|
|
223
|
+
)
|
|
224
|
+
async def network_handler(
|
|
225
|
+
ctx: MCPContext,
|
|
226
|
+
task: Annotated[str, Field(description="Task to execute on the network")],
|
|
227
|
+
agents: Annotated[Optional[List[str]], Field(description="Specific agents to use")] = None,
|
|
228
|
+
mode: Annotated[Optional[str], Field(description="Execution mode: local, distributed, or hybrid")] = None,
|
|
229
|
+
model: Annotated[Optional[str], Field(description="Model preference")] = None,
|
|
230
|
+
routing: Annotated[Optional[str], Field(description="Routing strategy: sequential, parallel, or consensus")] = None,
|
|
231
|
+
require_local: Annotated[Optional[bool], Field(description="Require local-only execution")] = None,
|
|
232
|
+
) -> str:
|
|
233
|
+
"""Dispatch work to agent networks."""
|
|
234
|
+
params = NetworkToolParams(
|
|
235
|
+
task=task,
|
|
236
|
+
agents=agents,
|
|
237
|
+
mode=mode,
|
|
238
|
+
model=model,
|
|
239
|
+
routing=routing,
|
|
240
|
+
require_local=require_local,
|
|
241
|
+
)
|
|
242
|
+
return await tool.call(ctx, **params)
|
|
243
|
+
|
|
244
|
+
return tool
|
|
245
|
+
|
|
246
|
+
|
|
247
|
+
# Alias swarm to use network tool with local-only mode
|
|
248
|
+
@final
|
|
249
|
+
class LocalSwarmTool(NetworkTool):
|
|
250
|
+
"""Local-only version of the network tool (swarm compatibility).
|
|
251
|
+
|
|
252
|
+
This provides backward compatibility with the swarm tool
|
|
253
|
+
while using local compute resources only.
|
|
254
|
+
"""
|
|
255
|
+
|
|
256
|
+
name = "swarm"
|
|
257
|
+
description = "Run agent swarms locally using hanzo-miner compute"
|
|
258
|
+
|
|
259
|
+
def __init__(self, permission_manager: PermissionManager, **kwargs):
|
|
260
|
+
"""Initialize as local-only network."""
|
|
261
|
+
super().__init__(
|
|
262
|
+
permission_manager=permission_manager,
|
|
263
|
+
default_mode="local",
|
|
264
|
+
**kwargs
|
|
265
|
+
)
|
|
266
|
+
|
|
267
|
+
@override
|
|
268
|
+
async def call(self, ctx: MCPContext, **params: Unpack[NetworkToolParams]) -> str:
|
|
269
|
+
"""Execute with local-only mode."""
|
|
270
|
+
# Force local mode
|
|
271
|
+
params["mode"] = "local"
|
|
272
|
+
params["require_local"] = True
|
|
273
|
+
return await super().call(ctx, **params)
|
hanzo_mcp/tools/agent/prompt.py
CHANGED
|
@@ -49,23 +49,63 @@ def get_system_prompt(
|
|
|
49
49
|
# Extract tool names for display
|
|
50
50
|
tool_names = ", ".join(f"`{tool.name}`" for tool in filtered_tools)
|
|
51
51
|
|
|
52
|
-
# Base system prompt
|
|
53
|
-
system_prompt = f"""You are a sub-agent
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
1. You
|
|
57
|
-
2. You
|
|
58
|
-
3.
|
|
59
|
-
4.
|
|
60
|
-
5. When relevant, share file names and code snippets
|
|
61
|
-
6. Any file paths you return
|
|
62
|
-
7.
|
|
52
|
+
# Base system prompt - agents always have edit tools
|
|
53
|
+
system_prompt = f"""You are a Claude sub-agent with access to these tools: {tool_names}.
|
|
54
|
+
|
|
55
|
+
CAPABILITIES:
|
|
56
|
+
1. You have FULL read and write access - you can create, edit, and modify files
|
|
57
|
+
2. You can ask clarifying questions if needed - your response goes to the coordinating agent
|
|
58
|
+
3. You work as part of a team of specialized agents
|
|
59
|
+
4. Other agents may be available via MCP tools (look for tools named after agents)
|
|
60
|
+
5. When relevant, share file names and code snippets
|
|
61
|
+
6. Any file paths you return MUST be absolute. DO NOT use relative paths.
|
|
62
|
+
7. You can only work with the absolute paths provided in your task prompt.
|
|
63
|
+
|
|
64
|
+
CLARIFICATION:
|
|
65
|
+
- You can request clarification ONCE per task using the request_clarification tool
|
|
66
|
+
- Use this when instructions are ambiguous or you need additional context
|
|
67
|
+
- Types: AMBIGUOUS_INSTRUCTION, MISSING_CONTEXT, MULTIPLE_OPTIONS, CONFIRMATION_NEEDED, ADDITIONAL_INFO
|
|
68
|
+
- The main loop will provide automated guidance based on context
|
|
69
|
+
|
|
70
|
+
CRITICAL REVIEW (Devil's Advocate):
|
|
71
|
+
- Use the critic tool to get harsh, challenging feedback that attacks assumptions
|
|
72
|
+
- The critic will find flaws and push for improvements aggressively
|
|
73
|
+
- You can request up to 2 critic reviews per task
|
|
74
|
+
- Review types: CODE_QUALITY, CORRECTNESS, PERFORMANCE, SECURITY, COMPLETENESS, BEST_PRACTICES, GENERAL
|
|
75
|
+
- Use when you need someone to find what's wrong with your approach
|
|
76
|
+
|
|
77
|
+
BALANCED REVIEW:
|
|
78
|
+
- Use the review tool for constructive, balanced code review
|
|
79
|
+
- Provides objective assessment without predetermined bias
|
|
80
|
+
- You can request up to 3 reviews per task
|
|
81
|
+
- Focus areas: GENERAL, FUNCTIONALITY, READABILITY, MAINTAINABILITY, TESTING, DOCUMENTATION, ARCHITECTURE
|
|
82
|
+
- Use for regular code review and feedback
|
|
83
|
+
|
|
84
|
+
CREATIVE GUIDANCE:
|
|
85
|
+
- Use the iching tool when you need creative problem-solving approaches
|
|
86
|
+
- Combines ancient I Ching wisdom with Hanzo engineering principles
|
|
87
|
+
- Provides unique perspectives and actionable guidance
|
|
88
|
+
- Use when stuck, need fresh ideas, or want philosophical alignment
|
|
89
|
+
|
|
90
|
+
EDITING GUIDELINES:
|
|
91
|
+
- ALWAYS read the file first before attempting any edits
|
|
92
|
+
- For edit tool: The old_string must match EXACTLY including all whitespace, tabs, and newlines
|
|
93
|
+
- When copying text from read output, be careful with line numbers and indentation
|
|
94
|
+
- If an edit fails due to whitespace mismatch, try reading the specific lines again
|
|
95
|
+
- Prefer multi_edit when making multiple changes to the same file
|
|
96
|
+
- Test your edits by verifying the exact string exists in the file first
|
|
97
|
+
|
|
98
|
+
COLLABORATION:
|
|
99
|
+
- If you see MCP tools named after other agents, you can communicate with them
|
|
100
|
+
- Use agent MCP tools to delegate specialized tasks or get expert opinions
|
|
101
|
+
- Share context when communicating with other agents
|
|
63
102
|
|
|
64
103
|
RESPONSE FORMAT:
|
|
65
|
-
- Begin with a summary of
|
|
66
|
-
-
|
|
67
|
-
-
|
|
68
|
-
-
|
|
104
|
+
- Begin with a summary of what you did or found
|
|
105
|
+
- If you have questions, ask them clearly
|
|
106
|
+
- Include details of any edits performed
|
|
107
|
+
- Report any errors encountered
|
|
108
|
+
- End with clear conclusions or next steps
|
|
69
109
|
"""
|
|
70
110
|
|
|
71
111
|
return system_prompt
|
|
@@ -95,21 +135,23 @@ def get_default_model(model_override: str | None = None) -> str:
|
|
|
95
135
|
return f"{provider}/{model_override}"
|
|
96
136
|
|
|
97
137
|
# Fall back to environment variables
|
|
98
|
-
|
|
138
|
+
# Default to Sonnet for cost efficiency
|
|
139
|
+
model = os.environ.get("AGENT_MODEL", "claude-3-5-sonnet-20241022")
|
|
99
140
|
|
|
100
141
|
# Special cases for tests
|
|
101
142
|
if (
|
|
102
143
|
model.startswith("test-model")
|
|
103
|
-
or model == "
|
|
104
|
-
and "TEST_MODE" in os.environ
|
|
144
|
+
or "TEST_MODE" in os.environ and model == "claude-3-5-sonnet-20241022"
|
|
105
145
|
):
|
|
106
146
|
return model
|
|
107
147
|
|
|
108
|
-
provider = os.environ.get("AGENT_PROVIDER", "
|
|
148
|
+
provider = os.environ.get("AGENT_PROVIDER", "anthropic")
|
|
109
149
|
|
|
110
150
|
# Only add provider prefix if it's not already in the model name
|
|
111
|
-
if "/" not in model and provider != "
|
|
151
|
+
if "/" not in model and provider != "anthropic":
|
|
112
152
|
return f"{provider}/{model}"
|
|
153
|
+
elif "/" not in model and provider == "anthropic":
|
|
154
|
+
return f"anthropic/{model}"
|
|
113
155
|
elif "/" not in model:
|
|
114
156
|
return f"openai/{model}"
|
|
115
157
|
else:
|