"use client"; import Link from "next/link"; import { Suspense, useEffect, useMemo, useState } from "react"; import { useSearchParams } from "next/navigation"; import type { DaemonPairingSession } from "@multica/types"; import { Button } from "@/components/ui/button"; import { Label } from "@/components/ui/label"; import { Select, SelectTrigger, SelectContent, SelectItem, } from "@/components/ui/select"; import { api } from "@/shared/api"; import { useAuthStore } from "@/features/auth"; import { useWorkspaceStore } from "@/features/workspace"; function formatExpiresAt(value: string) { return new Date(value).toLocaleString("en-US", { month: "short", day: "numeric", hour: "numeric", minute: "2-digit", }); } function LocalDaemonPairPageContent() { const searchParams = useSearchParams(); const token = searchParams.get("token") ?? ""; const user = useAuthStore((s) => s.user); const isLoading = useAuthStore((s) => s.isLoading); const workspace = useWorkspaceStore((s) => s.workspace); const workspaces = useWorkspaceStore((s) => s.workspaces); const [session, setSession] = useState(null); const [selectedWorkspaceId, setSelectedWorkspaceId] = useState(""); const [loading, setLoading] = useState(true); const [submitting, setSubmitting] = useState(false); const [error, setError] = useState(""); const nextLoginURL = useMemo(() => { const next = `/pair/local?token=${encodeURIComponent(token)}`; return `/login?next=${encodeURIComponent(next)}`; }, [token]); const selectedWorkspace = useMemo( () => workspaces.find((item) => item.id === selectedWorkspaceId) ?? null, [selectedWorkspaceId, workspaces], ); useEffect(() => { if (!token) { setError("Missing pairing token."); setLoading(false); return; } setLoading(true); api.getDaemonPairingSession(token) .then((value) => { setSession(value); setSelectedWorkspaceId(value.workspace_id || workspace?.id || workspaces[0]?.id || ""); }) .catch((err) => setError(err instanceof Error ? err.message : "Failed to load pairing session.")) .finally(() => setLoading(false)); }, [token, workspace?.id, workspaces]); const approve = async () => { if (!token || !selectedWorkspaceId) return; setSubmitting(true); setError(""); try { const approved = await api.approveDaemonPairingSession(token, { workspace_id: selectedWorkspaceId, }); setSession(approved); } catch (err) { setError(err instanceof Error ? err.message : "Failed to approve pairing session."); } finally { setSubmitting(false); } }; return (

Connect Local Codex Runtime

Approve this pairing request to register your local Codex runtime with a workspace.

{loading || isLoading ? (
Loading pairing session...
) : error ? (
{error}
) : session ? ( <>
{session.runtime_name}
{session.device_name} {session.runtime_version ? ` ยท ${session.runtime_version}` : ""}
{session.runtime_type}
Expires {formatExpiresAt(session.expires_at)}
{!user ? (

Sign in first, then choose which workspace should own this local runtime.

Sign in to continue
) : session.status === "approved" || session.status === "claimed" ? (
This runtime is linked to a workspace. Return to the daemon window to finish setup.
) : session.status === "expired" ? (
This pairing link expired. Restart the daemon to generate a new link.
) : workspaces.length === 0 ? (
You do not have a workspace yet. Create one first, then reopen this pairing link.
) : (
)} ) : null}
); } export default function LocalDaemonPairPage() { return ( ); }