import { Link, createFileRoute } from "@tanstack/react-router"
import { useQuery } from "@tanstack/react-query"
import { useEffect, useState } from "react"
import { ArrowLeft } from "lucide-react"
import { PlanReview } from "@/components/agents/PlanReview"
import { Skeleton } from "@/components/ui/skeleton"
import { PlanApiError, getPlan } from "@/lib/plan"
export const Route = createFileRoute("/agents/$threadId_/plan")({
component: PlanPage,
})
function Centered({ children }: { children: React.ReactNode }) {
return (
{children}
)
}
function BackLink({ threadId }: { threadId: string }) {
return (
Back to conversation
)
}
function PlanPage() {
const { threadId } = Route.useParams()
// BlockNote + Yjs are browser-only; mount client-side before rendering.
const [mounted, setMounted] = useState(false)
useEffect(() => setMounted(true), [])
const query = useQuery({
queryKey: ["plan", threadId],
queryFn: () => getPlan(threadId),
// The agent shares the link as soon as it enters plan mode, before the plan
// is written — poll until the plan content is published.
refetchInterval: (q) => (q.state.data?.markdown ? false : 2000),
retry: (count, error) =>
!(
error instanceof PlanApiError &&
(error.status === 401 || error.status === 404)
) && count < 3,
})
if (!mounted || query.isLoading) {
return (
)
}
if (query.isError) {
const status = query.error instanceof PlanApiError ? query.error.status : 0
return (
{status === 401
? "Please sign in to view this plan."
: "This plan could not be found."}
)
}
const plan = query.data
if (!plan) {
return (
)
}
if (!plan.markdown.trim()) {
return (
The agent is still writing the plan. This page will update
automatically…
)
}
return (
)
}