You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
feat(frontend): Playground share links, last selection and links in from other /m pages - #8075
The /m prompt playground (hidden developer view playground) lost its work on a reload, could not be shared, and opened on the latest revision every time. No other /m screen linked to it. This is the last playground PR of the /m views program (map row PR 8).
Changes
Share links and reload. The playground writes its state to the address, in the same format as /w:
The hash holds the drafts, the evaluators connected after the app, and the test set (a connected test set or the local rows). On open, the page reads the hash first, then ?revisions=, then the app's last selection, then the latest revision. It uses the package urlSnapshotController (hydrateFromUrl, buildUrlComponents) and applies each draft when its revision data arrives. A broken or stale hash is ignored: the page falls back to ?revisions= or the latest revision. The address is written 300 ms after the last change, so typing does not re-render the page on every key.
Last selection per app. The page stores the revisions it showed, per app, under the /w key agenta:playground:last-selection. A plain link to the app opens on them.
Links into the playground. All links use prefetch={false} and an import-free URL builder, and show only while the view is on.
Prompts list: a prompt row opens the playground.
Variants page: "Open in playground" in the revision row menu, and in the revision drawer on both tabs.
Evaluators page (automatic tab): "Open in playground" in the drawer opens the evaluator playground.
Trace drawer: the span header's "Playground" button. /w runs openFromTrace, which writes into the shared playground store before it navigates. /m does not: the agent session screen shares that store. Instead /m builds the address, with the span inputs as one local test case in the hash. An agent trace opens the agent chat (decision F-D4). An evaluator span opens its revision in the evaluator playground. A chat span, or a span with no app, shows a message. The code loads on the first click.
Focus drawer: "Add to queue" for a test case of a connected test set, as in /w, with the /m queue picker (loaded on demand).
Not in this PR (target code is not in this base).
"New Evaluation" from the playground header: needs the M7 NewEvaluationSheet (feat/m-view-new-evaluation). The seam: open the sheet with initialRevisions set to the shown saved revisions.
"Add to test set" per generation row: needs the M10 drawer (feat/m-view-add-to-testset).
mobileRouteFor paths for the "on" step, not wired: /apps/{id}/playground (without session) to /m/w/{ws}/p/{p}/apps/{id}/playground with its search, and /evaluators/playground to the /m route. The gate sees only the path and search, so a hash does not carry over.
The deployment history row menu has no playground item.
Shared code and its effect on /w
@agenta/playgroundrestoreLoadableConnection: after the test cases load, it stops when the playground has moved to another revision or was left. It also takes an optional {isCurrent}. Before, a late answer replaced the test cases of the next screen. /w calls it without the option, so /w gets only the first check. This fixes the same race in /w.
@agenta/playground index: also exports extractReferences, resolveTraceRefs and looksLikePromptConfig. No behavior change.
@agenta/playground-ui/panels/focusFocusDrawer: an optional renderAddToQueue prop. /w does not use this panel.
@agenta/observability-uiTraceTypeHeader: a comment only.
/w bugs found
/w never registers setSelectionUpdateCallback. A shared compare link with two copies of one revision keeps the restore placeholder in the selection after the copy exists. /m registers it (tested).
The late test set restore above.
Decisions (Mahmoud may overrule)
The trace "Playground" button is gated on the playground view only. The M10 observability-actions view is not in this base.
The last selection shares the /w key, so /w and /m continue each other's selection.
No localStorage copy of the drafts (/w keeps one for snapshots over 8 KB). A snapshot over 8 KB is not written, so its drafts do not survive a reload.
A prompt row click opens the playground, as in /w. The row menu is unchanged.
Tests
New: playgroundSnapshot.test.tsx (round trip of drafts and rows through the hash, two copies of one revision, a broken hash, a stale hash, an evaluator restore, an evaluator draft that keeps the hash, a link into the open page, a hash-only change), last selection per app, playgroundLinks.test.ts (each URL builder and the trace targets), playgroundAddToQueue.test.tsx, restoreLoadableConnection.test.ts (package). New cases in the prompts and variants screen tests. These use the real playground controller and snapshot codec; only HTTP is mocked.
/m types and /w types pass. @agenta/playground tests: 296 pass. Full /m suite: 1,647 pass, 3 fail: membersTabRoleChange (known) and two delete tests in playgroundRevisionActions, which fail the same way on the base commit.
Lint on the changed files passes. speed:check passes. No antd in the playground route.
Size, first-load gzip against the base commit: the app shell is 0.5 KB smaller, and every page is 0.1 to 0.9 KB smaller. Prompts, variants and evaluators stay within 0.1 KB of the shell change. I did not find why the shell got smaller; it is likely a chunk re-split. I did not measure the on-demand playground chunk.
Review loop: three rounds of slop and simplify (Opus) and correctness (Codex), then a Codex correctness pass on the hash-only fix. Final ratings: slop Low, simplify Low, correctness Low. The last commit after that only styles the menu link.
Not verified: live QA on a running stack (no recording yet), and the trace button against real traces.
What to QA
Turn on the playground view first.
Open an app's playground, edit the prompt and a test case value, reload. The edits come back. Copy the address into a new tab. Same result.
Open the app again from the prompts list. It shows the revisions you had last, not the latest one.
Variants page: row menu, then "Open in playground". The playground opens on that revision. The revision drawer has the same button.
Traces page: open a completion app trace, then "Playground". The playground opens on that revision with the trace inputs as the test case. An agent trace opens the agent chat.
Connect a test set, open a row in the focus drawer, then "Add to queue". The row goes to the picked queue.
Regression: in /w, open a shared playground link with a connected test set and leave quickly. The next screen keeps its own test cases.
A late test set restore no longer connects after the page is left, chat rows wait for the
revision's mode, a link into the open playground sets it up again, and trace spans follow the
package's rules for span type, prompt inputs and evaluators.
Each set-up has its own token, so a restore that outlives it cannot touch the next set-up on the
same revision; the address waits for evaluator drafts too; only a chat span is refused.
Review loop result for head bdf33d3a8f (base 6b0e33ebc9), 3 rounds plus one Codex correctness pass on the last fix. Slop and simplify ran on Opus, correctness on Codex.
Lens
Round 1
Round 2
Round 3
Delta
Slop
Medium
Low
Low
Simplify
Low
Medium
Low
Correctness
High
High
Medium
Low
Fixed:
A late test set restore no longer connects after the page is left or set up again (package check plus a per set-up token passed as isCurrent).
Chat rows from a snapshot wait until the revision is known to be a chat app.
A link into the open playground, including a change of the hash alone, sets the page up again; a shallow change that drops the hash gets it back.
The address keeps an evaluator draft until its revision loads.
Trace inputs drop prompt templates; a chat span is refused with the package message; an evaluator span opens the evaluator playground.
Left on purpose:
restoringRef is kept instead of starting the writer from the restore promise: it also guards the hash re-add path.
No /m-level test for the per set-up token on the same revision; the package test covers isCurrent.
The commit after this head (7df76ba981) only adds two classes to the variants menu link.
Open prompts, revisions, evaluator revisions, and supported traces in the Playground when the relevant view is enabled.
Preserve Playground selections and drafts across links with URL snapshots and per-app saved selections.
Add eligible test cases to a queue from the Playground drawer.
Bug Fixes
Improve restoration of Playground state and test-case connections when navigating between views.
Avoid unnecessary navigation when clearing trace drawer parameters that are already absent.
The changes add URL-backed playground snapshots and saved selections, navigation from trace, prompt, evaluator, and revision views, and an optional Add to queue control in the focus drawer.
Changes: Playground integration
Layer / File(s)
Summary
Playground addresses and snapshot data web/mobile/src/features/playground/playgroundUrl.ts, playgroundLastSelection.ts, playgroundSnapshot.ts, web/mobile/tests/unit/playgroundLinks.test.ts
URL helpers build evaluator links, deduplicate revision IDs, and read or append snapshot hashes. Snapshot helpers serialize selection state, and local-storage helpers persist per-app selections.
The selection hook restores snapshots or revision state, synchronizes drafts, and debounces address updates. Loadable restoration checks whether the operation is still current. Tests cover restoration, saved selections, route changes, and interrupted loadable restoration.
The trace drawer binds a Playground action when the view is enabled. Target resolution handles span references and types, and can include trace inputs in a snapshot URL. The clear-parameters handler avoids navigation when neither parameter is present.
Prompt rows, evaluator revisions, and revision drawers and menus can link to playground URLs under their configured view conditions. Tests and stories cover these links.
sequenceDiagram
participant GlobalDrawers
participant bindTraceDrawerSeams
participant tracePlayground
participant Router
GlobalDrawers->>bindTraceDrawerSeams: pass router and playground setting
bindTraceDrawerSeams->>tracePlayground: load and call openTraceInPlayground
tracePlayground->>tracePlayground: resolve span references and target
tracePlayground->>Router: navigate to target URL
Router-->>tracePlayground: resolve navigation
tracePlayground->>Router: close trace drawer
Loading
Possibly related issues
Agenta-AI/agenta#8092: The issue concerns lost test-set rows and evaluator draft changes. This PR changes snapshot restoration and draft hydration in the same area.
Possibly related PRs
Agenta-AI/agenta#8050: Both PRs change trace-drawer behavior. This PR adds conditional Playground action binding.
Agenta-AI/agenta#8012: Both PRs change the playground route and URL contracts. This PR adds snapshots and saved-selection restoration.
Agenta-AI/agenta#8049: Both PRs modify playground selection state and URL synchronization.
Merge Risk: Low · previous review 42875
Mergeable with owner awareness: some evaluator trace links may open an unavailable page, failed trace lookups provide no feedback, and one test depends on the runner’s environment.
Pre-merge checks: 5
Check name
Status
Explanation
Title check
The title "feat(frontend): Playground share links, last selection and links in from other /m pages" matches the main change. The PR adds snapshot URLs for the /m playground, per-app last-selection per…
Description check
The description is related to the changeset. It explains the /m playground share links and reload behavior, the per-app last selection, the links into the playground from prompts, variants, evaluators…
Docstring Coverage
Docstring coverage is 100.00% which is sufficient. The required threshold is 60.00%. Docstring coverage is scoped to functions touched by this diff with cyclomatic complexity of at least 2. Documentat…
Linked Issues check
Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check
Check skipped because no linked issues were found for this pull request.
Full details: Title check
Explanation
The title "feat(frontend): Playground share links, last selection and links in from other /m pages" matches the main change. The PR adds snapshot URLs for the /m playground, per-app last-selection persistence, and links into the playground from prompts, variants, evaluators, traces, and the focus drawer. The title is long (87 characters, 13 words) and lists several items, but it still names the primary changes accurately.
Full details: Description check
Explanation
The description is related to the changeset. It explains the /m playground share links and reload behavior, the per-app last selection, the links into the playground from prompts, variants, evaluators, trace, and focus views, and the shared @agenta/playground changes. It also lists tests and QA steps that match the code summaries.
Full details: Docstring Coverage
Explanation
Docstring coverage is 100.00% which is sufficient. The required threshold is 60.00%. Docstring coverage is scoped to functions touched by this diff with cyclomatic complexity of at least 2. Documentation-only edits and deletions within surviving functions are included; unchanged diff context and fully deleted functions are excluded. Analyzed 1 functions across 37 files.
Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts
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.
Preview use finished or expired. Environment absence verified; retained storage requires separate provider accounting.
Post /preview as a new comment to request a one-hour preview. Repeating it while active does not extend the hour.
Preview data is disposable. Expiry is enforced by the next successful cleanup sweep, not an exact timer.
Environment deletion stops its compute. Provider-retained storage and permanent services may still be billed.
Included review availability: This review used your included allowance. Your plan provides up to 8 included reviews per hour; 5 remain after this review.
The trace drawer clears its params after the close animation. By then the
Playground button has moved to the playground, and the push there dropped the
snapshot with the trace inputs. Clearing is now a no-op when the address has no
trace or span param.
Included review availability: This review used your included allowance. Your plan provides up to 8 included reviews per hour; 4 remain after this review.
🤖 The AI agent says: The branch is up to date and live QA passed on head 3d961eb. QA found one bug, and this head fixes it.
What changed on the branch:
I merged release/v0.128.5 in with a merge commit. The one conflict was in VariantsTable.tsx. I kept the release side (optional collapsed and onDelete) and made playgroundHref optional too, because the new overview "Recent prompts" table does not pass it. The base is now release/v0.128.5.
Fix (3d961eb): Trace drawer > "Playground" opened the right revision but lost the trace inputs. After its close animation, the packaged trace drawer clears ?trace and ?span again. By then the page is the playground, and that push dropped the #pgSnapshot hash. The clear now does nothing when the address has no trace or span param. A new test in traceDrawerQuery.test.ts fails without the fix.
Setup: one fresh OSS dev stack built from release/v0.128.5 with #8075, #8076, #8077 and #8086 merged in, developer views playground,prompts,variants,endpoints,observability-app-filter on, a new account, Chromium at 1440 px and 390 px.
Passed at 1440 and 390:
Edit the system prompt and a test case value, then reload. Both edits come back. The same address also restores both edits in a new tab and in a new browser context.
A broken hash, a truncated hash, or an unknown revision id with a garbage hash falls back to the latest revision. No error shows.
Prompt row: the first visit opens the latest revision (v2). After you visit v1, the row opens v1 (the last selection).
Variants row menu and revision drawer, "Open in playground" on v1: the playground opens on v1.
Trace drawer, "Playground" (with the fix): the playground opens on v1 with country: Japan as the test case.
Merge order: this PR and #8086 change the same import block in usePlaygroundSelection.ts. Whichever merges second needs the release branch merged in again. The fix is the union of the two import lists.
Checks: /m types, /w types, pnpm run lint in web/mobile (0 errors), the PR's tests (mobile 96, playground package) and the new test, and speed:check after a fresh next build all pass. Needed CI is green. The web test jobs do not gate, and "tests / run-api-tests (acceptance)" was still pending when I posted this.
The screen recording (MP4) is saved with the QA evidence. I could not attach it here because the browser upload was not available in this session.
12-20: Trivial · Maintainability & Code Quality · Low value
Cut the two-line chat-span comment to one line.
The in-code comment rule allows one short line per comment. Lines 70-71 explain the chat-span decision across two lines.
🔧 Suggested fix
- // The drawer's button allows a chat span, which /w replays as a copy in its revision drawer.- // /m has no such drawer, and the span's prompt inputs do not fit the app's inputs.+ // /m has no chat replay drawer, unlike /w.
Included review availability: This review used your included allowance. Your plan provides up to 8 included reviews per hour; 4 remain after this review.
The reason will be displayed to describe this comment to others. Learn more.
Minor · Stability & Availability · Quick win
Supported by static analysis
Script executed:
#!/bin/bash# Check how the drawer calls openTraceInPlayground and whether it handles rejection.
rg -nP -C6 'openTraceInPlayground' web/mobile/src web/packages/agenta-observability-ui/src
resolveTracePlaygroundTarget awaits resolveTraceRefs(refs, projectId) without a try/catch. TraceTypeHeader.tsx only uses finally, so it does not handle the rejection. The user can receive no message and no navigation when the lookup fails. Show an error and return from openTraceInPlayground:
Suggested fix
- const target = await resolveTracePlaygroundTarget({- base: `/w/${workspaceId}/p/${projectId}`,- projectId,- span,- })+ let target: TracePlaygroundTarget+ try {+ target = await resolveTracePlaygroundTarget({+ base: `/w/${workspaceId}/p/${projectId}`,+ projectId,+ span,+ })+ } catch {+ message.error("Could not open this trace in the playground. Try again.")+ return null+ }
The expected URL assumes the flag is off. agentEntryHref reads the flag through getEnv, which falls back to process.env in the Node test environment. If NEXT_PUBLIC_AGENT_OVERVIEW=true is set in the shell that runs Vitest, this assertion fails. Nothing in the test or the Vitest config pins the flag.
Mock getEnv for this key. Do not use vi.stubEnv here: buildEnv captures the value at module load, so a stubbed process.env value does not override it.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
For the release after v0.128.5.
Context
The /m prompt playground (hidden developer view
playground) lost its work on a reload, could not be shared, and opened on the latest revision every time. No other /m screen linked to it. This is the last playground PR of the /m views program (map row PR 8).Changes
Share links and reload. The playground writes its state to the address, in the same format as /w:
The hash holds the drafts, the evaluators connected after the app, and the test set (a connected test set or the local rows). On open, the page reads the hash first, then
?revisions=, then the app's last selection, then the latest revision. It uses the packageurlSnapshotController(hydrateFromUrl,buildUrlComponents) and applies each draft when its revision data arrives. A broken or stale hash is ignored: the page falls back to?revisions=or the latest revision. The address is written 300 ms after the last change, so typing does not re-render the page on every key.Last selection per app. The page stores the revisions it showed, per app, under the /w key
agenta:playground:last-selection. A plain link to the app opens on them.Links into the playground. All links use
prefetch={false}and an import-free URL builder, and show only while the view is on.openFromTrace, which writes into the shared playground store before it navigates. /m does not: the agent session screen shares that store. Instead /m builds the address, with the span inputs as one local test case in the hash. An agent trace opens the agent chat (decision F-D4). An evaluator span opens its revision in the evaluator playground. A chat span, or a span with no app, shows a message. The code loads on the first click.Not in this PR (target code is not in this base).
NewEvaluationSheet(feat/m-view-new-evaluation). The seam: open the sheet withinitialRevisionsset to the shown saved revisions.feat/m-view-add-to-testset).mobileRouteForpaths for the "on" step, not wired:/apps/{id}/playground(withoutsession) to/m/w/{ws}/p/{p}/apps/{id}/playgroundwith its search, and/evaluators/playgroundto the /m route. The gate sees only the path and search, so a hash does not carry over.Shared code and its effect on /w
@agenta/playgroundrestoreLoadableConnection: after the test cases load, it stops when the playground has moved to another revision or was left. It also takes an optional{isCurrent}. Before, a late answer replaced the test cases of the next screen. /w calls it without the option, so /w gets only the first check. This fixes the same race in /w.@agenta/playgroundindex: also exportsextractReferences,resolveTraceRefsandlooksLikePromptConfig. No behavior change.@agenta/playground-ui/panels/focusFocusDrawer: an optionalrenderAddToQueueprop. /w does not use this panel.@agenta/observability-uiTraceTypeHeader: a comment only./w bugs found
setSelectionUpdateCallback. A shared compare link with two copies of one revision keeps the restore placeholder in the selection after the copy exists. /m registers it (tested).Decisions (Mahmoud may overrule)
playgroundview only. The M10observability-actionsview is not in this base.Tests
playgroundSnapshot.test.tsx(round trip of drafts and rows through the hash, two copies of one revision, a broken hash, a stale hash, an evaluator restore, an evaluator draft that keeps the hash, a link into the open page, a hash-only change), last selection per app,playgroundLinks.test.ts(each URL builder and the trace targets),playgroundAddToQueue.test.tsx,restoreLoadableConnection.test.ts(package). New cases in the prompts and variants screen tests. These use the real playground controller and snapshot codec; only HTTP is mocked.@agenta/playgroundtests: 296 pass. Full /m suite: 1,647 pass, 3 fail:membersTabRoleChange(known) and two delete tests inplaygroundRevisionActions, which fail the same way on the base commit.speed:checkpasses. No antd in the playground route.What to QA
Turn on the
playgroundview first.