feat(automation): complete unified automation system redesign

Phase 4 completion:
- Add ApprovalQueue component for managing pending approvals
- Add ExecutionResult component for displaying hand/workflow results
- Update Sidebar navigation to use unified AutomationPanel
- Replace separate 'hands' and 'workflow' tabs with single 'automation' tab
- Fix TypeScript type safety issues with unknown types in JSX expressions

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
iven
2026-03-18 17:12:05 +08:00
parent 3a7631e035
commit 3518fc8ece
74 changed files with 4984 additions and 687 deletions

View File

@@ -546,6 +546,187 @@ if (clones && clones.length > 0) {
2. 重新启动应用
3. 完成引导流程 → 应该成功更新默认 Agent
### 3.4 刷新页面后对话内容丢失
**症状**: 切换 Tab 时对话正常保留,但按 F5 刷新页面后对话内容消失
**根本原因**: `onComplete` 回调中没有将当前对话保存到 `conversations` 数组,导致 `persist` 中间件无法持久化
**问题分析**:
Zustand 的 `persist` 中间件只保存 `partialize` 中指定的字段:
```typescript
partialize: (state) => ({
conversations: state.conversations, // ← 从这里恢复
currentModel: state.currentModel,
currentAgentId: state.currentAgent?.id,
currentConversationId: state.currentConversationId,
}),
```
但 `messages` 数组只在内存中,刷新后丢失。恢复逻辑依赖 `conversations` 数组:
```typescript
onRehydrateStorage: () => (state) => {
if (state?.currentConversationId && state.conversations) {
const currentConv = state.conversations.find(c => c.id === state.currentConversationId);
if (currentConv) {
state.messages = [...currentConv.messages]; // ← 从 conversations 恢复
}
}
},
```
**问题**: `onComplete` 回调中只更新了 `messages`,没有调用 `upsertActiveConversation` 保存到 `conversations`
**修复代码**:
```typescript
onComplete: () => {
const state = get();
// Save conversation to persist across refresh
const conversations = upsertActiveConversation([...state.conversations], state);
const currentConvId = state.currentConversationId || conversations[0]?.id;
set({
isStreaming: false,
conversations, // ← 保存到 conversations 数组
currentConversationId: currentConvId, // ← 确保 ID 被设置
messages: state.messages.map((m) =>
m.id === assistantId ? { ...m, streaming: false, runId } : m
),
});
// ... rest of the callback
},
```
**文件**: `desktop/src/store/chatStore.ts`
**验证修复**:
1. 发送消息并获得 AI 回复
2. 按 F5 刷新页面
3. 对话内容应该保留
### 3.5 ChatArea 输入框布局错乱
**症状**: 对话过程中输入框被移动到页面顶部,而不是固定在底部
**根本原因**: `ChatArea` 组件返回的是 React Fragment (`<>...</>`),没有包裹在 flex 容器中
**问题代码**:
```typescript
// ❌ 错误 - Fragment 没有 flex 布局
return (
<>
<div className="h-14 ...">Header</div>
<div className="flex-1 ...">Messages</div>
<div className="border-t ...">Input</div>
</>
);
```
**修复代码**:
```typescript
// ✅ 正确 - 使用 flex 容器
return (
<div className="flex flex-col h-full">
<div className="h-14 flex-shrink-0 ...">Header</div>
<div className="flex-1 overflow-y-auto ...">Messages</div>
<div className="flex-shrink-0 ...">Input</div>
</div>
);
```
**文件**: `desktop/src/components/ChatArea.tsx`
**布局原理**:
```
┌─────────────────────────────────────┐
│ Header (h-14, flex-shrink-0) │ ← 固定高度
├─────────────────────────────────────┤
│ │
│ Messages (flex-1, overflow-y-auto) │ ← 占据剩余空间,可滚动
│ │
├─────────────────────────────────────┤
│ Input (flex-shrink-0) │ ← 固定在底部
└─────────────────────────────────────┘
```
---
## 7. 记忆系统问题
### 7.1 Memory Tab 为空,多轮对话后无记忆
**症状**: 经过多次对话后,右侧面板的"记忆"Tab 内容为空
**根本原因**: 多个配置问题导致记忆未被提取
**问题分析**:
1. **LLM 提取默认禁用**: `useLLM: false` 导致只使用规则提取
2. **提取阈值过高**: `minMessagesForExtraction: 4` 短对话不会触发
3. **agentId 不一致**: `MemoryPanel` 用 `'zclaw-main'``MemoryGraph` 用 `'default'`
4. **Gateway 端点不存在**: `GatewayLLMAdapter` 调用 `/api/llm/complete`OpenFang 无此端点
**修复方案**:
```typescript
// 1. 启用 LLM 提取 (memory-extractor.ts)
export const DEFAULT_EXTRACTION_CONFIG: ExtractionConfig = {
useLLM: true, // 从 false 改为 true
minMessagesForExtraction: 2, // 从 4 降低到 2
// ...
};
// 2. 统一 agentId fallback (MemoryGraph.tsx)
const agentId = currentAgent?.id || 'zclaw-main'; // 从 'default' 改为 'zclaw-main'
// 3. 修复 Gateway 适配器端点 (llm-service.ts)
// 使用 OpenFang 的 /api/agents/{id}/message 端点
const response = await fetch(`/api/agents/${agentId}/message`, {
method: 'POST',
body: JSON.stringify({ message: fullPrompt, ... }),
});
```
**文件**:
- `desktop/src/lib/memory-extractor.ts`
- `desktop/src/lib/llm-service.ts`
- `desktop/src/components/MemoryGraph.tsx`
**验证修复**:
1. 打开浏览器控制台
2. 进行至少 2 轮对话
3. 查看日志: `[MemoryExtractor] Using LLM-powered semantic extraction`
4. 检查 Memory Tab 是否显示提取的记忆
### 7.2 Memory Graph UI 与系统风格不一致
**症状**: 记忆图谱使用深色主题,与系统浅色主题不协调
**根本原因**: `MemoryGraph.tsx` 硬编码深色背景 `#1a1a2e`
**修复方案**:
```typescript
// Canvas 背景 - 支持亮/暗双主题
ctx.fillStyle = '#f9fafb'; // gray-50 (浅色)
// 工具栏 - 添加 dark: 变体
<div className="bg-gray-100 dark:bg-gray-800/50">
// 图谱画布 - 添加 dark: 变体
<div className="bg-gray-50 dark:bg-gray-900">
```
**文件**: `desktop/src/components/MemoryGraph.tsx`
**设计规范**:
- 使用 Tailwind 的 `dark:` 变体支持双主题
- 强调色使用 `orange-500` 而非 `blue-600`
- 文字颜色使用 `gray-700 dark:text-gray-300`
---
## 8. 相关文档
@@ -560,6 +741,8 @@ if (clones && clones.length > 0) {
| 日期 | 变更 |
|------|------|
| 2026-03-18 | 添加记忆提取和图谱 UI 问题 |
| 2026-03-18 | 添加刷新后对话丢失问题和 ChatArea 布局问题 |
| 2026-03-17 | 添加首次使用引导流程 |
| 2026-03-17 | 添加配置热重载限制问题 |
| 2026-03-14 | 初始版本 |