Skip to content

feat(studio): Virtual Models view/delete page with search, filtering, and autoprovisioned exclusion#689

Merged
marcusds merged 5 commits into
mainfrom
astd-300-build-virtualmodels-crud-ui-in-nemo-studio/mschwab
Jul 14, 2026
Merged

feat(studio): Virtual Models view/delete page with search, filtering, and autoprovisioned exclusion#689
marcusds merged 5 commits into
mainfrom
astd-300-build-virtualmodels-crud-ui-in-nemo-studio/mschwab

Conversation

@marcusds

@marcusds marcusds commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds a Virtual Models page to NeMo Studio (ASTD-300) — view and delete inference-routing VirtualModels, with a read-only middleware-pipeline details panel. Nav lives under the Models group.

Because nearly all VirtualModels are controller-managed passthroughs (autoprovisioned), the IGW list endpoint gains a way to exclude them, and the UI hides them by default. Search + column filtering round out the table to match the other Studio data views.

What's included

Studio UI (web/packages/studio)

  • VirtualModelsListRoute + VirtualModelsDataView + VirtualModelDetailsSidePanel
  • List columns: name, default model, middleware call count, created; row actions View / Delete
  • Read-only details panel: core fields + all three middleware pipelines (plugin, config_type, config)
  • Name search ($like) + column filters (default model text, created-at date range), search/filter-aware empty state
  • Route + sidebar nav wiring, no feature flag

Inference Gateway (services/core/inference-gateway)

  • exclude_autoprovisioned query param on list_virtual_models (default false) — server ANDs a real-boolean data.autoprovisioned == false condition
  • VirtualModelFilter for name / default_model_entity / created_at / updated_at filtering

Regenerated: OpenAPI spec, Python SDK (stainless), CLI (--exclude-autoprovisioned switch), web SDK (CI-rebuilt).

Design notes

  • Why exclude_autoprovisioned and not a generic filter[autoprovisioned]? A string-based deep-object filter delivers the value as "false", which never matches the SQLite entity store's JSON boolean. Inverting to a dedicated boolean param (default false) both fixes the match and lets the generated CLI expose a working positive --exclude-autoprovisioned switch. (Both issues were caught in a Codex review and fixed in afc16b7.)

Verification

  • pytest services/core/inference-gateway/tests/unit/test_virtual_models_router.py — 34 pass (incl. real-store exclusion + name $like)
  • pnpm --filter nemo-studio-ui test (VM suites) — 7 pass; typecheck + typecheck:go + eslint clean
  • ruff + ty clean on the IGW route
  • Manual: list + details rendered live against a local platform; --exclude-autoprovisioned CLI switch verified

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features
    • Added a Virtual Models page in Studio with workspace navigation, server-side search/filtering (including time ranges), sorting, pagination, and virtual model deletion.
    • Added a Virtual Model details side panel with middleware/pipeline metadata.
  • Documentation
    • Updated CLI and API docs to support excluding controller-managed (autoprovisioned) models via --exclude-autoprovisioned / exclude_autoprovisioned, plus expanded filter options (including default_model_entity, name, project, workspace, created_at, updated_at).
  • Tests
    • Added unit and UI coverage for exclusion behavior, name matching, empty states, and details-side-panel rendering.

marcusds added 3 commits July 14, 2026 13:52
Add a Studio page to view and delete VirtualModels: list with a
read-only details side panel (core fields + middleware pipelines) and
delete, wired to the IGW virtual-models API and generated SDK. Route +
sidebar nav under the Models group.

Controller-managed passthrough VirtualModels are noise in the UI, so the
IGW list endpoint gains an include_autoprovisioned flag (default true to
preserve CLI/SDK behavior) plus a VirtualModelFilter for name/entity/date
filtering. The Studio list passes include_autoprovisioned=false to hide
them. Regenerated OpenAPI, Python SDK, and CLI accordingly.

Signed-off-by: mschwab <mschwab@nvidia.com>
Add a name search bar (filter[name][$like]) plus column filters for
default_model_entity (text) and created_at (date range) to the Virtual
Models list, mirroring the other Studio data tables. The empty state
becomes search/filter-aware with a Clear Filters action.

Signed-off-by: mschwab <mschwab@nvidia.com>
…K and CLI

Codex review surfaced two dead filtering paths:

- filter[autoprovisioned]=false was advertised on the VirtualModel list
  filter but returned nothing: the deep-object value arrives as the string
  "false" while the SQLite entity store holds JSON booleans, so the exact
  match never hit. Drop the autoprovisioned field from VirtualModelFilter;
  string/date filters are unaffected.
- The generated CLI rendered the boolean list flag as a positive-only
  switch, so with a default of true it could never exclude autoprovisioned
  models (--include-autoprovisioned false was rejected as an extra arg).

Invert the query parameter to exclude_autoprovisioned (default false), which
the server ANDs as a real boolean data.autoprovisioned == false condition.
The CLI now exposes a working --exclude-autoprovisioned switch, and Studio
passes exclude_autoprovisioned=true. Regenerated OpenAPI, Python SDK, and
CLI.

Signed-off-by: mschwab <mschwab@nvidia.com>
@marcusds
marcusds requested review from a team as code owners July 14, 2026 21:51
@github-actions github-actions Bot added the feat label Jul 14, 2026
@github-actions

Copy link
Copy Markdown
Contributor

@github-actions

github-actions Bot commented Jul 14, 2026

Copy link
Copy Markdown
Contributor
Suite Lines Covered Line Rate Branch Rate
Unit Tests 24398/31577 77.3% 62.0%
Integration Tests 14024/30226 46.4% 19.3%

@coderabbitai

coderabbitai Bot commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: e6bce901-43dc-4335-9a2b-4bbb94ba3842

📥 Commits

Reviewing files that changed from the base of the PR and between d23b44f and 14c7c97.

📒 Files selected for processing (3)
  • web/packages/studio/src/components/dataViews/VirtualModelsDataView/index.tsx
  • web/packages/studio/src/routes/VirtualModelsListRoute/VirtualModelDetailsSidePanel/index.tsx
  • web/packages/studio/src/routes/VirtualModelsListRoute/index.tsx
🚧 Files skipped from review as they are similar to previous changes (3)
  • web/packages/studio/src/routes/VirtualModelsListRoute/index.tsx
  • web/packages/studio/src/components/dataViews/VirtualModelsDataView/index.tsx
  • web/packages/studio/src/routes/VirtualModelsListRoute/VirtualModelDetailsSidePanel/index.tsx

📝 Walkthrough

Walkthrough

Changes

Virtual Models API and CLI

Layer / File(s) Summary
API filtering and exclusion
services/core/inference-gateway/..., openapi/..., services/core/inference-gateway/tests/...
The list endpoint adds structured filters, autoprovisioned-model exclusion, parsed-filter responses, OpenAPI schemas, and coverage for filtering behavior.
CLI controls and documentation
packages/nemo_platform_ext/..., docs/cli/reference.mdx
The CLI adds exclusion and field-specific filter options, while documentation describes the updated pagination, sorting, and filtering options.

Studio Virtual Models

Layer / File(s) Summary
Studio route and navigation wiring
web/packages/studio/src/constants/routes.ts, web/packages/studio/src/routes/...
Studio adds the workspace route, lazy route registration, breadcrumbs, page layout, sidebar navigation, and route-gating coverage.
Studio listing and details UI
web/packages/studio/src/components/dataViews/VirtualModelsDataView/*, web/packages/studio/src/routes/VirtualModelsListRoute/VirtualModelDetailsSidePanel/*
The UI lists filtered Virtual Models while excluding autoprovisioned entries, supports search, empty/error states, details, and deletion, with integration tests for these flows.

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant VirtualModelsDataView
  participant list_virtual_models
  participant entity_client
  User->>VirtualModelsDataView: Search or open Virtual Models
  VirtualModelsDataView->>list_virtual_models: Filtered list request
  list_virtual_models->>entity_client: Query filtered, non-autoprovisioned models
  entity_client-->>list_virtual_models: Virtual Model page
  list_virtual_models-->>VirtualModelsDataView: Page response
  VirtualModelsDataView-->>User: Table and row actions
Loading
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the new Virtual Models page with search, filtering, and autoprovisioned exclusion.
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.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch astd-300-build-virtualmodels-crud-ui-in-nemo-studio/mschwab

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (2)
web/packages/studio/src/components/dataViews/VirtualModelsDataView/index.test.tsx (1)

58-130: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

No coverage for default-model or creation-date filters.

PR objectives mention filtering by default model and creation date, but only name-filter and autoprovisioned-exclusion are tested here. Consider adding cases for those filters if VirtualModelsDataView implements them.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@web/packages/studio/src/components/dataViews/VirtualModelsDataView/index.test.tsx`
around lines 58 - 130, Add tests in the VirtualModelsDataView suite for the
implemented default-model and creation-date filters, following the existing
name-filter request pattern: render with each corresponding query parameter,
capture the VMS_URL request, and assert the API receives the expected filter
parameters and values.
web/packages/studio/src/routes/VirtualModelsListRoute/index.tsx (1)

10-10: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Use import type for type-only symbols.

  • web/packages/studio/src/routes/VirtualModelsListRoute/index.tsx#L10-L10: change FC to a type-only import.
  • web/packages/studio/src/components/dataViews/VirtualModelsDataView/index.tsx#L20-L24: type-import the generated schema symbols.
  • web/packages/studio/src/components/dataViews/VirtualModelsDataView/index.tsx#L32-L38: split ComponentProps and FC into import type, then use ComponentProps on Line 37.
  • web/packages/studio/src/routes/VirtualModelsListRoute/VirtualModelDetailsSidePanel/index.tsx#L6-L8: type-import the schema symbols and FC.

As per coding guidelines, “Use import type for type-only imports in TypeScript.”

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@web/packages/studio/src/routes/VirtualModelsListRoute/index.tsx` at line 10,
Convert type-only imports to import type in
web/packages/studio/src/routes/VirtualModelsListRoute/index.tsx:10-10,
web/packages/studio/src/components/dataViews/VirtualModelsDataView/index.tsx:20-24
and 32-38, and
web/packages/studio/src/routes/VirtualModelsListRoute/VirtualModelDetailsSidePanel/index.tsx:6-8.
Type-import the generated schema symbols, FC, and ComponentProps; split
ComponentProps and FC from any runtime imports and keep ComponentProps used for
the relevant component props.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/cli/reference.mdx`:
- Around line 3473-3475: Regenerate the CLI reference so the Filter Options text
in the relevant documentation entry uses the correct `--filter.FIELD` syntax
instead of `--filter. FIELD`. Preserve the rest of the description and
precedence guidance unchanged.

---

Nitpick comments:
In
`@web/packages/studio/src/components/dataViews/VirtualModelsDataView/index.test.tsx`:
- Around line 58-130: Add tests in the VirtualModelsDataView suite for the
implemented default-model and creation-date filters, following the existing
name-filter request pattern: render with each corresponding query parameter,
capture the VMS_URL request, and assert the API receives the expected filter
parameters and values.

In `@web/packages/studio/src/routes/VirtualModelsListRoute/index.tsx`:
- Line 10: Convert type-only imports to import type in
web/packages/studio/src/routes/VirtualModelsListRoute/index.tsx:10-10,
web/packages/studio/src/components/dataViews/VirtualModelsDataView/index.tsx:20-24
and 32-38, and
web/packages/studio/src/routes/VirtualModelsListRoute/VirtualModelDetailsSidePanel/index.tsx:6-8.
Type-import the generated schema symbols, FC, and ComponentProps; split
ComponentProps and FC from any runtime imports and keep ComponentProps used for
the relevant component props.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: e036d87e-652a-4d4f-b9e8-658d444c1f68

📥 Commits

Reviewing files that changed from the base of the PR and between 3576fe7 and afc16b7.

⛔ Files ignored due to path filters (11)
  • sdk/python/nemo-platform/.nmpcontext/openapi.yaml is excluded by !sdk/**
  • sdk/python/nemo-platform/.nmpcontext/stainless.yaml is excluded by !sdk/**
  • sdk/python/nemo-platform/scripts/lint is excluded by !sdk/**
  • sdk/python/nemo-platform/src/nemo_platform/cli/commands/api/inference/virtual_models.py is excluded by !sdk/**
  • sdk/python/nemo-platform/src/nemo_platform/resources/inference/api.md is excluded by !sdk/**
  • sdk/python/nemo-platform/src/nemo_platform/resources/inference/virtual_models.py is excluded by !sdk/**
  • sdk/python/nemo-platform/src/nemo_platform/types/inference/__init__.py is excluded by !sdk/**
  • sdk/python/nemo-platform/src/nemo_platform/types/inference/virtual_model_filter_param.py is excluded by !sdk/**
  • sdk/python/nemo-platform/src/nemo_platform/types/inference/virtual_model_list_params.py is excluded by !sdk/**
  • sdk/python/nemo-platform/tests/api_resources/inference/test_virtual_models.py is excluded by !sdk/**
  • sdk/stainless.yaml is excluded by !sdk/**
📒 Files selected for processing (18)
  • docs/cli/reference.mdx
  • openapi/ga/individual/platform.openapi.yaml
  • openapi/ga/openapi.yaml
  • openapi/openapi.yaml
  • packages/nemo_platform_ext/src/nemo_platform_ext/cli/commands/api/inference/virtual_models.py
  • services/core/inference-gateway/src/nmp/core/inference_gateway/api/v2/virtual_models.py
  • services/core/inference-gateway/tests/unit/test_virtual_models_router.py
  • web/packages/studio/src/components/dataViews/VirtualModelsDataView/index.test.tsx
  • web/packages/studio/src/components/dataViews/VirtualModelsDataView/index.tsx
  • web/packages/studio/src/constants/routes.ts
  • web/packages/studio/src/routes/VirtualModelsListRoute/VirtualModelDetailsSidePanel/index.test.tsx
  • web/packages/studio/src/routes/VirtualModelsListRoute/VirtualModelDetailsSidePanel/index.tsx
  • web/packages/studio/src/routes/VirtualModelsListRoute/index.tsx
  • web/packages/studio/src/routes/WorkspaceLayout/WorkspaceSideNav.tsx
  • web/packages/studio/src/routes/groups/index.ts
  • web/packages/studio/src/routes/groups/virtualModelsRoutes.tsx
  • web/packages/studio/src/routes/index.tsx
  • web/packages/studio/src/routes/utils.ts

Comment thread docs/cli/reference.mdx
marcusds added 2 commits July 14, 2026 15:15
…invariant

The Virtual Models route ships without a feature flag, so the
all-flags-disabled safety-net test must allow it explicitly. Every other
workspace route stays gated.

Signed-off-by: mschwab <mschwab@nvidia.com>
Addresses a CodeRabbit nitpick — FC, ComponentProps, and generated schema
symbols are type-only; import them with import type per the repo TS guideline.

Signed-off-by: mschwab <mschwab@nvidia.com>
@marcusds
marcusds requested a review from mckornfield July 14, 2026 22:25
@marcusds
marcusds added this pull request to the merge queue Jul 14, 2026
Merged via the queue into main with commit 65aec46 Jul 14, 2026
59 checks passed
@marcusds
marcusds deleted the astd-300-build-virtualmodels-crud-ui-in-nemo-studio/mschwab branch July 14, 2026 23:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants