mirror of
https://github.com/YspCoder/clawgo.git
synced 2026-05-03 07:07:29 +08:00
autonomy M1 phase2: expose idle-run source and block reasons in task queue; add whitelist policy plumbing
This commit is contained in:
@@ -361,6 +361,10 @@ func (al *AgentLoop) appendTaskAuditEvent(taskID string, msg bus.InboundMessage,
|
||||
}
|
||||
path := filepath.Join(al.workspace, "memory", "task-audit.jsonl")
|
||||
_ = os.MkdirAll(filepath.Dir(path), 0755)
|
||||
source := "direct"
|
||||
if msg.Metadata != nil && msg.Metadata["trigger"] != "" {
|
||||
source = msg.Metadata["trigger"]
|
||||
}
|
||||
row := map[string]interface{}{
|
||||
"task_id": taskID,
|
||||
"time": time.Now().UTC().Format(time.RFC3339),
|
||||
@@ -369,6 +373,8 @@ func (al *AgentLoop) appendTaskAuditEvent(taskID string, msg bus.InboundMessage,
|
||||
"chat_id": msg.ChatID,
|
||||
"sender_id": msg.SenderID,
|
||||
"status": status,
|
||||
"source": source,
|
||||
"idle_run": source == "autonomy",
|
||||
"duration_ms": durationMs,
|
||||
"suppressed": suppressed,
|
||||
"retry_count": 0,
|
||||
|
||||
@@ -1436,6 +1436,43 @@ func (s *RegistryServer) handleWebUITaskQueue(w http.ResponseWriter, r *http.Req
|
||||
running = append(running, row)
|
||||
}
|
||||
}
|
||||
|
||||
// Merge autonomy queue states (including waiting/blocked-by-user) for full audit visibility.
|
||||
tasksPath := filepath.Join(strings.TrimSpace(s.workspacePath), "memory", "tasks.json")
|
||||
if tb, err := os.ReadFile(tasksPath); err == nil {
|
||||
var tasks []map[string]interface{}
|
||||
if json.Unmarshal(tb, &tasks) == nil {
|
||||
seen := map[string]struct{}{}
|
||||
for _, it := range items {
|
||||
seen[fmt.Sprintf("%v", it["task_id"])] = struct{}{}
|
||||
}
|
||||
for _, t := range tasks {
|
||||
id := fmt.Sprintf("%v", t["id"])
|
||||
if id == "" {
|
||||
continue
|
||||
}
|
||||
if _, ok := seen[id]; ok {
|
||||
continue
|
||||
}
|
||||
row := map[string]interface{}{
|
||||
"task_id": id,
|
||||
"time": t["updated_at"],
|
||||
"status": t["status"],
|
||||
"source": t["source"],
|
||||
"idle_run": true,
|
||||
"input_preview": t["content"],
|
||||
"block_reason": t["block_reason"],
|
||||
"logs": []string{fmt.Sprintf("autonomy state: %v", t["status"])},
|
||||
"retry_count": 0,
|
||||
}
|
||||
items = append(items, row)
|
||||
if fmt.Sprintf("%v", row["status"]) == "running" {
|
||||
running = append(running, row)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_ = json.NewEncoder(w).Encode(map[string]interface{}{"ok": true, "running": running, "items": items})
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,9 @@ type TaskAuditItem = {
|
||||
chat_id?: string;
|
||||
sender_id?: string;
|
||||
status?: string;
|
||||
source?: string;
|
||||
idle_run?: boolean;
|
||||
block_reason?: string;
|
||||
duration_ms?: number;
|
||||
retry_count?: number;
|
||||
error?: string;
|
||||
@@ -72,7 +75,7 @@ const TaskAudit: React.FC = () => {
|
||||
className={`w-full text-left px-3 py-2 border-b border-zinc-800/60 hover:bg-zinc-800/40 ${active ? 'bg-indigo-500/15' : ''}`}
|
||||
>
|
||||
<div className="text-sm font-medium text-zinc-100 truncate">{it.task_id || `task-${idx + 1}`}</div>
|
||||
<div className="text-xs text-zinc-400 truncate">{it.channel} · {it.status} · {it.duration_ms || 0}ms · retry:{it.retry_count || 0}</div>
|
||||
<div className="text-xs text-zinc-400 truncate">{it.channel || '-'} · {it.status} · {it.duration_ms || 0}ms · retry:{it.retry_count || 0} · {it.source || '-'}</div>
|
||||
<div className="text-[11px] text-zinc-500 truncate">{it.time}</div>
|
||||
</button>
|
||||
);
|
||||
@@ -90,6 +93,7 @@ const TaskAudit: React.FC = () => {
|
||||
<div className="grid grid-cols-2 md:grid-cols-3 gap-3">
|
||||
<div><div className="text-zinc-500 text-xs">Task ID</div><div className="font-mono break-all">{selected.task_id}</div></div>
|
||||
<div><div className="text-zinc-500 text-xs">Status</div><div>{selected.status}</div></div>
|
||||
<div><div className="text-zinc-500 text-xs">Source</div><div>{selected.source || '-'}</div></div>
|
||||
<div><div className="text-zinc-500 text-xs">Duration</div><div>{selected.duration_ms || 0}ms</div></div>
|
||||
<div><div className="text-zinc-500 text-xs">Channel</div><div>{selected.channel}</div></div>
|
||||
<div><div className="text-zinc-500 text-xs">Session</div><div className="font-mono break-all">{selected.session}</div></div>
|
||||
@@ -106,6 +110,11 @@ const TaskAudit: React.FC = () => {
|
||||
<div className="p-2 rounded bg-zinc-950/60 border border-zinc-800 whitespace-pre-wrap text-red-300">{selected.error || '-'}</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div className="text-zinc-500 text-xs mb-1">Block Reason</div>
|
||||
<div className="p-2 rounded bg-zinc-950/60 border border-zinc-800 whitespace-pre-wrap text-amber-200">{selected.block_reason || '-'}</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div className="text-zinc-500 text-xs mb-1">{t('taskLogs')}</div>
|
||||
<div className="p-2 rounded bg-zinc-950/60 border border-zinc-800 whitespace-pre-wrap text-zinc-200">{Array.isArray(selected.logs) && selected.logs.length ? selected.logs.join('\n') : '-'}</div>
|
||||
|
||||
Reference in New Issue
Block a user