Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
90 changes: 59 additions & 31 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -1,54 +1,82 @@
# Repository Guidelines

## Project Structure & Module Organization

This repository is an npm workspace monorepo:
- `apps/server`: Express API + Vite middleware integration (`src/index.ts`). Routes: `POST /api/run-stream` (SSE, primary), `POST /api/run` (batch JSON), `POST /api/resume` (approval resumption), `GET /api/config` (provider/model config), `GET /api/default-workflow` (optional startup workflow).
- `apps/web`: Vite frontend for the workflow editor (`src/app/workflow-editor.ts`).
- `packages/types`: Shared TypeScript contracts used by server, web, and engine.
- `packages/workflow-engine`: Reusable workflow execution runtime.
- `design-system/`: Git submodule with UI tokens/components consumed by the web app.
- `data/runs/`: Runtime run snapshots (gitignored artifacts).
- `.config/config.json`: Provider and model definitions served via `/api/config` (committed). `.config/default-workflow.json`: Optional startup workflow loaded by the editor on init (gitignored).

- `apps/server`: Express API + Vite middleware integration (`src/index.ts`).
- `apps/web`: Vite frontend workflow editor (`src/app/workflow-editor.ts`).
- `packages/types`: Shared TypeScript contracts.
- `packages/workflow-engine`: Reusable workflow runtime.
- `design-system/`: Git submodule with UI tokens/components.
- `data/runs/`: Runtime run snapshots (gitignored).
- `.config/config.json`: Provider/model definitions (committed).
- `.config/default-workflow.json`: Optional startup workflow (gitignored).

Server routes:

- `POST /api/run-stream` (SSE run, primary)
- `POST /api/run` (batch JSON run)
- `POST /api/resume-stream` (SSE resume, primary)
- `POST /api/resume` (batch JSON resume)
- `GET /api/run/:runId` (active/persisted run fetch)
- `GET /api/config` (provider/model config)
- `GET /api/default-workflow` (optional startup workflow)

## Build, Test, and Development Commands

- `npm install`: Install all workspace dependencies.
- `npm run dev`: Start integrated server + UI on `http://localhost:3000`.
- `npm run dev:web`: Run frontend-only Vite dev server.
- `npm run build`: Build shared packages, server, and web app.
- `npm run lint`: Run ESLint for all TypeScript files.
- `npm run typecheck`: Type-check server and web workspaces.
- `npm test`: Run current repo test gate (`workflow-engine` + server typecheck scripts).
- `npm run build`: Build server and web app.
- `npm run build:packages`: Build shared packages.
- `npm run lint`: Run ESLint.
- `npm run typecheck`: Typecheck server and web workspaces.
- `npm test`: Run repo test gate (`workflow-engine` + server typecheck scripts).

## Coding Style & Naming Conventions
- Language: TypeScript across apps/packages, with `strict` mode enabled.
- Use `import type` where applicable (`@typescript-eslint/consistent-type-imports` is enforced).
- Keep unused parameters/locals prefixed with `_` to satisfy lint rules.
- Match existing file naming patterns: kebab-case files (`openai-agents-llm.ts`), PascalCase classes, UPPER_SNAKE_CASE constants.
- Follow existing indentation/style in each file; do not reformat unrelated code.

- Language: TypeScript with `strict` mode.
- Use `import type` where applicable (`@typescript-eslint/consistent-type-imports`).
- Prefix unused parameters/locals with `_`.
- Naming patterns: kebab-case files, PascalCase classes, UPPER_SNAKE_CASE constants.
- Avoid reformatting unrelated code.

## Testing Guidelines
- Current CI checks in `.github/workflows/pr.yml`: `lint`, `build:packages`, `typecheck`, and `build`.

- CI checks in `.github/workflows/pr.yml`: `lint`, `build:packages`, `typecheck`, `build`.
- Web workspace uses Vitest (`npm --workspace apps/web run test`).
- When adding tests, prefer `*.test.ts` near the feature being tested.
- No coverage threshold is currently enforced; focus on targeted tests for changed behavior.
- Prefer targeted `*.test.ts` files near changed behavior.

## Commit & Pull Request Guidelines
- Prefer short, imperative commit subjects. Existing history favors Conventional Commit prefixes like `feat(web): ...` and `fix: ...`.

