{!comment.parentCommentId && canComment && (
diff --git a/apps/client/src/features/comment/types/comment.types.ts b/apps/client/src/features/comment/types/comment.types.ts
index 164e63dc..ddffcb91 100644
--- a/apps/client/src/features/comment/types/comment.types.ts
+++ b/apps/client/src/features/comment/types/comment.types.ts
@@ -17,6 +17,13 @@ export interface IComment {
deletedAt?: Date;
creator: IUser;
resolvedBy?: IUser;
+ // Agent-edit provenance (returned by the backend via selectAll('comments')).
+ // createdSource === "agent" marks a comment authored via an AI agent (MCP /
+ // internal AI chat); aiChatId deep-links to the internal chat when present
+ // (null for an external MCP agent); resolvedSource marks an AI-resolved thread.
+ createdSource?: string;
+ aiChatId?: string | null;
+ resolvedSource?: string | null;
yjsSelection?: {
anchor: any;
head: any;
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 c39430d1..83f6457e 100644
--- a/apps/client/src/features/page-history/components/history-item.tsx
+++ b/apps/client/src/features/page-history/components/history-item.tsx
@@ -1,19 +1,11 @@
-import { Text, Group, UnstyledButton, Avatar, Tooltip, Badge } from "@mantine/core";
-import { IconSparkles } from "@tabler/icons-react";
+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 { formattedDate } from "@/lib/time";
import classes from "./css/history.module.css";
import clsx from "clsx";
import { IPageHistory } from "@/features/page-history/types/page.types";
import { memo, useCallback } from "react";
-import { useTranslation } from "react-i18next";
-import { useSetAtom } from "jotai";
-import {
- activeAiChatIdAtom,
- aiChatWindowOpenAtom,
- aiChatDraftAtom,
-} from "@/features/ai-chat/atoms/ai-chat-atom.ts";
-import { historyAtoms } from "@/features/page-history/atoms/history-atoms.ts";
const MAX_VISIBLE_AVATARS = 5;
@@ -26,87 +18,6 @@ interface HistoryItemProps {
isActive: boolean;
}
-/**
- * Badge marking a version written by the AI agent (provenance C3 / §7.4). It is
- * ADDITIVE — shown next to the human author, never replacing them. When the
- * version carries an `aiChatId`, clicking the badge deep-links into that chat:
- * it sets the active-chat atom, opens the floating AI-chat window, and closes
- * the history modal. The click is contained (stopPropagation) so it does not
- * also trigger the row's version-select.
- */
-function AiAgentBadge({
- authorName,
- aiChatId,
-}: {
- authorName?: string;
- aiChatId?: string | null;
-}) {
- const { t } = useTranslation();
- const setAiChatWindowOpen = useSetAtom(aiChatWindowOpenAtom);
- const setActiveChatId = useSetAtom(activeAiChatIdAtom);
- const setDraft = useSetAtom(aiChatDraftAtom);
- const setHistoryModalOpen = useSetAtom(historyAtoms);
-
- const tooltip = t("Edited by AI agent on behalf of {{name}}", {
- name: authorName ?? "",
- });
-
- const openChat = useCallback(
- (event: React.SyntheticEvent) => {
- event.stopPropagation();
- if (!aiChatId) return;
- setActiveChatId(aiChatId);
- // Switching to another chat must start with a clean composer — clear any
- // unsent draft so it does not leak from the previously open chat.
- setDraft("");
- setAiChatWindowOpen(true);
- setHistoryModalOpen(false);
- },
- [
- aiChatId,
- setActiveChatId,
- setDraft,
- setAiChatWindowOpen,
- setHistoryModalOpen,
- ],
- );
-
- const badge = (
-
}
- style={aiChatId ? { cursor: "pointer" } : undefined}
- {...(aiChatId
- ? {
- // Keep the default Badge root element (not a