Some checks failed
CI / Lint & TypeCheck (push) Has been cancelled
CI / Unit Tests (push) Has been cancelled
CI / Build Frontend (push) Has been cancelled
CI / Rust Check (push) Has been cancelled
CI / Security Scan (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled
重构所有代码和文档中的项目名称,将OpenFang统一更新为ZCLAW。包括: - 配置文件中的项目名称 - 代码注释和文档引用 - 环境变量和路径 - 类型定义和接口名称 - 测试用例和模拟数据 同时优化部分代码结构,移除未使用的模块,并更新相关依赖项。
22 KiB
22 KiB
ZCLAW Hands & Workflow 集成开发方案
上下文
目标: 将 ZCLAW 的 Hands 和 Workflow 功能深度集成到 ZClaw 桌面客户端,提供与 ZCLAW Web 界面对等的用户体验。
当前状态:
- ZClaw 已有基础的
HandsPanel.tsx和WorkflowList.tsx组件 - 这些组件功能有限,缺少 ZCLAW 的核心 UI 特性
- ZCLAW v0.4.0 提供了 8 个 Hands 和完整的 Workflow/Scheduler 系统
参考界面: http://127.0.0.1:50051 (ZCLAW Dashboard)
一、ZCLAW 界面分析总结
1.1 Hands 页面设计
┌─────────────────────────────────────────────────────────────────┐
│ Hands — Curated Autonomous Capability Packages │
│ Available 8 Active │
├─────────────────────────────────────────────────────────────────┤
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ 🌐 Browser Hand [READY] │ │
│ │ Autonomous web browser — navigates sites... │ │
│ │ │ │
│ │ REQUIREMENTS │ │
│ │ ✓ Python 3 must be installed │ │
│ │ ✓ Chromium or Google Chrome must be installed │ │
│ │ │ │
│ │ 18 tool(s) · 3 metric(s) [productivity] │ │
│ │ [Details] [Activate] │ │
│ └─────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
详情弹窗内容:
- AGENT CONFIG: Provider, Model
- REQUIREMENTS: 检查项和状态 (✓/✗)
- TOOLS: 工具名称列表
- DASHBOARD METRICS: 指标名称列表
- Activate 按钮
1.2 Workflows 页面设计
┌─────────────────────────────────────────────────────────────────┐
│ Workflows │
│ What are Workflows? Workflows chain multiple agents... │
│ [List] [Visual Builder] [+ New Workflow] │
├─────────────────────────────────────────────────────────────────┤
│ NAME │ STEPS │ CREATED │ ACTIONS │
│ ──────────────────┼───────┼──────────────┼────────────────────│
│ 测试工作流 │ 1 │ 2026/3/14 │ [Run][Edit][Del] │
└─────────────────────────────────────────────────────────────────┘
1.3 Scheduler 页面设计
┌─────────────────────────────────────────────────────────────────┐
│ Scheduler [+ New Job] │
│ [Scheduled Jobs] [Event Triggers] [Run History] │
├─────────────────────────────────────────────────────────────────┤
│ Scheduled Jobs │
│ Create cron-based scheduled jobs... │
│ │
│ [No scheduled jobs] │
│ Create a cron job to run agents on a recurring schedule. │
│ [+ Create Scheduled Job] │
└─────────────────────────────────────────────────────────────────┘
1.4 Approvals 页面设计
┌─────────────────────────────────────────────────────────────────┐
│ Execution Approvals [Refresh] │
│ [All] [Pending] [Approved] [Rejected] │
├─────────────────────────────────────────────────────────────────┤
│ [No approvals] │
│ When agents request permission for sensitive actions, │
│ they'll appear here. │
└─────────────────────────────────────────────────────────────────┘
二、ZClaw 现有实现分析
2.1 已有组件
| 文件 | 功能 | 完成度 |
|---|---|---|
HandsPanel.tsx |
Hand 列表、触发、审批、取消 | 40% |
WorkflowList.tsx |
Workflow 列表、执行 | 30% |
TriggersPanel.tsx |
Trigger 列表 | 20% |
gatewayStore.ts |
状态管理 (Hands/Workflow API) | 60% |
2.2 缺失功能
-
Hands:
- ❌ 详情弹窗 (Details Modal)
- ❌ Requirements 状态检查可视化
- ❌ 工具和指标列表展示
- ❌ Agent Config 显示 (Provider/Model)
- ❌ 激活动画和状态反馈
- ❌ 分类标签 (productivity/data/content/communication)
-
Workflows:
- ❌ 创建/编辑 Workflow
- ❌ Visual Builder
- ❌ 执行历史查看
- ❌ 步骤详情展示
-
Scheduler:
- ❌ Scheduled Jobs 管理
- ❌ Event Triggers 管理
- ❌ Cron 表达式编辑器
- ❌ Run History
-
Approvals:
- ❌ 独立 Approvals 页面
- ❌ 筛选功能 (All/Pending/Approved/Rejected)
- ❌ 审批详情展示
三、开发方案
3.1 Phase 1: 增强 HandsPanel (优先级: 高)
目标: 提供与 ZCLAW 对等的 Hands 管理体验
文件修改:
desktop/src/components/HandsPanel.tsx(重写)desktop/src/components/HandDetailsModal.tsx(新建)desktop/src/store/gatewayStore.ts(扩展)
UI 设计:
// HandCard 组件结构
<div className="hand-card">
<div className="hand-header">
<span className="hand-icon">{hand.icon}</span>
<h3>{hand.name}</h3>
<StatusBadge status={hand.status} /> {/* READY/SETUP NEEDED/RUNNING */}
</div>
<p className="hand-description">{hand.description}</p>
{/* Requirements 检查 */}
{hand.requirements && (
<div className="hand-requirements">
<span className="label">REQUIREMENTS</span>
{hand.requirements.map(req => (
<div className={req.met ? 'met' : 'unmet'}>
<span>{req.met ? '✓' : '✗'}</span>
<span>{req.description}</span>
</div>
))}
</div>
)}
{/* 元信息 */}
<div className="hand-meta">
<span>{hand.toolCount} tool(s)</span>
<span>{hand.metricCount} metric(s)</span>
<span className="category-tag">{hand.category}</span>
</div>
{/* 操作按钮 */}
<div className="hand-actions">
<Button variant="outline" onClick={onDetails}>Details</Button>
<Button variant="primary" onClick={onActivate} disabled={!hand.requirementsMet}>
{hand.status === 'running' ? 'Running...' : 'Activate'}
</Button>
</div>
</div>
HandDetailsModal 组件:
// 详情弹窗
<Modal>
<ModalHeader>
<span className="icon">{hand.icon}</span>
<h2>{hand.name}</h2>
<StatusBadge status={hand.status} />
</ModalHeader>
<ModalBody>
{/* Agent Config */}
<Section title="AGENT CONFIG">
<Row label="Provider" value={hand.provider} />
<Row label="Model" value={hand.model} />
</Section>
{/* Requirements */}
<Section title="REQUIREMENTS">
{hand.requirements.map(req => (
<RequirementItem {...req} />
))}
</Section>
{/* Tools */}
<Section title="TOOLS">
<ToolGrid tools={hand.tools} />
</Section>
{/* Dashboard Metrics */}
<Section title="DASHBOARD METRICS">
<MetricList metrics={hand.metrics} />
</Section>
</ModalBody>
<ModalFooter>
<Button variant="outline" onClick={onClose}>Close</Button>
<Button variant="primary" onClick={onActivate}>Activate</Button>
</ModalFooter>
</Modal>
API 扩展:
// gatewayStore.ts 扩展
interface Hand {
id: string;
name: string;
description: string;
status: 'idle' | 'running' | 'needs_approval' | 'error' | 'unavailable';
icon?: string;
category?: string; // productivity, data, content, communication
provider?: string;
model?: string;
requirements?: Array<{
description: string;
met: boolean;
details?: string;
}>;
tools?: string[];
metrics?: string[];
toolCount?: number;
metricCount?: number;
currentRunId?: string;
}
// 新增 API 调用
getHandDetails: (name: string) => Promise<HandDetails>;
activateHand: (name: string, params?: Record<string, unknown>) => Promise<HandRun>;
deactivateHand: (name: string) => Promise<void>;
3.2 Phase 2: 增强 WorkflowList (优先级: 高)
目标: 提供完整的 Workflow 管理能力
文件修改:
desktop/src/components/WorkflowList.tsx(重写)desktop/src/components/WorkflowEditor.tsx(新建)desktop/src/components/WorkflowHistory.tsx(新建)desktop/src/store/gatewayStore.ts(扩展)
UI 设计:
// WorkflowList 组件结构
<div className="workflow-list">
<div className="workflow-header">
<h2>Workflows</h2>
<div className="view-toggle">
<Button active={view === 'list'}>List</Button>
<Button active={view === 'visual'}>Visual Builder</Button>
</div>
<Button variant="primary" onClick={onCreate}>+ New Workflow</Button>
</div>
<p className="workflow-description">
Workflows chain multiple agents into automated pipelines...
</p>
<table className="workflow-table">
<thead>
<tr>
<th>NAME</th>
<th>STEPS</th>
<th>CREATED</th>
<th>ACTIONS</th>
</tr>
</thead>
<tbody>
{workflows.map(wf => (
<tr key={wf.id}>
<td>{wf.name}</td>
<td>{wf.steps}</td>
<td>{formatDate(wf.createdAt)}</td>
<td>
<Button size="sm" onClick={() => onRun(wf.id)}>Run</Button>
<Button size="sm" onClick={() => onEdit(wf.id)}>Edit</Button>
<Button size="sm" onClick={() => onHistory(wf.id)}>History</Button>
<Button size="sm" variant="danger" onClick={() => onDelete(wf.id)}>Delete</Button>
</td>
</tr>
))}
</tbody>
</table>
</div>
WorkflowEditor 组件 (简化版):
<WorkflowEditor workflow={workflow}>
<div className="workflow-editor">
<div className="workflow-info">
<Input label="Name" value={workflow.name} onChange={...} />
<Textarea label="Description" value={workflow.description} onChange={...} />
</div>
<div className="workflow-steps">
<h3>Steps</h3>
{workflow.steps.map((step, index) => (
<WorkflowStep
key={index}
step={step}
onEdit={() => editStep(index)}
onDelete={() => deleteStep(index)}
/>
))}
<Button onClick={addStep}>+ Add Step</Button>
</div>
<div className="workflow-actions">
<Button variant="outline" onClick={onCancel}>Cancel</Button>
<Button variant="primary" onClick={onSave}>Save Workflow</Button>
</div>
</div>
</WorkflowEditor>
API 扩展:
// gatewayStore.ts 扩展
interface Workflow {
id: string;
name: string;
description?: string;
steps: WorkflowStep[];
createdAt: string;
updatedAt?: string;
}
interface WorkflowStep {
id: string;
agentId: string;
promptTemplate: string;
inputMapping?: Record<string, string>;
outputMapping?: Record<string, string>;
condition?: string;
timeout?: number;
}
// 新增 API 调用
createWorkflow: (workflow: CreateWorkflowInput) => Promise<Workflow>;
updateWorkflow: (id: string, updates: Partial<Workflow>) => Promise<Workflow>;
getWorkflowHistory: (id: string) => Promise<WorkflowRun[]>;
getWorkflowDetails: (id: string) => Promise<Workflow>;
3.3 Phase 3: 新建 SchedulerPanel (优先级: 中)
目标: 提供定时任务和事件触发器管理
文件新建:
desktop/src/components/SchedulerPanel.tsxdesktop/src/components/ScheduledJobEditor.tsxdesktop/src/components/EventTriggerEditor.tsx
UI 设计:
<SchedulerPanel>
<Tabs defaultValue="scheduled">
<TabsList>
<TabsTrigger value="scheduled">Scheduled Jobs</TabsTrigger>
<TabsTrigger value="triggers">Event Triggers</TabsTrigger>
</TabsList>
<TabsContent value="scheduled">
<div className="scheduled-jobs">
<Button onClick={onCreateJob}>+ Create Scheduled Job</Button>
{jobs.length === 0 ? (
<EmptyState
title="No scheduled jobs"
description="Create a cron job to run agents on a recurring schedule."
action="+ Create Scheduled Job"
onAction={onCreateJob}
/>
) : (
<JobList jobs={jobs} onEdit={onEditJob} onDelete={onDeleteJob} />
)}
</div>
</TabsContent>
<TabsContent value="triggers">
<div className="event-triggers">
<p>Event triggers fire agents in response to system events...</p>
{triggers.length === 0 ? (
<EmptyState title="No event triggers" />
) : (
<TriggerList triggers={triggers} />
)}
</div>
</TabsContent>
</Tabs>
</SchedulerPanel>
3.4 Phase 4: 新建 ApprovalsPanel (优先级: 中)
目标: 提供审批管理界面
文件新建:
desktop/src/components/ApprovalsPanel.tsx
UI 设计:
<ApprovalsPanel>
<div className="approvals-header">
<h2>Execution Approvals</h2>
<Button onClick={onRefresh}>Refresh</Button>
</div>
<div className="approvals-filters">
<Button active={filter === 'all'}>All</Button>
<Button active={filter === 'pending'}>Pending</Button>
<Button active={filter === 'approved'}>Approved</Button>
<Button active={filter === 'rejected'}>Rejected</Button>
</div>
<div className="approvals-list">
{filteredApprovals.length === 0 ? (
<EmptyState
title="No approvals"
description="When agents request permission for sensitive actions, they'll appear here."
/>
) : (
filteredApprovals.map(approval => (
<ApprovalCard
key={approval.id}
approval={approval}
onApprove={() => onApprove(approval.id)}
onReject={() => onReject(approval.id)}
/>
))
)}
</div>
</ApprovalsPanel>
3.5 Phase 5: 导航重构 (优先级: 中)
目标: 重构导航结构,匹配 ZCLAW 布局
文件修改:
desktop/src/components/Sidebar.tsxdesktop/src/components/RightPanel.tsxdesktop/src/App.tsx
新导航结构:
┌────────────────────┐
│ ZCLAW │
├────────────────────┤
│ CHAT │
│ └─ Chat │
│ MONITOR │
│ └─ Overview │
│ └─ Analytics │
│ └─ Logs │
│ AGENTS │
│ └─ Sessions │
│ └─ Approvals │
│ └─ Comms │
│ AUTOMATION │
│ └─ Workflows │
│ └─ Scheduler │
│ EXTENSIONS │
│ └─ Channels │
│ └─ Skills │
│ └─ Hands │
│ SYSTEM │
│ └─ Runtime │
│ └─ Settings │
└────────────────────┘
四、关键文件清单
4.1 需要修改的文件
| 文件路径 | 修改内容 |
|---|---|
desktop/src/components/HandsPanel.tsx |
重写 HandCard,添加详情弹窗 |
desktop/src/components/WorkflowList.tsx |
添加创建/编辑功能 |
desktop/src/store/gatewayStore.ts |
扩展 Hand/Workflow 类型定义 |
desktop/src/components/Sidebar.tsx |
重构导航结构 |
desktop/src/components/RightPanel.tsx |
集成新组件 |
desktop/src/lib/gateway-client.ts |
添加新 API 调用 |
4.2 需要新建的文件
| 文件路径 | 功能 |
|---|---|
desktop/src/components/HandDetailsModal.tsx |
Hand 详情弹窗 |
desktop/src/components/WorkflowEditor.tsx |
Workflow 编辑器 |
desktop/src/components/WorkflowHistory.tsx |
Workflow 执行历史 |
desktop/src/components/SchedulerPanel.tsx |
Scheduler 管理面板 |
desktop/src/components/ScheduledJobEditor.tsx |
定时任务编辑器 |
desktop/src/components/EventTriggerEditor.tsx |
事件触发器编辑器 |
desktop/src/components/ApprovalsPanel.tsx |
审批管理面板 |
五、验证方案
5.1 手动测试
-
Hands 测试:
- 启动 ZClaw,连接 ZCLAW (端口 50051)
- 打开 Hands 标签
- 验证 8 个 Hands 正确显示
- 点击 Details 查看详情弹窗
- 点击 Activate 激活一个 Hand
- 验证状态变化和反馈
-
Workflow 测试:
- 打开 Workflow 标签
- 创建新 Workflow
- 编辑 Workflow 步骤
- 执行 Workflow
- 查看执行历史
-
Scheduler 测试:
- 创建定时任务
- 编辑 Cron 表达式
- 验证任务触发
-
Approvals 测试:
- 触发需要审批的 Hand
- 验证 Approvals 页面显示
- 批准/拒绝审批
5.2 自动化测试
# 运行相关测试
pnpm vitest run tests/desktop/handsPanel.test.tsx
pnpm vitest run tests/desktop/workflowList.test.tsx
pnpm vitest run tests/desktop/gatewayStore.test.ts
# 类型检查
pnpm tsc --noEmit
六、开发顺序 (根据用户确认)
用户选择:
- ✅ 优先实现 Hands 增强
- ✅ 需要完整实现 Scheduler 和 Approvals
推荐开发顺序:
| 顺序 | Phase | 工作量 | 说明 |
|---|---|---|---|
| 1 | Phase 1: HandsPanel 增强 | 2-3 天 | 最高优先级,核心功能 |
| 2 | Phase 4: ApprovalsPanel | 1 天 | Hand 执行需要审批流程 |
| 3 | Phase 2: WorkflowList 增强 | 2-3 天 | 完整工作流管理 |
| 4 | Phase 3: SchedulerPanel | 2 天 | 定时任务和事件触发器 |
| 5 | Phase 5: 导航重构 | 1-2 天 | 统一导航结构 |
| 总计 | - | 8-11 天 | - |
六-A、第一步实施细节: HandsPanel 增强
文件修改清单
-
desktop/src/components/HandsPanel.tsx(重写)- 添加 HandCard 组件重构
- 添加状态徽章 (READY/SETUP NEEDED/RUNNING)
- 添加 Requirements 可视化
- 添加分类标签
- 添加工具/指标计数
-
desktop/src/components/HandDetailsModal.tsx(新建)- Agent Config 显示 (Provider/Model)
- Requirements 列表
- Tools 列表
- Dashboard Metrics 列表
- Activate 按钮
-
desktop/src/store/gatewayStore.ts(扩展)- 扩展 Hand 类型定义
- 添加 getHandDetails API
-
desktop/src/lib/gateway-client.ts(扩展)- 添加 getHandDetails 方法
UI 组件设计
// HandStatusBadge 组件
type HandStatus = 'idle' | 'running' | 'needs_approval' | 'error' | 'unavailable' | 'setup_needed';
const STATUS_CONFIG: Record<HandStatus, { label: string; className: string }> = {
idle: { label: 'READY', className: 'bg-green-100 text-green-700' },
running: { label: 'RUNNING', className: 'bg-blue-100 text-blue-700 animate-pulse' },
needs_approval: { label: 'NEEDS APPROVAL', className: 'bg-yellow-100 text-yellow-700' },
error: { label: 'ERROR', className: 'bg-red-100 text-red-700' },
unavailable: { label: 'UNAVAILABLE', className: 'bg-gray-100 text-gray-500' },
setup_needed: { label: 'SETUP NEEDED', className: 'bg-orange-100 text-orange-700' },
};
// RequirementItem 组件
function RequirementItem({ description, met, details }: Requirement) {
return (
<div className={`flex items-start gap-2 text-sm ${met ? 'text-green-700' : 'text-red-600'}`}>
<span className="flex-shrink-0">{met ? '✓' : '✗'}</span>
<span>{description}</span>
{details && <span className="text-gray-400 text-xs">({details})</span>}
</div>
);
}
七、风险与缓解
| 风险 | 影响 | 缓解措施 |
|---|---|---|
| ZCLAW API 变更 | 高 | 使用实际 API 测试验证,保持与 ZCLAW v0.4.0 兼容 |
| UI 复杂度 | 中 | 分阶段实现,先核心功能后高级功能 |
| 性能问题 | 低 | 使用虚拟列表处理大量数据 |
计划创建时间: 2026-03-14 参考版本: ZCLAW v0.4.0