https://github.com/zenml-io/kitaru-ui
UI interface for Kitaru - durable execution for AI agents, built on ZenML
https://github.com/zenml-io/kitaru-ui
agent-framework ai-agents checkpoints durable-execution llm mcp mlops observability pydantic pydantic-ai react replay typescript workflow-orchestration
Last synced: 1 day ago
JSON representation
UI interface for Kitaru - durable execution for AI agents, built on ZenML
- Host: GitHub
- URL: https://github.com/zenml-io/kitaru-ui
- Owner: zenml-io
- License: apache-2.0
- Created: 2026-03-05T14:32:53.000Z (about 1 month ago)
- Default Branch: main
- Last Pushed: 2026-04-14T14:59:58.000Z (3 days ago)
- Last Synced: 2026-04-14T16:32:10.481Z (3 days ago)
- Topics: agent-framework, ai-agents, checkpoints, durable-execution, llm, mcp, mlops, observability, pydantic, pydantic-ai, react, replay, typescript, workflow-orchestration
- Language: TypeScript
- Homepage: https://kitaru.ai/
- Size: 846 KB
- Stars: 2
- Watchers: 1
- Forks: 1
- Open Issues: 19
-
Metadata Files:
- Readme: README.md
- License: LICENSE
- Agents: AGENTS.md
Awesome Lists containing this project
README
# Kitaru UI
Kitaru UI is the web dashboard for [Kitaru](https://kitaru.ai) — a durable agent infrastructure framework for Python that enables reliable agent execution with built-in crash recovery, human-in-the-loop approval, and cost tracking. It is a single-page application built with React 19 and Vite.
## Current Scope
The app currently supports:
- **Server activation** — first-run setup flow when the ZenML server has not yet been activated
- **Login / session management** — cookie-based authentication with the ZenML backend
- **Private area shell** — authenticated layout with a placeholder home page
## Tech Stack
| Layer | Tool |
| --------------- | -------------------------------------------------------------------------------- |
| Framework | Vite 7 + React 19 (SPA) |
| Routing | [@tanstack/react-router](https://tanstack.com/router) (file-based, code-split) |
| Server state | [@tanstack/react-query](https://tanstack.com/query) |
| Forms | React Hook Form + Zod |
| Styling | Tailwind CSS v4 (via `@tailwindcss/vite`) |
| UI primitives | [Base UI](https://base-ui.com/) + [class-variance-authority](https://cva.style/) |
| Icons | [lucide-react](https://lucide.dev/) |
| Notifications | [Sonner](https://sonner.emilkowal.dev/) |
| Theming | next-themes |
| Type generation | openapi-typescript (from ZenML server OpenAPI spec) |
| Testing | Vitest |
| Compiler | React Compiler (via Babel plugin) |
## Local Development
### Prerequisites
- Node.js (LTS)
- [pnpm](https://pnpm.io/)
- A running ZenML server (default: `http://localhost:8237`)
### Setup
```bash
# Install dependencies
pnpm install
# Copy environment config
cp .env.example .env
# Start dev server (default: http://localhost:5173)
pnpm dev
```
By default, the app sends requests to relative paths (for example `/api/v1/current-user`). In local development, the Vite dev server proxies `/api` requests to `VITE_BACKEND_URL`, so the frontend and backend appear on the same origin.
### Environment Variables
| Variable | Default | Description |
| ------------------- | ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ |
| `VITE_BACKEND_URL` | `http://localhost:8237` | ZenML server URL used by the Vite dev proxy |
| `VITE_API_BASE_URL` | _(unset)_ | Optional API origin override (build-time). If set (for example `https://backend.test.com`), requests are sent to `/api/v1/...` directly. |
### Scripts
```bash
pnpm dev # Start development server
pnpm build # Type-check and build for production
pnpm preview # Preview the production build locally
pnpm lint # Run ESLint
pnpm format # Format code with Prettier
pnpm test:unit # Run unit tests (Vitest)
pnpm generate:types # Generate OpenAPI types: pnpm generate:types --
```
### Pre-commit Hooks
The repo uses [Lefthook](https://github.com/evilmartians/lefthook) for pre-commit hooks that auto-fix ESLint issues and format staged files with Prettier.
## Architecture
### Project Structure
The frontend architecture is module-based under `src/modules/`.
```
src/
modules/
root/ Root Module bootstrap and app-global resources
/
domain/ Types and actual API/request functions
business-logic/ TanStack Query definitions and module logic
feature/ Stateful containers and entrypoints
util/ Module-scoped utilities
ui/ Stateless presentational components
routes/ File-based TanStack Router route definitions
shared/
api/domain/ Transport layer (apiClient, paths, errors)
api/utils/ URL builders, error helpers
router/utils/ Router-specific shared helpers
ui/ Reusable UI primitives (Base UI-based)
utils/ Shared utilities (styles, page titles)
assets/ Icons, images (importable as React components via SVGR)
```
### Module Layers
- `domain/` contains module-owned types and the actual request functions that talk to the backend.
- `business-logic/` contains TanStack Query definitions and other module-specific logic.
- `feature/` contains stateful containers, orchestration, and module entrypoints.
- `util/` contains small module-scoped helpers.
- `ui/` contains stateless, dumb UI components.
### Generated Files
These files are auto-generated and should not be hand-edited:
- `src/routeTree.gen.ts` — generated by TanStack Router plugin from `src/routes/`
- `src/shared/api/types.ts` — generated by `pnpm generate:types` from the ZenML OpenAPI spec
Both are excluded from ESLint.
### App Boot Sequence
1. `src/main.tsx` creates the router with the generated route tree and injects a shared `queryClient`
2. Root route (`__root.tsx`) fetches server info — if the server is inactive, redirects to `/activate-server`
3. Private route (`_private.tsx`) ensures the current user is loaded before rendering children
4. If any query returns a 401, a global `QueryCache` error handler redirects to `/login`
### Data Fetching
- **Request functions** live in `domain/` and handle transport and response parsing.
- **Query keys and query collections** live in `business-logic/` and are built with `queryOptions(...)` or `infiniteQueryOptions(...)`.
- **Read APIs** should prefer grouped exports such as `deviceQueryKeys` and `deviceQueries` instead of standalone exported fetcher-query helpers.
- **Route loaders** call `context.queryClient.ensureQueryData(...)` to preload data
- **Mutations** are exposed from `business-logic/` as `mutationOptions(...)` factories, while their underlying request functions stay in `domain/`
- **Components** call `useMutation(...)` directly with mutation options
- Global 401 handling lives in the `QueryCache` error callback (`query-client.ts`)
### Authentication
- `apiClient` sends all requests with `credentials: "include"` (cookie auth)
- By default requests are relative (`/api/v1/...`); optionally set `VITE_API_BASE_URL` to target a full backend origin
- Vite proxies `/api` to `VITE_BACKEND_URL` in development
- Login uses `application/x-www-form-urlencoded` content type (exception to the default JSON headers)
## CI
GitHub Actions (`.github/workflows/build-validation.yml`) runs on push to `main` and on all PRs:
1. `pnpm install --frozen-lockfile`
2. `pnpm lint`
3. `pnpm build`
4. `pnpm test:unit`
## Contributing
See [AGENTS.md](./AGENTS.md) for the full coding conventions, naming rules, data fetching patterns, and architectural guidance used by coding agents and contributors.