loops wizard: extract AutoProvisionCard to stay under 1250 lines
Co-Authored-By: Claude Opus 4.7 <[email protected]>
This commit is contained in:
co-authored by
Claude Opus 4.7
parent
65b19b0fc5
commit
279d785f5b
@@ -0,0 +1,93 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import type { CSSProperties } from "react";
|
||||||
|
import type { AutoProvisionResponse } from "@/lib/api/research";
|
||||||
|
|
||||||
|
const mono =
|
||||||
|
"ui-monospace, SFMono-Regular, SF Mono, Menlo, Monaco, Consolas, monospace";
|
||||||
|
|
||||||
|
export function AutoProvisionCard({
|
||||||
|
autoTeam,
|
||||||
|
autoProvisioning,
|
||||||
|
autoProvisionError,
|
||||||
|
disabled,
|
||||||
|
onProvision,
|
||||||
|
hintStyle,
|
||||||
|
primaryBtn,
|
||||||
|
description,
|
||||||
|
}: {
|
||||||
|
autoTeam: AutoProvisionResponse | null;
|
||||||
|
autoProvisioning: boolean;
|
||||||
|
autoProvisionError: string | null;
|
||||||
|
disabled: boolean;
|
||||||
|
onProvision: () => void;
|
||||||
|
hintStyle: CSSProperties;
|
||||||
|
primaryBtn: CSSProperties;
|
||||||
|
description?: string;
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
padding: 12,
|
||||||
|
borderRadius: 8,
|
||||||
|
border: `1px solid ${autoTeam ? "rgba(95,208,138,.35)" : "rgba(94,200,216,.35)"}`,
|
||||||
|
background: autoTeam
|
||||||
|
? "rgba(95,208,138,.06)"
|
||||||
|
: "rgba(94,200,216,.06)",
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "column",
|
||||||
|
gap: 10,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
style={{
|
||||||
|
fontFamily: mono,
|
||||||
|
fontSize: 12,
|
||||||
|
color: autoTeam ? "#83e6a5" : "#7cd6e0",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{autoTeam
|
||||||
|
? `Team ready · ${autoTeam.agents.length} agents · ${autoTeam.topology_kind}`
|
||||||
|
: "No team yet? Auto-provision one from the task."}
|
||||||
|
</span>
|
||||||
|
{!autoTeam && (
|
||||||
|
<p style={hintStyle}>
|
||||||
|
{description ??
|
||||||
|
"We ask Claude Sonnet 5 to derive 3–5 roles from the task above, then create each agent + wire them in."}
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
{autoTeam ? (
|
||||||
|
<div style={{ display: "flex", flexWrap: "wrap", gap: 6 }}>
|
||||||
|
{autoTeam.agents.map((a) => (
|
||||||
|
<span
|
||||||
|
key={a.agent_id}
|
||||||
|
style={{
|
||||||
|
fontFamily: mono,
|
||||||
|
fontSize: 11,
|
||||||
|
padding: "3px 8px",
|
||||||
|
borderRadius: 999,
|
||||||
|
border: "1px solid rgba(255,255,255,.14)",
|
||||||
|
background: "rgba(255,255,255,.04)",
|
||||||
|
color: "#d7d7db",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{a.role_slot} · {a.display_name}
|
||||||
|
</span>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={onProvision}
|
||||||
|
disabled={disabled}
|
||||||
|
style={{ ...primaryBtn, opacity: disabled ? 0.5 : 1 }}
|
||||||
|
>
|
||||||
|
{autoProvisioning ? "Provisioning…" : "Auto-provision team"}
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
{autoProvisionError && (
|
||||||
|
<p style={{ ...hintStyle, color: "#ff8a7a" }}>{autoProvisionError}</p>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -27,6 +27,7 @@ import {
|
|||||||
autoProvisionTeam,
|
autoProvisionTeam,
|
||||||
type AutoProvisionResponse,
|
type AutoProvisionResponse,
|
||||||
} from "@/lib/api/research";
|
} from "@/lib/api/research";
|
||||||
|
import { AutoProvisionCard } from "./AutoProvisionCard";
|
||||||
// Do NOT import @/lib/api/team here — it transitively pulls bearer.ts
|
// Do NOT import @/lib/api/team here — it transitively pulls bearer.ts
|
||||||
// (next/headers, server-only) into the client bundle and breaks the
|
// (next/headers, server-only) into the client bundle and breaks the
|
||||||
// production build. Call /api/team/claws with plain fetch instead.
|
// production build. Call /api/team/claws with plain fetch instead.
|
||||||
@@ -706,77 +707,16 @@ export function LoopsWizard({
|
|||||||
|
|
||||||
{step === 6 && (
|
{step === 6 && (
|
||||||
<div style={{ display: "flex", flexDirection: "column", gap: 14 }}>
|
<div style={{ display: "flex", flexDirection: "column", gap: 14 }}>
|
||||||
<div
|
<AutoProvisionCard
|
||||||
style={{
|
autoTeam={autoTeam}
|
||||||
padding: 12,
|
autoProvisioning={autoProvisioning}
|
||||||
borderRadius: 8,
|
autoProvisionError={autoProvisionError}
|
||||||
border: `1px solid ${autoTeam ? "rgba(95,208,138,.35)" : "rgba(94,200,216,.35)"}`,
|
|
||||||
background: autoTeam
|
|
||||||
? "rgba(95,208,138,.06)"
|
|
||||||
: "rgba(94,200,216,.06)",
|
|
||||||
display: "flex",
|
|
||||||
flexDirection: "column",
|
|
||||||
gap: 10,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
style={{
|
|
||||||
fontFamily: mono,
|
|
||||||
fontSize: 12,
|
|
||||||
color: autoTeam ? "#83e6a5" : "#7cd6e0",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{autoTeam
|
|
||||||
? `Team ready · ${autoTeam.agents.length} agents · ${autoTeam.topology_kind}`
|
|
||||||
: "No team yet? Auto-provision one from the loop's task."}
|
|
||||||
</span>
|
|
||||||
{!autoTeam && (
|
|
||||||
<p style={hintStyle}>
|
|
||||||
We ask Claude Sonnet 5 to derive 3–5 roles from the task
|
|
||||||
above, then create each agent + wire them into this loop.
|
|
||||||
</p>
|
|
||||||
)}
|
|
||||||
{autoTeam ? (
|
|
||||||
<div style={{ display: "flex", flexWrap: "wrap", gap: 6 }}>
|
|
||||||
{autoTeam.agents.map((a) => (
|
|
||||||
<span
|
|
||||||
key={a.agent_id}
|
|
||||||
style={{
|
|
||||||
fontFamily: mono,
|
|
||||||
fontSize: 11,
|
|
||||||
padding: "3px 8px",
|
|
||||||
borderRadius: 999,
|
|
||||||
border: "1px solid rgba(255,255,255,.14)",
|
|
||||||
background: "rgba(255,255,255,.04)",
|
|
||||||
color: "#d7d7db",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{a.role_slot} · {a.display_name}
|
|
||||||
</span>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
) : (
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
onClick={runAutoProvision}
|
|
||||||
disabled={autoProvisioning || task.trim().length === 0}
|
disabled={autoProvisioning || task.trim().length === 0}
|
||||||
style={{
|
onProvision={runAutoProvision}
|
||||||
...primaryBtn,
|
hintStyle={hintStyle}
|
||||||
opacity:
|
primaryBtn={primaryBtn}
|
||||||
autoProvisioning || task.trim().length === 0 ? 0.5 : 1,
|
description="We ask Claude Sonnet 5 to derive 3–5 roles from the task above, then create each agent + wire them into this loop."
|
||||||
}}
|
/>
|
||||||
>
|
|
||||||
{autoProvisioning
|
|
||||||
? "Provisioning…"
|
|
||||||
: "Auto-provision team"}
|
|
||||||
</button>
|
|
||||||
)}
|
|
||||||
{autoProvisionError && (
|
|
||||||
<p style={{ ...hintStyle, color: "#ff8a7a" }}>
|
|
||||||
{autoProvisionError}
|
|
||||||
</p>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{rosterAgents.length > 0 && !autoTeam ? (
|
{rosterAgents.length > 0 && !autoTeam ? (
|
||||||
<>
|
<>
|
||||||
|
|||||||
Reference in New Issue
Block a user