gaaaaaaaaaaa's picture
Publish trajectory_rag
a414867 verified
Raw History Blame Contribute Delete
4.68 kB
"use client";
import {
CheckCircle2,
Circle,
Crosshair,
Download,
FileInput,
GitBranchPlus,
Radio,
Save,
Square,
Upload
} from "lucide-react";
import { Button } from "@/components/ui/Button";
import { PlaybackControls } from "@/components/tree-visualizer/PlaybackControls";
import type { TreeNodeViewMode } from "@/components/tree-visualizer/viewMode";
import { cn } from "@/lib/utils";
interface TreeCommandBarProps {
hasTree: boolean;
isDirty: boolean;
isPlaying: boolean;
isSaving: boolean;
isValidating: boolean;
nodeViewMode: TreeNodeViewMode;
onCreate: () => void;
onImport: () => void;
onModelStream: () => void;
onSave: () => void;
onExportRaw: () => void;
onValidate: () => void;
onReplay: () => void;
onPause: () => void;
onStep: () => void;
onFitView: () => void;
onNodeViewModeChange: (mode: TreeNodeViewMode) => void;
}
export function TreeCommandBar({
hasTree,
isDirty,
isPlaying,
isSaving,
isValidating,
nodeViewMode,
onCreate,
onImport,
onModelStream,
onSave,
onExportRaw,
onValidate,
onReplay,
onPause,
onStep,
onFitView,
onNodeViewModeChange
}: TreeCommandBarProps) {
const modeOptions = [
{ mode: "full" as const, label: "Full", icon: Square },
{ mode: "atom" as const, label: "Atom", icon: Circle }
];
return (
<header className="absolute left-4 right-4 top-4 z-20 flex min-h-14 items-center justify-between gap-3 rounded-xl border border-paper-300 bg-white/82 px-3 py-2 shadow-panel backdrop-blur-xl">
<div className="flex min-w-0 items-center gap-2 overflow-x-auto scrollbar-thin">
<Button variant="primary" onClick={onCreate} title="Create a new tree from pasted trajectory text">
<GitBranchPlus className="h-4 w-4" />
Create Tree
</Button>
<Button onClick={onImport} title="Import raw trajectory text">
<Upload className="h-4 w-4" />
Import
</Button>
<Button onClick={onModelStream} title="Create a new tree by streaming model trajectory nodes">
<Radio className="h-4 w-4" />
Create tree by model
</Button>
<Button onClick={onSave} disabled={!hasTree || isSaving || !isDirty} title="Save current tree edits">
<Save className="h-4 w-4" />
{isSaving ? "Saving" : "Save"}
</Button>
<Button
className="min-w-[138px]"
onClick={onExportRaw}
disabled={!hasTree}
title="Export the full original pasted trajectory message"
>
<Download className="h-4 w-4" />
Export Raw
</Button>
<Button onClick={onValidate} disabled={!hasTree || isValidating} title="Validate current tree">
<CheckCircle2 className="h-4 w-4" />
{isValidating ? "Validating" : "Validate"}
</Button>
</div>
<div className="flex shrink-0 items-center gap-2">
<div
role="radiogroup"
aria-label="Node view mode"
className="inline-flex h-9 items-center rounded-lg border border-paper-300 bg-paper-50 p-1 shadow-sm"
>
{modeOptions.map(({ mode, label, icon: Icon }) => {
const active = nodeViewMode === mode;
return (
<button
key={mode}
type="button"
role="radio"
aria-checked={active}
onClick={() => onNodeViewModeChange(mode)}
title={`${label} node view`}
className={cn(
"inline-flex h-7 min-w-8 items-center justify-center gap-1.5 rounded-md px-2 text-xs font-semibold transition md:min-w-[68px]",
active ? "bg-white text-claude-700 shadow-sm" : "text-ink-500 hover:text-ink-900"
)}
>
<Icon className="h-3.5 w-3.5 shrink-0" />
<span className="hidden md:inline">{label}</span>
</button>
);
})}
</div>
<PlaybackControls
isPlaying={isPlaying}
disabled={!hasTree}
onReplay={onReplay}
onPause={onPause}
onStep={onStep}
/>
<Button onClick={onFitView} disabled={!hasTree} title="Fit the tree into view">
<Crosshair className="h-4 w-4" />
Fit View
</Button>
<div className="hidden items-center gap-2 rounded-lg border border-paper-300 bg-paper-50 px-3 py-2 text-xs text-ink-500 lg:flex">
<FileInput className="h-4 w-4 text-claude-500" />
{isDirty ? "unsaved edits" : "workspace synced"}
</div>
</div>
</header>
);
}