Intelligence

Artifacts

Browse the repository, read documents, and manage the governance folders. Source, runtime, and infrastructure are read-only.

Repository
README.md
CONSTITUTION_COMPLIANCE_AUDIT_V1.mdREADME.md
repositories/aaf-holdings/hq01/app/artifacts/page.tsx
5.1 KB
import { FolderTree, FileWarning } from "lucide-react";
import { PageHeader } from "@/components/layout/page-header";
import { Markdown } from "@/components/shared/markdown";
import { FileTree } from "@/components/artifacts/file-tree";
import { FolderManager } from "@/components/files/folder-manager";
import { FileDeleteButton } from "@/components/files/file-delete-button";
import { Card } from "@/components/ui/card";
import { getArtifactTree, getArtifactFile } from "@/lib/content/artifacts";
import { CONTENT_ROOT } from "@/lib/content/config";
import { ALLOWED_EXTENSIONS } from "@/lib/uploads/config";
import { isManaged, listManagedDir, type ManagedDir } from "@/lib/files/manager";

export const dynamic = "force-dynamic";
export const metadata = { title: "Artifacts" };

function formatBytes(bytes: number): string {
  if (bytes < 1024) return `${bytes} B`;
  if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
  return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
}

export default function ArtifactsPage({
  searchParams,
}: {
  searchParams: { file?: string; dir?: string };
}) {
  const tree = getArtifactTree();
  const selectedPath = searchParams.file ?? null;
  const selectedDir = searchParams.dir ?? null;
  const file = selectedPath ? getArtifactFile(selectedPath) : null;
  const isMarkdown = file?.ext === ".md" || file?.ext === ".mdx";
  const fileManaged = selectedPath ? isManaged(selectedPath) : false;

  // When a managed folder is selected, load its contents for the file-manager.
  let folder: ManagedDir | null = null;
  if (!selectedPath && selectedDir && isManaged(selectedDir)) {
    try {
      folder = listManagedDir(selectedDir);
    } catch {
      folder = null;
    }
  }

  const accept = [...ALLOWED_EXTENSIONS].join(",");

  return (
    <div>
      <PageHeader
        eyebrow="Intelligence"
        title="Artifacts"
        description="Browse the repository, read documents, and manage the governance folders. Source, runtime, and infrastructure are read-only."
      />

      <div className="grid grid-cols-1 gap-6 lg:grid-cols-[300px_1fr]">
        <Card className="h-fit max-h-[72vh] overflow-y-auto p-2 lg:sticky lg:top-6">
          <div className="px-2 py-1.5 text-[11px] font-semibold uppercase tracking-[0.1em] text-muted-foreground">
            Repository
          </div>
          <FileTree tree={tree} selected={selectedPath} selectedDir={selectedDir} />
        </Card>

        <div className="min-w-0">
          {file ? (
            <Card className="overflow-hidden">
              <div className="flex items-center justify-between gap-3 border-b border-border bg-secondary/40 px-5 py-3">
                <span className="truncate font-mono text-[12px] font-medium text-foreground">
                  {file.path}
                </span>
                <div className="flex shrink-0 items-center gap-3">
                  <span className="text-[11px] tabular-nums text-muted-foreground">
                    {formatBytes(file.size)}
                  </span>
                  {fileManaged && <FileDeleteButton path={file.path} />}
                </div>
              </div>
              {file.content === null ? (
                <div className="px-5 py-16 text-center text-sm text-muted-foreground">
                  This file is binary or too large to preview.
                </div>
              ) : isMarkdown ? (
                <div className="p-8">
                  <Markdown>{file.content}</Markdown>
                </div>
              ) : (
                <pre className="overflow-x-auto bg-[hsl(220,18%,9%)] p-5 text-[12.5px] leading-relaxed text-[hsl(220,14%,92%)]">
                  <code className="font-mono">{file.content}</code>
                </pre>
              )}
            </Card>
          ) : selectedPath ? (
            <Card className="flex flex-col items-center justify-center px-6 py-24 text-center">
              <FileWarning className="mb-4 h-8 w-8 text-muted-foreground/50" />
              <h3 className="text-sm font-semibold">File not found</h3>
              <p className="mt-1 max-w-sm text-sm text-muted-foreground">
                <code className="font-mono text-xs">{selectedPath}</code> could
                not be read.
              </p>
            </Card>
          ) : folder ? (
            <FolderManager folder={folder} accept={accept} />
          ) : (
            <Card className="flex flex-col items-center justify-center px-6 py-24 text-center">
              <FolderTree className="mb-4 h-8 w-8 text-muted-foreground/50" />
              <h3 className="text-sm font-semibold">Select a file or folder</h3>
              <p className="mt-1 max-w-sm text-sm text-muted-foreground">
                Click a file to read it, or a folder to manage it. Folders under
                canonical, constitutions, doctrine, roadmaps, templates,
                artifacts, and uploads can be created, filled, and deleted.
              </p>
            </Card>
          )}
        </div>
      </div>

      <p className="mt-6 font-mono text-[11px] text-muted-foreground">
        root · {CONTENT_ROOT}
      </p>
    </div>
  );
}

root · /srv/aaf