import { AuthOrchestrationOperateScope, OPEN_OWNED_WORK_STATUSES, OWNED_WORK_CLOSURE_UX, OwnedWorkItemId, ThreadId, type EnvironmentId, type OwnedWorkHistoryEntry, type OwnedWorkItem, } from "@t3tools/contracts"; import { type AtomCommandResult, isAtomCommandInterrupted, squashAtomCommandFailure, } from "@t3tools/client-runtime/state/runtime"; import { ClipboardListIcon, HistoryIcon } from "lucide-react"; import { useState } from "react"; import { cn, randomUUID } from "../../lib/utils"; import { readEnvironmentScope, useEnvironmentScope } from "../../state/session"; import { threadEnvironment } from "../../state/threads"; import { useQuietThreadProjection } from "~/state/entities"; import { useOrchestrationCommand } from "~/state/use-orchestration-command"; import { stackedThreadToast, toastManager } from "../ui/toast"; import { ThreadDetailsControl } from "./ThreadDetailsControl"; import { ThreadDetailsSection } from "./ThreadDetailsSection"; import { THREAD_DETAILS_PANEL_ICON_CLASS, THREAD_DETAILS_PANEL_LABEL_CLASS, THREAD_DETAILS_PANEL_ROW_CONTENT_CLASS, } from "./threadDetailsPanelStyles"; function statusLabel(status: OwnedWorkItem["status"]): string { switch (status) { case "assigned": return "Assigned"; case "claimed": return "Claimed"; case "in_progress": return "In progress"; case "on_hold": return "On hold"; case "needs_attention": return "Needs attention"; case "handed_off": return "Handed off"; case "completed": return "Completed"; case "cancelled": return "Cancelled"; } } function historyLine(entry: OwnedWorkHistoryEntry): string { const note = entry.note?.trim(); const reason = entry.closureReason ? ` (${entry.closureReason})` : ""; return note ? `${entry.kind}${reason}: ${note}` : `${entry.kind}${reason}`; } export function ThreadOwnedWorkPanel(props: { readonly environmentId: EnvironmentId; readonly threadId: ThreadId; readonly density: "full" | "compact" | "essential"; }) { const threadRef = { environmentId: props.environmentId, threadId: props.threadId }; const items = useQuietThreadProjection(threadRef)?.projection.thread.ownedWorkItems ?? []; const openItems = items.filter((item) => OPEN_OWNED_WORK_STATUSES.has(item.status)); const closedItems = items.filter((item) => !OPEN_OWNED_WORK_STATUSES.has(item.status)); const canOperate = useEnvironmentScope(props.environmentId, AuthOrchestrationOperateScope); const [title, setTitle] = useState(""); const [busyItemId, setBusyItemId] = useState(null); const [showHistory, setShowHistory] = useState(closedItems.length > 0 && openItems.length === 0); const [expandedHistoryId, setExpandedHistoryId] = useState(null); const assign = useOrchestrationCommand(threadEnvironment.assignOwnedWork, { label: "assign owned work", }); const claim = useOrchestrationCommand(threadEnvironment.claimOwnedWork, { label: "claim owned work", }); const handoff = useOrchestrationCommand(threadEnvironment.handoffOwnedWork, { label: "handoff owned work", }); const resume = useOrchestrationCommand(threadEnvironment.resumeOwnedWork, { label: "resume owned work", }); const complete = useOrchestrationCommand(threadEnvironment.completeOwnedWork, { label: "complete owned work", }); const cancel = useOrchestrationCommand(threadEnvironment.cancelOwnedWork, { label: "cancel owned work", }); if (items.length === 0 && props.density !== "full") return null; const reportFailure = (failureTitle: string, error: unknown) => { toastManager.add( stackedThreadToast({ type: "error", title: failureTitle, description: error instanceof Error ? error.message : String(error), }), ); }; const run = async ( itemId: string, action: () => Promise>, failureTitle: string, ) => { if ( busyItemId !== null || !readEnvironmentScope(props.environmentId, AuthOrchestrationOperateScope) ) return; setBusyItemId(itemId); const result = await action(); setBusyItemId(null); if (result._tag === "Failure" && !isAtomCommandInterrupted(result)) { reportFailure(failureTitle, squashAtomCommandFailure(result)); } }; const onAssign = async () => { const trimmed = title.trim(); if (trimmed === "" || busyItemId !== null) return; if (!readEnvironmentScope(props.environmentId, AuthOrchestrationOperateScope)) return; const itemId = OwnedWorkItemId.make(`owned-work:${randomUUID()}`); setBusyItemId(itemId); const result = await assign({ environmentId: props.environmentId, input: { threadId: props.threadId, itemId, title: trimmed, createdByThreadId: props.threadId, }, }); setBusyItemId(null); if (result._tag === "Failure" && !isAtomCommandInterrupted(result)) { reportFailure("Could not assign work", squashAtomCommandFailure(result)); return; } setTitle(""); }; const compactSummary = openItems.length === 0 ? closedItems.length === 0 ? null : `${closedItems.length} closed` : `${openItems.length} open`; if (props.density !== "full") { if (compactSummary === null) return null; return (
{compactSummary}
{openItems.slice(0, 3).map((item) => (
{item.title} {statusLabel(item.status)}
))}
); } return (
{canOperate ? (
{ event.preventDefault(); void onAssign(); }} > setTitle(event.target.value)} placeholder="Assign work…" className="border-border/60 bg-background h-7 min-w-0 flex-1 rounded-md border px-2 text-xs outline-none focus-visible:ring-1 focus-visible:ring-inset focus-visible:ring-ring" disabled={busyItemId !== null} /> Assign
) : null} {openItems.length === 0 && closedItems.length === 0 ? (

No owned work on this thread.

) : null}
    {openItems.map((item) => { const ownerThreadId = item.claimedByThreadId ?? item.assigneeThreadId; const waiting = item.status === "on_hold" || item.status === "needs_attention"; const reason = item.holdReason ?? item.attentionReason; return (
  • {item.title} {statusLabel(item.status)}
    {ownerThreadId ? (

    {ownerThreadId}

    ) : null} {reason ? (

    {reason}

    ) : null} {item.progress ? (

    {item.progress}

    ) : null} {canOperate ? (
    {item.status === "assigned" || item.status === "handed_off" ? ( void run( item.id, () => claim({ environmentId: props.environmentId, input: { threadId: props.threadId, itemId: item.id, claimedByThreadId: props.threadId, }, }), "Could not claim work", ) } > Claim ) : null} {waiting ? ( void run( item.id, () => resume({ environmentId: props.environmentId, input: { threadId: props.threadId, itemId: item.id, actorThreadId: props.threadId, }, }), "Could not resume work", ) } > Resume ) : null} {item.status !== "assigned" && item.status !== "handed_off" ? ( void run( item.id, () => complete({ environmentId: props.environmentId, input: { threadId: props.threadId, itemId: item.id, closureReason: OWNED_WORK_CLOSURE_UX.done.reason, actorThreadId: props.threadId, }, }), "Could not complete work", ) } > {OWNED_WORK_CLOSURE_UX.done.label} ) : null} void run( item.id, () => cancel({ environmentId: props.environmentId, input: { threadId: props.threadId, itemId: item.id, actorThreadId: props.threadId, }, }), "Could not cancel work", ) } > {OWNED_WORK_CLOSURE_UX.cancel.label} {item.status !== "assigned" ? ( { const toThreadId = window.prompt( "Handoff to thread id", item.assigneeThreadId ?? "", ); if (toThreadId === null || toThreadId.trim() === "") return; void run( item.id, () => handoff({ environmentId: props.environmentId, input: { threadId: props.threadId, itemId: item.id, toThreadId: ThreadId.make(toThreadId.trim()), actorThreadId: props.threadId, }, }), "Could not hand off work", ); }} > {OWNED_WORK_CLOSURE_UX.handoff.label} ) : null} setExpandedHistoryId((current) => (current === item.id ? null : item.id)) } > History
    ) : null} {expandedHistoryId === item.id ? (
      {(item.history ?? []).map((entry) => (
    1. {historyLine(entry)}
    2. ))}
    ) : null}
  • ); })}
{closedItems.length > 0 ? (
setShowHistory((value) => !value)} > {showHistory ? "Hide history" : `History (${closedItems.length})`} {showHistory ? (
    {closedItems.map((item) => (
  • {item.title} {statusLabel(item.status)} {item.closureReason ? ` · ${item.closureReason}` : ""}
      {(item.history ?? []).map((entry) => (
    1. {historyLine(entry)}
    2. ))}
  • ))}
) : null}
) : null}
); }