diff options
| author | Adam Malczewski <[email protected]> | 2026-05-22 04:09:00 +0900 |
|---|---|---|
| committer | Adam Malczewski <[email protected]> | 2026-05-22 04:09:00 +0900 |
| commit | 8f1dd855f0c4c877bff8d3a4ba193432b268b1c2 (patch) | |
| tree | 296a5641d8e84365875ecc0819282cfcf5502be0 /packages/frontend/src/lib/components/ToolCallDisplay.svelte | |
| parent | e43df9a50ed9ad25dc07a7d5ee90c66d14e8a16f (diff) | |
| download | dispatch-8f1dd855f0c4c877bff8d3a4ba193432b268b1c2.tar.gz dispatch-8f1dd855f0c4c877bff8d3a4ba193432b268b1c2.zip | |
feat: two-row tab bar with temp/persistent subagent tabs, tab persistence
- Split tab bar into user tabs (top) and subagent tabs (bottom row)
- Bottom row only visible when active user tab has child agents
- Parent user tab stays highlighted when viewing a subagent tab
- Temp tabs auto-disappear when agent completes, click to promote to persistent
- 'Open Tab' button on summon tool calls to view/reopen subagent history
- Reopening archived tabs fetches full chat history from backend
- Add parent_tab_id column to DB with safe ALTER TABLE migration
- Persist keyId, modelId, parentTabId on child tab creation
- Flush partial assistant messages on abort/error (finally block)
- Defensive JSON.parse in message restoration
- Allow all Vite hosts for local development
- Fix nested button in ToolCallDisplay (button inside button)
Diffstat (limited to 'packages/frontend/src/lib/components/ToolCallDisplay.svelte')
| -rw-r--r-- | packages/frontend/src/lib/components/ToolCallDisplay.svelte | 23 |
1 files changed, 20 insertions, 3 deletions
diff --git a/packages/frontend/src/lib/components/ToolCallDisplay.svelte b/packages/frontend/src/lib/components/ToolCallDisplay.svelte index 805de6d..213ba17 100644 --- a/packages/frontend/src/lib/components/ToolCallDisplay.svelte +++ b/packages/frontend/src/lib/components/ToolCallDisplay.svelte @@ -1,4 +1,5 @@ <script lang="ts"> +import { tabStore } from "../tabs.svelte.js"; import type { ToolCallDisplay } from "../types.js"; const { toolCall }: { toolCall: ToolCallDisplay } = $props(); @@ -41,17 +42,33 @@ const isShell = $derived(toolCall.name === "run_shell"); const shellResult = $derived( isShell && toolCall.result !== undefined ? parseShellResult(toolCall.result) : null, ); + +const summonAgentId = $derived.by(() => { + if (toolCall.name !== "summon" || !toolCall.result) return null; + const match = toolCall.result.match(/agent_id:\s*([a-f0-9-]+)/); + return match ? match[1] : null; +}); </script> <div class="collapse collapse-arrow mb-2 p-1 opacity-60 {isExpanded ? 'collapse-open' : ''}"> - <button - type="button" + <!-- svelte-ignore a11y_no_static_element_interactions --> + <div class="collapse-title flex items-center gap-2 text-sm italic cursor-pointer w-full text-left" onclick={toggle} + role="button" + tabindex="0" + onkeydown={(e) => { if (e.key === 'Enter' || e.key === ' ') toggle(); }} aria-expanded={isExpanded} > <span class="badge badge-neutral badge-sm">tool</span> <span class="font-mono">{toolCall.name}</span> + {#if summonAgentId !== null} + <button + type="button" + class="btn btn-xs btn-ghost" + onclick={(e) => { e.stopPropagation(); tabStore.openAgentTab(summonAgentId!); }} + >Open Tab</button> + {/if} {#if toolCall.result !== undefined} {#if isShell && shellResult !== null} <span class="badge badge-sm ml-auto {shellResult.exitCode === 0 ? 'badge-success' : 'badge-error'}"> @@ -65,7 +82,7 @@ const shellResult = $derived( {:else} <span class="badge badge-warning badge-sm ml-auto">pending</span> {/if} - </button> + </div> <div class="collapse-content text-xs"> <div class="mt-2"> |
