Skip to content

fix(dashboard): new agents appear at once, not on the 30 s poll (#3109) - #3158

Merged
vybe merged 2 commits into
devfrom
fix/3109-dashboard-agent-created
Oct 1, 2026
Merged

vybe merged 2 commits into
devfrom
fix/3109-dashboard-agent-created

Conversation

@dolho

@dolho dolho commented Oct 1, 2026

Copy link
Copy Markdown
Contributor

Summary

On a fresh install, after the first-run overlay closed, the dashboard Timeline stayed empty for about 30 s, although setup had already seeded four agents. The issue names three gaps, and this fixes all of them:

  1. The overlay refetched nothing on close. Dashboard now watches the overlay's v-model:open and calls networkStore.fetchAgents() when it goes from true to false, as onCreateModalClose does for the create modal. This covers finish, skip and confirm-close. Setup's seeding doesn't go through the crud create path, so this refetch is what fixes the reported case.
  2. stores/network.js had no agent_created handler. It now refetches the REST list, which is access-controlled and tag-filtered and carries the full row, instead of inserting the broadcast's partial row (feat: agent-reported structured reports via MCP + dashboard display #918 thin trigger). A burst of creates is merged into one refetch (300 ms).
  3. agent_created / agent_deleted had no type key, and the dashboard dispatches on type. Both now send it, like agent_started / agent_stopped already do. This also revives the dead agent_deleted branch, which now reads the name from data.data, where it actually is.

The ent#467 /ws scoping reads event first, so it's unaffected; its tests pass.

Changes

  • src/backend/services/agent_service/crud.py, src/backend/routers/agents.py: add "type" to the agent_created and agent_deleted broadcasts
  • src/frontend/src/stores/network.js: the agent_created handler (coalesced refetch) and the revived agent_deleted branch
  • src/frontend/src/views/Dashboard.vue: refetch when the first-run overlay closes
  • Tests:
    • tests/unit/test_3109_agent_ws_type.py
    • src/frontend/tests/unit/networkAgentCreatedWs.spec.js
    • src/frontend/tests/unit/dashboardFirstRunRefetch.mount.spec.js

Test Plan

  • Backend:
    • the real _broadcast_agent_created payload carries type;
    • an AST guard requires every agent lifecycle broadcast to carry a matching type, so a new event added with event only fails.
  • Store: the store's own WebSocket is fed the backend's envelope:
    • 4 creates cause 1 refetch;
    • the broadcast payload is never inserted;
    • agent_deleted removes the agent.
  • Dashboard (mounted): closing the overlay refetches; opening it doesn't.
  • Mutation: reverting each source file turns its tests red. crud.py: 2; agents.py: 1; network.js: 3; Dashboard.vue: 1.
  • Full frontend suite: 4,499 passed. check-design-tokens and npm run build: OK. Related backend suites (ent#467 scoping, ent#107 seed, capacity, backlog): 148 passed.

Fixes #3109

🤖 Generated with Claude Code

After the first-run overlay closed on a fresh install, the Timeline showed no
agents for about 30 seconds, although setup had already seeded four. Three gaps
let that happen; each is fixed here.

1. Closing the overlay refetched nothing. Dashboard now watches the overlay's
   v-model and calls networkStore.fetchAgents() on true -> false, as
   onCreateModalClose already does for the create modal. That covers finish,
   skip and confirm-close. Setup's seeding does not go through the crud create
   path, so this refetch is what fixes the reported case.
2. stores/network.js had no `agent_created` handler. It now has one. The event
   triggers a refetch of the REST list, which is the access-controlled,
   tag-filtered source of the full row, rather than inserting the broadcast's
   partial row (the #918 thin-trigger rule). A burst (setup seeds four) is
   coalesced into one refetch within AGENT_CREATED_COALESCE_MS (300 ms).
3. The backend sent `agent_created` and `agent_deleted` with `event` but no
   `type`, and the dashboard dispatcher keys on `type`. Both now send `type`
   too, like agent_started and agent_stopped. That also revives the dead
   `agent_deleted` branch, which now reads the name from `data.data` where the
   payload carries it. The ent#467 /ws scoping reads `event` first, so it is
   unaffected (its tests pass).

Tests:
- test_3109_agent_ws_type.py: the real _broadcast_agent_created payload, plus
  an AST guard that every agent lifecycle broadcast in the backend carries a
  matching `type`.
- networkAgentCreatedWs.spec.js: the store's own WebSocket fed the backend's
  envelope. Four creates cause one refetch, the payload is never inserted, and
  a delete removes the agent.
- dashboardFirstRunRefetch.mount.spec.js: Dashboard mounted; closing the
  overlay refetches and opening it does not.

Reverting each source file turns its tests red: crud.py 2, agents.py 1,
network.js 3, Dashboard.vue 1. Full frontend suite 4,499 passed; the design
token check and the build pass; the related backend suites (ent#467 scoping,
ent#107 seed, capacity, backlog) pass.

Fixes #3109

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@dolho dolho added the ui PR touches the frontend UI — triggers Playwright e2e tests label Oct 1, 2026
…atches on (#3109)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@dolho

dolho commented Oct 1, 2026

Copy link
Copy Markdown
Contributor Author

/review report: fix/3109-dashboard-agent-created → dev

Files changed: 8 (+297/-1, including a learnings fragment). Scope: CLEAN. Plan completion: 3/3 suggested-scope items done:

  • refetch on overlay close;
  • an agent_created handler;
  • type on the broadcasts, reviving agent_deleted.

Execution coverage

changed symbol executed by live consumer verdict
_broadcast_agent_created type test_3109_agent_ws_type.py (real call) stores/network.js dispatcher ✅
agents.py agent_deleted type (both sites) the AST guard in the same file the same dispatcher 🛡 guard (its live consumer is the dispatcher)
network.js agent_created → coalesced fetchAgents networkAgentCreatedWs.spec.js (store's own socket) Dashboard / Timeline ✅
network.js revived agent_deleted same same ✅
Dashboard.vue overlay-close refetch dashboardFirstRunRefetch.mount.spec.js FirstRunOverlay v-model ✅

Fix mutations: reverting each file turns its tests red. crud.py: 2; agents.py: 1; network.js: 3; Dashboard.vue: 1.

Live check (local dev stack, 2026-10-01, dev + this PR)

With the dashboard open, an agent was created through POST /api/agents:

  • it appeared on the dashboard 0.53 s after creation (before this PR: the 30 s poll);
  • after DELETE it disappeared after 0.52 s.

Both test agents were removed.

Critical findings

None.

Informational

  • [I1] utils/websocket.js still pushes the agent_created payload into agentsStore as a partial row (pre-existing). With ent#467's per-agent /ws scoping it only reaches viewers with access, and fetchAgents write-through replaces it on the next read. Not introduced here; noted for consistency with the refetch rule this PR follows.
  • [I2] The coalescing timer isn't cleared on disconnectWebSocket (confidence 5/10). Worst case is one extra harmless fetchAgents after a disconnect.

Clean categories

  • ent#467 scoping: reads event first; test_ent467_ws_agent_scope.py passes.
  • Disclosure: the broadcast payload is unchanged apart from type.
  • Docs: bug-fix tier (commit message). A learnings fragment was added for the recurring "producer shape ≠ dispatcher key" class: docs/memory/learnings/2026-10-01-ws-event-vs-type-key.md.

Summary: Critical 0 · Informational 2 · Scope clean.

@vybe vybe left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

merge-train: batch validated on train #3172

@vybe
vybe merged commit 097e53c into dev Oct 1, 2026
26 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ui PR touches the frontend UI — triggers Playwright e2e tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants