Commit 2a25933
feat(ui): rewrite the web interface on Vite, and give conversations a first-class API (#2569)
---
*🤖 written by Claude (start)*
### Summary
Rebuilds the web interface on **Vite + React 19** — React Router, SWR,
antd 6, Emotion. It is a static bundle behind nginx with no server
process; settings come from `window.environmentVariables`, rewritten by
the container on every start, so one image serves every deployment.
The application API is reached over **gRPC-Web**:
`grpcserver.WebHandler` wraps the existing `*grpc.Server`, and the HTTP
server routes gRPC-Web requests to it ahead of its middleware chain.
> [!NOTE]
> **Reading the diff.** 616 of the 696 files are `ui/`, which is the
rewrite's tree — read it as a new app, not as a diff. The other 80 are
three things:
> - **`helm/`** — the UI pod stops running a Next.js server and becomes
nginx serving a static bundle, so `nginx.conf`, `supervisord.conf`,
`ui-deployment.yaml` and the UI values change together with their tests.
> - **`go/` and `proto/`** — the gRPC-Web seam (`grpcserver/grpcweb.go`,
`httpserver/server.go`, `app.go`) and the five `AgentInstance` changes
below, plus generated proto and sqlc output.
> - **`CLAUDE.md` and `.nvmrc`** — the repo guide's UI section, and the
pinned Node version.
### Testing this PR
One command builds a Kind cluster and installs **this checkout** on it —
controller, UI and agent runtime all built from the working tree, over
the chart's published images. It ends holding two port-forwards, the UI
on 8080 and the controller on 8083, so the last thing it prints is a
working URL and `cd ui && yarn dev` needs nothing configured.
```sh
./scripts/setup-cluster/setup-cluster.sh # ~25 min, mostly image builds
```
**http://localhost:8080**
> [!TIP]
> The script also leaves one agent on the cluster — an `assistant`
template on a `kagent` harness — so **Agents** has something in it and
you can send a message straight away, without creating anything first.
> [!WARNING]
> `make create-kind-cluster && make helm-install` does **not** work, and
fails silently five different ways — including that the chart installs
published images, so none of your changes are on the cluster while
everything looks healthy.
[`scripts/setup-cluster/README.md`](https://github.com/kagent-dev/kagent/blob/charlesthebird/uiRewrite/scripts/setup-cluster/README.md)
covers each one, and the dev-server loop for iterating.
### UI Extensions
The app declares vendor extension points anyone can use to add to it or
restyle it, all in one configuration object:
| Point | Contributes |
| --- | --- |
| `navItems` | Sidebar entries, positioned by `order` |
| `navOverrides` | Hide, rename, re-order or redirect the app's own
entries |
| `routes` | Whole pages, merged into the router |
| `routeHandles` | Shell data attached to the app's own routes |
| `slots` | Components at named points inside existing pages |
| `formFields` | Extra fields on existing forms |
| `tableColumns` | Extra columns on existing tables |
| `api` | Operation and endpoint overrides, payload transforms |
| `providers` | App-level React providers |
| `theme` | Colour, radius and font tokens |
| `shell` | Whole shell regions replaced outright |
| `branding` | Name and mark wherever the shell states its identity |
| `providerIcons` | Provider icons for the model-config form |
| `agentLinks` | Agent destinations |
Installing one is two edits: build a `VendorExtensionConfig`, then point
`src/vendorExtensions/activeConfig.ts` at it. Overriding theme tokens
restyles the app's own components, not just the extension's.
> [!NOTE]
> 📖
[`ui/docs/vendor-extensions.md`](https://github.com/kagent-dev/kagent/blob/charlesthebird/uiRewrite/ui/docs/vendor-extensions.md)
— every extension point and what it receives. Worth reading before
reviewing the `vendorExtensions/` tree.
### Substrate
The pages follow the CRDs. An **Agent** is derived, not a resource — a
`Harness` × `AgentTemplate` pair read from
`AgentTemplate.status.harnesses[]`, so there is no "New agent" button.
The landing page explains the four concepts over three tabs; an agent's
page lists its conversations, and a conversation is an `AgentInstance`.
Five additive server-side changes, none affecting an existing caller:
| Change | Note |
| --- | --- |
| `AgentInstance` gains a `name` | End to end, via
`UpdateAgentInstanceName`. A column, so the write touches only the
column. Renamed from the conversations table, the rail's action menu or
the details modal; the rail lists newest first. |
| `ListAgentInstances` takes a query | Narrows to one agent, resolved
through `prepared_revision`. |
| A2A gateway reads in any state | A suspended conversation still opens.
|
| A share resolves to its owner | The token widens what the reader's
account may read. |
| `app.go` defaults the A2A gateway | Used when no extension supplies
one; an extension's handler still wins. |
### Test Coverage
```sh
cd ui && yarn typecheck && yarn lint && yarn test && yarn test:pw
cd go && go test ./...
make proto-generate && make -C go sqlc-generate # then confirm `git status` is clean
```
385 unit tests. The browser suite runs in **Chromium and Firefox**, plus
a Chromium pass with the example extension installed, and in parallel in
CI.
### Follow Ups
- **The browser suite runs against the dev server, not the built image
and a real controller.** The `UI Playwright E2E` workflow that did that
is removed here, along with the harness it drove
(`playwright/scripts/setup.sh`, `playwright/mocks/server.mjs`);
restoring it is follow-up work. `yarn test:pw:live` covers a few
journeys against a real cluster in the meantime.
- **Storybook and the Chromatic workflow are removed**, since the
rewrite ships no stories.
-
[`ui/playwright/DEFERRED.md`](https://github.com/kagent-dev/kagent/blob/charlesthebird/uiRewrite/ui/playwright/DEFERRED.md)
lists the rest, and the surface each spec waits on. Nothing is committed
as a skipped test.
> [!NOTE]
> `go test ./...` fails one pre-existing test on macOS —
`TestFetchSourceReusesExistingMaterialization`, `/var` vs
`/private/var`, in a package this change does not touch.
### Upgrade Notes
> [!CAUTION]
> **Breaking.** The chart no longer sets `NEXT_PUBLIC_BACKEND_URL`,
`BACKEND_INTERNAL_URL` or `BACKEND_GRPC_URL`, and drops
`ui.backendInternalUrl`, `ui.backendGrpcUrl` and
`ui.volumes.nextjsCache`.
The oauth2-proxy `skip-auth-regex` now names `/assets/` and
`env-config.js` instead of the Next.js paths, which no longer exist.
**Also included, unrelated to the rewrite:** `helm/tools/grafana-mcp`
now passes `-allowed-hosts`. The server rejects any Host header it was
not told about, so one reached over the cluster network answered the MCP
handshake with `Forbidden` — the `RemoteMCPServer` sat `Accepted=False`
and every agent using it failed to build its tool set. Found while
testing the tools pages; happy to split it out if preferred.
---
*🤖 written by Claude (end)*
---------
Signed-off-by: Nicholas Bucher <behappy54321@gmail.com>
Signed-off-by: Eitan Yarmush <eitan.yarmush@solo.io>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-authored-by: Eitan Yarmush <eitan.yarmush@solo.io>1 parent 426a133 commit 2a25933
698 files changed
Lines changed: 66795 additions & 66505 deletions
File tree
- .github/workflows
- go
- api
- database
- gen/kagent/api/v1alpha1
- v1alpha3
- core
- cmd/controller-v2
- internal
- database
- gen
- queries
- grpcserver
- httpserver
- service/kubecrud
- pkg
- app
- auth
- migrations/core
- sandboxbackend/substrate
- v2
- a2agateway
- agentinstance
- translator
- kagent
- helm
- kagent
- files
- templates
- tests
- tools/grafana-mcp
- templates
- tests
- proto/kagent/api/v1alpha1
- python/packages/kagent-adk/src/kagent/adk
- scripts/setup-cluster
- ui
- .storybook
- mocks
- docs
- playwright
- fixtures
- helpers
- live
- helpers
- mocks
- scripts
- tests
- agent-templates
- agents
- auth
- chat
- extensions
- lists
- mcp-servers
- models
- onboarding
- prompt-libraries
- prompts
- substrate
- public
- scripts
- src
- api
- chat
- domain
- grpc
- hooks
- app
- a2a-sandboxes/[namespace]/[agentName]
- actions
- __tests__
- agents
- [namespace]/[name]/chat
- [chatId]
- new-harness
- new
- apps/[appName]
- login
- mcp
- new
- models
- new
- __tests__
- prompts
- [namespace]/[name]
- new
- substrate
- auth
- components
- Structure
- __tests__
- agent-form
- agent-instances
- agent-template-form
- agent
- branding
- chat
- __tests__
- common
- create
- __tests__
- dashboard
- icons
- layout
- mcp-apps
- mcp
- model-form
- models
- new
- onboarding
- steps
- prompts
- sidebars
- __tests__
- substrate
- table
- tools
- ui
- contexts
- __tests__
- generated/kagent/api/v1alpha1
- hooks
- lib
- __tests__
- grpc
- mocks
- pages
- agents
- router
- stories/pages
- theme
- types
- vendorExtensions
- api
- example
Some content is hidden
Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
358 | 358 | | |
359 | 359 | | |
360 | 360 | | |
361 | | - | |
362 | | - | |
363 | 361 | | |
364 | | - | |
365 | | - | |
| 362 | + | |
| 363 | + | |
| 364 | + | |
366 | 365 | | |
367 | 366 | | |
368 | 367 | | |
| 368 | + | |
| 369 | + | |
| 370 | + | |
| 371 | + | |
| 372 | + | |
| 373 | + | |
| 374 | + | |
369 | 375 | | |
370 | 376 | | |
371 | | - | |
| 377 | + | |
| 378 | + | |
| 379 | + | |
| 380 | + | |
| 381 | + | |
372 | 382 | | |
373 | 383 | | |
374 | 384 | | |
375 | | - | |
| 385 | + | |
376 | 386 | | |
377 | | - | |
| 387 | + | |
378 | 388 | | |
379 | | - | |
| 389 | + | |
380 | 390 | | |
381 | | - | |
| 391 | + | |
| 392 | + | |
| 393 | + | |
382 | 394 | | |
383 | | - | |
| 395 | + | |
384 | 396 | | |
385 | | - | |
| 397 | + | |
386 | 398 | | |
387 | | - | |
| 399 | + | |
388 | 400 | | |
389 | 401 | | |
390 | 402 | | |
| |||
This file was deleted.
This file was deleted.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
108 | 108 | | |
109 | 109 | | |
110 | 110 | | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
| 174 | + | |
| 175 | + | |
| 176 | + | |
| 177 | + | |
| 178 | + | |
| 179 | + | |
| 180 | + | |
| 181 | + | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
| 186 | + | |
| 187 | + | |
| 188 | + | |
| 189 | + | |
111 | 190 | | |
112 | 191 | | |
113 | 192 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
94 | 94 | | |
95 | 95 | | |
96 | 96 | | |
97 | | - | |
98 | 97 | | |
99 | 98 | | |
100 | 99 | | |
| |||
124 | 123 | | |
125 | 124 | | |
126 | 125 | | |
127 | | - | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
128 | 130 | | |
129 | 131 | | |
130 | 132 | | |
131 | 133 | | |
132 | 134 | | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
133 | 139 | | |
134 | 140 | | |
135 | 141 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
270 | 270 | | |
271 | 271 | | |
272 | 272 | | |
| 273 | + | |
| 274 | + | |
| 275 | + | |
| 276 | + | |
| 277 | + | |
| 278 | + | |
| 279 | + | |
| 280 | + | |
| 281 | + | |
| 282 | + | |
| 283 | + | |
| 284 | + | |
| 285 | + | |
| 286 | + | |
| 287 | + | |
| 288 | + | |
| 289 | + | |
| 290 | + | |
273 | 291 | | |
274 | 292 | | |
275 | 293 | | |
276 | 294 | | |
277 | | - | |
278 | 295 | | |
279 | 296 | | |
280 | 297 | | |
| 298 | + | |
| 299 | + | |
| 300 | + | |
| 301 | + | |
| 302 | + | |
| 303 | + | |
| 304 | + | |
281 | 305 | | |
282 | 306 | | |
283 | 307 | | |
| |||
0 commit comments