feat(client): project managed services to digital employee
This commit is contained in:
@@ -10,6 +10,7 @@ import type {
|
||||
DebugTask,
|
||||
DigitalEmployeeDecision,
|
||||
DigitalEmployeeDuty,
|
||||
DigitalEmployeeManagedService,
|
||||
DigitalEmployeeRunDetail,
|
||||
DigitalEmployeeTaskExecutionSummary,
|
||||
DigitalEmployeeWorkEvent,
|
||||
@@ -117,6 +118,7 @@ interface QimingclawSyncFailure {
|
||||
interface QimingclawSnapshot {
|
||||
generatedAt: string;
|
||||
services: Record<string, QimingclawServiceStatus | null>;
|
||||
managedServices?: QimingclawManagedService[] | null;
|
||||
sessions: {
|
||||
total: number;
|
||||
active: number;
|
||||
@@ -128,6 +130,22 @@ interface QimingclawSnapshot {
|
||||
planTemplates?: QimingclawPlanTemplateRecord[] | null;
|
||||
}
|
||||
|
||||
interface QimingclawManagedService {
|
||||
serviceId: string;
|
||||
name: string;
|
||||
kind: string;
|
||||
status: string;
|
||||
statusLabel: string;
|
||||
running: boolean;
|
||||
error?: string | null;
|
||||
requiresHumanAction: boolean;
|
||||
dependentTasks: string[];
|
||||
restartCount: number;
|
||||
lastSeenAt: string;
|
||||
instance?: Record<string, unknown>;
|
||||
lease?: Record<string, unknown>;
|
||||
}
|
||||
|
||||
interface QimingclawPlanTemplateList {
|
||||
generatedAt: string;
|
||||
templateDir: string;
|
||||
@@ -655,6 +673,82 @@ function serviceLine(snapshot: QimingclawSnapshot | null, key: string, label: st
|
||||
return `${label}:未运行${service.error ? `,${service.error}` : ''}`;
|
||||
}
|
||||
|
||||
function buildManagedServices(snapshot: QimingclawSnapshot | null): DigitalEmployeeManagedService[] {
|
||||
const fromSnapshot = snapshot?.managedServices ?? [];
|
||||
if (fromSnapshot.length > 0) {
|
||||
return fromSnapshot.map((service) => ({
|
||||
service_id: service.serviceId,
|
||||
name: service.name,
|
||||
kind: service.kind,
|
||||
status: service.status,
|
||||
status_label: service.statusLabel,
|
||||
running: service.running,
|
||||
error: service.error ?? null,
|
||||
requires_human_action: service.requiresHumanAction,
|
||||
dependent_tasks: service.dependentTasks ?? [],
|
||||
restart_count: service.restartCount ?? 0,
|
||||
last_seen_at: service.lastSeenAt,
|
||||
instance: service.instance,
|
||||
lease: service.lease,
|
||||
}));
|
||||
}
|
||||
|
||||
return [
|
||||
fallbackManagedService(snapshot, 'agent', 'Agent', 'agent', ['ACP 会话执行', 'Plan Agent']),
|
||||
fallbackManagedService(snapshot, 'mcp', 'MCP Proxy', 'mcp', ['Skill Catalog', 'MCP 工具调用']),
|
||||
fallbackManagedService(snapshot, 'computerServer', 'Computer Server', 'desktop', ['/computer/chat', '远程任务接入']),
|
||||
fallbackManagedService(snapshot, 'fileServer', 'File Server', 'file', ['Artifact 上传', '文件交付']),
|
||||
fallbackManagedService(snapshot, 'lanproxy', 'Lanproxy', 'network', ['远程访问', '管理端回连']),
|
||||
fallbackManagedService(snapshot, 'guiServer', 'GUI Agent Server', 'gui', ['GUI 自动化']),
|
||||
];
|
||||
}
|
||||
|
||||
function fallbackManagedService(
|
||||
snapshot: QimingclawSnapshot | null,
|
||||
key: string,
|
||||
name: string,
|
||||
kind: string,
|
||||
dependentTasks: string[],
|
||||
): DigitalEmployeeManagedService {
|
||||
const service = snapshot?.services[key];
|
||||
const running = service?.running === true;
|
||||
const status = service?.error ? 'degraded' : running ? 'running' : 'stopped';
|
||||
return {
|
||||
service_id: key,
|
||||
name,
|
||||
kind,
|
||||
status,
|
||||
status_label: status === 'running' ? '运行中' : status === 'degraded' ? '异常' : '未运行',
|
||||
running,
|
||||
error: service?.error ?? null,
|
||||
requires_human_action: Boolean(service?.error),
|
||||
dependent_tasks: dependentTasks,
|
||||
restart_count: 0,
|
||||
last_seen_at: snapshot?.generatedAt ?? new Date().toISOString(),
|
||||
instance: service ? {
|
||||
port: service.port,
|
||||
engineType: service.engineType,
|
||||
serverCount: service.serverCount,
|
||||
serverNames: service.serverNames,
|
||||
} : undefined,
|
||||
lease: {
|
||||
state: status === 'running' ? 'active' : status,
|
||||
updatedAt: snapshot?.generatedAt ?? new Date().toISOString(),
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
function managedServiceLine(service: DigitalEmployeeManagedService): string {
|
||||
const deps = service.dependent_tasks.length > 0 ? `;依赖任务:${service.dependent_tasks.slice(0, 2).join('、')}` : '';
|
||||
return `${service.name}:${service.status_label}${service.error ? `,${service.error}` : ''}${deps}`;
|
||||
}
|
||||
|
||||
function managedServiceSummary(services: DigitalEmployeeManagedService[]): string {
|
||||
const runningCount = services.filter((service) => service.running).length;
|
||||
const issueCount = services.filter((service) => service.requires_human_action || service.status === 'degraded').length;
|
||||
return `ManagedService:${runningCount}/${services.length} 运行,${issueCount} 项需处理`;
|
||||
}
|
||||
|
||||
function syncLine(snapshot: QimingclawSnapshot | null): string {
|
||||
const sync = snapshot?.sync;
|
||||
if (!sync) return '管理端同步:未连接';
|
||||
@@ -1703,6 +1797,9 @@ function buildWorkday(date: string, snapshot: QimingclawSnapshot | null): Digita
|
||||
const hasLiveRuntime = hasRuntimeRecords(snapshot);
|
||||
const sync = snapshot?.sync;
|
||||
const artifactSources = reportArtifactSources(buildArtifacts(snapshot));
|
||||
const managedServices = buildManagedServices(snapshot);
|
||||
const managedServiceIssues = managedServices.filter((service) => service.requires_human_action || service.status === 'degraded');
|
||||
const runningManagedServiceCount = managedServices.filter((service) => service.running).length;
|
||||
|
||||
return {
|
||||
source: 'live',
|
||||
@@ -1723,18 +1820,20 @@ function buildWorkday(date: string, snapshot: QimingclawSnapshot | null): Digita
|
||||
current_status: state.profile.currentStatus,
|
||||
current_status_label: state.profile.currentStatus === 'resting' ? '休息中' : '工作中',
|
||||
status_label: hasLiveRuntime
|
||||
? (failureCount > 0 ? '有异常' : runningCount > 0 ? '执行中' : '已同步')
|
||||
? (failureCount > 0 || managedServiceIssues.length > 0 ? '有异常' : runningCount > 0 ? '执行中' : '已同步')
|
||||
: confirmed ? '运行中' : '待确认',
|
||||
status_tone: hasLiveRuntime
|
||||
? (failureCount > 0 ? 'danger' : runningCount > 0 ? 'running' : 'success')
|
||||
? (failureCount > 0 || managedServiceIssues.length > 0 ? 'danger' : runningCount > 0 ? 'running' : 'success')
|
||||
: confirmed ? 'running' : 'waiting',
|
||||
summary: hasLiveRuntime
|
||||
? `当前日期 ${displayDate(date)} 已读取 ${liveRecordCount} 条 qimingclaw 本地运行记录。`
|
||||
? `当前日期 ${displayDate(date)} 已读取 ${liveRecordCount} 条 qimingclaw 本地运行记录,${managedServiceSummary(managedServices)}。`
|
||||
: confirmed
|
||||
? `当前日期 ${displayDate(date)} 已确认 ${selectedCount} 项任务。`
|
||||
: `当前日期 ${displayDate(date)} 待确认今日任务。`,
|
||||
bubble_text: hasLiveRuntime
|
||||
? '我已接入 qimingclaw 本地运行记录,会持续展示真实任务、事件和同步状态。'
|
||||
? managedServiceIssues.length > 0
|
||||
? `我发现 ${managedServiceIssues.length} 项常驻服务需要处理,会把影响到的任务标出来。`
|
||||
: '我已接入 qimingclaw 本地运行记录,会持续展示真实任务、事件和同步状态。'
|
||||
: confirmed
|
||||
? '我已接入 qimingclaw 客户端执行链路,正在等待真实 Run/Event 数据接入。'
|
||||
: '请先确认今天要执行的任务,我会把它们映射到 qimingclaw 执行链路。',
|
||||
@@ -1751,8 +1850,11 @@ function buildWorkday(date: string, snapshot: QimingclawSnapshot | null): Digita
|
||||
{ label: '异常', value: String(failureCount) },
|
||||
{ label: '待同步', value: String(sync?.pending ?? 0) },
|
||||
{ label: '同步异常', value: String(sync?.failed ?? 0) },
|
||||
{ label: '服务运行', value: `${runningManagedServiceCount}/${managedServices.length}` },
|
||||
{ label: '需处理服务', value: String(managedServiceIssues.length) },
|
||||
],
|
||||
},
|
||||
managed_services: managedServices,
|
||||
duties,
|
||||
events,
|
||||
execution_summaries: executionSummaries,
|
||||
@@ -1771,6 +1873,8 @@ function buildWorkday(date: string, snapshot: QimingclawSnapshot | null): Digita
|
||||
serviceLine(snapshot, 'agent', 'Agent'),
|
||||
serviceLine(snapshot, 'mcp', 'MCP'),
|
||||
serviceLine(snapshot, 'computerServer', 'Computer Server'),
|
||||
managedServiceSummary(managedServices),
|
||||
...managedServiceIssues.slice(0, 3).map(managedServiceLine),
|
||||
syncLine(snapshot),
|
||||
`活跃会话:${snapshot?.sessions.active ?? 0} / ${snapshot?.sessions.total ?? 0}`,
|
||||
],
|
||||
|
||||
Reference in New Issue
Block a user