12 KiB
CLAUDE.md
本文件用于指导 Claude Code 在本仓库中工作。内容以当前 popiart-node 代码结构为准:新开发只面向 Popi 服务链路,不再扩展旧网关兼容。
构建与开发命令
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。当前只需要提供以下变量:
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 节点:
smartImagesmartVideosmartAudiosmartText
这些 smart 节点根据连接状态在输入模式和生成模式之间切换。新交互、新模型参数、新任务创建能力应落到 smart 节点和 Popi 任务链路。
src/utils/nodeCreationTypes.ts 中的 legacy create 节点不得再被新建:
imageInputvideoInputaudioInputpromptnanoBananagenerateVideogenerateAudiollmGenerate
这些旧节点只用于读取历史工作流或内部兼容,不作为新功能入口,不要给它们增加新能力。
新增节点 checklist
新增节点类型时必须接入以下位置:
- 在
src/types/nodes.ts定义节点数据类型,并加入NodeType。 - 在
src/components/nodes/创建节点组件,并从src/components/nodes/index.ts导出。 - 在
src/components/workflowTypes.tsx注册到workflowNodeTypes。 - 在
src/store/utils/nodeDefaults.ts的createDefaultNodeData()添加默认数据。 - 在
src/constants/nodeDimensions.ts添加默认尺寸。 - 在连接规则中声明输入/输出能力,相关工具包括
src/utils/nodeConnectionSpec.ts、src/utils/nodeConnectionRegistry.ts、src/utils/nodeHandles.ts。 - 如果节点会被执行,在
src/store/execution/executeNode.ts和对应 executor 中加入逻辑。 - 如果节点产出可被下游消费的数据,更新
src/store/utils/connectedInputs.ts。 - 添加聚焦测试,至少覆盖默认数据、连接能力、执行或主要 UI 行为。
Handle 标准
所有节点统一使用单 handle:
- 输入 handle:
input - 输出 handle:
output
不要新增旧式 image-0、text-0 等索引 handle。src/utils/nodeHandles.ts 会通过 normalizeConnectionHandles() 和 normalizeWorkflowEdgeHandles() 归一化连接;src/utils/nodeConnectionSpec.ts 决定 handle 是否可见以及可接受/产出的媒体类型。
即将废除的老节点
老输入节点:
imageInputvideoInputaudioInputprompt
老生成节点:
nanoBananagenerateVideogenerateAudiollmGenerate
这些节点可以继续被历史 workflow 加载,但不是新建入口。后续开发不要围绕这些节点设计新参数、新 UI、新任务创建逻辑。
工作流执行
工作流执行由 useWorkflowStore 调度:
- 用户点击运行,或触发快捷键。
executeWorkflow()根据节点依赖分层执行。- 每个节点通过
src/store/execution/executeNode.ts分发到具体 executor。 - executor 使用
getConnectedInputs()获取上游图片、视频、音频、文本和动态输入。 - 分组锁定、暂停边、条件分支、批处理等逻辑在 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 链路:
runPopiartTask()
-> /api/generate/task/create
-> submitPopiTask()
-> /api/generate/task/poll
关键文件:
src/lib/popiartTask/runTask.tssrc/store/execution/popiartTaskClient.tssrc/app/api/generate/task/create/route.tssrc/app/api/generate/task/poll/route.tssrc/app/api/generate/providers/popiserver.ts
生成请求必须携带 Popi 模型身份:
selectedModel.modelIdselectedModel.displayName
客户端序列化任务时会剥离 selectedModel.provider,服务端按 Popi 处理。任务链路中的关键字段包括:
typesubTypeparametersextraTaskParamsreferenceSubjectListdynamicInputsbatchSizeaudioVoiceIdimagesvideosvoicesmediaType
模型列表和模型详情来自:
/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/<short-description>或fix/<short-description>。 - 所有 PR 默认指向
master:gh pr create --base master。 - 不要直接 push 到
master。