[FE/feat] Query Registry#4754
Draft
ardaerzin wants to merge 21 commits into
Draft
Conversation
Add a /queries page to view and manage saved trace-filter queries used by live evaluations: - New scoped @agenta/entities/query entity (create/edit/archive/unarchive, list, live match-count, matching-traces) over the Fern queries client - Query Registry dashboard with grouped table, search, duplicate, and a manage drawer that reuses the shared Filters editor inline - Toggle-able matching-traces preview reusing the observability columns + InfiniteVirtualTable shell - Active list plus a dedicated /queries/archived route with restore, mirroring the Evaluators archived-route pattern - Sidebar link, EE page stubs, and full-height layout wiring - Repoint the live-eval Online Evaluation drawer at the shared create path
Reuse the observability annotation pipeline (collect invocation links → queryAllAnnotations → attachAnnotationsToTraces) and derive evaluatorSlugs from the enriched traces, so the preview renders the evaluator-metric columns like the Observability table.
…nged applyFilter already no-ops when the draft equals the applied filter; reflect that in the button's disabled state for the always-visible inline editor (Query Registry drawer). The popover keeps Apply enabled as its primary close affordance.
…le baseline mapFilterData (props → internal) is not a clean inverse of sanitizeFilterItems, so comparing the sanitized draft against the raw filterData always read 'changed' — leaving Apply enabled on open and letting a clean draft fire onApplyFilter, which dirtied the drawer's Save too. Run both sides of the comparison through the same map → explode → sanitize pipeline so an untouched draft compares equal. Scoped to inline mode; the popover keeps Apply as its close affordance.
Queries are git-style entities (Query → Variant → Revision) with full commit/fork/revision-log on the backend, so model the edit drawer's draft state like the workflow/testset molecules instead of an ad-hoc form snapshot. - @agenta/entities/query: queryMolecule (createMolecule over the head-revision query + draft atoms), with a SEMANTIC order-insensitive isDirty (name + filtering + windowing deep-diff) so change-then-revert reads as clean, plus saveQueryHeadAtom committing a new head revision via editSimpleQuery. - Drawer: edit mode now drives the molecule (useController + reducers.update sync + saveQueryHeadAtom), replacing the snapshot-based dirty check; create stays on the one-shot path. - Unit tests for the semantic dirty diff (order-insensitivity + revert-to-clean). Revision history surfacing still depends on the backend simple-queries list returning variant_id (tracked in TODOS.md).
Each query (artifact) row in the registry expands to its earlier revisions, mirroring the workflow registry variants table (custom Name-cell toggle + tree-child rows, virtual-table-friendly), lazy-loaded on first expand. - Repoint queryQueryRevisions to query by the artifact ref (query_refs), not variant_id — simple queries are single-variant, so this is the full history and needs no variant id (which the list doesn't return). No backend change. - Revision child rows show a version badge + filter + created on/by; a loader placeholder shows while fetching; 'No earlier versions' when a query has only its head. - Per-row action hiding (ActionItem.hidden) suppresses the menu on revision rows; row-click is a no-op on them. - Corrected the stale TODOS.md note (revision history was never actually blocked on variant_id). Mechanically the expand reuses useGroupedTreeData's pattern (controlled expandedRowKeys + expandIcon: null + custom cell toggle) without the flat-revisions store rework, preserving the active/archived tabs + search + archive that operate on the artifact.
- Lazy revisions never loaded: the custom Name-cell toggle drives expansion, but the fetch was wired to antd's onExpand, which never fires when the caret is hidden (expandIcon: null). Move the fetch into the toggle's handleExpand so expanding actually fetches. - Expand toggle showed a bordered/focused box: it was a <button> (default chrome + focus ring). Switch to a plain <span onClick>, matching the workflow registry toggle. - Revision/loader rows showed a selection checkbox: override rowSelection.getCheckboxProps to disable + hide the checkbox on those rows.
… workflow variants) Make the parent row represent the latest revision, like the workflow variants table (comp-1 v5 + children v4..v1), instead of a version-less header. - Entity: add queryRevisionsForQueries — one batched queryQueryRevisions over multiple query_refs, grouped client-side by queryId (QueryRevisionSummary now carries queryId). Reuses the existing latest-revision pattern instead of a backend change. - Table: batch-fetch the visible page's revisions, enrich each head row with its head version badge + earlier-revision child rows. The expand toggle shows only when history exists; a spacer keeps single-revision rows aligned. - Replaces the lazy per-expand fetch (and its loader/empty placeholder rows) with the eager batched load.
Other git-style entities collect a commit message on update; do the same for queries. - Entity: add commitQueryRevision (git /queries/revisions/commit) which carries a message, unlike editSimpleQuery. saveQueryHeadAtom now commits via this when the head variant id is known (from the molecule's server data), falling back to editSimpleQuery otherwise; SaveQueryHeadParams gains an optional message. - Drawer: edit Save opens a lightweight commit modal (EnhancedModal + optional message textarea) instead of committing silently; create stays a one-shot. Theme-aware modal, resets with the drawer. - Test: commitQueryRevision payload contract (message + variant id).
Replace the bespoke commit modal with the reusable @agenta/entity-ui EntityCommitModal that other git-style entities use — version transition (vN → vN+1), filtering/windowing JSON diff preview, and commit message — for visual + behavioural consistency. - entity-ui: add 'query' to EntityType (+ its display-label entry) and a queryModalAdapter (getDisplayName, archive deleteAtom, commitAtom wrapping saveQueryHeadAtom, dataAtom = queryMolecule.atoms.data, commitContextAtom providing the version + diff). Registered alongside the other adapters. - Drawer: render the shared modal externally-controlled with the unwanted flows OFF — no commitModes (no save-mode/new-variant radio) and no createEntityFields (no name editing; the drawer owns the name). onSuccess refreshes the registry store + closes the drawer, solving the modal↔drawer↔list coordination.
After committing an edit, the registry's head rows refetch (paginated store invalidate), but the parent version badges + expandable revision rows come from the table's batched revision cache (React state), which was fetched once and never refreshed — so the version stayed stale and the new revision didn't appear. Add a refresh signal (queryRegistryRevisionsRefreshAtom) bumped by invalidateQueryRegistryStore; the table drops its cached revisions when it fires, so the batched fetch re-runs and the version + child rows reflect the new revision.
QueryRevisionSummary already carries the revision message; thread it onto the head + revision rows and render a 'Commit message' column (ellipsis + tooltip), mirroring the workflow variants table's Commit notes.
Mirror the workflow registry: drop the auto-created v0 initial revision from the version history (Number(version) > 0), and flag the parent (head) row as the latest with a 'Last modified' tag + dot.
Match the workflow registry, where revision rows carry per-revision actions. Revision (child) rows can now be archived via the new archiveQueryRevision (/queries/revisions/{id}/archive) — any version including the head; the parent row still archives the whole query artifact. The archive confirm modal adapts its copy (version vs query).
Archiving a revision soft-deletes it, but it had no visible home — the Archived tab is artifact-level (whole queries). Queries use soft-delete + restore (unlike the workflow registry's hard delete), so surface archived revisions inline in the version history instead of letting them vanish.
- Entity: queryRevisionsForQueries gains includeArchived (the registry passes it); QueryRevisionSummary carries deletedAt; add unarchiveQueryRevision (/queries/revisions/{id}/unarchive).
- Table: head = latest non-archived revision; archived revisions render as children tagged 'Archived' (greyed). Their action menu swaps Archive → Restore; handleRestore branches revision vs query.
- The refresh signal already re-runs the batched fetch, so archive/restore reflect immediately.
Archived revisions previously rendered inline in the active list, which was misleading (no other entity shows soft-deleted revisions among active ones). They now surface as flat, restorable rows in the Archived tab alongside archived queries; the active tab batch-fetches active revisions only.
Exercises the query data atoms and the registry's read/archive logic against a REAL running backend (no mocks): molecule head-revision fetch + isDirty round-trip, querySimpleQueries listing, batched revision history after a commit, single-revision archive/restore via the includeArchived split (the Archived-tab logic), and whole-query archive/restore active-vs-archived split. Reuses the existing ephemeral-account harness; the suite is skipIf(!hasBackend) so it skips (never passes) when no backend is configured.
The workflow switcher's 'Evaluators' group reads nonHumanEvaluatorsAtom,
which resolves is_feedback from each evaluator's latest revision — fanning
out one batched POST /workflows/revisions/query over every evaluator in the
project. That ran on sidebar mount (e.g. opening the playground) just to
render a collapsed card.
Defer the subscription until the switcher is first opened: a one-way
switcherActivated latch (set from both Dropdowns' onOpenChange) swaps the
read between nonHumanEvaluatorsAtom and a stable empty atom, so the fan-out
never mounts until needed. Reopening is served from cache. The menu={{items}}
rendering is untouched, so the sticky group-title styling is unaffected.
…ent latch The aggregate evaluator atoms (key map, meta map, non-human list, feedback schemas, full-page list) each resolve EVERY evaluator's latest revision — one batched POST /workflows/revisions/query over the whole project. Several consumers read them eagerly on mount (the playground header's evaluator picker + meta-map read, the sidebar switcher), so a plain playground load fired the whole fan-out before the user touched anything. Add a shared, one-way activation gate in evaluatorUtils: those atoms stay dormant (return stable empty values, mount no revision query) until a consumer that genuinely needs enrichment activates it. - Adapter hooks (useEvaluatorEnrichedData + the enriched evaluator adapters) activate on mount by default, so every existing evaluator picker is unchanged. A new `lazy` option opts out. - Playground: the header's 'Add evaluators' picker activates on pointer-enter/ focus (lazy); the variant-config browse adapter is lazy on app playgrounds (where it's unused) and eager on evaluator entities. A cold app-playground load no longer fires the batch. - Sidebar switcher activates on open (converged onto the shared gate). - Filters + CreateQueueDrawer activate eagerly (they need the data on mount), so observability + annotation behaviour is preserved.
…te drawer mounts Follow-up to the lazy enrichment gate. Two always-mounted consumers still fanned out the per-evaluator latest-revision batch on a plain playground load, because they read evaluator-list atoms that flow through the (ungated) evaluatorRevisionFlagsMapAtom: - The evaluator EntityPicker subscribes to the adapter's list atom on mount (even while closed) via useLevelData. The enriched evaluator adapter now holds that list empty while `lazy` and the enrichment gate is closed, so a closed picker subscribes to nothing. - AnnotateDrawer is mounted (closed) in shared layouts incl. the playground and read humanEvaluatorsListDataAtom unconditionally. It now reads the list only when `open`. Cold playground load no longer fires POST /workflows/revisions/query; the data resolves when the picker is opened / the drawer opens. Evaluation-page consumers are untouched.
…unds The evaluator template catalog (GET /evaluators/catalog/templates) was fetched on every playground load by two always-mounted readers of evaluatorTemplatesDataAtom: - PlaygroundVariantConfig read it unconditionally, though it only uses the catalog once an evaluatorKey resolves (built-in evaluator URI). Now reads the catalog only for evaluator workflows — apps skip it (mirrors the workflow molecule, which already gates its catalog read on evaluatorKey). - The enriched evaluator adapter read the templates map/data on mount even when lazy. Now holds them empty until the enrichment gate opens (same lazy condition as the list/maps), so the playground 'Add evaluators' picker fetches the catalog on open, not on mount. It's a single static, 5-min-cached request (not the per-evaluator fan-out), but this keeps a cold app-playground load free of it. Evaluator playgrounds and other pickers are unchanged.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Important Review skippedDraft detected. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Summary
tba...
Testing
QA follow-up
query registry page & live evals
Checklist
Contributor Resources