# CLAUDE.md 本文件用于指导 Claude Code 在本仓库中工作。内容以当前 `popiart-node` 代码结构为准:新开发只面向 Popi 服务链路,不再扩展旧网关兼容。 ## 构建与开发命令 ```bash npm run dev # 启动自定义 Next.js server,默认 http://localhost:3000 npm run build # 生产构建 npm run start # 启动生产服务 npm run lint # 运行 Next.js lint npm run test # 使用 Vitest 运行测试(watch 模式) npm run test:run # 单次运行测试(CI 模式) npm run test:coverage # 生成测试覆盖率 ``` `npm run dev` 执行的是 `node server.js`,默认访问地址为 `http://localhost:3000`,并把请求超时扩展到 10 分钟,用于长耗时生成任务。 ## 环境变量 在项目根目录创建 `.env.local`。当前只需要提供以下变量: ```env POPIART_API_BASE_URL=https://wwwtest.popi.art SKIP_GENERATION_GATEWAY=false SMART_GENERATE_UPLOAD_ENABLED=true ``` 不要在本文件中新增 Gemini、OpenAI、Kie、fal、Replicate、WaveSpeed、NEWAPIWG 或 provider mode 配置。当前开发原则是 Popi-only。 ## 项目概览 `popiart-node` 是一个基于节点的 AI 媒体工作流编辑器。用户在 React Flow 画布上创建节点,通过统一 handle 连接图片、视频、音频、文本和 3D 数据,并按依赖顺序创建/轮询 Popi 生成任务。 核心技术栈: - **Next.js 16** App Router + TypeScript - **React 19** - **@xyflow/react** 用于节点画布 - **Konva / react-konva** 用于标注绘制 - **Zustand** 用于全局状态 - **Ant Design** 和 Tailwind CSS 用于 UI - **Vitest** 用于测试 ## 关键文件 | 用途 | 位置 | | --- | --- | | 主工作流状态和执行调度 | `src/store/workflowStore.ts` | | 节点执行器 | `src/store/execution/` | | 上游输入聚合和 workflow 校验 | `src/store/utils/connectedInputs.ts` | | 节点默认数据 | `src/store/utils/nodeDefaults.ts` | | 节点默认尺寸 | `src/constants/nodeDimensions.ts` | | 节点/边注册 | `src/components/workflowTypes.tsx` | | 主画布组件 | `src/components/WorkflowCanvas.tsx` | | 节点组件 | `src/components/nodes/` | | 类型入口 | `src/types/index.ts` | | 节点类型定义 | `src/types/nodes.ts` | | Popi 模型接口适配 | `src/app/api/_popiserverModels.ts` | | 生成 API 入口 | `src/app/api/generate/route.ts` | | 任务创建/轮询 API | `src/app/api/generate/task/` | | Popi 任务网关适配 | `src/app/api/generate/providers/popiserver.ts` | | 客户端任务创建与轮询 | `src/lib/popiartTask/runTask.ts` | | 多语言 | `src/i18n/index.tsx` | ## 全局状态 当前全局状态分散在多个 Zustand store。新增或修改功能时,应优先复用对应 store,不要把跨组件状态塞进局部组件。 | Store / 模块 | 作用 | | --- | --- | | `useWorkflowStore` | 主工作流状态。管理节点、边、选择、分组、连接、执行、运行状态、撤销重做、workflow 序列化。 | | `useModelStore` | Popi 模型列表和模型详情缓存。按 `image`、`video`、`audio`、`3d`、`llm`、`multiAngle`、`highDefinition`、`outpainting`、`inpainting` 分组。 | | `useGenerationPreferenceStore` | 图片、视频、音频生成默认偏好。保存默认模型、参数、比例、分辨率、批量数、`voiceId`、`subType`。 | | `useUserStore` | 登录 token、用户信息、用户信息拉取状态。持久化到 `node-banana-user-session`。 | | `useAppConfigStore` | 应用配置和预览图后缀配置,来自 `/api/config`。 | | `useCanvasWorkflowStore` | 当前画布工作流标题、描述和加载状态。 | | `useNodeToolStore` | 节点级工具面板状态。管理 composer、多角度、高清、裁剪、宫格、扩图、局部重绘、标注等工具。 | | `useAnnotationStore` | 标注弹窗、绘制工具、标注图形、选中图形和 undo/redo 历史。 | | `useLoginModalStore` | 登录弹窗状态和打开原因。 | | `useFTUXStore` | 首次引导流程、步骤状态和教程样例图。 | ## 节点标准 标准新建节点优先使用 smart 节点: - `smartImage` - `smartVideo` - `smartAudio` - `smartText` 这些 smart 节点根据连接状态在输入模式和生成模式之间切换。新交互、新模型参数、新任务创建能力应落到 smart 节点和 Popi 任务链路。 `src/utils/nodeCreationTypes.ts` 中的 legacy create 节点不得再被新建: - `imageInput` - `videoInput` - `audioInput` - `prompt` - `nanoBanana` - `generateVideo` - `generateAudio` - `llmGenerate` 这些旧节点只用于读取历史工作流或内部兼容,不作为新功能入口,不要给它们增加新能力。 ### 新增节点 checklist 新增节点类型时必须接入以下位置: 1. 在 `src/types/nodes.ts` 定义节点数据类型,并加入 `NodeType`。 2. 在 `src/components/nodes/` 创建节点组件,并从 `src/components/nodes/index.ts` 导出。 3. 在 `src/components/workflowTypes.tsx` 注册到 `workflowNodeTypes`。 4. 在 `src/store/utils/nodeDefaults.ts` 的 `createDefaultNodeData()` 添加默认数据。 5. 在 `src/constants/nodeDimensions.ts` 添加默认尺寸。 6. 在连接规则中声明输入/输出能力,相关工具包括 `src/utils/nodeConnectionSpec.ts`、`src/utils/nodeConnectionRegistry.ts`、`src/utils/nodeHandles.ts`。 7. 如果节点会被执行,在 `src/store/execution/executeNode.ts` 和对应 executor 中加入逻辑。 8. 如果节点产出可被下游消费的数据,更新 `src/store/utils/connectedInputs.ts`。 9. 添加聚焦测试,至少覆盖默认数据、连接能力、执行或主要 UI 行为。 ### Handle 标准 所有节点统一使用单 handle: - 输入 handle:`input` - 输出 handle:`output` 不要新增旧式 `image-0`、`text-0` 等索引 handle。`src/utils/nodeHandles.ts` 会通过 `normalizeConnectionHandles()` 和 `normalizeWorkflowEdgeHandles()` 归一化连接;`src/utils/nodeConnectionSpec.ts` 决定 handle 是否可见以及可接受/产出的媒体类型。 ## 即将废除的老节点 老输入节点: - `imageInput` - `videoInput` - `audioInput` - `prompt` 老生成节点: - `nanoBanana` - `generateVideo` - `generateAudio` - `llmGenerate` 这些节点可以继续被历史 workflow 加载,但不是新建入口。后续开发不要围绕这些节点设计新参数、新 UI、新任务创建逻辑。 ## 工作流执行 工作流执行由 `useWorkflowStore` 调度: 1. 用户点击运行,或触发快捷键。 2. `executeWorkflow()` 根据节点依赖分层执行。 3. 每个节点通过 `src/store/execution/executeNode.ts` 分发到具体 executor。 4. executor 使用 `getConnectedInputs()` 获取上游图片、视频、音频、文本和动态输入。 5. 分组锁定、暂停边、条件分支、批处理等逻辑在 store 和 execution 工具层处理。 核心 executor 位于 `src/store/execution/`: - `nanoBananaExecutor.ts`:图片生成旧执行器和 smart image 生成路径。 - `generateVideoExecutor.ts`:视频生成。 - `generateAudioExecutor.ts`:音频生成。 - `generate3dExecutor.ts`:3D 生成。 - `llmGenerateExecutor.ts`:文本生成。 - `derivedImageExecutor.ts`:裁剪、宫格、高清、扩图、局部重绘等派生图片任务。 - `videoProcessingExecutors.ts`:视频拼接、裁剪、抽帧、曲线等处理。 - `batchExecution.ts`:批量执行。 ## Popi-only 任务创建 创建任务统一走 Popi 链路: ```text runPopiartTask() -> /api/generate/task/create -> submitPopiTask() -> /api/generate/task/poll ``` 关键文件: - `src/lib/popiartTask/runTask.ts` - `src/store/execution/popiartTaskClient.ts` - `src/app/api/generate/task/create/route.ts` - `src/app/api/generate/task/poll/route.ts` - `src/app/api/generate/providers/popiserver.ts` 生成请求必须携带 Popi 模型身份: - `selectedModel.modelId` - `selectedModel.displayName` 客户端序列化任务时会剥离 `selectedModel.provider`,服务端按 Popi 处理。任务链路中的关键字段包括: - `type` - `subType` - `parameters` - `extraTaskParams` - `referenceSubjectList` - `dynamicInputs` - `batchSize` - `audioVoiceId` - `images` - `videos` - `voices` - `mediaType` 模型列表和模型详情来自: - `/api/models` - `/api/models/[modelId]` 这两个接口只接受 Popi provider。`src/lib/providerMode.ts` 固定只支持 `popiserver`。 ## 旧网关清理规则 Gemini、Kie、fal、Replicate、WaveSpeed、newapiwg 等老网关的存量代码**目前仍大量存在**于仓库中(例如 `src/lib/providers/` 下的 `fal.ts`、`replicate.ts`、`wavespeed.ts`,以及散落在多处的相关引用)。这里描述的是**目标状态**:新开发不得依赖或扩展这些老网关,遇到相关代码时按清理项处理,逐步移除而不是继续兼容。 如果任务中遇到以下内容,应作为清理项删除,而不是继续兼容或扩展: - 旧网关兼容分支。 - 旧 provider API key 逻辑。 - 旧 provider 选择 UI。 - 以 Gemini/Kie/fal/Replicate/WaveSpeed/newapiwg 为默认路径的模型注册、schema、polling 或 payload 转换。 当前文档中的 provider 相关描述应始终以 Popi 为准。 ## API Routes `src/app/api/` 当前按功能分组: | 分组 | 用途 | | --- | --- | | `auth/*` | 登录、登出、二维码、验证码等认证接口。 | | `captcha` | 图形/验证码接口。 | | `user/info` | 当前用户信息。 | | `config` | 应用配置。 | | `env-status` | 环境/配置状态检查。 | | `models`、`models/[modelId]` | Popi 模型列表和模型详情/schema。 | | `generate`、`generate/task/*`、`generate/poll` | 生成入口、任务创建和轮询。任务链路实际使用 `generate/task/create` 与 `generate/task/poll`。 | | `llm` | 文本生成接口。 | | `canvas-workflows/*` | 画布 workflow 保存、加载、更新。 | | `canvas-templates/*` | 画布模板列表、分类和详情。 | | `popi/asset/*` | Popi 素材库。 | | `popi/user-file/*` | 用户文件、文件夹、移动、重命名、删除、封面等。 | | `popi/media/upload`、`images/upload` | 媒体上传。 | | `points/*` | 点数估算、报价、任务价格计算。 | | `quickstart/*` | 快速开始和 prompt-to-workflow。 | | `chat` | 画布聊天/编辑操作。 | | `logs` | 会话日志。 | | `proxy-media`、`open-file` | 媒体代理和本地文件打开。 | | `recommend-banners` | 推荐 banner 数据。 | | `content/privacy-policy/latest` | 最新隐私政策。 | 不要重新引入旧的 `/api/workflow` 或 `/api/save-generation` 描述。 ## localStorage Keys 常见持久化 key: - `node-banana-workflow-costs`:workflow 成本数据。 - `node-banana-nanoBanana-defaults`:图片生成默认值。名称保留历史兼容,新文档中按 Generate Image defaults 理解。 - `node-banana-provider-settings`:provider 设置。当前只应保留 Popi。 - `node-banana-recent-models`:最近使用模型。 - `node-banana-node-defaults`:节点默认参数。 - `node-banana-canvas-navigation`:画布导航设置。 - `node-banana-ftux-completed`:首次引导完成状态。 - `node-banana-user-session`:用户 token 和用户信息。 - `node-banana-inline-parameters`:节点内联参数面板开关。 - `popiart-node-language`:语言设置。 ## Git 工作流 - 默认分支是 `master`(`origin/HEAD → master`),仓库当前不存在 `develop` 分支。 - 创建 feature/fix 分支前先切到 `master` 并拉取最新。 - 分支命名使用 `feature/` 或 `fix/`。 - 所有 PR 默认指向 `master`:`gh pr create --base master`。 - 不要直接 push 到 `master`。