Repository navigation
Closed
Labels
enhancementNew feature or requestNew feature or request
Description
As the owner, I would like Settings > Overview > "Recent tool calls" to keep showing my tool calls after Relay restarts, so the panel agrees with relay audit.
Background
The panel filters the in-memory audit ring (1000 events) on the client. After a relay restart, or once about 8 h of 30-second control calls have filled the ring, it shows "No tool calls recorded yet." while relay audit still lists tool calls. Seen for real on the devbox right after a rebuild, while working #160. #160's fix kept the empty-state text as written, so this is new behaviour, not a bug.
Acceptance criteria
- After a Relay relaunch, the panel lists the most recent tool calls recorded before it (the same rows
relay auditshows forcall_tool). - Control traffic can't push tool calls out of the panel.
- The empty state appears only when the audit log truly has no tool calls.
- A journey covers the relaunch case (depends on devbox/verify: a door into the Settings UI, and an Overview tool-calls journey #168).
Tasks
- T1 · Source: serve the panel's rows from the audit log, filtered to tool calls on the server side, with a bounded count.
- T2 · UI: the panel reads the new source; the empty-state logic follows it.
- T3 · Journey: tool call, relaunch, and the row is still listed.
Contract
Full text in the comment "Contract (relay#339 lane)". Ownership:
- T1
internal/audit/ops.go,cmd/relay/audit_routes.go,cmd/relay/ipc_audit.go,cmd/relay/ipc_handlers.go - T2
web/src/app.js,internal/webassets/settings.html - T3
e2e/features/g8_recent_tool_calls_test.go - T4
docs/routes.md,docs/events.md,docs/FEATURES.md,docs/architecture.md,docs/audit-log.md
Decisions made for the owner
- G8.03 already existed (the Overview row); it is updated in place, not duplicated. A third test,
TestRecentToolCallsCappedAtSix, pins the bound. - A remote
call_toolwrites an intent and a completion row; the panel shows both, asrelay audit --event call_tool --tail 6does. - Theoretical, not coded: the load answer can land before the same call's live event, showing one row twice until the next rebuild. Reasoned from the write order only.
Metadata
Metadata
Assignees
Labels
enhancementNew feature or requestNew feature or request
Activity
barelyworkingcode commentedon Oct 10, 2026
Owner decision (2026-10-10, delegated to watcher, item 1): approved, narrowed. Serve the panel's rows from the audit log, filtered to tool calls on the server side with a bounded count, so the panel agrees with relay audit after a relaunch. Proof: an e2e feature test through the CLI or HTTP door (the same rows relay audit shows for call_tool), red on main; the panel itself stays a screen row covered by the settings-window journeys at epic close. Drop T3 (a new journey) and the dependency on #168, which is closed. Goes to the relay bug bash lane after #200, #181, #214, #155.
barelyworkingcode commentedon Oct 10, 2026
Contract (relay#339 lane)
internal/audit/ops.go:RecentToolCallsLimit = 6;(*AuditOps).RecentToolCalls() []AuditEvent= Flush, thenQuery{Event: call_tool, Deep: true, Limit: 6}(the same file readrelay audituses,AuditTailBudget).[]when auditing is off. No caller-set filter or count.GET /api/audit/recent-tool-calls,control.ClassReadviaRegisterAuditRoutes, same listeners asGET /api/audit; 200, JSON array of audit rows, newest first, at most 6; query params ignored. Eventaudit.recent_tool_calls(count).recent_tool_calls→onRecentToolCalls(events), read off the main thread.web/src/app.js: Overview loads fromrecent_tool_calls; livecall_toolrows prepend, capped at 6; empty state only after load.internal/audit/ops.go,cmd/relay/audit_routes.go,cmd/relay/ipc_audit.go,cmd/relay/ipc_handlers.go; T2web/src/app.js,internal/webassets/settings.html(regenerated); T3 newe2e/features/g8_recent_tool_calls_test.go; T4docs/routes.md,docs/events.md,docs/FEATURES.md(G8.03),docs/architecture.md,docs/audit-log.md.TestRecentToolCallsSurviveRestart(2 calls, GET, restart, GET equals and matchesrelay audit --event call_tool --tail 6);TestRecentToolCallsOutlastControlTraffic(ring_size 4, control reads push calls out of the ring, route still lists both; empty[]before any call). Waits: mcp.state event, bridge reply, HTTP responses, harness Restart's ready.Decisions made for the owner
GET /api/audit?event=call_tool(the ring the panel reads) returning nothing after a restart whilerelay auditlists the calls; the PR records both.readcredential already sees every row viaGET /api/audit; this is a subset with the same redaction. Not inremoteHandlers.Merge pull request #358 from barelyworkingcode/fix/169-recent-tool-calls