Skip to content

Conversation

@ardaerzin
Copy link
Contributor

@ardaerzin ardaerzin commented Feb 2, 2026

the introduction of local drafts demanded a stateful url for playground with more information than just the displayed revision ids.

with this pr, we'll now have urls with:

  • displayed revisions
  • patch state information which allows
    • sharing local drafts
    • sharing uncommitted edits to api backed revisions

Open with Devin

…mpression

- Add snapshot subpath export to package.json
- Add lz-string@1.5.0 dependency for compression
- Add @types/lz-string@1.5.0 dev dependency
… management

- Add snapshot.ts with buildOssAppRevisionDraftPatch and applyOssAppRevisionDraftPatch functions
- Add parameterConversion.ts utilities for enhanced data conversion and comparison
- Export snapshot functions and types from ossAppRevision package
- Update isDirty check to compare parameters instead of full objects
- Add stripVolatileKeys, enhancedPromptsToParameters, enhancedCustomPropertiesToParameters helpers
- Add
… runnable entities

- Add snapshotAdapter.ts registry for unified snapshot operations across runnable types
- Implement appRevision snapshot adapter with buildDraftPatch and applyDraftPatch functions
- Implement ossAppRevision snapshot adapter using existing snapshot utilities
- Add auto-registration of adapters on module import
- Add Zod validation schemas for patch data structures
- Export snapshot adapter types and registry from
…port

- Add uuid@^11.1.0 dependency for draft key generation
- Add snapshot submodule with schema, codec, and validation utilities
- Add PlaygroundSnapshotV2 schema supporting commit and draft selection items
- Add encodeSnapshot/decodeSnapshot functions using lz-string compression
- Add snapshot controller and hydration utilities to state management
- Export snapshot types and functions from main package entry point
- Add MAX_ENCODED
- Add uuid@^11.1.0 to playground package dependencies
…ydration documentation

- Export clearPendingHydrations function from state module
- Update snapshot module documentation to reference PlaygroundSnapshotV2 instead of V1
- Simplify hydrateSnapshotAtom implementation by removing unnecessary snapshotV2 variable
- Update hydration documentation to remove v1 migration step from process description
…ot and update version to 1

- Remove PlaygroundSnapshotV2 type alias in favor of single PlaygroundSnapshot type
- Update SNAPSHOT_VERSION from 2 to 1
- Update all type references from PlaygroundSnapshotV2 to PlaygroundSnapshot
- Update version validation error message to use SNAPSHOT_VERSION constant
- Update documentation examples to reference PlaygroundSnapshot and use SNAPSHOT_VERSION constant
…aring with runnable type resolution

- Add urlSnapshotController with buildEncodedSnapshot, buildUrlComponents, and hydrateFromUrl actions
- Add RunnableTypeResolver interface for entity-agnostic type resolution
- Add setRunnableTypeResolver, getRunnableTypeResolver, and resetRunnableTypeResolver utilities
- Add hydrationComplete and pendingHydrationCount selectors for tracking hydration status
- Add applyPendingHydrations action
…pport

