Skip to content

fix(frontend): the running-elsewhere strip stops accusing your own tab - #5857

Merged
mmabrouk merged 1 commit into
release/v0.112.0from
fix/running-elsewhere-banner
Aug 10, 2026
Merged

fix(frontend): the running-elsewhere strip stops accusing your own tab#5857
mmabrouk merged 1 commit into
release/v0.112.0from
fix/running-elsewhere-banner

Conversation

@mmabrouk

@mmabrouk mmabrouk commented Aug 9, 2026

Copy link
Copy Markdown
Member

Fixes #5844.

Root cause

runningElsewhere = nest.isRunning && !busy mixed an instant local signal with a stale one: busy drops when the stream closes, while nest.isRunning comes from the project-wide liveness poll (staleTime 10s / refetch 15s). Nothing refreshed it at turn end, so for up to about 15 seconds after every answer, the tab that ran the turn accused itself of running elsewhere.

The fix

  1. Turn-end invalidation refreshes the liveness query in onFinish. The runner clears its heartbeat before ending the response stream, so the immediate refetch sees the settled server state.
  2. Local-first derivation treats running and awaiting as active ownership by this tab. error is correctly treated as settled, not active, so a newer liveness result can still reveal a subsequent run from another tab.
  3. Settlement stamp records active-to-idle and active-to-error transitions. The derivation only trusts liveness data newer than that local settlement, preventing stale backend state from flashing the strip after either a successful or failed local turn.

This also avoids unnecessary transcript catch-up polling after local turns and subscribes the dock to the derived boolean instead of every liveness poll result.

Verification

  • 163/163 AgentChatSlice tests pass, including regression coverage for stale and refreshed liveness after a local error.
  • tsc --noEmit passes.
  • ESLint and Prettier pass for the changed files.

Live check: create an agent and send a message. The strip must not appear in the same tab after success, while awaiting approval, or from stale liveness after an error. A fresh run from a second tab must still show the strip.

@vercel

vercel Bot commented Aug 9, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
agenta-documentation Error Error Aug 10, 2026 10:56am

Request Review

@dosubot dosubot Bot added size:M This PR changes 30-99 lines, ignoring generated files. bug report Something isn't working frontend labels Aug 9, 2026
@coderabbitai

coderabbitai Bot commented Aug 9, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Summary by CodeRabbit

  • Bug Fixes

    • Improved detection of sessions running in another location.
    • Refreshed session activity status when a local turn finishes.
    • Prevented stale activity information from incorrectly indicating remote execution.
    • Improved accuracy when distinguishing local activity from activity occurring elsewhere.
  • Tests

    • Added coverage for remote activity detection, refreshed activity data, and session status transitions.

Walkthrough

The change records local session settlement timestamps, derives remote-run state from local status and refreshed backend liveness, refreshes liveness after turn completion, and uses the derived state during session hydration.

Changes

Session liveness lifecycle

Layer / File(s) Summary
Track local session settlement
web/oss/src/components/AgentChatSlice/state/sessions.ts, web/oss/src/components/AgentChatSlice/state/sessions.runStatus.test.ts
Session state records timestamps when local runs settle. Tests cover valid and ignored transitions.
Derive remote-run state
web/oss/src/components/AgentChatSlice/state/liveness.ts, web/oss/src/components/AgentChatSlice/state/liveness.test.ts
isRunningElsewhere and sessionRunningElsewhereAtomFamily suppress remote activity during local runs, inactive backend liveness, or stale post-settlement snapshots. Tests cover these conditions.
Wire liveness refresh and hydration
web/oss/src/components/AgentChatSlice/hooks/useAgentChatSession.ts, web/oss/src/components/AgentChatSlice/hooks/useSessionHydration.ts
Turn completion invalidates session-liveness. Session hydration reads the derived remote-run state and keeps the local busy guard.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant useAgentChatSession
  participant QueryClient
  participant sessionRunningElsewhereAtomFamily
  participant useSessionHydration
  useAgentChatSession->>QueryClient: Invalidate session-liveness after turn completion
  QueryClient->>sessionRunningElsewhereAtomFamily: Refresh liveness timestamp
  sessionRunningElsewhereAtomFamily->>useSessionHydration: Provide remote-run state
  useSessionHydration->>useSessionHydration: Apply remote-run state with local busy guard
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly summarizes the primary frontend fix for preventing the running-elsewhere strip from appearing in the tab that executed the turn.
Description check ✅ Passed The description directly explains the root cause, fix, affected behavior, and verification for the running-elsewhere strip changes.
✨ Finishing Touches 💡 1
🛠️ Fix failing CI checks 💡
  • Create stacked PR
  • Commit on current branch
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/running-elsewhere-banner

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

