# actory-frontend **Repository Path**: actory-suite/actory-frontend ## Basic Information - **Project Name**: actory-frontend - **Description**: Actory Suite — actory-frontend - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-08-07 - **Last Updated**: 2026-08-09 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # actory-frontend > Actory 的统一前端。单 App + 三中心路由组,承载场景编排、Agent 构建、运营治理与本体建模的全部交互。 ![Next.js](https://img.shields.io/badge/Next.js-16-black) ![React](https://img.shields.io/badge/React-19-blue) ![pnpm](https://img.shields.io/badge/pnpm-workspace-orange) ![port](https://img.shields.io/badge/port-3000-darkgreen) --- ## 目录 - [项目定位](#项目定位) - [系统架构](#系统架构) - [完整页面清单](#完整页面清单) - [画布组件族](#画布组件族) - [共享包](#共享包) - [API 调用模式](#api-调用模式) - [跨仓协作](#跨仓协作) - [项目结构](#项目结构) - [开发指南](#开发指南) --- ## 项目定位 frontend 是 Actory 八仓库中的**唯一前端**。它将三中心(场景中心 / 运营中心 / 本体中心)统一在一个 Next.js App 里,通过 Route Group 组织路由——不是物理分离的三个 App,而是同一个 `src/app/` 下的三组路由。 ``` 用户浏览器 │ ▼ ┌─────────────────────────────────────────────────┐ │ actory-frontend :3000 │ │ │ │ 场景中心 运营中心 本体中心 │ │ (scene) (ops) (ontology) │ │ Agent 构建+ 运行监控+ 本体建模+ │ │ 场景编排+ 平台治理+ 语义实例 │ │ 价值呈现 治理洞察 │ │ │ │ ────────── 全部走 gateway :3100 ────────── │ └─────────────────────────────────────────────────┘ ``` ### 职责边界 | ✅ 负责 | ❌ 不负责 | |---------|---------| | 三中心全部页面渲染(47 页面) | 后端业务逻辑(归 engine / platform) | | 画布可视化编排(拖拽 + 节点连线) | 场景执行引擎(归 engine) | | 双态运行:设计态画布预览 + 运行态对话 | 数据持久化(归 platform / engine DB) | | API 请求封装 + Token 注入 | 鉴权验签(归 gateway) | | 共享组件库(ui-core 66 文件) | 领域算法(归 domain-breeding) | | 共享逻辑包(shared 20 文件) | IM 协议适配(归 im-gateway) | | draft/published 双版本消费 | DSL 编译执行(归 engine SceneCompiler) | --- ## 系统架构 ### 单 App + Route Group 架构 ``` src/app/ │ ┌────────────┼─────────────┐ │ │ │ login/ designer/ page.tsx ← 独立路由(无 Shell) │ [id]/ │ │ │ │ │ 全屏画布编辑器 三中心入口卡片 │ (无 BsfShell) │ ┌────▼───── (shell)/ ──────────────────┐ │ Route Group │ │ (ErrorBoundary 包裹) │ │ │ │ ┌───────────┬───────────┬───────────┐ │ │ │ (scene) │ (ops) │(ontology) │ │ │ │ │ │ │ │ │ │ BsfShell │ BsfShell │ BsfShell │ │ │ │ console= │ console= │ console= │ │ │ │ "scene" │ "ops" │"ontology" │ │ │ │ │ │ │ │ │ │ builder/ │ ops/ │ ontology/ │ │ │ │ factory/ │ (20路由) │ semantic/ │ │ │ │ (16路由) │ │ (3路由) │ │ │ └───────────┴───────────┴───────────┘ │ └─────────────────────────────────────────┘ ``` ### 三层 Route Group 规范 ``` 层级 1: (shell)/ → ErrorBoundary(三中心共享错误边界) │ ├── 层级 2: (scene)/ → BsfShell console="scene" + SCENE_NAV │ │ │ ├── builder/ → Agent 构建 + 技能 + 实验室 + 市场 │ └── factory/ → 场景编排 + 数据 + 大屏 + 渠道 + 问数 │ ├── 层级 2: (ops)/ → BsfShell console="ops" + OPS_NAV │ └── ops/ → 运行监控 + 平台治理 + 资源 + 洞察 │ └── 层级 2: (ontology)/ → BsfShell console="ontology" + ONTOLOGY_NAV ├── ontology/ → 本体建模首页 └── semantic/ → 语义实例浏览 ``` > **铁律**:三中心 = 3 个嵌套 Route Group,不平铺在 `(shell)/` 下。 > 场景中心的 builder + factory 共享**一个** `(scene)/layout.tsx` 挂 BsfShell,不各挂一个。 ### 技术栈 ``` ┌─────────────────────────────────────────────────────────┐ │ 前端技术栈 │ │ │ │ ┌─────────────┐ ┌──────────────┐ ┌───────────────┐ │ │ │ Next.js 16 │ │ React 19 │ │ TypeScript │ │ │ │ App Router │ │ RSC + 'use │ │ strict mode │ │ │ │ Route Group │ │ client' │ │ paths @/* │ │ │ └─────────────┘ └──────────────┘ └───────────────┘ │ │ │ │ ┌─────────────┐ ┌──────────────┐ ┌───────────────┐ │ │ │ pnpm │ │ Zustand │ │ @xyflow/ │ │ │ │ workspace │ │ 状态管理 │ │ react │ │ │ │ ui-core + │ │ (stores) │ │ 画布引擎 │ │ │ │ shared │ │ │ │ │ │ │ └─────────────┘ └──────────────┘ └───────────────┘ │ │ │ │ ┌─────────────┐ ┌──────────────┐ ┌───────────────┐ │ │ │ Vitest 4 │ │ ESLint 10 │ │ CSS Modules │ │ │ │ + jsdom │ │ + Prettier │ │ scoped │ │ │ │ + RTL 16 │ │ flat config │ │ styles │ │ │ └─────────────┘ └──────────────┘ └───────────────┘ │ └─────────────────────────────────────────────────────────┘ ``` ### 架构演进历史 ``` 阶段 1 (初始) 阶段 2 (合并) 阶段 3 (R13 扁平化) ┌───────┐ ┌───────┐ ┌───────┐ ┌──────────────────┐ ┌──────────────────┐ │ontology│ │scene- │ │ops- │ │ apps/scene-center/│ │ src/app/ │ │:3001 │ │center │ │center │ │ src/app/ │ │ (shell)/ │ │ │ │:3002 │ │:3003 │ │ (shell)/ │ │ (scene)/ │ └───┬───┘ └──┬───┘ └──┬───┘ │ (scene)/ │ ──────▶ │ (ops)/ │ │ │ │ │ (ops)/ │ 扁平化 │ (ontology)/ │ └────────┴────────┘ │ (ontology)/ │ (删 apps/)│ packages/ │ Nginx :80 └──────────────────┘ │ ui-core/ │ 反代统一端口 │ shared/ │ └──────────────────┘ 1 App · 1 镜像 · 1 端口 ``` --- ## 完整页面清单 > 47 个页面,按三中心 + 独立路由分组。每页标注关键能力。 ### 独立路由(无 Shell)— 3 页面 | # | 路由 | 文件 | 关键能力 | |---|------|------|---------| | 1 | `/` | `app/page.tsx` | 三中心入口卡片,引导用户进入对应中心 | | 2 | `/login` | `app/login/page.tsx` | 统一登录页,复用 ui-core `LoginPage` 组件 | | 3 | `/designer/[id]` | `app/designer/[id]/page.tsx` | **全屏画布编排器**(无 BsfShell),拖拽节点 + 连线 + 配置 + 模拟运行 | ### 场景中心 (scene) — 16 页面 #### Builder 子域 — Agent 构建 | # | 路由 | 关键能力 | |---|------|---------| | 4 | `/builder` | 任务看板:Agent 构建任务概览、进度追踪 | | 5 | `/builder/agents` | 智能体广场:Agent 列表、按类型筛选(TOOL/TASK/ROLE/EMPLOYEE) | | 6 | `/builder/agents/[id]` | Agent 详情:基本信息 + Persona + Reasoning + Execution 配置 + 版本 + 发布向导 | | 7 | `/builder/skills` | 技能市场:技能列表、搜索、版本查看 | | 8 | `/builder/skills/[id]` | 技能详情:版本列表、版本对比(VersionDiffView)、评分表单 | | 9 | `/builder/skills/[id]/score` | 技能评分:评测面板、指标打分 | | 10 | `/builder/market` | 智能体市场:Agent 商品化展示、克隆入口 | | 11 | `/builder/lab` | 智能实验室:ChatTab(对话调试)+ EvalTab(评测)+ MemoryTab(记忆查看) | #### Factory 子域 — 场景编排与价值呈现 | # | 路由 | 关键能力 | |---|------|---------| | 12 | `/factory/scenes` | 场景列表:卡片视图、状态标签(DRAFT/RUNNING/PAUSED)、发布入口 | | 13 | `/factory/scenes/[id]` | 场景详情:场景配置 + 资源面板(SceneResourcesTab)+ 执行历史 + 对话运行入口 | | 14 | `/factory/scenes/[id]/chat` | **运行态对话页**:对话式交互,published 版本执行,轮询取结果 | | 15 | `/factory/automations` | 自动化规则:触发器 + 条件 + 动作配置 | | 16 | `/factory/data` | 数据管道:数据源(SourceStep)→ 处理(PipelinePanel)→ 同步(SyncStep) | | 17 | `/factory/screens` | 决策大屏:可视化看板入口 | | 18 | `/factory/channels` | IM 交付渠道:渠道列表、outboundUrl 配置、启用/停用 | | 19 | `/factory/ask` | 智能问数:自然语言查询入口 | ### 运营中心 (ops) — 24 页面 #### 运行监控 | # | 路由 | 关键能力 | |---|------|---------| | 20 | `/ops` | 运维首页:KPI 总览(Agent 总数/在线/场景数/今日调用量/Tokens/成本)+ 健康度 + 最近执行 | | 21 | `/ops/agents` | Agent 健康度:状态分布、成本统计、删除/暂停操作 | | 22 | `/ops/agents/[id]` | Agent 运行详情:调用历史、成本趋势、状态变更 | | 23 | `/ops/scenes` | 场景监控:执行列表、状态筛选、最近执行详情入口 | | 24 | `/ops/scenes/[id]` | 场景运行详情:场景配置 + 执行历史 | | 25 | `/ops/scenes/[id]/executions/[execId]` | 执行详情:节点级结果(NodeResultDto)、耗时、Token 消耗 | #### 平台治理 | # | 路由 | 关键能力 | |---|------|---------| | 26 | `/ops/projects` | 项目空间:项目列表 | | 27 | `/ops/projects/new` | 新建项目:项目基本信息表单 | | 28 | `/ops/projects/[id]` | 项目详情:概览(OverviewTab)+ Agent 列表(AgentsTab)+ 成员管理(MembersTab)+ 阶段推进 | | 29 | `/ops/org` | 组织管理:组织结构 | | 30 | `/ops/roles` | 角色管理:角色权限配置 | | 31 | `/ops/users` | 用户管理:用户列表、角色分配 | #### 平台资源 | # | 路由 | 关键能力 | |---|------|---------| | 32 | `/ops/models` | 模型管理:Provider 列表(ProviderPanel)+ 模型配置(ModelPanel)+ 对话测试 | | 33 | `/ops/mcp` | MCP 服务器:服务器列表、工具导入、连接测试 | | 34 | `/ops/knowledge` | 知识库:知识库列表、新建 | | 35 | `/ops/knowledge/[id]` | 知识库详情:文档管理、搜索测试、RAG 配置、分块配置 | | 36 | `/ops/delivery` | IM 渠道管理:渠道列表 | | 37 | `/ops/delivery/[id]` | 渠道详情:渠道配置 + 消息记录 | | 38 | `/ops/delivery/[id]/messages` | 消息列表:IM 消息历史 | #### 治理洞察 | # | 路由 | 关键能力 | |---|------|---------| | 39 | `/ops/costs` | 成本中心:Token 消耗 + 美元成本趋势 | | 40 | `/ops/audit` | 审计日志:操作审计追溯 | | 41 | `/ops/reviews` | 审核队列:审批列表、决策(approve/reject/modify) | | 42 | `/ops/alerts` | 告警中心:告警列表、告警规则管理 | | 43 | `/ops/insights` | 飞轮洞察:进化信号、经验注入、飞轮配置 | ### 本体中心 (ontology) — 4 页面 | # | 路由 | 关键能力 | |---|------|---------| | 44 | `/ontology` | 本体首页:对象/逻辑/动作/关系四 Tab 管理(ObjectsTab / LogicsTab / ActionsTab / RelationsTab) | | 45 | `/ontology/semantic` | 语义实例浏览:对象实例 + 关系实例 + 逻辑实例 + 动作执行,五步引导式建模 | | 46 | `/ontology/semantic/objects/[id]` | 对象实例详情:记录列表、字段编辑、关系链接、动作执行 | > **注**:`/factory/workbench`(工作台)和 `/factory/screens`(大屏)共 2 页也属于场景中心,已计入上方编号 17-19 区间。总页面 = 3(独立)+ 16(场景)+ 24(运营)+ 4(本体)= **47 页面**。 --- ## 画布组件族 > 8 个核心文件位于 `packages/ui-core/src/components/factory/`,构成场景画布的全部交互能力。 ### 组件总览 ``` ┌─────────────────────────────────────────────────────────────────┐ │ DesignerPage │ │ (画布容器 + 工具栏 + 运行态锁) │ │ │ │ ┌──────────┐ ┌──────────────────────────┐ ┌───────────────┐ │ │ │ SceneNode │ │ ReactFlow 画布 │ │ SceneNode │ │ │ │ Library │ │ (nodeTypes + edges) │ │ Inspector │ │ │ │ │ │ │ │ │ │ │ │ 节点库 │ │ 拖拽 / 连线 / 选中 │ │ 选中节点的 │ │ │ │ 拖入画布 │ │ 运行态: 只读锁 │ │ 配置面板 │ │ │ │ │ │ runStatus 高亮 │ │ │ │ │ └──────────┘ └──────────────────────────┘ └───────────────┘ │ │ │ │ ┌──────────────────────────────────────────────────────────────┐│ │ │ useSceneDesigner ││ │ │ (画布状态管理 Hook + 双态运行逻辑) ││ │ │ nodes/edges CRUD · 保存 · 发布 · 模拟运行 · 轮询执行 ││ │ └──────────────────────────────────────────────────────────────┘│ │ │ │ ┌─────────────────┐ ┌──────────────────┐ ┌────────────────┐ │ │ │ flow-nodes │ │ scene-designer │ │ SceneAgent │ │ │ │ 9种节点渲染 │ │ -types │ │ Fields │ │ │ │ + runStatus 叠加│ │ DTO + toFlow/ │ │ Agent 配置字段 │ │ │ └─────────────────┘ │ fromFlow 转换 │ └────────────────┘ │ │ └──────────────────┘ │ │ ┌─────────────────────────────────────────────────────────────┐ │ │ │ SceneIntegrationFields · designer.module.css │ │ │ │ 集成字段配置 · 画布样式(节点/连线/runStatus 动画) │ │ │ └─────────────────────────────────────────────────────────────┘ │ └─────────────────────────────────────────────────────────────────┘ ``` ### 8 个文件详解 | # | 文件 | 职责 | 关键导出 | |---|------|------|---------| | 1 | `DesignerPage.tsx` | 画布容器:布局编排(节点库 + ReactFlow + Inspector),运行态只读锁(隐藏节点库/Inspector、禁用拖拽/连线/选中) | `DesignerPage` | | 2 | `useSceneDesigner.ts` | 画布状态引擎:nodes/edges CRUD、保存、发布、模拟运行(不跳转,调 `POST /scenes/{id}/run {version:'draft'}`)、轮询 `executions/{id}` 叠加 `runStatus` | `useSceneDesigner` | | 3 | `flow-nodes.tsx` | 9 种节点类型渲染:`BaseNode` 组件 + `NODE_META` 元数据表 + `runStatus` 状态图标(RUNNING spinner / DONE ✓ / FAILED ✗ / WAITING ⏸) + 条件节点双 Handle | `nodeTypes`, `FlowNodeData`, `FlowNode` | | 4 | `scene-designer-types.ts` | 类型与转换:`SceneDto` / `AgentLite` / `McpServerLite` / `ModelLite` / `ChannelLite` / `OntologyLite`;`toFlow()`(DTO→ReactFlow)/ `fromFlow()`(ReactFlow→DTO)双向转换 | `toFlow`, `fromFlow`, `SceneDto` | | 5 | `SceneNodeLibrary.tsx` | 节点库面板:9 种节点类型可拖拽入画布,按类别分组展示 | `SceneNodeLibrary` | | 6 | `SceneNodeInspector.tsx` | 配置检查器:选中节点后按类型渲染对应配置字段(LLM 模型选择 / MCP 工具选择 / Agent 绑定 / 条件表达式 / HITL 审批角色等) | `SceneNodeInspector` | | 7 | `SceneAgentFields.tsx` | Agent 节点专用配置:Agent 绑定、useTools 开关、模型路由 | `SceneAgentFields` | | 8 | `SceneIntegrationFields.tsx` | 集成配置字段:MCP 工具、本体对象、渠道绑定等跨系统集成参数 | `SceneIntegrationFields` | | — | `designer.module.css` | 画布样式:节点类型配色、runStatus 高亮动画、Handle 样式、spinner | (CSS Module) | ### 9 种节点类型 ``` ┌──────────────────────────────────────────────────────────────────┐ │ 画布节点类型 │ │ │ │ ┌─────────┐ │ │ │ START │ 起点标记(不产出 step,不可删除) │ │ └────┬────┘ │ │ │ │ │ ┌────▼────┐ ┌─────────┐ ┌────────┐ ┌──────────┐ │ │ │ONTOLOGY │ │ AGENT │ │ LLM │ │ MCP │ │ │ │ 本体查询 │ │ Agent │ │ LLM调用 │ │ MCP工具 │ │ │ │ 对象+过滤│ │ 委托 │ │ 模型路由│ │ 工具选择 │ │ │ └─────────┘ └─────────┘ └────────┘ └──────────┘ │ │ │ │ ┌────────────┐ ┌──────────┐ ┌──────────────┐ │ │ │ CONDITION │ │ HITL │ │ NOTIFICATION │ │ │ │ 条件分支 │ │ 人工确认 │ │ 消息通知 │ │ │ │ 双Handle │ │ 审批角色 │ │ 渠道+模板 │ │ │ │ true/false │ │ 超时 │ │ │ │ │ └────────────┘ └──────────┘ └──────────────┘ │ │ │ │ ┌─────────┐ │ │ │ OUTPUT │ 终点标记(终点输出,无 source Handle) │ │ └─────────┘ │ └──────────────────────────────────────────────────────────────────┘ ``` | 节点类型 | 图标 | 编译为 (engine) | 配置字段 | |---------|------|-----------------|---------| | `START` | node-start | — (起点标记) | 无(不可删除) | | `ONTOLOGY` | ontology | 知识检索 step | objectId, filter | | `AGENT` | agent-bot | Agent 委托 step | agentId, useTools | | `LLM` | node-llm | LLM 调用 step | model, systemPrompt, promptTemplate | | `MCP` | mcp | MCP 工具调用 step | toolId, mcpSystem | | `CONDITION` | node-condition | 条件分支 step | expression, trueLabel, falseLabel | | `HITL` | node-hitl | 人工确认 step | approverRole, timeoutMinutes | | `NOTIFICATION` | node-notification | 消息通知 step | channelId, messageTemplate | | `OUTPUT` | node-output | — (终点标记) | template | ### runStatus 状态叠加 ``` 节点 runStatus 状态(叠加在节点样式上) ┌──────────────────────────────────────────────┐ │ PENDING 灰色底 等待执行 │ │ RUNNING 蓝色底 + 旋转动画 (spinner) │ │ WAITING 黄色底 + ⏸ 图标 等待人工确认 │ │ DONE 绿色底 + ✓ 图标 执行完成 │ │ FAILED 红色底 + ✕ 图标 执行失败 │ │ SKIPPED 灰色底 (虚线) 跳过 │ └──────────────────────────────────────────────┘ CSS 类名映射: runPENDING / runRUNNING / runWAITING / runDONE / runFAILED ``` ### 双态运行图示 ``` ┌─── 设计态(FDE 调试)──────────────────┐ │ │ │ 路由: /designer/{id} │ │ 画布: 全屏 ReactFlow │ │ version: draft │ │ │ │ ① FDE 点击「▷ 模拟运行」 │ │ ② POST /scenes/{id}/run │ │ { version: "draft" } │ │ ③ 所有节点重置为 PENDING │ │ ④ 轮询 GET /executions/{id} │ │ → nodeResults 叠加到节点 │ │ → RUNNING 蓝/DONE 绿/FAILED 红 │ │ ⑤ 运行态: 画布只读锁 │ │ 隐藏节点库 + Inspector │ │ 禁用拖拽/连线/选中 │ │ ⑥ FDE 就地看到哪步出错 → 改 → 重跑 │ │ │ │ 目的: 调试编排逻辑 │ └────────────────────────────────────────┘ │ 同一执行引擎 │ ConfigProvider → SceneCompiler → Orchestrator │ 只是 version 参数不同 ▼ ┌─── 运行态(业务用户)──────────────────┐ │ │ │ 路由: /factory/scenes/{id}/chat │ │ 页面: 对话式交互 │ │ version: published │ │ │ │ ① 业务用户输入问题 │ │ ② POST /scenes/{id}/run │ │ { input, version: "published", │ │ sync: true } │ │ ③ 轮询 GET /executions/{id} │ │ ④ 取最后有 output 的节点作为回复 │ │ ⑤ 流式展示对话结果 │ │ │ │ 目的: 问一句拿结果 │ │ 业务用户不关心画布 │ └────────────────────────────────────────┘ ``` > **为什么双态**:Actory 是 B2B 交付平台——FDE 建场景给业务用户用。FDE 要画布调试(节点状态可视化),业务用户只要对话。与 draft/published 双版本天然映射:draft 给画布预览,published 给运行态消费。 ### nodeResults → runStatus 映射链路 ``` 画布节点 id engine TaskStep ExecutionDto (flow-nodes) .step_code .nodeResults │ │ │ │ │ │ └────── 三者天然对齐 ───────┘ │ (SceneCompiler │ step id = 画布 node id) │ │ nodeResults[].status │ ┌─────────▼──────────┐ │ applyNodeResults │ │ (useSceneDesigner)│ │ │ │ Map │ │ │ │ │ ▼ │ │ setNodes(叠加 │ │ runStatus) │ └────────────────────┘ ``` --- ## 共享包 ### 包结构总览 ``` packages/ ├── ui-core/ ← 共享 UI 组件库(66 ts/tsx 文件) │ └── src/ │ ├── index.ts ← 统一导出(57 个 re-export) │ └── components/ │ ├── factory/ ← 画布组件族(8 文件 + 1 CSS) │ ├── builder/ ← Agent 构建组件(13 文件) │ ├── shell/ ← BsfShell + nav(3 文件) │ ├── ui/ ← 页面基元(page/controls/icon) │ ├── shared/ ← 共享组件(ConfirmDialog 等) │ ├── ops/ ← 运营中心组件(charts) │ ├── auth/ ← 登录页 + auth-guard │ └── 基础组件目录 ← Button/Input/Modal/...(12 目录) │ └── shared/ ← 共享逻辑包(20 ts/tsx 文件) └── src/ ├── index.ts ← 统一导出(14 个 re-export) ├── lib/ │ ├── client/ ← API Client 核心(13 文件) │ └── i18n/ ← 国际化(2 文件) └── stores/ ← Zustand stores(2 文件) ``` ### ui-core 子模块说明(66 文件) | 子模块 | 文件数 | 关键组件 | 说明 | |--------|--------|---------|------| | **factory/** | 8+1 | DesignerPage, useSceneDesigner, flow-nodes, SceneNodeLibrary, SceneNodeInspector, SceneAgentFields, SceneIntegrationFields, scene-designer-types | 画布编排全部能力,详见 [画布组件族](#画布组件族) | | **builder/** | 13 | AgentDesigner, AgentBindingsPanel, AgentVersionCard, CanaryChart, CloneAgentModal, CreateAgentModal, HarnessTabs, PublishWizard, SkillMarketGrid, SkillReviewForm, SkillVersionList, VersionDiffView | Agent 构建 + 技能管理 + 发布向导 + 版本对比 | | **shell/** | 3 | BsfShell, nav (SCENE_NAV / OPS_NAV / ONTOLOGY_NAV) | 三中心统一 Shell 框架 + 导航配置 | | **ui/** | 4 | page (PageHeader/StatCard/Panel/Chips/SearchInput/BsfTable/Pill/Dot/EmptyHint/Skeleton), controls (Select/TextInput/Field), icon (IconName 系统), useConfirm | 页面级共享基元,对齐原型设计语言 | | **shared/** | 5 | ConfirmDialog, DataTable, EmptyState, PageHeader, StatusBadge | 扁平版共享组件(与目录组件有重叠,历史原因) | | **ops/** | 2 | charts (趋势图/成本图) | 运营中心专用图表组件 | | **auth/** | 2 | LoginPage, auth-guard (AuthGuard) | 登录页 + 路由鉴权守卫 | | **基础组件** | 12 目录 | Button, Input, Modal, Card, DataTable, EmptyState, Header, Sidebar, StatusBadge, Toast, Skeleton, A2ACard, LayerAccordion, AgentCard | 原子级 UI 组件(自 agent-os-v5 移植) | | **根级** | 3 | error-boundary, index.ts | 错误边界 + 统一导出 | ### shared 子模块说明(20 文件) | 子模块 | 文件数 | 关键导出 | 说明 | |--------|--------|---------|------| | **client/api.ts** | 1 | `apiFetch`, `ApiClientError` | 核心 API 封装(见下方代码示例) | | **client/auth.ts** | 1 | `getToken`, `setToken`, `clearToken` | Token 管理(localStorage) | | **client/types.ts** | 1 | `AgentDto`, `SceneDto`, `ExecutionDto`, `NodeResultDto`, `StatsOverviewDto`, `ModelDto`, `McpToolDto` | API 响应类型定义 | | **client/domain-types.ts** | 1 | `AGENT_TYPES`, `NODE_TYPES`, `EXECUTION_STATUSES`, `SCENE_STATUS_META`, `BUSINESS_RULES` | 领域枚举 + 元数据字典 | | **client/hooks.ts** | 1 | 通用 hooks(数据获取、分页、列表筛选) | 页面级复用 hooks | | **client/pagination.ts** | 1 | 分页工具函数 | 列表分页逻辑 | | **client/stores.ts** | 1 | 全局 Zustand stores | 跨页面状态共享 | | **client/use-debounce.ts** | 1 | `useDebounce` | 搜索输入防抖 | | **client/use-ensure-project.ts** | 1 | `useEnsureProject` | 页面级项目上下文确保 | | **client/format.ts** | 1 | 格式化工具(时间/数字/货币) | 显示层格式化 | | **i18n/** | 2 | `useLocale`, `dictionary` | 中英双语字典 | | **stores/** | 2 | `useAgentStore`, `useProjectStore` | Agent/项目 状态管理 | | **测试** | 4 | api.test, auth.test, pagination.test, hooks.test, use-debounce.test | 82 tests / 5 文件 | ### API Client 代码示例 ```typescript // packages/shared/src/lib/client/api.ts export class ApiClientError extends Error { constructor( public code: string, message: string, public status: number, ) { super(message); } } export function apiFetch(path: string, init?: RequestInit): Promise { const token = getToken(); // localStorage 读取 const headers = new Headers(init?.headers); headers.set('Content-Type', 'application/json'); if (token) headers.set('Authorization', `Bearer ${token}`); return fetch(path, { ...init, headers }) // 相对路径请求 .then(res => { if (res.status === 401 && !token) { window.location.href = '/login'; // 未登录跳转 throw new ApiClientError('UNAUTHORIZED', '未登录', 401); } return res.json().then((body) => { // 兼容 V5 格式 { success: true, data: ... } if (body.success === true) return body.data as T; // 兼容旧格式 { data: ... } if ('data' in body) return body.data as T; // 错误: { success: false, error: { code, message } } throw new ApiClientError(body.error?.code, body.error?.message, res.status); }); }); } // 页面中使用 import { apiFetch } from '@actory/shared'; // GET const agents = await apiFetch('/api/v1/agents'); // POST const result = await apiFetch('/api/v1/scenes/123/run', { method: 'POST', body: JSON.stringify({ input: '分析种猪数据', version: 'published' }), }); ``` --- ## API 调用模式 ### 请求链路 ``` 页面组件 next.config.ts gateway ─────── ────────── ─────── apiFetch('/api/v1/agents') │ │ fetch('/api/v1/agents') rewrites: HTTP │ 相对路径 /api/v1/:path* 转发 │ → 同源请求 → http://localhost:3100 到各后端 │ /api/v1/:path* 服务 └──────────────────────────► Next.js dev proxy ──► gateway :3100 │ ┌────────────────────┼───────────────┐ ▼ ▼ ▼ platform:3002 engine:8000 im-gateway:8003 (设计态数据) (运行态引擎) (IM 渠道) ``` ### 关键设计 | 特性 | 说明 | |------|------| | **相对路径** | `apiFetch` 使用 `fetch(path)` 发相对路径请求,不拼绝对域名 | | **dev 同源代理** | `next.config.ts` 配 `rewrites: /api/v1/:path* → gateway:3100` | | **Bearer Token** | `apiFetch` 自动注入 `Authorization: Bearer ` | | **401 处理** | 无 Token 的 401 → 跳登录;有 Token 的 401 → 抛错(业务鉴权) | | **双格式兼容** | 兼容 V5 `{success, data}` 和旧版 `{data, error}` | | **超时** | 30s AbortController 超时 | | **无 codegen** | 类型全部手写,共享类型在 `shared/lib/client/types.ts` + `domain-types.ts` | ### 页面级 API 调用模式 ``` ┌─────────────────────────────────────────────────────────────┐ │ 通用列表页模式 │ │ │ │ useDebounce(search) ──► debouncedSearch │ │ │ │ │ ▼ │ │ apiFetch(`/api/v1/agents?search=${debouncedSearch}`) │ │ │ │ │ ▼ │ │ useState(data) ──► BsfTable 渲染 │ │ │ │ │ ▼ │ │ pagination (page/pageSize) ──► 翻页重新 fetch │ └─────────────────────────────────────────────────────────────┘ ┌─────────────────────────────────────────────────────────────┐ │ 详情页模式 │ │ │ │ const { id } = useParams() │ │ apiFetch(`/api/v1/agents/${id}`) ──► AgentDto │ │ apiFetch(`/api/v1/stats/agent-cost?agentId=${id}`) │ │ │ │ │ ▼ │ │ useState(agent) + useState(costData) │ │ │ │ │ ▼ │ │ AgentDesigner / KpiCard / charts 渲染 │ └─────────────────────────────────────────────────────────────┘ ┌─────────────────────────────────────────────────────────────┐ │ 场景执行模式 │ │ │ │ 设计态: │ │ apiFetch(`/scenes/${id}/run`, { │ │ method: 'POST', body: { version: 'draft' } │ │ }) │ │ → 轮询 executions/{id} → applyNodeResults → 画布高亮 │ │ │ │ 运行态: │ │ apiFetch(`/scenes/${id}/run`, { │ │ method: 'POST', body: { input, version: 'published' } │ │ }) │ │ → 轮询 executions/{id} → 取最后有 output 的节点 → 回复 │ └─────────────────────────────────────────────────────────────┘ ``` --- ## 跨仓协作 ### 依赖关系图 ``` ┌──────────────────┐ │ actory-frontend │ │ :3000 │ └────────┬─────────┘ │ HTTP /api/v1/* │ ┌────────▼─────────┐ │ gateway :3100 │ └────────┬─────────┘ │ ┌──────────┼──────────────┐ ▼ ▼ ▼ ┌──────────┐ ┌────────┐ ┌────────────┐ │platform │ │engine │ │im-gateway │ │ :3002 │ │:8000 │ │ :8003 │ │设计态数据 │ │运行态 │ │IM 渠道 │ └──────────┘ └───┬────┘ └────────────┘ │ ┌─────▼─────┐ │mcp-gateway│ │ :8001 │ └─────┬─────┘ │ ┌─────▼─────┐ │domain- │ │breeding │ │ :8002 │ └───────────┘ ``` ### 前端调用的后端服务 | 后端服务 | 端口 | 前端调用场景 | |---------|------|------------| | **gateway** | 3100 | 所有 API 请求的唯一入口(dev 同源代理) | | **platform** | 3002 | Agent CRUD、场景 CRUD、项目/组织/角色、模型/MCP/知识库管理 | | **engine** | 8000 | 场景执行(draft/published)、执行历史、对话、SSE | | **im-gateway** | 8003 | IM 渠道管理、消息记录 | ### 前端 → 后端 API 分类 | API 分类 | 典型端点 | 调用页面 | |---------|---------|---------| | **Agent 管理** | `GET/POST/PUT/DELETE /agents` | builder/agents, builder/agents/[id] | | **场景管理** | `GET/POST/PUT /scenes`, `POST /scenes/{id}/run` | factory/scenes, designer, factory/scenes/[id]/chat | | **执行查询** | `GET /executions`, `GET /executions/{id}` | ops/scenes, ops/scenes/[id]/executions/[execId] | | **模型管理** | `GET/PUT /models/providers`, `POST /models/chat` | ops/models | | **MCP 管理** | `GET/POST /mcp`, `POST /mcp/{id}/import` | ops/mcp | | **知识库** | `GET/POST /knowledge`, `PUT /knowledge-bases/{id}/rag-config` | ops/knowledge, ops/knowledge/[id] | | **本体** | `GET/POST/PUT/DELETE /ontology/*` | ontology, ontology/semantic | | **统计** | `GET /stats/overview`, `GET /stats/trend`, `GET /stats/cost` | ops, ops/costs | | **项目** | `GET/POST /projects`, `PUT /projects/{id}/phase` | ops/projects, ops/projects/[id] | | **治理** | `GET /audit`, `GET /approvals`, `POST /approvals/{id}/decide` | ops/audit, ops/reviews | | **进化** | `GET /flywheel`, `PUT /flywheel`, `POST /insights/{id}/inject` | ops/insights | ### 铁律 - 前端**只走 gateway**,不直连任何后端服务 - 前端**无 codegen**,所有类型手写维护 - 前端**不处理后端业务逻辑**,只做渲染 + 请求 + 状态管理 - 三中心**共享一套 API Client**(`@actory/shared`),不各写各的 --- ## 项目结构 ``` actory-frontend/ ├── src/ │ └── app/ │ ├── layout.tsx ← root layout (AuthGuard) │ ├── page.tsx ← 三中心入口卡片 │ ├── login/ │ │ └── page.tsx ← 统一登录 │ ├── designer/ │ │ └── [id]/ │ │ └── page.tsx ← ★ 全屏画布编排器(无 Shell) │ └── (shell)/ ← Route Group(ErrorBoundary) │ ├── layout.tsx ← ErrorBoundary │ │ │ ├── (scene)/ ← 场景中心 Route Group │ │ ├── layout.tsx ← BsfShell console="scene" + SCENE_NAV │ │ ├── builder/ ← Agent 构建 │ │ │ ├── page.tsx ← 任务看板 │ │ │ ├── agents/ │ │ │ │ ├── page.tsx ← 智能体广场 │ │ │ │ └── [id]/ │ │ │ │ └── page.tsx ← Agent 详情 │ │ │ ├── skills/ │ │ │ │ ├── page.tsx ← 技能市场 │ │ │ │ └── [id]/ │ │ │ │ ├── page.tsx ← 技能详情 │ │ │ │ └── score/ │ │ │ │ └── page.tsx ← 技能评分 │ │ │ ├── market/ │ │ │ │ └── page.tsx ← 智能体市场 │ │ │ └── lab/ │ │ │ ├── page.tsx ← 智能实验室 │ │ │ └── components/ │ │ │ ├── ChatTab.tsx ← 对话调试 │ │ │ ├── EvalTab.tsx ← 评测面板 │ │ │ └── MemoryTab.tsx ← 记忆查看 │ │ └── factory/ ← 场景编排 │ │ ├── scenes/ │ │ │ ├── page.tsx ← 场景列表 │ │ │ └── [id]/ │ │ │ ├── page.tsx ← 场景详情 │ │ │ ├── chat/ │ │ │ │ └── page.tsx ← ★ 运行态对话页 │ │ │ └── components/ │ │ │ └── SceneResourcesTab.tsx │ │ ├── data/ ← 数据管道 │ │ │ └── components/ │ │ │ ├── PipelinePanel.tsx │ │ │ ├── SourceStep.tsx │ │ │ └── SyncStep.tsx │ │ ├── automations/ │ │ │ └── page.tsx ← 自动化规则 │ │ ├── screens/ │ │ │ └── page.tsx ← 决策大屏 │ │ ├── channels/ │ │ │ └── page.tsx ← IM 交付渠道 │ │ ├── ask/ │ │ │ └── page.tsx ← 智能问数 │ │ └── workbench/ │ │ └── page.tsx ← 工作台 │ │ │ ├── (ops)/ ← 运营中心 Route Group │ │ └── layout.tsx ← BsfShell console="ops" + OPS_NAV │ │ └── ops/ │ │ ├── page.tsx ← 运维首页 │ │ ├── agents/ │ │ │ ├── page.tsx ← Agent 健康度 │ │ │ └── [id]/ │ │ │ └── page.tsx ← Agent 运行详情 │ │ ├── scenes/ │ │ │ ├── page.tsx ← 场景监控 │ │ │ └── [id]/ │ │ │ ├── page.tsx ← 场景运行详情 │ │ │ └── executions/ │ │ │ └── [execId]/ │ │ │ └── page.tsx ← 执行详情 │ │ ├── projects/ │ │ │ ├── page.tsx ← 项目空间 │ │ │ ├── new/ │ │ │ │ └── page.tsx ← 新建项目 │ │ │ └── [id]/ │ │ │ ├── page.tsx ← 项目详情 │ │ │ └── components/ │ │ │ ├── OverviewTab.tsx │ │ │ ├── AgentsTab.tsx │ │ │ └── MembersTab.tsx │ │ ├── models/ │ │ │ ├── page.tsx ← 模型管理 │ │ │ └── components/ │ │ │ ├── ProviderPanel.tsx │ │ │ └── ModelPanel.tsx │ │ ├── mcp/ │ │ │ └── page.tsx ← MCP 服务器 │ │ ├── knowledge/ │ │ │ ├── page.tsx ← 知识库 │ │ │ └── [id]/ │ │ │ └── page.tsx ← 知识库详情 │ │ ├── delivery/ │ │ │ ├── page.tsx ← IM 渠道管理 │ │ │ └── [id]/ │ │ │ ├── page.tsx ← 渠道详情 │ │ │ └── messages/ │ │ │ └── page.tsx ← 消息列表 │ │ ├── org/page.tsx ← 组织管理 │ │ ├── roles/page.tsx ← 角色管理 │ │ ├── users/page.tsx ← 用户管理 │ │ ├── costs/page.tsx ← 成本中心 │ │ ├── audit/page.tsx ← 审计日志 │ │ ├── reviews/page.tsx ← 审核队列 │ │ ├── alerts/page.tsx ← 告警中心 │ │ ├── insights/page.tsx ← 飞轮洞察 │ │ └── components/ │ │ └── useConfirmDelete.ts ← 共享删除确认 hook │ │ │ └── (ontology)/ ← 本体中心 Route Group │ ├── layout.tsx ← BsfShell console="ontology" + ONTOLOGY_NAV │ ├── page.tsx ← 本体首页 │ ├── components/ │ │ ├── ObjectsTab.tsx │ │ ├── LogicsTab.tsx │ │ ├── ActionsTab.tsx │ │ ├── RelationsTab.tsx │ │ └── CreateModal.tsx │ ├── OntologyGraph.tsx │ └── semantic/ │ ├── page.tsx ← 语义实例浏览 │ ├── objects/ │ │ └── [id]/ │ │ └── page.tsx ← 对象实例详情 │ └── components/ │ ├── ObjectsStep.tsx │ ├── LogicsStep.tsx │ ├── ActionsStep.tsx │ ├── ObjModal.tsx │ ├── LogicModal.tsx │ ├── ActionModal.tsx │ └── RelModal.tsx │ ├── packages/ │ ├── ui-core/ ← 共享 UI 组件库(66 ts/tsx) │ │ ├── src/ │ │ │ ├── index.ts ← 57 个 re-export │ │ │ └── components/ │ │ │ ├── factory/ ← 画布组件族(8+1 文件) │ │ │ │ ├── DesignerPage.tsx │ │ │ │ ├── useSceneDesigner.ts │ │ │ │ ├── flow-nodes.tsx │ │ │ │ ├── scene-designer-types.ts │ │ │ │ ├── SceneNodeLibrary.tsx │ │ │ │ ├── SceneNodeInspector.tsx │ │ │ │ ├── SceneAgentFields.tsx │ │ │ │ ├── SceneIntegrationFields.tsx │ │ │ │ └── designer.module.css │ │ │ ├── builder/ ← Agent 构建组件(13 文件) │ │ │ ├── shell/ ← BsfShell + nav │ │ │ ├── ui/ ← 页面基元 │ │ │ ├── shared/ ← 共享组件 │ │ │ ├── ops/ ← 运营图表 │ │ │ ├── auth/ ← 登录 + 守卫 │ │ │ ├── error-boundary.tsx │ │ │ └── 基础组件/ ← Button/Input/Modal/... │ │ └── package.json │ │ │ └── shared/ ← 共享逻辑包(20 ts/tsx) │ ├── src/ │ │ ├── index.ts ← 14 个 re-export │ │ ├── lib/ │ │ │ ├── client/ ← API Client 核心 │ │ │ │ ├── api.ts ← ★ apiFetch 封装 │ │ │ │ ├── auth.ts ← Token 管理 │ │ │ │ ├── types.ts ← API 响应类型 │ │ │ │ ├── domain-types.ts ← 领域枚举 │ │ │ │ ├── hooks.ts ← 通用 hooks │ │ │ │ ├── pagination.ts ← 分页工具 │ │ │ │ ├── stores.ts ← 全局 stores │ │ │ │ ├── use-debounce.ts ← 防抖 hook │ │ │ │ ├── use-ensure-project.ts ← 项目上下文 │ │ │ │ ├── format.ts ← 格式化工具 │ │ │ │ └── *.test.* ← 测试(82 tests) │ │ │ └── i18n/ ← 国际化 │ │ └── stores/ ← Zustand stores │ └── package.json │ ├── package.json ← App 依赖(next/react/workspace:*) ├── next.config.ts ← transpilePackages + rewrites + redirects ├── tsconfig.json ← paths @/* → ./src/* ├── Dockerfile ← 1 个镜像(node:22-alpine) ├── eslint.config.mjs ← ESLint flat config ├── vitest.config.ts ← Vitest + jsdom + React 19 ├── vitest.setup.ts ← mock next/navigation + localStorage ├── pnpm-workspace.yaml ← packages/* only ├── .npmrc ← pnpm 配置 ├── .prettierrc ← Prettier 配置 └── pnpm-lock.yaml ← 锁定文件 ``` --- ## 开发指南 ### 环境准备 ```bash pnpm install # 安装依赖(含 workspace 包) cp .env.example .env # 配置环境变量(可选,dev 用 rewrites 代理) ``` ### 日常开发 ```bash pnpm dev # 启动 dev server(:3000) pnpm build # 生产构建(47 路由) pnpm typecheck # TypeScript 类型检查(tsc --noEmit) pnpm test # Vitest 单元测试(82 tests) pnpm test:watch # 监听模式 pnpm test:coverage # 覆盖率 pnpm lint # ESLint 检查 pnpm lint:fix # ESLint 自动修复 pnpm format # Prettier 格式化 pnpm format:check # Prettier 检查 ``` ### 前置依赖 | 依赖 | 端口 | 说明 | |------|------|------| | **gateway** | 3100 | dev 模式由 `next.config.ts` rewrites 代理,所有 API 请求入口 | | **platform** | 3002 | 设计态数据(Agent/场景/项目 CRUD),gateway 转发 | | **engine** | 8000 | 运行态引擎(场景执行/对话/SSE),gateway 转发 | | **Redis** | 6379 | engine 依赖(SSE PubSub + 缓存),非前端直接依赖 | ### 验证工作流 ``` 开发流程 │ ① pnpm typecheck (tsc --noEmit) ← 先查类型错误(快) │ ② pnpm test ← 单元测试(82 tests) │ ③ pnpm lint ← ESLint 检查 │ ④ pnpm build ← 完整构建(47 路由产出) │ ⑤ pnpm dev → 浏览器验证 ← 页面渲染验证 │ ⑥ 提交前确认: - 同一 console 标识不重复挂 BsfShell - page.tsx 不超过 400 行 - 无 V5 遗产残留(employee/foundry console 标识) ``` ### 注意事项 | 事项 | 说明 | |------|------| | **ui-core 组件 API 签名** | 组件分散在多目录,API 签名不统一(`sub` vs `subtitle`,`hierarchy` vs `variant`)。写页面前先 `grep -rn "export function" packages/ui-core/src/components/` 确认签名 | | **BsfTable 用法** | 手写 `` 行,不是 columns/data 声明式:`{items.map(i => ...)}` | | **Route Group 嵌套** | 子路由自动继承上层 layout——子路由除非要换 console/nav,否则不要写 `layout.tsx`。检查:`find src/app -name 'layout.tsx' \| xargs grep -l 'BsfShell'`,同一 console 出现两次就是重复 | | **V5 遗产** | grep 到 `employee`/`foundry` 时看上下文:`employeeNo`/Agent type `'employee'` 是业务语义,`console="employee"` 是 V5 残留需改 `scene` | | **transpilePackages** | `next.config.ts` 配了 `transpilePackages: ['@actory/ui-core', '@actory/shared']`,workspace 内 TS 源码包以源码形式被引用 | | **React 19 + RTL 16** | Vitest 配了 jsdom + React 19 act 兼容(`NODE_ENV=development`),详见 test-generation skill | | **旧路由重定向** | `next.config.ts` 配了 5 个 redirects(V5 遗产路由 → ops/ontology),防外链断裂 |