完成 Muse Studio React SPA 基座和六个用户端功能域,接入 MSW Mock、Tiptap 写作台、知识库资料管理、智能体槽位预检绑定、市场授权安装和个人中心用量权益视图。
193 lines
6.6 KiB
Markdown
193 lines
6.6 KiB
Markdown
# muse-studio 智能体、市场、个人中心实现留痕
|
||
|
||
## 任务背景
|
||
|
||
继续执行 `docs/superpowers/plans/2026-05-24-P2-muse-studio.md` 的 P2 用户端搭建任务。接手时,`muse-studio` 已经完成脚手架、基础设施、写作台、作品工作区和知识库工作台;本次重点补齐剩余三个用户端功能域:
|
||
|
||
- 智能体工作台
|
||
- 创作市场
|
||
- 个人中心
|
||
|
||
同时修复当前代码基线的 TypeScript / ESLint 阻断,补齐对应 Hook 测试和页面冒烟验证。
|
||
|
||
## 已完成内容
|
||
|
||
### 1. 智能体工作台
|
||
|
||
新增智能体功能域:
|
||
|
||
- `src/features/agent/hooks/useAgents.ts`
|
||
- `src/features/agent/components/AgentList.tsx`
|
||
- `src/features/agent/components/AgentCreateForm.tsx`
|
||
- `src/features/agent/components/SlotBindingPanel.tsx`
|
||
- `src/features/agent/hooks/useAgents.test.tsx`
|
||
- `src/pages/AgentPage.tsx`
|
||
|
||
实现能力:
|
||
|
||
- 查询系统默认与用户自建智能体列表。
|
||
- 创建用户自建配置型智能体。
|
||
- 在沙盒上下文中试用智能体,结果只进入预览,不写作品事实。
|
||
- 查询作品开放智能体槽位。
|
||
- 执行槽位预检,再消费预检凭证绑定槽位,避免直接写槽位事实。
|
||
- 保护节点只读展示,不允许前端发起替换。
|
||
|
||
对应 Mock API 在 `src/api/mocks/handlers/ai.ts` 中补齐:
|
||
|
||
- `GET /app-api/muse/agents`
|
||
- `POST /app-api/muse/agents`
|
||
- `POST /app-api/muse/agents/:agentId/test`
|
||
- `GET /app-api/muse/works/:workId/agent-slots`
|
||
- `POST /app-api/muse/works/:workId/agent-slots/:slotKey/prechecks`
|
||
- `POST /app-api/muse/works/:workId/agent-slots/:slotKey/bind`
|
||
|
||
### 2. 创作市场
|
||
|
||
新增市场功能域:
|
||
|
||
- `src/features/market/hooks/useMarket.ts`
|
||
- `src/features/market/components/MarketBrowse.tsx`
|
||
- `src/features/market/hooks/useMarket.test.tsx`
|
||
- `src/pages/MarketPage.tsx`
|
||
|
||
实现能力:
|
||
|
||
- 按作品、智能体、知识库三类资产筛选市场列表。
|
||
- 支持关键词搜索。
|
||
- 展示分类摘要。
|
||
- 获取市场资产授权。
|
||
- 安装已授权的智能体或知识库到账户可用资产列表。
|
||
- 明确区分“授权获取”和“安装”,不暗示自动绑定作品或写入作品事实。
|
||
|
||
对应 Mock API 在 `src/api/mocks/handlers/market.ts` 中补齐:
|
||
|
||
- `GET /app-api/muse/marketplace/assets`
|
||
- `GET /app-api/muse/marketplace/categories`
|
||
- `GET /app-api/muse/marketplace/assets/:assetId`
|
||
- `POST /app-api/muse/marketplace/assets/:assetId/purchase`
|
||
- `POST /app-api/muse/marketplace/assets/:assetId/install`
|
||
|
||
### 3. 个人中心
|
||
|
||
新增个人中心功能域:
|
||
|
||
- `src/features/account/hooks/useAccount.ts`
|
||
- `src/features/account/components/PersonalCenter.tsx`
|
||
- `src/features/account/components/UsageStats.tsx`
|
||
- `src/features/account/hooks/useAccount.test.tsx`
|
||
- `src/pages/AccountPage.tsx`
|
||
|
||
实现能力:
|
||
|
||
- 展示账户资料、账号状态、邮箱和手机号验证状态。
|
||
- 支持保存昵称和公开署名。
|
||
- 展示账户级 Token 用量、待归属数量、计量异常数量。
|
||
- 展示权益、配额和资源使用进度。
|
||
- 展示用量归属分布。
|
||
|
||
对应 Mock API 在 `src/api/mocks/handlers/account.ts` 中补齐:
|
||
|
||
- `GET /app-api/muse/profile`
|
||
- `PATCH /app-api/muse/profile`
|
||
- `GET /app-api/muse/account/entitlements`
|
||
- `GET /app-api/muse/account/usage`
|
||
|
||
## 关键工程实践与避坑
|
||
|
||
### 1. 以当前 OpenAPI 为准,不沿用旧计划里的简化路径
|
||
|
||
P2 计划中的部分路径仍是早期简化版,例如:
|
||
|
||
- `/agents/:agentId/slots`
|
||
- `/market/assets`
|
||
- `/account/profile`
|
||
|
||
当前真实 OpenAPI 已经演进为:
|
||
|
||
- `/app-api/muse/agents`
|
||
- `/app-api/muse/works/{workId}/agent-slots`
|
||
- `/app-api/muse/marketplace/assets`
|
||
- `/app-api/muse/profile`
|
||
- `/app-api/muse/account/usage`
|
||
- `/app-api/muse/account/entitlements`
|
||
|
||
后续继续 P2 或 P3 时,应优先以 `docs/api-contracts/generated/typescript/*`、`muse-studio/src/types/*` 和当前产品规格为准,不直接照抄旧 plan 路径。
|
||
|
||
### 2. `exactOptionalPropertyTypes` 下不能显式传 `undefined`
|
||
|
||
新增测试和 Mock 时多次遇到该问题:
|
||
|
||
- 可选字段如果值可能是 `undefined`,不要写进对象字面量。
|
||
- 需要先构造基础对象,再按条件追加字段。
|
||
- 测试中如果字段必填,应先用 `if (!slot) throw new Error(...)` 做显式收窄,再传 `slot.revision`。
|
||
|
||
典型写法:
|
||
|
||
```typescript
|
||
const dto: AgentCreateDTO = { name: name.trim() };
|
||
if (trimmedDescription) {
|
||
dto.description = trimmedDescription;
|
||
}
|
||
```
|
||
|
||
### 3. React 新 lint 规则更严格
|
||
|
||
之前 `MuseEditor` 中使用 `useCallback(debounce(...))` 会触发 React Hooks 静态规则。已调整为 `useMemo(() => debounce(...), deps)`。
|
||
|
||
组件文件中导出非组件函数也会触发 Fast Refresh 规则,因此将知识库类型守卫移到:
|
||
|
||
- `src/features/knowledge/utils/typeGuards.ts`
|
||
|
||
### 4. 市场和智能体必须保持 owner 边界
|
||
|
||
市场获取授权不等于安装,安装不等于作品绑定。智能体槽位绑定必须先预检,再绑定:
|
||
|
||
1. 调用 `prechecks` 获取短期 `agentSlotPrecheckId`。
|
||
2. 调用 `bind` 消费该凭证。
|
||
3. Mock 中会校验槽位 revision,避免直接跳过预检写入槽位。
|
||
|
||
这符合产品规格中“市场不拥有最终业务事实,目标 owner 空间最终确认”的边界。
|
||
|
||
## 验证记录
|
||
|
||
本次收口执行过以下验证:
|
||
|
||
```bash
|
||
pnpm exec tsc -b --pretty false
|
||
pnpm exec vitest run
|
||
pnpm lint
|
||
pnpm build
|
||
```
|
||
|
||
结果:
|
||
|
||
- TypeScript 编译通过。
|
||
- Vitest:7 个测试文件、23 个测试全部通过。
|
||
- ESLint:退出码 0;仅 `public/mockServiceWorker.js` 生成文件存在 unused eslint-disable warning。
|
||
- Vite build 通过;存在 chunk > 500KB 提示,后续可做路由级 code splitting。
|
||
|
||
还启动过开发服务器:
|
||
|
||
```bash
|
||
pnpm dev --host 127.0.0.1
|
||
```
|
||
|
||
并使用 Playwright + 本机 Chrome 冒烟访问:
|
||
|
||
- `http://127.0.0.1:5173/agents`
|
||
- `http://127.0.0.1:5173/market`
|
||
- `http://127.0.0.1:5173/account`
|
||
|
||
截图检查结论:
|
||
|
||
- 页面非空。
|
||
- 主要标题、列表、卡片、用量和权益面板可见。
|
||
- 未发现明显文字重叠、空白页或加载失败状态。
|
||
|
||
## 后续建议
|
||
|
||
1. 如果继续 P2,可补 Playwright E2E 用例,覆盖作品创建、写作台 AI 生成、智能体试用、市场授权安装、个人资料保存。
|
||
2. 当前构建包提示超过 500KB,后续可以按路由拆分 `AgentPage`、`MarketPage`、`AccountPage` 等功能域。
|
||
3. `public/mockServiceWorker.js` 的 lint warning 来自生成文件,可通过 ESLint ignore 或生成文件豁免处理,不建议手改生成文件。
|
||
4. P2 plan 清单仍未同步真实完成状态,后续可以单独更新计划文档,明确 Feature 3 实际已演进为“知识库列表 + 资料管理”形态,而不是旧版“实体/草稿/图谱”。
|