Skip to content

feat(studio): T02 node status overlay - #998

Merged
LinuxDevil merged 3 commits into
mainfrom
fb-t02-node-status
Nov 9, 2026
Merged

LinuxDevil merged 3 commits into
mainfrom
fb-t02-node-status

Conversation

@LinuxDevil

Copy link
Copy Markdown
Owner

Summary

Forge Builder ticket T02 (P6 Test and debug; deps D14 + C02, both merged). The canvas node status overlay is now driven by the server's node stream frames ({type:'node'}, NodeStatePayload — §3.3 node ids stamped by the SDK's nodeIdExporter) instead of the gen_ai.operation.name span-name heuristic, so every stamped node kind (agent, tools, subagents, handoffs, guardrails, approval waits, flow steps) lights up — not only LLM/tool nodes.

  • src/state/nodeStateReducer.ts (new, pure): NodeStates = latest frame per node id; applyNodeState keeps the newest by at, same-span-id frames always override, returns the same object when stale (React bail-out); isNewRun(prev, next) detects a run's first running status.
  • useAgentStream.ts / AppState.tsx: folds node messages into nodeStates, exposed on AppState; resets on agent switch, on runAgent() (via useAgentControls), and on isNewRun (tracked with a runStatusRef, also fed by the initial /status fetch).
  • canvas/nodeStatus.ts: span heuristic deleted; new nodeRunStatuses(nodeIds, nodeStates, runStatus) maps running→running/paused/idle by live run status, waiting→paused, done→done, error→error; sub-path child frames (sub:<name>/…) raise their group node via the existing rank; unknown ids ignored. nodeLookup.ts kept for Logs/Trace panels.
  • NodeCard.tsx / agents.css: cardClassName gains paused/error/done flags; .rf-node.paused warning-border pulsing ring, .rf-node.error static danger-border ring, .rf-node.done pill only; ring animation off under prefers-reduced-motion. U01 --warning-border/--danger-border tokens verified present in theme.css.

T01's test-pane drawer is in flight on fb-t01-test-pane and was not a dependency; the overlay lives entirely on the canvas per the ticket.

Test plan

  • npm run typecheck --workspace apps/agent-forge — clean
  • npm test --workspace apps/agent-forge -- --run — 181 files / 3480 tests pass
  • New/updated tests: state/__tests__/nodeStateReducer.test.ts (at-ordering, same-span override, isNewRun table), canvas/__tests__/nodeStatus.test.ts (frame mapping table, frame-by-frame run, group raise, rank, unknown ids), AgentNode.test.tsx (paused/error/done classes + updated snapshot), polishCss.test.ts (ring tokens + reduced-motion)
  • npx eslint on touched files — clean; fallow audit --base origin/main — no issues in changed files

Drive the canvas node status overlay from the server's `node` frames
(D14/S20) instead of the gen_ai span-name heuristic: a new pure
nodeStateReducer keeps the latest frame per node id (latest `at` wins,
same span id overrides), useAgentStream folds `node` messages into
AppState.nodeStates and resets them on agent switch, runAgent() and a
new run's first `running` status (isNewRun). nodeRunStatuses maps
running/waiting/done/error frames onto the card vocabulary - running is
live only while the run is, waiting reads paused, and sub-path child
frames raise their `sub:<name>` group node by rank. Cards gain
paused/error/done state classes with warning/danger ring styling in
agents.css (ring animation off under prefers-reduced-motion).
Approval waits never reached the canvas: the wait span was not stamped
with the SDK node-id attribute, so nodeStates.ts derived no 'waiting'
frame and the node never read paused. Compile spec agents through a new
shared compileSpecWithNodeIds helper (spec/v2) that wires the
nodeIdExporter into the compiler trace exporter, and teach
nodeStateFor to map the approval-wait marker span start to 'waiting'.
Client nodeRunStatuses maps waiting frames to paused and keeps them
paused for the rest of the run.
…pe graph

The lousho/spec entry is browser-safe; typing the parameter as Subagents
made api-extractor inline the whole agent runtime type graph
(SimpleAgent, AgentRun, approvals, checkpoints...) as forgotten exports
in api/spec.api.md. A structural parameter (a name->agent record or a
{ list } catalog) accepts the same callers without the report churn.
Regenerate api/index.api.md and api/spec.api.md for the new public
exports compileSpecWithNodeIds and subAgentNodeIndexes.
@LinuxDevil
LinuxDevil merged commit 1831a93 into main Nov 9, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant