import { useMemo, useState } from "react";
import { useQuery } from "@tanstack/react-query";
import { AlertCircle, CheckCircle2, ClipboardCheck, Download, FlaskConical, GitPullRequest, Plus, Trash2, Copy, Upload, X } from "lucide-react";
import {
asWorkspaceApiError, exportWorkspace, getWorkspace, getWorkspaceRegistryStatus, importWorkspace,
listWorkspaces, pullWorkspaceRegistry, testWorkspace, validateWorkspace, type CanonicalWorkspace,
type PublishWorkspaceRequest, type WorkspaceRecord, type WorkspaceRevision,
} from "../api/workspaces";
import { workspaceDeletionDrafts, workspaceDrafts, type WorkspaceDeletionDraft, type WorkspaceDraft } from "../workspaces/drafts";
import { Button } from "../components/ui/button";
import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle } from "../components/ui/dialog";
import { WorkspaceEditor } from "./WorkspaceEditor";
import { WorkspacePublishDialog } from "./WorkspacePublishDialog";
const EMPTY_COMMIT = "0".repeat(40);
function newWorkspace(): CanonicalWorkspace {
return {
workspace: { schema_version: 2, id: "new-workspace", name: "New workspace", language: "en" },
dwh: { engine: "postgres", database: "database", schema: "public", supported_transports: ["postgres_direct"] },
semantic_index: {
vector_store: { engine: "pgvector", database: "vectors", schema: "public", collection: "documents", dimensions: 768, distance: "cosine", supported_transports: ["pgvector_direct"] },
embedding: { provider: "ollama_compatible", model: "nomic-embed-text", dimensions: 768 },
},
llm_policy: { allowed: ["zai/glm-5.2"] },
};
}
function draftFromRecord(record: WorkspaceRecord): WorkspaceDraft {
return {
workspaceId: record.workspace.workspace.id,
baseCommit: record.revision.commit,
baseBlob: record.revision.blob,
workspace: record.workspace,
updatedAt: new Date().toISOString(),
};
}
function proposedId(id: string): string {
const copy = `${id.slice(0, 58)}-copy`;
// A max-length source ending in "-copy" would otherwise reproduce itself.
return copy === id ? `${id.slice(0, 61)}-2` : copy;
}
function QueryError({ name, message, retryLabel, onRetry }: {
name: string;
message: string;
retryLabel: string;
onRetry: () => void;
}) {
return
;
}
export function WorkspaceManager({ open, onClose }: { open: boolean; onClose: () => void }) {
const [selectedId, setSelectedId] = useState();
const [localDraft, setLocalDraft] = useState();
const [notice, setNotice] = useState();
const [diagnostics, setDiagnostics] = useState([]);
const [deletionDraft, setDeletionDraft] = useState();
const [publishRequest, setPublishRequest] = useState();
const [transferring, setTransferring] = useState(false);
const statusQuery = useQuery({ queryKey: ["workspace-registry-status"], queryFn: getWorkspaceRegistryStatus, enabled: open });
const workspacesQuery = useQuery({ queryKey: ["workspaces"], queryFn: listWorkspaces, enabled: open });
const detailQuery = useQuery({
queryKey: ["workspace", selectedId],
queryFn: () => getWorkspace(selectedId!),
enabled: Boolean(open && selectedId && !localDraft),
});
const status = statusQuery.data;
const workspaces = workspacesQuery.data ?? [];
const record = detailQuery.data;
const savedDraft = selectedId && !localDraft ? workspaceDrafts.load(selectedId) : undefined;
const savedDeletionDraft = selectedId && !deletionDraft ? workspaceDeletionDrafts.load(selectedId) : undefined;
const currentDraft = localDraft ?? savedDraft ?? (record ? draftFromRecord(record) : undefined);
const activeDeletionDraft = deletionDraft ?? savedDeletionDraft;
const canTest = Boolean(record && currentDraft?.workspaceId === record.workspace.workspace.id);
const selectedSummary = useMemo(() => workspaces.find((workspace) => workspace.id === selectedId), [selectedId, workspaces]);
function selectWorkspace(id: string) {
setSelectedId(id);
setLocalDraft(undefined);
setDeletionDraft(undefined);
setNotice(undefined);
setDiagnostics([]);
setPublishRequest(undefined);
}
function createWorkspace() {
const draft: WorkspaceDraft = { workspaceId: "new-workspace", baseCommit: EMPTY_COMMIT, workspace: newWorkspace(), updatedAt: new Date().toISOString() };
setSelectedId(draft.workspaceId);
setLocalDraft(draft);
setDeletionDraft(undefined);
setNotice("New draft. Choose its immutable workspace ID before saving.");
setDiagnostics([]);
setPublishRequest(undefined);
}
function duplicateWorkspace() {
if (!currentDraft) return;
const id = proposedId(currentDraft.workspace.workspace.id);
const duplicate: WorkspaceDraft = {
...currentDraft,
workspaceId: id,
workspace: { ...currentDraft.workspace, workspace: { ...currentDraft.workspace.workspace, id, name: `${currentDraft.workspace.workspace.name} copy` } },
updatedAt: new Date().toISOString(),
};
setSelectedId(id);
setLocalDraft(duplicate);
setDeletionDraft(undefined);
setNotice("Duplicate draft. Give it a new immutable workspace ID before publishing.");
setPublishRequest(undefined);
}
function saveDraft(draft: WorkspaceDraft) {
workspaceDrafts.save(draft);
setSelectedId(draft.workspaceId);
setLocalDraft(draft);
setNotice("Draft saved in this browser.");
}
function requestPublish(request: PublishWorkspaceRequest) {
if (request.action !== "delete") {
const nextDraft: WorkspaceDraft = {
workspaceId: request.workspace.workspace.id,
baseCommit: request.baseCommit,
...(request.action === "update" ? { baseBlob: request.baseBlob } : {}),
workspace: request.workspace,
updatedAt: new Date().toISOString(),
};
workspaceDrafts.save(nextDraft);
setLocalDraft(nextDraft);
setSelectedId(nextDraft.workspaceId);
}
setNotice(undefined);
setDiagnostics([]);
setPublishRequest(request);
}
function requestDeletionPublish() {
if (!activeDeletionDraft) return;
requestPublish({ action: "delete", id: activeDeletionDraft.id, baseCommit: activeDeletionDraft.baseCommit, baseBlob: activeDeletionDraft.baseBlob });
}
async function pullLatest() {
setNotice(undefined);
setDiagnostics([]);
try {
await pullWorkspaceRegistry();
await Promise.all([statusQuery.refetch(), workspacesQuery.refetch()]);
setNotice("Registry updated. Reload a workspace to review its latest revision.");
} catch (error) {
const safe = asWorkspaceApiError(error);
setDiagnostics([safe ? `${safe.code}: ${safe.message}` : "git_unavailable: Registry pull could not be completed"]);
throw error;
}
}
function reloadWorkspace() {
if (selectedId) {
workspaceDrafts.discard(selectedId);
workspaceDeletionDrafts.discard(selectedId);
}
setLocalDraft(undefined);
setDeletionDraft(undefined);
setPublishRequest(undefined);
setNotice("Workspace reloaded from the registry. Your prior browser draft was discarded.");
setDiagnostics([]);
void detailQuery.refetch();
}
async function importBundle(file: File | undefined) {
if (!file) return;
setTransferring(true);
setNotice(undefined);
setDiagnostics([]);
try {
const result = await importWorkspace(file);
const imported: WorkspaceDraft = {
workspaceId: result.draft.workspace.workspace.id,
baseCommit: EMPTY_COMMIT,
workspace: result.draft.workspace,
updatedAt: new Date().toISOString(),
};
workspaceDrafts.save(imported);
setSelectedId(imported.workspaceId);
setLocalDraft(imported);
setDeletionDraft(undefined);
setPublishRequest(undefined);
setNotice("Imported draft saved in this browser. Validate it before publishing.");
} catch (error) {
const safe = asWorkspaceApiError(error);
setDiagnostics([safe ? `${safe.code}: ${safe.message}` : "workspace_invalid: Workspace bundle could not be imported"]);
} finally {
setTransferring(false);
}
}
async function downloadBundle() {
if (!record) return;
setTransferring(true);
setNotice(undefined);
setDiagnostics([]);
try {
const bundle = await exportWorkspace(record.workspace.workspace.id);
const url = URL.createObjectURL(bundle);
const link = document.createElement("a");
link.href = url;
link.download = `${record.workspace.workspace.id}.zip`;
link.click();
URL.revokeObjectURL(url);
setNotice("Workspace bundle downloaded.");
} catch (error) {
const safe = asWorkspaceApiError(error);
setDiagnostics([safe ? `${safe.code}: ${safe.message}` : "workspace_invalid: Workspace bundle could not be exported"]);
} finally {
setTransferring(false);
}
}
function published(revision: WorkspaceRevision | undefined) {
const publishedRequest = publishRequest;
if (publishedRequest?.action === "delete") {
workspaceDeletionDrafts.discard(publishedRequest.id);
setSelectedId(undefined);
} else if (publishedRequest) {
workspaceDrafts.discard(publishedRequest.workspace.workspace.id);
setSelectedId(publishedRequest.workspace.workspace.id);
}
setLocalDraft(undefined);
setDeletionDraft(undefined);
setPublishRequest(undefined);
setNotice(revision ? `Published revision ${revision.commit.slice(0, 12)}.` : "Workspace published.");
void Promise.all([statusQuery.refetch(), workspacesQuery.refetch(), detailQuery.refetch()]);
}
function saveResolvedDraft(draft: WorkspaceDraft) {
workspaceDrafts.save(draft);
setSelectedId(draft.workspaceId);
setLocalDraft(draft);
setDeletionDraft(undefined);
setPublishRequest(undefined);
setDiagnostics([]);
setNotice(`Revised draft saved with registry revision ${draft.baseCommit.slice(0, 12)}. Validate it before publishing.`);
}
async function validateCurrent() {
if (!currentDraft) return;
setNotice(undefined);
setDiagnostics([]);
try {
const result = await validateWorkspace(currentDraft.workspace);
setLocalDraft({ ...currentDraft, workspace: result.workspace, updatedAt: new Date().toISOString() });
setNotice("Workspace definition is valid.");
} catch (error) {
const safe = asWorkspaceApiError(error);
setDiagnostics([safe ? `${safe.code}: ${safe.message}` : "workspace_invalid: Validation could not be completed"]);
}
}
async function testCurrent() {
if (!record) return;
setNotice(undefined);
setDiagnostics([]);
try {
const result = await testWorkspace(record.workspace.workspace.id);
setDiagnostics(result.diagnostics.map((diagnostic) => `${diagnostic.code}: ${diagnostic.message}`));
if (result.diagnostics.length === 0) setNotice(result.activatable ? "Installation test passed." : "Installation test completed.");
} catch (error) {
const safe = asWorkspaceApiError(error);
setDiagnostics([safe ? `${safe.code}: ${safe.message}` : "connector_unavailable: Installation test could not be completed"]);
}
}
function stageDeletion() {
if (!currentDraft?.baseBlob || !record || currentDraft.workspaceId !== record.workspace.workspace.id) return;
const draft = { id: currentDraft.workspaceId, baseCommit: currentDraft.baseCommit, baseBlob: currentDraft.baseBlob, updatedAt: new Date().toISOString() };
workspaceDeletionDrafts.save(draft);
setDeletionDraft(draft);
setNotice("Deletion draft staged locally.");
setDiagnostics([]);
}
return (
);
}