- Prefer short, imperative commit subjects.
- Conventional prefixes are common (`feat(web):`, `fix:`, `chore:`).
- Keep commits scoped to one logical change.
- PRs should include: purpose, risk/impact, linked issue (if any), and validation steps run locally.
- For UI changes in `apps/web`, include screenshots or short recordings.
- PRs should include purpose, risk/impact, and validation steps.
- For UI changes in `apps/web`, include screenshots or recordings.

## Security & Configuration Tips
- Set `OPENAI_API_KEY` in your shell before running agent workflows.
- Never commit secrets, `.env` files, or generated run data from `data/runs/`.

- Set `OPENAI_API_KEY` before running agent workflows.
- Never commit secrets, `.env` files, or generated data from `data/runs/`.

## Design System Policy
- Treat `design-system/` (git submodule) as the source of truth for UI primitives.
- Prefer existing tokens/components from the submodule before building custom UI in `apps/web`.
- If a needed component does not exist in `design-system/`, pause and consult the user before adding a new component or introducing a non-design-system alternative.
- In a brand new git worktree, initialize submodules before development (`git submodule update --init --recursive`), or the design-system assets will be missing.

- Treat `design-system/` as source of truth for UI primitives.
- Prefer submodule tokens/components over custom alternatives.
- If a needed component is missing in `design-system/`, consult user before adding alternatives.
- In fresh worktrees, run `git submodule update --init --recursive`.

## Subagent Graph Rules
- Subagent links are tool-delegation edges and do not represent execution flow edges.
- Subagent hierarchies must remain acyclic (for example, `A -> B -> A` is invalid).
- Subagent targets are tool-only nodes and cannot participate in regular execution edges.

- Links between agents and subagents are tool-delegation edges, not execution edges.
- Hierarchies of subagents must remain acyclic.
- Targets of subagent links are tool-only and cannot participate in regular execution edges.

## Additional Documentation

- `docs/README.md`
- `docs/api.md`
- `docs/workflow-semantics.md`
- `apps/web/docs/run-readiness.md`
149 changes: 71 additions & 78 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -1,113 +1,106 @@
# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
This file provides guidance to Claude Code when working in this repository.

## Project Overview

Visual workflow builder for agentic LLM pipelines. Users drag-and-drop nodes (Start, Agent, If/Else, Approval) onto a canvas, connect them, configure LLM prompts and branching logic, then execute workflows server-side against OpenAI. Run results are persisted as JSON audit trails.
AgentFlow is a visual workflow editor and runtime for LLM pipelines.

## Monorepo Layout
Users compose workflows with `Start`, `Agent`, `Condition`, and `Approval` nodes, then execute server-side with persisted run records.
In the UI, `Condition` maps to runtime node type `"if"` in workflow JSON and persisted run records.

npm workspace monorepo:
## Monorepo Layout

| Package | Purpose |
|---------|---------|
| `packages/types` | Shared TypeScript contracts (`WorkflowNode`, `WorkflowGraph`, `WorkflowRunResult`, etc.) |
| `packages/workflow-engine` | Pure runtime executor (`WorkflowEngine` class, `WorkflowLLM` interface) — no OpenAI dependency |
| `apps/server` | Express API + Vite dev middleware. Routes: `POST /api/run`, `POST /api/run-stream`, `POST /api/resume`, `GET /api/config`, `GET /api/default-workflow` |
| `apps/web` | Vite SPA — `WorkflowEditor` class handles canvas, node palette, and run console |
| `design-system/` | Git submodule (CodeSignal DS) — CSS tokens and components consumed by web app |
| --- | --- |
| `packages/types` | Shared TypeScript contracts (`WorkflowGraph`, `WorkflowRunResult`, etc.) |
| `packages/workflow-engine` | Runtime executor (`WorkflowEngine`, `WorkflowLLM`) |
| `apps/server` | Express API + Vite middleware/static hosting |
| `apps/web` | Vite SPA editor (`WorkflowEditor`) |
| `design-system/` | Git submodule for UI foundations/components |

## API Surface

- `POST /api/run-stream`
- `POST /api/run`
- `POST /api/resume-stream`
- `POST /api/resume`
- `GET /api/run/:runId`
- `GET /api/config`
- `GET /api/default-workflow`

## Common Commands

