Skip to content

fix(ai): tighter agent timeline — thread the rail, fold MCP approval into its run-node - #61

Merged
ndemianc merged 1 commit into
developfrom
fix/agent-timeline-rail-and-mcp-fold
Jul 29, 2026
Merged

fix(ai): tighter agent timeline — thread the rail, fold MCP approval into its run-node#61
ndemianc merged 1 commit into
developfrom
fix/agent-timeline-rail-and-mcp-fold

Conversation

@ndemianc

Copy link
Copy Markdown
Contributor

Two changes that make the agent activity timeline read as one clean thread — most visible on an MCP run, which is what prompted this.

1. Thread the rail across the row gap

The timeline rail is drawn per-row (.tl-rail::before spans one row), but #log stacks rows with a gap: 12px flex gap — so there was 12px of dead space between every row and the rail rendered as disconnected stubs ("cut in the middle"). Now a row that directly follows another timeline row extends its rail up to meet it:

#log > .tl + .tl > .tl-rail::before { top: -12px; }

A run of tool / approval / group nodes reads as one connected line (GitHub / Cursor / Claude style); a narration bubble in between still breaks it (intended). Scoped to #log's direct children, so rows nested inside a collapsed group keep their own contiguous rail.

2. Fold an approved MCP call into one row

A manually-approved MCP tool call rendered two rows — an Approved · server · tool chip and a separate 🔌 server · tool node. The run-node now folds into the approval chip so each call is one row (Copilot-style, one-row-per-action):

  • agent.js tags the run-node kind: 'mcp'.
  • addMcpApproval hands its row to the incoming node only when approved.
  • addAgentLine folds a kind==='mcp' node into that pending row, and clears the window otherwise.

Edge cases preserved: allow-listed calls were already one row (no card); skipped calls keep their Skipped chip (nothing ran); only the approved / always-allowed pair folds. The folded row shows 🔌 server · tool (matching allow-listed calls) rather than the approval verb — the persistent allow-list effect lives in settings.

Tests

  • Two new webviewCss static invariants: the rail-bridge offset stays equal to #log's gap (no drift), and the MCP fold's three-part handshake stays wired end to end (agent.jsaddMcpApprovaladdAgentLine).
  • Verified both files parse (agent.js + the chat.html webview <script>); full extension suite 27 suites, 0 failures.

🤖 Generated with Claude Code

Copilot AI review requested due to automatic review settings July 29, 2026 01:09

Copilot AI 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.

Pull request overview

This PR refines the LevelCode AI webview’s agent activity timeline so MCP activity reads as a single, continuous “thread” (rail continuity + one-row-per-approved-MCP-call), and adds CSS/JS invariants to prevent regressions.

Changes:

  • Extend the timeline rail across #log’s flex gap between consecutive top-level timeline rows.
  • Fold an approved MCP tool call’s run-node into the approval row (so it renders as one timeline row instead of two).
  • Add regression tests for the rail-gap offset sync and the MCP folding handshake; add a new design doc for chat sessions.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.

File Description
extensions/levelcode-ai/media/chat.html Adds the rail-bridging CSS rule; introduces mcpMergePending and folds approved MCP run-nodes into the approval row.
extensions/levelcode-ai/agent.js Tags MCP tool run-node posts with kind: 'mcp' so the webview can detect and fold them.
extensions/levelcode-ai/test/webviewCss.test.js Adds invariants to keep the rail gap/offset in sync and ensure the MCP fold wiring remains intact.
docs/levelcode-chat-sessions-design.md Adds a proposed design document for persistent chat sessions (not referenced in the PR description).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread docs/levelcode-chat-sessions-design.md Outdated
Comment on lines +1 to +5
# Chat Sessions — design

**Status:** proposed · **Scope:** `extensions/levelcode-ai` (chat + agent) · **Depends on:** nothing new; reuses the M5 compaction machinery

The problem, in one sentence: **"New Chat" is destructive.** `conversation` and
…into its run-node

Two timeline-rendering fixes, most visible on an MCP run:

1. Thread the rail across #log's 12px flex-gap between consecutive top-level
   rows (#log > .tl + .tl > .tl-rail::before { top: -12px }). The per-row rail
   left a 12px void between EVERY row, so a run read as disconnected stubs
   ('cut in the middle'); it now reads as one connected line, breaking only at
   narration (intended). Scoped to #log's direct children so grouped rows keep
   their own rail.

2. Fold an approved MCP tool call into ONE row instead of an 'Approved · server
   · tool' chip PLUS a separate '🔌 server · tool' node. agent.js tags the
   run-node kind:'mcp'; addMcpApproval hands its row to that node only when
   approved; addAgentLine folds it in. Allow-listed calls were already one row;
   skipped calls keep their chip.

Two new webviewCss invariants (rail-bridge == #log gap; the fold handshake).
Full extension suite: 27 suites, 0 failures.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings July 29, 2026 01:15
@ndemianc
ndemianc force-pushed the fix/agent-timeline-rail-and-mcp-fold branch from d72508f to 54ccaa5 Compare July 29, 2026 01:15

Copilot AI 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.

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated no new comments.

Comments suppressed due to low confidence (1)

extensions/levelcode-ai/media/chat.html:1876

  • The MCP fold can incorrectly consume an agentTool row if mcpMergePending points at a detached element (e.g. the user triggers “New chat” / the host posts {type:'reset'} after approval but before the run-node arrives). In that case addAgentLine returns early after mutating a node that’s no longer in #log, so the tool row never renders. Guard the fold with log.contains(mcpMergePending) so a stale ref falls through to normal rendering and gets cleared.
    if (kind === 'mcp' && mcpMergePending){
      mcpMergePending.className = 'tl tl-tool';
      mcpMergePending.innerHTML = rowHtml;
      mcpMergePending = null;
      scrollIfStuck();

@ndemianc
ndemianc merged commit 124af85 into develop Jul 29, 2026
2 checks passed
@ndemianc
ndemianc deleted the fix/agent-timeline-rail-and-mcp-fold branch July 29, 2026 01:19
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.

2 participants