chore(client): remove digital demo scenario residue
This commit is contained in:
@@ -1,292 +0,0 @@
|
||||
import type { PlanMessage } from '@/lib/api';
|
||||
import type {
|
||||
DashboardOverview,
|
||||
JournalEntry,
|
||||
Mission,
|
||||
MissionStep,
|
||||
SkillSummary,
|
||||
} from '@/lib/consoleDataAdapter';
|
||||
import type { DebugPlan, DebugRun, DebugTask, FlowResponse } from '@/types/api';
|
||||
|
||||
function todayAt(hour: number, minute: number): string {
|
||||
const date = new Date();
|
||||
date.setHours(hour, minute, 0, 0);
|
||||
return date.toISOString();
|
||||
}
|
||||
|
||||
function makeTask(
|
||||
missionId: string,
|
||||
stepId: string,
|
||||
title: string,
|
||||
status: string,
|
||||
skillId: string,
|
||||
startedAt: string | null,
|
||||
finishedAt: string | null,
|
||||
): MissionStep['tasks'][number] {
|
||||
return {
|
||||
id: `${missionId}-${stepId}-task`,
|
||||
title,
|
||||
status,
|
||||
assignedSkillId: skillId,
|
||||
startedAt,
|
||||
finishedAt,
|
||||
};
|
||||
}
|
||||
|
||||
function makeMission(
|
||||
id: string,
|
||||
title: string,
|
||||
objective: string,
|
||||
status: string,
|
||||
updatedAt: string,
|
||||
steps: MissionStep[],
|
||||
): Mission {
|
||||
return {
|
||||
id,
|
||||
title,
|
||||
objective,
|
||||
status,
|
||||
createdAt: todayAt(8, 0),
|
||||
updatedAt,
|
||||
steps,
|
||||
sourceIds: { planId: id, taskIds: steps.flatMap((step) => step.tasks.map((task) => task.id)) },
|
||||
};
|
||||
}
|
||||
|
||||
const DEMO_SKILLS: SkillSummary[] = [
|
||||
{ id: 'qimingclaw-client-health-check', name: '客户端自检', version: '1.0.0', enabled: true, description: '检查 Agent、MCP、Computer Server 和会话状态。', category: '执行', capabilityLevel: 'core', source: 'skill-api' },
|
||||
{ id: 'qimingclaw-remote-task-ingress', name: '远程任务接入', version: '1.0.0', enabled: true, description: '接收管理端下发任务并投射到本地执行队列。', category: '通信', capabilityLevel: 'core', source: 'skill-api' },
|
||||
{ id: 'qimingclaw-acp-session-runner', name: 'ACP 会话执行', version: '1.0.0', enabled: true, description: '通过 qimingclaw ACP 引擎执行任务并记录 Run/Event。', category: '执行', capabilityLevel: 'specialized', source: 'skill-api' },
|
||||
{ id: 'qimingclaw-mcp-capability-scan', name: 'MCP 能力扫描', version: '1.0.0', enabled: true, description: '读取 MCP server 和工具清单,生成数字员工技能能力池。', category: '工具', capabilityLevel: 'standard', source: 'skill-api' },
|
||||
{ id: 'qimingclaw-approval-sync', name: '审批同步', version: '1.0.0', enabled: true, description: '把待确认事项回写到本地 approval 表并同步管理端。', category: '治理', capabilityLevel: 'specialized', source: 'skill-api' },
|
||||
{ id: 'qimingclaw-artifact-report', name: '产物整理', version: '1.0.0', enabled: true, description: '整理本地执行产物、文件路径和日报输出。', category: '产物', capabilityLevel: 'standard', source: 'skill-api' },
|
||||
{ id: 'qimingclaw-sync-diagnostics', name: '同步诊断', version: '1.0.0', enabled: true, description: '汇总 outbox 失败、重试历史和管理端同步状态。', category: '运维', capabilityLevel: 'standard', source: 'skill-api' },
|
||||
{ id: 'qimingclaw-daily-report', name: '本地日报', version: '1.0.0', enabled: true, description: '基于 qimingclaw workday 投影生成本地文本日报。', category: '报表', capabilityLevel: 'standard', source: 'skill-api' },
|
||||
];
|
||||
|
||||
const DEMO_MISSIONS: Mission[] = [
|
||||
makeMission(
|
||||
'qimingclaw-client-readiness',
|
||||
'qimingclaw 客户端运行自检',
|
||||
'检查客户端数字员工运行所需的 Agent、ACP、MCP、Computer Server 和同步配置。',
|
||||
'active',
|
||||
todayAt(10, 35),
|
||||
[
|
||||
{ id: 'agent', title: '检查 Agent 服务', status: 'completed', preferredSkills: ['qimingclaw-client-health-check'], tasks: [makeTask('qimingclaw-client-readiness', 'agent', '读取 Agent 运行状态', 'completed', 'qimingclaw-client-health-check', todayAt(8, 30), todayAt(8, 33))] },
|
||||
{ id: 'mcp', title: '扫描 MCP server', status: 'completed', preferredSkills: ['qimingclaw-mcp-capability-scan'], tasks: [makeTask('qimingclaw-client-readiness', 'mcp', '生成 MCP 能力清单', 'completed', 'qimingclaw-mcp-capability-scan', todayAt(8, 35), todayAt(8, 41))] },
|
||||
{ id: 'computer', title: '检查 Computer Server', status: 'completed', preferredSkills: ['qimingclaw-client-health-check'], tasks: [makeTask('qimingclaw-client-readiness', 'computer', '确认电脑控制入口', 'completed', 'qimingclaw-client-health-check', todayAt(8, 45), todayAt(8, 51))] },
|
||||
{ id: 'sync', title: '读取同步队列', status: 'running', preferredSkills: ['qimingclaw-sync-diagnostics'], tasks: [makeTask('qimingclaw-client-readiness', 'sync', '汇总 outbox 状态', 'running', 'qimingclaw-sync-diagnostics', todayAt(10, 28), null)] },
|
||||
],
|
||||
),
|
||||
makeMission('qimingclaw-remote-task-ingress', '09:00 远程任务接入', '接收管理端下发任务,进入 /computer/chat 与 ACP 执行链路。', 'completed', todayAt(9, 6), [
|
||||
{ id: 'ingress', title: '接收管理端任务', status: 'completed', preferredSkills: ['qimingclaw-remote-task-ingress'], tasks: [makeTask('qimingclaw-remote-task-ingress', 'ingress', '解析远程任务 payload', 'completed', 'qimingclaw-remote-task-ingress', todayAt(9, 0), todayAt(9, 6))] },
|
||||
]),
|
||||
makeMission('qimingclaw-acp-run-0930', '09:30 ACP 会话执行', '用 qimingclaw ACP 会话执行本地任务并记录运行事件。', 'completed', todayAt(9, 32), [
|
||||
{ id: 'run-session', title: '创建 ACP 会话', status: 'completed', preferredSkills: ['qimingclaw-acp-session-runner'], tasks: [makeTask('qimingclaw-acp-run-0930', 'run-session', '执行客户端任务', 'completed', 'qimingclaw-acp-session-runner', todayAt(9, 30), todayAt(9, 32))] },
|
||||
]),
|
||||
makeMission('qimingclaw-mcp-tools-1030', '10:30 MCP 工具能力投射', '读取当前 MCP 配置、server 状态和工具限制,生成技能库能力项。', 'running', todayAt(10, 35), [
|
||||
{ id: 'scan-tools', title: '扫描 MCP 工具', status: 'running', preferredSkills: ['qimingclaw-mcp-capability-scan'], tasks: [makeTask('qimingclaw-mcp-tools-1030', 'scan-tools', '整理 MCP 工具清单', 'running', 'qimingclaw-mcp-capability-scan', todayAt(10, 30), null)] },
|
||||
]),
|
||||
makeMission('qimingclaw-approval-review-1130', '11:30 本地审批确认', '把数字员工待确认事项写回 formal approval 表并进入同步队列。', 'approved', todayAt(11, 20), [
|
||||
{ id: 'approval', title: '处理 approval 决策', status: 'pending', preferredSkills: ['qimingclaw-approval-sync'], tasks: [makeTask('qimingclaw-approval-review-1130', 'approval', '回写 approval 状态', 'pending', 'qimingclaw-approval-sync', null, null)] },
|
||||
]),
|
||||
makeMission('qimingclaw-artifact-1430', '14:30 执行产物整理', '提取 Run/Event payload 中的文件、路径和输出,投射到 artifact 列表。', 'draft', todayAt(14, 10), [
|
||||
{ id: 'artifact', title: '整理执行产物', status: 'pending', preferredSkills: ['qimingclaw-artifact-report'], tasks: [makeTask('qimingclaw-artifact-1430', 'artifact', '生成产物索引', 'pending', 'qimingclaw-artifact-report', null, null)] },
|
||||
]),
|
||||
makeMission('qimingclaw-sync-1630', '16:30 管理端同步诊断', '检查 outbox 失败、退避状态和最近同步尝试。', 'draft', todayAt(16, 10), [
|
||||
{ id: 'sync-diagnostics', title: '生成同步诊断', status: 'pending', preferredSkills: ['qimingclaw-sync-diagnostics'], tasks: [makeTask('qimingclaw-sync-1630', 'sync-diagnostics', '导出同步诊断', 'pending', 'qimingclaw-sync-diagnostics', null, null)] },
|
||||
]),
|
||||
makeMission('qimingclaw-daily-report', '18:00 本地日报生成', '基于 qimingclaw workday 投影生成可下载文本日报。', 'draft', todayAt(17, 10), [
|
||||
{ id: 'daily-report', title: '生成数字员工日报', status: 'pending', preferredSkills: ['qimingclaw-daily-report'], tasks: [makeTask('qimingclaw-daily-report', 'daily-report', '整理日报文本', 'pending', 'qimingclaw-daily-report', null, null)] },
|
||||
]),
|
||||
makeMission('zhihu-hotlist-monitor', '知乎热榜采集', '通过计划模板调用知乎热榜采集技能,导出表格文件并生成当天热点摘要。', 'approved', todayAt(10, 12), [
|
||||
{ id: 'collect-zhihu', title: '采集知乎热榜', status: 'pending', preferredSkills: ['zhihu-hotlist'], tasks: [makeTask('zhihu-hotlist-monitor', 'collect-zhihu', '采集知乎热榜', 'pending', 'zhihu-hotlist', null, null)] },
|
||||
{ id: 'export-xlsx', title: '导出表格文件', status: 'pending', preferredSkills: ['office-export-xlsx'], tasks: [makeTask('zhihu-hotlist-monitor', 'export-xlsx', '导出热榜表格', 'pending', 'office-export-xlsx', null, null)] },
|
||||
]),
|
||||
];
|
||||
|
||||
function cloneMission(mission: Mission): Mission {
|
||||
return {
|
||||
...mission,
|
||||
steps: mission.steps.map((step) => ({
|
||||
...step,
|
||||
preferredSkills: [...step.preferredSkills],
|
||||
tasks: step.tasks.map((task) => ({ ...task })),
|
||||
})),
|
||||
sourceIds: { planId: mission.sourceIds.planId, taskIds: [...mission.sourceIds.taskIds] },
|
||||
};
|
||||
}
|
||||
|
||||
export function getDemoMissions(): Mission[] {
|
||||
return DEMO_MISSIONS.map(cloneMission);
|
||||
}
|
||||
|
||||
export function getDemoSkills(): SkillSummary[] {
|
||||
return DEMO_SKILLS.map((skill) => ({ ...skill }));
|
||||
}
|
||||
|
||||
export function buildDemoTasks(missions: Mission[]): DebugTask[] {
|
||||
return missions.flatMap((mission) => mission.steps.flatMap((step) => step.tasks.map((task) => ({
|
||||
task_id: task.id,
|
||||
title: task.title,
|
||||
status: task.status,
|
||||
plan_id: mission.id,
|
||||
step_id: step.id,
|
||||
assigned_skill_id: task.assignedSkillId || '',
|
||||
description: `${mission.title} · ${step.title}`,
|
||||
created_at: mission.createdAt || todayAt(8, 0),
|
||||
updated_at: mission.updatedAt || mission.createdAt || todayAt(8, 0),
|
||||
started_at: task.startedAt,
|
||||
finished_at: task.finishedAt,
|
||||
}))));
|
||||
}
|
||||
|
||||
export function buildDemoRuns(tasks: DebugTask[]): DebugRun[] {
|
||||
return tasks
|
||||
.filter((task) => ['completed', 'running'].includes(task.status))
|
||||
.map((task, index) => ({
|
||||
run_id: `qimingclaw-fallback-run-${index + 1}`,
|
||||
task_id: task.task_id,
|
||||
plan_id: task.plan_id,
|
||||
attempt_no: 1,
|
||||
lifecycle: task.status === 'running' ? 'Running' : 'Succeeded',
|
||||
created_at: task.started_at || task.created_at,
|
||||
completed_at: task.finished_at,
|
||||
}));
|
||||
}
|
||||
|
||||
export function buildDemoOverview(tasks: DebugTask[]): DashboardOverview {
|
||||
return {
|
||||
generatedAt: new Date().toISOString(),
|
||||
isPartial: true,
|
||||
sources: [{ endpoint: 'qimingclaw-fallback', ok: true, loadedAt: new Date().toISOString() }],
|
||||
taskTotals: {
|
||||
total: tasks.length,
|
||||
queued: tasks.filter((task) => task.status === 'pending').length,
|
||||
running: tasks.filter((task) => task.status === 'running').length,
|
||||
succeeded: tasks.filter((task) => task.status === 'completed').length,
|
||||
failed: 0,
|
||||
},
|
||||
approvals: { total: 1, pending: 1 },
|
||||
health: { activeTasks: tasks.filter((task) => task.status === 'running').length, failedTasks: 0, pendingConfirmations: 1 },
|
||||
};
|
||||
}
|
||||
|
||||
export function buildDemoPlans(missions: Mission[]): DebugPlan[] {
|
||||
return missions.map((mission) => ({
|
||||
plan_id: mission.id,
|
||||
title: mission.title,
|
||||
objective: mission.objective,
|
||||
status: mission.status,
|
||||
created_at: mission.createdAt || todayAt(8, 0),
|
||||
steps: mission.steps.map((step) => ({
|
||||
step_id: step.id,
|
||||
title: step.title,
|
||||
depends_on: [],
|
||||
preferred_skills: step.preferredSkills,
|
||||
tasks: step.tasks.map((task) => ({
|
||||
task_id: task.id,
|
||||
title: task.title,
|
||||
status: task.status,
|
||||
})),
|
||||
})),
|
||||
}));
|
||||
}
|
||||
|
||||
export function buildDemoJournalEntries(missions: Mission[]): JournalEntry[] {
|
||||
return missions
|
||||
.slice(0, 8)
|
||||
.map((mission, index) => ({
|
||||
id: `qimingclaw-fallback-journal-${index + 1}`,
|
||||
kind: mission.status === 'completed' ? 'completed' : mission.status === 'active' || mission.status === 'running' ? 'start' : 'pending_authorization',
|
||||
source: 'qimingclaw-fallback',
|
||||
message: `${mission.title}:${mission.objective}`,
|
||||
occurredAt: mission.updatedAt,
|
||||
planId: mission.id,
|
||||
taskId: mission.sourceIds.taskIds[0] || null,
|
||||
}));
|
||||
}
|
||||
|
||||
export function buildDemoFlowEvents(mission: Mission): NonNullable<FlowResponse['events']> {
|
||||
const activeStep = mission.steps.find((step) => step.status === 'running') || mission.steps.find((step) => step.status === 'pending') || mission.steps[0];
|
||||
const events: NonNullable<FlowResponse['events']> = [
|
||||
{ event_id: `${mission.id}-event-1`, kind: 'entered_session', occurred_at: mission.createdAt || todayAt(8, 0), message: `已接收场景:${mission.title}` },
|
||||
{ event_id: `${mission.id}-event-2`, kind: 'start', occurred_at: mission.updatedAt || mission.createdAt || todayAt(8, 0), message: `当前目标:${mission.objective}` },
|
||||
];
|
||||
if (activeStep) {
|
||||
events.push({
|
||||
event_id: `${mission.id}-event-3`,
|
||||
kind: mission.status === 'completed' ? 'completed' : mission.status === 'approved' || mission.status === 'draft' ? 'pending_authorization' : 'RunStarted',
|
||||
occurred_at: mission.updatedAt || mission.createdAt || todayAt(8, 0),
|
||||
message: `${activeStep.title}`,
|
||||
});
|
||||
}
|
||||
if (mission.status === 'completed') {
|
||||
events.push({
|
||||
event_id: `${mission.id}-event-4`,
|
||||
kind: 'RunCompleted',
|
||||
occurred_at: mission.updatedAt || mission.createdAt || todayAt(8, 0),
|
||||
message: '已完成本场景执行并回写结果。',
|
||||
});
|
||||
}
|
||||
return events;
|
||||
}
|
||||
|
||||
export function buildDemoPlanMessages(mission: Mission): PlanMessage[] {
|
||||
const completedSteps = mission.steps.filter((step) => step.status === 'completed').length;
|
||||
const runningStep = mission.steps.find((step) => step.status === 'running');
|
||||
const closing =
|
||||
mission.status === 'completed'
|
||||
? `当前已完成全部 ${mission.steps.length} 个步骤,结果已整理完毕。`
|
||||
: runningStep
|
||||
? `当前正在处理“${runningStep.title}”,已完成 ${completedSteps} 个步骤。`
|
||||
: `当前场景已准备就绪,可直接发起执行。`;
|
||||
|
||||
return [
|
||||
{ role: 'user', content: `请执行场景:${mission.title}` },
|
||||
{ role: 'assistant', content: `已接收。业务目标:${mission.objective}` },
|
||||
{ role: 'assistant', content: closing },
|
||||
];
|
||||
}
|
||||
|
||||
export function runDemoMissionOnce(missions: Mission[], missionId: string): Mission[] {
|
||||
return missions.map((mission) => {
|
||||
if (mission.id !== missionId) return mission;
|
||||
return {
|
||||
...mission,
|
||||
status: 'running',
|
||||
updatedAt: new Date().toISOString(),
|
||||
steps: mission.steps.map((step, index) => ({
|
||||
...step,
|
||||
status: index === 0 ? 'running' : step.status === 'completed' ? 'completed' : 'pending',
|
||||
tasks: step.tasks.map((task) => ({
|
||||
...task,
|
||||
status: index === 0 ? 'running' : task.status === 'completed' ? 'completed' : 'pending',
|
||||
startedAt: index === 0 ? new Date().toISOString() : task.startedAt,
|
||||
finishedAt: index === 0 ? null : task.finishedAt,
|
||||
})),
|
||||
})),
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
export function completeDemoMissionOnce(missions: Mission[], missionId: string): Mission[] {
|
||||
return missions.map((mission) => {
|
||||
if (mission.id !== missionId) return mission;
|
||||
return {
|
||||
...mission,
|
||||
status: 'completed',
|
||||
updatedAt: new Date().toISOString(),
|
||||
steps: mission.steps.map((step) => ({
|
||||
...step,
|
||||
status: 'completed',
|
||||
tasks: step.tasks.map((task) => ({
|
||||
...task,
|
||||
status: 'completed',
|
||||
startedAt: task.startedAt || new Date().toISOString(),
|
||||
finishedAt: new Date().toISOString(),
|
||||
})),
|
||||
})),
|
||||
};
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user