github-actions Bot commented Aug 9, 2026

Copy link
Copy Markdown
Contributor

Railway Preview Environment

Status Destroyed (PR closed)

Updated at 2026-08-10T14:57:03.503Z

Issue #5844. runningElsewhere mixed an instant local signal with the cached 15s liveness poll, so the strip appeared after a local answer finished.

- Invalidate session liveness when a turn finishes.
- Treat running and awaiting as active local ownership. An error is settled: stale liveness stays hidden, while a newer true result can reveal a run from another tab.
- Stamp active-to-idle and active-to-error transitions, and only trust liveness data newer than that settlement.

This also avoids local transcript catch-up polling after a turn. 163 AgentChatSlice tests pass; TypeScript, ESLint, and Prettier are clean.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1


ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Organization UI (inherited)

Review profile: CHILL

Plan: Pro Plus

Run ID: 8125c6f7-72b5-459e-9e3d-2eeb88a7d84c

📥 Commits

Reviewing files that changed from the base of the PR and between 765a717 and 4b0eb5c.

📒 Files selected for processing (4)
  • web/oss/src/components/AgentChatSlice/state/liveness.test.ts
  • web/oss/src/components/AgentChatSlice/state/liveness.ts
  • web/oss/src/components/AgentChatSlice/state/sessions.runStatus.test.ts
  • web/oss/src/components/AgentChatSlice/state/sessions.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • web/oss/src/components/AgentChatSlice/state/liveness.test.ts
  • web/oss/src/components/AgentChatSlice/state/liveness.ts

Comment on lines +35 to +46
it("stamps an active run when it errors without restamping on cleanup", () => {
const store = createStore()
const id = `run-status-parked-${Date.now()}`

store.set(setSessionStatusAtom, {id, status: "awaiting"})
store.set(setSessionStatusAtom, {id, status: "error"})
const settledAt = store.get(sessionLocalSettledAtAtomFamily(id))
expect(settledAt).toBeGreaterThan(0)

store.set(setSessionStatusAtom, {id, status: "idle"})
expect(store.get(sessionLocalSettledAtAtomFamily(id))).toBe(settledAt)
})

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Locate and inspect the target test and related run-status implementation without executing repository code.
target="web/oss/src/components/AgentChatSlice/state/sessions.runStatus.test.ts"
if [ -f "$target" ]; then
  echo "== target target =="
  wc -l "$target"
  echo "== target contents =="
  cat -n "$target"
else
  echo "Target not found; locating similar files..."
  fd -i 'sessions.*runStatus.*test.*|runStatus.*test' .
fi

echo "== related implementation files =="
fd -i 'sessions.*ts|runStatus.*ts' web/oss/src/components/AgentChatSlice/state 2>/dev/null || true

echo "== Date.now usages in related state files =="
rg -n "Date\.now|setSessionStatusAtom|sessionLocalSettledAtAtomFamily|settlement|settled" web/oss/src/components/AgentChatSlice/state || true

Repository: Agenta-AI/agenta

Length of output: 9065


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== sessions.ts relevant atom definitions =="
sed -n '860,930p' web/oss/src/components/AgentChatSlice/state/sessions.ts | cat -n

echo "== package scripts/vitest availability =="
fd -a package.json . | sed 's#^\./##' | head -20
if [ -f web/package.json ]; then
  node - <<'JS'
const fs = require('fs')
const pkg = JSON.parse(fs.readFileSync('web/package.json', 'utf8'))
console.log(JSON.stringify(pkg.scripts || {}, null, 2))
console.log('vitest' in (pkg.dependencies || {}))
console.log('`@vitest`' in (Object.assign({}, pkg.devDependencies, pkg.dependencies || {})))
JS
fi
rg -n '"vitest"|"test:vite"|describe|testEnvironment' web/package.json web/vitest.config* web/package-lock.json 2>/dev/null || true

Repository: Agenta-AI/agenta

Length of output: 7523


Make the cleanup assertion distinguish the timestamp values.

setSessionStatusAtom can stamp the same Date.now() value for both the error settlement and the later idle cleanup path. Assert settledAt against the mocked error time, then keep the cleanup value equal to that same value rather than only comparing the two timestamps.

@mmabrouk mmabrouk added the lgtm This PR has been approved by a maintainer label Aug 10, 2026
@mmabrouk
mmabrouk merged commit aaa6f7a into release/v0.112.0 Aug 10, 2026
63 of 65 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug report Something isn't working frontend lgtm This PR has been approved by a maintainer size:M This PR changes 30-99 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant