refactor(studio): move shared UI components into @nemo/common - #1192
Conversation
|
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughThe PR centralizes shared Studio components and utilities in ChangesShared common package and plugin integration
Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches 💡 1⚔️ Resolve merge conflicts 💡
📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 13
🧹 Nitpick comments (5)
web/packages/common/src/components/AccessibleTitle/index.tsx (1)
4-4: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winUse type-only imports.
web/packages/common/src/components/AccessibleTitle/index.tsx#L4-L4: moveFCandPropsWithChildrentoimport type.web/packages/common/src/components/AccordionSection/index.tsx#L10-L10: moveFC,PropsWithChildren, andReactNodetoimport type.🤖 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/common/src/components/AccessibleTitle/index.tsx` at line 4, Convert FC and PropsWithChildren to type-only imports in AccessibleTitle, and convert FC, PropsWithChildren, and ReactNode to type-only imports in AccordionSection; leave runtime React imports unchanged.Source: Coding guidelines
web/packages/common/src/components/ExpandableMessage/index.tsx (1)
5-5: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winUse type-only imports for type-only symbols.
- Mark the listed type-only symbols as
type.- In
FileUpload/index.tsx, also markFC,MouseEvent,MouseEventHandler,ReactNode,DropEvent,DropzoneOptions, andFileRejectionas type-only.- Keep runtime imports such as
FileTag,ErrorCode,React, anduseDropzoneas value imports.🤖 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/common/src/components/ExpandableMessage/index.tsx` at line 5, Update imports at web/packages/common/src/components/ExpandableMessage/index.tsx:5-5, web/packages/common/src/components/FileTag/index.tsx:4-6, web/packages/common/src/components/FileUpload/index.tsx:4-4, web/packages/common/src/components/FileUpload/util.ts:4-4, web/packages/common/src/components/InputErrorText/index.tsx:5-5, and web/packages/common/src/components/QuickActionsMenu/QuickActionsMenuRoot/index.tsx:15-15 to mark all type-only symbols with the type modifier. In FileUpload/index.tsx, apply this to FC, MouseEvent, MouseEventHandler, ReactNode, DropEvent, DropzoneOptions, and FileRejection, while retaining FileTag, ErrorCode, React, and useDropzone as value imports.Source: Coding guidelines
web/packages/studio/src/components/CustomizationFileTag/index.tsx (1)
4-4: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winUse explicit type-only imports.
web/packages/studio/src/components/CustomizationFileTag/index.tsx#L4-L4: keepFileTagas a value import and importFileTagPropswithimport type.web/packages/studio/src/components/CustomizationFileUpload/index.tsx#L4-L4: change theRenderFileTagFnimport toimport type.As per coding guidelines, use
import typefor type-only imports.🤖 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/CustomizationFileTag/index.tsx` at line 4, Update the import in web/packages/studio/src/components/CustomizationFileTag/index.tsx:4 so FileTag remains a value import while FileTagProps uses import type; update the RenderFileTagFn import in web/packages/studio/src/components/CustomizationFileUpload/index.tsx:4 to use import type.Source: Coding guidelines
web/packages/studio/src/components/DatasetFileUpload/index.tsx (1)
4-5: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winMark type-only imports with
import type.
FileTagStatusandRenderFileTagFnare type exports. Split them intoimport typedeclarations.As per coding guidelines, use
import typefor type-only imports.🤖 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/DatasetFileUpload/index.tsx` around lines 4 - 5, Update the imports in the DatasetFileUpload module so the type-only symbols FileTagStatus and RenderFileTagFn use separate import type declarations, while retaining FileTag and FileUpload as regular runtime imports.Source: Coding guidelines
web/packages/studio/src/util/logVersion.ts (1)
7-11: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winDeclare the public return type.
Add the explicit return type to the exported function:
-export const logVersion = async () => { +export const logVersion = async (): Promise<void> => {As per coding guidelines, public APIs should declare explicit return types.
🤖 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/util/logVersion.ts` around lines 7 - 11, Update the exported logVersion function to declare its explicit Promise-based return type, matching its async implementation and existing behavior.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 `@plugins/example-plugin/web/AGENTS.md`:
- Around line 38-41: Add host.breadcrumbs to the injected host capability list
near the existing navigation entry, keeping it consistent with the capability
contract defined in SharedUiPage.tsx.
In `@plugins/example-plugin/web/src/SharedUiPage.tsx`:
- Line 13: Update the import of pluginPath in SharedUiPage.tsx to use the
project’s configured absolute alias instead of the relative "./paths" path,
while preserving the same imported symbol.
- Around line 26-34: Update the breadcrumb effect in SharedUiPage to return a
cleanup function that clears the page trail through setBreadcrumbs when the page
unmounts. Preserve the existing breadcrumb setup on mount and ensure cleanup
also runs when its dependencies change.
In `@web/packages/common/src/api/common/utils.ts`:
- Around line 4-8: Update the import of GenericSortField, PaginationData, and
ValidationError to use a type-only import, since these SDK symbols are
referenced only in type positions.
- Around line 99-105: Update the request-context formatting in the error
handling logic around error.config so user-visible messages never include raw
URLs with query parameters or fragments. Sanitize url by removing its query
string and fragment before appending it to parts, while preserving the existing
method and URL context when available.
- Around line 37-43: Update the item validation predicate in the API error
utility to require that item.loc is an array before accepting the object.
Preserve the existing msg and type checks so downstream filtering can safely
call filter on loc.
In `@web/packages/common/src/components/ExpandableMessage/index.tsx`:
- Around line 55-58: The fixed danger styling is currently overwritten by caller
className props. In
web/packages/common/src/components/ExpandableMessage/index.tsx#L55-L58, update
the Text className handling to merge attributes.Text.className while always
retaining text-feedback-danger; apply the same merge in
web/packages/common/src/components/InputErrorText/index.tsx#L18-L18 for
props.className.
In `@web/packages/studio/src/components/DataDesignerJobActionsMenu/index.tsx`:
- Around line 4-7: Replace the deep internal `@nemo/common/src/`... imports with
public `@nemo/common` barrel imports: in
web/packages/studio/src/components/DataDesignerJobActionsMenu/index.tsx (lines
4-7), import QuickActionsMenuRoot and QuickActionItem; in
web/packages/studio/src/components/DatasetFileUpload/index.tsx (lines 4-5),
import FileTag and FileUpload; in
web/packages/studio/src/routes/InferenceProvidersListRoute/index.tsx (line 13)
and web/packages/studio/src/routes/IntakeLayout/index.tsx (line 4), import
AccessibleTitle; and in web/packages/studio/src/routes/JobDetailRoute/index.tsx
(lines 4-5), import AccessibleTitle and CancelJobButton. Ensure none of these
migrated shared UI imports use `@nemo/common/src/` paths.
In `@web/packages/studio/src/components/promoted/ErrorPanel.test.tsx`:
- Around line 4-5: Update the import containing ErrorPanelProps to use a
type-only import while keeping the runtime ErrorPanel import unchanged.
In
`@web/packages/studio/src/components/PromptTuningForm/InContextLearningSection/index.tsx`:
- Line 5: Update the shared UI imports to use the public `@nemo/common` entry
point: in
web/packages/studio/src/components/PromptTuningForm/InContextLearningSection/index.tsx:5,
web/packages/studio/src/routes/agents/AgentSuggestionsRoute/index.tsx:4, and
web/packages/studio/src/routes/agents/AgentsListRoute/index.tsx:4, import
AccordionSection or AccessibleTitle from `@nemo/common` instead of deep-linking
into src. Export either component through web/packages/common/src/plugin.ts if
the barrel does not already expose it.
In
`@web/packages/studio/src/components/PromptTuningForm/InferenceParametersSection/index.tsx`:
- Line 4: Update Studio’s module resolver and TypeScript path mapping to resolve
shared UI through the curated `@nemo/common` entry point exported by plugin.ts,
then replace the seven deep imports in
web/packages/studio/src/components/PromptTuningForm/InferenceParametersSection/index.tsx
(anchor), PromptTemplateSection/index.tsx, ToolsSection/index.tsx,
QuickActionsMenu/QuickActionsMenuDefault/index.tsx,
routes/agents/CopilotChatRoute/historyPanel/HistoryPanelContents.tsx,
routes/agents/CopilotChatRoute/index.tsx, and
routes/evaluation/EvaluationLayout/index.tsx with imports from that entry point.
In `@web/packages/studio/src/plugins/PluginRenderer.tsx`:
- Around line 56-57: Update the cleanup useEffect in PluginRenderer to include
pluginName in its dependency array so setBreadcrumbs([]) runs when the routed
plugin changes, then add a test covering a retained PluginRenderer switching
pluginName and clearing the previous breadcrumbs.
In `@web/packages/studio/src/routes/optimizer/OptimizerRoute/index.tsx`:
- Around line 5-10: Replace all listed deep shared-UI imports with the bare
`@nemo/common` barrel, and add any missing symbols to plugin.ts exports:
web/packages/studio/src/routes/optimizer/OptimizerRoute/index.tsx (lines 5-10)
for AccessibleTitle, StudioDataView, and ErrorPanel;
web/packages/studio/src/routes/optimizer/OptimizerInsightRoute/index.tsx (lines
4-6) for AccessibleTitle, ErrorMessage, and ExpandableMessage;
web/packages/studio/src/routes/index.tsx (line 5) for ErrorPanel;
web/packages/studio/src/routes/guardrails/GuardrailDetailRoute/index.tsx (line
6) for AccessibleTitle;
web/packages/studio/src/routes/guardrails/GuardrailDetailRoute/GuardrailDetailActions.tsx
(lines 4-8) for DeleteConfirmationModal and QuickActionsMenuRoot;
web/packages/studio/src/components/promoted/DeleteConfirmationModal.test.tsx
(line 4) for DeleteConfirmationModal; and
web/packages/studio/src/components/promoted/CancelJobButton.test.tsx (line 4)
for CancelJobButton.
---
Nitpick comments:
In `@web/packages/common/src/components/AccessibleTitle/index.tsx`:
- Line 4: Convert FC and PropsWithChildren to type-only imports in
AccessibleTitle, and convert FC, PropsWithChildren, and ReactNode to type-only
imports in AccordionSection; leave runtime React imports unchanged.
In `@web/packages/common/src/components/ExpandableMessage/index.tsx`:
- Line 5: Update imports at
web/packages/common/src/components/ExpandableMessage/index.tsx:5-5,
web/packages/common/src/components/FileTag/index.tsx:4-6,
web/packages/common/src/components/FileUpload/index.tsx:4-4,
web/packages/common/src/components/FileUpload/util.ts:4-4,
web/packages/common/src/components/InputErrorText/index.tsx:5-5, and
web/packages/common/src/components/QuickActionsMenu/QuickActionsMenuRoot/index.tsx:15-15
to mark all type-only symbols with the type modifier. In FileUpload/index.tsx,
apply this to FC, MouseEvent, MouseEventHandler, ReactNode, DropEvent,
DropzoneOptions, and FileRejection, while retaining FileTag, ErrorCode, React,
and useDropzone as value imports.
In `@web/packages/studio/src/components/CustomizationFileTag/index.tsx`:
- Line 4: Update the import in
web/packages/studio/src/components/CustomizationFileTag/index.tsx:4 so FileTag
remains a value import while FileTagProps uses import type; update the
RenderFileTagFn import in
web/packages/studio/src/components/CustomizationFileUpload/index.tsx:4 to use
import type.
In `@web/packages/studio/src/components/DatasetFileUpload/index.tsx`:
- Around line 4-5: Update the imports in the DatasetFileUpload module so the
type-only symbols FileTagStatus and RenderFileTagFn use separate import type
declarations, while retaining FileTag and FileUpload as regular runtime imports.
In `@web/packages/studio/src/util/logVersion.ts`:
- Around line 7-11: Update the exported logVersion function to declare its
explicit Promise-based return type, matching its async implementation and
existing behavior.
🪄 Autofix
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: bb6b888f-fa73-4f91-99cc-42e77e521843
⛔ Files ignored due to path filters (2)
plugins/example-plugin/src/nemo_example_plugin/web/dist/index.jsis excluded by!**/dist/**web/pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (214)
plugins/example-plugin/web/AGENTS.mdplugins/example-plugin/web/src/SharedUiPage.tsxplugins/example-plugin/web/src/types.tsweb/packages/common/package.jsonweb/packages/common/src/api/common/utils.test.tsweb/packages/common/src/api/common/utils.tsweb/packages/common/src/components/AccessibleTitle/index.test.tsxweb/packages/common/src/components/AccessibleTitle/index.tsxweb/packages/common/src/components/AccordionSection/index.tsxweb/packages/common/src/components/CancelJobButton/index.tsxweb/packages/common/src/components/ConfirmationModal/index.tsxweb/packages/common/src/components/DeleteConfirmationModal/index.tsxweb/packages/common/src/components/ErrorPanel/index.tsxweb/packages/common/src/components/ExpandableMessage/index.test.tsxweb/packages/common/src/components/ExpandableMessage/index.tsxweb/packages/common/src/components/FileTag/index.tsxweb/packages/common/src/components/FileUpload/index.tsxweb/packages/common/src/components/FileUpload/util.tsweb/packages/common/src/components/InputErrorText/index.tsxweb/packages/common/src/components/QuickActionsMenu/QuickActionsMenuRoot/index.test.tsxweb/packages/common/src/components/QuickActionsMenu/QuickActionsMenuRoot/index.tsxweb/packages/common/src/plugin.tsweb/packages/common/src/utils/error.tsweb/packages/common/src/utils/forms/error.test.tsweb/packages/common/src/utils/forms/error.tsweb/packages/common/src/utils/logger.tsweb/packages/studio/src/App.tsxweb/packages/studio/src/api/datasets/useDatasetFileContent.tsweb/packages/studio/src/api/guardrail-checks/guardrailChecks.tsweb/packages/studio/src/components/AnonymizerJobActionsMenu/index.tsxweb/packages/studio/src/components/BulkDeleteModal/index.tsxweb/packages/studio/src/components/CreateFilesetStart/useDescribeWithAi.tsweb/packages/studio/src/components/CustomizationFileTag/index.tsxweb/packages/studio/src/components/CustomizationFileUpload/index.tsxweb/packages/studio/src/components/CustomizationFilesetCreateModal/index.tsxweb/packages/studio/src/components/DataDesignerJobActionsMenu/index.tsxweb/packages/studio/src/components/DatasetCreateModal/index.tsxweb/packages/studio/src/components/DatasetFileUpload/index.tsxweb/packages/studio/src/components/DatasetInputFile/index.tsxweb/packages/studio/src/components/DatasetsTable/index.test.tsxweb/packages/studio/src/components/DatasetsTable/index.tsxweb/packages/studio/src/components/ExperimentCreateModal/index.tsxweb/packages/studio/src/components/FilesTable/CreateFileSplitsModal/index.tsxweb/packages/studio/src/components/FilesTable/DirectoryQuickActions/index.tsxweb/packages/studio/src/components/FilesTable/FileQuickActions/index.tsxweb/packages/studio/src/components/FilesTable/RenameFileModal/index.tsxweb/packages/studio/src/components/FilesTable/TransformFileModal/index.tsxweb/packages/studio/src/components/FilesetActionMenu/index.tsxweb/packages/studio/src/components/FilesetCreateModal/index.tsxweb/packages/studio/src/components/FilesetFilePreviewPanel/components/FileActions/index.tsxweb/packages/studio/src/components/IntakeDetail/IntakeComponents/AnnotationsPanel.tsxweb/packages/studio/src/components/IntakeDetail/IntakeComponents/useSpanAnnotationActions.tsweb/packages/studio/src/components/IntakeDetail/SessionDetailView.tsxweb/packages/studio/src/components/IntakeDetail/TraceSpanAccordions.tsxweb/packages/studio/src/components/IntakeLists/IntakeSpansTable.tsxweb/packages/studio/src/components/IntakeLists/IntakeTracesTable.tsxweb/packages/studio/src/components/ModelActionsMenu/index.tsxweb/packages/studio/src/components/ModelChat/index.tsxweb/packages/studio/src/components/ModelComparePrompts/useModelComparePrompts.tsweb/packages/studio/src/components/NewCustomizationForm/index.tsxweb/packages/studio/src/components/NewDataDesignerJobForm/JobRequestGenerator.tsxweb/packages/studio/src/components/NewDataDesignerJobForm/usePreview.tsweb/packages/studio/src/components/NewDataDesignerJobForm/utils.test.tsweb/packages/studio/src/components/NewDataDesignerJobForm/utils.tsweb/packages/studio/src/components/PromptTuningForm/ImportFromDatasetModal/index.tsxweb/packages/studio/src/components/PromptTuningForm/InContextLearningSection/index.tsxweb/packages/studio/src/components/PromptTuningForm/InferenceParametersSection/index.tsxweb/packages/studio/src/components/PromptTuningForm/PromptTemplateSection/index.tsxweb/packages/studio/src/components/PromptTuningForm/ToolsSection/index.tsxweb/packages/studio/src/components/QuickActionsMenu/QuickActionsMenuDefault/index.tsxweb/packages/studio/src/components/WorkspaceCreateModal/index.tsxweb/packages/studio/src/components/WorkspaceDropdown/index.tsxweb/packages/studio/src/components/common/SearchBar/index.tsxweb/packages/studio/src/components/dataViews/AgentEvaluationsDataView/index.tsxweb/packages/studio/src/components/dataViews/AgentsDataView/index.tsxweb/packages/studio/src/components/dataViews/CustomModelsDataView/index.tsxweb/packages/studio/src/components/dataViews/DeploymentsDataView/index.tsxweb/packages/studio/src/components/dataViews/ExperimentDataView/index.tsxweb/packages/studio/src/components/dataViews/GuardrailsDataView/index.tsxweb/packages/studio/src/components/dataViews/InferenceProvidersDataView/index.tsxweb/packages/studio/src/components/dataViews/JobsDataView/index.tsxweb/packages/studio/src/components/dataViews/SafeSynthesizerJobsDataView/index.tsxweb/packages/studio/src/components/dataViews/SecretsDataView/index.tsxweb/packages/studio/src/components/dataViews/VirtualModelsDataView/index.tsxweb/packages/studio/src/components/evaluation/Configurations/form/InputFile/useInputFile.tsweb/packages/studio/src/components/evaluation/Jobs/ActionMenu.tsxweb/packages/studio/src/components/evaluation/Jobs/DetailsPanel.tsxweb/packages/studio/src/components/evaluation/Jobs/EvaluationJobBulkDeleteModal.tsxweb/packages/studio/src/components/evaluation/Jobs/form/ScoreDefinitions.tsxweb/packages/studio/src/components/filesets/AddToFolderModal/index.tsxweb/packages/studio/src/components/filesets/FilesetFileExplorer/DatasetFileDropzone/index.tsxweb/packages/studio/src/components/filesets/FilesetFileExplorer/NewDirectoryModal/index.tsxweb/packages/studio/src/components/filesets/hooks/useBulkDownload.tsweb/packages/studio/src/components/filesets/hooks/useBulkDuplicate.tsweb/packages/studio/src/components/promoted/CancelJobButton.test.tsxweb/packages/studio/src/components/promoted/DeleteConfirmationModal.test.tsxweb/packages/studio/src/components/promoted/ErrorPanel.test.tsxweb/packages/studio/src/components/sidePanels/MetricRunSidePanel/index.tsxweb/packages/studio/src/components/sidePanels/ModelPanels/ModelPanel/components.tsxweb/packages/studio/src/components/sidePanels/ModelPanels/ModelPanel/index.tsxweb/packages/studio/src/main.tsxweb/packages/studio/src/plugins/PluginErrorBoundary.tsxweb/packages/studio/src/plugins/PluginRenderer.test.tsxweb/packages/studio/src/plugins/PluginRenderer.tsxweb/packages/studio/src/plugins/types.tsweb/packages/studio/src/plugins/utils.tsweb/packages/studio/src/routes/AnonymizerBuilderRoute/components/AnonymizerBuilderForm.tsxweb/packages/studio/src/routes/AnonymizerBuilderRoute/index.tsxweb/packages/studio/src/routes/AnonymizerJobDetailRoute/index.tsxweb/packages/studio/src/routes/AnonymizerListRoute/index.tsxweb/packages/studio/src/routes/AuthSuccessRoute/index.tsxweb/packages/studio/src/routes/CustomizationJobDetailsRoute/DetailActions.tsxweb/packages/studio/src/routes/CustomizationJobDetailsRoute/index.tsxweb/packages/studio/src/routes/CustomizationJobListRoute/index.tsxweb/packages/studio/src/routes/DashboardLandingRoute/index.tsxweb/packages/studio/src/routes/DataDesignerJobBuildRoute/index.tsxweb/packages/studio/src/routes/DataDesignerJobDetailsRoute/index.tsxweb/packages/studio/src/routes/DataDesignerJobListRoute/index.tsxweb/packages/studio/src/routes/DeploymentsListRoute/CreateDeploymentSidePanel/useCreateDeploymentBySource.tsweb/packages/studio/src/routes/DeploymentsListRoute/index.tsxweb/packages/studio/src/routes/DeploymentsListRoute/useDeleteDeploymentAndConfig.tsweb/packages/studio/src/routes/EvaluationDetailRoute/index.tsxweb/packages/studio/src/routes/EvaluationSessionDetailRoute/SessionCompareColumn.tsxweb/packages/studio/src/routes/EvaluationSessionDetailRoute/TestCaseCompare.tsxweb/packages/studio/src/routes/ExperimentDetailRoute/index.tsxweb/packages/studio/src/routes/ExperimentRoute/index.tsxweb/packages/studio/src/routes/FilesetDetailRoute/index.tsxweb/packages/studio/src/routes/FilesetListRoute/ActionMenu/index.test.tsxweb/packages/studio/src/routes/FilesetListRoute/ActionMenu/index.tsxweb/packages/studio/src/routes/FilesetListRoute/index.tsxweb/packages/studio/src/routes/FilesetNewRoute/helpers.tsweb/packages/studio/src/routes/FilesetNewRoute/index.tsxweb/packages/studio/src/routes/FilesetNewRoute/useCreateFileset.tsweb/packages/studio/src/routes/InferenceProvidersListRoute/CreateInferenceProviderSidePanel/index.tsxweb/packages/studio/src/routes/InferenceProvidersListRoute/index.tsxweb/packages/studio/src/routes/IntakeLayout/index.tsxweb/packages/studio/src/routes/JobDetailRoute/index.tsxweb/packages/studio/src/routes/JobsRoute/index.tsxweb/packages/studio/src/routes/LegacyNewDataDesignerJobRoute/index.tsxweb/packages/studio/src/routes/NewDataDesignerJobRoute/index.tsxweb/packages/studio/src/routes/PromptTuningFormRoute/index.tsxweb/packages/studio/src/routes/SafeSynthesizerJobDetailsRoute/index.tsxweb/packages/studio/src/routes/SafeSynthesizerJobReportRoute/index.tsxweb/packages/studio/src/routes/SafeSynthesizerListRoute/index.tsxweb/packages/studio/src/routes/SafeSynthesizerNewRoute/index.test.tsxweb/packages/studio/src/routes/SafeSynthesizerNewRoute/index.tsxweb/packages/studio/src/routes/SecretsListRoute/CreateSecretModal/index.tsxweb/packages/studio/src/routes/SecretsListRoute/EditSecretModal/index.tsxweb/packages/studio/src/routes/SecretsListRoute/index.tsxweb/packages/studio/src/routes/VirtualModelsListRoute/index.tsxweb/packages/studio/src/routes/WorkspaceBaseModelsRoute/index.tsxweb/packages/studio/src/routes/WorkspaceDashboardRoute/index.tsxweb/packages/studio/src/routes/WorkspaceLayout/WorkspaceSideNav.tsxweb/packages/studio/src/routes/WorkspaceMembersRoute/WorkspaceMemberModal.tsxweb/packages/studio/src/routes/WorkspaceMembersRoute/index.tsxweb/packages/studio/src/routes/WorkspaceSettingsRoute/DeleteWorkspaceModal/index.tsxweb/packages/studio/src/routes/WorkspaceSettingsRoute/EditDescriptionModal/index.tsxweb/packages/studio/src/routes/WorkspaceSettingsRoute/index.tsxweb/packages/studio/src/routes/agents/AgentDetailRoute/DeploymentLogsView.tsxweb/packages/studio/src/routes/agents/AgentDetailRoute/index.tsxweb/packages/studio/src/routes/agents/AgentEvaluationsRoute/AgentEvaluationDetailRoute.tsxweb/packages/studio/src/routes/agents/AgentEvaluationsRoute/AgentEvaluationsListRoute.tsxweb/packages/studio/src/routes/agents/AgentMonitorRoute/index.tsxweb/packages/studio/src/routes/agents/AgentSuggestionsRoute/api.tsweb/packages/studio/src/routes/agents/AgentSuggestionsRoute/index.tsxweb/packages/studio/src/routes/agents/AgentSuggestionsRoute/useOptimizerSuggestions.tsweb/packages/studio/src/routes/agents/AgentSuggestionsRoute/utils.tsweb/packages/studio/src/routes/agents/AgentsListRoute/CloneAgentModal/index.tsxweb/packages/studio/src/routes/agents/AgentsListRoute/CreateExampleAgentModal/index.tsxweb/packages/studio/src/routes/agents/AgentsListRoute/index.tsxweb/packages/studio/src/routes/agents/CopilotChatRoute/ChatThreadErrorBoundary.tsxweb/packages/studio/src/routes/agents/CopilotChatRoute/historyPanel/HistoryPanelContents.tsxweb/packages/studio/src/routes/agents/CopilotChatRoute/index.tsxweb/packages/studio/src/routes/agents/CopilotChatRoute/stream.test.tsweb/packages/studio/src/routes/agents/CopilotChatRoute/stream.tsweb/packages/studio/src/routes/evaluation/EvaluationLayout/index.tsxweb/packages/studio/src/routes/evaluation/EvaluationResultDetailsRoute/index.tsxweb/packages/studio/src/routes/evaluation/EvaluationResultsLayout/index.tsxweb/packages/studio/src/routes/groups/agentRoutes.tsxweb/packages/studio/src/routes/groups/anonymizerRoutes.tsxweb/packages/studio/src/routes/groups/customizationRoutes.tsxweb/packages/studio/src/routes/groups/dashboardRoutes.tsxweb/packages/studio/src/routes/groups/dataDesignerRoutes.tsxweb/packages/studio/src/routes/groups/deploymentRoutes.tsxweb/packages/studio/src/routes/groups/evaluationRoutes.tsxweb/packages/studio/src/routes/groups/experimentRoutes.tsxweb/packages/studio/src/routes/groups/filesetRoutes.tsxweb/packages/studio/src/routes/groups/guardrailsRoutes.tsxweb/packages/studio/src/routes/groups/inferenceProviderRoutes.tsxweb/packages/studio/src/routes/groups/intakeRoutes.tsxweb/packages/studio/src/routes/groups/jobRoutes.tsxweb/packages/studio/src/routes/groups/memberRoutes.tsxweb/packages/studio/src/routes/groups/modelCompareRoutes.tsxweb/packages/studio/src/routes/groups/optimizerRoutes.tsxweb/packages/studio/src/routes/groups/safeSynthesizerRoutes.tsxweb/packages/studio/src/routes/groups/secretsRoutes.tsxweb/packages/studio/src/routes/groups/settingsRoutes.tsxweb/packages/studio/src/routes/groups/virtualModelsRoutes.tsxweb/packages/studio/src/routes/guardrails/GuardrailChecksTab/GuardrailTestCard.tsxweb/packages/studio/src/routes/guardrails/GuardrailChecksTab/GuardrailTestCasesEditor.tsxweb/packages/studio/src/routes/guardrails/GuardrailDetailRoute/GuardrailDetailActions.tsxweb/packages/studio/src/routes/guardrails/GuardrailDetailRoute/index.tsxweb/packages/studio/src/routes/guardrails/GuardrailsRoute/CreateGuardrailModal/index.tsxweb/packages/studio/src/routes/guardrails/GuardrailsRoute/index.tsxweb/packages/studio/src/routes/index.tsxweb/packages/studio/src/routes/optimizer/InsightTracesTable/index.tsxweb/packages/studio/src/routes/optimizer/OptimizerInsightRoute/index.tsxweb/packages/studio/src/routes/optimizer/OptimizerRoute/index.tsxweb/packages/studio/src/util/files.tsweb/packages/studio/src/util/llm.tsweb/packages/studio/src/util/logVersion.tsweb/packages/studio/src/util/logger.test.tsweb/packages/studio/src/util/strings.tsweb/packages/studio/src/workers/LargeFileWorker.ts
💤 Files with no reviewable changes (1)
- web/packages/studio/src/components/NewDataDesignerJobForm/utils.ts
There was a problem hiding this comment.
Caution
Inline review comments failed to post. This is likely due to GitHub's internal server error or limits when posting large numbers of comments. If you are seeing this consistently it is likely a permissions issue. Please check "Moderation" -> "Code review limits" under your organization settings.
Actionable comments posted: 13
🧹 Nitpick comments (5)
web/packages/common/src/components/AccessibleTitle/index.tsx (1)
4-4: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winUse type-only imports.
web/packages/common/src/components/AccessibleTitle/index.tsx#L4-L4: moveFCandPropsWithChildrentoimport type.web/packages/common/src/components/AccordionSection/index.tsx#L10-L10: moveFC,PropsWithChildren, andReactNodetoimport type.🤖 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/common/src/components/AccessibleTitle/index.tsx` at line 4, Convert FC and PropsWithChildren to type-only imports in AccessibleTitle, and convert FC, PropsWithChildren, and ReactNode to type-only imports in AccordionSection; leave runtime React imports unchanged.Source: Coding guidelines
web/packages/common/src/components/ExpandableMessage/index.tsx (1)
5-5: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winUse type-only imports for type-only symbols.
- Mark the listed type-only symbols as
type.- In
FileUpload/index.tsx, also markFC,MouseEvent,MouseEventHandler,ReactNode,DropEvent,DropzoneOptions, andFileRejectionas type-only.- Keep runtime imports such as
FileTag,ErrorCode,React, anduseDropzoneas value imports.🤖 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/common/src/components/ExpandableMessage/index.tsx` at line 5, Update imports at web/packages/common/src/components/ExpandableMessage/index.tsx:5-5, web/packages/common/src/components/FileTag/index.tsx:4-6, web/packages/common/src/components/FileUpload/index.tsx:4-4, web/packages/common/src/components/FileUpload/util.ts:4-4, web/packages/common/src/components/InputErrorText/index.tsx:5-5, and web/packages/common/src/components/QuickActionsMenu/QuickActionsMenuRoot/index.tsx:15-15 to mark all type-only symbols with the type modifier. In FileUpload/index.tsx, apply this to FC, MouseEvent, MouseEventHandler, ReactNode, DropEvent, DropzoneOptions, and FileRejection, while retaining FileTag, ErrorCode, React, and useDropzone as value imports.Source: Coding guidelines
web/packages/studio/src/components/CustomizationFileTag/index.tsx (1)
4-4: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winUse explicit type-only imports.
web/packages/studio/src/components/CustomizationFileTag/index.tsx#L4-L4: keepFileTagas a value import and importFileTagPropswithimport type.web/packages/studio/src/components/CustomizationFileUpload/index.tsx#L4-L4: change theRenderFileTagFnimport toimport type.As per coding guidelines, use
import typefor type-only imports.🤖 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/CustomizationFileTag/index.tsx` at line 4, Update the import in web/packages/studio/src/components/CustomizationFileTag/index.tsx:4 so FileTag remains a value import while FileTagProps uses import type; update the RenderFileTagFn import in web/packages/studio/src/components/CustomizationFileUpload/index.tsx:4 to use import type.Source: Coding guidelines
web/packages/studio/src/components/DatasetFileUpload/index.tsx (1)
4-5: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winMark type-only imports with
import type.
FileTagStatusandRenderFileTagFnare type exports. Split them intoimport typedeclarations.As per coding guidelines, use
import typefor type-only imports.🤖 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/DatasetFileUpload/index.tsx` around lines 4 - 5, Update the imports in the DatasetFileUpload module so the type-only symbols FileTagStatus and RenderFileTagFn use separate import type declarations, while retaining FileTag and FileUpload as regular runtime imports.Source: Coding guidelines
web/packages/studio/src/util/logVersion.ts (1)
7-11: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winDeclare the public return type.
Add the explicit return type to the exported function:
-export const logVersion = async () => { +export const logVersion = async (): Promise<void> => {As per coding guidelines, public APIs should declare explicit return types.
🤖 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/util/logVersion.ts` around lines 7 - 11, Update the exported logVersion function to declare its explicit Promise-based return type, matching its async implementation and existing behavior.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 `@plugins/example-plugin/web/AGENTS.md`:
- Around line 38-41: Add host.breadcrumbs to the injected host capability list
near the existing navigation entry, keeping it consistent with the capability
contract defined in SharedUiPage.tsx.
In `@plugins/example-plugin/web/src/SharedUiPage.tsx`:
- Line 13: Update the import of pluginPath in SharedUiPage.tsx to use the
project’s configured absolute alias instead of the relative "./paths" path,
while preserving the same imported symbol.
- Around line 26-34: Update the breadcrumb effect in SharedUiPage to return a
cleanup function that clears the page trail through setBreadcrumbs when the page
unmounts. Preserve the existing breadcrumb setup on mount and ensure cleanup
also runs when its dependencies change.
In `@web/packages/common/src/api/common/utils.ts`:
- Around line 4-8: Update the import of GenericSortField, PaginationData, and
ValidationError to use a type-only import, since these SDK symbols are
referenced only in type positions.
- Around line 99-105: Update the request-context formatting in the error
handling logic around error.config so user-visible messages never include raw
URLs with query parameters or fragments. Sanitize url by removing its query
string and fragment before appending it to parts, while preserving the existing
method and URL context when available.
- Around line 37-43: Update the item validation predicate in the API error
utility to require that item.loc is an array before accepting the object.
Preserve the existing msg and type checks so downstream filtering can safely
call filter on loc.
In `@web/packages/common/src/components/ExpandableMessage/index.tsx`:
- Around line 55-58: The fixed danger styling is currently overwritten by caller
className props. In
web/packages/common/src/components/ExpandableMessage/index.tsx#L55-L58, update
the Text className handling to merge attributes.Text.className while always
retaining text-feedback-danger; apply the same merge in
web/packages/common/src/components/InputErrorText/index.tsx#L18-L18 for
props.className.
In `@web/packages/studio/src/components/DataDesignerJobActionsMenu/index.tsx`:
- Around line 4-7: Replace the deep internal `@nemo/common/src/`... imports with
public `@nemo/common` barrel imports: in
web/packages/studio/src/components/DataDesignerJobActionsMenu/index.tsx (lines
4-7), import QuickActionsMenuRoot and QuickActionItem; in
web/packages/studio/src/components/DatasetFileUpload/index.tsx (lines 4-5),
import FileTag and FileUpload; in
web/packages/studio/src/routes/InferenceProvidersListRoute/index.tsx (line 13)
and web/packages/studio/src/routes/IntakeLayout/index.tsx (line 4), import
AccessibleTitle; and in web/packages/studio/src/routes/JobDetailRoute/index.tsx
(lines 4-5), import AccessibleTitle and CancelJobButton. Ensure none of these
migrated shared UI imports use `@nemo/common/src/` paths.
In `@web/packages/studio/src/components/promoted/ErrorPanel.test.tsx`:
- Around line 4-5: Update the import containing ErrorPanelProps to use a
type-only import while keeping the runtime ErrorPanel import unchanged.
In
`@web/packages/studio/src/components/PromptTuningForm/InContextLearningSection/index.tsx`:
- Line 5: Update the shared UI imports to use the public `@nemo/common` entry
point: in
web/packages/studio/src/components/PromptTuningForm/InContextLearningSection/index.tsx:5,
web/packages/studio/src/routes/agents/AgentSuggestionsRoute/index.tsx:4, and
web/packages/studio/src/routes/agents/AgentsListRoute/index.tsx:4, import
AccordionSection or AccessibleTitle from `@nemo/common` instead of deep-linking
into src. Export either component through web/packages/common/src/plugin.ts if
the barrel does not already expose it.
In
`@web/packages/studio/src/components/PromptTuningForm/InferenceParametersSection/index.tsx`:
- Line 4: Update Studio’s module resolver and TypeScript path mapping to resolve
shared UI through the curated `@nemo/common` entry point exported by plugin.ts,
then replace the seven deep imports in
web/packages/studio/src/components/PromptTuningForm/InferenceParametersSection/index.tsx
(anchor), PromptTemplateSection/index.tsx, ToolsSection/index.tsx,
QuickActionsMenu/QuickActionsMenuDefault/index.tsx,
routes/agents/CopilotChatRoute/historyPanel/HistoryPanelContents.tsx,
routes/agents/CopilotChatRoute/index.tsx, and
routes/evaluation/EvaluationLayout/index.tsx with imports from that entry point.
In `@web/packages/studio/src/plugins/PluginRenderer.tsx`:
- Around line 56-57: Update the cleanup useEffect in PluginRenderer to include
pluginName in its dependency array so setBreadcrumbs([]) runs when the routed
plugin changes, then add a test covering a retained PluginRenderer switching
pluginName and clearing the previous breadcrumbs.
In `@web/packages/studio/src/routes/optimizer/OptimizerRoute/index.tsx`:
- Around line 5-10: Replace all listed deep shared-UI imports with the bare
`@nemo/common` barrel, and add any missing symbols to plugin.ts exports:
web/packages/studio/src/routes/optimizer/OptimizerRoute/index.tsx (lines 5-10)
for AccessibleTitle, StudioDataView, and ErrorPanel;
web/packages/studio/src/routes/optimizer/OptimizerInsightRoute/index.tsx (lines
4-6) for AccessibleTitle, ErrorMessage, and ExpandableMessage;
web/packages/studio/src/routes/index.tsx (line 5) for ErrorPanel;
web/packages/studio/src/routes/guardrails/GuardrailDetailRoute/index.tsx (line
6) for AccessibleTitle;
web/packages/studio/src/routes/guardrails/GuardrailDetailRoute/GuardrailDetailActions.tsx
(lines 4-8) for DeleteConfirmationModal and QuickActionsMenuRoot;
web/packages/studio/src/components/promoted/DeleteConfirmationModal.test.tsx
(line 4) for DeleteConfirmationModal; and
web/packages/studio/src/components/promoted/CancelJobButton.test.tsx (line 4)
for CancelJobButton.
---
Nitpick comments:
In `@web/packages/common/src/components/AccessibleTitle/index.tsx`:
- Line 4: Convert FC and PropsWithChildren to type-only imports in
AccessibleTitle, and convert FC, PropsWithChildren, and ReactNode to type-only
imports in AccordionSection; leave runtime React imports unchanged.
In `@web/packages/common/src/components/ExpandableMessage/index.tsx`:
- Line 5: Update imports at
web/packages/common/src/components/ExpandableMessage/index.tsx:5-5,
web/packages/common/src/components/FileTag/index.tsx:4-6,
web/packages/common/src/components/FileUpload/index.tsx:4-4,
web/packages/common/src/components/FileUpload/util.ts:4-4,
web/packages/common/src/components/InputErrorText/index.tsx:5-5, and
web/packages/common/src/components/QuickActionsMenu/QuickActionsMenuRoot/index.tsx:15-15
to mark all type-only symbols with the type modifier. In FileUpload/index.tsx,
apply this to FC, MouseEvent, MouseEventHandler, ReactNode, DropEvent,
DropzoneOptions, and FileRejection, while retaining FileTag, ErrorCode, React,
and useDropzone as value imports.
In `@web/packages/studio/src/components/CustomizationFileTag/index.tsx`:
- Line 4: Update the import in
web/packages/studio/src/components/CustomizationFileTag/index.tsx:4 so FileTag
remains a value import while FileTagProps uses import type; update the
RenderFileTagFn import in
web/packages/studio/src/components/CustomizationFileUpload/index.tsx:4 to use
import type.
In `@web/packages/studio/src/components/DatasetFileUpload/index.tsx`:
- Around line 4-5: Update the imports in the DatasetFileUpload module so the
type-only symbols FileTagStatus and RenderFileTagFn use separate import type
declarations, while retaining FileTag and FileUpload as regular runtime imports.
In `@web/packages/studio/src/util/logVersion.ts`:
- Around line 7-11: Update the exported logVersion function to declare its
explicit Promise-based return type, matching its async implementation and
existing behavior.
🪄 Autofix
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: bb6b888f-fa73-4f91-99cc-42e77e521843
⛔ Files ignored due to path filters (2)
plugins/example-plugin/src/nemo_example_plugin/web/dist/index.jsis excluded by!**/dist/**web/pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (214)
plugins/example-plugin/web/AGENTS.mdplugins/example-plugin/web/src/SharedUiPage.tsxplugins/example-plugin/web/src/types.tsweb/packages/common/package.jsonweb/packages/common/src/api/common/utils.test.tsweb/packages/common/src/api/common/utils.tsweb/packages/common/src/components/AccessibleTitle/index.test.tsxweb/packages/common/src/components/AccessibleTitle/index.tsxweb/packages/common/src/components/AccordionSection/index.tsxweb/packages/common/src/components/CancelJobButton/index.tsxweb/packages/common/src/components/ConfirmationModal/index.tsxweb/packages/common/src/components/DeleteConfirmationModal/index.tsxweb/packages/common/src/components/ErrorPanel/index.tsxweb/packages/common/src/components/ExpandableMessage/index.test.tsxweb/packages/common/src/components/ExpandableMessage/index.tsxweb/packages/common/src/components/FileTag/index.tsxweb/packages/common/src/components/FileUpload/index.tsxweb/packages/common/src/components/FileUpload/util.tsweb/packages/common/src/components/InputErrorText/index.tsxweb/packages/common/src/components/QuickActionsMenu/QuickActionsMenuRoot/index.test.tsxweb/packages/common/src/components/QuickActionsMenu/QuickActionsMenuRoot/index.tsxweb/packages/common/src/plugin.tsweb/packages/common/src/utils/error.tsweb/packages/common/src/utils/forms/error.test.tsweb/packages/common/src/utils/forms/error.tsweb/packages/common/src/utils/logger.tsweb/packages/studio/src/App.tsxweb/packages/studio/src/api/datasets/useDatasetFileContent.tsweb/packages/studio/src/api/guardrail-checks/guardrailChecks.tsweb/packages/studio/src/components/AnonymizerJobActionsMenu/index.tsxweb/packages/studio/src/components/BulkDeleteModal/index.tsxweb/packages/studio/src/components/CreateFilesetStart/useDescribeWithAi.tsweb/packages/studio/src/components/CustomizationFileTag/index.tsxweb/packages/studio/src/components/CustomizationFileUpload/index.tsxweb/packages/studio/src/components/CustomizationFilesetCreateModal/index.tsxweb/packages/studio/src/components/DataDesignerJobActionsMenu/index.tsxweb/packages/studio/src/components/DatasetCreateModal/index.tsxweb/packages/studio/src/components/DatasetFileUpload/index.tsxweb/packages/studio/src/components/DatasetInputFile/index.tsxweb/packages/studio/src/components/DatasetsTable/index.test.tsxweb/packages/studio/src/components/DatasetsTable/index.tsxweb/packages/studio/src/components/ExperimentCreateModal/index.tsxweb/packages/studio/src/components/FilesTable/CreateFileSplitsModal/index.tsxweb/packages/studio/src/components/FilesTable/DirectoryQuickActions/index.tsxweb/packages/studio/src/components/FilesTable/FileQuickActions/index.tsxweb/packages/studio/src/components/FilesTable/RenameFileModal/index.tsxweb/packages/studio/src/components/FilesTable/TransformFileModal/index.tsxweb/packages/studio/src/components/FilesetActionMenu/index.tsxweb/packages/studio/src/components/FilesetCreateModal/index.tsxweb/packages/studio/src/components/FilesetFilePreviewPanel/components/FileActions/index.tsxweb/packages/studio/src/components/IntakeDetail/IntakeComponents/AnnotationsPanel.tsxweb/packages/studio/src/components/IntakeDetail/IntakeComponents/useSpanAnnotationActions.tsweb/packages/studio/src/components/IntakeDetail/SessionDetailView.tsxweb/packages/studio/src/components/IntakeDetail/TraceSpanAccordions.tsxweb/packages/studio/src/components/IntakeLists/IntakeSpansTable.tsxweb/packages/studio/src/components/IntakeLists/IntakeTracesTable.tsxweb/packages/studio/src/components/ModelActionsMenu/index.tsxweb/packages/studio/src/components/ModelChat/index.tsxweb/packages/studio/src/components/ModelComparePrompts/useModelComparePrompts.tsweb/packages/studio/src/components/NewCustomizationForm/index.tsxweb/packages/studio/src/components/NewDataDesignerJobForm/JobRequestGenerator.tsxweb/packages/studio/src/components/NewDataDesignerJobForm/usePreview.tsweb/packages/studio/src/components/NewDataDesignerJobForm/utils.test.tsweb/packages/studio/src/components/NewDataDesignerJobForm/utils.tsweb/packages/studio/src/components/PromptTuningForm/ImportFromDatasetModal/index.tsxweb/packages/studio/src/components/PromptTuningForm/InContextLearningSection/index.tsxweb/packages/studio/src/components/PromptTuningForm/InferenceParametersSection/index.tsxweb/packages/studio/src/components/PromptTuningForm/PromptTemplateSection/index.tsxweb/packages/studio/src/components/PromptTuningForm/ToolsSection/index.tsxweb/packages/studio/src/components/QuickActionsMenu/QuickActionsMenuDefault/index.tsxweb/packages/studio/src/components/WorkspaceCreateModal/index.tsxweb/packages/studio/src/components/WorkspaceDropdown/index.tsxweb/packages/studio/src/components/common/SearchBar/index.tsxweb/packages/studio/src/components/dataViews/AgentEvaluationsDataView/index.tsxweb/packages/studio/src/components/dataViews/AgentsDataView/index.tsxweb/packages/studio/src/components/dataViews/CustomModelsDataView/index.tsxweb/packages/studio/src/components/dataViews/DeploymentsDataView/index.tsxweb/packages/studio/src/components/dataViews/ExperimentDataView/index.tsxweb/packages/studio/src/components/dataViews/GuardrailsDataView/index.tsxweb/packages/studio/src/components/dataViews/InferenceProvidersDataView/index.tsxweb/packages/studio/src/components/dataViews/JobsDataView/index.tsxweb/packages/studio/src/components/dataViews/SafeSynthesizerJobsDataView/index.tsxweb/packages/studio/src/components/dataViews/SecretsDataView/index.tsxweb/packages/studio/src/components/dataViews/VirtualModelsDataView/index.tsxweb/packages/studio/src/components/evaluation/Configurations/form/InputFile/useInputFile.tsweb/packages/studio/src/components/evaluation/Jobs/ActionMenu.tsxweb/packages/studio/src/components/evaluation/Jobs/DetailsPanel.tsxweb/packages/studio/src/components/evaluation/Jobs/EvaluationJobBulkDeleteModal.tsxweb/packages/studio/src/components/evaluation/Jobs/form/ScoreDefinitions.tsxweb/packages/studio/src/components/filesets/AddToFolderModal/index.tsxweb/packages/studio/src/components/filesets/FilesetFileExplorer/DatasetFileDropzone/index.tsxweb/packages/studio/src/components/filesets/FilesetFileExplorer/NewDirectoryModal/index.tsxweb/packages/studio/src/components/filesets/hooks/useBulkDownload.tsweb/packages/studio/src/components/filesets/hooks/useBulkDuplicate.tsweb/packages/studio/src/components/promoted/CancelJobButton.test.tsxweb/packages/studio/src/components/promoted/DeleteConfirmationModal.test.tsxweb/packages/studio/src/components/promoted/ErrorPanel.test.tsxweb/packages/studio/src/components/sidePanels/MetricRunSidePanel/index.tsxweb/packages/studio/src/components/sidePanels/ModelPanels/ModelPanel/components.tsxweb/packages/studio/src/components/sidePanels/ModelPanels/ModelPanel/index.tsxweb/packages/studio/src/main.tsxweb/packages/studio/src/plugins/PluginErrorBoundary.tsxweb/packages/studio/src/plugins/PluginRenderer.test.tsxweb/packages/studio/src/plugins/PluginRenderer.tsxweb/packages/studio/src/plugins/types.tsweb/packages/studio/src/plugins/utils.tsweb/packages/studio/src/routes/AnonymizerBuilderRoute/components/AnonymizerBuilderForm.tsxweb/packages/studio/src/routes/AnonymizerBuilderRoute/index.tsxweb/packages/studio/src/routes/AnonymizerJobDetailRoute/index.tsxweb/packages/studio/src/routes/AnonymizerListRoute/index.tsxweb/packages/studio/src/routes/AuthSuccessRoute/index.tsxweb/packages/studio/src/routes/CustomizationJobDetailsRoute/DetailActions.tsxweb/packages/studio/src/routes/CustomizationJobDetailsRoute/index.tsxweb/packages/studio/src/routes/CustomizationJobListRoute/index.tsxweb/packages/studio/src/routes/DashboardLandingRoute/index.tsxweb/packages/studio/src/routes/DataDesignerJobBuildRoute/index.tsxweb/packages/studio/src/routes/DataDesignerJobDetailsRoute/index.tsxweb/packages/studio/src/routes/DataDesignerJobListRoute/index.tsxweb/packages/studio/src/routes/DeploymentsListRoute/CreateDeploymentSidePanel/useCreateDeploymentBySource.tsweb/packages/studio/src/routes/DeploymentsListRoute/index.tsxweb/packages/studio/src/routes/DeploymentsListRoute/useDeleteDeploymentAndConfig.tsweb/packages/studio/src/routes/EvaluationDetailRoute/index.tsxweb/packages/studio/src/routes/EvaluationSessionDetailRoute/SessionCompareColumn.tsxweb/packages/studio/src/routes/EvaluationSessionDetailRoute/TestCaseCompare.tsxweb/packages/studio/src/routes/ExperimentDetailRoute/index.tsxweb/packages/studio/src/routes/ExperimentRoute/index.tsxweb/packages/studio/src/routes/FilesetDetailRoute/index.tsxweb/packages/studio/src/routes/FilesetListRoute/ActionMenu/index.test.tsxweb/packages/studio/src/routes/FilesetListRoute/ActionMenu/index.tsxweb/packages/studio/src/routes/FilesetListRoute/index.tsxweb/packages/studio/src/routes/FilesetNewRoute/helpers.tsweb/packages/studio/src/routes/FilesetNewRoute/index.tsxweb/packages/studio/src/routes/FilesetNewRoute/useCreateFileset.tsweb/packages/studio/src/routes/InferenceProvidersListRoute/CreateInferenceProviderSidePanel/index.tsxweb/packages/studio/src/routes/InferenceProvidersListRoute/index.tsxweb/packages/studio/src/routes/IntakeLayout/index.tsxweb/packages/studio/src/routes/JobDetailRoute/index.tsxweb/packages/studio/src/routes/JobsRoute/index.tsxweb/packages/studio/src/routes/LegacyNewDataDesignerJobRoute/index.tsxweb/packages/studio/src/routes/NewDataDesignerJobRoute/index.tsxweb/packages/studio/src/routes/PromptTuningFormRoute/index.tsxweb/packages/studio/src/routes/SafeSynthesizerJobDetailsRoute/index.tsxweb/packages/studio/src/routes/SafeSynthesizerJobReportRoute/index.tsxweb/packages/studio/src/routes/SafeSynthesizerListRoute/index.tsxweb/packages/studio/src/routes/SafeSynthesizerNewRoute/index.test.tsxweb/packages/studio/src/routes/SafeSynthesizerNewRoute/index.tsxweb/packages/studio/src/routes/SecretsListRoute/CreateSecretModal/index.tsxweb/packages/studio/src/routes/SecretsListRoute/EditSecretModal/index.tsxweb/packages/studio/src/routes/SecretsListRoute/index.tsxweb/packages/studio/src/routes/VirtualModelsListRoute/index.tsxweb/packages/studio/src/routes/WorkspaceBaseModelsRoute/index.tsxweb/packages/studio/src/routes/WorkspaceDashboardRoute/index.tsxweb/packages/studio/src/routes/WorkspaceLayout/WorkspaceSideNav.tsxweb/packages/studio/src/routes/WorkspaceMembersRoute/WorkspaceMemberModal.tsxweb/packages/studio/src/routes/WorkspaceMembersRoute/index.tsxweb/packages/studio/src/routes/WorkspaceSettingsRoute/DeleteWorkspaceModal/index.tsxweb/packages/studio/src/routes/WorkspaceSettingsRoute/EditDescriptionModal/index.tsxweb/packages/studio/src/routes/WorkspaceSettingsRoute/index.tsxweb/packages/studio/src/routes/agents/AgentDetailRoute/DeploymentLogsView.tsxweb/packages/studio/src/routes/agents/AgentDetailRoute/index.tsxweb/packages/studio/src/routes/agents/AgentEvaluationsRoute/AgentEvaluationDetailRoute.tsxweb/packages/studio/src/routes/agents/AgentEvaluationsRoute/AgentEvaluationsListRoute.tsxweb/packages/studio/src/routes/agents/AgentMonitorRoute/index.tsxweb/packages/studio/src/routes/agents/AgentSuggestionsRoute/api.tsweb/packages/studio/src/routes/agents/AgentSuggestionsRoute/index.tsxweb/packages/studio/src/routes/agents/AgentSuggestionsRoute/useOptimizerSuggestions.tsweb/packages/studio/src/routes/agents/AgentSuggestionsRoute/utils.tsweb/packages/studio/src/routes/agents/AgentsListRoute/CloneAgentModal/index.tsxweb/packages/studio/src/routes/agents/AgentsListRoute/CreateExampleAgentModal/index.tsxweb/packages/studio/src/routes/agents/AgentsListRoute/index.tsxweb/packages/studio/src/routes/agents/CopilotChatRoute/ChatThreadErrorBoundary.tsxweb/packages/studio/src/routes/agents/CopilotChatRoute/historyPanel/HistoryPanelContents.tsxweb/packages/studio/src/routes/agents/CopilotChatRoute/index.tsxweb/packages/studio/src/routes/agents/CopilotChatRoute/stream.test.tsweb/packages/studio/src/routes/agents/CopilotChatRoute/stream.tsweb/packages/studio/src/routes/evaluation/EvaluationLayout/index.tsxweb/packages/studio/src/routes/evaluation/EvaluationResultDetailsRoute/index.tsxweb/packages/studio/src/routes/evaluation/EvaluationResultsLayout/index.tsxweb/packages/studio/src/routes/groups/agentRoutes.tsxweb/packages/studio/src/routes/groups/anonymizerRoutes.tsxweb/packages/studio/src/routes/groups/customizationRoutes.tsxweb/packages/studio/src/routes/groups/dashboardRoutes.tsxweb/packages/studio/src/routes/groups/dataDesignerRoutes.tsxweb/packages/studio/src/routes/groups/deploymentRoutes.tsxweb/packages/studio/src/routes/groups/evaluationRoutes.tsxweb/packages/studio/src/routes/groups/experimentRoutes.tsxweb/packages/studio/src/routes/groups/filesetRoutes.tsxweb/packages/studio/src/routes/groups/guardrailsRoutes.tsxweb/packages/studio/src/routes/groups/inferenceProviderRoutes.tsxweb/packages/studio/src/routes/groups/intakeRoutes.tsxweb/packages/studio/src/routes/groups/jobRoutes.tsxweb/packages/studio/src/routes/groups/memberRoutes.tsxweb/packages/studio/src/routes/groups/modelCompareRoutes.tsxweb/packages/studio/src/routes/groups/optimizerRoutes.tsxweb/packages/studio/src/routes/groups/safeSynthesizerRoutes.tsxweb/packages/studio/src/routes/groups/secretsRoutes.tsxweb/packages/studio/src/routes/groups/settingsRoutes.tsxweb/packages/studio/src/routes/groups/virtualModelsRoutes.tsxweb/packages/studio/src/routes/guardrails/GuardrailChecksTab/GuardrailTestCard.tsxweb/packages/studio/src/routes/guardrails/GuardrailChecksTab/GuardrailTestCasesEditor.tsxweb/packages/studio/src/routes/guardrails/GuardrailDetailRoute/GuardrailDetailActions.tsxweb/packages/studio/src/routes/guardrails/GuardrailDetailRoute/index.tsxweb/packages/studio/src/routes/guardrails/GuardrailsRoute/CreateGuardrailModal/index.tsxweb/packages/studio/src/routes/guardrails/GuardrailsRoute/index.tsxweb/packages/studio/src/routes/index.tsxweb/packages/studio/src/routes/optimizer/InsightTracesTable/index.tsxweb/packages/studio/src/routes/optimizer/OptimizerInsightRoute/index.tsxweb/packages/studio/src/routes/optimizer/OptimizerRoute/index.tsxweb/packages/studio/src/util/files.tsweb/packages/studio/src/util/llm.tsweb/packages/studio/src/util/logVersion.tsweb/packages/studio/src/util/logger.test.tsweb/packages/studio/src/util/strings.tsweb/packages/studio/src/workers/LargeFileWorker.ts
💤 Files with no reviewable changes (1)
- web/packages/studio/src/components/NewDataDesignerJobForm/utils.ts
🛑 Comments failed to post (4)
web/packages/common/src/api/common/utils.ts (3)
4-8: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Use a type-only import.
These SDK symbols are used only as types. Use
import typefor this import.🤖 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/common/src/api/common/utils.ts` around lines 4 - 8, Update the import of GenericSortField, PaginationData, and ValidationError to use a type-only import, since these SDK symbols are referenced only in type positions.Source: Coding guidelines
37-43: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win
Validate
locas an array.The guard accepts
loc: nullor another non-array value. Line 76 then callsfilterand throws while handling an API error. Require an array before returningtrue.Proposed fix
'type' in item && - 'loc' in item + 'loc' in item && + Array.isArray(item.loc) && + item.loc.every((part) => typeof part === 'string' || typeof part === 'number')📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.(item) => typeof item === 'object' && item !== null && 'msg' in item && typeof item.msg === 'string' && 'type' in item && 'loc' in item && Array.isArray(item.loc) && item.loc.every((part) => typeof part === 'string' || typeof part === 'number')🤖 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/common/src/api/common/utils.ts` around lines 37 - 43, Update the item validation predicate in the API error utility to require that item.loc is an array before accepting the object. Preserve the existing msg and type checks so downstream filtering can safely call filter on loc.
99-105: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win
Do not return raw request URLs.
Line 104 can expose query parameters in a user-visible error message. Query parameters can contain identifiers or credentials. Omit the URL, or remove its query string and fragment before returning the message.
🤖 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/common/src/api/common/utils.ts` around lines 99 - 105, Update the request-context formatting in the error handling logic around error.config so user-visible messages never include raw URLs with query parameters or fragments. Sanitize url by removing its query string and fragment before appending it to parts, while preserving the existing method and URL context when available.web/packages/common/src/components/ExpandableMessage/index.tsx (1)
55-58: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Preserve required error styling.
Later prop spreads replace the fixed danger class. A caller can remove
text-feedback-danger.
web/packages/common/src/components/ExpandableMessage/index.tsx#L55-L58: Mergeattributes.Text.classNameand keeptext-feedback-danger.web/packages/common/src/components/InputErrorText/index.tsx#L18-L18: Mergeprops.classNameand keeptext-feedback-danger.📍 Affects 2 files
web/packages/common/src/components/ExpandableMessage/index.tsx#L55-L58(this comment)web/packages/common/src/components/InputErrorText/index.tsx#L18-L18🤖 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/common/src/components/ExpandableMessage/index.tsx` around lines 55 - 58, The fixed danger styling is currently overwritten by caller className props. In web/packages/common/src/components/ExpandableMessage/index.tsx#L55-L58, update the Text className handling to merge attributes.Text.className while always retaining text-feedback-danger; apply the same merge in web/packages/common/src/components/InputErrorText/index.tsx#L18-L18 for props.className.
Review on #1192 caught two gaps in the breadcrumbs wiring. PluginRenderer cleared the trail only on unmount, but the router reuses the component across a :pluginName change, so the outgoing plugin's breadcrumbs stayed visible until the incoming one set its own. Key the cleanup on pluginName. The new test fails without that dep. SharedUiPage set a trail and never cleared it. Studio only clears when the whole plugin unmounts, so navigating between pages inside a plugin left the previous page's crumb behind. The example is the template other plugins copy, and AGENTS.md told authors not to hand-roll cleanup — true for plugin unmount, wrong for page unmount. Fixed both, and listed breadcrumbs in the host capability enumeration it was missing from. Signed-off-by: mschwab <mschwab@nvidia.com>
|
/nvskills-ci |
|
Moved the Iron Swarm UI onto this branch for #1037 — the barrel made it straightforward, thanks :)
Plugin nav groups don't merge with core ones. Flagging both since they'll affect any plugin that follows. |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (3)
web/packages/common/src/providers/toast/useNotify.ts (1)
4-4: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winUse
import typefor type-only imports.
web/packages/common/src/providers/toast/useNotify.ts#L4-L4: ChangeNotifyFnto a type-only import.web/packages/common/src/providers/toast/useNotify.test.tsx#L5-L10: ChangeMessageFnOptions,NotifyFn, andFCto type-only imports.web/packages/common/src/components/ConfirmationModal/index.tsx#L7-L7: ChangeNotifyFnto a type-only import.web/packages/common/src/components/DeleteConfirmationModal/index.tsx#L6-L6: ChangeNotifyFnto a type-only import.web/packages/common/src/components/LogViewer/index.tsx#L5-L5: ChangeNotifyFnto a type-only import.As per coding guidelines, “Use
import typefor type-only imports.”🤖 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/common/src/providers/toast/useNotify.ts` at line 4, Convert the type-only imports to use import type in useNotify.ts (NotifyFn), useNotify.test.tsx (MessageFnOptions, NotifyFn, and FC), ConfirmationModal/index.tsx (NotifyFn), DeleteConfirmationModal/index.tsx (NotifyFn), and LogViewer/index.tsx (NotifyFn); preserve any runtime imports separately where needed.Source: Coding guidelines
web/packages/common/src/providers/toast/useNotify.test.tsx (1)
12-18: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winDeclare
NotifierProps.
Notifieruses an inline props shape. Define an explicit props interface.As per coding guidelines, “Define explicit props interfaces for all React components.”
🤖 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/common/src/providers/toast/useNotify.test.tsx` around lines 12 - 18, Define a named NotifierProps interface for the onNotify and options props, then update the Notifier component to use that interface instead of the inline props shape. Preserve the existing optional types and notification behavior.Source: Coding guidelines
plugins/example-plugin/web/AGENTS.md (1)
88-117: 📐 Maintainability & Code Quality | 🔵 Trivial | 🏗️ Heavy liftSplit this mixed documentation page.
This page combines explanation, how-to steps, and contract reference. Move this notification guidance to a cross-linked reference or how-to page.
As per coding guidelines, “Each documentation page should fit ONE Diataxis quadrant.”
🤖 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 `@plugins/example-plugin/web/AGENTS.md` around lines 88 - 117, Split the mixed AGENTS.md content so the notification explanation and usage example move to an appropriate cross-linked how-to or reference page, while keeping the contract reference in its own documentation page. Update links between the pages and ensure each page follows a single Diataxis quadrant.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 `@web/packages/studio/src/routes/WorkspaceLayout/WorkspaceSideNav.tsx`:
- Around line 337-350: Update the plugin navigation items before the merge in
mergedItems so every plugin item.id is prefixed with its plugin name, while
preserving group matching and item order. Use the plugin identity available in
pluginNavGroups, ensure nested plugin navigation IDs are handled consistently if
applicable, and add a regression test proving plugin IDs cannot collide with
core NavigationDrawer keys.
---
Nitpick comments:
In `@plugins/example-plugin/web/AGENTS.md`:
- Around line 88-117: Split the mixed AGENTS.md content so the notification
explanation and usage example move to an appropriate cross-linked how-to or
reference page, while keeping the contract reference in its own documentation
page. Update links between the pages and ensure each page follows a single
Diataxis quadrant.
In `@web/packages/common/src/providers/toast/useNotify.test.tsx`:
- Around line 12-18: Define a named NotifierProps interface for the onNotify and
options props, then update the Notifier component to use that interface instead
of the inline props shape. Preserve the existing optional types and notification
behavior.
In `@web/packages/common/src/providers/toast/useNotify.ts`:
- Line 4: Convert the type-only imports to use import type in useNotify.ts
(NotifyFn), useNotify.test.tsx (MessageFnOptions, NotifyFn, and FC),
ConfirmationModal/index.tsx (NotifyFn), DeleteConfirmationModal/index.tsx
(NotifyFn), and LogViewer/index.tsx (NotifyFn); preserve any runtime imports
separately where needed.
🪄 Autofix
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: 58cd014a-5c71-4c51-8b72-911451721d2f
📒 Files selected for processing (13)
plugins/example-plugin/web/AGENTS.mdplugins/example-plugin/web/src/types.tsweb/packages/common/src/components/ConfirmationModal/index.tsxweb/packages/common/src/components/DeleteConfirmationModal/index.tsxweb/packages/common/src/components/LogViewer/index.tsxweb/packages/common/src/plugin.tsweb/packages/common/src/providers/toast/types.tsweb/packages/common/src/providers/toast/useNotify.test.tsxweb/packages/common/src/providers/toast/useNotify.tsweb/packages/studio/src/plugins/PluginRenderer.tsxweb/packages/studio/src/plugins/types.tsweb/packages/studio/src/routes/WorkspaceLayout/WorkspaceSideNav.test.tsxweb/packages/studio/src/routes/WorkspaceLayout/WorkspaceSideNav.tsx
🚧 Files skipped from review as they are similar to previous changes (2)
- web/packages/studio/src/plugins/PluginRenderer.tsx
- web/packages/common/src/plugin.ts
Plugin bundles reach Studio's shared UI through the curated barrel in common/src/plugin.ts, but seven of the components Iron Swarm needs lived in web/packages/studio and were therefore unreachable. Move them into @nemo/common and export them, so the next plugin gets them for free rather than reimplementing a table, an accordion, or a file picker. Moved with git mv so history follows: AccessibleTitle, AccordionSection, ExpandableMessage, FileTag, InputErrorText, FileUpload (+util), QuickActionsMenuRoot, and api/common/utils, along with their tests. Studio's ~100 importers now point at @nemo/common directly; no shims are left behind. common gains react-dropzone, which came with FileUpload. Also adds JOB_POLLING_INTERVAL_MS to the barrel — the one name the audit of Iron Swarm's usage found missing. Three candidates were deliberately left out of the barrel, and the measurement is why. Exporting CreateSecretModal, fetchAgentsForSelect, and getErrorMessage pulled the generated SDK client into the shared vendor bundle, taking it from 241 kB to 553 kB and dragging in axios and oidc-client-ts. That is not just weight: plugins are meant to receive the SDK on host.sdk precisely so there is one axios instance carrying Studio's OIDC interceptor, and a second copy in common.js would have issued unauthenticated requests. The bundle is back to 314 kB with axios, oidc-client-ts and zod absent; the remainder is react-dropzone, which FileUpload genuinely needs. A plugin that wants those three composes them from the primitives the barrel does export, wired to host.sdk. Signed-off-by: mschwab <mschwab@nvidia.com>
Studio's breadcrumb bar renders in GlobalNav, which sits in the layout's navbar grid area while a plugin renders in the content area several route levels below. A plugin therefore cannot render breadcrumbs itself; it can only write into the context GlobalNav consumes. That is the same shape as notifications writing to Studio's shared toaster, so expose it the same way, on the host handle. Studio clears the trail when the plugin unmounts rather than trusting each plugin to clean up, and the setter is a plain function instead of copying useBreadcrumbs' mount-only semantics — plugin detail routes need to update the trail as data arrives. Iron Swarm's routes import useBreadcrumbs directly today; this is what they move to. Signed-off-by: mschwab <mschwab@nvidia.com>
… and the logger to @nemo/common Completes the shared-UI promotion. These four were blocked on Studio's OTEL logger, which imports constants/environment and pulls in the whole feature-flag chain, so move the logger too — but sever it from that config rather than dragging it along. The service name arrives via configureLogger(), which App.tsx calls at bootstrap; logVersion stays in Studio because it needs VERSION_SHA. CancelJobButton read the workspace off the URL via useWorkspaceFromPath. It now takes it as a prop, which is what let it move and is better regardless — a component that reads the router is harder to reuse. Both call sites already had the workspace in scope. Also relocates getErrorMessage out of NewDataDesignerJobForm/utils. It is seven dependency-free lines with nothing to do with Data Designer, and importing it was what dragged that 206-line module — and the logger chain behind it — into anything that wanted a formatted error string. Two of the four are deliberately not exported to plugins. CancelJobButton calls the jobs API through the generated SDK, and ErrorPanel formats errors through the axios-aware helper; exporting either put axios and oidc-client-ts back into the shared vendor bundle, which is the same correctness problem as before — plugins get their SDK on host.sdk so there is exactly one authenticated client. Both still live in common for Studio's own use. The bundle lands at 339 kB with axios absent. Signed-off-by: mschwab <mschwab@nvidia.com>
Review on #1192 caught two gaps in the breadcrumbs wiring. PluginRenderer cleared the trail only on unmount, but the router reuses the component across a :pluginName change, so the outgoing plugin's breadcrumbs stayed visible until the incoming one set its own. Key the cleanup on pluginName. The new test fails without that dep. SharedUiPage set a trail and never cleared it. Studio only clears when the whole plugin unmounts, so navigating between pages inside a plugin left the previous page's crumb behind. The example is the template other plugins copy, and AGENTS.md told authors not to hand-roll cleanup — true for plugin unmount, wrong for page unmount. Fixed both, and listed breadcrumbs in the host capability enumeration it was missing from. Signed-off-by: mschwab <mschwab@nvidia.com>
ToastProvider does not cross the plugin boundary. Studio mounts it by deep import, so it lands in Studio's own module graph, while a plugin resolves the bare `@nemo/common` specifier to public/vendor/common.js — a second copy with its own ToastContext. ConfirmationModal, DeleteConfirmationModal and LogViewer are all plugin API and all called useToast internally, so rendering any of them from a plugin threw "useToast must be used within a ToastProvider". Mounting the provider from the shared copy is not reachable: Studio's tsconfig maps only `@nemo/common/*`, and `@nemo/common` is in VENDOR_IMPORT_MAP but not VENDOR_EXTERNALS, so Studio never emits a bare import to externalize. Adding it would split Studio against itself — the provider in vendor, every deep-import useToast caller still bundled. Instead the three components take an optional onNotify. A new useNotify hook resolves the sink: onNotify first, then the surrounding ToastProvider, then a logger.warn and drop. It reads ToastContext with useContext rather than useToast, so an absent context is a supported state instead of a throw. PluginNotifications.notify also gains the toast options argument so durationMs survives the boundary rather than being silently dropped at it. Signed-off-by: mschwab <mschwab@nvidia.com>
WorkspaceSideNav concatenated plugin groups onto the core list, so a plugin whose navItems() returned group: 'Safety' rendered a second "Safety" header beneath Studio's rather than joining it. Plugin groups now accumulate by name and fold into the matching core group, using the existing isGroup guard so ungrouped top-level items are left alone. Groups matching nothing append in plugin order, and two plugins naming the same group merge into one. Signed-off-by: mschwab <mschwab@nvidia.com>
NavigationDrawer keys items by item.id and keys accordion state by it too. Merging plugin groups into core groups of the same name puts both sets of items in one array, so a plugin reusing a core id (say 'virtual-models') now produces duplicate React keys where it previously only collided in accordion state. Plugin ids are prefixed with the plugin name. Nothing else reads them — active state matches on href — so the prefix is confined to the two key sites. Also applies the review's import-type and explicit-props-interface nits on the lines this branch introduced. Signed-off-by: mschwab <mschwab@nvidia.com>
LogViewer now resolves its toast sink through useNotify, which imports ToastContext from the same module the test replaced wholesale. The mock returned only useToast, so every render in the file threw. The mocked success fn was never asserted, so the mock can go: with no provider, useNotify falls back to a logged warning instead of throwing. Signed-off-by: mschwab <mschwab@nvidia.com>
db5dcd8 to
441b2f8
Compare
Summary
Plugin bundles reach Studio's shared UI through the curated barrel in
common/src/plugin.ts(#1180), but most of the components Iron Swarm needs lived inweb/packages/studioand were unreachable. This moves them into@nemo/common, addshost.breadcrumbsto the plugin contract, and keeps the shared vendor bundle free of the SDK.Follow-up to #1180; prerequisite for moving the Iron Swarm UI out of Studio (#1037).
Related Issue
None.
Changes
Moved to
@nemo/common(viagit mv, so history follows) with their tests —AccessibleTitle,AccordionSection,ExpandableMessage,FileTag,InputErrorText,FileUpload,QuickActionsMenuRoot,ConfirmationModal,DeleteConfirmationModal,ErrorPanel,CancelJobButton, plusapi/common/utils,util/forms/errorandutil/logger. Studio's ~150 importers point at@nemo/commondirectly; no re-export shims.host.breadcrumbs— Studio's breadcrumb bar renders inGlobalNav, in the layout's navbar grid area, while a plugin renders in the content area several route levels below. A plugin cannot render it itself and can only write into the contextGlobalNavconsumes, so it's exposed on the host handle likenotifications. Studio clears the trail on plugin unmount and on:pluginNamechange.Three severs, so a shared library doesn't inherit Studio app config:
loggertakes its service name viaconfigureLogger(), called fromApp.tsxconstants/environment→featureFlagsintocommon;logVersionstays in Studio since it needsVERSION_SHACancelJobButtontakesworkspaceas a propuseWorkspaceFromPath; both call sites already had the valuegetErrorMessagemoved out ofNewDataDesignerJobForm/utilsWhat is deliberately not plugin API
Exporting
CreateSecretModal,fetchAgentsForSelect,getErrorMessage(the axios-aware one),CancelJobButtonorErrorPanelpulls the generated SDK client into the shared vendor bundle:vendor/common.jsNot just weight: plugins receive the SDK on
host.sdkso there is exactly one axios instance carrying Studio's OIDC interceptor. A second copy insidecommon.jswould issue unauthenticated requests against a differently-configured client. Those components still live incommonfor Studio's use; a plugin composes equivalents from the primitives the barrel does export, wired tohost.sdk.Barrel is 42 exports.
Type of Change
Quality Gates
plugins/example-plugin/web/AGENTS.md.Verification
Signed-off-by:traileruv run pre-commit runpasses, or any blocked checks are identified belowpnpm --filter @nemo/common typecheck/lintpnpm --filter @nemo/common testpnpm --filter nemo-studio-ui typecheck/lintpnpm --filter nemo-studio-ui testpnpm --filter nemo-studio-ui buildvendor/common.js339 kB, 42 exports, axios/oidc/zod absenttypecheck/builduv run pre-commit runAlso verified:
@nemo/commoncontains zero@studio/*imports, and no stale references to removed paths.Not verified in a browser. Green typecheck/lint/tests, but the promoted components have not been exercised in a running Studio.
Request NVSkills CIis failing for two reasons, one of which is not this PR: the gate requires a/nvskills-cicomment becauseplugins/changed, and the reusable workflow itself crashes withjq: Argument list too long(exit 2) on this PR's 216-file list — a bug inNVIDIA/skills/.github/workflows/team-request.yml@e0cd22dthat will hit any large PR touching a watched path.Follow-up
@nemo/common/src/...(its documented convention, ~144 pre-existing call sites). If a Studio-facing public barrel is wanted, it should be separate fromplugin.ts, which is plugin API with bundle consequences.host.sdk.agents— needed by the Iron Swarm move, sincefetchAgentsForSelectis not plugin API.Summary by CodeRabbit