diff --git a/Dockerfile b/Dockerfile index e6daeb72..2140e707 100644 --- a/Dockerfile +++ b/Dockerfile @@ -17,8 +17,9 @@ RUN pnpm build FROM base AS installer +# git: required by the git-sync VaultGit (shells out to git) RUN apt-get update \ - && apt-get install -y --no-install-recommends curl bash \ + && apt-get install -y --no-install-recommends curl bash git \ && rm -rf /var/lib/apt/lists/* WORKDIR /app diff --git a/apps/client/public/locales/en-US/translation.json b/apps/client/public/locales/en-US/translation.json index 44aa952a..06761ddb 100644 --- a/apps/client/public/locales/en-US/translation.json +++ b/apps/client/public/locales/en-US/translation.json @@ -1217,6 +1217,8 @@ "Ran tool {{name}}": "Ran tool {{name}}", "AI-agent": "AI-agent", "Edited by AI agent on behalf of {{name}}": "Edited by AI agent on behalf of {{name}}", + "Git sync": "Git sync", + "Synced from Git on behalf of {{name}}": "Synced from Git on behalf of {{name}}", "Endpoints": "Endpoints", "where we fetch models": "where we fetch models", "All endpoints are OpenAI-compatible. Point the Base URL at OpenAI, OpenRouter, a local Ollama, or any self-hosted server.": "All endpoints are OpenAI-compatible. Point the Base URL at OpenAI, OpenRouter, a local Ollama, or any self-hosted server.", diff --git a/apps/client/src/components/ui/git-sync-badge.tsx b/apps/client/src/components/ui/git-sync-badge.tsx new file mode 100644 index 00000000..805d0d0e --- /dev/null +++ b/apps/client/src/components/ui/git-sync-badge.tsx @@ -0,0 +1,36 @@ +import { Badge, Tooltip } from "@mantine/core"; +import { IconGitMerge } from "@tabler/icons-react"; +import { useTranslation } from "react-i18next"; + +interface GitSyncBadgeProps { + authorName?: string; +} + +/** + * Badge marking a version written by the git-sync data plane — a VaultGit pull + * applied through the native datasource (provenance §8.1). Like {@link AiAgentBadge} + * it is ADDITIVE — shown next to the human author, never replacing them. A + * git-sync edit is NOT an agent edit and has no chat to deep-link into, so it is + * a small, neutral, non-clickable label. + */ +export function GitSyncBadge({ authorName }: GitSyncBadgeProps) { + const { t } = useTranslation(); + + const tooltip = t("Synced from Git on behalf of {{name}}", { + name: authorName ?? "", + }); + + return ( + + } + > + {t("Git sync")} + + + ); +} diff --git a/apps/client/src/features/page-history/components/history-item.tsx b/apps/client/src/features/page-history/components/history-item.tsx index ccb15c0a..9a6d25a5 100644 --- a/apps/client/src/features/page-history/components/history-item.tsx +++ b/apps/client/src/features/page-history/components/history-item.tsx @@ -1,6 +1,7 @@ import { Text, Group, UnstyledButton, Avatar, Tooltip } from "@mantine/core"; import { CustomAvatar } from "@/components/ui/custom-avatar.tsx"; import { AiAgentBadge } from "@/components/ui/ai-agent-badge.tsx"; +import { GitSyncBadge } from "@/components/ui/git-sync-badge.tsx"; import { formattedDate } from "@/lib/time"; import classes from "./css/history.module.css"; import clsx from "clsx"; @@ -41,6 +42,7 @@ const HistoryItem = memo(function HistoryItem({ const contributors = historyItem.contributors; const hasContributors = contributors && contributors.length > 0; const isAgentEdit = historyItem.lastUpdatedSource === "agent"; + const isGitSyncEdit = historyItem.lastUpdatedSource === "git-sync"; return ( setHistoryModalOpen(false)} /> )} + + {isGitSyncEdit && ( + + )} );