589c5b06fe
- Auto-fixed 70 lint errors (import sorting, aliased errors, datetime.UTC)
- Fixed 85 remaining errors manually:
- E501: wrapped long lines in queen_profiles, catalog, routes_credentials
- F821: added missing TYPE_CHECKING imports for AgentHost, ToolRegistry,
HookContext, HookResult; added runtime imports where needed
- F811: removed duplicate method definitions in queen_lifecycle_tools
- F841/B007: removed unused variables in discovery.py
- W291: removed trailing whitespace in queen nodes
- E402: moved import to top of queen_memory_v2.py
- Fixed AgentRuntime -> AgentHost in example template type annotations
- Reformatted 343 files with ruff format
168 lines
5.4 KiB
Python
168 lines
5.4 KiB
Python
"""Integration test: Run a real EventLoopNode against the Antigravity backend.
|
|
|
|
Run: .venv/bin/python core/tests/test_antigravity_eventloop.py
|
|
|
|
Requires:
|
|
- ~/.hive/antigravity-accounts.json with valid credentials
|
|
(run 'uv run python core/antigravity_auth.py auth account add' to authenticate)
|
|
"""
|
|
|
|
import asyncio
|
|
import logging
|
|
import sys
|
|
from unittest.mock import MagicMock
|
|
|
|
sys.path.insert(0, "core")
|
|
|
|
logging.basicConfig(level=logging.WARNING, format="%(levelname)s %(name)s: %(message)s")
|
|
# Show our provider's retry/stream logs
|
|
logging.getLogger("framework.llm.litellm").setLevel(logging.DEBUG)
|
|
|
|
from framework.agent_loop.agent_loop import AgentLoop as EventLoopNode # noqa: E402
|
|
from framework.agent_loop.internals.types import LoopConfig # noqa: E402
|
|
from framework.config import RuntimeConfig # noqa: E402
|
|
from framework.llm.litellm import LiteLLMProvider # noqa: E402
|
|
from framework.orchestrator.node import DataBuffer, NodeContext, NodeResult, NodeSpec # noqa: E402
|
|
|
|
|
|
def make_provider() -> LiteLLMProvider:
|
|
cfg = RuntimeConfig()
|
|
if not cfg.api_key:
|
|
print("ERROR: No Antigravity token found.")
|
|
print(" 1. Run 'antigravity-auth accounts add' to authenticate.")
|
|
print(" 2. Run 'antigravity-auth serve' to start the local proxy.")
|
|
print(" 3. Configure Hive: run quickstart.sh and select option 7 (Antigravity).")
|
|
sys.exit(1)
|
|
print(f"Model : {cfg.model}")
|
|
print(f"Base : {cfg.api_base}")
|
|
print(f"Antigravity : {'localhost:8069' in (cfg.api_base or '')}")
|
|
return LiteLLMProvider(
|
|
model=cfg.model,
|
|
api_key=cfg.api_key,
|
|
api_base=cfg.api_base,
|
|
**cfg.extra_kwargs,
|
|
)
|
|
|
|
|
|
def make_context(
|
|
llm: LiteLLMProvider,
|
|
*,
|
|
node_id: str = "test",
|
|
system_prompt: str = "You are a helpful assistant.",
|
|
output_keys: list[str] | None = None,
|
|
) -> NodeContext:
|
|
if output_keys is None:
|
|
output_keys = ["answer"]
|
|
|
|
spec = NodeSpec(
|
|
id=node_id,
|
|
name="Test Node",
|
|
description="Integration test node",
|
|
node_type="event_loop",
|
|
output_keys=output_keys,
|
|
system_prompt=system_prompt,
|
|
)
|
|
|
|
runtime = MagicMock()
|
|
runtime.start_run = MagicMock(return_value="run-1")
|
|
runtime.decide = MagicMock(return_value="dec-1")
|
|
runtime.record_outcome = MagicMock()
|
|
runtime.end_run = MagicMock()
|
|
|
|
buffer = DataBuffer()
|
|
|
|
return NodeContext(
|
|
runtime=runtime,
|
|
node_id=node_id,
|
|
node_spec=spec,
|
|
buffer=buffer,
|
|
input_data={},
|
|
llm=llm,
|
|
available_tools=[],
|
|
max_tokens=4096,
|
|
)
|
|
|
|
|
|
async def run_test(name: str, llm: LiteLLMProvider, system: str, output_keys: list[str]) -> NodeResult:
|
|
print(f"\n{'=' * 60}")
|
|
print(f"TEST: {name}")
|
|
print(f"{'=' * 60}")
|
|
|
|
ctx = make_context(llm, system_prompt=system, output_keys=output_keys)
|
|
node = EventLoopNode(config=LoopConfig(max_iterations=3))
|
|
|
|
try:
|
|
result = await node.execute(ctx)
|
|
print(f" Success : {result.success}")
|
|
print(f" Output : {result.output}")
|
|
if result.error:
|
|
print(f" Error : {result.error}")
|
|
return result
|
|
except Exception as e:
|
|
print(f" EXCEPTION: {type(e).__name__}: {e}")
|
|
import traceback
|
|
|
|
traceback.print_exc()
|
|
return NodeResult(success=False, error=str(e))
|
|
|
|
|
|
async def main():
|
|
llm = make_provider()
|
|
print()
|
|
|
|
# Test 1: Simple text output — the node should call set_output to fill "answer"
|
|
r1 = await run_test(
|
|
name="Simple text generation",
|
|
llm=llm,
|
|
system=(
|
|
"You are a helpful assistant. When asked a question, use the "
|
|
"set_output tool to store your answer in the 'answer' key. "
|
|
"Keep answers short (1-2 sentences)."
|
|
),
|
|
output_keys=["answer"],
|
|
)
|
|
|
|
# Test 2: If test 1 failed, try bare stream() to isolate the issue
|
|
if not r1.success:
|
|
print(f"\n{'=' * 60}")
|
|
print("FALLBACK: Testing bare provider.stream() directly")
|
|
print(f"{'=' * 60}")
|
|
try:
|
|
from framework.llm.stream_events import (
|
|
FinishEvent,
|
|
StreamErrorEvent,
|
|
TextDeltaEvent,
|
|
ToolCallEvent,
|
|
)
|
|
|
|
text = ""
|
|
events = []
|
|
async for event in llm.stream(
|
|
messages=[{"role": "user", "content": "Say hello in 3 words."}],
|
|
):
|
|
events.append(type(event).__name__)
|
|
if isinstance(event, TextDeltaEvent):
|
|
text = event.snapshot
|
|
elif isinstance(event, FinishEvent):
|
|
print(f" Finish: stop={event.stop_reason} in={event.input_tokens} out={event.output_tokens}")
|
|
elif isinstance(event, StreamErrorEvent):
|
|
print(f" StreamError: {event.error} (recoverable={event.recoverable})")
|
|
elif isinstance(event, ToolCallEvent):
|
|
print(f" ToolCall: {event.tool_name}")
|
|
print(f" Text : {text!r}")
|
|
print(f" Events : {events}")
|
|
print(f" RESULT : {'OK' if text else 'EMPTY'}")
|
|
except Exception as e:
|
|
print(f" EXCEPTION: {type(e).__name__}: {e}")
|
|
import traceback
|
|
|
|
traceback.print_exc()
|
|
|
|
print(f"\n{'=' * 60}")
|
|
print("DONE")
|
|
print(f"{'=' * 60}")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
asyncio.run(main())
|