Skip to content

Commit 5c55027

Browse files
Merge pull request #5071 from TimothyZhang7/feature/queen-bee
Feature/queen bee
2 parents 132d84c + e03fd48 commit 5c55027

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+7650
-425
lines changed

core/framework/agents/__init__.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
"""Framework-provided agents."""
2+
3+
from pathlib import Path
4+
5+
FRAMEWORK_AGENTS_DIR = Path(__file__).parent
6+
7+
8+
def list_framework_agents() -> list[Path]:
9+
"""List all framework agent directories."""
10+
return sorted(
11+
[p for p in FRAMEWORK_AGENTS_DIR.iterdir() if p.is_dir() and (p / "agent.py").exists()],
12+
key=lambda p: p.name,
13+
)
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
"""
2+
Hive Coder — Native coding agent that builds Hive agent packages.
3+
4+
Deeply understands the agent framework and produces complete Python packages
5+
with goals, nodes, edges, system prompts, MCP configuration, and tests
6+
from natural language specifications.
7+
"""
8+
9+
from .agent import (
10+
HiveCoderAgent,
11+
conversation_mode,
12+
default_agent,
13+
edges,
14+
entry_node,
15+
entry_points,
16+
goal,
17+
identity_prompt,
18+
loop_config,
19+
nodes,
20+
pause_nodes,
21+
terminal_nodes,
22+
)
23+
from .config import AgentMetadata, RuntimeConfig, default_config, metadata
24+
25+
__version__ = "1.0.0"
26+
27+
__all__ = [
28+
"HiveCoderAgent",
29+
"default_agent",
30+
"goal",
31+
"nodes",
32+
"edges",
33+
"entry_node",
34+
"entry_points",
35+
"pause_nodes",
36+
"terminal_nodes",
37+
"conversation_mode",
38+
"identity_prompt",
39+
"loop_config",
40+
"RuntimeConfig",
41+
"AgentMetadata",
42+
"default_config",
43+
"metadata",
44+
]
Lines changed: 223 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,223 @@
1+
"""CLI entry point for Hive Coder agent."""
2+
3+
import asyncio
4+
import json
5+
import logging
6+
import sys
7+
8+
import click
9+
10+
from .agent import HiveCoderAgent, default_agent
11+
12+
13+
def setup_logging(verbose=False, debug=False):
14+
"""Configure logging for execution visibility."""
15+
if debug:
16+
level, fmt = logging.DEBUG, "%(asctime)s %(name)s: %(message)s"
17+
elif verbose:
18+
level, fmt = logging.INFO, "%(message)s"
19+
else:
20+
level, fmt = logging.WARNING, "%(levelname)s: %(message)s"
21+
logging.basicConfig(level=level, format=fmt, stream=sys.stderr)
22+
logging.getLogger("framework").setLevel(level)
23+
24+
25+
@click.group()
26+
@click.version_option(version="1.0.0")
27+
def cli():
28+
"""Hive Coder — Build Hive agent packages from natural language."""
29+
pass
30+
31+
32+
@cli.command()
33+
@click.option("--request", "-r", type=str, required=True, help="What agent to build")
34+
@click.option("--mock", is_flag=True, help="Run in mock mode")
35+
@click.option("--quiet", "-q", is_flag=True, help="Only output result JSON")
36+
@click.option("--verbose", "-v", is_flag=True, help="Show execution details")
37+
@click.option("--debug", is_flag=True, help="Show debug logging")
38+
def run(request, mock, quiet, verbose, debug):
39+
"""Execute agent building from a request."""
40+
if not quiet:
41+
setup_logging(verbose=verbose, debug=debug)
42+
43+
context = {"user_request": request}
44+
45+
result = asyncio.run(default_agent.run(context, mock_mode=mock))
46+
47+
output_data = {
48+
"success": result.success,
49+
"steps_executed": result.steps_executed,
50+
"output": result.output,
51+
}
52+
if result.error:
53+
output_data["error"] = result.error
54+
55+
click.echo(json.dumps(output_data, indent=2, default=str))
56+
sys.exit(0 if result.success else 1)
57+
58+
59+
@cli.command()
60+
@click.option("--mock", is_flag=True, help="Run in mock mode")
61+
@click.option("--verbose", "-v", is_flag=True, help="Show execution details")
62+
@click.option("--debug", is_flag=True, help="Show debug logging")
63+
def tui(mock, verbose, debug):
64+
"""Launch the TUI dashboard for interactive agent building."""
65+
setup_logging(verbose=verbose, debug=debug)
66+
67+
try:
68+
from framework.tui.app import AdenTUI
69+
except ImportError:
70+
click.echo("TUI requires the 'textual' package. Install with: pip install textual")
71+
sys.exit(1)
72+
73+
from pathlib import Path
74+
75+
from framework.llm import LiteLLMProvider
76+
from framework.runner.tool_registry import ToolRegistry
77+
from framework.runtime.agent_runtime import create_agent_runtime
78+
from framework.runtime.execution_stream import EntryPointSpec
79+
80+
async def run_with_tui():
81+
agent = HiveCoderAgent()
82+
83+
agent._tool_registry = ToolRegistry()
84+
85+
storage_path = Path.home() / ".hive" / "agents" / "hive_coder"
86+
storage_path.mkdir(parents=True, exist_ok=True)
87+
88+
mcp_config_path = Path(__file__).parent / "mcp_servers.json"
89+
if mcp_config_path.exists():
90+
agent._tool_registry.load_mcp_config(mcp_config_path)
91+
92+
llm = None
93+
if not mock:
94+
llm = LiteLLMProvider(
95+
model=agent.config.model,
96+
api_key=agent.config.api_key,
97+
api_base=agent.config.api_base,
98+
)
99+
100+
tools = list(agent._tool_registry.get_tools().values())
101+
tool_executor = agent._tool_registry.get_executor()
102+
graph = agent._build_graph()
103+
104+
runtime = create_agent_runtime(
105+
graph=graph,
106+
goal=agent.goal,
107+
storage_path=storage_path,
108+
entry_points=[
109+
EntryPointSpec(
110+
id="start",
111+
name="Build Agent",
112+
entry_node="coder",
113+
trigger_type="manual",
114+
isolation_level="isolated",
115+
),
116+
],
117+
llm=llm,
118+
tools=tools,
119+
tool_executor=tool_executor,
120+
)
121+
122+
await runtime.start()
123+
124+
try:
125+
app = AdenTUI(runtime)
126+
await app.run_async()
127+
finally:
128+
await runtime.stop()
129+
130+
asyncio.run(run_with_tui())
131+
132+
133+
@cli.command()
134+
@click.option("--json", "output_json", is_flag=True)
135+
def info(output_json):
136+
"""Show agent information."""
137+
info_data = default_agent.info()
138+
if output_json:
139+
click.echo(json.dumps(info_data, indent=2))
140+
else:
141+
click.echo(f"Agent: {info_data['name']}")
142+
click.echo(f"Version: {info_data['version']}")
143+
click.echo(f"Description: {info_data['description']}")
144+
click.echo(f"\nNodes: {', '.join(info_data['nodes'])}")
145+
click.echo(f"Client-facing: {', '.join(info_data['client_facing_nodes'])}")
146+
click.echo(f"Entry: {info_data['entry_node']}")
147+
click.echo(f"Terminal: {', '.join(info_data['terminal_nodes']) or '(forever-alive)'}")
148+
149+
150+
@cli.command()
151+
def validate():
152+
"""Validate agent structure."""
153+
validation = default_agent.validate()
154+
if validation["valid"]:
155+
click.echo("Agent is valid")
156+
if validation["warnings"]:
157+
for warning in validation["warnings"]:
158+
click.echo(f" WARNING: {warning}")
159+
else:
160+
click.echo("Agent has errors:")
161+
for error in validation["errors"]:
162+
click.echo(f" ERROR: {error}")
163+
sys.exit(0 if validation["valid"] else 1)
164+
165+
166+
@cli.command()
167+
@click.option("--verbose", "-v", is_flag=True)
168+
def shell(verbose):
169+
"""Interactive agent building session (CLI, no TUI)."""
170+
asyncio.run(_interactive_shell(verbose))
171+
172+
173+
async def _interactive_shell(verbose=False):
174+
"""Async interactive shell."""
175+
setup_logging(verbose=verbose)
176+
177+
click.echo("=== Hive Coder ===")
178+
click.echo("Describe the agent you want to build (or 'quit' to exit):\n")
179+
180+
agent = HiveCoderAgent()
181+
await agent.start()
182+
183+
try:
184+
while True:
185+
try:
186+
request = await asyncio.get_event_loop().run_in_executor(None, input, "Build> ")
187+
if request.lower() in ["quit", "exit", "q"]:
188+
click.echo("Goodbye!")
189+
break
190+
191+
if not request.strip():
192+
continue
193+
194+
click.echo("\nBuilding agent...\n")
195+
196+
result = await agent.trigger_and_wait("default", {"user_request": request})
197+
198+
if result is None:
199+
click.echo("\n[Execution timed out]\n")
200+
continue
201+
202+
if result.success:
203+
output = result.output or {}
204+
agent_name = output.get("agent_name", "unknown")
205+
validation = output.get("validation_result", "unknown")
206+
click.echo(f"\nAgent '{agent_name}' built. Validation: {validation}\n")
207+
else:
208+
click.echo(f"\nBuild failed: {result.error}\n")
209+
210+
except KeyboardInterrupt:
211+
click.echo("\nGoodbye!")
212+
break
213+
except Exception as e:
214+
click.echo(f"Error: {e}", err=True)
215+
import traceback
216+
217+
traceback.print_exc()
218+
finally:
219+
await agent.stop()
220+
221+
222+
if __name__ == "__main__":
223+
cli()

0 commit comments

Comments
 (0)