import json
import os
import subprocess
import requests
API_KEY = os.getenv("ANTHROPIC_API_KEY")
BASE_URL = os.getenv("ANTHROPIC_BASE_URL", "http://localhost:8080")
SYSTEM_PROMPT = """
Ты терминальный AI-агент.
Если нужен инструмент, отвечай ТОЛЬКО JSON.
Пример:
{
"tool": "write_file",
"args": {
"path": "hello.py",
"content": "print('hello')"
}
}
Доступные инструменты:
read_file(path)
write_file(path, content)
list_files(path)
run_command(command)
Если инструмент не нужен — отвечай обычным текстом.
"""
def read_file(path):
with open(path, "r", encoding="utf-8") as f:
return f.read()
def write_file(path, content):
with open(path, "w", encoding="utf-8") as f:
f.write(content)
return f"saved: {path}"
def list_files(path="."):
return "\n".join(os.listdir(path))
def run_command(command):
result = subprocess.run(
command,
shell=True,
capture_output=True,
text=True
)
return result.stdout + result.stderr
TOOLS = {
"read_file": read_file,
"write_file": write_file,
"list_files": list_files,
"run_command": run_command,
}
messages = []
def ask_llm():
payload = {
"model": "claude-sonnet-4",
"messages": messages,
"system": SYSTEM_PROMPT,
"max_tokens": 4000
}
headers = {
"Authorization": f"Bearer {API_KEY}",
"Content-Type": "application/json"
}
r = requests.post(
f"{BASE_URL}/v1/messages",
json=payload,
headers=headers,
timeout=300
)
r.raise_for_status()
data = r.json()
try:
return data["content"][0]["text"]
except Exception:
return str(data)
while True:
user = input("\n> ")
if user.lower() in ["exit", "quit"]:
break
messages.append({
"role": "user",
"content": user
})
for _ in range(10):
response = ask_llm()
print("\nAI:")
print(response)
try:
call = json.loads(response)
tool_name = call["tool"]
args = call["args"]
if tool_name not in TOOLS:
break
result = TOOLS[tool_name](**args)
print("\nTOOL RESULT:")
print(result)
messages.append({
"role": "assistant",
"content": response
})
messages.append({
"role": "user",
"content": f"Tool result:\n{result}"
})
except Exception:
messages.append({
"role": "assistant",
"content": response
})
break