auto-sync: 2026-05-17 11:24:16
This commit is contained in:
+307
-509
@@ -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),
|
||||
|
||||
// ── 远程 Skills(v2.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; }
|
||||
|
||||
@@ -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>,
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user