Skip to content

Report command results to the hub — surface spawn/start refusals in the UI #22

Description

@xerhab

Context

Commands ride the heartbeat reply and are executed by handle_commands() in agent/hub-agent.py with at-least-once delivery and cmdId de-dup. But the ack is binary — "executed" — with no outcome attached. Several refusal paths only write to the container log:

  • spawn() refuses at MAX_SESSIONS or for an unknown repo → log(...) and return; no session record is created.
  • start() refuses at MAX_SESSIONS → same.
  • a poison command that throws is deliberately acked (correct — no retry loops) but its error goes only to the log.

The UI's optimistic pending state (pending map in index.html) covers this with a timeout: the spinner shows "Starting a new session…" for up to 45 seconds (PENDING_TTL_MS) and then silently disappears.

Problem

A refused spawn is indistinguishable from a slow one. The operator clicks, watches a ghost card spin for 45s, and ends up with nothing and no explanation — the actual reason ("at MAX_SESSIONS (6)") is buried in a container-log tail. Failures that do create a session record surface fine via errorMsg; it's precisely the refusals-without-a-record that vanish.

Proposal

  • Extend the ack channel: instead of ackedCommands: [cmdId], report ackedCommands: [{cmdId, ok, error?}] (keeping backward compat by accepting both shapes hub-side during transition).
  • Hub: keep a short-lived results map per host (cmdId → outcome, TTL a few minutes) in the agent record, exposed via /api/agents.
  • UI: the pending-state reconciler (reconcilePending()) checks results by cmdId — the spawn POST already returns the cmdId, it just isn't stored. On a failed result: clear the ghost immediately and show the error (toast or inline in the repo block).
  • This also gives restart a real completion signal — currently the UI notes it has "no observable signal — cleared by timeout" (RESTART_TTL_MS).

Touchpoints

  • agent/hub-agent.py — refusals become raised/returned errors captured into the ack; handle_commands(), spawn(), start()
  • agent-hub/server.js — result retention + API shape
  • agent-hub/public/index.html — store cmdIds from POST responses, reconcile against results, error display

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions