Skip to content

FEAT GUI: Add prompt table and seed detail view #2745

Open

Description

@romanlutz

Is your feature request related to a problem? Please describe.

Dataset cards now exist, but their selection page only shows a summary. Users need a drill-down where they can inspect actual examples and select a seed without copying it through notebooks. Long prompts and linked multimodal examples must remain understandable without loading the whole dataset.

Work item 4 of 17 in #2744. Ready for contribution: the browsing API is completed in #2989/#2748, and catalog/navigation is completed in #3071/#2747. This is the single active main-explorer item. Keep this slice read-only; media playback, chat import, and scenario multi-select remain later milestones.

Describe the solution you'd like

Extend the shipped selection page

Build on the catalog/navigation shipped in #3071 rather than creating another Datasets route:

  • Extend DatasetSelection at /datasets/detail?selection_key=<encoded> with the paginated logical-example table and expandable details. Keep the selected dataset summary and reuse datasetDetailPath and selectionKeyFromSearchParams from frontend/src/utils/routeParams.ts. Missing or repeated selection keys must not choose an arbitrary dataset or trigger an unscoped seed request.
  • Preserve the existing DatasetCard navigation state { catalogPath } and catalogPathFromNavigationState validation. Back to datasets must retain the originating catalog search, facets, and sort, including after refreshing the selection page. Direct links without valid return state fall back to /datasets; do not accept arbitrary return URLs.
  • Keep catalog state and example-browsing state distinct. Catalog q searches dataset names, and its unlabeled and sort controls apply to catalog metadata. The seed API uses search for prompt/objective content and has neither a sort parameter nor an unlabeled-only filter. Do not forward the whole catalog query or implement those filters by searching/sorting only the current seed page.
  • Reuse useLoadedDatasets for loaded-only catalog metadata and its refresh behavior. Add typed list/detail methods to datasetsApi in frontend/src/services/api.ts and the corresponding shared wire types in frontend/src/types/index.ts; currently the frontend client exposes only listDatasets. The backend browse/detail endpoints already exist. Use the shared API client and error normalization rather than another client or backend API.
  • Load only the requested example page, then fetch full member data on expansion/inspection. Use the existing useRuntime().generation and request-cancellation patterns: do not show a late response from a previous dataset, filter set, or runtime. On runtime changes, invalidate example pages, cursors, selected/expanded examples, and detail caches as well as the catalog.

Use the existing browsing contract

Consume the contract in #2748 and the merged browsing guide:

  • List with GET /api/datasets/seeds?selection_key=<key>; expand with GET /api/datasets/seeds/{example_id}?selection_key=<key>. Keep the API-provided selection_key opaque in route and selection state, including unnamed datasets and names requiring URL encoding. Carry both selection_key and example_id; a shared group ID must not pull members from another dataset.
  • Show the server's optional name, preview/preview_truncated, modalities, seed_types, piece_count, objective_count, harm_categories, and has_unlabeled_harm. Dataset cards instead use has_unlabeled_harm_categories; do not mix the two shapes. The matching-example count is list total, not the page length, catalog total, or a sum of piece counts.
  • Detail members are SeedRecord inspection data, not executable seeds. Show full stored value, member IDs/hashes, nullable role/sequence, parameters, typed objective conditions, and available provenance/metadata. Simulated-conversation configuration remains raw JSON in value; do not expect top-level num_turns or reconstructed template properties. Use seed_type for type labels and show declared parameters when present. There are no is_template/is_configuration flags; preserve unknown template state instead of inventing certainty from parameters.
  • Retain all returned members in server order. Missing local/template/media files do not remove stored records. Do not open files, render templates, reconstruct seeds, fetch providers, or execute configuration simply by opening a row. Media values can remain non-playing inspection placeholders until FEAT GUI: Share image, audio, and video previews with datasets #2749 adds shared previews.

Include server-side text search and the supported facets, clear filters, a return-to-catalog action, and copy-full-text/copy-ID utilities. Send search (up to 1,000 characters) and repeated singular modality, seed_type, and harm_category query parameters, not bracket-suffixed arrays. Values within a facet are OR-matched and different facets are AND-matched; different members can satisfy different facets while the whole selected-dataset example remains intact. Use available catalog metadata and the backend's seed types for filter choices, not a scan of every seed page.

Search applies to stored text prompts/objectives only. Explain that simulated-conversation JSON is excluded and can be located by its seed-type facet. Do not implement broader page-local text search or promise Unicode-insensitive search beyond the backend's ASCII case behavior on SQLite.

Use limit (default 20, range 1-100), pagination.has_more, and opaque next_cursor. Preserve the server's newest-first ordering by earliest member date and then canonical textual example ID. Reset paging when dataset, search, facets, or page size change. Keep visited cursors with navigation state for Previous/Back: this endpoint's prev_cursor echoes the current request cursor, not the preceding page. Do not invent a previous cursor or promise random page jumps. A 400 invalid/mismatched cursor should offer an explicit refresh, never silently change the result set. Preserve example filters, page, and inspected example through navigation and refresh where the runtime is unchanged.

Copy full content from the inspected member's detail value, never from a shortened or safe-label preview. Preserve exact whitespace and report clipboard failures clearly. Show missing metadata as missing, without inventing a license or classifying unlabeled content as safe. Keep no matching examples distinct from a missing/invalid dataset selection, a deleted example (404), and an API failure. A valid key with no stored rows has a normal empty response. Refresh catalog metadata when previously loaded data becomes empty or unavailable, rather than retaining a stale summary.

Use single-example selection for the initial chat workflow, represented by the dataset key and logical example ID. Leave a small extension point for later multi-select, but do not concatenate independent examples or add import/send/launch actions here. Treat dataset content as untrusted text: do not execute HTML, templates, embedded instructions, or simulated-conversation configuration while inspecting it.

Acceptance criteria

  • The existing card-to-selection route now opens the table. The page's Back link, browser Back/Forward, refresh, encoded/unnamed keys, missing/repeated keys, and safe return-path fallback preserve their intended behavior.
  • Server-side search/facets, filter-bound cursor pagination, Previous/Back, page-size/filter resets, and matching-example totals use the shipped API shapes. Catalog name search/sort is not reused as seed search/sort.
  • Only the requested page and lazily inspected details are fetched. The catalog still does not prefetch seed pages for counts or filters. Late responses and runtime changes cannot display stale rows or detail/selection state.
  • Dataset-scoped logical examples remain intact, including missing-file records. Raw configuration, typed conditions, nullable roles/sequences, IDs/hashes, provenance, and full text survive expansion without execution or reconstruction.
  • Copy actions preserve exact content and report failures. Unsupported shapes and unknown template state stay inspectable. Tests cover configuration-type filtering and the documented text-search exclusion.
  • Loading, no matches, empty data, missing selection/example, validation errors, and API failures have usable states. Result status is announced for both positive and zero results; retry and expansion have sensible keyboard focus behavior.
  • Keyboard single selection, focus restoration, long prompt/category wrapping, and mobile touch targets preserve the accessibility fixes from FEAT: Add dataset catalog navigation and cards #3071. Add focused component/routing/API-client tests and real-stack browser coverage using local fixtures without credentials.
  • Replace the temporary "Individual examples are not yet listed" copy in DatasetSelection and the matching DatasetCard screen-reader description. Update placeholder/no-table assertions, route-helper documentation that currently says keys are only used for catalog lookup, and frontend/README.md. Keep the no-seed-prefetch guarantee for the catalog, not for the newly implemented detail page.

Describe alternatives you've considered, if relevant

Do not edit/delete seeds, fetch remote metadata, add batch sending, or render media independently here. #2749 adds shared media previews, #2751 adds chat import actions, and #2759 adds scenario multi-select. Do not rebuild the existing catalog, change the memory schema, add a new dataset store, or replace the shipped browsing API.

Additional context

Starting points: frontend/src/components/Datasets/{DatasetSelection,DatasetCard,DatasetCatalog}.tsx, frontend/src/components/Datasets/datasetQuery.ts, frontend/src/hooks/useLoadedDatasets.ts, frontend/src/utils/routeParams.ts, frontend/src/services/api.ts, and frontend/src/types/index.ts. Existing contract sources are pyrit/backend/routes/datasets.py, pyrit/backend/models/datasets.py, and pyrit/backend/services/dataset_service.py.

Reuse the existing History table/pagination presentation, but retain this endpoint's cursor semantics. Build on the existing dataset routing/unit tests and frontend/e2e/datasets.spec.ts; do not weaken the Back-link, live-region, long-label, or touch-target regressions from #3071. Follow doc/code/framework.md and the applicable frontend style/test instructions. Development and browser tests must use local seed fixtures and the real backend where appropriate, without privileged Hugging Face access, provider downloads, or paid target calls.

Relationship to scenario dataset generation

The scenario dataset plan complements this browser. Generated text objectives from merged #2904/#3116 become ordinary browsable rows once stored in memory. The provenance/metadata requirement above includes the existing SeedRecord.origin and, when present, metadata.generation_conversation_id; preserve unknown provenance rather than inferring it from provider availability. Reading these records must not call the generation target or prepare missing data.

The still-open #3143 adds shared scenario source controls and aggregate catalog origins, not this logical-example table. Reuse compatible shared types when available, but this item can proceed with the shipped browsing API and has no new dependency on #3143. Do not add generator configuration, automatic generation, or regeneration controls here.

Activity

  1. added
    not ready yetThis issue needs more definition or is blocked by a pending change.
    GUIUmbrella label for all feedback submitted via the Co-PyRIT GUI
    on Sep 22, 2026
  2. added
    help wantedExtra attention is needed
    and removed
    not ready yetThis issue needs more definition or is blocked by a pending change.
    on Oct 12, 2026
  3. juliosuas commented on Oct 12, 2026

    @juliosuas
    Contributor

    Hey Roman Lutz (@romanlutz), I'd like to take this one since it builds right on top of #3071. Plan is to extend DatasetSelection with the paginated example table plus expandable rows for long/multimodal examples, reusing the selection_key helpers and keeping the catalogPath back-nav. I'll keep it read-only as described. Mind assigning it to me?

  4. romanlutz commented on Oct 12, 2026

    @romanlutz
    ContributorAuthor

    Of course! I'll assign it to you.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

GUIUmbrella label for all feedback submitted via the Co-PyRIT GUIfeature-requesthelp wantedExtra attention is needed

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions