import type { PlanAnnotationAnchor } from "@/lib/plan-native-anchors"; export type PreferredEditor = | "vscode" | "cursor" | "finder" | "terminal" | "ghostty" | "xcode"; export const PREFERRED_EDITOR_STORAGE_KEY = "agent-native-plans.preferredEditor"; export const DESKTOP_PLAN_SYNC_AUTO_KEY_PREFIX = "agent-native-plans.desktopSync.auto."; export const PREFERRED_EDITOR_VALUES: PreferredEditor[] = [ "vscode", "cursor", "finder", "terminal", "ghostty", "xcode", ]; const EDITOR_OPTIONS: Array<{ value: PreferredEditor; label: string }> = [ { value: "vscode", label: "VS Code" }, // i18n-ignore stable app name { value: "cursor", label: "Cursor" }, // i18n-ignore stable app name { value: "finder", label: "Finder" }, // i18n-ignore stable app name { value: "terminal", label: "Terminal" }, // i18n-ignore stable app name { value: "ghostty", label: "Ghostty" }, // i18n-ignore stable app name { value: "xcode", label: "Xcode" }, // i18n-ignore stable app name ]; const EDITOR_ICON_HTML: Record = { vscode: ``, // i18n-ignore inline SVG icon markup cursor: ``, // i18n-ignore inline SVG icon markup finder: ``, // i18n-ignore inline SVG icon markup terminal: ``, // i18n-ignore inline SVG icon markup ghostty: ``, // i18n-ignore inline SVG icon markup xcode: ``, // i18n-ignore inline SVG icon markup }; export type RuntimeAnnotation = { id: string; index: number; message: string; kind: string; status: string; createdBy: string; parentCommentId?: string | null; authorEmail?: string | null; authorName?: string | null; authorAvatarUrl?: string | null; authorColor?: string | null; authorInitials?: string | null; sectionId?: string | null; createdAt?: string; anchor: PlanAnnotationAnchor; replies: RuntimeAnnotationComment[]; participants: RuntimeAnnotationParticipant[]; commentCount: number; }; export type RuntimeAnnotationComment = { id: string; message: string; status: string; createdBy: string; parentCommentId?: string | null; authorEmail?: string | null; authorName?: string | null; authorAvatarUrl?: string | null; authorColor?: string | null; authorInitials?: string | null; createdAt?: string; }; export type RuntimeAnnotationParticipant = { id: string; authorEmail?: string | null; authorName?: string | null; authorAvatarUrl?: string | null; authorColor?: string | null; authorInitials?: string | null; }; export function injectAnnotationRuntime(input: { html: string; annotations: RuntimeAnnotation[]; annotateMode: boolean; theme: "dark" | "light"; preferredEditor: PreferredEditor; labels: { closeCodePreview: string; }; }) { const { html, annotations, annotateMode, theme, preferredEditor, labels } = input; const payload = JSON.stringify({ annotateMode, annotations, theme, preferredEditor, }).replace(/[<>&\u2028\u2029]/g, (char) => { return ( { "<": "\\u003c", ">": "\\u003e", "&": "\\u0026", "\u2028": "\\u2028", "\u2029": "\\u2029", }[char] ?? char ); }); const editorOptionsPayload = JSON.stringify(EDITOR_OPTIONS).replace( /[<>&\u2028\u2029]/g, (char) => { return ( { "<": "\\u003c", ">": "\\u003e", "&": "\\u0026", "\u2028": "\\u2028", "\u2029": "\\u2029", }[char] ?? char ); }, ); const editorIconPayload = JSON.stringify(EDITOR_ICON_HTML).replace( /[<>&\u2028\u2029]/g, (char) => { return ( { "<": "\\u003c", ">": "\\u003e", "&": "\\u0026", "\u2028": "\\u2028", "\u2029": "\\u2029", }[char] ?? char ); }, ); const closeCodePreviewLabel = escapeRuntimeJsString(labels.closeCodePreview); const runtime = ``; if (html.includes("")) { return html.replace("", `${runtime}`); } return `${html}${runtime}`; } function escapeRuntimeJsString(value: string) { return value .replace(/\\/g, "\\\\") .replace(/'/g, "\\'") .replace(/&/g, "&") .replace(//g, "\\u003e") .replace(/"/g, """); }