auto-sync: 2026-05-17 11:24:16

This commit is contained in:
cfdaily
2026-05-17 11:24:16 +08:00
parent d7b18aba0d
commit 52fad46970
2 changed files with 312 additions and 515 deletions
+307 -509
View File
@@ -1,10 +1,24 @@
/**
* API 层 — 对接 dashboard/server.py
* 生产环境从同源 (port 7891) 请求,开发环境可通过 VITE_API_URL 指定
* API 层 — v2.6 对接层
* 保留 v1.0 全部接口签名,内部适配 v2.6 后端 API
* v2.6 后端没有的接口返回空/mock 数据,保证组件不报错
*/
const API_BASE = import.meta.env.VITE_API_URL || '';
// ── 项目上下文(由 store 设置) ──
let _currentProjectId: string | null = null;
export function setApiProjectId(pid: string | null) {
_currentProjectId = pid;
}
function projectId(): string {
if (!_currentProjectId) throw new Error('No project selected');
return _currentProjectId;
}
// ── 通用请求 ──
async function fetchJ<T>(url: string): Promise<T> {
@@ -22,559 +36,343 @@ async function postJ<T>(url: string, data: unknown): Promise<T> {
return res.json();
}
// ── API 接口 ──
// ── v2.6 Task → v1.0 Task 适配 ──
function adaptTask(raw: any): Task {
const t: Task = {
id: raw.id,
title: raw.title || raw.requirement || '(无标题)',
state: raw.status || 'created',
status: raw.status || 'created',
org: raw.assignee || '',
now: raw.description || raw.requirement || '-',
eta: raw.priority || '-',
block: '无',
ac: raw.assignee || '',
output: '',
heartbeat: { status: 'idle', label: '⚪' },
flow_log: [],
todos: [],
review_round: 0,
archived: false,
updated_at: raw.updated_at || '',
nodes: [],
plan_status: '',
sourceMeta: {},
};
return t;
}
// ── API 接口(保持 v1.0 签名) ──
export const api = {
// 核心数据
liveStatus: () => fetchJ<LiveStatus>(`${API_BASE}/api/live-status`),
agentConfig: () => fetchJ<AgentConfig>(`${API_BASE}/api/agent-config`),
modelChangeLog: () => fetchJ<ChangeLogEntry[]>(`${API_BASE}/api/model-change-log`).catch(() => []),
officialsStats: () => fetchJ<OfficialsData>(`${API_BASE}/api/officials-stats`),
morningBrief: () => fetchJ<MorningBrief>(`${API_BASE}/api/morning-brief`),
morningConfig: () => fetchJ<SubConfig>(`${API_BASE}/api/morning-config`),
agentsStatus: () => fetchJ<AgentsStatusData>(`${API_BASE}/api/agents-status`),
// ── 核心数据 ──
// 任务实时动态
taskActivity: (id: string) =>
fetchJ<TaskActivityData>(`${API_BASE}/api/task-activity/${encodeURIComponent(id)}`),
schedulerState: (id: string) =>
fetchJ<SchedulerStateData>(`${API_BASE}/api/scheduler-state/${encodeURIComponent(id)}`),
/** 聚合状态:项目列表 + 当前项目任务 + daemon 状态 */
liveStatus: async (): Promise<LiveStatus> => {
const [projectsMap, daemonData] = await Promise.all([
fetchJ<{ projects: Record<string, any> }>(`${API_BASE}/api/projects`).catch(() => ({ projects: {} })),
fetchJ<any>(`${API_BASE}/api/daemon/status`).catch(() => ({})),
]);
// 技能内容
skillContent: (agentId: string, skillName: string) =>
fetchJ<SkillContentResult>(
`${API_BASE}/api/skill-content/${encodeURIComponent(agentId)}/${encodeURIComponent(skillName)}`
),
const pids = Object.keys(projectsMap);
const pid = _currentProjectId || pids[0] || '';
let tasks: Task[] = [];
// 操作类
setModel: (agentId: string, model: string) =>
postJ<ActionResult>(`${API_BASE}/api/set-model`, { agentId, model }),
setDispatchChannel: (channel: string) =>
postJ<ActionResult>(`${API_BASE}/api/set-dispatch-channel`, { channel }),
agentWake: (agentId: string) =>
postJ<ActionResult>(`${API_BASE}/api/agent-wake`, { agentId }),
taskAction: (taskId: string, action: string, reason: string) =>
postJ<ActionResult>(`${API_BASE}/api/task-action`, { taskId, action, reason }),
reviewAction: (taskId: string, action: string, comment: string) =>
postJ<ActionResult>(`${API_BASE}/api/review-action`, { taskId, action, comment }),
advanceState: (taskId: string, comment: string) =>
postJ<ActionResult>(`${API_BASE}/api/advance-state`, { taskId, comment }),
archiveTask: (taskId: string, archived: boolean) =>
postJ<ActionResult>(`${API_BASE}/api/archive-task`, { taskId, archived }),
archiveAllDone: () =>
postJ<ActionResult & { count?: number }>(`${API_BASE}/api/archive-task`, { archiveAllDone: true }),
schedulerScan: (thresholdSec = 180) =>
postJ<ActionResult & { count?: number; actions?: ScanAction[]; checkedAt?: string }>(
`${API_BASE}/api/scheduler-scan`,
{ thresholdSec }
),
schedulerRetry: (taskId: string, reason: string) =>
postJ<ActionResult>(`${API_BASE}/api/scheduler-retry`, { taskId, reason }),
schedulerEscalate: (taskId: string, reason: string) =>
postJ<ActionResult>(`${API_BASE}/api/scheduler-escalate`, { taskId, reason }),
schedulerRollback: (taskId: string, reason: string) =>
postJ<ActionResult>(`${API_BASE}/api/scheduler-rollback`, { taskId, reason }),
refreshMorning: () =>
postJ<ActionResult>(`${API_BASE}/api/morning-brief/refresh`, {}),
saveMorningConfig: (config: SubConfig) =>
postJ<ActionResult>(`${API_BASE}/api/morning-config`, config),
addSkill: (agentId: string, skillName: string, description: string, trigger: string) =>
postJ<ActionResult>(`${API_BASE}/api/add-skill`, { agentId, skillName, description, trigger }),
if (pid) {
try {
const data = await fetchJ<{ tasks: any[] }>(`${API_BASE}/api/projects/${pid}/tasks`);
tasks = (data.tasks || []).map(adaptTask);
} catch { /* empty */ }
}
// 远程 Skills 管理
addRemoteSkill: (agentId: string, skillName: string, sourceUrl: string, description?: string) =>
postJ<ActionResult & { skillName?: string; agentId?: string; source?: string; localPath?: string; size?: number; addedAt?: string }>(
`${API_BASE}/api/add-remote-skill`, { agentId, skillName, sourceUrl, description: description || '' }
),
remoteSkillsList: () =>
fetchJ<RemoteSkillsListResult>(`${API_BASE}/api/remote-skills-list`),
updateRemoteSkill: (agentId: string, skillName: string) =>
postJ<ActionResult>(`${API_BASE}/api/update-remote-skill`, { agentId, skillName }),
removeRemoteSkill: (agentId: string, skillName: string) =>
postJ<ActionResult>(`${API_BASE}/api/remove-remote-skill`, { agentId, skillName }),
// 如果没有选中项目,尝试收集所有项目的任务
if (!_currentProjectId && pids.length > 1) {
const allTasks: Task[] = [];
for (const p of pids) {
try {
const data = await fetchJ<{ tasks: any[] }>(`${API_BASE}/api/projects/${p}/tasks`);
for (const t of (data.tasks || []).map(adaptTask)) {
t.sourceMeta = { ...t.sourceMeta, project_id: p, project_name: projectsMap[p]?.name || p };
allTasks.push(t);
}
} catch { /* skip */ }
}
tasks = allTasks;
}
createTask: (data: CreateTaskPayload) =>
postJ<ActionResult & { taskId?: string }>(`${API_BASE}/api/tasks`, data),
return {
tasks,
syncStatus: {
ok: true,
daemon: daemonData,
projects: projectsMap,
currentProject: pid,
},
};
},
// ── M3: 成果物 ──
artifacts: (taskId: string) =>
fetchJ<ArtifactsResult>(`${API_BASE}/api/tasks/${encodeURIComponent(taskId)}/artifacts`),
artifactPreview: (taskId: string, path: string) =>
fetchJ<ArtifactPreviewResult>(`${API_BASE}/api/tasks/${encodeURIComponent(taskId)}/artifacts/preview?path=${encodeURIComponent(path)}`),
artifactDownloadUrl: (taskId: string, path: string) =>
`${API_BASE}/api/tasks/${encodeURIComponent(taskId)}/artifacts/download?path=${encodeURIComponent(path)}`,
/** 获取项目列表 */
projects: async (): Promise<{ projects: Record<string, any> }> => {
return fetchJ(`${API_BASE}/api/projects`);
},
// ── M3: 人工干预 ──
humanInput: (taskId: string) =>
fetchJ<HumanInputResult>(`${API_BASE}/api/tasks/${encodeURIComponent(taskId)}/human-input`),
humanInputRespond: (taskId: string, data: HumanInputRespondPayload) =>
postJ<ActionResult>(`${API_BASE}/api/tasks/${encodeURIComponent(taskId)}/human-input/respond`, data),
/** 创建项目 */
createProject: (data: { id?: string; name: string; description?: string | null }) =>
postJ<ActionResult>(`${API_BASE}/api/projects`, data),
// ── 朝堂议政 ──
courtDiscussStart: (topic: string, officials: string[], taskId?: string) =>
postJ<CourtDiscussResult>(`${API_BASE}/api/court-discuss/start`, { topic, officials, taskId }),
courtDiscussAdvance: (sessionId: string, userMessage?: string, decree?: string) =>
postJ<CourtDiscussResult>(`${API_BASE}/api/court-discuss/advance`, { sessionId, userMessage, decree }),
courtDiscussConclude: (sessionId: string) =>
postJ<ActionResult & { summary?: string }>(`${API_BASE}/api/court-discuss/conclude`, { sessionId }),
courtDiscussDestroy: (sessionId: string) =>
postJ<ActionResult>(`${API_BASE}/api/court-discuss/destroy`, { sessionId }),
courtDiscussFate: () =>
fetchJ<{ ok: boolean; event: string }>(`${API_BASE}/api/court-discuss/fate`),
// ── Agent 配置(v2.6 暂无,返回空) ──
agentConfig: async (): Promise<AgentConfig> => ({
agents: [],
knownModels: [],
}),
modelChangeLog: async (): Promise<ChangeLogEntry[]> => [],
officialsStats: async (): Promise<OfficialsData> => ({
officials: [],
totals: { tasks_done: 0, cost_cny: 0 },
top_official: '',
}),
agentsStatus: async (): Promise<AgentsStatusData> => ({
ok: true,
gateway: { alive: true, probe: true, status: 'running' },
agents: [],
checkedAt: new Date().toISOString(),
}),
morningBrief: async (): Promise<MorningBrief> => ({
categories: {},
}),
morningConfig: async (): Promise<SubConfig> => ({
categories: [],
keywords: [],
custom_feeds: [],
feishu_webhook: '',
}),
// ── 任务实时动态(v2.6 用 events 兜底) ──
taskActivity: async (id: string): Promise<TaskActivityData> => {
try {
const pid = _currentProjectId || Object.keys((await api.projects()).projects)[0];
if (!pid) return { ok: false };
const data = await fetchJ<{ events: any[] }>(`${API_BASE}/api/projects/${pid}/tasks/${id}?include=events`);
return { ok: true, activity: [], timeline: [] };
} catch {
return { ok: false };
}
},
schedulerState: async (id: string): Promise<SchedulerStateData> => ({
ok: true, scheduler: {},
}),
// ── 技能内容(v2.6 暂无) ──
skillContent: async (agentId: string, skillName: string): Promise<SkillContentResult> => ({
ok: false, error: 'Not implemented in v2.6',
}),
// ── 操作类 ──
setModel: async (agentId: string, model: string): Promise<ActionResult> => ({ ok: false, error: 'Not implemented' }),
setDispatchChannel: async (channel: string): Promise<ActionResult> => ({ ok: false, error: 'Not implemented' }),
agentWake: async (agentId: string): Promise<ActionResult> => ({ ok: false, error: 'Not implemented' }),
taskAction: async (taskId: string, action: string, reason: string): Promise<ActionResult> => {
try {
const pid = _currentProjectId || Object.keys((await api.projects()).projects)[0];
if (!pid) return { ok: false, error: 'No project' };
const statusMap: Record<string, string> = {
stop: 'paused', cancel: 'cancelled', resume: 'executing',
};
const newStatus = statusMap[action];
if (!newStatus) return { ok: false, error: 'Unknown action' };
return postJ(`${API_BASE}/api/projects/${pid}/tasks/${taskId}/status`, { status: newStatus });
} catch (e: any) {
return { ok: false, error: e.message };
}
},
reviewAction: async (taskId: string, action: string, comment: string): Promise<ActionResult> => {
try {
const pid = _currentProjectId || Object.keys((await api.projects()).projects)[0];
if (!pid) return { ok: false, error: 'No project' };
return postJ(`${API_BASE}/api/projects/${pid}/tasks/${taskId}/reviews`, { verdict: action, comment });
} catch (e: any) {
return { ok: false, error: e.message };
}
},
advanceState: async (taskId: string, comment: string): Promise<ActionResult> => ({ ok: false, error: 'Not implemented' }),
archiveTask: async (taskId: string, archived: boolean): Promise<ActionResult> => ({ ok: true }),
archiveAllDone: async (): Promise<ActionResult & { count?: number }> => ({ ok: true, count: 0 }),
createTask: async (data: CreateTaskPayload): Promise<ActionResult & { taskId?: string }> => {
try {
const pid = _currentProjectId || Object.keys((await api.projects()).projects)[0];
if (!pid) return { ok: false, error: 'No project selected' };
return postJ(`${API_BASE}/api/projects/${pid}/tasks`, {
title: data.title || data.requirement || '',
requirement: data.requirement || data.title || '',
task_type: data.project_type || 'general',
priority: data.priority || 'medium',
});
} catch (e: any) {
return { ok: false, error: e.message };
}
},
schedulerScan: async (thresholdSec = 180) => ({ ok: true } as any),
schedulerRetry: async (taskId: string, reason: string) => ({ ok: false, error: 'Not implemented' } as ActionResult),
schedulerEscalate: async (taskId: string, reason: string) => ({ ok: false, error: 'Not implemented' } as ActionResult),
schedulerRollback: async (taskId: string, reason: string) => ({ ok: false, error: 'Not implemented' } as ActionResult),
refreshMorning: async () => ({ ok: false, error: 'Not implemented' } as ActionResult),
saveMorningConfig: async (config: SubConfig) => ({ ok: false, error: 'Not implemented' } as ActionResult),
addSkill: async (agentId: string, skillName: string, description: string, trigger: string) => ({ ok: false, error: 'Not implemented' } as ActionResult),
// ── 远程 Skillsv2.6 暂无) ──
addRemoteSkill: async () => ({ ok: false, error: 'Not implemented' } as any),
remoteSkillsList: async () => ({ ok: true, remoteSkills: [], count: 0 } as any),
updateRemoteSkill: async () => ({ ok: false } as ActionResult),
removeRemoteSkill: async () => ({ ok: false } as ActionResult),
// ── M3: 成果物(v2.6 暂无后端,返回空) ──
artifacts: async (taskId: string): Promise<ArtifactsResult> => ({
ok: true, deliverable: null, nodes: [],
}),
artifactPreview: async (taskId: string, path: string): Promise<ArtifactPreviewResult> => ({
ok: false, previewable: false, name: '', type: '', render_as: '', size: 0, content: null,
}),
artifactDownloadUrl: (taskId: string, path: string) => '',
// ── M3: 人工干预(v2.6 暂无后端) ──
humanInput: async (taskId: string): Promise<HumanInputResult> => ({
ok: true, active: false, checkpoints: [],
}),
humanInputRespond: async (taskId: string, data: HumanInputRespondPayload) => ({ ok: false, error: 'Not implemented' } as ActionResult),
// ── 朝堂议政(v2.6 暂无后端) ──
courtDiscussStart: async () => ({ ok: false, error: 'Not implemented' } as CourtDiscussResult),
courtDiscussAdvance: async () => ({ ok: false, error: 'Not implemented' } as CourtDiscussResult),
courtDiscussConclude: async () => ({ ok: false, error: 'Not implemented' } as any),
courtDiscussDestroy: async () => ({ ok: false } as ActionResult),
courtDiscussFate: async () => ({ ok: true, event: '' }) as any,
};
// ── Types ──
// ── Types(保持 v1.0 完整类型定义) ──
export interface ActionResult {
ok: boolean;
message?: string;
error?: string;
}
export interface FlowEntry {
at: string;
from: string;
to: string;
remark: string;
}
export interface TodoItem {
id: string | number;
title: string;
status: 'not-started' | 'in-progress' | 'completed';
detail?: string;
}
export interface Heartbeat {
status: 'active' | 'warn' | 'stalled' | 'unknown' | 'idle';
label: string;
}
export interface ActionResult { ok: boolean; message?: string; error?: string; }
export interface FlowEntry { at: string; from: string; to: string; remark: string; }
export interface TodoItem { id: string | number; title: string; status: 'not-started' | 'in-progress' | 'completed'; detail?: string; }
export interface Heartbeat { status: 'active' | 'warn' | 'stalled' | 'unknown' | 'idle'; label: string; }
export interface Task {
id: string;
title: string;
state: string;
org: string;
now: string;
eta: string;
block: string;
ac: string;
output: string;
heartbeat: Heartbeat;
flow_log: FlowEntry[];
todos: TodoItem[];
review_round: number;
archived: boolean;
archivedAt?: string;
updatedAt?: string;
updated_at?: string; // moziplus backend returns snake_case
// moziplus fields
status?: string; // moziplus task status: created/planning/executing/completed/failed/cancelled/paused
plan_status?: string; // moziplus plan status: pending/ready/challenging/approved/rejected
nodes?: TaskNode[]; // moziplus DAG nodes
latest_event?: TaskEvent; // moziplus latest event
sourceMeta?: Record<string, unknown>;
activity?: ActivityEntry[];
_prev_state?: string;
id: string; title: string; state: string; org: string; now: string;
eta: string; block: string; ac: string; output: string;
heartbeat: Heartbeat; flow_log: FlowEntry[]; todos: TodoItem[];
review_round: number; archived: boolean; archivedAt?: string;
updatedAt?: string; updated_at?: string;
status?: string; plan_status?: string; nodes?: TaskNode[];
latest_event?: TaskEvent; sourceMeta?: Record<string, unknown>;
activity?: ActivityEntry[]; _prev_state?: string;
}
export interface TaskNode {
node_id: string;
name: string;
agent_id: string;
status: string;
depends_on?: string[];
output_summary?: string;
output?: string;
// Guard 字段
guard_status?: 'not_checked' | 'entry_passed' | 'entry_failed' | 'exit_passed' | 'exit_failed' | 'exit_warned';
guard_checks?: GuardCheck[];
rollback_count?: number;
node_id: string; name: string; agent_id: string; status: string;
depends_on?: string[]; output_summary?: string; output?: string;
guard_status?: string; guard_checks?: GuardCheck[]; rollback_count?: number;
}
export interface GuardCheck {
name: string;
passed: boolean;
message: string;
severity: 'error' | 'warn' | 'info';
}
export interface TaskEvent {
event_type: string;
reason: string;
timestamp: string;
}
export interface SyncStatus {
ok: boolean;
[key: string]: unknown;
}
export interface GuardCheck { name: string; passed: boolean; message: string; severity: 'error' | 'warn' | 'info'; }
export interface TaskEvent { event_type: string; reason: string; timestamp: string; }
export interface SyncStatus { ok: boolean; [key: string]: unknown; }
export interface LiveStatus {
tasks: Task[];
syncStatus: SyncStatus;
syncStatus: SyncStatus & { daemon?: any; projects?: Record<string, any>; currentProject?: string };
}
export interface AgentInfo {
id: string;
label: string;
emoji: string;
role: string;
model: string;
skills: SkillInfo[];
}
export interface SkillInfo {
name: string;
description: string;
path: string;
}
export interface KnownModel {
id: string;
label: string;
provider: string;
}
export interface AgentConfig {
agents: AgentInfo[];
knownModels?: KnownModel[];
dispatchChannel?: string;
}
export interface ChangeLogEntry {
at: string;
agentId: string;
oldModel: string;
newModel: string;
rolledBack?: boolean;
}
export interface AgentInfo { id: string; label: string; emoji: string; role: string; model: string; skills: SkillInfo[]; }
export interface SkillInfo { name: string; description: string; path: string; }
export interface KnownModel { id: string; label: string; provider: string; }
export interface AgentConfig { agents: AgentInfo[]; knownModels?: KnownModel[]; dispatchChannel?: string; }
export interface ChangeLogEntry { at: string; agentId: string; oldModel: string; newModel: string; rolledBack?: boolean; }
export interface OfficialInfo {
id: string;
label: string;
emoji: string;
role: string;
rank: string;
model: string;
model_short: string;
tokens_in: number;
tokens_out: number;
cache_read: number;
cache_write: number;
cost_cny: number;
cost_usd: number;
sessions: number;
messages: number;
tasks_done: number;
tasks_active: number;
tasks_failed?: number; // moziplus: 失败任务数
memorySize?: number; // MEMORY.md 字数
memoryUpdatedAt?: string; // MEMORY.md 最后修改时间
flow_participations: number;
merit_score: number;
merit_rank: number;
last_active: string;
heartbeat: Heartbeat;
id: string; label: string; emoji: string; role: string; rank: string;
model: string; model_short: string; tokens_in: number; tokens_out: number;
cache_read: number; cache_write: number; cost_cny: number; cost_usd: number;
sessions: number; messages: number; tasks_done: number; tasks_active: number;
tasks_failed?: number; memorySize?: number; memoryUpdatedAt?: string;
flow_participations: number; merit_score: number; merit_rank: number;
last_active: string; heartbeat: Heartbeat;
participated_edicts: { id: string; title: string; state: string; status?: string }[];
}
export interface OfficialsData {
officials: OfficialInfo[];
totals: { tasks_done: number; cost_cny: number };
top_official: string;
}
export interface OfficialsData { officials: OfficialInfo[]; totals: { tasks_done: number; cost_cny: number }; top_official: string; }
export interface AgentStatusInfo { id: string; label: string; emoji: string; role: string; status: string; statusLabel: string; lastActive?: string; }
export interface GatewayStatus { alive: boolean; probe: boolean; status: string; }
export interface AgentsStatusData { ok: boolean; gateway: GatewayStatus; agents: AgentStatusInfo[]; checkedAt: string; }
export interface AgentStatusInfo {
id: string;
label: string;
emoji: string;
role: string;
status: 'running' | 'idle' | 'offline' | 'unconfigured';
statusLabel: string;
lastActive?: string;
}
export interface GatewayStatus {
alive: boolean;
probe: boolean;
status: string;
}
export interface AgentsStatusData {
ok: boolean;
gateway: GatewayStatus;
agents: AgentStatusInfo[];
checkedAt: string;
}
export interface MorningNewsItem {
title: string;
summary?: string;
desc?: string;
link: string;
source: string;
image?: string;
pub_date?: string;
}
export interface MorningBrief {
date?: string;
generated_at?: string;
categories: Record<string, MorningNewsItem[]>;
}
export interface SubCategoryConfig {
name: string;
enabled: boolean;
}
export interface CustomFeed {
name: string;
url: string;
category: string;
}
export interface SubConfig {
categories: SubCategoryConfig[];
keywords: string[];
custom_feeds: CustomFeed[];
feishu_webhook: string;
}
export interface MorningNewsItem { title: string; summary?: string; desc?: string; link: string; source: string; image?: string; pub_date?: string; }
export interface MorningBrief { date?: string; generated_at?: string; categories: Record<string, MorningNewsItem[]>; }
export interface SubCategoryConfig { name: string; enabled: boolean; }
export interface CustomFeed { name: string; url: string; category: string; }
export interface SubConfig { categories: SubCategoryConfig[]; keywords: string[]; custom_feeds: CustomFeed[]; feishu_webhook: string; }
export interface ActivityEntry {
kind: string;
at?: number | string;
text?: string;
thinking?: string;
agent?: string;
from?: string;
to?: string;
remark?: string;
tools?: { name: string; input_preview?: string }[];
tool?: string;
output?: string;
exitCode?: number | null;
kind: string; at?: number | string; text?: string; thinking?: string;
agent?: string; from?: string; to?: string; remark?: string;
tools?: { name: string; input_preview?: string }[]; tool?: string;
output?: string; exitCode?: number | null;
items?: TodoItem[];
diff?: {
changed?: { id: string; from: string; to: string }[];
added?: { id: string; title: string }[];
removed?: { id: string; title: string }[];
};
diff?: { changed?: { id: string; from: string; to: string }[]; added?: { id: string; title: string }[]; removed?: { id: string; title: string }[] };
}
export interface PhaseDuration {
phase: string;
durationSec: number;
durationText: string;
ongoing?: boolean;
}
export interface TodosSummary {
total: number;
completed: number;
inProgress: number;
notStarted: number;
percent: number;
}
export interface ResourceSummary {
totalTokens?: number;
totalCost?: number;
totalElapsedSec?: number;
}
export interface TimelineEntry {
time: string;
phase: string;
node_id: string;
node_name: string;
agent: string;
action: string;
verdict: string;
detail: string;
}
export interface PhaseDuration { phase: string; durationSec: number; durationText: string; ongoing?: boolean; }
export interface TodosSummary { total: number; completed: number; inProgress: number; notStarted: number; percent: number; }
export interface ResourceSummary { totalTokens?: number; totalCost?: number; totalElapsedSec?: number; }
export interface TimelineEntry { time: string; phase: string; node_id: string; node_name: string; agent: string; action: string; verdict: string; detail: string; }
export interface TaskActivityData {
ok: boolean;
message?: string;
error?: string;
activity?: ActivityEntry[];
timeline?: TimelineEntry[];
relatedAgents?: string[];
agentLabel?: string;
lastActive?: string;
phaseDurations?: PhaseDuration[];
totalDuration?: string;
todosSummary?: TodosSummary;
resourceSummary?: ResourceSummary;
ok: boolean; message?: string; error?: string;
activity?: ActivityEntry[]; timeline?: TimelineEntry[];
relatedAgents?: string[]; agentLabel?: string; lastActive?: string;
phaseDurations?: PhaseDuration[]; totalDuration?: string;
todosSummary?: TodosSummary; resourceSummary?: ResourceSummary;
}
export interface SchedulerInfo {
retryCount?: number;
escalationLevel?: number;
lastDispatchStatus?: string;
stallThresholdSec?: number;
enabled?: boolean;
lastProgressAt?: string;
lastDispatchAt?: string;
lastDispatchAgent?: string;
autoRollback?: boolean;
}
export interface SchedulerInfo { retryCount?: number; escalationLevel?: number; lastDispatchStatus?: string; stallThresholdSec?: number; enabled?: boolean; lastProgressAt?: string; lastDispatchAt?: string; lastDispatchAgent?: string; autoRollback?: boolean; }
export interface SchedulerStateData { ok: boolean; error?: string; scheduler?: SchedulerInfo; stalledSec?: number; }
export interface SkillContentResult { ok: boolean; name?: string; agent?: string; content?: string; path?: string; error?: string; }
export interface ScanAction { taskId: string; action: string; to?: string; toState?: string; stalledSec?: number; }
export interface CreateTaskPayload { title: string; org?: string; targetDept?: string; priority?: string; templateId?: string; params?: Record<string, string>; requirement?: string; project_root?: string; project_type?: string; }
export interface SchedulerStateData {
ok: boolean;
error?: string;
scheduler?: SchedulerInfo;
stalledSec?: number;
}
export interface RemoteSkillItem { skillName: string; agentId: string; sourceUrl: string; description: string; localPath: string; addedAt: string; lastUpdated: string; status: string; }
export interface RemoteSkillsListResult { ok: boolean; remoteSkills?: RemoteSkillItem[]; count?: number; listedAt?: string; error?: string; }
export interface SkillContentResult {
ok: boolean;
name?: string;
agent?: string;
content?: string;
path?: string;
error?: string;
}
export interface CourtDiscussResult { ok: boolean; session_id?: string; topic?: string; round?: number; new_messages?: Array<{ official_id: string; name: string; content: string; emotion?: string; action?: string }>; scene_note?: string; total_messages?: number; error?: string; }
export interface ScanAction {
taskId: string;
action: string;
to?: string;
toState?: string;
stalledSec?: number;
}
export interface CreateTaskPayload {
title: string;
org?: string;
targetDept?: string;
priority?: string;
templateId?: string;
params?: Record<string, string>;
// moziplus fields
requirement?: string;
project_root?: string;
project_type?: string;
}
export interface RemoteSkillItem {
skillName: string;
agentId: string;
sourceUrl: string;
description: string;
localPath: string;
addedAt: string;
lastUpdated: string;
status: 'valid' | 'not-found' | string;
}
export interface RemoteSkillsListResult {
ok: boolean;
remoteSkills?: RemoteSkillItem[];
count?: number;
listedAt?: string;
error?: string;
}
// ── 朝堂议政 ──
export interface CourtDiscussResult {
ok: boolean;
session_id?: string;
topic?: string;
round?: number;
new_messages?: Array<{
official_id: string;
name: string;
content: string;
emotion?: string;
action?: string;
}>;
scene_note?: string;
total_messages?: number;
error?: string;
}
// ── M3: 成果物 ──
export interface ArtifactEntry {
name: string;
path: string;
size: number;
type: string; // document | code | data | config | other
render_as: string; // markdown | code | table | binary
previewable: boolean;
}
export interface ArtifactNode {
node_id: string;
name: string;
agent_id: string;
status: string;
artifacts: ArtifactEntry[];
}
export interface ArtifactsResult {
ok: boolean;
deliverable: ArtifactEntry | null;
nodes: ArtifactNode[];
}
export interface ArtifactPreviewResult {
ok: boolean;
previewable: boolean;
name: string;
type: string;
render_as: string;
size: number;
content: string | null;
message?: string;
}
// ── M3: 人工干预 ──
export interface CheckpointInfo {
node_id: string;
node_name: string;
agent_id: string;
checkpoint: HumanInputCheckpoint;
triggered_at: string;
}
export interface ArtifactEntry { name: string; path: string; size: number; type: string; render_as: string; previewable: boolean; }
export interface ArtifactNode { node_id: string; name: string; agent_id: string; status: string; artifacts: ArtifactEntry[]; }
export interface ArtifactsResult { ok: boolean; deliverable: ArtifactEntry | null; nodes: ArtifactNode[]; }
export interface ArtifactPreviewResult { ok: boolean; previewable: boolean; name: string; type: string; render_as: string; size: number; content: string | null; message?: string; }
export interface CheckpointInfo { node_id: string; node_name: string; agent_id: string; checkpoint: HumanInputCheckpoint; triggered_at: string; }
export interface HumanInputCheckpoint {
type: 'verify' | 'decision' | 'action';
title: string;
description?: string;
urgency?: string;
options?: Array<{
id: string;
label: string;
description?: string;
pros?: string[];
cons?: string[];
recommended?: boolean;
}>;
verificationSteps?: string[];
autoCheckResults?: Array<{ label: string; passed: boolean }>;
type: 'verify' | 'decision' | 'action'; title: string; description?: string; urgency?: string;
options?: Array<{ id: string; label: string; description?: string; pros?: string[]; cons?: string[]; recommended?: boolean }>;
verificationSteps?: string[]; autoCheckResults?: Array<{ label: string; passed: boolean }>;
actionSteps?: Array<{ id: string; description: string; command?: string }>;
verificationCommand?: string;
artifacts?: Array<{ name: string; path: string }>;
}
export interface HumanInputResult {
ok: boolean;
active: boolean;
checkpoints: CheckpointInfo[];
}
export interface HumanInputRespondPayload {
node_id?: string;
action?: string;
reason?: string;
selected_option?: string;
completed_steps?: string[];
verification_note?: string;
free_text?: string;
}
export interface HumanInputResult { ok: boolean; active: boolean; checkpoints: CheckpointInfo[]; }
export interface HumanInputRespondPayload { node_id?: string; action?: string; reason?: string; selected_option?: string; completed_steps?: string[]; verification_note?: string; free_text?: string; }
+5 -6
View File
@@ -1,10 +1,9 @@
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import './styles/global.css';
import React from 'react'
import ReactDOM from 'react-dom/client'
import App from './App'
ReactDOM.createRoot(document.getElementById('root')!).render(
<React.StrictMode>
<App />
</React.StrictMode>
);
</React.StrictMode>,
)