```bash
npm install # Install all workspace deps
npm run dev # Start integrated server+UI on http://localhost:3000
npm run build # Build packages → server → web (production)
npm run lint # ESLint across all TypeScript
npm run typecheck # tsc --noEmit for server and web
npm test # Run workflow-engine + server tests

# Workspace-specific
npm --workspace apps/web run test # Vitest for web
npm --workspace packages/workflow-engine run test # Engine tests
npm run build:packages # Build only shared packages (types + engine)
npm install
npm run dev
npm run build
npm run build:packages
npm run lint
npm run typecheck
npm test

npm --workspace apps/web run test
```

## Architecture

**Request flow (streaming):** Browser (`api.ts` `runWorkflowStream`) → `POST /api/run-stream` → `WorkflowEngine.run()` with `onLog` callback → each `WorkflowLogEntry` is streamed to the client as an SSE event → final result persisted to `data/runs/run_<id>.json` → `done` event sent to close stream. This is the primary run path — the UI renders agent responses progressively as they arrive.

**Request flow (batch):** `POST /api/run` runs the same engine synchronously and returns the full `WorkflowRunResult` as JSON. Still available but not used by the default UI.

**Approval/pause flow:** When engine hits an Approval node, it sets `waitingForInput=true` and the engine instance is stored in an in-memory `Map` (`store/active-workflows.ts`). Client calls `POST /api/resume` with user input to continue.
## Architecture Notes

**Agent backend:** Server agent execution is implemented through OpenAI Agents SDK (`apps/server/src/services/openai-agents-llm.ts`). Agent runs are capped with `maxTurns: 20` to bound loop iterations.
## Execution path

**Subagent hierarchy:** Agent nodes may expose other agent nodes as tools through subagent links. These links are not execution-flow edges. The subagent graph must be acyclic, and subagent targets are tool-only (no regular execution edges).
Primary path is streaming:

**Build dependency chain:** `packages/types` → `packages/workflow-engine` → `apps/server` / `apps/web`. Always run `build:packages` before typechecking or building apps.
`apps/web` -> `POST /api/run-stream` -> `WorkflowEngine.run()` -> SSE log events -> persisted run record -> final `done` event.

## Design System (Git Submodule)
Resume follows equivalent streaming path through `POST /api/resume-stream`.

`design-system/` is a CodeSignal design system git submodule. It is the **source of truth** for all UI primitives — always prefer existing DS tokens and components over custom CSS or new UI elements. If a needed component doesn't exist in the DS, consult the user before adding alternatives.
## Persistence

### Token layers
Each run/resume operation persists `data/runs/run_<runId>.json` with:

Tokens live in three foundation files linked as static CSS in `apps/web/index.html`:
- workflow graph
- logs
- status
- state snapshot
- `currentNodeId`
- `waitingForInput`

- **Colors** (`colors/colors.css`): Two-tier system — base scales (`--Colors-Base-Primary-700`) and semantic names (`--Colors-Backgrounds-Main-Default`, `--Colors-Text-Body-Strong`, `--Colors-Stroke-Default`, etc.). Dark mode is automatic via `@media (prefers-color-scheme: dark)`.
- **Spacing** (`spacing/spacing.css`): Spacing scale `--UI-Spacing-spacing-{none|min|xxs|xs|s|mxs|ms|m|ml|mxl|l|xl|xxl|xxxl|4xl|max}`, border radii `--UI-Radius-radius-{size}`, and input heights `--UI-Input-{min|xs|sm|md|lg}`.
- **Typography** (`typography/typography.css`): Font families (`--body-family`, `--heading-family`, `--code-family`), size variables (`--Fonts-Body-Default-md`), and utility classes (`.body-small`, `.heading-xxxsmall`, `.label-small`, `.code`).
## Paused-run restoration

### Component CSS + JS
On server startup, paused runs are rehydrated into in-memory active workflow map when restore fields are present.

Component CSS is loaded statically in `index.html` (button, boxes, dropdown, icons, input, modal, split-panel, tags). Interactive components with JS (Dropdown, Modal, SplitPanel) are **lazy-loaded at runtime** via dynamic `import()` from the submodule path:
## Subagent hierarchy

