mirror of
https://github.com/lobehub/lobehub.git
synced 2026-09-20 04:56:13 +08:00
edbcbe3233
* ✨ feat(cli): record local hetero agent runs as execution snapshots A heterogeneous agent run executed by the CLI left no durable record of itself: server-ingest runs persisted messages, standalone `lh hetero exec` runs persisted nothing, and neither produced the `ExecutionSnapshot` a native agent run writes. A process killed mid-run was simply gone. Record every run — server-ingest or standalone — into the same snapshot format the server already uses, under `~/.lobehub/traces`, so `lh trace op list` / `inspect` read local and production runs without branching. `HeteroTraceRecorder` folds the adapter's event stream into steps: `stream_start` … `step_complete{turn_metadata}` becomes a `call_llm` step carrying that turn's model and usage, `tool_start` … `tool_end` becomes its own `call_tool` step, and `step_complete{result_usage}` supplies the session grand total. Turns after the first open lazily, so adapters that emit `stream_start` once per session (Claude Code) and per turn segment alike. Writes are serialized and coalesced, and go straight through rather than re-reading the partial on every step as `appendStepToPartial` does. Three fixes in the tracing store that this depends on: - `savePartial` now writes atomically (temp file + rename). A partial exists precisely so a killed process can be recovered from it, and a plain `writeFile` interrupted by SIGKILL leaves truncated JSON — unparseable at exactly the moment it is needed. - `FileSnapshotStore` takes a `dirName`, so a host owning its own layout does not end up with a nested hidden `.agent-tracing/` inside it. - The `latest.json` symlink no longer fails the save when two runs race on it. `lh connect` sweeps the store on start: partials whose last step is older than six hours become `interrupted` snapshots (otherwise a crashed run — the one most worth finding — is the only one `list` cannot show), and snapshots past a fourteen-day window are deleted. Also isolates the CLI home in tests. Driving a command end to end previously wrote into the developer's real `~/.lobehub`, which this change would have turned into hundreds of stray trace files per test run. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * 🐛 fix(cli): keep subagent work out of the main trace spine Two issues from review. Claude Code's Task tool emits the subagent's turns and tool calls on the SAME stream as the main agent's, tagged with a `subagent` peer field. The recorder consumed them as main-agent events, so the child's text was appended to the parent's turn, the child's usage closed that turn early, and the child's tools surfaced as top-level calls — corrupting the trace precisely for the runs that use Agent/Task. Skip subagent-scoped events: the parent's own `Task` step still records what the child returned, which mirrors how the native runtime keeps a sub-agent in its own child operation rather than the parent's. `lh trace op inspect`/`replay` resolved the default `latest` target from the CLI-home store alone, and each store answers `latest` with its own newest entry — so a developer who had run both `lh hetero exec` and a local server inspected a stale run while `lh trace op list`, which merges and sorts both stores, showed the newer one first. Compare the two stores for the default target; an explicit id still needs no comparison. Both are covered by tests that fail without the fix — the subagent one drives the real `ClaudeCodeAdapter` through a Task sequence. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5 <noreply@anthropic.com>