chore: ruff lint
This commit is contained in:
@@ -176,8 +176,8 @@ to see ALL available tools (names + descriptions, grouped by category). \
|
|||||||
ONLY use tools from this list in your node definitions. \
|
ONLY use tools from this list in your node definitions. \
|
||||||
NEVER guess or fabricate tool names from memory.
|
NEVER guess or fabricate tool names from memory.
|
||||||
|
|
||||||
list_agent_tools() # ALWAYS call this first (simple mode, truncated descriptions)
|
list_agent_tools() # ALWAYS call this first (simple mode)
|
||||||
list_agent_tools(group="google", output_schema="full") # then drill into a provider for full descriptions + input_schema
|
list_agent_tools(group="google", output_schema="full") # drill into a provider
|
||||||
|
|
||||||
NEVER skip the first call. Always start with the full list \
|
NEVER skip the first call. Always start with the full list \
|
||||||
so you know what providers and tools exist before drilling in. \
|
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:
|
5. Preferred loaded example:
|
||||||
local_business_extractor/*agent name*/ has been loaded. It finds local businesses on \
|
local_business_extractor/*agent name*/ has been loaded. It finds local businesses on \
|
||||||
Google Maps, extracts contact details, and syncs them to Google Sheets.
|
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
|
## When user ask identity and responsibility
|
||||||
|
|
||||||
@@ -886,8 +887,8 @@ queen_node = NodeSpec(
|
|||||||
client_facing=True,
|
client_facing=True,
|
||||||
max_node_visits=0,
|
max_node_visits=0,
|
||||||
input_keys=["greeting"],
|
input_keys=["greeting"],
|
||||||
output_keys=[], # Queen should never have this
|
output_keys=[], # Queen should never have this
|
||||||
nullable_output_keys=[], # Queen should never have this
|
nullable_output_keys=[], # Queen should never have this
|
||||||
success_criteria=(
|
success_criteria=(
|
||||||
"User's intent is understood, coding tasks are completed correctly, "
|
"User's intent is understood, coding tasks are completed correctly, "
|
||||||
"and the worker is managed effectively when delegated to."
|
"and the worker is managed effectively when delegated to."
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ Usage:
|
|||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import json as _json
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
import time
|
import time
|
||||||
@@ -37,8 +38,6 @@ from dataclasses import dataclass, field
|
|||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
import json as _json
|
|
||||||
|
|
||||||
import httpx
|
import httpx
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|||||||
@@ -230,9 +230,9 @@ class LoopConfig:
|
|||||||
class HookContext:
|
class HookContext:
|
||||||
"""Context passed to every lifecycle hook."""
|
"""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
|
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
|
@dataclass
|
||||||
@@ -240,7 +240,7 @@ class HookResult:
|
|||||||
"""What a hook may return to modify node state."""
|
"""What a hook may return to modify node state."""
|
||||||
|
|
||||||
system_prompt: str | None = None # replace current system prompt
|
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(
|
parts.append(
|
||||||
"DATA FILES (use load_data('<filename>'), read_file('<full_path>'), "
|
"DATA FILES (use load_data('<filename>'), read_file('<full_path>'), "
|
||||||
"or run_command('cat \"<full_path>\"') to read):\n"
|
"or run_command('cat \"<full_path>\"') to read):\n" + file_list
|
||||||
+ file_list
|
|
||||||
)
|
)
|
||||||
if not all_files:
|
if not all_files:
|
||||||
parts.append(
|
parts.append(
|
||||||
|
|||||||
@@ -560,10 +560,10 @@ class SessionManager:
|
|||||||
_QUEEN_BUILDING_TOOLS,
|
_QUEEN_BUILDING_TOOLS,
|
||||||
_QUEEN_RUNNING_TOOLS,
|
_QUEEN_RUNNING_TOOLS,
|
||||||
_QUEEN_STAGING_TOOLS,
|
_QUEEN_STAGING_TOOLS,
|
||||||
_package_builder_knowledge,
|
|
||||||
_appendices,
|
_appendices,
|
||||||
_queen_behavior_always,
|
|
||||||
_gcu_building_section,
|
_gcu_building_section,
|
||||||
|
_package_builder_knowledge,
|
||||||
|
_queen_behavior_always,
|
||||||
_queen_behavior_building,
|
_queen_behavior_building,
|
||||||
_queen_behavior_running,
|
_queen_behavior_running,
|
||||||
_queen_behavior_staging,
|
_queen_behavior_staging,
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ from framework.runner.tool_registry import ToolRegistry
|
|||||||
from framework.runtime.agent_runtime import AgentRuntime, create_agent_runtime
|
from framework.runtime.agent_runtime import AgentRuntime, create_agent_runtime
|
||||||
from framework.runtime.execution_stream import EntryPointSpec
|
from framework.runtime.execution_stream import EntryPointSpec
|
||||||
|
|
||||||
from .config import default_config, metadata
|
from .config import default_config
|
||||||
from .nodes import (
|
from .nodes import (
|
||||||
intake_node,
|
intake_node,
|
||||||
job_search_node,
|
job_search_node,
|
||||||
@@ -291,5 +291,6 @@ class JobHunterAgent:
|
|||||||
errors.append(f"Entry node '{self.entry_node}' not found")
|
errors.append(f"Entry node '{self.entry_node}' not found")
|
||||||
return {"valid": len(errors) == 0, "errors": errors}
|
return {"valid": len(errors) == 0, "errors": errors}
|
||||||
|
|
||||||
|
|
||||||
# Create default instance
|
# Create default instance
|
||||||
default_agent = JobHunterAgent()
|
default_agent = JobHunterAgent()
|
||||||
|
|||||||
@@ -130,5 +130,7 @@ if __name__ == "__main__":
|
|||||||
print_running_prompt()
|
print_running_prompt()
|
||||||
else:
|
else:
|
||||||
print(f"Unknown phase: {phase}")
|
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)
|
sys.exit(1)
|
||||||
|
|||||||
@@ -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}")
|
raise FileNotFoundError(f"log directory not found: {logs_dir}")
|
||||||
|
|
||||||
files = sorted(
|
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,
|
key=lambda path: path.stat().st_mtime,
|
||||||
reverse=True,
|
reverse=True,
|
||||||
)[:limit_files]
|
)[:limit_files]
|
||||||
@@ -113,7 +117,9 @@ def _format_timestamp(raw: str) -> str:
|
|||||||
return raw
|
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)
|
by_session: dict[str, list[dict[str, Any]]] = defaultdict(list)
|
||||||
for record in records:
|
for record in records:
|
||||||
execution_id = str(record.get("execution_id") or "").strip()
|
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] = []
|
summaries: list[SessionSummary] = []
|
||||||
for execution_id, session_records in by_session.items():
|
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]
|
first = session_records[0]
|
||||||
last = session_records[-1]
|
last = session_records[-1]
|
||||||
summaries.append(
|
summaries.append(
|
||||||
@@ -132,13 +143,26 @@ def _group_sessions(records: list[dict[str, Any]]) -> tuple[list[SessionSummary]
|
|||||||
start_timestamp=str(first.get("timestamp", "")),
|
start_timestamp=str(first.get("timestamp", "")),
|
||||||
end_timestamp=str(last.get("timestamp", "")),
|
end_timestamp=str(last.get("timestamp", "")),
|
||||||
turn_count=len(session_records),
|
turn_count=len(session_records),
|
||||||
streams=sorted({str(r.get("stream_id", "")) for r in session_records if r.get("stream_id")}),
|
streams=sorted(
|
||||||
nodes=sorted({str(r.get("node_id", "")) for r in session_records if r.get("node_id")}),
|
{
|
||||||
|
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(
|
models=sorted(
|
||||||
{
|
{
|
||||||
str(r.get("token_counts", {}).get("model", ""))
|
str(r.get("token_counts", {}).get("model", ""))
|
||||||
for r in session_records
|
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 = {
|
sessions_data = {
|
||||||
execution_id: sorted(
|
execution_id: sorted(
|
||||||
records,
|
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()
|
for execution_id, records in sessions.items()
|
||||||
}
|
}
|
||||||
@@ -809,7 +836,9 @@ def main() -> int:
|
|||||||
records = _discover_records(args.logs_dir.expanduser(), args.limit_files)
|
records = _discover_records(args.logs_dir.expanduser(), args.limit_files)
|
||||||
summaries, sessions = _group_sessions(records)
|
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:
|
if initial_session_id and initial_session_id not in sessions:
|
||||||
print(f"session not found: {initial_session_id}")
|
print(f"session not found: {initial_session_id}")
|
||||||
return 1
|
return 1
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "tools"))
|
|||||||
|
|
||||||
# Set PROJECT_ROOT before importing
|
# Set PROJECT_ROOT before importing
|
||||||
import tools.coder_tools_server as srv
|
import tools.coder_tools_server as srv
|
||||||
|
|
||||||
srv.PROJECT_ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
|
srv.PROJECT_ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
|
||||||
|
|
||||||
# Access the underlying function (FastMCP wraps it as FunctionTool)
|
# Access the underlying function (FastMCP wraps it as FunctionTool)
|
||||||
|
|||||||
+82
-49
@@ -1253,7 +1253,10 @@ def validate_agent_package(agent_name: str) -> str:
|
|||||||
try:
|
try:
|
||||||
proc = subprocess.run(
|
proc = subprocess.run(
|
||||||
[
|
[
|
||||||
"uv", "run", "python", "-c",
|
"uv",
|
||||||
|
"run",
|
||||||
|
"python",
|
||||||
|
"-c",
|
||||||
f"from {agent_name} import default_agent; print(default_agent.validate())",
|
f"from {agent_name} import default_agent; print(default_agent.validate())",
|
||||||
],
|
],
|
||||||
capture_output=True,
|
capture_output=True,
|
||||||
@@ -1279,10 +1282,13 @@ def validate_agent_package(agent_name: str) -> str:
|
|||||||
try:
|
try:
|
||||||
proc = subprocess.run(
|
proc = subprocess.run(
|
||||||
[
|
[
|
||||||
"uv", "run", "python", "-c",
|
"uv",
|
||||||
f'from framework.runner.runner import AgentRunner; '
|
"run",
|
||||||
|
"python",
|
||||||
|
"-c",
|
||||||
|
f"from framework.runner.runner import AgentRunner; "
|
||||||
f'r = AgentRunner.load("exports/{agent_name}", '
|
f'r = AgentRunner.load("exports/{agent_name}", '
|
||||||
f'skip_credential_validation=True); '
|
f"skip_credential_validation=True); "
|
||||||
f'print("AgentRunner.load (graph-only): OK")',
|
f'print("AgentRunner.load (graph-only): OK")',
|
||||||
],
|
],
|
||||||
capture_output=True,
|
capture_output=True,
|
||||||
@@ -1336,7 +1342,6 @@ def validate_agent_package(agent_name: str) -> str:
|
|||||||
# Build summary
|
# Build summary
|
||||||
failed_steps = [name for name, step in steps.items() if not step.get("passed")]
|
failed_steps = [name for name, step in steps.items() if not step.get("passed")]
|
||||||
total = len(steps)
|
total = len(steps)
|
||||||
passed_count = total - len(failed_steps)
|
|
||||||
valid = len(failed_steps) == 0
|
valid = len(failed_steps) == 0
|
||||||
|
|
||||||
if valid:
|
if valid:
|
||||||
@@ -1394,13 +1399,15 @@ def initialize_agent_package(agent_name: str, nodes: str | None = None) -> str:
|
|||||||
import re
|
import re
|
||||||
|
|
||||||
if not re.match(r"^[a-z][a-z0-9_]*$", agent_name):
|
if not re.match(r"^[a-z][a-z0-9_]*$", agent_name):
|
||||||
return json.dumps({
|
return json.dumps(
|
||||||
"success": False,
|
{
|
||||||
"error": (
|
"success": False,
|
||||||
f"Invalid agent_name '{agent_name}'. Must be snake_case: "
|
"error": (
|
||||||
"lowercase letters, numbers, underscores, starting with a letter."
|
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"]
|
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 --
|
# -- config.py --
|
||||||
_write("config.py", f'''\
|
_write(
|
||||||
|
"config.py",
|
||||||
|
f'''\
|
||||||
"""Runtime configuration."""
|
"""Runtime configuration."""
|
||||||
|
|
||||||
import json
|
import json
|
||||||
@@ -1471,7 +1480,8 @@ class AgentMetadata:
|
|||||||
|
|
||||||
|
|
||||||
metadata = AgentMetadata()
|
metadata = AgentMetadata()
|
||||||
''')
|
''',
|
||||||
|
)
|
||||||
|
|
||||||
# -- nodes/__init__.py --
|
# -- nodes/__init__.py --
|
||||||
node_specs = []
|
node_specs = []
|
||||||
@@ -1479,7 +1489,7 @@ metadata = AgentMetadata()
|
|||||||
for node_id in node_list:
|
for node_id in node_list:
|
||||||
var = _node_var_name(node_id)
|
var = _node_var_name(node_id)
|
||||||
node_var_names.append(var)
|
node_var_names.append(var)
|
||||||
is_first = (node_id == entry_node)
|
is_first = node_id == entry_node
|
||||||
node_specs.append(f'''\
|
node_specs.append(f'''\
|
||||||
{var} = NodeSpec(
|
{var} = NodeSpec(
|
||||||
id="{node_id}",
|
id="{node_id}",
|
||||||
@@ -1516,17 +1526,19 @@ __all__ = {node_var_names!r}
|
|||||||
edge_defs = []
|
edge_defs = []
|
||||||
for i in range(len(node_list) - 1):
|
for i in range(len(node_list) - 1):
|
||||||
src, tgt = node_list[i], node_list[i + 1]
|
src, tgt = node_list[i], node_list[i + 1]
|
||||||
edge_defs.append(f'''\
|
edge_defs.append(f"""\
|
||||||
EdgeSpec(
|
EdgeSpec(
|
||||||
id="{src}-to-{tgt}",
|
id="{src}-to-{tgt}",
|
||||||
source="{src}",
|
source="{src}",
|
||||||
target="{tgt}",
|
target="{tgt}",
|
||||||
condition=EdgeCondition.ON_SUCCESS,
|
condition=EdgeCondition.ON_SUCCESS,
|
||||||
priority=1,
|
priority=1,
|
||||||
),''')
|
),""")
|
||||||
edges_str = "\n".join(edge_defs) if edge_defs else " # TODO: Add edges"
|
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}."""
|
"""Agent graph construction for {human_name}."""
|
||||||
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
@@ -1735,10 +1747,13 @@ class {class_name}:
|
|||||||
|
|
||||||
|
|
||||||
default_agent = {class_name}()
|
default_agent = {class_name}()
|
||||||
''')
|
''',
|
||||||
|
)
|
||||||
|
|
||||||
# -- __init__.py --
|
# -- __init__.py --
|
||||||
_write("__init__.py", f'''\
|
_write(
|
||||||
|
"__init__.py",
|
||||||
|
f'''\
|
||||||
"""{human_name} — TODO: Add description."""
|
"""{human_name} — TODO: Add description."""
|
||||||
|
|
||||||
from .agent import (
|
from .agent import (
|
||||||
@@ -1773,10 +1788,13 @@ __all__ = [
|
|||||||
"default_config",
|
"default_config",
|
||||||
"metadata",
|
"metadata",
|
||||||
]
|
]
|
||||||
''')
|
''',
|
||||||
|
)
|
||||||
|
|
||||||
# -- __main__.py --
|
# -- __main__.py --
|
||||||
_write("__main__.py", f'''\
|
_write(
|
||||||
|
"__main__.py",
|
||||||
|
f'''\
|
||||||
"""CLI entry point for {human_name}."""
|
"""CLI entry point for {human_name}."""
|
||||||
|
|
||||||
import asyncio
|
import asyncio
|
||||||
@@ -1827,7 +1845,9 @@ def info():
|
|||||||
"""Show agent info."""
|
"""Show agent info."""
|
||||||
data = default_agent.info()
|
data = default_agent.info()
|
||||||
click.echo(
|
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"Nodes: {{', '.join(data[\'nodes\'])}}")
|
||||||
click.echo(f"Client-facing: {{', '.join(data[\'client_facing_nodes\'])}}")
|
click.echo(f"Client-facing: {{', '.join(data[\'client_facing_nodes\'])}}")
|
||||||
@@ -1848,21 +1868,30 @@ def validate():
|
|||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
cli()
|
cli()
|
||||||
''')
|
''',
|
||||||
|
)
|
||||||
|
|
||||||
# -- mcp_servers.json --
|
# -- mcp_servers.json --
|
||||||
_write("mcp_servers.json", json.dumps({
|
_write(
|
||||||
"hive-tools": {
|
"mcp_servers.json",
|
||||||
"transport": "stdio",
|
json.dumps(
|
||||||
"command": "uv",
|
{
|
||||||
"args": ["run", "python", "mcp_server.py", "--stdio"],
|
"hive-tools": {
|
||||||
"cwd": "../../tools",
|
"transport": "stdio",
|
||||||
"description": "Hive tools MCP server",
|
"command": "uv",
|
||||||
}
|
"args": ["run", "python", "mcp_server.py", "--stdio"],
|
||||||
}, indent=2))
|
"cwd": "../../tools",
|
||||||
|
"description": "Hive tools MCP server",
|
||||||
|
}
|
||||||
|
},
|
||||||
|
indent=2,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
# -- tests/conftest.py --
|
# -- tests/conftest.py --
|
||||||
_write("tests/conftest.py", f'''\
|
_write(
|
||||||
|
"tests/conftest.py",
|
||||||
|
'''\
|
||||||
"""Test fixtures."""
|
"""Test fixtures."""
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
@@ -1893,22 +1922,26 @@ def runner_loaded():
|
|||||||
from framework.runner.runner import AgentRunner
|
from framework.runner.runner import AgentRunner
|
||||||
|
|
||||||
return AgentRunner.load(AGENT_PATH)
|
return AgentRunner.load(AGENT_PATH)
|
||||||
''')
|
''',
|
||||||
|
)
|
||||||
|
|
||||||
return json.dumps({
|
return json.dumps(
|
||||||
"success": True,
|
{
|
||||||
"agent_name": agent_name,
|
"success": True,
|
||||||
"class_name": class_name,
|
"agent_name": agent_name,
|
||||||
"entry_node": entry_node,
|
"class_name": class_name,
|
||||||
"nodes": node_list,
|
"entry_node": entry_node,
|
||||||
"files_written": files_written,
|
"nodes": node_list,
|
||||||
"file_count": len(files_written),
|
"files_written": files_written,
|
||||||
"next_steps": [
|
"file_count": len(files_written),
|
||||||
f"Customize node definitions in exports/{agent_name}/nodes/__init__.py",
|
"next_steps": [
|
||||||
f"Define goal and edges in exports/{agent_name}/agent.py",
|
f"Customize node definitions in exports/{agent_name}/nodes/__init__.py",
|
||||||
f"Run validate_agent_package(\"{agent_name}\") to check structure",
|
f"Define goal and edges in exports/{agent_name}/agent.py",
|
||||||
],
|
f'Run validate_agent_package("{agent_name}") to check structure',
|
||||||
}, indent=2)
|
],
|
||||||
|
},
|
||||||
|
indent=2,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
# ── Main ──────────────────────────────────────────────────────────────────
|
# ── Main ──────────────────────────────────────────────────────────────────
|
||||||
|
|||||||
Reference in New Issue
Block a user