fix: improvements

This commit is contained in:
2026-03-28 22:20:19 +01:00
parent cbd8f1568b
commit 223336c606
10 changed files with 506 additions and 249 deletions

View File

@@ -2,104 +2,215 @@
## 1. Executive Summary
This document provides a high-level overview of the ZUI application's architecture, focusing on component organization, data flow, technology stack, and contribution guidelines for junior developers and AI agents.
Zui is a node-based visual editor for composing configs, templates, variables, and AI-generated content. The frontend is a React 18 SPA backed by a thin Express API for AI agent calls. All graph data is persisted in `localStorage`; the backend is stateless.
---
## 2. Technology Stack
- **Frontend**: React 18, TypeScript, Vite, Tailwind CSS, Shadcn UI, Zustand (canvasStore), custom hooks, and canvas rendering engine.
- **Backend**: Node.js 18, TypeScript, Express-like routing, Docker, and environment variable configuration.
- **Database/Storage**: In-memory state management with optional persistence via cacheRepository.
- **Testing**: Vitest, React Testing Library, and Jest-like utilities.
| Layer | Technology |
| --- | --- |
| Frontend framework | React 18, TypeScript (strict), Vite 7 |
| Graph canvas | `@xyflow/react` v12 (React Flow) |
| State management | Zustand 5 (command/reducer pattern) |
| Styling | Tailwind CSS + Shadcn UI (`@radix-ui/*`) |
| Rich text | BlockNote 0.36 with custom blocks |
| Templating | Nunjucks |
| Graph traversal | `graphology` + `graphology-traversal` |
| Routing | React Router v6 |
| Backend | Node.js 20+, TypeScript, Express 4 |
| AI SDK | Vercel AI SDK v4 + `@ai-sdk/openai` |
| Testing | Vitest, React Testing Library |
## 3. High-Level Structure
---
The workspace is divided into two primary directories:
## 3. Project Structure
- **frontend/**: Contains the React application, component library, pages, and styling.
- **backend/**: Contains server-side code, services, repositories, models, and middleware.
```text
frontend/src/
├── main.tsx # Entry: registers node types & config types, mounts app
├── app/
│ ├── canvas/ # CanvasPage, canvasStore (Zustand), canvasStore.test.ts
│ ├── kosmos/ # KosmosPage, sidebar, AI settings, KosmosContext
│ └── recollections/
│ ├── RecollectionsPage # Workspace list
│ ├── RecollectionLayout # Shared layout (sidebar + outlet)
│ ├── flux/ # Flux view (graph canvas)
│ ├── logos/ # Logos view (BlockNote rich text)
│ └── katalogos/ # Katalogos view (artifact gallery)
├── components/
│ ├── graph/ # AnimatedEdge, BaseNode, handles, keyboard shortcuts
│ ├── nodes/ # One folder per node type
│ └── ui/ # Shadcn primitives
├── hooks/ # useGraphStateWithHistory, useResizeHeight, …
└── lib/
└── graph/
├── nodeRegistry.ts # Mutable plugin registry
├── registerBuiltinNodes.tsx
├── nodeTypeBuilder.ts # Fluent builder for node descriptors
├── configTypes.ts # Output type registry (plantuml, markdown, wireframe)
├── rendering.ts # 3-step rendering pipeline contract
├── state.ts # Graph state types
└── canvasStore/ # Reducer + selectors
### 3.1 Frontend Modules
backend/src/
├── index.ts # Express app, CORS, routes, error handler
├── routes/agentRoutes.ts # POST /api/agent, POST /api/agent/stream
├── services/agentService.ts # LLM call logic (Vercel AI SDK)
├── repositories/cacheRepository.ts
├── models/index.ts
└── middleware/rateLimiter.ts
```
| Module | Purpose | Key Files |
|--------|---------|-----------|
| **canvas** | Core graph/canvas rendering, nodes, edges, and interactive graph features. | `src/app/canvas/*`, `src/components/graph/*`, `src/components/nodes/*` |
| **recollections** | Collection management, browsing, editing, and related UI. | `src/app/recollections/*`, `src/components/ui/*` |
| **kosmos** | Knowledge organization system, settings, and user preferences. | `src/app/kosmos/*` |
| **layout** | Layout and navigation components shared across pages. | `src/app/recollections/layout/*` |
| **components** | Reusable UI components (buttons, dialogs, avatars, etc.). | `src/components/ui/*` |
| **hooks** | Custom React hooks for state, effects, and utilities. | `src/hooks/*` |
| **lib** | Shared utilities, types, and low-level helpers. | `src/lib/*` |
---
### 3.2 Backend Modules
## 4. Key Architectural Patterns
| Module | Purpose | Key Files |
|--------|---------|-----------|
| **services** | Business logic, external API interactions, and complex computations. | `backend/src/services/*` |
| **repositories** | Data access abstraction, caching, and persistence. | `backend/src/repositories/*` |
| **models** | TypeScript interfaces and type definitions for domain objects. | `backend/src/models/*` |
| **routes** | HTTP route definitions and controllers. | `backend/src/routes/*` |
| **middleware** | Request processing pipeline (e.g., rate limiting, authentication). | `backend/src/middleware/*` |
| **index.ts** | Application entry point that composes services, routes, and middleware. | `backend/src/index.ts` |
### 4.1 Command / Reducer Store (canvasStore)
## 4. Data Flow
The Zustand canvas store uses a pure reducer (`canvasStoreReducer`) with a discriminated union of `CanvasCommand` types. All mutations go through `dispatch(command)`. In dev mode every command is logged to the console.
1. **User Interaction** (React components) → dispatches actions → updates local state (Zustand) → triggers re-render.
2. **State Changes** may trigger async calls to **services** (frontend) → which call **backend APIs** → responses are cached via **cacheRepository**.
3. **Backend** processes requests via **routes**, applies **middleware**, interacts with **repositories** and **models**, and returns JSON responses.
4. **Caching** layer reduces repeated expensive computations or DB queries, improving performance.
The store has three slices:
## 5. Component Interaction Patterns
- **`graph`** — nodes and edges (the React Flow state)
- **`path`** — trigger pulse for edge animation
- **`ui`** — renaming state, fullscreen node, pending connection
- **Container Components** (e.g., `CanvasPage`, `RecollectionPage`) manage layout and state provision.
- **Presentational Components** (e.g., `TreeBrowser`, `AgentNode`) focus on UI rendering only.
- **Custom Hooks** encapsulate logic (e.g., `useResizeHeight`, `useStreamingContent`) and are reused across components.
- **Context Providers** (`KosmosContext`, `RecollectionSidebarContext`) supply global state to deeply nested component trees.
### 4.2 Delta-based Undo / Redo
## 6. Extensibility & Plugin Architecture
`useGraphStateWithHistory` computes *inverse deltas* (only the nodes/edges that changed) rather than snapshotting the full graph. Maximum 100 history entries. Drag operations commit a pre-drag snapshot on `onNodeDragStop`.
- **Node Types** are registered via `nodeRegistry.ts` and extended through descriptor files.
- **New node types** can be added by creating a descriptor, implementing rendering logic, and registering it in `registerBuiltinNodes.tsx`.
- **Extensibility points** are documented in `NODE_TYPE_EXTENSIBILITY_PROPOSAL.md`.
### 4.3 Node Plugin Registry
## 7. Performance Considerations
Node types are registered via a mutable registry in `nodeRegistry.ts`. The built-ins are registered at app init from `registerBuiltinNodes.tsx`. Adding a new node type requires:
- **Large Render Trees**: `CanvasPage` and `RecollectionPage` handle thousands of nodes; memoization (`useMemo`, `useCallback`) and lazy loading are essential.
- **State Updates**: Prefer granular state updates in `canvasStore` to avoid full tree re-renders.
- **Code Splitting**: Dynamic imports are used for heavy modules (e.g., rendering views, graph utilities).
1. Implement a React component for the node.
2. Create a descriptor using `NodeTypeBuilder`.
3. Call `registerNodeType(descriptor)` — no edits to core code.
## 8. Contribution Workflow
### 4.4 Fluent Builder for Node Descriptors
1. Fork the repository and clone the workspace.
2. Install dependencies: `pnpm install` (or `npm ci`).
3. Run the dev server: `pnpm dev` (frontend) and `pnpm start` (backend).
`NodeTypeBuilder` provides a type-safe method-chaining API (`idPrefix`, `withInputOutput`, `classification`, `allowedSourceTypes`, `help`, `menu`, `withFullscreen`, `sourceRenderingLogic`, …). Required fields are validated at `.build()`.
### 4.5 Three-Step Rendering Pipeline
Defined as an explicit contract in `rendering.ts`:
1. **Resolve** — source node (Config/Agent) produces `{ resolved, outputTypeId, reasoning? }`
2. **Render** — output type handler converts the resolved string (PlantUML → Kroki SVG, Markdown → HTML, Wireframe → SVG)
3. **Display** — the Rendering node shows an image viewport or scrollable HTML
### 4.6 Node Classification System
Four metaphorical classes drive the create menu grouping:
| Class | Node type | Metaphor |
| --- | --- | --- |
| `psyche` | Variable | source / input |
| `physis` | Data (CSV) | physical data |
| `pneuma` | Config / Render | transformation |
| `archon` | Agent | AI / LLM |
### 4.7 Recollections (Workspaces)
Each workspace (recollection) is stored in `localStorage`:
| Key | Content |
| --- | --- |
| `zui_platform_recollections` | Metadata index (id, name, icon, timestamps) |
| `zui_graph_<id>` | Flux graph (nodes + edges) |
| `zui_logos_<id>` | BlockNote rich text document |
| `zui_render_cache_<id>` | Rendered artifact cache |
Legacy key prefix `emanations` is migrated to `recollections` on first load.
### 4.8 User-configurable AI Connection
`KosmosContext` persists `aiConnection` (provider, baseURL, model, apiKey) in `localStorage` under `zui_ai_connection`. The Agent node forwards this to the backend with each request, so users can switch between OpenAI and local LLMs (LM Studio, Ollama) from the UI without env variable changes.
### 4.9 Diagram Rendering via Kroki
PlantUML diagrams are rendered by proxying to `https://kroki.io` via `/api/kroki/plantuml/svg`. This proxy is configured in both the Vite dev server and Nginx production config. Timeout: 15 seconds.
---
## 5. Data Flow
```text
User interaction
→ dispatch(CanvasCommand) [canvasStore reducer]
→ Zustand state update [graph / path / ui slices]
→ React re-render [React Flow nodes/edges]
Rendering node triggered
→ Resolve source node [Config/Agent → resolved string]
→ Render output type [plantuml/markdown/wireframe]
→ Kroki proxy (PlantUML) [GET /api/kroki/plantuml/svg]
→ Agent backend (AI) [POST /api/agent or /api/agent/stream]
→ Display artifact [image / HTML / SVG viewport]
Agent node (streaming)
→ POST /api/agent/stream [Express → agentService]
→ Vercel AI SDK streams SSE [backend → frontend]
→ useStreamingContent hook consumes [updates node data]
```
---
## 6. Backend Architecture
The backend is intentionally thin and stateless. It has three responsibilities:
1. **Proxy AI calls** — forwards prompts to the configured LLM (OpenAI or OpenAI-compatible).
2. **Stream responses**`POST /api/agent/stream` uses `pipeTextStreamToResponse` from the Vercel AI SDK.
3. **Health check**`GET /health` for Docker/orchestration readiness probes.
The `InMemoryCache` and `rateLimiter` middleware are implemented but not yet wired into the agent routes.
---
## 7. Contribution Workflow
1. Fork the repository and clone locally.
2. Install dependencies: `cd frontend && npm install` and `cd backend && npm install`.
3. Run the dev servers (see README).
4. Create a feature branch: `git checkout -b feat/your-feature`.
5. Follow the **Coding Standards** (see `CONTRIBUTING.md` for details).
6. Submit a Pull Request with:
- Descriptive title.
- Linked issue(s).
- Updated tests (if applicable).
- Documentation updates (if relevant).
7. Code Review Checklist:
- [ ] Readability: clear naming, minimal nesting.
- [ ] Maintainability: extracted utilities, JSDoc, TypeScript typings.
- [ ] Performance: no unnecessary re-renders, proper memoization.
- [ ] Accessibility: semantic HTML, ARIA attributes.
- [ ] Security: no hardcoded secrets, proper input validation.
5. Follow the Coding Standards (see [CONTRIBUTING.md](CONTRIBUTING.md)).
6. Submit a Pull Request with a descriptive title, linked issue(s), updated tests, and documentation changes if relevant.
## 9. Coding Standards
### PR Review Checklist
- **TypeScript**: Strict mode (`strict`, `noImplicitAny`, `noUnusedVars`).
- [ ] Readability: clear naming, minimal nesting
- [ ] TypeScript: no `any`, strict types throughout
- [ ] Performance: no unnecessary re-renders, proper memoization
- [ ] Accessibility: semantic HTML, ARIA attributes where needed
- [ ] Security: no hardcoded secrets, input validated at boundaries
---
## 8. Coding Standards
- **TypeScript**: strict mode (`strict`, `noImplicitAny`, `noUnusedLocals`).
- **Naming**: PascalCase for components, camelCase for functions/variables, UPPER_SNAKE_CASE for constants.
- **File Structure**: Featurefirst (`features/<feature>/`) or domaingrouped (`src/app/recollections/...`).
- **Documentation**: JSDoc for all public APIs, TSDoc for types, and inline comments for complex logic.
- **Formatting**: Prettier configured via `frontend/prettier.config.cjs`.
- **File structure**: domain-grouped under `src/app/<domain>/` and `src/components/<category>/`.
- **Formatting**: Prettier via `frontend/prettier.config.cjs`; line length ≤ 120.
- **Comments**: JSDoc for public APIs; inline only where logic is non-obvious.
## 10. Quick Reference for AI Agents
---
- **Key Entry Points**: `frontend/src/main.tsx`, `backend/src/index.ts`.
- **State Management**: `src/lib/graph/state.ts`, `src/app/canvas/canvasStore.*`.
- **Routing**: `backend/src/routes/agentRoutes.ts`.
- **Caching**: `backend/src/repositories/cacheRepository.ts`.
- **Performance Hotspots**: `CanvasPage.tsx`, `RecollectionPage.tsx`, large utility functions in `src/lib/*`.
## 9. Quick Reference for AI Agents
*This overview is intended to serve as a living document; future sections will expand on each module, performance audit findings, and junior developer quickstart guides.*
| Topic | Location |
| --- | --- |
| Entry point | `frontend/src/main.tsx` |
| Canvas store | `frontend/src/app/canvas/canvasStore.ts` |
| Store reducer | `frontend/src/app/canvas/canvasStoreReducer.ts` |
| Node registry | `frontend/src/lib/graph/nodeRegistry.ts` |
| Node builder | `frontend/src/lib/graph/nodeTypeBuilder.ts` |
| Rendering pipeline | `frontend/src/lib/graph/rendering.ts` |
| Built-in node registration | `frontend/src/lib/graph/registerBuiltinNodes.tsx` |
| AI settings context | `frontend/src/app/kosmos/KosmosContext.tsx` |
| Backend entry | `backend/src/index.ts` |
| Agent service | `backend/src/services/agentService.ts` |
*This document is a living reference; update it when architectural decisions change.*