group activity entries by plan step + remove inline renderers from chat
- Tool calls in Activity timeline are now tagged with current plan step - Indented entries show which step they belong to - Step tracking via update_plan_step(status=running) tool calls - Removed inline tool renderers from chat (health summary, fleet snapshot, etc.) — all tool output now visible only in sidebar Activity timeline
This commit is contained in:
@@ -59,7 +59,7 @@
|
||||
{/if}
|
||||
<button
|
||||
type="button"
|
||||
class="flex w-full items-start gap-2 px-3 py-1.5 text-left text-xs hover:bg-muted/30 {hasDetail ? 'cursor-pointer' : 'cursor-default'}"
|
||||
class="flex w-full items-start gap-2 {entry.indent ? 'pl-7' : 'px-3'} py-1.5 text-left text-xs hover:bg-muted/30 {hasDetail ? 'cursor-pointer' : 'cursor-default'}"
|
||||
onclick={() => hasDetail && toggle(entry.id)}
|
||||
>
|
||||
<!-- status icon -->
|
||||
|
||||
@@ -13,6 +13,8 @@ export interface ActivityEntry {
|
||||
detail?: string
|
||||
timestamp: number
|
||||
toolName?: string
|
||||
stepSeq?: number
|
||||
indent?: boolean
|
||||
status: 'running' | 'done' | 'failed'
|
||||
}
|
||||
|
||||
@@ -39,11 +41,23 @@ export const activityLog = derived([messages, planSteps, currentTask], ([$msgs,
|
||||
})
|
||||
}
|
||||
|
||||
// Tool calls (from messages)
|
||||
// Tool calls (from messages). Tag each tool with the plan step that's
|
||||
// currently running when it fires.
|
||||
let currentStepSeq = 0
|
||||
let entryIdx = 0
|
||||
for (let mi = 0; mi < $msgs.length; mi++) {
|
||||
for (const t of $msgs[mi].tools) {
|
||||
// Track current step from update_plan_step calls
|
||||
if (t.type === 'tool_use' && t.name === 'update_plan_step') {
|
||||
const s = (t.args as any)?.seq as number | undefined
|
||||
const status = (t.args as any)?.status as string | undefined
|
||||
if (s && status === 'running') currentStepSeq = s
|
||||
} else if (t.name === 'set_goal' || t.name === 'propose_plan' || t.name === 'complete_task') {
|
||||
currentStepSeq = 0
|
||||
}
|
||||
|
||||
const label = toolActivityLabel(t)
|
||||
const stepTag = currentStepSeq > 0 ? currentStepSeq : undefined
|
||||
if (t.type === 'tool_use') {
|
||||
entries.push({
|
||||
id: t.id ?? `tool_${mi}_${entryIdx++}`,
|
||||
@@ -51,10 +65,11 @@ export const activityLog = derived([messages, planSteps, currentTask], ([$msgs,
|
||||
description: label,
|
||||
timestamp: now - ($msgs.length - mi) * 1000,
|
||||
toolName: t.name,
|
||||
stepSeq: stepTag,
|
||||
indent: stepTag != null,
|
||||
status: 'running'
|
||||
})
|
||||
} else if (t.type === 'tool_result') {
|
||||
// Find and update matching tool_use entry
|
||||
const running = entries.find((e) =>
|
||||
e.type === 'tool_running' && e.id === t.id && e.status === 'running'
|
||||
)
|
||||
@@ -76,6 +91,8 @@ export const activityLog = derived([messages, planSteps, currentTask], ([$msgs,
|
||||
detail: !t.error ? (typeof t.result === 'string' ? t.result.slice(0, 200) : '') : undefined,
|
||||
timestamp: now - ($msgs.length - mi) * 1000,
|
||||
toolName: t.name,
|
||||
stepSeq: stepTag,
|
||||
indent: stepTag != null,
|
||||
status: t.error ? 'failed' : 'done'
|
||||
})
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
import TaskContextPanel from '$lib/components/TaskContextPanel.svelte'
|
||||
import InlineApproval from '$lib/components/InlineApproval.svelte'
|
||||
import AgentIndicator from '$lib/components/AgentIndicator.svelte'
|
||||
import { getToolRenderer } from '$lib/tool-renderers'
|
||||
import { Button } from '$lib/components/ui/button'
|
||||
import { Textarea } from '$lib/components/ui/textarea'
|
||||
import ArrowUpIcon from '@lucide/svelte/icons/arrow-up'
|
||||
@@ -45,14 +44,6 @@
|
||||
scrolledUp = false
|
||||
}
|
||||
|
||||
const MAX_INLINE_CARDS = 5
|
||||
|
||||
function getInlineTools(msg: { tools: any[] }): any[] {
|
||||
const matched = msg.tools.filter((t) => getToolRenderer(t))
|
||||
if (matched.length <= MAX_INLINE_CARDS) return matched
|
||||
return matched.slice(0, MAX_INLINE_CARDS)
|
||||
}
|
||||
|
||||
// Resizable right rail (session graph). Persisted so it survives reloads.
|
||||
const RAIL_MIN = 260
|
||||
const RAIL_MAX = 620
|
||||
@@ -147,12 +138,6 @@
|
||||
<div class="max-w-[85%] rounded-2xl rounded-br-sm bg-primary px-4 py-2.5 text-sm text-primary-foreground whitespace-pre-wrap">{msg.text}</div>
|
||||
{:else}
|
||||
<div class="flex w-full flex-col gap-2">
|
||||
{#each getInlineTools(msg) as tool (tool.id)}
|
||||
{@const renderer = getToolRenderer(tool)}
|
||||
{#if renderer}
|
||||
<renderer.component {tool} />
|
||||
{/if}
|
||||
{/each}
|
||||
{#if msg.text}
|
||||
<div class="prose-chat max-w-none text-sm leading-relaxed">
|
||||
<!-- eslint-disable-next-line svelte/no-at-html-tags — sanitized via DOMPurify -->
|
||||
|
||||
Reference in New Issue
Block a user