chore: lint

This commit is contained in:
Richard Tang
2026-04-20 13:09:02 -07:00
parent c1d7b0ee69
commit 17150a53bd
11 changed files with 120 additions and 151 deletions
@@ -567,7 +567,7 @@ def build_llm_compaction_prompt(
user_messages_section = (
"6. **User Messages** — Reproduce EVERY user message verbatim and "
"in full, in chronological order, each on its own line prefixed "
"with the message index (e.g. \"[U1] ...\"). Do NOT paraphrase, "
'with the message index (e.g. "[U1] ..."). Do NOT paraphrase, '
"summarise, merge, or omit any user message. Preserve markdown, "
"code fences, whitespace, and punctuation exactly as the user "
"wrote them.\n"
+4 -2
View File
@@ -4,6 +4,7 @@ from __future__ import annotations
import json
from dataclasses import dataclass, field
from datetime import UTC
from pathlib import Path
@@ -227,9 +228,10 @@ def discover_agents() -> dict[str, list[AgentEntry]]:
# Fallback: use directory creation time if metadata lacks created_at
if not colony_created_at:
try:
from datetime import datetime, timezone
from datetime import datetime
stat = path.stat()
colony_created_at = datetime.fromtimestamp(stat.st_birthtime, tz=timezone.utc).isoformat()
colony_created_at = datetime.fromtimestamp(stat.st_birthtime, tz=UTC).isoformat()
except Exception:
pass
@@ -112,10 +112,7 @@ def format_conversation_excerpt(messages: list[Message]) -> str:
# Surface tool-call intent for empty assistant turns so the
# evaluator sees what the queen has been doing.
if not content and msg.tool_calls:
names = [
tc.get("function", {}).get("name", "?")
for tc in msg.tool_calls
]
names = [tc.get("function", {}).get("name", "?") for tc in msg.tool_calls]
content = f"(called: {', '.join(names)})"
if len(content) > _MAX_ASSISTANT_CONTENT_CHARS:
content = content[:_MAX_ASSISTANT_CONTENT_CHARS] + "..."
@@ -224,9 +221,7 @@ async def evaluate(
return {
"ready": False,
"reasons": ["evaluation_failed"],
"missing_prerequisites": [
"evaluator LLM call failed; retry once the queen can reach the model again"
],
"missing_prerequisites": ["evaluator LLM call failed; retry once the queen can reach the model again"],
}
raw = (getattr(response, "content", "") or "").strip()
@@ -239,9 +234,7 @@ async def evaluate(
return {
"ready": False,
"reasons": ["evaluation_failed"],
"missing_prerequisites": [
"evaluator returned malformed JSON; retry"
],
"missing_prerequisites": ["evaluator returned malformed JSON; retry"],
}
return _normalize_verdict(parsed)
+2 -12
View File
@@ -474,12 +474,7 @@ queen_node = NodeSpec(
nullable_output_keys=[], # Queen should never have this
skip_judge=True, # Queen is a conversational agent; suppress tool-use pressure feedback
tools=sorted(
set(
_QUEEN_INDEPENDENT_TOOLS
+ _QUEEN_INCUBATING_TOOLS
+ _QUEEN_WORKING_TOOLS
+ _QUEEN_REVIEWING_TOOLS
)
set(_QUEEN_INDEPENDENT_TOOLS + _QUEEN_INCUBATING_TOOLS + _QUEEN_WORKING_TOOLS + _QUEEN_REVIEWING_TOOLS)
),
system_prompt=(
_queen_character_core
@@ -492,12 +487,7 @@ queen_node = NodeSpec(
)
ALL_QUEEN_TOOLS = sorted(
set(
_QUEEN_INDEPENDENT_TOOLS
+ _QUEEN_INCUBATING_TOOLS
+ _QUEEN_WORKING_TOOLS
+ _QUEEN_REVIEWING_TOOLS
)
set(_QUEEN_INDEPENDENT_TOOLS + _QUEEN_INCUBATING_TOOLS + _QUEEN_WORKING_TOOLS + _QUEEN_REVIEWING_TOOLS)
)
__all__ = [
+1 -2
View File
@@ -141,8 +141,7 @@ async def await_completion(
return last
if loop.time() >= deadline:
logger.warning(
"compaction_status: timed out after %.0fs waiting for %s "
"(proceeding with raw transcript)",
"compaction_status: timed out after %.0fs waiting for %s (proceeding with raw transcript)",
timeout,
queen_dir,
)
+5 -11
View File
@@ -1081,8 +1081,7 @@ async def _compact_inherited_conversation(
of the summary.
"""
import json as _json
from datetime import UTC as _UTC
from datetime import datetime as _datetime
from datetime import UTC as _UTC, datetime as _datetime
try:
result = await _compact_queen_conversation_in_place(
@@ -1140,8 +1139,7 @@ async def _compact_inherited_conversation(
logger.warning("compact_inherited: failed to append fork marker", exc_info=True)
logger.info(
"compact_inherited: compacted %d parent message(s) -> 1 summary "
"(%d chars) for colony forked from %s",
"compact_inherited: compacted %d parent message(s) -> 1 summary (%d chars) for colony forked from %s",
messages_compacted,
summary_chars,
source_session_id,
@@ -1501,8 +1499,7 @@ async def fork_session_into_colony(
)
except TimeoutError:
compaction_error = (
f"compaction timed out after {_COMPACTION_TIMEOUT_SECONDS:.0f}s "
"(falling back to raw transcript)"
f"compaction timed out after {_COMPACTION_TIMEOUT_SECONDS:.0f}s (falling back to raw transcript)"
)
logger.warning(
"fork_session_into_colony: %s for %s",
@@ -1512,8 +1509,7 @@ async def fork_session_into_colony(
except Exception as exc:
compaction_error = f"compaction failed: {exc}"
logger.warning(
"fork_session_into_colony: %s for %s "
"(falling back to raw transcript)",
"fork_session_into_colony: %s for %s (falling back to raw transcript)",
compaction_error,
_dest_queen_dir,
exc_info=True,
@@ -1619,9 +1615,7 @@ async def fork_session_into_colony(
# compact). Frontend uses this to decide whether to display a
# "preparing colony…" state while session-load blocks on the
# compaction marker.
"compaction_status": (
"in_progress" if source_queen_dir.exists() else "skipped"
),
"compaction_status": ("in_progress" if source_queen_dir.exists() else "skipped"),
}
+12 -24
View File
@@ -86,8 +86,6 @@ _INCUBATING_APPROVAL_GUIDANCE = (
)
def _render_credentials_block(provider: Any) -> str:
"""Call a credentials_prompt_provider safely and return its output.
@@ -570,9 +568,7 @@ async def _start_trigger_timer(session: Any, trigger_id: str, tdef: Any) -> None
if cron_expr:
try:
_peek = croniter(cron_expr, datetime.now(tz=UTC)).get_next(datetime)
_next_delay = max(
0.0, (_peek - datetime.now(tz=UTC)).total_seconds()
)
_next_delay = max(0.0, (_peek - datetime.now(tz=UTC)).total_seconds())
except Exception:
_next_delay = 60.0
else:
@@ -1557,8 +1553,7 @@ def register_queen_lifecycle_tools(
return None, f"triggers[{idx}] ('{tid}') interval_minutes must be > 0, got {interval}"
else:
return None, (
f"triggers[{idx}] ('{tid}') timer trigger needs 'cron' or "
"'interval_minutes' in trigger_config."
f"triggers[{idx}] ('{tid}') timer trigger needs 'cron' or 'interval_minutes' in trigger_config."
)
else: # webhook
path = (t_config.get("path") or "").strip() if isinstance(t_config.get("path"), str) else ""
@@ -1573,7 +1568,9 @@ def register_queen_lifecycle_tools(
"trigger_type": t_type,
"trigger_config": t_config,
"task": task_str.strip(),
"name": entry.get("name") if isinstance(entry.get("name"), str) and entry.get("name").strip() else tid,
"name": (
entry.get("name") if isinstance(entry.get("name"), str) and entry.get("name").strip() else tid
),
}
)
return normalized, None
@@ -1698,7 +1695,9 @@ def register_queen_lifecycle_tools(
colony_name=cn,
task=(task or "").strip(),
tasks=tasks if isinstance(tasks, list) else None,
concurrency_hint=concurrency_hint if isinstance(concurrency_hint, int) and concurrency_hint > 0 else None,
concurrency_hint=(
concurrency_hint if isinstance(concurrency_hint, int) and concurrency_hint > 0 else None
),
)
except Exception as e:
logger.exception("create_colony: fork failed after installing skill")
@@ -1739,9 +1738,7 @@ def register_queen_lifecycle_tools(
# the background; opening the colony will
# block on that until it finishes. "skipped"
# means no compaction was needed.
"compaction_status": fork_result.get(
"compaction_status", "skipped"
),
"compaction_status": fork_result.get("compaction_status", "skipped"),
},
)
)
@@ -1820,9 +1817,7 @@ def register_queen_lifecycle_tools(
"tasks_seeded": len(fork_result.get("task_ids") or []),
# Transcript compaction runs in the background; opening
# the colony blocks on this marker until it finishes.
"compaction_status": fork_result.get(
"compaction_status", "skipped"
),
"compaction_status": fork_result.get("compaction_status", "skipped"),
}
)
@@ -2105,12 +2100,7 @@ def register_queen_lifecycle_tools(
cn = (colony_name or "").strip()
if not _COLONY_NAME_RE.match(cn):
return json.dumps(
{
"error": (
"colony_name must be lowercase alphanumeric with "
"underscores (e.g. 'morning_hn_digest')."
)
}
{"error": ("colony_name must be lowercase alphanumeric with underscores (e.g. 'morning_hn_digest').")}
)
purpose = (intended_purpose or "").strip()
@@ -2197,9 +2187,7 @@ def register_queen_lifecycle_tools(
"status": "not_ready",
"colony_name": cn,
"reasons": verdict.get("reasons", []),
"missing_prerequisites": verdict.get(
"missing_prerequisites", []
),
"missing_prerequisites": verdict.get("missing_prerequisites", []),
}
)
+2 -6
View File
@@ -565,9 +565,7 @@ async def test_triggers_written_to_triggers_json(patched_home: Path, patched_for
@pytest.mark.asyncio
async def test_triggers_omitted_does_not_write_triggers_json(
patched_home: Path, patched_fork: list[dict]
) -> None:
async def test_triggers_omitted_does_not_write_triggers_json(patched_home: Path, patched_fork: list[dict]) -> None:
"""No triggers arg → no triggers.json (colony runs on-demand)."""
executor, _ = _make_executor()
@@ -585,9 +583,7 @@ async def test_triggers_omitted_does_not_write_triggers_json(
@pytest.mark.asyncio
async def test_triggers_invalid_cron_fails_before_fork(
patched_home: Path, patched_fork: list[dict]
) -> None:
async def test_triggers_invalid_cron_fails_before_fork(patched_home: Path, patched_fork: list[dict]) -> None:
"""A bad cron fails fast: no skill written, no fork call."""
executor, _ = _make_executor()
+49 -38
View File
@@ -469,11 +469,13 @@ class BeelineBridge:
parsed = json.loads(payload)
except Exception:
parsed = {"_raw": payload}
write_log({
"type": "viewport_event",
"tab_id": tab_id,
**parsed,
})
write_log(
{
"type": "viewport_event",
"tab_id": tab_id,
**parsed,
}
)
return
# Attach-time canary → attach_canary (proves extension
@@ -483,11 +485,13 @@ class BeelineBridge:
parsed = json.loads(payload)
except Exception:
parsed = {"_raw": payload}
write_log({
"type": "attach_canary",
"tab_id": tab_id,
**parsed,
})
write_log(
{
"type": "attach_canary",
"tab_id": tab_id,
**parsed,
}
)
return
# Everything else — keep a compact row so we can tell
@@ -503,24 +507,28 @@ class BeelineBridge:
compact.append(v[:120])
elif v is not None:
compact.append(str(v)[:120])
write_log({
"type": "cdp_event",
"tab_id": tab_id,
"method": method,
"level": params.get("type"),
"args": compact,
})
write_log(
{
"type": "cdp_event",
"tab_id": tab_id,
"method": method,
"level": params.get("type"),
"args": compact,
}
)
return
# Other forwarded events (Page.lifecycleEvent, frameResized,
# frameNavigated, Target.targetInfoChanged) are rare and high
# signal — keep the full param dict but truncate strings.
write_log({
"type": "cdp_event",
"tab_id": tab_id,
"method": method,
"params": params,
})
write_log(
{
"type": "cdp_event",
"tab_id": tab_id,
"method": method,
"params": params,
}
)
# Main-frame navigation wipes the previous document's scripts.
# Our [hive_vp] probe's event listeners die with it. Reinstall
@@ -541,6 +549,7 @@ class BeelineBridge:
if method == "Page.frameResized" and tab_id is not None:
try:
from .tools.inspection import _viewport_sizes
_viewport_sizes.pop(tab_id, None)
except Exception:
pass
@@ -550,6 +559,7 @@ class BeelineBridge:
current document of ``tab_id``. Called from sync context
inside ``_handle_cdp_event``, so we create a task on the
running loop. Failures are silent."""
async def _do() -> None:
try:
# The new document's global scope doesn't have
@@ -566,6 +576,7 @@ class BeelineBridge:
)
except Exception:
pass
try:
asyncio.get_event_loop().create_task(_do())
except RuntimeError:
@@ -868,8 +879,7 @@ class BeelineBridge:
{
"expression": (
"console.info('[hive_attach_canary]', "
"JSON.stringify({tabId: "
+ str(tab_id) + ", ts: Date.now()}))"
"JSON.stringify({tabId: " + str(tab_id) + ", ts: Date.now()}))"
),
"returnByValue": True,
"awaitPromise": False,
@@ -1379,9 +1389,7 @@ class BeelineBridge:
# `(function(){ return (...)(x,y) })()` and the value
# actually comes back — without it the wrapper drops
# the result on the floor (returns undefined).
probe_result = await self.evaluate(
tab_id, f"return ({_HIT_ELEMENT_JS})({x}, {y})"
)
probe_result = await self.evaluate(tab_id, f"return ({_HIT_ELEMENT_JS})({x}, {y})")
hit_probe = (probe_result or {}).get("result")
except Exception:
hit_probe = None
@@ -1410,16 +1418,19 @@ class BeelineBridge:
if hit_probe is not None:
try:
from .telemetry import write_log
write_log({
"type": "click_hit_probe",
"tab_id": tab_id,
"intended": {"x": x, "y": y},
"viewport": hit_probe.get("viewport"),
"hit": hit_probe.get("hit"),
"stack": hit_probe.get("stack"),
"sweep": hit_probe.get("sweep"),
"offsetInRect": hit_probe.get("offsetInRect"),
})
write_log(
{
"type": "click_hit_probe",
"tab_id": tab_id,
"intended": {"x": x, "y": y},
"viewport": hit_probe.get("viewport"),
"hit": hit_probe.get("hit"),
"stack": hit_probe.get("stack"),
"sweep": hit_probe.get("sweep"),
"offsetInRect": hit_probe.get("offsetInRect"),
}
)
except Exception:
pass
return resp
+40 -40
View File
@@ -240,23 +240,22 @@ async def _ensure_viewport_size(tab_id: int, _caller: str = "unknown") -> tuple[
try:
from ..telemetry import write_log
write_log({
"type": "viewport_sample",
"tab_id": tab_id,
"caller": _caller,
"live_w": cw,
"live_h": ch,
"cached_w": cached_before[0] if cached_before else None,
"cached_h": cached_before[1] if cached_before else None,
"deltaH_vs_cache": (
(ch - cached_before[1])
if (cached_before and ch > 0)
else None
),
"returned_w": result_cw,
"returned_h": result_ch,
"evaluate_error": evaluate_error,
})
write_log(
{
"type": "viewport_sample",
"tab_id": tab_id,
"caller": _caller,
"live_w": cw,
"live_h": ch,
"cached_w": cached_before[0] if cached_before else None,
"cached_h": cached_before[1] if cached_before else None,
"deltaH_vs_cache": ((ch - cached_before[1]) if (cached_before and ch > 0) else None),
"returned_w": result_cw,
"returned_h": result_ch,
"evaluate_error": evaluate_error,
}
)
except Exception:
pass
@@ -362,31 +361,32 @@ def register_inspection_tools(mcp: FastMCP) -> None:
# physical_scale is derived from pngWidth.
try:
from ..telemetry import write_log
expected_w = css_width * dpr
expected_h = css_height_raw * dpr
write_log({
"type": "screenshot_geometry",
"tab_id": target_tab,
"url": screenshot_result.get("url", ""),
"pngWidth": png_w,
"pngHeight": png_h,
"cssWidth": css_width,
"cssHeight": css_height_raw,
"dpr": dpr,
"expectedPngWidth": expected_w,
"expectedPngHeight": expected_h,
"deltaPngWidthPx": png_w - expected_w,
"deltaPngHeightPx": png_h - expected_h,
# If the PNG is taller than cssHeight×dpr (e.g. a
# devtools-attached banner adds rows above the page
# in the capture), clicks land BELOW intended at
# the top of the page and converge to 0 error at
# the bottom. Reverse signs if PNG is shorter.
# Worst-case error in CSS px at fy=0:
"yErrorAtTopCssPx": (
(png_h - expected_h) / dpr if dpr else 0
),
})
write_log(
{
"type": "screenshot_geometry",
"tab_id": target_tab,
"url": screenshot_result.get("url", ""),
"pngWidth": png_w,
"pngHeight": png_h,
"cssWidth": css_width,
"cssHeight": css_height_raw,
"dpr": dpr,
"expectedPngWidth": expected_w,
"expectedPngHeight": expected_h,
"deltaPngWidthPx": png_w - expected_w,
"deltaPngHeightPx": png_h - expected_h,
# If the PNG is taller than cssHeight×dpr (e.g. a
# devtools-attached banner adds rows above the page
# in the capture), clicks land BELOW intended at
# the top of the page and converge to 0 error at
# the bottom. Reverse signs if PNG is shorter.
# Worst-case error in CSS px at fy=0:
"yErrorAtTopCssPx": ((png_h - expected_h) / dpr if dpr else 0),
}
)
except Exception:
pass
+1 -5
View File
@@ -64,11 +64,7 @@ async def _build_visual_response(result: dict, bridge, target_tab: int | None) -
shot = await bridge.screenshot(target_tab, full_page=False)
if not shot.get("ok"):
return [text_block]
highlights = (
[_interaction_highlights[target_tab]]
if target_tab in _interaction_highlights
else None
)
highlights = [_interaction_highlights[target_tab]] if target_tab in _interaction_highlights else None
data, _ = await asyncio.to_thread(
_resize_and_annotate,
shot["data"],