From 19dd40ed3ad23bf3b3201cc8ab20eb75aea91f63 Mon Sep 17 00:00:00 2001 From: Richard Tang Date: Fri, 6 Mar 2026 19:11:53 -0800 Subject: [PATCH] chore: ruff lint --- .../agents/hive_coder/nodes/__init__.py | 11 +- core/framework/credentials/aden/client.py | 3 +- core/framework/graph/event_loop_node.py | 9 +- core/framework/server/session_manager.py | 4 +- examples/templates/job_hunter/agent.py | 3 +- scripts/debug_queen_prompt.py | 4 +- scripts/llm_debug_log_visualizer.py | 45 ++++-- scripts/test_init_package.py | 1 + tools/coder_tools_server.py | 131 +++++++++++------- 9 files changed, 138 insertions(+), 73 deletions(-) diff --git a/core/framework/agents/hive_coder/nodes/__init__.py b/core/framework/agents/hive_coder/nodes/__init__.py index dba85d84..d969adaa 100644 --- a/core/framework/agents/hive_coder/nodes/__init__.py +++ b/core/framework/agents/hive_coder/nodes/__init__.py @@ -176,8 +176,8 @@ to see ALL available tools (names + descriptions, grouped by category). \ ONLY use tools from this list in your node definitions. \ NEVER guess or fabricate tool names from memory. - list_agent_tools() # ALWAYS call this first (simple mode, truncated descriptions) - list_agent_tools(group="google", output_schema="full") # then drill into a provider for full descriptions + input_schema + list_agent_tools() # ALWAYS call this first (simple mode) + list_agent_tools(group="google", output_schema="full") # drill into a provider NEVER skip the first call. Always start with the full list \ so you know what providers and tools exist before drilling in. \ @@ -541,7 +541,8 @@ on what it does from Worker Profile>." 5. Preferred loaded example: local_business_extractor/*agent name*/ has been loaded. It finds local businesses on \ Google Maps, extracts contact details, and syncs them to Google Sheets. - ask_user("Do you want to run it?", ["Yes, run it", "Check credentials first", "Modify the worker"]) + ask_user("Do you want to run it?", ["Yes, run it", "Check credentials first", + "Modify the worker"]) ## When user ask identity and responsibility @@ -886,8 +887,8 @@ queen_node = NodeSpec( client_facing=True, max_node_visits=0, input_keys=["greeting"], - output_keys=[], # Queen should never have this - nullable_output_keys=[], # Queen should never have this + output_keys=[], # Queen should never have this + nullable_output_keys=[], # Queen should never have this success_criteria=( "User's intent is understood, coding tasks are completed correctly, " "and the worker is managed effectively when delegated to." diff --git a/core/framework/credentials/aden/client.py b/core/framework/credentials/aden/client.py index 46bbd719..1ad97b2d 100644 --- a/core/framework/credentials/aden/client.py +++ b/core/framework/credentials/aden/client.py @@ -30,6 +30,7 @@ Usage: from __future__ import annotations +import json as _json import logging import os import time @@ -37,8 +38,6 @@ from dataclasses import dataclass, field from datetime import datetime from typing import Any -import json as _json - import httpx logger = logging.getLogger(__name__) diff --git a/core/framework/graph/event_loop_node.py b/core/framework/graph/event_loop_node.py index 0675b226..57bc6732 100644 --- a/core/framework/graph/event_loop_node.py +++ b/core/framework/graph/event_loop_node.py @@ -230,9 +230,9 @@ class LoopConfig: class HookContext: """Context passed to every lifecycle hook.""" - event: str # event name, e.g. "session_start" + event: str # event name, e.g. "session_start" trigger: str | None # message that triggered the hook, if any - system_prompt: str # current system prompt at hook invocation time + system_prompt: str # current system prompt at hook invocation time @dataclass @@ -240,7 +240,7 @@ class HookResult: """What a hook may return to modify node state.""" system_prompt: str | None = None # replace current system prompt - inject: str | None = None # inject an additional user message + inject: str | None = None # inject an additional user message # --------------------------------------------------------------------------- @@ -3699,8 +3699,7 @@ class EventLoopNode(NodeProtocol): ) parts.append( "DATA FILES (use load_data(''), read_file(''), " - "or run_command('cat \"\"') to read):\n" - + file_list + "or run_command('cat \"\"') to read):\n" + file_list ) if not all_files: parts.append( diff --git a/core/framework/server/session_manager.py b/core/framework/server/session_manager.py index 14ea5030..0b21ca39 100644 --- a/core/framework/server/session_manager.py +++ b/core/framework/server/session_manager.py @@ -560,10 +560,10 @@ class SessionManager: _QUEEN_BUILDING_TOOLS, _QUEEN_RUNNING_TOOLS, _QUEEN_STAGING_TOOLS, - _package_builder_knowledge, _appendices, - _queen_behavior_always, _gcu_building_section, + _package_builder_knowledge, + _queen_behavior_always, _queen_behavior_building, _queen_behavior_running, _queen_behavior_staging, diff --git a/examples/templates/job_hunter/agent.py b/examples/templates/job_hunter/agent.py index d90118df..75364098 100644 --- a/examples/templates/job_hunter/agent.py +++ b/examples/templates/job_hunter/agent.py @@ -11,7 +11,7 @@ from framework.runner.tool_registry import ToolRegistry from framework.runtime.agent_runtime import AgentRuntime, create_agent_runtime from framework.runtime.execution_stream import EntryPointSpec -from .config import default_config, metadata +from .config import default_config from .nodes import ( intake_node, job_search_node, @@ -291,5 +291,6 @@ class JobHunterAgent: errors.append(f"Entry node '{self.entry_node}' not found") return {"valid": len(errors) == 0, "errors": errors} + # Create default instance default_agent = JobHunterAgent() diff --git a/scripts/debug_queen_prompt.py b/scripts/debug_queen_prompt.py index ca262fbb..e5d5a8d9 100644 --- a/scripts/debug_queen_prompt.py +++ b/scripts/debug_queen_prompt.py @@ -130,5 +130,7 @@ if __name__ == "__main__": print_running_prompt() else: print(f"Unknown phase: {phase}") - print("Usage: uv run scripts/debug_queen_prompt.py [building|staging|running|all]") + print( + "Usage: uv run scripts/debug_queen_prompt.py [building|staging|running|all]" + ) sys.exit(1) diff --git a/scripts/llm_debug_log_visualizer.py b/scripts/llm_debug_log_visualizer.py index be38d933..52e64e3a 100644 --- a/scripts/llm_debug_log_visualizer.py +++ b/scripts/llm_debug_log_visualizer.py @@ -93,7 +93,11 @@ def _discover_records(logs_dir: Path, limit_files: int) -> list[dict[str, Any]]: raise FileNotFoundError(f"log directory not found: {logs_dir}") files = sorted( - [path for path in logs_dir.iterdir() if path.is_file() and path.suffix == ".jsonl"], + [ + path + for path in logs_dir.iterdir() + if path.is_file() and path.suffix == ".jsonl" + ], key=lambda path: path.stat().st_mtime, reverse=True, )[:limit_files] @@ -113,7 +117,9 @@ def _format_timestamp(raw: str) -> str: return raw -def _group_sessions(records: list[dict[str, Any]]) -> tuple[list[SessionSummary], dict[str, list[dict[str, Any]]]]: +def _group_sessions( + records: list[dict[str, Any]], +) -> tuple[list[SessionSummary], dict[str, list[dict[str, Any]]]]: by_session: dict[str, list[dict[str, Any]]] = defaultdict(list) for record in records: execution_id = str(record.get("execution_id") or "").strip() @@ -122,7 +128,12 @@ def _group_sessions(records: list[dict[str, Any]]) -> tuple[list[SessionSummary] summaries: list[SessionSummary] = [] for execution_id, session_records in by_session.items(): - session_records.sort(key=lambda record: (str(record.get("timestamp", "")), record.get("iteration", 0))) + session_records.sort( + key=lambda record: ( + str(record.get("timestamp", "")), + record.get("iteration", 0), + ) + ) first = session_records[0] last = session_records[-1] summaries.append( @@ -132,13 +143,26 @@ def _group_sessions(records: list[dict[str, Any]]) -> tuple[list[SessionSummary] start_timestamp=str(first.get("timestamp", "")), end_timestamp=str(last.get("timestamp", "")), turn_count=len(session_records), - streams=sorted({str(r.get("stream_id", "")) for r in session_records if r.get("stream_id")}), - nodes=sorted({str(r.get("node_id", "")) for r in session_records if r.get("node_id")}), + streams=sorted( + { + str(r.get("stream_id", "")) + for r in session_records + if r.get("stream_id") + } + ), + nodes=sorted( + { + str(r.get("node_id", "")) + for r in session_records + if r.get("node_id") + } + ), models=sorted( { str(r.get("token_counts", {}).get("model", "")) for r in session_records - if isinstance(r.get("token_counts"), dict) and r.get("token_counts", {}).get("model") + if isinstance(r.get("token_counts"), dict) + and r.get("token_counts", {}).get("model") } ), ) @@ -172,7 +196,10 @@ def _render_html( sessions_data = { execution_id: sorted( records, - key=lambda record: (str(record.get("timestamp", "")), record.get("iteration", 0)), + key=lambda record: ( + str(record.get("timestamp", "")), + record.get("iteration", 0), + ), ) for execution_id, records in sessions.items() } @@ -809,7 +836,9 @@ def main() -> int: records = _discover_records(args.logs_dir.expanduser(), args.limit_files) summaries, sessions = _group_sessions(records) - initial_session_id = args.session or (summaries[0].execution_id if summaries else "") + initial_session_id = args.session or ( + summaries[0].execution_id if summaries else "" + ) if initial_session_id and initial_session_id not in sessions: print(f"session not found: {initial_session_id}") return 1 diff --git a/scripts/test_init_package.py b/scripts/test_init_package.py index 863e71c3..59386c39 100644 --- a/scripts/test_init_package.py +++ b/scripts/test_init_package.py @@ -10,6 +10,7 @@ sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "tools")) # Set PROJECT_ROOT before importing import tools.coder_tools_server as srv + srv.PROJECT_ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), "..")) # Access the underlying function (FastMCP wraps it as FunctionTool) diff --git a/tools/coder_tools_server.py b/tools/coder_tools_server.py index a2293e33..2cf6eb19 100644 --- a/tools/coder_tools_server.py +++ b/tools/coder_tools_server.py @@ -1253,7 +1253,10 @@ def validate_agent_package(agent_name: str) -> str: try: proc = subprocess.run( [ - "uv", "run", "python", "-c", + "uv", + "run", + "python", + "-c", f"from {agent_name} import default_agent; print(default_agent.validate())", ], capture_output=True, @@ -1279,10 +1282,13 @@ def validate_agent_package(agent_name: str) -> str: try: proc = subprocess.run( [ - "uv", "run", "python", "-c", - f'from framework.runner.runner import AgentRunner; ' + "uv", + "run", + "python", + "-c", + f"from framework.runner.runner import AgentRunner; " f'r = AgentRunner.load("exports/{agent_name}", ' - f'skip_credential_validation=True); ' + f"skip_credential_validation=True); " f'print("AgentRunner.load (graph-only): OK")', ], capture_output=True, @@ -1336,7 +1342,6 @@ def validate_agent_package(agent_name: str) -> str: # Build summary failed_steps = [name for name, step in steps.items() if not step.get("passed")] total = len(steps) - passed_count = total - len(failed_steps) valid = len(failed_steps) == 0 if valid: @@ -1394,13 +1399,15 @@ def initialize_agent_package(agent_name: str, nodes: str | None = None) -> str: import re if not re.match(r"^[a-z][a-z0-9_]*$", agent_name): - return json.dumps({ - "success": False, - "error": ( - f"Invalid agent_name '{agent_name}'. Must be snake_case: " - "lowercase letters, numbers, underscores, starting with a letter." - ), - }) + return json.dumps( + { + "success": False, + "error": ( + f"Invalid agent_name '{agent_name}'. Must be snake_case: " + "lowercase letters, numbers, underscores, starting with a letter." + ), + } + ) node_list = [n.strip() for n in nodes.split(",") if n.strip()] if nodes else ["start"] @@ -1427,7 +1434,9 @@ def initialize_agent_package(agent_name: str, nodes: str | None = None) -> str: } # -- config.py -- - _write("config.py", f'''\ + _write( + "config.py", + f'''\ """Runtime configuration.""" import json @@ -1471,7 +1480,8 @@ class AgentMetadata: metadata = AgentMetadata() -''') +''', + ) # -- nodes/__init__.py -- node_specs = [] @@ -1479,7 +1489,7 @@ metadata = AgentMetadata() for node_id in node_list: var = _node_var_name(node_id) node_var_names.append(var) - is_first = (node_id == entry_node) + is_first = node_id == entry_node node_specs.append(f'''\ {var} = NodeSpec( id="{node_id}", @@ -1516,17 +1526,19 @@ __all__ = {node_var_names!r} edge_defs = [] for i in range(len(node_list) - 1): src, tgt = node_list[i], node_list[i + 1] - edge_defs.append(f'''\ + edge_defs.append(f"""\ EdgeSpec( id="{src}-to-{tgt}", source="{src}", target="{tgt}", condition=EdgeCondition.ON_SUCCESS, priority=1, - ),''') + ),""") edges_str = "\n".join(edge_defs) if edge_defs else " # TODO: Add edges" - _write("agent.py", f'''\ + _write( + "agent.py", + f'''\ """Agent graph construction for {human_name}.""" from pathlib import Path @@ -1735,10 +1747,13 @@ class {class_name}: default_agent = {class_name}() -''') +''', + ) # -- __init__.py -- - _write("__init__.py", f'''\ + _write( + "__init__.py", + f'''\ """{human_name} — TODO: Add description.""" from .agent import ( @@ -1773,10 +1788,13 @@ __all__ = [ "default_config", "metadata", ] -''') +''', + ) # -- __main__.py -- - _write("__main__.py", f'''\ + _write( + "__main__.py", + f'''\ """CLI entry point for {human_name}.""" import asyncio @@ -1827,7 +1845,9 @@ def info(): """Show agent info.""" data = default_agent.info() click.echo( - f"Agent: {{data[\'name\']}}\\nVersion: {{data[\'version\']}}\\nDescription: {{data[\'description\']}}" + f"Agent: {{data[\'name\']}}\n" + f"Version: {{data[\'version\']}}\n" + f"Description: {{data[\'description\']}}" ) click.echo(f"Nodes: {{', '.join(data[\'nodes\'])}}") click.echo(f"Client-facing: {{', '.join(data[\'client_facing_nodes\'])}}") @@ -1848,21 +1868,30 @@ def validate(): if __name__ == "__main__": cli() -''') +''', + ) # -- mcp_servers.json -- - _write("mcp_servers.json", json.dumps({ - "hive-tools": { - "transport": "stdio", - "command": "uv", - "args": ["run", "python", "mcp_server.py", "--stdio"], - "cwd": "../../tools", - "description": "Hive tools MCP server", - } - }, indent=2)) + _write( + "mcp_servers.json", + json.dumps( + { + "hive-tools": { + "transport": "stdio", + "command": "uv", + "args": ["run", "python", "mcp_server.py", "--stdio"], + "cwd": "../../tools", + "description": "Hive tools MCP server", + } + }, + indent=2, + ), + ) # -- tests/conftest.py -- - _write("tests/conftest.py", f'''\ + _write( + "tests/conftest.py", + '''\ """Test fixtures.""" import sys @@ -1893,22 +1922,26 @@ def runner_loaded(): from framework.runner.runner import AgentRunner return AgentRunner.load(AGENT_PATH) -''') +''', + ) - return json.dumps({ - "success": True, - "agent_name": agent_name, - "class_name": class_name, - "entry_node": entry_node, - "nodes": node_list, - "files_written": files_written, - "file_count": len(files_written), - "next_steps": [ - f"Customize node definitions in exports/{agent_name}/nodes/__init__.py", - f"Define goal and edges in exports/{agent_name}/agent.py", - f"Run validate_agent_package(\"{agent_name}\") to check structure", - ], - }, indent=2) + return json.dumps( + { + "success": True, + "agent_name": agent_name, + "class_name": class_name, + "entry_node": entry_node, + "nodes": node_list, + "files_written": files_written, + "file_count": len(files_written), + "next_steps": [ + f"Customize node definitions in exports/{agent_name}/nodes/__init__.py", + f"Define goal and edges in exports/{agent_name}/agent.py", + f'Run validate_agent_package("{agent_name}") to check structure', + ], + }, + indent=2, + ) # ── Main ──────────────────────────────────────────────────────────────────