fix(agent): debug panel copyDebugInfo — full state snapshot (was 9 fields, now all model atoms)
Previously copyDebugInfo() only exported 9 hand-picked fields (conversation_id, thread_id, connection/streaming state, user, env, message count, truncated tool calls, error). The debug panel was missing LLM health (status, retry, banner), confirmation/HITL state (pending_tool, args, risk), queue position, message previews, full tool call objects, and UI flags (sidebar, debug panel, cancelled). Now: - Full model snapshot with all fields - active_tool_calls_full — complete ToolCall objects - last_message_preview — first 200 chars of last message - LLM status, banner dismiss, retry countdown - HITL confirmation state (pending_tool_name, args, risk, level) - Conversations count, queue position, user_cancelled flag - Visual debug panel grid: 5-column layout with new rows for LLM health, confirmation, queue, sidebar, convs_count
This commit is contained in:
@@ -287,18 +287,49 @@
|
||||
}
|
||||
|
||||
async function copyDebugInfo() {
|
||||
const lastMsg = model.messages.at(-1);
|
||||
const payload = {
|
||||
// ── Identifiers ──
|
||||
conversation_id: model.currentConversationId,
|
||||
pending_thread_id: model.pendingThreadId,
|
||||
connection_state: model.connectionState,
|
||||
streaming_state: model.streamingState,
|
||||
user_id: model.userId,
|
||||
environment_id: model.envId,
|
||||
messages: model.messages.length,
|
||||
active_tool_calls: model.activeToolCalls.map((tc) => ({
|
||||
tool: tc.tool,
|
||||
status: tc.status,
|
||||
})),
|
||||
// ── Connection & Streaming ──
|
||||
connection_state: model.connectionState,
|
||||
streaming_state: model.streamingState,
|
||||
agent_phase: model.agentPhase,
|
||||
// ── Messages ──
|
||||
messages_count: model.messages.length,
|
||||
last_message_id: lastMsg?.id ?? null,
|
||||
last_message_role: lastMsg?.role ?? null,
|
||||
last_message_preview: lastMsg?.text?.slice(0, 200) ?? null,
|
||||
// ── Streaming buffer ──
|
||||
partial_text_length: model.partialText.length,
|
||||
partial_tokens_count: model.partialTokens.length,
|
||||
// ── Tool calls (full objects) ──
|
||||
active_tool_calls: model.activeToolCalls.length,
|
||||
active_tool_calls_full: model.activeToolCalls,
|
||||
// ── HITL / Confirmation ──
|
||||
confirmation_message: model.confirmationMessage,
|
||||
pending_tool_name: model.pendingToolName,
|
||||
pending_tool_args: model.pendingToolArgs,
|
||||
pending_confirmation_risk: model.pendingConfirmationRisk,
|
||||
pending_risk_level: model.pendingRiskLevel,
|
||||
// ── LLM health ──
|
||||
llm_status: model.llmStatus,
|
||||
llm_banner_dismissed: model.llmBannerDismissed,
|
||||
llm_retry_countdown: model.llmRetryCountdown,
|
||||
llm_banner_message: model.llmBannerMessage,
|
||||
// ── Conversation list ──
|
||||
conversations_count: model.conversations.length,
|
||||
conversations_has_next: model.conversationsHasNext,
|
||||
// ── UI state ──
|
||||
is_debug_panel_open: model.isDebugPanelOpen,
|
||||
is_conversation_sidebar_open: model.isConversationSidebarOpen,
|
||||
is_loading_history: model.isLoadingHistory,
|
||||
queue_position: model.queuePosition,
|
||||
user_cancelled: model._userCancelled,
|
||||
// ── Error ──
|
||||
error: model.error,
|
||||
};
|
||||
try {
|
||||
@@ -415,23 +446,29 @@
|
||||
</div>
|
||||
|
||||
{#if model.isDebugPanelOpen}
|
||||
<div class="mt-3 grid gap-2 rounded-lg border border-border bg-surface-page px-3 py-2 text-[11px] text-text-muted sm:grid-cols-2 lg:grid-cols-4">
|
||||
<div class="mt-3 grid gap-2 rounded-lg border border-border bg-surface-page px-3 py-2 text-[11px] text-text-muted sm:grid-cols-2 lg:grid-cols-5">
|
||||
<!-- ── Row 1: IDs ── -->
|
||||
<div class="min-w-0">
|
||||
<span class="font-medium text-text-subtle">conv_id</span>
|
||||
<div class="truncate font-mono text-text" title={model.conversationIdLabel}>{model.conversationIdLabel}</div>
|
||||
<div class="truncate font-mono text-text" title={model.conversationIdLabel || "null"}>{model.conversationIdLabel || "null"}</div>
|
||||
</div>
|
||||
<div class="min-w-0">
|
||||
<span class="font-medium text-text-subtle">thread_id</span>
|
||||
<div class="truncate font-mono text-text" title={model.pendingThreadIdLabel}>{model.pendingThreadIdLabel}</div>
|
||||
</div>
|
||||
<div class="min-w-0">
|
||||
<span class="font-medium text-text-subtle">state</span>
|
||||
<div class="truncate font-mono text-text">{model.connectionState} / {model.streamingState}</div>
|
||||
</div>
|
||||
<div class="min-w-0">
|
||||
<span class="font-medium text-text-subtle">env / user</span>
|
||||
<div class="truncate font-mono text-text" title={`${model.envIdLabel} / ${model.userIdLabel}`}>{model.envIdLabel} / {model.userIdLabel}</div>
|
||||
</div>
|
||||
<div class="min-w-0">
|
||||
<span class="font-medium text-text-subtle">phase</span>
|
||||
<div class="truncate font-mono text-text">{model.agentPhase}</div>
|
||||
</div>
|
||||
<div class="min-w-0">
|
||||
<span class="font-medium text-text-subtle">state</span>
|
||||
<div class="truncate font-mono text-text">{model.connectionState} / {model.streamingState}</div>
|
||||
</div>
|
||||
<!-- ── Row 2: Messages & tools ── -->
|
||||
<div class="min-w-0">
|
||||
<span class="font-medium text-text-subtle">messages</span>
|
||||
<div class="truncate font-mono text-text">{model.messageCountLabel}</div>
|
||||
@@ -441,12 +478,69 @@
|
||||
<div class="truncate font-mono text-text" title={model.lastMessageIdLabel}>{model.lastMessageIdLabel}</div>
|
||||
</div>
|
||||
<div class="min-w-0">
|
||||
<span class="font-medium text-text-subtle">tools</span>
|
||||
<span class="font-medium text-text-subtle">tools (active)</span>
|
||||
<div class="truncate font-mono text-text">{model.activeToolCalls.length}</div>
|
||||
</div>
|
||||
<div class="min-w-0">
|
||||
<span class="font-medium text-text-subtle">queue</span>
|
||||
<div class="truncate font-mono text-text">{model.queuePosition}</div>
|
||||
</div>
|
||||
<div class="min-w-0">
|
||||
<span class="font-medium text-text-subtle">partial_tokens</span>
|
||||
<div class="truncate font-mono text-text">{model.partialTokens.length}</div>
|
||||
</div>
|
||||
<!-- ── Row 3: LLM health ── -->
|
||||
<div class="min-w-0">
|
||||
<span class="font-medium text-text-subtle">llm_status</span>
|
||||
<div class="truncate font-mono text-text">{model.llmStatus}</div>
|
||||
</div>
|
||||
<div class="min-w-0">
|
||||
<span class="font-medium text-text-subtle">llm_retry</span>
|
||||
<div class="truncate font-mono text-text">{model.llmRetryCountdown}s</div>
|
||||
</div>
|
||||
<div class="min-w-0">
|
||||
<span class="font-medium text-text-subtle">banner_dismissed</span>
|
||||
<div class="truncate font-mono text-text">{String(model.llmBannerDismissed)}</div>
|
||||
</div>
|
||||
<div class="min-w-0">
|
||||
<span class="font-medium text-text-subtle">sidebar</span>
|
||||
<div class="truncate font-mono text-text">{String(model.isConversationSidebarOpen)}</div>
|
||||
</div>
|
||||
<div class="min-w-0">
|
||||
<span class="font-medium text-text-subtle">convs_count</span>
|
||||
<div class="truncate font-mono text-text">{model.conversations.length}</div>
|
||||
</div>
|
||||
<!-- ── Row 4: Confirmation (if active) ── -->
|
||||
{#if model.pendingToolName}
|
||||
<div class="min-w-0">
|
||||
<span class="font-medium text-text-subtle">pending_tool</span>
|
||||
<div class="truncate font-mono text-text">{model.pendingToolName}</div>
|
||||
</div>
|
||||
<div class="min-w-0">
|
||||
<span class="font-medium text-text-subtle">risk</span>
|
||||
<div class="truncate font-mono text-text">{model.pendingConfirmationRisk || model.pendingRiskLevel || "—"}</div>
|
||||
</div>
|
||||
<div class="min-w-0">
|
||||
<span class="font-medium text-text-subtle">confirm_msg</span>
|
||||
<div class="truncate font-mono text-text" title={model.confirmationMessage || ""}>{model.confirmationMessage?.slice(0, 60) || "—"}</div>
|
||||
</div>
|
||||
{:else}
|
||||
<div class="min-w-0">
|
||||
<span class="font-medium text-text-subtle">pending_tool</span>
|
||||
<div class="truncate font-mono text-text">—</div>
|
||||
</div>
|
||||
<div class="min-w-0">
|
||||
<span class="font-medium text-text-subtle">pending_thread</span>
|
||||
<div class="truncate font-mono text-text">{model.pendingThreadId ? model.pendingThreadId.slice(0, 12) : "—"}</div>
|
||||
</div>
|
||||
<div class="min-w-0">
|
||||
<span class="font-medium text-text-subtle">cancelled</span>
|
||||
<div class="truncate font-mono text-text">{String(model._userCancelled)}</div>
|
||||
</div>
|
||||
{/if}
|
||||
<div class="min-w-0">
|
||||
<span class="font-medium text-text-subtle">error</span>
|
||||
<div class="truncate font-mono text-text" title={model.error || "none"}>{model.error || "none"}</div>
|
||||
<div class="truncate font-mono text-text" title={model.error || ""}>{model.error?.slice(0, 80) || "none"}</div>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
Reference in New Issue
Block a user