feat(11-E): seed service_agent_v3 Python flow on startup #22
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "feat/11-phase-e-seed-agent-v3"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
service_agent_v3Python flow: replaces the deleted DAG template with a@flow-decorated Python file embedded viainclude_str!and seeded as aWorkflow+WorkflowVersionon every server startup.instrument(client)so every RPC call appears in thePlay.spanstree.Changes
crates/hero_logic/src/seed_flows/service_agent_v3.py— flow source, ~320 LOC.@flow(name="service_agent_v3", inputs={prompt, model}).crates/hero_logic/src/seed.rs— replaces the no-op stub with aBUILT_IN_FLOWStable + JSON-RPC-over-UDS upsert. Idempotent onWorkflow.nameso user edits survive restart.crates/hero_logic/tests/e2e_create_event.rs— integration test that runs the full pipeline against live router + aibroker + osis_calendar. Skips cleanly when any prerequisite is missing..gitignore— add__pycache__/and*.pyc.Test plan
cargo build --workspacecleancargo test -p hero_logic --lib— 48 tests pass (4 new inseed.rs)cargo test -p hero_logic --test e2e_create_event— skips cleanly without live aibroker/osis_calendarhero_proc+hero_aibroker+hero_osis_calendarrunning — verifies the agent creates an event with the expected titleHow to verify locally (when services are up)
🤖 Generated with Claude Code
Replaces the deleted templates/service_agent_v3.json with a @flow-decorated Python file embedded via include_str! and seeded as a Workflow + WorkflowVersion on every server startup. The flow exercises the full Phase C executor stack — hero_router for service discovery, hero_aibroker REST for chat completions, generated stubs for selected services, subprocess for the generated script, retry-with-feedback on failure — and uses instrument(client) so every RPC call appears in the Play span tree. Files: - crates/hero_logic/src/seed_flows/service_agent_v3.py — the flow source. 320 LOC. @flow(name="service_agent_v3", inputs={prompt, model}) - crates/hero_logic/src/seed.rs — replaces the no-op stub with a BUILT_IN_FLOWS table + JSON-RPC-over-UDS upsert. Idempotent on Workflow.name so user edits survive restart. - crates/hero_logic/tests/e2e_create_event.rs — integration test that runs the full pipeline against live router+aibroker+osis_calendar. Skips cleanly when any prerequisite is missing. Tests: - 4 new unit tests in seed.rs (parser, source-vs-seed name match) - 48 hero_logic unit tests still green - E2E test skips cleanly without live aibroker/osis_calendar Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>Discovery from running the live E2E test against a real hero_proc/hero_router/hero_aibroker/hero_osis_calendar stack (per the hero_running + hero_sockets + herolib_ai skills): 1. Aibroker chat is JSON-RPC `ai.chat` on rpc.sock — NOT REST `/v1/chat/completions` on rest.sock (rest.sock is SSE-only per `herolib_ai`). Rewrote `_AibrokerChat.chat()` to post a JSON-RPC 2.0 envelope to `/rpc` with method `ai.chat`. 2. Default model bumped from `qwen/qwen-2.5-coder-32b-instruct` (truncates output around 100 chars in this broker config — the model emits stub scripts that compile-and-print-nothing) to `deepseek/deepseek-v3.1-terminus` which consistently emits complete code blocks. 3. OSIS `*_set` system-prompt guidance: the auto-generated `event_set(data: str)` wrapper sends `{"data": "<json string>"}` which the OSIS server rejects (it requires `data` to be a JSON object and EVERY field of the type to be present). Added an explicit pattern in the system prompt steering the LLM to call `client._call("event.set", {"data": <dict>})` with all defaults filled in. Stable across multiple runs. 4. Test diagnostics: print Play.spans tree on assertion (truncated per-line, full code visible) so future debugging doesn't require poking at the tempdir before it's torn down. Added matching `cg_span.log(code)` in the flow so the generated script lands in the span tree alongside its `code_chars` tag. Result: end-to-end test passes in ~8s. Agent reads the prompt, discovers 34 services, picks hero_osis_calendar, generates a complete dict-based event_set call, executes it, and the resulting event with the expected unique title is visible via `event.list`. Tests: - 48 hero_logic unit tests still green - e2e_create_event passes against live stack; skips cleanly without Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>The play detail page was rendering an empty cytoscape DAG (the old Node/Edge graph deleted in Phase D) — `GRAPH_DATA = {edges:[], nodes:[]}` because there are no nodes anymore. The data was all there in Play.spans but the UI didn't know how to render it. This commit replaces the DAG canvas with a span-tree view so users can actually see what their Python flow did: - Input pane (top): pretty-printed JSON of the @flow function's inputs - Step tree (middle): one row per span with name, status chip, duration_ms. Indentation matches parent_id depth so nested flow.step("...") and instrument()-wrapped RPC calls visibly nest under their parent. Click a span to expand and see: * RPC service.method (for instrument()-wrapped spans) * Link to child play (for play_run_async sub-flows) * Error traceback (for failed spans) * Full tags JSON (parameters, results, code, etc.) * Captured logs (stdout/stderr the flow logged via span.log) - Output pane (bottom): pretty-printed JSON return value - Side panel: status, duration, tokens, top-level error, workflow link - Live polling every 800ms while non-terminal — both server and client use the same depth algorithm so the running tree updates without a template re-render Removed: - All cytoscape / dagre / cytoscape-dagre / node-html-label CDN imports - The retry button (LogicService.play_retry was deleted in Phase D) - node_runs / node_logs paths in the play handler — replaced by spans Files: - crates/hero_logic_ui/src/routes.rs: PlayDetailTemplate now carries input_pretty / output_pretty / spans_json. New helpers `pretty_json_or_string` and `build_spans_view` pre-shape the data with depth resolved from parent_id walks (capped at 32 to defend against pathological cycles). - crates/hero_logic_ui/templates/play_detail.html: Drop the cytoscape canvas + drawer; render the input/steps/output sections inline with a JS-driven expand/collapse for span detail. Verified: http://localhost:9988/hero_logic/ui/plays/00gg now shows the prompt, 14 spans nested by parent_id (3 chat calls under select/code/debug attempts, RPC spans under each composite step), full generated Python code in the code_generation span's tags, and the agent's summary in the root span's result tag. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>