- Add usePlaygroundUrlSync hook to sync selection and drafts to URL in real-time
- Add urlSnapshotController integration with OSS runnable type resolver
- Add snapshot hash parameter (#pgSnapshot) for encoding draft patches in URL
- Add clearSnapshotFromUrl and updatePlaygroundUrlWithDrafts utilities
- Add selectedDraftHashAtom and selectedServerDataHashAtom for change detection
- Add isSelectionStorageHydrated check to prevent overwriting persisted selections
…t clearing

- Remove clearSnapshotFromUrl import and usage from usePlaygroundUrlSync
- Remove prevHydrationCompleteRef and hydration completion URL clearing effect
- Remove snapshot clearing after applying pending hydrations
- Rely on draftHash effect to rebuild URL when draft state changes after hydration
- Add comment explaining URL rebuild behavior during hydration
…state detection

- Add debug logging to ossAppRevisionIsDirtyWithBridgeAtomFamily when dirty state is detected
- Strip null values from message objects during parameter comparison to match server data format
- Update stripVolatileKeys to skip null values in nested objects (name, toolCalls, toolCallId)
- Update stripVolatileKeys documentation to clarify null handling behavior
- Extract strippedDraft and strippedServer variables for debug
… frontend-feature/stateless-playground-url-state
@vercel
Copy link

vercel bot commented Feb 2, 2026

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

Project Deployment Actions Updated (UTC)
agenta-documentation Ready Ready Preview, Comment Feb 9, 2026 6:26pm

Request Review

… frontend-feature/stateless-playground-url-state
… frontend-feature/stateless-playground-url-state
ardaerzin and others added 2 commits February 2, 2026 19:31
… frontend-feature/stateless-playground-url-state
… frontend-feature/stateless-playground-url-state
- Add isPlaceholderId function to detect placeholder IDs used during pending hydrations
- Update isLocalDraftId to recognize numeric-only IDs (timestamps) as local drafts
- Export isPlaceholderId from shared utils
…ter interface

- Add optional createLocalDraftWithPatch method for hydration support
- Used to recreate local drafts from URL snapshots with patches
… snapshotAdapter

- Add createLocalDraftWithPatch for hydrating local drafts from URL snapshots
- Add generatePlaceholderId and isPlaceholderId helpers
- Export isPlaceholderId from ossAppRevision module
…r createLocalDraftFromRevision

- Add resolveRootSourceId to always point to server revision, not another local draft
- Make createLocalDraftFromRevision return null instead of throwing when source unavailable
- Add getLocalDraftBySourceId helper for finding existing drafts
- Export resolveRootSourceId for use in snapshot adapters
- Add isPlaceholderId check to directQueryAtomFamily and enrichedQueryAtomFamily
- Placeholder IDs are temporary IDs used during pending hydrations
- Remove debug logging from isDirty check
…pshotController

- Add generatePlaceholderId for temporary IDs during pending hydrations
- Support creating local drafts for duplicate source revisions in compare mode
- Add selectionUpdateCallback for replacing placeholder IDs with actual local draft IDs
- Track pending hydrations with createLocalDraft flag and selectionIndex
- Export setSelectionUpdateCallback and isPlaceholderId
…arams

- Local draft IDs are ephemeral and won't work when opened in a new tab
- Resolve to source revision IDs for the query param
- Hash param contains patch data to reconstruct draft state
- Export new functions from agenta-playground package for OSS consumption
- Register callback to replace placeholder/source IDs with local draft IDs
- Use latestAppRevisionIdAtom for default selection (matches 'Last modified' tag)
- Skip URL revision processing when pending hydrations exist
- Improve ensurePlaygroundDefaults logic
- Remove console.log statements from discardRevisionDraft
- Remove unused prompt-related code from prompts.ts
Copy link
Contributor

@devin-ai-integration devin-ai-integration bot left a comment

Choose a reason for hiding this comment

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

Devin Review found 3 potential issues.

View 10 additional findings in Devin Review.

Open in Devin Review

@dosubot dosubot bot added size:XXL This PR changes 1000+ lines, ignoring generated files. and removed size:L This PR changes 100-499 lines, ignoring generated files. labels Feb 9, 2026
Rename file_id → file_data, name → filename, and mime_type → format in message content handlers to align with backend API expectations.
…schema

Add normalizeFileContentParts function to mirror reverseTransformer logic:
- Move data URLs from file_id to file_data
- Deduplicate aliased fields (name→filename, mime_type→format)
- Remove empty string values

Also revert file content field names in useMessageContentHandlers to use file_id, name, and mime_type (internal format) before normalization.
Copy link
Contributor

@devin-ai-integration devin-ai-integration bot left a comment

Choose a reason for hiding this comment

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

Devin Review found 2 new potential issues.

View 25 additional findings in Devin Review.

Open in Devin Review

Comment on lines 756 to 757
if revision_id is None:
raise ValueError(f"App revision with id {revision_id} not found!")
Copy link
Contributor

Choose a reason for hiding this comment

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

🟡 Misleading error message when revision_id is None: says 'not found' instead of 'required'

At line 757, the code checks if revision_id is None and raises ValueError(f"App revision with id {revision_id} not found!"). Since revision_id is confirmed to be None at this point, the error message renders as "App revision with id None not found!", which is misleading — the revision wasn't looked up and not found, the parameter was simply missing.

Impact and Context

This error message appears in the evaluate_batch_testset function in the evaluation pipeline. The old code checked if revision is None after fetching, which correctly meant "not found". The new code checks the input parameter before fetching, so the semantic is "missing/required", but the message still says "not found".

Impact: Debugging evaluation failures becomes harder because the error message doesn't accurately describe the root cause (missing required parameter vs. failed lookup).

Suggested change
if revision_id is None:
raise ValueError(f"App revision with id {revision_id} not found!")
if revision_id is None:
raise ValueError("revision_id is required but was not provided!")
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

<Space style={{justifyContent: "space-between"}}>
<Text className={classes.historyItemsTitle}>
<b>Revision</b> <span>v{item.revision}</span>
<b>Revision</b> <span>v{index + 1}</span>
Copy link
Contributor

Choose a reason for hiding this comment

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

🟡 DeploymentHistory revision numbering reversed: index + 1 counts from wrong end

The EE DeploymentHistory component changed from item.revision to index + 1 for displaying version numbers. Since the revision list is sorted newest-first (by new Date(b.created_at).getTime() - new Date(a.created_at).getTime() in web/oss/src/components/DeploymentsDashboard/atoms/index.ts:84), the newest revision gets v1 and the oldest gets vN.

Root Cause and Impact

The OSS atoms layer computes environment_revision: arr.length - index (web/oss/src/components/DeploymentsDashboard/atoms/index.ts:89) which gives the highest number to the newest revision — the conventional chronological ordering. The search filter at web/oss/src/components/DeploymentsDashboard/atoms/index.ts:106 uses v${item.environment_revision}, so searching for "v1" matches the oldest deployment.

But the EE DeploymentHistory uses index + 1, so the same oldest deployment is labeled with the highest number (e.g., v5). This means the same revision shows different version numbers in the table vs. the timeline history view.

Impact: Users see inconsistent revision numbers between the deployment table and the deployment history timeline. Version labels in the history view are effectively reversed.

Prompt for agents
In web/ee/src/components/DeploymentHistory/DeploymentHistory.tsx at line 244, the expression `index + 1` produces reversed version numbers because the list is sorted newest-first. The items should be labeled using a count-from-end approach to match the OSS atoms convention. Either:

1. Compute the revision number the same way the atoms do: replace `index + 1` with the total number of items minus the index. Since you're inside a `.map()`, you need access to the array length. If using `.map((item, index, arr) => ...)`, use `arr.length - index`.

2. Or, if the items already have an `environment_revision` field from the atoms layer, use `item.environment_revision` or `item.revision` instead of computing from the index.
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

@dosubot dosubot bot added size:L This PR changes 100-499 lines, ignoring generated files. and removed size:XXL This PR changes 1000+ lines, ignoring generated files. labels Feb 9, 2026
Copy link
Contributor

@devin-ai-integration devin-ai-integration bot left a comment

Choose a reason for hiding this comment

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

Devin Review found 1 new potential issue.

View 28 additional findings in Devin Review.

Open in Devin Review

…g encoding

Replace URLSearchParams with manual parsing in extractSnapshotFromHash to avoid '+' → space conversion that corrupts LZ-String's compressToEncodedURIComponent output.
@bekossy bekossy changed the base branch from main to release/v0.85.0 February 9, 2026 18:50
@dosubot dosubot bot added the lgtm This PR has been approved by a maintainer label Feb 9, 2026
@bekossy bekossy merged commit 5c48a37 into release/v0.85.0 Feb 9, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Frontend lgtm This PR has been approved by a maintainer size:L This PR changes 100-499 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants