Submatter/apps/web/components/ai/agents-mode.tsx

103 lines
2.9 KiB
TypeScript

"use client";
import { useState } from "react";
import { AlertTriangle, Bot, Loader2 } from "lucide-react";
import { agentBuilderStub, type AgentBuilderAdapter } from "./agent-builder";
import { WorkspaceComposer } from "./workspace-composer";
export type AgentLibraryStatus =
| { status: "loading" }
| { status: "empty" }
| { status: "error"; message: string };
export function AgentLibraryState({ state }: { state: AgentLibraryStatus }) {
if (state.status === "loading") {
return (
<p role="status" className="flex items-center gap-2">
<Loader2 className="size-4 animate-spin" aria-hidden="true" />
Loading agents…
</p>
);
}
if (state.status === "error") {
return (
<p role="alert" className="flex items-center gap-2 text-destructive">
<AlertTriangle className="size-4" aria-hidden="true" />
{state.message}
</p>
);
}
return (
<div className="space-y-2 text-center">
<Bot className="mx-auto size-8 text-primary" aria-hidden="true" />
<h3 className="font-medium">No reusable agents yet</h3>
<p className="text-sm text-muted-foreground">
Agent creation and the workspace library are coming soon. You can draft
instructions below; nothing will be created or sent to Chat.
</p>
</div>
);
}
export function AgentsMode({
workspaceSlug,
active,
builder = agentBuilderStub,
libraryState = { status: "empty" },
}: {
workspaceSlug: string;
active: boolean;
builder?: AgentBuilderAdapter;
libraryState?: AgentLibraryStatus;
}) {
const [input, setInput] = useState("");
const [notice, setNotice] = useState<string | null>(null);
const [busy, setBusy] = useState(false);
async function submitBuilderRequest() {
setBusy(true);
try {
const result = await builder({ workspaceSlug, prompt: input.trim() });
setNotice(result.message);
} catch {
setNotice(
"Builder unavailable. Your draft has been kept; please try again later.",
);
} finally {
setBusy(false);
}
}
return (
<div className="flex h-full min-h-0 flex-col">
<div className="min-h-0 flex-1 overflow-y-auto">
<section
aria-label="Agent library"
className="mx-auto max-w-3xl space-y-6 px-4 py-6"
>
<h2 className="text-lg font-semibold">Agent library</h2>
<AgentLibraryState state={libraryState} />
{notice && (
<p
role="status"
className="rounded-lg border p-3 text-sm text-muted-foreground"
>
{notice}
</p>
)}
</section>
</div>
<WorkspaceComposer
mode="agents"
active={active}
input={input}
onInputChange={setInput}
busy={busy}
onSubmit={() => {
void submitBuilderRequest();
}}
/>
</div>
);
}