diff --git a/src/frontend/src/api.ts b/src/frontend/src/api.ts index c0253aa..a7e7ea2 100644 --- a/src/frontend/src/api.ts +++ b/src/frontend/src/api.ts @@ -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(url: string): Promise { @@ -22,559 +36,343 @@ async function postJ(url: string, data: unknown): Promise { 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(`${API_BASE}/api/live-status`), - agentConfig: () => fetchJ(`${API_BASE}/api/agent-config`), - modelChangeLog: () => fetchJ(`${API_BASE}/api/model-change-log`).catch(() => []), - officialsStats: () => fetchJ(`${API_BASE}/api/officials-stats`), - morningBrief: () => fetchJ(`${API_BASE}/api/morning-brief`), - morningConfig: () => fetchJ(`${API_BASE}/api/morning-config`), - agentsStatus: () => fetchJ(`${API_BASE}/api/agents-status`), + // ── 核心数据 ── - // 任务实时动态 - taskActivity: (id: string) => - fetchJ(`${API_BASE}/api/task-activity/${encodeURIComponent(id)}`), - schedulerState: (id: string) => - fetchJ(`${API_BASE}/api/scheduler-state/${encodeURIComponent(id)}`), + /** 聚合状态:项目列表 + 当前项目任务 + daemon 状态 */ + liveStatus: async (): Promise => { + const [projectsMap, daemonData] = await Promise.all([ + fetchJ<{ projects: Record }>(`${API_BASE}/api/projects`).catch(() => ({ projects: {} })), + fetchJ(`${API_BASE}/api/daemon/status`).catch(() => ({})), + ]); - // 技能内容 - skillContent: (agentId: string, skillName: string) => - fetchJ( - `${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(`${API_BASE}/api/set-model`, { agentId, model }), - setDispatchChannel: (channel: string) => - postJ(`${API_BASE}/api/set-dispatch-channel`, { channel }), - agentWake: (agentId: string) => - postJ(`${API_BASE}/api/agent-wake`, { agentId }), - taskAction: (taskId: string, action: string, reason: string) => - postJ(`${API_BASE}/api/task-action`, { taskId, action, reason }), - reviewAction: (taskId: string, action: string, comment: string) => - postJ(`${API_BASE}/api/review-action`, { taskId, action, comment }), - advanceState: (taskId: string, comment: string) => - postJ(`${API_BASE}/api/advance-state`, { taskId, comment }), - archiveTask: (taskId: string, archived: boolean) => - postJ(`${API_BASE}/api/archive-task`, { taskId, archived }), - archiveAllDone: () => - postJ(`${API_BASE}/api/archive-task`, { archiveAllDone: true }), - schedulerScan: (thresholdSec = 180) => - postJ( - `${API_BASE}/api/scheduler-scan`, - { thresholdSec } - ), - schedulerRetry: (taskId: string, reason: string) => - postJ(`${API_BASE}/api/scheduler-retry`, { taskId, reason }), - schedulerEscalate: (taskId: string, reason: string) => - postJ(`${API_BASE}/api/scheduler-escalate`, { taskId, reason }), - schedulerRollback: (taskId: string, reason: string) => - postJ(`${API_BASE}/api/scheduler-rollback`, { taskId, reason }), - refreshMorning: () => - postJ(`${API_BASE}/api/morning-brief/refresh`, {}), - saveMorningConfig: (config: SubConfig) => - postJ(`${API_BASE}/api/morning-config`, config), - addSkill: (agentId: string, skillName: string, description: string, trigger: string) => - postJ(`${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( - `${API_BASE}/api/add-remote-skill`, { agentId, skillName, sourceUrl, description: description || '' } - ), - remoteSkillsList: () => - fetchJ(`${API_BASE}/api/remote-skills-list`), - updateRemoteSkill: (agentId: string, skillName: string) => - postJ(`${API_BASE}/api/update-remote-skill`, { agentId, skillName }), - removeRemoteSkill: (agentId: string, skillName: string) => - postJ(`${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(`${API_BASE}/api/tasks`, data), + return { + tasks, + syncStatus: { + ok: true, + daemon: daemonData, + projects: projectsMap, + currentProject: pid, + }, + }; + }, - // ── M3: 成果物 ── - artifacts: (taskId: string) => - fetchJ(`${API_BASE}/api/tasks/${encodeURIComponent(taskId)}/artifacts`), - artifactPreview: (taskId: string, path: string) => - fetchJ(`${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 }> => { + return fetchJ(`${API_BASE}/api/projects`); + }, - // ── M3: 人工干预 ── - humanInput: (taskId: string) => - fetchJ(`${API_BASE}/api/tasks/${encodeURIComponent(taskId)}/human-input`), - humanInputRespond: (taskId: string, data: HumanInputRespondPayload) => - postJ(`${API_BASE}/api/tasks/${encodeURIComponent(taskId)}/human-input/respond`, data), + /** 创建项目 */ + createProject: (data: { id?: string; name: string; description?: string | null }) => + postJ(`${API_BASE}/api/projects`, data), - // ── 朝堂议政 ── - courtDiscussStart: (topic: string, officials: string[], taskId?: string) => - postJ(`${API_BASE}/api/court-discuss/start`, { topic, officials, taskId }), - courtDiscussAdvance: (sessionId: string, userMessage?: string, decree?: string) => - postJ(`${API_BASE}/api/court-discuss/advance`, { sessionId, userMessage, decree }), - courtDiscussConclude: (sessionId: string) => - postJ(`${API_BASE}/api/court-discuss/conclude`, { sessionId }), - courtDiscussDestroy: (sessionId: string) => - postJ(`${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 => ({ + agents: [], + knownModels: [], + }), + + modelChangeLog: async (): Promise => [], + + officialsStats: async (): Promise => ({ + officials: [], + totals: { tasks_done: 0, cost_cny: 0 }, + top_official: '', + }), + + agentsStatus: async (): Promise => ({ + ok: true, + gateway: { alive: true, probe: true, status: 'running' }, + agents: [], + checkedAt: new Date().toISOString(), + }), + + morningBrief: async (): Promise => ({ + categories: {}, + }), + + morningConfig: async (): Promise => ({ + categories: [], + keywords: [], + custom_feeds: [], + feishu_webhook: '', + }), + + // ── 任务实时动态(v2.6 用 events 兜底) ── + + taskActivity: async (id: string): Promise => { + 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 => ({ + ok: true, scheduler: {}, + }), + + // ── 技能内容(v2.6 暂无) ── + + skillContent: async (agentId: string, skillName: string): Promise => ({ + ok: false, error: 'Not implemented in v2.6', + }), + + // ── 操作类 ── + + setModel: async (agentId: string, model: string): Promise => ({ ok: false, error: 'Not implemented' }), + setDispatchChannel: async (channel: string): Promise => ({ ok: false, error: 'Not implemented' }), + agentWake: async (agentId: string): Promise => ({ ok: false, error: 'Not implemented' }), + + taskAction: async (taskId: string, action: string, reason: string): Promise => { + try { + const pid = _currentProjectId || Object.keys((await api.projects()).projects)[0]; + if (!pid) return { ok: false, error: 'No project' }; + const statusMap: Record = { + 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 => { + 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 => ({ ok: false, error: 'Not implemented' }), + + archiveTask: async (taskId: string, archived: boolean): Promise => ({ ok: true }), + + archiveAllDone: async (): Promise => ({ ok: true, count: 0 }), + + createTask: async (data: CreateTaskPayload): Promise => { + 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 => ({ + ok: true, deliverable: null, nodes: [], + }), + artifactPreview: async (taskId: string, path: string): Promise => ({ + 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 => ({ + 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; - 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; + 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; 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; -} - -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; } +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; 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; - // 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; } diff --git a/src/frontend/src/main.tsx b/src/frontend/src/main.tsx index dc3f4b5..c4c5b6d 100644 --- a/src/frontend/src/main.tsx +++ b/src/frontend/src/main.tsx @@ -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( - -); + , +)