```typescript
// Pattern used in workflow-editor.ts
const mod = await import(`${origin}/design-system/components/dropdown/dropdown.js`);
const DropdownCtor = mod.default;
const dropdown = new DropdownCtor(container, { items, selectedValue, onSelect });
```

Components currently used in the web app:
- **SplitPanel** — main layout (canvas left, run console right). Constructor: `new SplitPanel(el, { initialSplit, minLeft, minRight })`.
- **Dropdown** — model and reasoning-effort selectors. Constructor: `new Dropdown(el, { items, selectedValue, placeholder, width, onSelect })`.
- **Modal** — help dialog, confirmation prompts. Constructor: `new Modal({ size, title, content, footerButtons })`. Also `Modal.createHelpModal()` factory.
- **Button** — pure CSS (`.button .button-primary`, `.button-secondary`, `.button-danger`, sizes via `.button-small`/`.button-xsmall`).
- **Input** — pure CSS (`.input` for text/number, `.input-checkbox` / `.input-radio` with wrapper structure).

### Styling rules for the web app
Subagent links are tool-delegation edges (`sourceHandle: "subagent"`), not execution edges. Hierarchy must be acyclic and subagent targets are tool-only nodes.

`apps/web/src/workflow-editor.css` consumes DS tokens throughout. When writing new CSS:
- Use semantic color tokens (`--Colors-Backgrounds-Main-Top`, `--Colors-Stroke-Default`) rather than base scales or raw hex values.
- Use spacing tokens (`--UI-Spacing-spacing-s`) instead of hardcoded pixel values.
- Use radius tokens (`--UI-Radius-radius-xs`) for border-radius.
- Use typography variables/classes (`--body-family`, `.body-small`) for font styling.
## Design System

## Coding Conventions
`design-system/` is a git submodule and source of truth for UI primitives.

- TypeScript strict mode everywhere. Use `import type` (enforced by `@typescript-eslint/consistent-type-imports`).
- File naming: kebab-case. Classes: PascalCase. Constants: UPPER_SNAKE_CASE.
- Prefix unused parameters with `_`.
- Tests: `*.test.ts` co-located near the feature. Vitest for web, CI runs lint → build:packages → typecheck → build.
- Commits: short imperative subjects, Conventional Commit prefixes (`feat(web):`, `fix:`, `chore:`).
- CSS tokens/components are linked in `apps/web/index.html`.
- Interactive DS components are dynamically imported in `workflow-editor.ts`.
- `apps/web/public/design-system` is a symlink to root submodule.

## Local Configuration (`.config/`)
Initialize submodule in fresh worktrees:

The `.config/` directory holds developer-local files that are partially gitignored:
```bash
git submodule update --init --recursive
```

- **`config.json`** *(committed)* — provider and model definitions. The server serves this via `GET /api/config`; the web app loads it on startup to populate the model and reasoning-effort dropdowns. Structure: `{ providers: [{ id, name, enabled, models: [{ id, name, reasoningEfforts[] }] }] }`.
- **`default-workflow.json`** *(gitignored)* — optional startup workflow. If present, the editor loads it instead of the blank Start node. Same `{ nodes, connections }` shape as a run record's `workflow` field.
## Configuration

Agent node `userPrompt` fields support `{{PREVIOUS_OUTPUT}}` as a template token, which is substituted with the previous node's output before the LLM is called.
- `OPENAI_API_KEY`: required for agent-node execution.
- `PORT`: server port (default `3000`).
- `PROJECT_ROOT`: optional root override.
- `.config/config.json`: provider/model config served by API.
- `.config/default-workflow.json`: optional startup workflow (gitignored).

## Environment
## References

- Requires Node.js 20+.
- `OPENAI_API_KEY` must be exported in your shell for Agent node execution.
- `data/runs/` is gitignored — created automatically at runtime.
- `.config/default-workflow.json` is gitignored — create it locally to preload a workflow on startup.
- Clone with `--recurse-submodules` to pull the design-system submodule.
- In a brand new git worktree, run `git submodule update --init --recursive` before development so the design-system submodule is available.
- `docs/README.md`
- `docs/architecture.md`
- `docs/api.md`
- `docs/workflow-semantics.md`
- `docs/run-persistence.md`
- `docs/configuration.md`
- `docs/troubleshooting.md`
- `apps/web/docs/run-readiness.md`
Loading