diff --git a/pkg/nodes/registry_server.go b/pkg/nodes/registry_server.go index 8af4d4a..5f3a213 100644 --- a/pkg/nodes/registry_server.go +++ b/pkg/nodes/registry_server.go @@ -92,6 +92,7 @@ func (s *RegistryServer) Start(ctx context.Context) error { mux.HandleFunc("/webui/api/task_audit", s.handleWebUITaskAudit) mux.HandleFunc("/webui/api/task_queue", s.handleWebUITaskQueue) mux.HandleFunc("/webui/api/tasks", s.handleWebUITasks) + mux.HandleFunc("/webui/api/task_daily_summary", s.handleWebUITaskDailySummary) mux.HandleFunc("/webui/api/exec_approvals", s.handleWebUIExecApprovals) mux.HandleFunc("/webui/api/logs/stream", s.handleWebUILogsStream) mux.HandleFunc("/webui/api/logs/recent", s.handleWebUILogsRecent) @@ -1559,6 +1560,38 @@ func (s *RegistryServer) handleWebUITaskQueue(w http.ResponseWriter, r *http.Req _ = json.NewEncoder(w).Encode(map[string]interface{}{"ok": true, "running": running, "items": items, "stats": stats}) } +func (s *RegistryServer) handleWebUITaskDailySummary(w http.ResponseWriter, r *http.Request) { + if !s.checkAuth(r) { + http.Error(w, "unauthorized", http.StatusUnauthorized) + return + } + if r.Method != http.MethodGet { + http.Error(w, "method not allowed", http.StatusMethodNotAllowed) + return + } + date := r.URL.Query().Get("date") + if date == "" { + date = time.Now().UTC().Format("2006-01-02") + } + path := filepath.Join(strings.TrimSpace(s.workspacePath), "memory", date+".md") + b, err := os.ReadFile(path) + if err != nil { + _ = json.NewEncoder(w).Encode(map[string]interface{}{"ok": true, "date": date, "report": ""}) + return + } + text := string(b) + marker := "## Autonomy Daily Report (" + date + ")" + idx := strings.Index(text, marker) + report := "" + if idx >= 0 { + report = text[idx:] + if n := strings.Index(report[len(marker):], "\n## "); n > 0 { + report = report[:len(marker)+n] + } + } + _ = json.NewEncoder(w).Encode(map[string]interface{}{"ok": true, "date": date, "report": report}) +} + func (s *RegistryServer) handleWebUITasks(w http.ResponseWriter, r *http.Request) { if !s.checkAuth(r) { http.Error(w, "unauthorized", http.StatusUnauthorized) diff --git a/webui/src/i18n/index.ts b/webui/src/i18n/index.ts index 7948bb9..a1cabe9 100644 --- a/webui/src/i18n/index.ts +++ b/webui/src/i18n/index.ts @@ -31,6 +31,8 @@ const resources = { createTask: 'Create', updateTask: 'Update', deleteTask: 'Delete', + dailySummary: 'Daily Summary', + noDailySummary: 'No autonomy daily summary yet.', error: 'Error', noTaskAudit: 'No task audit records', selectTask: 'Select a task from the left list', @@ -196,6 +198,8 @@ const resources = { createTask: '新建', updateTask: '更新', deleteTask: '删除', + dailySummary: '日报摘要', + noDailySummary: '暂无自治日报。', error: '错误', noTaskAudit: '暂无任务审计记录', selectTask: '请从左侧选择任务', diff --git a/webui/src/pages/TaskAudit.tsx b/webui/src/pages/TaskAudit.tsx index a8e9dc0..599ef1b 100644 --- a/webui/src/pages/TaskAudit.tsx +++ b/webui/src/pages/TaskAudit.tsx @@ -33,6 +33,7 @@ const TaskAudit: React.FC = () => { const [sourceFilter, setSourceFilter] = useState('all'); const [statusFilter, setStatusFilter] = useState('all'); const [draft, setDraft] = useState({ id: '', content: '', priority: 'normal', status: 'todo', source: 'manual', due_at: '' }); + const [dailyReport, setDailyReport] = useState(''); const fetchData = async () => { setLoading(true); @@ -45,6 +46,13 @@ const TaskAudit: React.FC = () => { const sorted = arr.sort((a: any, b: any) => String(b.time || '').localeCompare(String(a.time || ''))); setItems(sorted); if (sorted.length > 0) setSelected(sorted[0]); + const dr = await fetch(`/webui/api/task_daily_summary${q}`); + if (dr.ok) { + const dj = await dr.json(); + setDailyReport(String(dj.report || '')); + } else { + setDailyReport(''); + } } catch (e) { console.error(e); setItems([]); @@ -116,6 +124,11 @@ const TaskAudit: React.FC = () => { +
+
{t('dailySummary')}
+
{dailyReport || t('noDailySummary')}
+
+
{t('taskQueue')}