This file provides guidance to ai agents when working with code in this repository.
The wiki/architecture/architecture.md file contains a comprehensive codebase map and architectural overview. Before implementing features or refactoring, consult this document to understand the system design.
IMPORTANT: You MUST maintain both AGENTS.md and wiki/architecture/architecture.md up to date when implementing tasks that modify the codebase structure, core layers, or commands.
bun run dev # Start Next.js dev server
bun run build # Production build
bun run check # TypeScript type-check (no emit)
bun run lint # ESLint
bun run format # Prettier
bun run test # Vitest (run once)
bun run test:ui # Vitest with browser UI
bun run preflight # format + check + lint + test (pre-merge gate)Run a single test file:
bun run test src/__tests__/workflow-engine.test.tsThe pre-commit hook runs lint-staged (format + lint on staged files). Never skip it with --no-verify.
Flowcraft is a Next.js 16 / React 19 app with two distinct product surfaces built on the same stack.
A node-based pipeline builder powered by @xyflow/react. Users wire together nodes (LLM, image, video, music, text, file, upscale, resize, list, router, custom-workflow, workflow-input/output) into DAGs that execute sequentially or in batch.
Key layers:
src/lib/schemas.ts— Zod schemas for all nodedatashapes; single source of truth for types (re-exported viasrc/lib/types.ts).src/lib/flow/node-registry.ts— Central registry mappingNodeType → NodeDefinition. Every node is adapted from a primitive (located insrc/primitives/) and registered viasrc/lib/node-adapters/index.ts.src/lib/flow/workflow-engine.ts— Orchestrates execution: detects batch mode, fans out requests atBATCH_CONCURRENCY, and calls each node's executor via the registry.src/lib/store/use-flow-store.ts— Zustand store (sliced intograph-slice+ui-slice). Persisted tolocalStoragewith transient fields stripped (executing,batchProgress, etc.).src/lib/node-adapters/utils/— Shared helpers:mention-resolver.tsresolves@nodereferences in prompts;execute-api-call.tswraps API routes;node-helpers.tshasgatherInputsutilities.
Adding a new node type: create a primitive definition in src/primitives/<type>/definition.ts, import and adapt it using toNodeDefinition in src/lib/node-adapters/index.ts (adding it to allNodeDefinitions), add the type to NodeType in src/lib/types.ts, register its Zod schema in src/lib/schemas.ts, and add a React component in src/components/nodes/.
A freeform media workspace where an AI agent (Director/Agent A) orchestrates image and video generation via chat.
Key layers:
src/lib/canvas/agent/agent-runner.ts—CanvasAgentRunnerwraps the Google ADK. Two variants:- Agent A (
variant: "a"): streaming LLM for simple image/video plans. Uses SSE streaming. - Agent B / Director (
variant: "b"): multi-turn agentic loop withThinkingLevel.LOW. UsesStreamingMode.NONEbecause SSE closes after the first turn. Loads pattern skills fromsrc/lib/canvas/agent/skills/patterns/.
- Agent A (
src/lib/canvas/agent/tools.ts— ADK tool definitions:planImageGenerationTool,planVideoGenerationTool,planProductionTool,suggestActionsTool.src/lib/canvas/agent/topology.ts— Kahn's algorithm (topoSort) for DAG-aware parallel execution of production plans. Onlydepends_onedges create ordering constraints.src/lib/canvas/agent/prompt-engineer.ts—PromptEngineer: single-turn agent that enrichesPlanNode.promptIntent→PlanNode.promptusing primitive skill docs fromsrc/lib/canvas/agent/skills/primitives/.src/lib/canvas/agent/step-mapper.ts— Maps Director tool-call outputs intoGenerationStep[].src/lib/canvas/generation.ts—executePlan: resolves step references (canvas node URIs + inter-step dependencies), callsgeminiService/storageService, streamsStepEvents.src/lib/canvas/types.ts— All Canvas-specific types:CanvasNode,ProductionPlan,PlanNode,PlanEdge,MediaOperation,GenerationStep,ChatMessage.src/lib/store/use-canvas-store.ts— Zustand store for canvas state (nodes, messages, viewport).
Canvas API routes:
POST /api/canvases/[id]/chat— streamsAgentEvents from the ADK runner (SSE).POST /api/canvases/[id]/execute-plan— runs an approvedAgentPlanthroughgeneration.ts(SSE,maxDuration: 300).
- Auth:
next-authv5 with Google provider (src/auth.ts). All API routes callauth()for session. - Persistence: Firestore via
src/lib/firestore.ts. Services insrc/lib/services/wrap Firestore collections (flow.service,canvas.service,library.service, etc.). - Storage: GCS via
src/lib/services/storage.service.ts. Signed URLs cached insrc/lib/cache/signed-url-cache.ts(pre-warmed after generation). - AI:
@google/genaifor Gemini API calls;@google/adkfor the canvas agent framework. Both use Vertex AI (configured insrc/lib/config.ts). - UI: shadcn/ui components in
src/components/ui/(Radix primitives + Tailwind CSS v4). Flow node components insrc/components/nodes/, config panels insrc/components/panels/.
@/ resolves to src/ everywhere (configured in tsconfig.json and vitest.config.ts).
Tests live in src/__tests__/. Vitest with jsdom. Integration tests (.integration.test.ts) hit real Gemini endpoints and require env vars — they are slow and not part of the default CI gate.
Coverage thresholds: 60% lines/statements, 50% functions, 45% branches.