summaryrefslogtreecommitdiffhomepage
path: root/packages/frontend/src/lib/components/ToolCallDisplay.svelte
diff options
context:
space:
mode:
authorAdam Malczewski <[email protected]>2026-05-22 04:09:00 +0900
committerAdam Malczewski <[email protected]>2026-05-22 04:09:00 +0900
commit8f1dd855f0c4c877bff8d3a4ba193432b268b1c2 (patch)
tree296a5641d8e84365875ecc0819282cfcf5502be0 /packages/frontend/src/lib/components/ToolCallDisplay.svelte
parente43df9a50ed9ad25dc07a7d5ee90c66d14e8a16f (diff)
downloaddispatch-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.svelte23
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">