Commit graph

24 commits

Author SHA1 Message Date
devin-ai-integration[bot]
9a5e828310
feat(ui): inline Lens settings tab and investigation editor (#44479)
* feat(ui): move worker status into the Lens notch and New investigation into the list toolbar

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* feat(ui): make the Lens notch entry a settings gear that houses the worker section

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* feat(ui): replace the Lens worker modal with an inline Settings tab

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* feat(ui): section the Lens settings tab with tracing status and worker cards

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* fix(ui): let Lens settings sections span the full card width

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* feat(ui): replace the investigation setup modal with an inline side-by-side editor

New, edit, and duplicate now take over the Investigations tab body: matching
activity on the left, every setting on the right, with no wizard steps or modal

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* feat(ui): step the inline investigation setup vertically with traces alongside

Setup now sits on the left as three progressive steps (activity, criteria,
run) that collapse to a summary once done and reopen on click. Matching
activity stays on the right for every step. The editor gets a back control
and the Investigations notch shows a New, Editing, or Duplicate badge while
the editor is open

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* feat(ui): page the matching activity preview with useInfiniteQuery as it scrolls

Replace the Previous/Next offset buttons with the same infinite query and
near-tail prefetch the traces list uses, so the preview keeps loaded runs
and its title while the next page arrives

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* refactor(ui): make the investigation step field map exhaustive over the form schema

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* fix(ui): always show the Settings tab label in the Lens mode switch

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* refactor(ui): collapse Lens worker cards into compact status rows

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* fix(ui): keep the Lens Settings tab icon-only in every state

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* wip

* fix(ui): tick the Lens worker health dot so an expired heartbeat goes stale

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* refactor(ui): regroup Lens settings, model and api layers

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* refactor(ui): dedupe Lens formatting helpers

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* fix(ui): poll Lens once, drive the interval from data, settle mutations before invalidating

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* refactor(ui): let Lens leaves fetch their own data

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* refactor(ui): bind drawer and trace shortcuts through react-hotkeys-hook

One useShortcut hook replaces the three hand-rolled keydown listeners in SidePanel,
the trace step tree and the log drawer, with a layer option deciding which keys a
pane claims from the panel around it. The span tree footer now renders ShortcutHints
from what is actually bound instead of hand-typed kbd text.

* refactor(ui): extract Inspector from SidePanel

Inspector.Root owns the open item, J/K stepping, Escape and full screen;
Inspector.Row marks a list entry with aria-selected and data-state and toggles
it on click or Enter/Space; Inspector.Panel is the resizable side panel with the
exit animation and click-outside rules. The runs table and section compose these
parts directly, so RunDrawer and the SidePanel prop bag go away.

* refactor(ui): model the Lens worker screen as a tagged union and slot in its ready action

workerScreen() decides between list, form and install from the worker rows,
the registration result and the edit target, so WorkerSettings switches on
one value and each card owns its own copy. The post-install CTA is now a
ReactNode slot that LensWorkspace fills instead of an onReady callback
threaded through LensSettings and WorkerSettings. Clipboard copy state lives
in WorkerInstall as mutations, and the styled settings leaves export Props
types, set data-slot and accept native element props.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* refactor(ui): compose the Lens setup stepper from SetupStep children

Each step's heading, summary and fields now live together in one
SetupStep instead of four parallel structures keyed by index, and the
last-step spacing comes from CSS rather than a passed index. The mode
prop is now required since InvestigationsView always passes it.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* fix(ui): keep the Lens Settings panel mounted so a pending worker install survives tab switches

The settings TabsContent unmounted WorkerSettings whenever another tab was
active, dropping the one-time worker token shown during install. The panel
now uses keepMounted, and the workspace test registers a worker, switches
tabs and back, then follows the connected worker into the first
investigation through the slotted CTA.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* test(ui): cover the Lens worker install waiting-to-connected transition

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* refactor(ui): give the Lens activity preview a grouped contract and a structural debounce

useMatchingActivity now owns its return types (scope options, preview
status, page and optional manual selection) instead of borrowing them
from the components it feeds, and the preview takes those groups plus
the section attributes. The clear-selection action moves into the
preview footer, RunList becomes a RunRow leaf, and ScopeFields drops
the unused nameField and id props now that MetadataFilters calls useId
itself. The preview scope settles through a hashKey-based
useDebouncedValue instead of JSON round-tripping into state, and the
loading title follows isPlaceholderData since the query keeps previous
data. RunFields and AnalysisModelField take the analysis models and the
model gate as two objects instead of seven flat props.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* refactor(ui): select the Lens investigations screen with a pure tagged union

investigationScreen maps the list query and the route to one of loading,
failed, welcome, list, detail, setup or missing, so the view can switch
instead of juggling mutually exclusive booleans. The status model gains
activeJob, carries connected inside Readiness and folds the activity probe
into one ActivityCheck value for the welcome page

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* test(ui): cover the Lens preview footer clear action and the preview debounce

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* refactor(ui): let Lens investigation leaves own their URL slice and express intent

InvestigationsView renders the screen union and owns every write through
useInvestigationActions, so leaves receive on* handlers instead of the API
writer. useInvestigationResults becomes useRunSnapshot; FindingsTab,
HistoryTab, RunPicker and RequestEvidenceSheet read their own nuqs slice
and run their own queries. The finding sheet becomes an Inspector side
panel (FindingDetails) keyed per finding, with the trace and request
evidence sheets grouped in EvidenceSheets. WatchAllBanner owns its
mutation, the welcome page takes the readiness and activity values, the
progress sampler records on the wall clock outside render, and run
history invalidates when the list reports a scheduler-started job

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* test(ui): cover Lens investigation intents, pause, cancel, history refresh and the finding panel

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* fix(ui): keep the inspector open behind sheet overlays and mount HotkeysProvider from a client wrapper

* feat(ui): open Lens runs and evidence in the inspector panel

A quote's original trace step or logged request now stacks inside the finding
panel behind a back link, keeping the finding and its feedback draft mounted.
The detail Runs tab and the setup activity preview open runs in the same panel
with J/K stepping, so the TraceSheet and RequestEvidenceSheet modals are gone.
Picking a different finding or run clears any stacked evidence from the URL.

* feat(ui): open Lens investigations in the inspector panel beside the list

The investigations list stays on screen and a row opens its investigation in the
side panel, so J/K walk investigations and their open findings in display order
and the selected row carries the same highlight as runs. The panel body is the
former detail page; findings and runs opened inside it nest their own inspector,
which claims the keys from the one around it while open. Opening an investigation
and peeking at a finding now replace each other in the URL.

* fix(ui): run the Lens notch border along the tab pill and flag only a disconnected worker

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* fix(ui): show the shortcut hints in every inspector panel

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* refactor(ui): extract the Lens dot field into composable DotFieldRoot and DotFieldCanvas

Move the dot grid model and canvas painter out of TracesTimeline into
components/lens/dotField so other Lens surfaces can reuse it. The root
owns layout and context; overlays compose as children. agoLabel moves to
lens/model/format and the unused columnTop helper is dropped.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* refactor(ui): drop the manual refresh button from the runs time controls

Live polls and range changes refetch, so the button only cleared the zoom, which Escape already does

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* refactor(ui): extract the Lens run search into a composable SearchBox primitive

Move the query parser, glob matcher and autocomplete out of runSearch into
components/lens/search, generic over a QueryLanguage (field specs plus
what free text searches). SearchBox.Root owns the ProseMirror state, menu
and keyboard; SearchBox.Input and SearchBox.Suggestions compose under it.
Clause highlighting becomes a ProseMirror plugin built from the language.
RunSearch now only declares the run fields and composes the parts, so the
investigations tab can define its own language and reuse the same box.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* fix(ui): label the runs range by preset while Live and pin it once paused

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* refactor(ui): split the Lens search language from where its data lives

QueryLanguage is now pure vocabulary (keys, groups, icons). Reading
fields off loaded items moves to a ClientIndex consumed by a separate
evaluator, and value suggestions come from an injectable ValueSource, so
a server-backed runs list can plug in a facet lookup while the
investigations tab keeps filtering in memory. The parsed query serializes
to a typed SearchQuery (text terms plus eq/neq/glob/nglob filters) that
the client evaluator consumes today and a server can consume later. The
suggestion menu shows a loading row while a source is still answering.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* style(ui): format the Lens SearchBox and its test with the project prettier config

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* feat(ui): mirror the Lens run filters as trace SQL with a copyable curl in the search footer

The suggestions footer gains a slot, and SearchBox.ApiHint fills it with the
API equivalent of the typed query: a dialect chip, a one-line preview and a
Copy as curl button. The runs box translates each filter to a predicate over
the agent_traces_by_key rollup, bounded to the range the list shows, and
copies a POST to /v1/traces/query. Any other list can plug its own translate
into the same part.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* feat(ui): show the Lens introduction as a first-visit dialog with a typed don't-show-again

The guided setup no longer replaces the Lens tabs. It opens in a dialog on
the first visit of a session or from ?setup=lens, with a close and a
"Don't show this again" checkbox in its top-right corner. The header
"Set up Lens" button is gone. Dismissal state lives in a new schema-validated
web storage helper (src/lib/storage.ts) that reads through
useSyncExternalStore, so server renders see the fallback and other tabs stay
in sync; only Lens uses it for now.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* refactor(ui): keep only Copy as curl in the Lens run search footer

Drop the SQL chip and predicate preview; SearchBox.ApiHint becomes
SearchBox.CopyCommand, which takes the command for the current query.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* feat(ui): align the Lens investigations list with the traces list

Use the shared query SearchBox with investigation fields (name, agent, status, schedule), match the traces toolbar, and drop the count footer and inner padding.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* feat(ui): let Lens settings bring back the introduction after don't show again

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* refactor(ui): share one InspectorTable between the traces list and the Lens investigations tree

Compose TanStack Table, react-virtual and the shadcn table cells into InspectorTable parts (Root, Grid, Header, Body, Row, Indent). Investigations get findings as real sub-rows with TanStack expansion instead of a hand-rolled flattener.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* refactor(ui): break Lens import cycles and move shared pieces out of lens

Search and the dot field go to components/shared, run search and the preview
button go to view_logs where they are consumed. Lens api, services and demo
live under data/, all URL state in route.ts, storage keys in storage.ts, and
the session frame styles become cva variants.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* refactor(ui): one Lens readiness source and one onboarding flow

Readiness is computed once in model/readiness and read through
useLensReadiness, replacing useLensSetup, status.readiness and the welcome
screen's own checks. The Investigations welcome now renders the same
onboarding steps as the introduction dialog, with permissions and actions
coming from an OnboardingProvider instead of props passed down four levels.
StepIndicator and StateMessage are shared lens components, and the step
panels are labelled accordion regions.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* refactor(ui): read the Lens token from services and use semantic status colors

Lens services carry the access token they were built for, so trace evidence,
readiness and onboarding read it from context instead of a prop threaded
through six components. List and history invalidation lives in one data
hook. Status colors use the success, warning and destructive tokens, and
template-literal class names go through cn.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* refactor(ui): split Lens demo fixtures from the fake demo APIs

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* feat(ui): show Lens check history as a dot timeline

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* chores

* fix(ui): clear stale Lens evidence on run change and keep read-only users off Settings

Also names inline option objects to bring local/no-large-inline-object-arg back under budget.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Yujong Lee <yujong@berri.ai>
Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-04 07:20:14 +00:00
devin-ai-integration[bot]
5ddcc45b3a
feat(ui): share trace drawer as a closable SidePanel and polish Lens (#44473)
Some checks failed
Unit Tests: Proxy DB Operations / budgets (push) Blocked by required conditions
Unit Tests: Proxy DB Operations / custom-logging (push) Blocked by required conditions
Unit Tests: Proxy DB Operations / db-and-spend (push) Blocked by required conditions
Unit Tests: Proxy DB Operations / endpoints-and-responses (push) Blocked by required conditions
Unit Tests: Proxy DB Operations / guardrails-hooks (push) Blocked by required conditions
Unit Tests: Proxy DB Operations / jwt-and-keys (push) Blocked by required conditions
Unit Tests: Proxy DB Operations / key-generation (push) Blocked by required conditions
Unit Tests: Proxy DB Operations / logging-misc (push) Blocked by required conditions
Unit Tests: Proxy DB Operations / proxy-runtime (push) Blocked by required conditions
Unit Tests: Proxy DB Operations / proxy-server-core (push) Blocked by required conditions
Unit Tests: Proxy DB Operations / proxy-utils (push) Blocked by required conditions
Unit Tests / caching-local (push) Waiting to run
Unit Tests / core-utils (push) Waiting to run
Unit Tests / enterprise-package (push) Waiting to run
Unit Tests / enterprise-routing (push) Waiting to run
Unit Tests / integrations (push) Waiting to run
Unit Tests / All Other Providers (push) Waiting to run
Unit Tests / Vertex AI (push) Waiting to run
Unit Tests / mcp-integration (push) Waiting to run
Unit Tests / misc (push) Waiting to run
Unit Tests / proxy-auth (push) Waiting to run
Unit Tests / proxy-endpoints (push) Waiting to run
Unit Tests / proxy-extras (push) Waiting to run
Unit Tests / proxy-infra (push) Waiting to run
Unit Tests / proxy-infra-root (push) Waiting to run
Unit Tests / proxy-server (push) Waiting to run
Unit Tests / responses-caching-types (push) Waiting to run
GitHub Actions Security Analysis / zizmor (push) Waiting to run
Terraform Provider / gofmt, vet, build, test (push) Has been cancelled
Terraform Provider / Provider endpoints vs proxy OpenAPI schema (push) Has been cancelled
* feat(ui): extract trace drawer into a shared SidePanel that closes on outside press

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* feat(ui): center Lens mode switch in a notch joined to the content card

Larger Traces/Investigations switch, a subtle dot when an investigation is running or queued, and a bigger Lens title with a docs link.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(ui): stronger Lens frame border and header spacing

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(ui): align Lens notch fillet with the notch border

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(ui): centered Lens loading/error states and proxy JSON calls in dev

The dev server answered GET /lens with the Lens page HTML because the UI route shadowed the proxy fallback rewrite. JSON API requests now go to the proxy before page routes, and a non-JSON success body raises a readable ApiError.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* refactor(ui): theme-scale type and shape in trace views, aligned pane bars

Add local/no-arbitrary-design-value, scoped to TraceView and Lens, banning
arbitrary font size, tracking, leading, radius, border and CSS property
values. Map the Figma-export values onto the theme scale and replace hex
colors with info/destructive tokens.

Add PaneBar, a fixed-height bordered row, and build the step tree and span
detail headers from it so their borders line up across the split.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(ui): restore AgentTracesSection emptied in e7c3092571

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* feat(ui): move Set up tracing into the empty runs state

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* refactor(ui): let the runs table gate the setup CTA on an empty range

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* feat(ui): mark Lens demo mode with a blue toggle and frame instead of a banner

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(ui): draw Lens notch corners with CSS borders and thicken the demo frame

The SVG corner strokes did not snap to the same device pixels as the tab and
card borders, leaving a visible offset at the join.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* refactor(ui): drop the redundant Lens timeline header

The status, run counts, truncated agent legend and range span all repeated the Live toggle, runs table and range picker

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(ui): keep drawer shortcuts out of open menus and use usehooks-ts for timers and observers

SidePanel J/K/Esc now yields to menus and listboxes, not just dialogs.
The step tree shortcut footer wraps instead of clipping in narrow columns.
Replace hand-rolled timeout, keydown, media query and ResizeObserver effects
with usehooks-ts, and drop routine doc comments.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(ui): offer tracing setup when filters hide every run

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* feat(ui): replace Lens runs filters with a single ProseMirror query box

Agent and status dropdowns are gone. One query box (react-prosemirror) takes
free text plus key:value clauses (-key:value, key:*glob*) over name, agent,
status, model, input and trace_id, with field and value autocomplete. The
editor emits after a 150ms pause so typing no longer re-renders the runs view
per keystroke, and the URL keeps only q.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(ui): keep the open trace on screen while the next one loads

Switching to an unvisited trace remounted the panel and flashed a loading skeleton.
The drawer now keeps the previous trace visible, dimmed and inert, until the new one arrives.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* feat(ui): virtualize the Lens runs table and drop its status footer

The footer's run count only tracked how many pages had loaded and
"Updated just now" never changed, so it carried no signal. The zoom
clear button moves onto the timeline. Rows now render through
@tanstack/react-virtual so scrolling deep into a range stays cheap

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* refactor(ui): load traces with Suspense and show the previous run via useDeferredValue

Replaces keepPreviousData with the React pattern for showing stale content while fresh content loads.
Load failures go through an error boundary that retries the query on reset.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(ui): open investigation details from list rows instead of the edit dialog

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Yujong Lee <yujong@berri.ai>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 02:20:14 +00:00
yuneng-jiang
663e647bc8
refactor(ui): migrate antd Modal onto the shared shadcn Dialog (#37540)
* test(ui): cover the two modals no test would catch breaking

Both files sit in the antd Modal migration's blind spot. EditSSOSettingsModal's
test replaced antd wholesale with a stub Modal and asserted the stub's own
data-testid markup, so it proved nothing about the modal a user sees and would
have stayed green through any regression. routing_groups had no test at all.

Rewrite the first against the real antd Modal, querying by dialog role and
accessible name so the assertions hold under either library, and add an
integration test for the second that drives the row menu and the delete
confirmation end to end.

Modal width drops out of the SSO assertions: antd carries it as an inline style
and shadcn as a max-width class, so either form couples the test to the library
rather than to anything a user perceives.

* refactor(ui): move the straightforward antd Modals onto the shared Dialog

Twenty files whose Modal only used title, open, width, footer, className and
onCancel, so each one maps onto Dialog without judgement calls. Width becomes a
max-width class, the body gets the house scroll cap so tall content stays
reachable, and destroyOnHidden goes away because Base UI unmounts a closed
dialog on its own.

EditMembership needed a real fix rather than a translation. Clearing the form
after a submit resolved only ever worked by accident: the reset set every field
to undefined, which react-hook-form does not push out to a subscribed
Controller, and the fields looked cleared only because antd's Modal happened to
re-render the subtree afterwards. Dialog does not, so the stale values showed
through. emptyMemberFormValues now returns the empty value each control
actually understands, an empty string, null or an empty list, and the reset
lands whatever renders around it. Its test asserted the undefined shape while
describing the behaviour it was missing, so it now checks the values instead.

* refactor(ui): migrate the antd Modals that needed a judgement call

Sixteen more files. Most carried a prop that does not translate literally:
maskClosable becomes disablePointerDismissal, afterOpenChange becomes
onOpenChangeComplete, and closable={false} becomes showCloseButton={false}.

The styles prop went away everywhere it appeared. All but one instance set the
body to 24px and the header to 24px with no border, which is what DialogContent
already renders, so keeping it would have meant writing the default back by
hand.

Several Modals passed onOk alongside footer={null}, so antd rendered no OK
button and the handler could never fire. Each of those handlers was a
character-for-character copy of the neighbouring onCancel, so they are gone
rather than translated.

Rich titles now sit inside DialogHeader with DialogTitle carrying the heading
text, instead of the whole header block being nested inside DialogTitle. That
had put an h2 inside another h2, which is invalid and gave one dialog two
headings.

UserEnvVarsModal loses its formGeneration counter. Remounting the form when the
modal finished opening only mattered because antd kept a closed modal's
children mounted; Base UI unmounts them, so reopening is blank on its own. Its
test helper had encoded that remount as a timing assumption, so the file now
states the requirement outright and checks that reopening shows an empty field.

CreateMCPServer's cancel test read the tool list while the modal was closed,
which only worked because forceRender kept it mounted. It now asserts what a
user can actually observe: the panel is gone while closed, and reopening brings
back an empty URL and no tools.

Unmounting an open Base UI dialog leaves its scroll lock on <html> and <body>,
which survives cleanup() and makes every later test in the file see a locked
page where popups compute pointer-events: none and clicks quietly do nothing.
The shared setup now releases it.

* refactor(ui): finish the antd Modal migration onto the shared Dialog

Fifteen files whose Modal relied on antd's built-in footer. okText, cancelText,
onOk, okButtonProps, cancelButtonProps and confirmLoading collapse into two
explicit buttons in a DialogFooter, with danger becoming the destructive
variant and the various loading flags becoming disabled plus aria-busy. The one
okButtonProps that also hand-set a red background drops it, since the variant
already carries that.

add_guardrail_form keeps its own chrome, so its DialogContent turns off the
built-in close button and the padding, and its heading becomes the DialogTitle.
Under antd it passed title={null} and had no accessible name at all.

Modals that positioned themselves near the top of the viewport needed
translate-y-0 alongside top-8, because DialogContent centres itself with a
transform that top alone does not undo.

TeamGuardrailsTab's test reached its Mode select by index into every combobox on
the page. A modal dialog hides the rest of the page from assistive technology,
which antd never did, so the count changed and the index pointed at the wrong
control. It asks for the field by label now.

The mask-dismissal test drove antd's .ant-modal-wrap class directly; it uses the
overlay slot our own component exposes, and still fails if
disablePointerDismissal is dropped.

CreateUserButton stays on antd. Its Modal converts cleanly, but the colocated
test file then fails a varying handful of cases, and the cause sits in the test
file rather than the component, so it wants its own change.

Pruning suppressions for the touched files also cleared four
react-hooks/set-state-in-effect entries on CreateMCPServer that were already
stale before this branch.

* test(ui): pick Base UI select options through the shared helper

React 19's flush timing loses the race this test was relying on: the option
lands in the DOM one render before its positioner drops pointer-events: none,
so user-event refused the click. tests/test-utils already exports
chooseSelectOption for exactly this, added alongside the React 19 upgrade.
2026-08-19 23:16:42 +00:00
ryan-crabbe-berri
f1e143a87c
chore(ui): upgrade the dashboard to React 19 (#37411)
* chore(ui): upgrade the dashboard to React 19

Bumps react and react-dom from 18.3.1 to 19.2.8 with matching @types. Next 16 already required a React 19 peer, so this aligns the dashboard with what the framework expects and unblocks Base UI and shadcn work that assumes the React 19 ref model.

React 19 passes ref through as a regular prop, so the setup file's forwardRef tripwire and the ref-forwarding test's forwardRef case no longer describe real behavior; both now assert the React 19 contract instead. useRef<T>(null) now yields RefObject<T | null>, which is the one prop type MessageList had to widen.

* test(ui): wait for a Base UI select popup to open before clicking an option

The option lands in the DOM one render before the popup finishes entering, while its positioner still carries pointer-events: none, so clicking it throws. Waiting on the option's text alone was a race that React 19's flush timing loses, which is why four ToolPolicies cases went red on the bump.

chooseSelectOption in test-utils opens the trigger, finds the option by role, waits for it to stop being pointer-blocked, then clicks. It also replaces the last-match-by-text hack, which only worked because the popup happens to portal after the table.
2026-08-19 21:18:08 +00:00
ryan-crabbe-berri
bb8324c119
refactor(ui): drop @tremor/react and the theming scaffolding it needed (#37394)
The last tremor component import left the dashboard when the primitive
sweep merged, so the package, its v3 compatibility shim, its @theme token
block and the palette safelist it needed at runtime all have no consumer.

Removing the safelist is what shrinks the shipped stylesheet: tremor built
class names at runtime, so Tailwind had to emit every bg/text/border/ring/
stroke/fill utility across 22 palettes and 11 shades in case one was used.
Nothing in the app constructs a class name that way any more, so the
scanner finds every utility on its own.

The date-fns overrides pin also goes. It only existed because tremor and
react-day-picker@8 peered on date-fns 3 while Base UI wanted 4, and the
lockfile still resolves a single hoisted 4.4.0 without it.
2026-08-18 17:38:12 -07:00
ryan-crabbe-berri
087d82ffca
refactor(ui): move the model info view and pass-through endpoint forms off tremor (#37308)
* refactor(ui): move the model info view and pass-through endpoint forms off tremor

The pass-through settings form's Save button relied on tremor's implicit
submit, so it now carries an explicit type="submit" because the Base UI
button defaults to type="button". The include-subpath switch inside the
antd Form.Item is wired through onCheckedChange plus form.setFieldsValue,
since the Base UI switch does not read the onChange antd injects. Both
tab strips keep every panel mounted so the edit forms survive a tab
switch, pinned by a new mount-contract test on the model info view. Also
prunes the six tremor no-restricted-imports suppressions these files no
longer need.

* test(ui): pin the model info overview panel to its own dom node across tab switches

* fix(ui): keep the line tab strip on the model info and pass-through views

Both tab strips were bare tremor TabLists, which defaulted to the line
variant, so the straight rename turned them into filled segmented pills.
They now use the same full-width line strip the agent, guardrail and
prompt info views ship.
2026-08-18 23:19:23 +00:00
ryan-crabbe-berri
83ae623733
refactor(ui): codemod every toast call site onto lib/toast and delete the antd-era facades (#37253)
MessageManager and NotificationManager were thin facades over lib/toast since #37207. This
rewrites their ~750 call sites (226 files) to import { toast } from @/lib/toast directly:
success/info/warning/error keep their names, fromBackend becomes fromError, destroy/clear
become dismiss. The one config-object caller (CreateMCPServer's admin-review branch) becomes
an explicit toast.success(message, { description }). Behaviour is unchanged: no production
caller passed a duration, so every toast keeps the same kind, title and default duration.

Tests: the global vitest mock now targets @/lib/toast (toast.test.ts opts back out with
vi.unmock), so the per-file vi.mock boilerplate for the facades is deleted and assertions read
toast.success / toast.fromError. The two facade files, their test and their filename-case
suppressions are removed, along with the commented-out facade calls left in networking.tsx
2026-08-18 18:24:49 +00:00
Yuneng Jiang
a6b9cedd03
refactor(ui): inject the fetch client's base url instead of reading it at import
api.ts read globalThis.location when the module loaded, which froze the base
URL at import and pinned its test file to jsdom. The creation-time baseUrl and
the middleware's runtime rebase were also two mechanisms doing overlapping
work, and the rebase hand-copied eleven RequestInit fields on every call.

Pass openapi-fetch's Request option instead, so the constructor applies
whatever getRequestBaseUrl() returns at the moment the request is built.
registerBaseUrlGetter is now the single source of the base URL, rebaseUrl and
rebaseRequest are deleted, and the request is constructed once, so the init
openapi-fetch assembled reaches the platform Request untouched. The abort
signal is no longer copied by hand.

This preserves behaviour rather than approximating it: getProxyBaseUrl() falls
back to location.origin, so the runtime base was never empty in a browser and
the old middleware already rebased every request, discarding the creation-time
value each time.

setupTests.ts gates its DOM-only tail behind a window check; setup files run
for every environment, so that tail previously stopped any node-environment
test file from loading.

api.test.ts now runs under @vitest-environment node with its assertions intact
and no location stub, plus regressions for per-call base resolution and abort
forwarding. api.sameOrigin.test.ts covers the browser fallback to the page
origin, which needs a DOM environment.
2026-08-04 12:07:45 -07:00
ryan-crabbe-berri
592510ec18
feat(ui): shadcn charts foundation with tremor-compatible wrappers (#32668) 2026-07-09 18:18:52 -07:00
ryan-crabbe-berri
7d63b86e00
fix(ui): forward refs through ui primitives and fail tests on swallowed refs (#32401)
* fix(ui): forward refs through ui primitives and fail tests on swallowed refs

Under React 18 a ref passed to a plain function component is dropped
with only a dev console warning, so Base UI render-prop triggers
composed over our shadcn-style primitives silently stop working (the
tooltip just never opens; ui/badge.tsx hit exactly this on the shared
DataTable branch). Label, Separator, Skeleton, UiLoadingSpinner and the
Table family now use React.forwardRef like Button and Input already
did, a contract test pins ref delivery for each, and setupTests turns
React's ref warning into a test failure so the next primitive that
swallows a ref fails CI instead of shipping a dead tooltip

* fix(ui): include captured ref warnings in the tripwire error

The afterEach tripwire threw a fixed message and discarded the collected
React warnings, so a failure never said which component swallowed the ref.
Append the captured warnings (component name + stack) to the thrown error.
2026-07-09 11:59:16 -07:00
user
e96d850b84 chore(deps): address dependency review notes 2026-05-04 12:09:04 -07:00
user
bfdd786962 chore(deps): refresh dependency locks 2026-05-04 11:36:18 -07:00
yuneng-jiang
f3c6915d61 feat: add useChatHistory hook with tests (extracted from ChatUI)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 18:09:20 -07:00
yuneng-jiang
2285dc78b9 [Fix] UI - resolve flaky tests from leaked @tremor/react Tooltip timer
Local vi.mock("@tremor/react") overrides in router_settings tests were
clobbering the global setupTests.ts mock, re-introducing the real Tooltip
component which schedules a setTimeout. When jsdom tears down after each
test file, the pending timer fires and hits window is not defined, which
Vitest flags as an unhandled error that can cause false positive failures
in subsequent tests (including the create_mcp_server timeout in CI).

Fix: add Switch to the global @tremor/react mock in setupTests.ts (the
only reason the local overrides existed), then remove the three local
vi.mock("@tremor/react") blocks so all test files inherit the global mock
with properly stubbed Button, Tooltip, and Switch.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-28 10:28:27 -08:00
yuneng-jiang
825503fa1b Refactor react-query hooks 2025-12-24 10:13:55 -08:00
yuneng-jiang
805a8f0d9f Loading states for Edit Membership modal 2025-12-06 15:27:47 -08:00
Ishaan Jaffer
c6b8f19adc ui unit tests fix 2025-11-22 14:05:59 -08:00
yuneng-jiang
7b9c409760
Mock tremor's tooltip to fix flaky tests (#16786) 2025-11-18 17:40:50 -08:00
yuneng-jiang
54425eb57b
Fix flaky tests due to antd Notification Manager (#16740) 2025-11-17 19:47:20 -08:00
yuneng-jiang
4de182c98f
[Feature] UI - Organization Usage in Usage Tab (#16614)
* Organization Usage UI

* Resolved build issues

* Added a test
2025-11-15 16:23:48 -08:00
yuneng-jiang
c5496fd61c
[Feature] UI - Move Budgets out of Experimental (#16544)
* Move budget out of experimental and delete budget with friction

* Fixed tests

* Revert non test change
2025-11-12 13:27:02 -08:00
yuneng-jiang
dd053e1d12
[Feature] UI - Add tags in model creation (#16138)
* Add tags in model creation

* Removing unused import in test
2025-10-31 16:26:30 -07:00
=
5197268a58 added and ran prettier autoformatter 2025-10-04 18:19:48 -07:00
=
f80660acd9 vitests for GuardrailViewer components 2025-09-18 16:57:22 -07:00