Files
hack/tools/scripts/llm-key-hunter/results/_cache/content/anujbolewar_katalyst.json
T

1 line
20 KiB
JSON

{"repo": "anujbolewar/katalyst", "files": {"cli-engine/main.py": {"0fcb6d680f56ababab599bccf8fcc85b6a6a5197": {"t": 1785747512.7231996, "n": 9223, "h": "c589e5163db2778d", "c": "#!/usr/bin/env python3\n\"\"\"Custom Python Agent Engine for Katalyst daemon.\n\nUsage:\n main.py -p \"<prompt>\" --output-format json --max-turns <N>\n\nUses OpenAI-compatible API with a ReAct tool-calling loop.\nOutputs JSON matching ClaudeOutputMeta format to stdout.\n\"\"\"\n\nimport argparse\nimport json\nimport os\nimport sys\nfrom typing import Any\n\n# Load .env file if present (secrets written by Settings page)\nfrom dotenv import load_dotenv\nload_dotenv(os.path.join(os.path.dirname(__file__), \".env\"))\n\nfrom tools import TOOLS, dispatch\n\n\n# ─── Config ────────────────────────────────────────────────────────────────\n\nMODEL = \"deepseek/deepseek-chat\"\nMAX_TOKENS = 8192\nWORKSPACE = os.path.realpath(os.path.join(os.path.dirname(__file__), \"..\"))\n\nSYSTEM_PROMPT = \"\"\"You are an expert software engineering agent. You have access to tools for:\n\n- bash_command: Run shell commands (git, npm, ls, cat, grep, find, etc.)\n- read_file: Read any file in the project\n- write_file: Create or overwrite files\n- glob_search: Find files by pattern\n- grep_search: Search file contents with regex\n- task_complete: Signal that the task is finished\n\nIMPORTANT RULES:\n1. Work in the project root directory.\n2. Read files before editing them.\n3. When the task is complete, call task_complete with a summary.\n4. If you encounter errors, try alternative approaches.\n5. Do not ask questions — make decisions and proceed.\n6. Keep responses concise and action-oriented.\n\"\"\"\n\n\n# ─── OpenAI Client ─────────────────────────────────────────────────────────\n\ndef get_client():\n from openai import OpenAI\n\n api_key = _resolve_api_key()\n base_url = (\n os.environ.get(\"CUSTOM_ENGINE_BASE_URL\") or\n os.environ.get(\"OPENAI_API_BASE\") or\n \"https://openrouter.ai/api/v1\"\n )\n return OpenAI(api_key=api_key, base_url=base_url)\n\n\ndef _resolve_api_key() -> str:\n # 1. OPENROUTER_API_KEY env var\n key = os.environ.get(\"OPENROUTER_API_KEY\")\n if key and key not in (\"\", \"your_api_key_here\", \"sk-your-key-here\"):\n return key\n\n # 2. OPENAI_API_KEY env var\n key = os.environ.get(\"OPENAI_API_KEY\")\n if key and key not in (\"\", \"your_api_key_here\", \"sk-your-key-here\"):\n return key\n\n # 3. CUSTOM_ENGINE_API_KEY from .env (written by settings page)\n key = os.environ.get(\"CUSTOM_ENGINE_API_KEY\")\n if key:\n return key\n\n # 4. Read opencode-go key from opencode's auth.json\n key = _read_opencode_key()\n if key:\n return key\n\n # 5. Read openrouter key from auth.json\n key = _read_openrouter_key()\n if key:\n return key\n\n raise RuntimeError(\n \"No API key found. Set CUSTOM_ENGINE_API_KEY or OPENROUTER_API_KEY \"\n \"in the Settings page, or configure one in your environment.\"\n )\n\n\ndef _read_opencode_key() -> str | None:\n import json\n auth_paths = [\n os.path.expanduser(\"~/.local/share/opencode/auth.json\"),\n os.path.expanduser(\"~/.opencode/auth.json\"),\n ]\n for auth_path in auth_paths:\n try:\n with open(auth_path) as f:\n data = json.load(f)\n entry = data.get(\"opencode-go\", {})\n key = entry.get(\"key\")\n if key and key not in (\"\", \"your_api_key_here\"):\n return key\n except (FileNotFoundError, KeyError, json.JSONDecodeError):\n continue\n return None\n\n\ndef _read_openrouter_key() -> str | None:\n try:\n with open(os.path.expanduser(\"~/.local/share/opencode/auth.json\")) as f:\n data = json.load(f)\n # OpenRouter credentials are in account.json under the \"openrouter\" service\n account_path = os.path.expanduser(\"~/.local/share/opencode/account.json\")\n with open(account_path) as f:\n accounts = json.load(f)\n for a in accounts.get(\"accounts\", {}).values():\n if a.get(\"serviceID\") == \"openrouter\":\n key = a.get(\"credential\", {}).get(\"key\")\n if key and key not in (\"\", \"your_api_key_here\"):\n return key\n except (FileNotFoundError, KeyError, json.JSONDecodeError):\n pass\n return None\n\n\ndef call_openai(\n client, messages: list[dict[str, Any]], tools: list[dict[str, Any]]\n) -> dict[str, Any]:\n response = client.chat.completions.create(\n model=MODEL,\n max_tokens=MAX_TOKENS,\n messages=messages,\n tools=tools,\n )\n choice = response.choices[0]\n msg = choice.message\n\n tool_calls = []\n if msg.tool_calls:\n for tc in msg.tool_calls:\n try:\n args = json.loads(tc.function.arguments)\n except json.JSONDecodeError:\n args = {}\n tool_calls.append(\n {\n \"id\": tc.id,\n \"name\": tc.function.name,\n \"arguments\": args,\n }\n )\n\n return {\n \"content\": msg.content or \"\",\n \"tool_calls\": tool_calls,\n \"finish_reason\": choice.finish_reason,\n \"usage\": {\n \"input_tokens\": response.usage.prompt_tokens if response.usage else 0,\n \"output_tokens\": response.usage.completion_tokens if response.usage else 0,\n \"cache_read_input_tokens\": 0,\n \"cache_creation_input_tokens\": 0,\n },\n }\n\n\n# ─── ReAct Loop ────────────────────────────────────────────────────────────\n\ndef run_loop(prompt: str, max_turns: int) -> dict[str, Any]:\n client = get_client()\n\n messages: list[dict[str, Any]] = [\n {\"role\": \"system\", \"content\": SYSTEM_PROMPT},\n {\"role\": \"user\", \"content\": prompt},\n ]\n\n total_input = 0\n total_output = 0\n final_result = \"\"\n subtype = \"success\"\n is_error = False\n\n for turn in range(max_turns):\n try:\n response = call_openai(client, messages, TOOLS)\n except Exception as e:\n return {\n \"total_cost_usd\": 0,\n \"num_turns\": turn,\n \"subtype\": \"error_api\",\n \"session_id\": None,\n \"is_error\": True,\n \"result\": f\"API error on turn {turn + 1}: {e}\",\n \"usage\": {\n \"input_tokens\": total_input,\n \"output_tokens\": total_output,\n \"cache_read_input_tokens\": 0,\n \"cache_creation_input_tokens\": 0,\n },\n }\n\n usage = response[\"usage\"]\n total_input += usage[\"input_tokens\"]\n total_output += usage[\"output_tokens\"]\n\n content = response[\"content\"]\n tool_calls = response[\"tool_calls\"]\n\n # Append assistant message\n assistant_msg: dict[str, Any] = {\"role\": \"assistant\"}\n if content:\n assistant_msg[\"content\"] = content\n if tool_calls:\n assistant_msg[\"tool_calls\"] = [\n {\n \"id\": tc[\"id\"],\n \"type\": \"function\",\n \"function\": {\n \"name\": tc[\"name\"],\n \"arguments\": json.dumps(tc[\"arguments\"]),\n },\n }\n for tc in tool_calls\n ]\n messages.append(assistant_msg)\n\n # If no tool calls, agent is done\n if not tool_calls or response[\"finish_reason\"] == \"stop\":\n final_result = content\n break\n\n # Execute tool calls and collect results\n for tc in tool_calls:\n tool_name = tc[\"name\"]\n tool_input = tc[\"arguments\"]\n result_text = dispatch(tool_name, tool_input, WORKSPACE)\n\n messages.append(\n {\n \"role\": \"tool\",\n \"tool_call_id\": tc[\"id\"],\n \"content\": result_text,\n }\n )\n\n if tool_name == \"task_complete\":\n final_result = tool_input.get(\"summary\", result_text)\n subtype = \"success\"\n break\n\n if any(tc[\"name\"] == \"task_complete\" for tc in tool_calls):\n break\n\n else:\n subtype = \"error_max_turns\"\n is_error = True\n final_result = final_result or \"Max turns reached without completion.\"\n\n return {\n \"total_cost_usd\": 0,\n \"num_turns\": turn + 1,\n \"subtype\": subtype,\n \"session_id\": None,\n \"is_error\": is_error,\n \"result\": final_result.strip(),\n \"usage\": {\n \"input_tokens\": total_input,\n \"output_tokens\": total_output,\n \"cache_read_input_tokens\": 0,\n \"cache_creation_input_tokens\": 0,\n },\n }\n\n\n# ─── Main ──────────────────────────────────────────────────────────────────\n\ndef main():\n parser = argparse.ArgumentParser(description=\"Katalyst Custom Agent Engine\")\n parser.add_argument(\"-p\", \"--prompt\", required=True, help=\"Task prompt\")\n parser.add_argument(\n \"--output-format\", default=\"json\", help=\"Output format (ignored, always JSON)\"\n )\n parser.add_argument(\n \"--max-turns\", type=int, default=25, help=\"Maximum tool-calling turns\"\n )\n args = parser.parse_args()\n\n result = run_loop(args.prompt, args.max_turns)\n print(json.dumps(result))\n\n\nif __name__ == \"__main__\":\n main()\n"}, "4076dde218c478d9b42949e37ef9a80efe00f998": {"t": 1785773689.8534214, "n": 9223, "h": "c589e5163db2778d", "c": "#!/usr/bin/env python3\n\"\"\"Custom Python Agent Engine for Katalyst daemon.\n\nUsage:\n main.py -p \"<prompt>\" --output-format json --max-turns <N>\n\nUses OpenAI-compatible API with a ReAct tool-calling loop.\nOutputs JSON matching ClaudeOutputMeta format to stdout.\n\"\"\"\n\nimport argparse\nimport json\nimport os\nimport sys\nfrom typing import Any\n\n# Load .env file if present (secrets written by Settings page)\nfrom dotenv import load_dotenv\nload_dotenv(os.path.join(os.path.dirname(__file__), \".env\"))\n\nfrom tools import TOOLS, dispatch\n\n\n# ─── Config ────────────────────────────────────────────────────────────────\n\nMODEL = \"deepseek/deepseek-chat\"\nMAX_TOKENS = 8192\nWORKSPACE = os.path.realpath(os.path.join(os.path.dirname(__file__), \"..\"))\n\nSYSTEM_PROMPT = \"\"\"You are an expert software engineering agent. You have access to tools for:\n\n- bash_command: Run shell commands (git, npm, ls, cat, grep, find, etc.)\n- read_file: Read any file in the project\n- write_file: Create or overwrite files\n- glob_search: Find files by pattern\n- grep_search: Search file contents with regex\n- task_complete: Signal that the task is finished\n\nIMPORTANT RULES:\n1. Work in the project root directory.\n2. Read files before editing them.\n3. When the task is complete, call task_complete with a summary.\n4. If you encounter errors, try alternative approaches.\n5. Do not ask questions — make decisions and proceed.\n6. Keep responses concise and action-oriented.\n\"\"\"\n\n\n# ─── OpenAI Client ─────────────────────────────────────────────────────────\n\ndef get_client():\n from openai import OpenAI\n\n api_key = _resolve_api_key()\n base_url = (\n os.environ.get(\"CUSTOM_ENGINE_BASE_URL\") or\n os.environ.get(\"OPENAI_API_BASE\") or\n \"https://openrouter.ai/api/v1\"\n )\n return OpenAI(api_key=api_key, base_url=base_url)\n\n\ndef _resolve_api_key() -> str:\n # 1. OPENROUTER_API_KEY env var\n key = os.environ.get(\"OPENROUTER_API_KEY\")\n if key and key not in (\"\", \"your_api_key_here\", \"sk-your-key-here\"):\n return key\n\n # 2. OPENAI_API_KEY env var\n key = os.environ.get(\"OPENAI_API_KEY\")\n if key and key not in (\"\", \"your_api_key_here\", \"sk-your-key-here\"):\n return key\n\n # 3. CUSTOM_ENGINE_API_KEY from .env (written by settings page)\n key = os.environ.get(\"CUSTOM_ENGINE_API_KEY\")\n if key:\n return key\n\n # 4. Read opencode-go key from opencode's auth.json\n key = _read_opencode_key()\n if key:\n return key\n\n # 5. Read openrouter key from auth.json\n key = _read_openrouter_key()\n if key:\n return key\n\n raise RuntimeError(\n \"No API key found. Set CUSTOM_ENGINE_API_KEY or OPENROUTER_API_KEY \"\n \"in the Settings page, or configure one in your environment.\"\n )\n\n\ndef _read_opencode_key() -> str | None:\n import json\n auth_paths = [\n os.path.expanduser(\"~/.local/share/opencode/auth.json\"),\n os.path.expanduser(\"~/.opencode/auth.json\"),\n ]\n for auth_path in auth_paths:\n try:\n with open(auth_path) as f:\n data = json.load(f)\n entry = data.get(\"opencode-go\", {})\n key = entry.get(\"key\")\n if key and key not in (\"\", \"your_api_key_here\"):\n return key\n except (FileNotFoundError, KeyError, json.JSONDecodeError):\n continue\n return None\n\n\ndef _read_openrouter_key() -> str | None:\n try:\n with open(os.path.expanduser(\"~/.local/share/opencode/auth.json\")) as f:\n data = json.load(f)\n # OpenRouter credentials are in account.json under the \"openrouter\" service\n account_path = os.path.expanduser(\"~/.local/share/opencode/account.json\")\n with open(account_path) as f:\n accounts = json.load(f)\n for a in accounts.get(\"accounts\", {}).values():\n if a.get(\"serviceID\") == \"openrouter\":\n key = a.get(\"credential\", {}).get(\"key\")\n if key and key not in (\"\", \"your_api_key_here\"):\n return key\n except (FileNotFoundError, KeyError, json.JSONDecodeError):\n pass\n return None\n\n\ndef call_openai(\n client, messages: list[dict[str, Any]], tools: list[dict[str, Any]]\n) -> dict[str, Any]:\n response = client.chat.completions.create(\n model=MODEL,\n max_tokens=MAX_TOKENS,\n messages=messages,\n tools=tools,\n )\n choice = response.choices[0]\n msg = choice.message\n\n tool_calls = []\n if msg.tool_calls:\n for tc in msg.tool_calls:\n try:\n args = json.loads(tc.function.arguments)\n except json.JSONDecodeError:\n args = {}\n tool_calls.append(\n {\n \"id\": tc.id,\n \"name\": tc.function.name,\n \"arguments\": args,\n }\n )\n\n return {\n \"content\": msg.content or \"\",\n \"tool_calls\": tool_calls,\n \"finish_reason\": choice.finish_reason,\n \"usage\": {\n \"input_tokens\": response.usage.prompt_tokens if response.usage else 0,\n \"output_tokens\": response.usage.completion_tokens if response.usage else 0,\n \"cache_read_input_tokens\": 0,\n \"cache_creation_input_tokens\": 0,\n },\n }\n\n\n# ─── ReAct Loop ────────────────────────────────────────────────────────────\n\ndef run_loop(prompt: str, max_turns: int) -> dict[str, Any]:\n client = get_client()\n\n messages: list[dict[str, Any]] = [\n {\"role\": \"system\", \"content\": SYSTEM_PROMPT},\n {\"role\": \"user\", \"content\": prompt},\n ]\n\n total_input = 0\n total_output = 0\n final_result = \"\"\n subtype = \"success\"\n is_error = False\n\n for turn in range(max_turns):\n try:\n response = call_openai(client, messages, TOOLS)\n except Exception as e:\n return {\n \"total_cost_usd\": 0,\n \"num_turns\": turn,\n \"subtype\": \"error_api\",\n \"session_id\": None,\n \"is_error\": True,\n \"result\": f\"API error on turn {turn + 1}: {e}\",\n \"usage\": {\n \"input_tokens\": total_input,\n \"output_tokens\": total_output,\n \"cache_read_input_tokens\": 0,\n \"cache_creation_input_tokens\": 0,\n },\n }\n\n usage = response[\"usage\"]\n total_input += usage[\"input_tokens\"]\n total_output += usage[\"output_tokens\"]\n\n content = response[\"content\"]\n tool_calls = response[\"tool_calls\"]\n\n # Append assistant message\n assistant_msg: dict[str, Any] = {\"role\": \"assistant\"}\n if content:\n assistant_msg[\"content\"] = content\n if tool_calls:\n assistant_msg[\"tool_calls\"] = [\n {\n \"id\": tc[\"id\"],\n \"type\": \"function\",\n \"function\": {\n \"name\": tc[\"name\"],\n \"arguments\": json.dumps(tc[\"arguments\"]),\n },\n }\n for tc in tool_calls\n ]\n messages.append(assistant_msg)\n\n # If no tool calls, agent is done\n if not tool_calls or response[\"finish_reason\"] == \"stop\":\n final_result = content\n break\n\n # Execute tool calls and collect results\n for tc in tool_calls:\n tool_name = tc[\"name\"]\n tool_input = tc[\"arguments\"]\n result_text = dispatch(tool_name, tool_input, WORKSPACE)\n\n messages.append(\n {\n \"role\": \"tool\",\n \"tool_call_id\": tc[\"id\"],\n \"content\": result_text,\n }\n )\n\n if tool_name == \"task_complete\":\n final_result = tool_input.get(\"summary\", result_text)\n subtype = \"success\"\n break\n\n if any(tc[\"name\"] == \"task_complete\" for tc in tool_calls):\n break\n\n else:\n subtype = \"error_max_turns\"\n is_error = True\n final_result = final_result or \"Max turns reached without completion.\"\n\n return {\n \"total_cost_usd\": 0,\n \"num_turns\": turn + 1,\n \"subtype\": subtype,\n \"session_id\": None,\n \"is_error\": is_error,\n \"result\": final_result.strip(),\n \"usage\": {\n \"input_tokens\": total_input,\n \"output_tokens\": total_output,\n \"cache_read_input_tokens\": 0,\n \"cache_creation_input_tokens\": 0,\n },\n }\n\n\n# ─── Main ──────────────────────────────────────────────────────────────────\n\ndef main():\n parser = argparse.ArgumentParser(description=\"Katalyst Custom Agent Engine\")\n parser.add_argument(\"-p\", \"--prompt\", required=True, help=\"Task prompt\")\n parser.add_argument(\n \"--output-format\", default=\"json\", help=\"Output format (ignored, always JSON)\"\n )\n parser.add_argument(\n \"--max-turns\", type=int, default=25, help=\"Maximum tool-calling turns\"\n )\n args = parser.parse_args()\n\n result = run_loop(args.prompt, args.max_turns)\n print(json.dumps(result))\n\n\nif __name__ == \"__main__\":\n main()\n"}}}}