@zzusp/ccsm 1.0.1 → 1.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -21
- package/README.md +236 -236
- package/bin/cli.mjs +52 -52
- package/dist/assets/{DiskUsage-CKhggLs5.js → DiskUsage-BY6XwffG.js} +2 -2
- package/dist/assets/DiskUsage-BY6XwffG.js.map +1 -0
- package/dist/assets/{ImportPage-wge4VhZ-.js → ImportPage-Cwq5bx7G.js} +2 -2
- package/dist/assets/ImportPage-Cwq5bx7G.js.map +1 -0
- package/dist/assets/MarkdownContent-BFu7Nkk_.js +2 -0
- package/dist/assets/MarkdownContent-BFu7Nkk_.js.map +1 -0
- package/dist/assets/{ProjectMemory-Q4XX40j_.js → ProjectMemory-CcE3KbUK.js} +2 -2
- package/dist/assets/ProjectMemory-CcE3KbUK.js.map +1 -0
- package/dist/assets/index-CrWxV6sb.css +1 -0
- package/dist/assets/index-DTbWl1jb.js +11 -0
- package/dist/assets/index-DTbWl1jb.js.map +1 -0
- package/dist/assets/markdown-Bag5rX3T.js +30 -0
- package/dist/assets/markdown-Bag5rX3T.js.map +1 -0
- package/dist/index.html +26 -26
- package/package.json +81 -83
- package/server/index.ts +130 -130
- package/server/lib/active-sessions.test.ts +119 -119
- package/server/lib/active-sessions.ts +95 -95
- package/server/lib/bundle.test.ts +182 -182
- package/server/lib/bundle.ts +86 -86
- package/server/lib/claude-paths.test.ts +126 -126
- package/server/lib/claude-paths.ts +43 -43
- package/server/lib/cleanup-suggestions.ts +131 -131
- package/server/lib/constants.ts +8 -8
- package/server/lib/delete-project.ts +100 -100
- package/server/lib/delete.test.ts +244 -244
- package/server/lib/delete.ts +192 -192
- package/server/lib/disk-usage.ts +81 -81
- package/server/lib/encode-cwd.ts +24 -24
- package/server/lib/export-bundle.ts +236 -236
- package/server/lib/export-import-bundle.test.ts +337 -337
- package/server/lib/fs-size.ts +38 -38
- package/server/lib/import-bundle.ts +488 -488
- package/server/lib/load-memory.ts +120 -120
- package/server/lib/load-session.ts +209 -209
- package/server/lib/modified-files.test.ts +280 -280
- package/server/lib/modified-files.ts +228 -228
- package/server/lib/open-folder.ts +47 -47
- package/server/lib/parse-jsonl.ts +160 -139
- package/server/lib/port.ts +23 -23
- package/server/lib/safe-id.test.ts +41 -41
- package/server/lib/safe-id.ts +6 -6
- package/server/lib/safe-remove.test.ts +73 -73
- package/server/lib/safe-remove.ts +25 -25
- package/server/lib/scan.ts +289 -286
- package/server/lib/search-all.ts +130 -130
- package/server/lib/search-session.ts +203 -203
- package/server/lib/system-tags.ts +20 -20
- package/server/lib/update.ts +67 -67
- package/server/lib/version.test.ts +39 -39
- package/server/lib/version.ts +117 -117
- package/server/routes/disk-cleanup.ts +54 -54
- package/server/routes/disk.ts +9 -9
- package/server/routes/import.ts +87 -87
- package/server/routes/projects.ts +104 -104
- package/server/routes/search.ts +79 -79
- package/server/routes/sessions.ts +130 -130
- package/server/routes/version.ts +34 -34
- package/server/types.ts +1 -1
- package/shared/constants.ts +7 -7
- package/shared/types.ts +513 -511
- package/dist/assets/DiskUsage-CKhggLs5.js.map +0 -1
- package/dist/assets/ImportPage-wge4VhZ-.js.map +0 -1
- package/dist/assets/ProjectMemory-Q4XX40j_.js.map +0 -1
- package/dist/assets/index-7aMrnHJG.js +0 -7
- package/dist/assets/index-7aMrnHJG.js.map +0 -1
- package/dist/assets/index-BOeI_J4B.css +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"DiskUsage-CKhggLs5.js","sources":["../../web/src/components/CleanupSuggestions.tsx","../../web/src/components/StatCard.tsx","../../web/src/routes/DiskUsage.tsx"],"sourcesContent":["import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';\r\nimport { motion } from 'motion/react';\r\nimport { useEffect, useRef, useState } from 'react';\r\nimport { Link } from 'react-router-dom';\r\nimport {\r\n api,\r\n type DiskCleanupOrphan,\r\n type DiskCleanupSuggestions,\r\n type DiskOrphanDeleteResult,\r\n type DiskOrphanKind,\r\n} from '../lib/api.ts';\r\nimport { formatBytes, formatRelativeTime } from '../lib/format.ts';\r\nimport { useT } from '../lib/i18n.ts';\r\nimport { queryKeys } from '../lib/query-keys.ts';\r\nimport { Loading } from './Loading.tsx';\r\n\r\n/**\r\n * \"清理建议\" 区块:从 /api/disk-cleanup/suggestions 拉取最大的会话 + 两类孤儿目录,\r\n * 用户逐条确认后通过 DELETE /api/disk-cleanup/orphan/:kind/:sid 单条清理。\r\n * 不做批量、不做自动清理。\r\n */\r\nexport default function CleanupSuggestions() {\r\n const t = useT();\r\n const { data, isLoading, error } = useQuery({\r\n queryKey: queryKeys.diskCleanupSuggestions(),\r\n queryFn: () => api<DiskCleanupSuggestions>('/api/disk-cleanup/suggestions'),\r\n });\r\n\r\n return (\r\n <section className=\"surface-card mt-12 p-6\">\r\n <header className=\"flex flex-wrap items-baseline justify-between gap-x-4 gap-y-1\">\r\n <h2 className=\"font-display text-xl font-light tracking-tight text-[var(--color-fg-primary)]\">\r\n {t('cleanup.title')}\r\n </h2>\r\n <p className=\"min-w-0 flex-1 font-display text-[13px] italic leading-snug text-[var(--color-fg-muted)]\">\r\n {t('cleanup.tagline')}\r\n </p>\r\n </header>\r\n <div className=\"rule-dotted mt-3\" aria-hidden />\r\n\r\n {isLoading && <Loading label={t('common.computing')} className=\"mt-6\" />}\r\n {error && (\r\n <p className=\"mt-6 rounded-md border border-[var(--color-danger)]/40 bg-[var(--color-danger-soft)] px-4 py-3 text-sm text-[var(--color-danger)]\">\r\n {t('cleanup.failed', { msg: (error as Error).message })}\r\n </p>\r\n )}\r\n\r\n {data && (\r\n <div className=\"mt-6 space-y-8\">\r\n <LargeSessionsTable data={data.largeSessions} />\r\n <OrphanTable\r\n kind=\"file-history\"\r\n title={t('cleanup.section.orphanFileHistory')}\r\n hint={t('cleanup.section.orphanFileHistory.hint')}\r\n rows={data.orphanFileHistory}\r\n />\r\n <OrphanTable\r\n kind=\"session-env\"\r\n title={t('cleanup.section.orphanSessionEnv')}\r\n hint={t('cleanup.section.orphanSessionEnv.hint')}\r\n rows={data.orphanSessionEnv}\r\n />\r\n </div>\r\n )}\r\n </section>\r\n );\r\n}\r\n\r\nfunction SectionHeader({ title, hint }: { title: string; hint: string }) {\r\n return (\r\n <div\r\n className=\"flex flex-wrap items-baseline justify-between gap-x-3 gap-y-1 rounded-[var(--radius-input)] bg-[var(--color-sunken)] px-3 py-2\"\r\n >\r\n <h3 className=\"font-display text-[15px] font-light tracking-tight text-[var(--color-fg-primary)]\">\r\n {title}\r\n </h3>\r\n <span className=\"font-mono text-[10.5px] uppercase tracking-[0.16em] text-[var(--color-fg-muted)]\">\r\n {hint}\r\n </span>\r\n </div>\r\n );\r\n}\r\n\r\nfunction LargeSessionsTable({\r\n data,\r\n}: {\r\n data: DiskCleanupSuggestions['largeSessions'];\r\n}) {\r\n const t = useT();\r\n return (\r\n <div>\r\n <SectionHeader\r\n title={t('cleanup.section.largeSessions')}\r\n hint={t('cleanup.section.largeSessions.hint', { n: data.length || 10 })}\r\n />\r\n {data.length === 0 ? (\r\n <p className=\"mt-3 font-mono text-xs uppercase tracking-[0.18em] text-[var(--color-fg-muted)]\">\r\n {t('cleanup.empty.largeSessions')}\r\n </p>\r\n ) : (\r\n <div className=\"mt-3 -mx-6 overflow-x-auto px-6\">\r\n <table className=\"w-full table-fixed text-sm\">\r\n <colgroup>\r\n <col />\r\n <col className=\"w-[20rem]\" />\r\n <col className=\"w-24\" />\r\n <col className=\"w-24\" />\r\n <col className=\"w-20\" />\r\n </colgroup>\r\n <thead>\r\n <tr className=\"text-left\">\r\n <th className=\"px-2 py-2 eyebrow\">{t('cleanup.col.session')}</th>\r\n <th className=\"px-2 py-2 eyebrow\">{t('cleanup.col.project')}</th>\r\n <th className=\"px-2 py-2 eyebrow text-right\">{t('cleanup.col.last')}</th>\r\n <th className=\"px-2 py-2 eyebrow text-right\">{t('cleanup.col.size')}</th>\r\n <th className=\"px-2 py-2 eyebrow text-right\">{t('cleanup.col.actions')}</th>\r\n </tr>\r\n </thead>\r\n <tbody className=\"border-t border-[var(--color-hairline)]\">\r\n {data.map((row) => {\r\n const display = row.customTitle ?? row.title;\r\n return (\r\n <tr\r\n key={`${row.projectId}/${row.sessionId}`}\r\n className=\"ribbon-row border-b border-[var(--color-hairline)] hover:bg-[var(--color-sunken)]\"\r\n >\r\n <td className=\"px-2 py-2.5 align-top\">\r\n <div\r\n className=\"truncate font-medium text-[var(--color-fg-primary)]\"\r\n title={display}\r\n >\r\n {display}\r\n </div>\r\n <div\r\n className=\"mt-0.5 truncate font-mono text-[10.5px] text-[var(--color-fg-faint)]\"\r\n title={row.sessionId}\r\n >\r\n {row.sessionId}\r\n </div>\r\n </td>\r\n <td\r\n className=\"px-2 py-2.5 align-top font-mono text-[12px] text-[var(--color-fg-muted)]\"\r\n >\r\n <Link\r\n to={`/projects/${encodeURIComponent(row.projectId)}`}\r\n className=\"block truncate hover:text-[var(--color-fg-primary)]\"\r\n title={row.projectPath}\r\n >\r\n {shortCwd(row.projectPath)}\r\n </Link>\r\n </td>\r\n <td className=\"px-2 py-2.5 text-right align-top font-mono text-[12px] text-[var(--color-fg-secondary)]\">\r\n {formatRelativeTime(row.lastActivity)}\r\n </td>\r\n <td className=\"px-2 py-2.5 text-right align-top font-mono tabular-nums text-[var(--color-fg-primary)]\">\r\n {formatBytes(row.sizeBytes)}\r\n </td>\r\n <td className=\"px-2 py-2.5 text-right align-top\">\r\n <Link\r\n to={`/projects/${encodeURIComponent(row.projectId)}/sessions/${row.sessionId}`}\r\n className=\"inline-block rounded-[var(--radius-control)] border border-[var(--color-hairline-strong)] px-2.5 py-1 text-[11.5px] font-medium text-[var(--color-fg-secondary)] hover:bg-[var(--color-sunken)] hover:text-[var(--color-fg-primary)]\"\r\n >\r\n {t('cleanup.action.view')}\r\n </Link>\r\n </td>\r\n </tr>\r\n );\r\n })}\r\n </tbody>\r\n </table>\r\n </div>\r\n )}\r\n </div>\r\n );\r\n}\r\n\r\nfunction OrphanTable({\r\n kind,\r\n title,\r\n hint,\r\n rows,\r\n}: {\r\n kind: DiskOrphanKind;\r\n title: string;\r\n hint: string;\r\n rows: DiskCleanupOrphan[];\r\n}) {\r\n const t = useT();\r\n const [confirming, setConfirming] = useState<DiskCleanupOrphan | null>(null);\r\n return (\r\n <div>\r\n <SectionHeader title={title} hint={hint} />\r\n {rows.length === 0 ? (\r\n <p className=\"mt-3 font-mono text-xs uppercase tracking-[0.18em] text-[var(--color-fg-muted)]\">\r\n {t('cleanup.empty.orphan')}\r\n </p>\r\n ) : (\r\n <div className=\"mt-3 -mx-6 overflow-x-auto px-6\">\r\n <table className=\"w-full table-fixed text-sm\">\r\n <colgroup>\r\n <col />\r\n <col className=\"w-24\" />\r\n <col className=\"w-24\" />\r\n </colgroup>\r\n <thead>\r\n <tr className=\"text-left\">\r\n <th className=\"px-2 py-2 eyebrow\">{t('cleanup.col.sid')}</th>\r\n <th className=\"px-2 py-2 eyebrow text-right\">{t('cleanup.col.size')}</th>\r\n <th className=\"px-2 py-2 eyebrow text-right\">{t('cleanup.col.actions')}</th>\r\n </tr>\r\n </thead>\r\n <tbody className=\"border-t border-[var(--color-hairline)]\">\r\n {rows.map((row) => (\r\n <tr\r\n key={row.sessionId}\r\n className=\"ribbon-row border-b border-[var(--color-hairline)] hover:bg-[var(--color-sunken)]\"\r\n >\r\n <td\r\n className=\"px-2 py-2.5 align-top font-mono text-[12px] text-[var(--color-fg-secondary)]\"\r\n title={row.sessionId}\r\n >\r\n <span className=\"block truncate\">{row.sessionId}</span>\r\n </td>\r\n <td className=\"px-2 py-2.5 text-right align-top font-mono tabular-nums text-[var(--color-fg-primary)]\">\r\n {formatBytes(row.sizeBytes)}\r\n </td>\r\n <td className=\"px-2 py-2.5 text-right align-top\">\r\n <button\r\n type=\"button\"\r\n onClick={() => setConfirming(row)}\r\n className=\"inline-block rounded-[var(--radius-control)] border border-[var(--color-danger)]/40 px-2.5 py-1 text-[11.5px] font-medium text-[var(--color-danger)] hover:bg-[var(--color-danger-soft)]\"\r\n >\r\n {t('cleanup.action.delete')}\r\n </button>\r\n </td>\r\n </tr>\r\n ))}\r\n </tbody>\r\n </table>\r\n </div>\r\n )}\r\n {confirming && (\r\n <OrphanConfirmDialog\r\n kind={kind}\r\n orphan={confirming}\r\n onClose={() => setConfirming(null)}\r\n />\r\n )}\r\n </div>\r\n );\r\n}\r\n\r\nfunction OrphanConfirmDialog({\r\n kind,\r\n orphan,\r\n onClose,\r\n}: {\r\n kind: DiskOrphanKind;\r\n orphan: DiskCleanupOrphan;\r\n onClose: () => void;\r\n}) {\r\n const t = useT();\r\n const queryClient = useQueryClient();\r\n const mutation = useMutation({\r\n mutationFn: () =>\r\n api<DiskOrphanDeleteResult>(\r\n `/api/disk-cleanup/orphan/${kind}/${encodeURIComponent(orphan.sessionId)}`,\r\n { method: 'DELETE' },\r\n ),\r\n onSuccess: () => {\r\n queryClient.invalidateQueries({ queryKey: queryKeys.diskCleanupSuggestions() });\r\n queryClient.invalidateQueries({ queryKey: queryKeys.diskUsage() });\r\n onClose();\r\n },\r\n });\r\n\r\n const isPendingRef = useRef(mutation.isPending);\r\n isPendingRef.current = mutation.isPending;\r\n useEffect(() => {\r\n function onKey(e: KeyboardEvent) {\r\n if (e.key === 'Escape' && !isPendingRef.current) onClose();\r\n }\r\n window.addEventListener('keydown', onKey);\r\n return () => window.removeEventListener('keydown', onKey);\r\n }, [onClose]);\r\n\r\n return (\r\n <motion.div\r\n initial={{ opacity: 0 }}\r\n animate={{ opacity: 1 }}\r\n exit={{ opacity: 0 }}\r\n transition={{ duration: 0.18 }}\r\n className=\"fixed inset-0 z-[60] flex items-start justify-center bg-[oklch(0.16_0.006_85_/_0.55)] backdrop-blur-[2px] px-4 py-12\"\r\n onClick={() => !mutation.isPending && onClose()}\r\n >\r\n <motion.div\r\n initial={{ y: 8, opacity: 0 }}\r\n animate={{ y: 0, opacity: 1 }}\r\n transition={{ duration: 0.24, ease: [0.16, 1, 0.3, 1] }}\r\n className=\"w-full max-w-md overflow-hidden rounded-[var(--radius-panel)] border border-[var(--color-hairline)] bg-[var(--color-surface)] shadow-[var(--shadow-pop)]\"\r\n onClick={(e) => e.stopPropagation()}\r\n >\r\n <header className=\"border-b border-[var(--color-hairline)] px-6 py-5\">\r\n <p className=\"eyebrow text-[var(--color-danger)]\">{t('delete.eyebrow.confirm')}</p>\r\n <h2 className=\"mt-1 font-display text-xl font-light tracking-tight text-[var(--color-fg-primary)]\">\r\n {t('cleanup.confirm.title')}\r\n </h2>\r\n <p className=\"mt-2 text-sm text-[var(--color-fg-muted)]\">\r\n {t('cleanup.confirm.body', {\r\n kind,\r\n sid: orphan.sessionId,\r\n size: formatBytes(orphan.sizeBytes),\r\n })}\r\n </p>\r\n </header>\r\n {mutation.error && (\r\n <p className=\"mx-6 mt-3 rounded-md border border-[var(--color-danger)]/40 bg-[var(--color-danger-soft)] px-3 py-2 text-sm text-[var(--color-danger)]\">\r\n {(mutation.error as Error).message}\r\n </p>\r\n )}\r\n <footer className=\"flex justify-end gap-2 border-t border-[var(--color-hairline)] px-6 py-4\">\r\n <button\r\n type=\"button\"\r\n onClick={onClose}\r\n disabled={mutation.isPending}\r\n className=\"rounded-[var(--radius-control)] border border-[var(--color-hairline-strong)] px-4 py-1.5 text-sm text-[var(--color-fg-secondary)] hover:bg-[var(--color-sunken)] disabled:opacity-50\"\r\n >\r\n {t('cleanup.confirm.cancel')}\r\n </button>\r\n <button\r\n type=\"button\"\r\n onClick={() => mutation.mutate()}\r\n disabled={mutation.isPending}\r\n className=\"rounded-[var(--radius-control)] bg-[var(--color-danger)] px-4 py-1.5 text-sm font-medium text-white shadow-[var(--shadow-rise)] hover:opacity-90 disabled:cursor-not-allowed disabled:opacity-50\"\r\n >\r\n {mutation.isPending ? t('cleanup.action.deleting') : t('cleanup.confirm.confirm')}\r\n </button>\r\n </footer>\r\n </motion.div>\r\n </motion.div>\r\n );\r\n}\r\n\r\nfunction shortCwd(cwd: string): string {\r\n const parts = cwd.split(/[\\\\/]+/).filter(Boolean);\r\n if (parts.length <= 2) return cwd;\r\n return '…/' + parts.slice(-2).join('/');\r\n}\r\n","import type { ReactNode } from 'react';\r\n\r\ninterface Props {\r\n label: string;\r\n value: ReactNode;\r\n unit?: ReactNode;\r\n trail?: ReactNode;\r\n accent?: boolean;\r\n}\r\n\r\nexport default function StatCard({ label, value, unit, trail, accent }: Props) {\r\n return (\r\n <div\r\n className={\r\n 'surface-card is-interactive group relative overflow-hidden p-5 ' +\r\n (accent ? 'border-[var(--color-accent)]/40 hover:border-[var(--color-accent)]/60' : '')\r\n }\r\n >\r\n {accent && (\r\n <span\r\n aria-hidden\r\n className=\"pointer-events-none absolute -right-12 -top-12 h-32 w-32 rounded-full bg-[var(--color-accent-soft)] opacity-70 blur-2xl\"\r\n />\r\n )}\r\n <div className=\"eyebrow\">{label}</div>\r\n <div className=\"mt-3 flex items-baseline gap-1.5\">\r\n <span className=\"font-mono text-4xl font-light leading-none tracking-[-0.02em] tabular-nums text-[var(--color-fg-primary)]\">\r\n {value}\r\n </span>\r\n {unit && (\r\n <span className=\"font-mono text-[11px] uppercase tracking-[0.16em] text-[var(--color-fg-muted)]\">\r\n {unit}\r\n </span>\r\n )}\r\n </div>\r\n {trail && (\r\n <div className=\"mt-3 font-mono text-[11px] text-[var(--color-fg-muted)]\">{trail}</div>\r\n )}\r\n </div>\r\n );\r\n}\r\n","import { useQuery } from '@tanstack/react-query';\r\nimport { motion } from 'motion/react';\r\nimport { useEffect, useMemo, useState } from 'react';\r\nimport { Link } from 'react-router-dom';\r\nimport {\r\n Area,\r\n AreaChart,\r\n Cell,\r\n Pie,\r\n PieChart,\r\n ResponsiveContainer,\r\n Tooltip,\r\n XAxis,\r\n YAxis,\r\n} from 'recharts';\r\nimport CleanupSuggestions from '../components/CleanupSuggestions.tsx';\r\nimport { Loading } from '../components/Loading.tsx';\r\nimport { MetaItem, Sep } from '../components/PageHeader.tsx';\r\nimport StatCard from '../components/StatCard.tsx';\r\nimport { api, type DiskUsage } from '../lib/api.ts';\r\nimport { formatBytes, formatRelativeTime } from '../lib/format.ts';\r\nimport { useT } from '../lib/i18n.ts';\r\nimport { fadeUpItem, staggerParent } from '../lib/motion.ts';\r\nimport { queryKeys } from '../lib/query-keys.ts';\r\n\r\nconst PALETTE_VARS = [\r\n '--color-accent',\r\n '--color-moss',\r\n '--color-iris',\r\n '--color-fg-secondary',\r\n '--color-accent-ink',\r\n '--color-fg-muted',\r\n];\r\n\r\nconst CHART_VARS = [\r\n '--color-accent',\r\n '--color-fg-muted',\r\n '--color-hairline',\r\n '--color-surface',\r\n '--color-fg-primary',\r\n] as const;\r\n\r\n// Resolve a list of CSS variables on <html> and re-resolve whenever the\r\n// theme class flips. Recharts needs concrete colors; CSS vars don't traverse SVG cleanly.\r\nfunction useThemeColors<T extends readonly string[]>(vars: T): Record<T[number], string> {\r\n const [snapshot, setSnapshot] = useState(() => readVars(vars));\r\n useEffect(() => {\r\n const observer = new MutationObserver(() => setSnapshot(readVars(vars)));\r\n observer.observe(document.documentElement, { attributes: true, attributeFilter: ['class'] });\r\n return () => observer.disconnect();\r\n }, [vars]);\r\n return snapshot;\r\n}\r\n\r\nfunction readVars<T extends readonly string[]>(vars: T): Record<T[number], string> {\r\n const cs = getComputedStyle(document.documentElement);\r\n const out = {} as Record<T[number], string>;\r\n for (const v of vars) (out as Record<string, string>)[v] = cs.getPropertyValue(v).trim() || '#888';\r\n return out;\r\n}\r\n\r\nexport default function DiskUsageRoute() {\r\n const t = useT();\r\n const { data, isLoading, error } = useQuery({\r\n queryKey: queryKeys.diskUsage(),\r\n queryFn: () => api<DiskUsage>('/api/disk-usage'),\r\n });\r\n\r\n const colors = useThemeColors(CHART_VARS);\r\n const accent = colors['--color-accent'];\r\n const muted = colors['--color-fg-muted'];\r\n const hairline = colors['--color-hairline'];\r\n const surface = colors['--color-surface'];\r\n const fgPrimary = colors['--color-fg-primary'];\r\n\r\n const palette = useThemeColors(PALETTE_VARS);\r\n const resolvedPalette = useMemo(() => PALETTE_VARS.map((v) => palette[v]), [palette]);\r\n\r\n const pieData = useMemo(() => {\r\n if (!data) return [];\r\n return data.byProject.map((p) => ({\r\n name: shortCwd(p.decodedCwd),\r\n value: p.totalBytes,\r\n sessions: p.sessionCount,\r\n }));\r\n }, [data]);\r\n\r\n const monthData = useMemo(() => {\r\n if (!data) return [];\r\n return data.byMonth.map((m) => ({ month: m.month, MB: +(m.totalBytes / 1_048_576).toFixed(2) }));\r\n }, [data]);\r\n\r\n return (\r\n <section>\r\n <div className=\"surface-card p-6\">\r\n <Masthead\r\n title={t('disk.title')}\r\n tagline={t('disk.tagline')}\r\n stats={\r\n data\r\n ? {\r\n totalBytes: data.totalBytes,\r\n projectCount: data.byProject.length,\r\n totalSessions: data.totalSessions,\r\n }\r\n : null\r\n }\r\n />\r\n </div>\r\n\r\n {isLoading && <Loading label={t('common.computing')} className=\"mt-10\" />}\r\n {error && (\r\n <p className=\"mt-10 rounded-md border border-[var(--color-danger)]/40 bg-[var(--color-danger-soft)] px-4 py-3 text-sm text-[var(--color-danger)]\">\r\n {t('common.failed')}: {(error as Error).message}\r\n </p>\r\n )}\r\n\r\n {data && (\r\n <>\r\n <motion.div\r\n initial=\"hidden\"\r\n animate=\"show\"\r\n variants={staggerParent}\r\n className=\"mt-8 grid gap-3 sm:grid-cols-3\"\r\n >\r\n <motion.div variants={fadeUpItem}>\r\n <StatCard\r\n accent\r\n label={t('disk.stat.total')}\r\n value={formatBytes(data.totalBytes).split(' ')[0]}\r\n unit={formatBytes(data.totalBytes).split(' ')[1]}\r\n trail={t('disk.stat.acrossProjects', { n: data.byProject.length })}\r\n />\r\n </motion.div>\r\n <motion.div variants={fadeUpItem}>\r\n <StatCard\r\n label={t('disk.stat.sessions')}\r\n value={data.totalSessions.toLocaleString()}\r\n trail={\r\n data.topSessions[0]\r\n ? t('disk.stat.largest', { size: formatBytes(data.topSessions[0].totalBytes) })\r\n : undefined\r\n }\r\n />\r\n </motion.div>\r\n <motion.div variants={fadeUpItem}>\r\n <StatCard\r\n label={t('disk.stat.months')}\r\n value={data.byMonth.length}\r\n trail={\r\n data.byMonth[0]\r\n ? `${data.byMonth[0].month} → ${data.byMonth.at(-1)?.month ?? data.byMonth[0].month}`\r\n : undefined\r\n }\r\n />\r\n </motion.div>\r\n </motion.div>\r\n\r\n <div className=\"mt-12 grid gap-8 lg:grid-cols-5\">\r\n <Card\r\n title={t('disk.composition.title')}\r\n subtitle={t('disk.composition.subtitle')}\r\n className=\"lg:col-span-3\"\r\n >\r\n {pieData.length === 0 ? (\r\n <Empty />\r\n ) : (\r\n <div className=\"grid gap-6 md:grid-cols-[minmax(0,1fr)_minmax(0,1.1fr)] md:items-center\">\r\n <div className=\"relative mx-auto aspect-square w-full max-w-[260px]\">\r\n <ResponsiveContainer width=\"100%\" height=\"100%\">\r\n <PieChart margin={{ top: 0, right: 0, bottom: 0, left: 0 }}>\r\n <Pie\r\n data={pieData}\r\n dataKey=\"value\"\r\n nameKey=\"name\"\r\n cx=\"50%\"\r\n cy=\"50%\"\r\n innerRadius=\"58%\"\r\n outerRadius=\"92%\"\r\n paddingAngle={1.5}\r\n stroke={surface}\r\n strokeWidth={2}\r\n isAnimationActive={false}\r\n >\r\n {pieData.map((_, i) => (\r\n <Cell key={i} fill={resolvedPalette[i % resolvedPalette.length]} />\r\n ))}\r\n </Pie>\r\n <Tooltip\r\n contentStyle={tooltipStyle(surface, hairline, fgPrimary)}\r\n formatter={(value: number) => formatBytes(value)}\r\n />\r\n </PieChart>\r\n </ResponsiveContainer>\r\n <div className=\"pointer-events-none absolute inset-0 flex flex-col items-center justify-center text-center\">\r\n <span className=\"eyebrow\">{t('disk.composition.total')}</span>\r\n <span className=\"mt-1 font-mono text-2xl font-light tabular-nums text-[var(--color-fg-primary)]\">\r\n {formatBytes(data.totalBytes)}\r\n </span>\r\n </div>\r\n </div>\r\n <ol className=\"space-y-1.5 text-sm\">\r\n {pieData.slice(0, 8).map((p, i) => {\r\n const pct = ((p.value / data.totalBytes) * 100).toFixed(1);\r\n return (\r\n <li key={i} className=\"grid grid-cols-[14px_1fr_auto] items-baseline gap-2\">\r\n <span\r\n aria-hidden\r\n className=\"block h-2.5 w-2.5 self-center rounded-sm\"\r\n style={{ background: resolvedPalette[i % resolvedPalette.length] }}\r\n />\r\n <span className=\"truncate font-mono text-xs text-[var(--color-fg-secondary)]\" title={p.name}>\r\n {p.name}\r\n </span>\r\n <span className=\"font-mono tabular-nums text-xs text-[var(--color-fg-primary)]\">\r\n {pct}% <span className=\"text-[var(--color-fg-faint)]\">· {formatBytes(p.value)}</span>\r\n </span>\r\n </li>\r\n );\r\n })}\r\n </ol>\r\n </div>\r\n )}\r\n </Card>\r\n\r\n <Card\r\n title={t('disk.cadence.title')}\r\n subtitle={t('disk.cadence.subtitle')}\r\n className=\"lg:col-span-2\"\r\n >\r\n {monthData.length === 0 ? (\r\n <Empty />\r\n ) : (\r\n <div className=\"h-72\">\r\n <ResponsiveContainer width=\"100%\" height=\"100%\">\r\n <AreaChart data={monthData} margin={{ top: 10, right: 8, bottom: 0, left: -10 }}>\r\n <defs>\r\n <linearGradient id=\"cadenceFill\" x1=\"0\" y1=\"0\" x2=\"0\" y2=\"1\">\r\n <stop offset=\"0%\" stopColor={accent} stopOpacity={0.55} />\r\n <stop offset=\"100%\" stopColor={accent} stopOpacity={0} />\r\n </linearGradient>\r\n </defs>\r\n <XAxis\r\n dataKey=\"month\"\r\n tick={{ fontSize: 11, fill: muted, fontFamily: 'var(--font-mono)' }}\r\n tickLine={false}\r\n axisLine={{ stroke: hairline }}\r\n />\r\n <YAxis\r\n tick={{ fontSize: 11, fill: muted, fontFamily: 'var(--font-mono)' }}\r\n tickLine={false}\r\n axisLine={false}\r\n width={36}\r\n />\r\n <Tooltip\r\n contentStyle={tooltipStyle(surface, hairline, fgPrimary)}\r\n formatter={(value: number) => `${value.toFixed(2)} MB`}\r\n cursor={{ stroke: hairline, strokeDasharray: '2 3' }}\r\n />\r\n <Area\r\n type=\"monotone\"\r\n dataKey=\"MB\"\r\n stroke={accent}\r\n strokeWidth={1.6}\r\n fill=\"url(#cadenceFill)\"\r\n />\r\n </AreaChart>\r\n </ResponsiveContainer>\r\n </div>\r\n )}\r\n </Card>\r\n </div>\r\n\r\n <div className=\"surface-card mt-12 p-6\">\r\n <div className=\"flex items-baseline justify-between\">\r\n <h2 className=\"font-display text-xl font-light tracking-tight text-[var(--color-fg-primary)]\">\r\n {t('disk.heaviest.title')}\r\n </h2>\r\n {data.topSessions.length > 0 && (\r\n <span className=\"font-mono text-[11px] uppercase tracking-[0.16em] text-[var(--color-fg-muted)]\">\r\n {t('disk.heaviest.top', { n: data.topSessions.length })}\r\n </span>\r\n )}\r\n </div>\r\n <div className=\"rule-dotted mt-3\" aria-hidden />\r\n {data.topSessions.length === 0 ? (\r\n <Empty className=\"mt-6\" />\r\n ) : (\r\n <div className=\"mt-4 -mx-6 overflow-x-auto px-6\">\r\n <table className=\"w-full table-fixed text-sm\">\r\n <colgroup>\r\n <col className=\"w-10\" />\r\n <col />\r\n <col className=\"w-[22rem]\" />\r\n <col className=\"w-24\" />\r\n <col className=\"w-24\" />\r\n </colgroup>\r\n <thead>\r\n <tr className=\"text-left\">\r\n <th className=\"px-2 py-3 eyebrow\">{t('disk.col.num')}</th>\r\n <th className=\"px-2 py-3 eyebrow\">{t('disk.col.title')}</th>\r\n <th className=\"px-2 py-3 eyebrow\">{t('disk.col.project')}</th>\r\n <th className=\"px-2 py-3 eyebrow text-right\">{t('disk.col.last')}</th>\r\n <th className=\"px-2 py-3 eyebrow text-right\">{t('disk.col.size')}</th>\r\n </tr>\r\n </thead>\r\n <tbody className=\"border-t border-[var(--color-hairline)]\">\r\n {data.topSessions.map((s, i) => {\r\n const displayTitle = s.customTitle ?? s.title;\r\n return (\r\n <tr\r\n key={`${s.projectId}/${s.sessionId}`}\r\n className=\"ribbon-row border-b border-[var(--color-hairline)] hover:bg-[var(--color-sunken)]\"\r\n >\r\n <td className=\"px-2 py-3 align-top font-mono text-[11px] text-[var(--color-fg-faint)]\">\r\n {String(i + 1).padStart(2, '0')}\r\n </td>\r\n <td className=\"px-2 py-3 align-top\">\r\n <Link\r\n to={`/projects/${encodeURIComponent(s.projectId)}/sessions/${s.sessionId}`}\r\n className=\"block truncate font-medium text-[var(--color-fg-primary)] hover:text-[var(--color-accent-ink)] dark:hover:text-[var(--color-accent)]\"\r\n title={displayTitle}\r\n >\r\n {displayTitle}\r\n </Link>\r\n </td>\r\n <td className=\"px-2 py-3 align-top font-mono text-[12px] text-[var(--color-fg-muted)]\">\r\n <Link\r\n to={`/projects/${encodeURIComponent(s.projectId)}`}\r\n className=\"block truncate hover:text-[var(--color-fg-primary)]\"\r\n title={s.projectId}\r\n >\r\n {projectCwdLabel(data, s.projectId)}\r\n </Link>\r\n </td>\r\n <td className=\"px-2 py-3 text-right align-top font-mono text-[12.5px] text-[var(--color-fg-secondary)]\">\r\n {formatRelativeTime(s.lastAt)}\r\n </td>\r\n <td className=\"px-2 py-3 text-right align-top font-mono tabular-nums text-[var(--color-fg-primary)]\">\r\n {formatBytes(s.totalBytes)}\r\n </td>\r\n </tr>\r\n );\r\n })}\r\n </tbody>\r\n </table>\r\n </div>\r\n )}\r\n </div>\r\n\r\n <CleanupSuggestions />\r\n </>\r\n )}\r\n </section>\r\n );\r\n}\r\n\r\nfunction Masthead({\r\n title,\r\n tagline,\r\n stats,\r\n}: {\r\n title: string;\r\n tagline: string;\r\n stats: {\r\n totalBytes: number;\r\n projectCount: number;\r\n totalSessions: number;\r\n } | null;\r\n}) {\r\n const t = useT();\r\n return (\r\n <header className=\"relative\">\r\n <div className=\"flex flex-wrap items-baseline gap-x-4 gap-y-1\">\r\n <h1 className=\"font-display text-[clamp(1.75rem,3.5vw,2.25rem)] font-light leading-[1.1] tracking-[-0.02em] text-[var(--color-fg-primary)]\">\r\n {title}\r\n <span className=\"text-[var(--color-accent)]\">.</span>\r\n </h1>\r\n <p className=\"min-w-0 flex-1 font-display text-[13px] italic leading-snug text-[var(--color-fg-muted)]\">\r\n {tagline}\r\n </p>\r\n </div>\r\n {stats && (\r\n <div className=\"mt-3 flex flex-wrap items-baseline gap-x-3 gap-y-1 text-xs\">\r\n <MetaItem label={t('disk.meta.total')} value={formatBytes(stats.totalBytes)} />\r\n <Sep />\r\n <MetaItem label={t('disk.meta.projects')} value={stats.projectCount} />\r\n <Sep />\r\n <MetaItem label={t('disk.meta.sessions')} value={stats.totalSessions.toLocaleString()} />\r\n </div>\r\n )}\r\n </header>\r\n );\r\n}\r\n\r\nfunction tooltipStyle(surface: string, hairline: string, fg: string): React.CSSProperties {\r\n return {\r\n background: surface,\r\n border: `1px solid ${hairline}`,\r\n borderRadius: 8,\r\n fontFamily: 'var(--font-mono)',\r\n fontSize: 11,\r\n color: fg,\r\n boxShadow: 'var(--shadow-pop)',\r\n };\r\n}\r\n\r\nfunction projectCwdLabel(data: DiskUsage, projectId: string): string {\r\n const p = data.byProject.find((row) => row.projectId === projectId);\r\n return p ? shortCwd(p.decodedCwd) : projectId;\r\n}\r\n\r\nfunction shortCwd(cwd: string): string {\r\n const parts = cwd.split(/[\\\\/]+/).filter(Boolean);\r\n if (parts.length <= 2) return cwd;\r\n return '…/' + parts.slice(-2).join('/');\r\n}\r\n\r\nfunction Card({\r\n title,\r\n subtitle,\r\n children,\r\n className = '',\r\n}: {\r\n title: string;\r\n subtitle?: string;\r\n children: React.ReactNode;\r\n className?: string;\r\n}) {\r\n return (\r\n <section className={`surface-card p-5 ${className}`}>\r\n <header className=\"mb-4 flex items-baseline justify-between gap-3\">\r\n <h3 className=\"font-display text-lg font-light tracking-tight text-[var(--color-fg-primary)]\">\r\n {title}\r\n </h3>\r\n {subtitle && (\r\n <span className=\"font-mono text-[10px] uppercase tracking-[0.18em] text-[var(--color-fg-muted)]\">\r\n {subtitle}\r\n </span>\r\n )}\r\n </header>\r\n {children}\r\n </section>\r\n );\r\n}\r\n\r\nfunction Empty({ className = '' }: { className?: string }) {\r\n const t = useT();\r\n return (\r\n <p className={`font-mono text-xs uppercase tracking-[0.18em] text-[var(--color-fg-muted)] ${className}`}>\r\n {t('common.noData')}\r\n </p>\r\n );\r\n}\r\n"],"names":["CleanupSuggestions","t","useT","data","isLoading","error","useQuery","queryKeys","api","jsxs","jsx","Loading","LargeSessionsTable","OrphanTable","SectionHeader","title","hint","row","display","Link","shortCwd","formatRelativeTime","formatBytes","kind","rows","confirming","setConfirming","useState","OrphanConfirmDialog","orphan","onClose","queryClient","useQueryClient","mutation","useMutation","isPendingRef","useRef","useEffect","onKey","e","motion","cwd","parts","StatCard","label","value","unit","trail","accent","PALETTE_VARS","CHART_VARS","useThemeColors","vars","snapshot","setSnapshot","readVars","observer","cs","out","v","DiskUsageRoute","colors","muted","hairline","surface","fgPrimary","palette","resolvedPalette","useMemo","pieData","p","monthData","m","Masthead","Fragment","staggerParent","fadeUpItem","_a","Card","Empty","ResponsiveContainer","PieChart","Pie","_","i","Cell","Tooltip","tooltipStyle","pct","AreaChart","XAxis","YAxis","Area","s","displayTitle","projectCwdLabel","tagline","stats","MetaItem","Sep","fg","projectId","subtitle","children","className"],"mappings":"+XAqBA,SAAwBA,IAAqB,CAC3C,MAAMC,EAAIC,EAAA,EACJ,CAAE,KAAAC,EAAM,UAAAC,EAAW,MAAAC,CAAA,EAAUC,EAAS,CAC1C,SAAUC,EAAU,uBAAA,EACpB,QAAS,IAAMC,EAA4B,+BAA+B,CAAA,CAC3E,EAED,OACEC,EAAAA,KAAC,UAAA,CAAQ,UAAU,yBACjB,SAAA,CAAAA,EAAAA,KAAC,SAAA,CAAO,UAAU,gEAChB,SAAA,CAAAC,MAAC,KAAA,CAAG,UAAU,gFACX,SAAAT,EAAE,eAAe,EACpB,QACC,IAAA,CAAE,UAAU,2FACV,SAAAA,EAAE,iBAAiB,CAAA,CACtB,CAAA,EACF,EACAS,EAAAA,IAAC,MAAA,CAAI,UAAU,mBAAmB,cAAW,GAAC,EAE7CN,SAAcO,EAAA,CAAQ,MAAOV,EAAE,kBAAkB,EAAG,UAAU,OAAO,EACrEI,GACCK,EAAAA,IAAC,IAAA,CAAE,UAAU,oIACV,SAAAT,EAAE,iBAAkB,CAAE,IAAMI,EAAgB,OAAA,CAAS,CAAA,CACxD,EAGDF,GACCM,EAAAA,KAAC,MAAA,CAAI,UAAU,iBACb,SAAA,CAAAC,EAAAA,IAACE,GAAA,CAAmB,KAAMT,EAAK,aAAA,CAAe,EAC9CO,EAAAA,IAACG,EAAA,CACC,KAAK,eACL,MAAOZ,EAAE,mCAAmC,EAC5C,KAAMA,EAAE,wCAAwC,EAChD,KAAME,EAAK,iBAAA,CAAA,EAEbO,EAAAA,IAACG,EAAA,CACC,KAAK,cACL,MAAOZ,EAAE,kCAAkC,EAC3C,KAAMA,EAAE,uCAAuC,EAC/C,KAAME,EAAK,gBAAA,CAAA,CACb,CAAA,CACF,CAAA,EAEJ,CAEJ,CAEA,SAASW,EAAc,CAAE,MAAAC,EAAO,KAAAC,GAAyC,CACvE,OACEP,EAAAA,KAAC,MAAA,CACC,UAAU,iIAEV,SAAA,CAAAC,EAAAA,IAAC,KAAA,CAAG,UAAU,oFACX,SAAAK,EACH,EACAL,EAAAA,IAAC,OAAA,CAAK,UAAU,mFACb,SAAAM,CAAA,CACH,CAAA,CAAA,CAAA,CAGN,CAEA,SAASJ,GAAmB,CAC1B,KAAAT,CACF,EAEG,CACD,MAAM,EAAID,EAAA,EACV,cACG,MAAA,CACC,SAAA,CAAAQ,EAAAA,IAACI,EAAA,CACC,MAAO,EAAE,+BAA+B,EACxC,KAAM,EAAE,qCAAsC,CAAE,EAAGX,EAAK,QAAU,GAAI,CAAA,CAAA,EAEvEA,EAAK,SAAW,QACd,IAAA,CAAE,UAAU,kFACV,SAAA,EAAE,6BAA6B,CAAA,CAClC,QAEC,MAAA,CAAI,UAAU,kCACb,SAAAM,EAAAA,KAAC,QAAA,CAAM,UAAU,6BACf,SAAA,CAAAA,OAAC,WAAA,CACC,SAAA,CAAAC,EAAAA,IAAC,MAAA,EAAI,EACLA,EAAAA,IAAC,MAAA,CAAI,UAAU,WAAA,CAAY,EAC3BA,EAAAA,IAAC,MAAA,CAAI,UAAU,MAAA,CAAO,EACtBA,EAAAA,IAAC,MAAA,CAAI,UAAU,MAAA,CAAO,EACtBA,EAAAA,IAAC,MAAA,CAAI,UAAU,MAAA,CAAO,CAAA,EACxB,EACAA,MAAC,QAAA,CACC,SAAAD,EAAAA,KAAC,KAAA,CAAG,UAAU,YACZ,SAAA,CAAAC,MAAC,KAAA,CAAG,UAAU,oBAAqB,SAAA,EAAE,qBAAqB,EAAE,QAC3D,KAAA,CAAG,UAAU,oBAAqB,SAAA,EAAE,qBAAqB,EAAE,QAC3D,KAAA,CAAG,UAAU,+BAAgC,SAAA,EAAE,kBAAkB,EAAE,QACnE,KAAA,CAAG,UAAU,+BAAgC,SAAA,EAAE,kBAAkB,EAAE,QACnE,KAAA,CAAG,UAAU,+BAAgC,SAAA,EAAE,qBAAqB,CAAA,CAAE,CAAA,CAAA,CACzE,CAAA,CACF,QACC,QAAA,CAAM,UAAU,0CACd,SAAAP,EAAK,IAAKc,GAAQ,CACjB,MAAMC,EAAUD,EAAI,aAAeA,EAAI,MACvC,OACER,EAAAA,KAAC,KAAA,CAEC,UAAU,oFAEV,SAAA,CAAAA,EAAAA,KAAC,KAAA,CAAG,UAAU,wBACZ,SAAA,CAAAC,EAAAA,IAAC,MAAA,CACC,UAAU,sDACV,MAAOQ,EAEN,SAAAA,CAAA,CAAA,EAEHR,EAAAA,IAAC,MAAA,CACC,UAAU,uEACV,MAAOO,EAAI,UAEV,SAAAA,EAAI,SAAA,CAAA,CACP,EACF,EACAP,EAAAA,IAAC,KAAA,CACC,UAAU,2EAEV,SAAAA,EAAAA,IAACS,EAAA,CACC,GAAI,aAAa,mBAAmBF,EAAI,SAAS,CAAC,GAClD,UAAU,sDACV,MAAOA,EAAI,YAEV,SAAAG,GAASH,EAAI,WAAW,CAAA,CAAA,CAC3B,CAAA,QAED,KAAA,CAAG,UAAU,0FACX,SAAAI,EAAmBJ,EAAI,YAAY,EACtC,QACC,KAAA,CAAG,UAAU,yFACX,SAAAK,EAAYL,EAAI,SAAS,EAC5B,EACAP,EAAAA,IAAC,KAAA,CAAG,UAAU,mCACZ,SAAAA,EAAAA,IAACS,EAAA,CACC,GAAI,aAAa,mBAAmBF,EAAI,SAAS,CAAC,aAAaA,EAAI,SAAS,GAC5E,UAAU,uOAET,WAAE,qBAAqB,CAAA,CAAA,CAC1B,CACF,CAAA,CAAA,EAzCK,GAAGA,EAAI,SAAS,IAAIA,EAAI,SAAS,EAAA,CA4C5C,CAAC,CAAA,CACH,CAAA,CAAA,CACF,CAAA,CACF,CAAA,EAEJ,CAEJ,CAEA,SAASJ,EAAY,CACnB,KAAAU,EACA,MAAAR,EACA,KAAAC,EACA,KAAAQ,CACF,EAKG,CACD,MAAMvB,EAAIC,EAAA,EACJ,CAACuB,EAAYC,CAAa,EAAIC,EAAAA,SAAmC,IAAI,EAC3E,cACG,MAAA,CACC,SAAA,CAAAjB,EAAAA,IAACI,EAAA,CAAc,MAAAC,EAAc,KAAAC,CAAA,CAAY,EACxCQ,EAAK,SAAW,QACd,IAAA,CAAE,UAAU,kFACV,SAAAvB,EAAE,sBAAsB,CAAA,CAC3B,QAEC,MAAA,CAAI,UAAU,kCACb,SAAAQ,EAAAA,KAAC,QAAA,CAAM,UAAU,6BACf,SAAA,CAAAA,OAAC,WAAA,CACC,SAAA,CAAAC,EAAAA,IAAC,MAAA,EAAI,EACLA,EAAAA,IAAC,MAAA,CAAI,UAAU,MAAA,CAAO,EACtBA,EAAAA,IAAC,MAAA,CAAI,UAAU,MAAA,CAAO,CAAA,EACxB,EACAA,MAAC,QAAA,CACC,SAAAD,EAAAA,KAAC,KAAA,CAAG,UAAU,YACZ,SAAA,CAAAC,MAAC,KAAA,CAAG,UAAU,oBAAqB,SAAAT,EAAE,iBAAiB,EAAE,QACvD,KAAA,CAAG,UAAU,+BAAgC,SAAAA,EAAE,kBAAkB,EAAE,QACnE,KAAA,CAAG,UAAU,+BAAgC,SAAAA,EAAE,qBAAqB,CAAA,CAAE,CAAA,CAAA,CACzE,CAAA,CACF,QACC,QAAA,CAAM,UAAU,0CACd,SAAAuB,EAAK,IAAKP,GACTR,EAAAA,KAAC,KAAA,CAEC,UAAU,oFAEV,SAAA,CAAAC,EAAAA,IAAC,KAAA,CACC,UAAU,+EACV,MAAOO,EAAI,UAEX,SAAAP,EAAAA,IAAC,OAAA,CAAK,UAAU,iBAAkB,WAAI,SAAA,CAAU,CAAA,CAAA,QAEjD,KAAA,CAAG,UAAU,yFACX,SAAAY,EAAYL,EAAI,SAAS,EAC5B,EACAP,EAAAA,IAAC,KAAA,CAAG,UAAU,mCACZ,SAAAA,EAAAA,IAAC,SAAA,CACC,KAAK,SACL,QAAS,IAAMgB,EAAcT,CAAG,EAChC,UAAU,2LAET,WAAE,uBAAuB,CAAA,CAAA,CAC5B,CACF,CAAA,CAAA,EApBKA,EAAI,SAAA,CAsBZ,CAAA,CACH,CAAA,CAAA,CACF,CAAA,CACF,EAEDQ,GACCf,EAAAA,IAACkB,GAAA,CACC,KAAAL,EACA,OAAQE,EACR,QAAS,IAAMC,EAAc,IAAI,CAAA,CAAA,CACnC,EAEJ,CAEJ,CAEA,SAASE,GAAoB,CAC3B,KAAAL,EACA,OAAAM,EACA,QAAAC,CACF,EAIG,CACD,MAAM7B,EAAIC,EAAA,EACJ6B,EAAcC,EAAA,EACdC,EAAWC,EAAY,CAC3B,WAAY,IACV1B,EACE,4BAA4Be,CAAI,IAAI,mBAAmBM,EAAO,SAAS,CAAC,GACxE,CAAE,OAAQ,QAAA,CAAS,EAEvB,UAAW,IAAM,CACfE,EAAY,kBAAkB,CAAE,SAAUxB,EAAU,uBAAA,EAA0B,EAC9EwB,EAAY,kBAAkB,CAAE,SAAUxB,EAAU,UAAA,EAAa,EACjEuB,EAAA,CACF,CAAA,CACD,EAEKK,EAAeC,EAAAA,OAAOH,EAAS,SAAS,EAC9C,OAAAE,EAAa,QAAUF,EAAS,UAChCI,EAAAA,UAAU,IAAM,CACd,SAASC,EAAMC,EAAkB,CAC3BA,EAAE,MAAQ,UAAY,CAACJ,EAAa,SAASL,EAAA,CACnD,CACA,cAAO,iBAAiB,UAAWQ,CAAK,EACjC,IAAM,OAAO,oBAAoB,UAAWA,CAAK,CAC1D,EAAG,CAACR,CAAO,CAAC,EAGVpB,EAAAA,IAAC8B,EAAO,IAAP,CACC,QAAS,CAAE,QAAS,CAAA,EACpB,QAAS,CAAE,QAAS,CAAA,EACpB,KAAM,CAAE,QAAS,CAAA,EACjB,WAAY,CAAE,SAAU,GAAA,EACxB,UAAU,uHACV,QAAS,IAAM,CAACP,EAAS,WAAaH,EAAA,EAEtC,SAAArB,EAAAA,KAAC+B,EAAO,IAAP,CACC,QAAS,CAAE,EAAG,EAAG,QAAS,CAAA,EAC1B,QAAS,CAAE,EAAG,EAAG,QAAS,CAAA,EAC1B,WAAY,CAAE,SAAU,IAAM,KAAM,CAAC,IAAM,EAAG,GAAK,CAAC,CAAA,EACpD,UAAU,2JACV,QAAUD,GAAMA,EAAE,gBAAA,EAElB,SAAA,CAAA9B,EAAAA,KAAC,SAAA,CAAO,UAAU,oDAChB,SAAA,CAAAC,MAAC,IAAA,CAAE,UAAU,qCAAsC,SAAAT,EAAE,wBAAwB,EAAE,QAC9E,KAAA,CAAG,UAAU,qFACX,SAAAA,EAAE,uBAAuB,EAC5B,EACAS,EAAAA,IAAC,IAAA,CAAE,UAAU,4CACV,WAAE,uBAAwB,CACzB,KAAAa,EACA,IAAKM,EAAO,UACZ,KAAMP,EAAYO,EAAO,SAAS,CAAA,CACnC,CAAA,CACH,CAAA,EACF,EACCI,EAAS,OACRvB,MAAC,IAAA,CAAE,UAAU,yIACT,SAAAuB,EAAS,MAAgB,OAAA,CAC7B,EAEFxB,EAAAA,KAAC,SAAA,CAAO,UAAU,2EAChB,SAAA,CAAAC,EAAAA,IAAC,SAAA,CACC,KAAK,SACL,QAASoB,EACT,SAAUG,EAAS,UACnB,UAAU,uLAET,WAAE,wBAAwB,CAAA,CAAA,EAE7BvB,EAAAA,IAAC,SAAA,CACC,KAAK,SACL,QAAS,IAAMuB,EAAS,OAAA,EACxB,SAAUA,EAAS,UACnB,UAAU,mMAET,WAAS,UAAYhC,EAAE,yBAAyB,EAAIA,EAAE,yBAAyB,CAAA,CAAA,CAClF,CAAA,CACF,CAAA,CAAA,CAAA,CACF,CAAA,CAGN,CAEA,SAASmB,GAASqB,EAAqB,CACrC,MAAMC,EAAQD,EAAI,MAAM,QAAQ,EAAE,OAAO,OAAO,EAChD,OAAIC,EAAM,QAAU,EAAUD,EACvB,KAAOC,EAAM,MAAM,EAAE,EAAE,KAAK,GAAG,CACxC,CCjVA,SAAwBC,EAAS,CAAE,MAAAC,EAAO,MAAAC,EAAO,KAAAC,EAAM,MAAAC,EAAO,OAAAC,GAAiB,CAC7E,OACEvC,EAAAA,KAAC,MAAA,CACC,UACE,mEACCuC,EAAS,wEAA0E,IAGrF,SAAA,CAAAA,GACCtC,EAAAA,IAAC,OAAA,CACC,cAAW,GACX,UAAU,yHAAA,CAAA,EAGdA,EAAAA,IAAC,MAAA,CAAI,UAAU,UAAW,SAAAkC,EAAM,EAChCnC,EAAAA,KAAC,MAAA,CAAI,UAAU,mCACb,SAAA,CAAAC,EAAAA,IAAC,OAAA,CAAK,UAAU,4GACb,SAAAmC,EACH,EACCC,GACCpC,EAAAA,IAAC,OAAA,CAAK,UAAU,iFACb,SAAAoC,CAAA,CACH,CAAA,EAEJ,EACCC,GACCrC,EAAAA,IAAC,MAAA,CAAI,UAAU,0DAA2D,SAAAqC,CAAA,CAAM,CAAA,CAAA,CAAA,CAIxF,CCfA,MAAME,EAAe,CACnB,iBACA,eACA,eACA,uBACA,qBACA,kBACF,EAEMC,GAAa,CACjB,iBACA,mBACA,mBACA,kBACA,oBACF,EAIA,SAASC,EAA4CC,EAAoC,CACvF,KAAM,CAACC,EAAUC,CAAW,EAAI3B,EAAAA,SAAS,IAAM4B,EAASH,CAAI,CAAC,EAC7Df,OAAAA,EAAAA,UAAU,IAAM,CACd,MAAMmB,EAAW,IAAI,iBAAiB,IAAMF,EAAYC,EAASH,CAAI,CAAC,CAAC,EACvE,OAAAI,EAAS,QAAQ,SAAS,gBAAiB,CAAE,WAAY,GAAM,gBAAiB,CAAC,OAAO,EAAG,EACpF,IAAMA,EAAS,WAAA,CACxB,EAAG,CAACJ,CAAI,CAAC,EACFC,CACT,CAEA,SAASE,EAAsCH,EAAoC,CACjF,MAAMK,EAAK,iBAAiB,SAAS,eAAe,EAC9CC,EAAM,CAAA,EACZ,UAAWC,KAAKP,EAAOM,EAA+BC,CAAC,EAAIF,EAAG,iBAAiBE,CAAC,EAAE,KAAA,GAAU,OAC5F,OAAOD,CACT,CAEA,SAAwBE,IAAiB,OACvC,MAAM3D,EAAIC,EAAA,EACJ,CAAE,KAAAC,EAAM,UAAAC,EAAW,MAAAC,CAAA,EAAUC,EAAS,CAC1C,SAAUC,EAAU,UAAA,EACpB,QAAS,IAAMC,EAAe,iBAAiB,CAAA,CAChD,EAEKqD,EAASV,EAAeD,EAAU,EAClCF,EAASa,EAAO,gBAAgB,EAChCC,EAAQD,EAAO,kBAAkB,EACjCE,EAAWF,EAAO,kBAAkB,EACpCG,EAAUH,EAAO,iBAAiB,EAClCI,EAAYJ,EAAO,oBAAoB,EAEvCK,EAAUf,EAAeF,CAAY,EACrCkB,EAAkBC,EAAAA,QAAQ,IAAMnB,EAAa,IAAKU,GAAMO,EAAQP,CAAC,CAAC,EAAG,CAACO,CAAO,CAAC,EAE9EG,EAAUD,EAAAA,QAAQ,IACjBjE,EACEA,EAAK,UAAU,IAAKmE,IAAO,CAChC,KAAMlD,EAASkD,EAAE,UAAU,EAC3B,MAAOA,EAAE,WACT,SAAUA,EAAE,YAAA,EACZ,EALgB,CAAA,EAMjB,CAACnE,CAAI,CAAC,EAEHoE,EAAYH,EAAAA,QAAQ,IACnBjE,EACEA,EAAK,QAAQ,IAAKqE,IAAO,CAAE,MAAOA,EAAE,MAAO,GAAI,EAAEA,EAAE,WAAa,SAAW,QAAQ,CAAC,GAAI,EAD7E,CAAA,EAEjB,CAACrE,CAAI,CAAC,EAET,cACG,UAAA,CACC,SAAA,CAAAO,EAAAA,IAAC,MAAA,CAAI,UAAU,mBACb,SAAAA,EAAAA,IAAC+D,GAAA,CACC,MAAOxE,EAAE,YAAY,EACrB,QAASA,EAAE,cAAc,EACzB,MACEE,EACI,CACE,WAAYA,EAAK,WACjB,aAAcA,EAAK,UAAU,OAC7B,cAAeA,EAAK,aAAA,EAEtB,IAAA,CAAA,EAGV,EAECC,SAAcO,EAAA,CAAQ,MAAOV,EAAE,kBAAkB,EAAG,UAAU,QAAQ,EACtEI,GACCI,EAAAA,KAAC,IAAA,CAAE,UAAU,qIACV,SAAA,CAAAR,EAAE,eAAe,EAAE,KAAII,EAAgB,OAAA,EAC1C,EAGDF,GACCM,EAAAA,KAAAiE,WAAA,CACE,SAAA,CAAAjE,EAAAA,KAAC+B,EAAO,IAAP,CACC,QAAQ,SACR,QAAQ,OACR,SAAUmC,EACV,UAAU,iCAEV,SAAA,CAAAjE,EAAAA,IAAC8B,EAAO,IAAP,CAAW,SAAUoC,EACpB,SAAAlE,EAAAA,IAACiC,EAAA,CACC,OAAM,GACN,MAAO1C,EAAE,iBAAiB,EAC1B,MAAOqB,EAAYnB,EAAK,UAAU,EAAE,MAAM,GAAG,EAAE,CAAC,EAChD,KAAMmB,EAAYnB,EAAK,UAAU,EAAE,MAAM,GAAG,EAAE,CAAC,EAC/C,MAAOF,EAAE,2BAA4B,CAAE,EAAGE,EAAK,UAAU,OAAQ,CAAA,CAAA,EAErE,EACAO,EAAAA,IAAC8B,EAAO,IAAP,CAAW,SAAUoC,EACpB,SAAAlE,EAAAA,IAACiC,EAAA,CACC,MAAO1C,EAAE,oBAAoB,EAC7B,MAAOE,EAAK,cAAc,eAAA,EAC1B,MACEA,EAAK,YAAY,CAAC,EACdF,EAAE,oBAAqB,CAAE,KAAMqB,EAAYnB,EAAK,YAAY,CAAC,EAAE,UAAU,CAAA,CAAG,EAC5E,MAAA,CAAA,EAGV,EACAO,EAAAA,IAAC8B,EAAO,IAAP,CAAW,SAAUoC,EACpB,SAAAlE,EAAAA,IAACiC,EAAA,CACC,MAAO1C,EAAE,kBAAkB,EAC3B,MAAOE,EAAK,QAAQ,OACpB,MACEA,EAAK,QAAQ,CAAC,EACV,GAAGA,EAAK,QAAQ,CAAC,EAAE,KAAK,QAAM0E,EAAA1E,EAAK,QAAQ,GAAG,EAAE,IAAlB,YAAA0E,EAAqB,QAAS1E,EAAK,QAAQ,CAAC,EAAE,KAAK,GACjF,MAAA,CAAA,CAER,CACF,CAAA,CAAA,CAAA,EAGFM,EAAAA,KAAC,MAAA,CAAI,UAAU,kCACb,SAAA,CAAAC,EAAAA,IAACoE,EAAA,CACC,MAAO7E,EAAE,wBAAwB,EACjC,SAAUA,EAAE,2BAA2B,EACvC,UAAU,gBAET,SAAAoE,EAAQ,SAAW,EAClB3D,EAAAA,IAACqE,IAAM,EAEPtE,EAAAA,KAAC,MAAA,CAAI,UAAU,0EACb,SAAA,CAAAA,EAAAA,KAAC,MAAA,CAAI,UAAU,sDACb,SAAA,CAAAC,MAACsE,GAAoB,MAAM,OAAO,OAAO,OACvC,gBAACC,EAAA,CAAS,OAAQ,CAAE,IAAK,EAAG,MAAO,EAAG,OAAQ,EAAG,KAAM,GACrD,SAAA,CAAAvE,EAAAA,IAACwE,EAAA,CACC,KAAMb,EACN,QAAQ,QACR,QAAQ,OACR,GAAG,MACH,GAAG,MACH,YAAY,MACZ,YAAY,MACZ,aAAc,IACd,OAAQL,EACR,YAAa,EACb,kBAAmB,GAElB,SAAAK,EAAQ,IAAI,CAACc,EAAGC,IACf1E,EAAAA,IAAC2E,EAAA,CAAa,KAAMlB,EAAgBiB,EAAIjB,EAAgB,MAAM,CAAA,EAAnDiB,CAAsD,CAClE,CAAA,CAAA,EAEH1E,EAAAA,IAAC4E,EAAA,CACC,aAAcC,EAAavB,EAASD,EAAUE,CAAS,EACvD,UAAYpB,GAAkBvB,EAAYuB,CAAK,CAAA,CAAA,CACjD,CAAA,CACF,CAAA,CACF,EACApC,EAAAA,KAAC,MAAA,CAAI,UAAU,6FACb,SAAA,CAAAC,MAAC,OAAA,CAAK,UAAU,UAAW,SAAAT,EAAE,wBAAwB,EAAE,QACtD,OAAA,CAAK,UAAU,iFACb,SAAAqB,EAAYnB,EAAK,UAAU,CAAA,CAC9B,CAAA,CAAA,CACF,CAAA,EACF,EACAO,EAAAA,IAAC,KAAA,CAAG,UAAU,sBACX,SAAA2D,EAAQ,MAAM,EAAG,CAAC,EAAE,IAAI,CAACC,EAAGc,IAAM,CACjC,MAAMI,GAAQlB,EAAE,MAAQnE,EAAK,WAAc,KAAK,QAAQ,CAAC,EACzD,OACEM,EAAAA,KAAC,KAAA,CAAW,UAAU,sDACpB,SAAA,CAAAC,EAAAA,IAAC,OAAA,CACC,cAAW,GACX,UAAU,2CACV,MAAO,CAAE,WAAYyD,EAAgBiB,EAAIjB,EAAgB,MAAM,CAAA,CAAE,CAAA,EAEnEzD,EAAAA,IAAC,QAAK,UAAU,8DAA8D,MAAO4D,EAAE,KACpF,WAAE,IAAA,CACL,EACA7D,EAAAA,KAAC,OAAA,CAAK,UAAU,gEACb,SAAA,CAAA+E,EAAI,KAAE/E,EAAAA,KAAC,OAAA,CAAK,UAAU,+BAA+B,SAAA,CAAA,KAAGa,EAAYgD,EAAE,KAAK,CAAA,CAAA,CAAE,CAAA,CAAA,CAChF,CAAA,CAAA,EAXOc,CAYT,CAEJ,CAAC,CAAA,CACH,CAAA,CAAA,CACF,CAAA,CAAA,EAIJ1E,EAAAA,IAACoE,EAAA,CACC,MAAO7E,EAAE,oBAAoB,EAC7B,SAAUA,EAAE,uBAAuB,EACnC,UAAU,gBAET,SAAAsE,EAAU,SAAW,EACpB7D,EAAAA,IAACqE,EAAA,CAAA,CAAM,EAEPrE,EAAAA,IAAC,MAAA,CAAI,UAAU,OACb,SAAAA,EAAAA,IAACsE,EAAA,CAAoB,MAAM,OAAO,OAAO,OACvC,SAAAvE,OAACgF,EAAA,CAAU,KAAMlB,EAAW,OAAQ,CAAE,IAAK,GAAI,MAAO,EAAG,OAAQ,EAAG,KAAM,KACxE,SAAA,CAAA7D,EAAAA,IAAC,OAAA,CACC,SAAAD,EAAAA,KAAC,iBAAA,CAAe,GAAG,cAAc,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IACvD,SAAA,CAAAC,MAAC,QAAK,OAAO,KAAK,UAAWsC,EAAQ,YAAa,IAAM,QACvD,OAAA,CAAK,OAAO,OAAO,UAAWA,EAAQ,YAAa,CAAA,CAAG,CAAA,CAAA,CACzD,CAAA,CACF,EACAtC,EAAAA,IAACgF,EAAA,CACC,QAAQ,QACR,KAAM,CAAE,SAAU,GAAI,KAAM5B,EAAO,WAAY,kBAAA,EAC/C,SAAU,GACV,SAAU,CAAE,OAAQC,CAAA,CAAS,CAAA,EAE/BrD,EAAAA,IAACiF,EAAA,CACC,KAAM,CAAE,SAAU,GAAI,KAAM7B,EAAO,WAAY,kBAAA,EAC/C,SAAU,GACV,SAAU,GACV,MAAO,EAAA,CAAA,EAETpD,EAAAA,IAAC4E,EAAA,CACC,aAAcC,EAAavB,EAASD,EAAUE,CAAS,EACvD,UAAYpB,GAAkB,GAAGA,EAAM,QAAQ,CAAC,CAAC,MACjD,OAAQ,CAAE,OAAQkB,EAAU,gBAAiB,KAAA,CAAM,CAAA,EAErDrD,EAAAA,IAACkF,EAAA,CACC,KAAK,WACL,QAAQ,KACR,OAAQ5C,EACR,YAAa,IACb,KAAK,mBAAA,CAAA,CACP,CAAA,CACF,EACF,CAAA,CACF,CAAA,CAAA,CAEJ,EACF,EAEAvC,EAAAA,KAAC,MAAA,CAAI,UAAU,yBACb,SAAA,CAAAA,EAAAA,KAAC,MAAA,CAAI,UAAU,sCACb,SAAA,CAAAC,MAAC,KAAA,CAAG,UAAU,gFACX,SAAAT,EAAE,qBAAqB,EAC1B,EACCE,EAAK,YAAY,OAAS,GACzBO,EAAAA,IAAC,QAAK,UAAU,iFACb,SAAAT,EAAE,oBAAqB,CAAE,EAAGE,EAAK,YAAY,MAAA,CAAQ,CAAA,CACxD,CAAA,EAEJ,EACAO,EAAAA,IAAC,MAAA,CAAI,UAAU,mBAAmB,cAAW,GAAC,EAC7CP,EAAK,YAAY,SAAW,EAC3BO,EAAAA,IAACqE,GAAM,UAAU,MAAA,CAAO,EAExBrE,EAAAA,IAAC,OAAI,UAAU,kCACb,SAAAD,EAAAA,KAAC,QAAA,CAAM,UAAU,6BACf,SAAA,CAAAA,OAAC,WAAA,CACC,SAAA,CAAAC,EAAAA,IAAC,MAAA,CAAI,UAAU,MAAA,CAAO,QACrB,MAAA,EAAI,EACLA,EAAAA,IAAC,MAAA,CAAI,UAAU,WAAA,CAAY,EAC3BA,EAAAA,IAAC,MAAA,CAAI,UAAU,MAAA,CAAO,EACtBA,EAAAA,IAAC,MAAA,CAAI,UAAU,MAAA,CAAO,CAAA,EACxB,EACAA,MAAC,QAAA,CACC,SAAAD,EAAAA,KAAC,KAAA,CAAG,UAAU,YACZ,SAAA,CAAAC,MAAC,KAAA,CAAG,UAAU,oBAAqB,SAAAT,EAAE,cAAc,EAAE,QACpD,KAAA,CAAG,UAAU,oBAAqB,SAAAA,EAAE,gBAAgB,EAAE,QACtD,KAAA,CAAG,UAAU,oBAAqB,SAAAA,EAAE,kBAAkB,EAAE,QACxD,KAAA,CAAG,UAAU,+BAAgC,SAAAA,EAAE,eAAe,EAAE,QAChE,KAAA,CAAG,UAAU,+BAAgC,SAAAA,EAAE,eAAe,CAAA,CAAE,CAAA,CAAA,CACnE,CAAA,CACF,EACAS,EAAAA,IAAC,SAAM,UAAU,0CACd,WAAK,YAAY,IAAI,CAACmF,EAAGT,IAAM,CAC9B,MAAMU,EAAeD,EAAE,aAAeA,EAAE,MACxC,OACApF,EAAAA,KAAC,KAAA,CAEC,UAAU,oFAEV,SAAA,CAAAC,EAAAA,IAAC,KAAA,CAAG,UAAU,yEACX,SAAA,OAAO0E,EAAI,CAAC,EAAE,SAAS,EAAG,GAAG,CAAA,CAChC,EACA1E,EAAAA,IAAC,KAAA,CAAG,UAAU,sBACZ,SAAAA,EAAAA,IAACS,EAAA,CACC,GAAI,aAAa,mBAAmB0E,EAAE,SAAS,CAAC,aAAaA,EAAE,SAAS,GACxE,UAAU,uIACV,MAAOC,EAEN,SAAAA,CAAA,CAAA,EAEL,EACApF,EAAAA,IAAC,KAAA,CAAG,UAAU,yEACZ,SAAAA,EAAAA,IAACS,EAAA,CACC,GAAI,aAAa,mBAAmB0E,EAAE,SAAS,CAAC,GAChD,UAAU,sDACV,MAAOA,EAAE,UAER,SAAAE,GAAgB5F,EAAM0F,EAAE,SAAS,CAAA,CAAA,EAEtC,QACC,KAAA,CAAG,UAAU,0FACX,SAAAxE,EAAmBwE,EAAE,MAAM,EAC9B,QACC,KAAA,CAAG,UAAU,uFACX,SAAAvE,EAAYuE,EAAE,UAAU,CAAA,CAC3B,CAAA,CAAA,EA7BK,GAAGA,EAAE,SAAS,IAAIA,EAAE,SAAS,EAAA,CAgCtC,CAAC,CAAA,CACH,CAAA,CAAA,CACF,CAAA,CACF,CAAA,EAEJ,QAEC7F,GAAA,CAAA,CAAmB,CAAA,CAAA,CACtB,CAAA,EAEJ,CAEJ,CAEA,SAASyE,GAAS,CAChB,MAAA1D,EACA,QAAAiF,EACA,MAAAC,CACF,EAQG,CACD,MAAMhG,EAAIC,EAAA,EACV,OACEO,EAAAA,KAAC,SAAA,CAAO,UAAU,WAChB,SAAA,CAAAA,EAAAA,KAAC,MAAA,CAAI,UAAU,gDACb,SAAA,CAAAA,EAAAA,KAAC,KAAA,CAAG,UAAU,8HACX,SAAA,CAAAM,EACDL,EAAAA,IAAC,OAAA,CAAK,UAAU,6BAA6B,SAAA,GAAA,CAAC,CAAA,EAChD,EACAA,EAAAA,IAAC,IAAA,CAAE,UAAU,2FACV,SAAAsF,CAAA,CACH,CAAA,EACF,EACCC,GACCxF,EAAAA,KAAC,MAAA,CAAI,UAAU,6DACb,SAAA,CAAAC,EAAAA,IAACwF,EAAA,CAAS,MAAOjG,EAAE,iBAAiB,EAAG,MAAOqB,EAAY2E,EAAM,UAAU,CAAA,CAAG,QAC5EE,EAAA,EAAI,EACLzF,MAACwF,GAAS,MAAOjG,EAAE,oBAAoB,EAAG,MAAOgG,EAAM,aAAc,QACpEE,EAAA,EAAI,EACLzF,EAAAA,IAACwF,EAAA,CAAS,MAAOjG,EAAE,oBAAoB,EAAG,MAAOgG,EAAM,cAAc,gBAAe,CAAG,CAAA,CAAA,CACzF,CAAA,EAEJ,CAEJ,CAEA,SAASV,EAAavB,EAAiBD,EAAkBqC,EAAiC,CACxF,MAAO,CACL,WAAYpC,EACZ,OAAQ,aAAaD,CAAQ,GAC7B,aAAc,EACd,WAAY,mBACZ,SAAU,GACV,MAAOqC,EACP,UAAW,mBAAA,CAEf,CAEA,SAASL,GAAgB5F,EAAiBkG,EAA2B,CACnE,MAAM/B,EAAInE,EAAK,UAAU,KAAMc,GAAQA,EAAI,YAAcoF,CAAS,EAClE,OAAO/B,EAAIlD,EAASkD,EAAE,UAAU,EAAI+B,CACtC,CAEA,SAASjF,EAASqB,EAAqB,CACrC,MAAMC,EAAQD,EAAI,MAAM,QAAQ,EAAE,OAAO,OAAO,EAChD,OAAIC,EAAM,QAAU,EAAUD,EACvB,KAAOC,EAAM,MAAM,EAAE,EAAE,KAAK,GAAG,CACxC,CAEA,SAASoC,EAAK,CACZ,MAAA/D,EACA,SAAAuF,EACA,SAAAC,EACA,UAAAC,EAAY,EACd,EAKG,CACD,OACE/F,EAAAA,KAAC,UAAA,CAAQ,UAAW,oBAAoB+F,CAAS,GAC/C,SAAA,CAAA/F,EAAAA,KAAC,SAAA,CAAO,UAAU,iDAChB,SAAA,CAAAC,EAAAA,IAAC,KAAA,CAAG,UAAU,gFACX,SAAAK,EACH,EACCuF,GACC5F,EAAAA,IAAC,OAAA,CAAK,UAAU,iFACb,SAAA4F,CAAA,CACH,CAAA,EAEJ,EACCC,CAAA,EACH,CAEJ,CAEA,SAASxB,EAAM,CAAE,UAAAyB,EAAY,IAA8B,CACzD,MAAM,EAAItG,EAAA,EACV,OACEQ,MAAC,KAAE,UAAW,8EAA8E8F,CAAS,GAClG,SAAA,EAAE,eAAe,CAAA,CACpB,CAEJ"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ImportPage-wge4VhZ-.js","sources":["../../web/src/routes/ImportPage.tsx"],"sourcesContent":["import { useMutation, useQueryClient } from '@tanstack/react-query';\r\nimport { useState } from 'react';\r\nimport { Link } from 'react-router-dom';\r\nimport PageHeader from '../components/PageHeader.tsx';\r\nimport {\r\n api,\r\n type ImportCollisionPolicy,\r\n type ImportPreviewResult,\r\n type ImportResult,\r\n type ImportSessionAction,\r\n} from '../lib/api.ts';\r\nimport { useT } from '../lib/i18n.ts';\r\nimport { queryKeys } from '../lib/query-keys.ts';\r\n\r\nconst POLICIES: ImportCollisionPolicy[] = ['skip', 'overwrite-if-newer', 'keep-both'];\r\n\r\nconst POLICY_KEY = {\r\n skip: 'import.policy.skip',\r\n 'overwrite-if-newer': 'import.policy.overwrite-if-newer',\r\n 'keep-both': 'import.policy.keep-both',\r\n} as const;\r\n\r\nconst ACTION_KEY = {\r\n create: 'import.action.create',\r\n overwrite: 'import.action.overwrite',\r\n 'keep-both': 'import.action.keep-both',\r\n skip: 'import.action.skip',\r\n} as const;\r\n\r\nconst SUGGEST_KEY = {\r\n 'existing-project': 'import.suggestion.existing-project',\r\n 'original-path': 'import.suggestion.original-path',\r\n 'same-basename': 'import.suggestion.same-basename',\r\n} as const;\r\n\r\nconst MEM_KEY = {\r\n create: 'import.memory.create',\r\n skip: 'import.memory.skip',\r\n conflict: 'import.memory.conflict',\r\n} as const;\r\n\r\nfunction actionTone(action: ImportSessionAction): string {\r\n switch (action) {\r\n case 'create':\r\n return 'border-[var(--color-moss)]/40 bg-[var(--color-moss-soft)] text-[var(--color-fg-primary)]';\r\n case 'overwrite':\r\n return 'border-[var(--color-danger)]/40 bg-[var(--color-danger-soft)] text-[var(--color-danger)]';\r\n case 'keep-both':\r\n return 'border-[var(--color-accent)]/40 bg-[var(--color-accent-soft)] text-[var(--color-accent-ink)] dark:text-[var(--color-accent)]';\r\n default:\r\n return 'border-[var(--color-hairline-strong)] bg-[var(--color-sunken)] text-[var(--color-fg-muted)]';\r\n }\r\n}\r\n\r\nexport default function ImportPage() {\r\n const t = useT();\r\n const queryClient = useQueryClient();\r\n\r\n const [bundleDir, setBundleDir] = useState('');\r\n const [targetCwd, setTargetCwd] = useState('');\r\n const [policy, setPolicy] = useState<ImportCollisionPolicy>('skip');\r\n const [preview, setPreview] = useState<ImportPreviewResult | null>(null);\r\n\r\n const previewMutation = useMutation({\r\n mutationFn: (vars: { targetCwd?: string; collisionPolicy: ImportCollisionPolicy }) =>\r\n api<ImportPreviewResult>('/api/import/preview', {\r\n method: 'POST',\r\n body: JSON.stringify({\r\n bundleDir: bundleDir.trim(),\r\n targetCwd: vars.targetCwd,\r\n collisionPolicy: vars.collisionPolicy,\r\n }),\r\n }),\r\n onSuccess: (data) => {\r\n setPreview(data);\r\n setTargetCwd(data.remap.targetCwd);\r\n },\r\n });\r\n\r\n const commitMutation = useMutation({\r\n mutationFn: () =>\r\n api<ImportResult>('/api/import', {\r\n method: 'POST',\r\n body: JSON.stringify({\r\n bundleDir: bundleDir.trim(),\r\n targetCwd: targetCwd.trim(),\r\n collisionPolicy: policy,\r\n }),\r\n }),\r\n onSuccess: (data) => {\r\n queryClient.invalidateQueries({ queryKey: queryKeys.projects() });\r\n queryClient.invalidateQueries({ queryKey: queryKeys.projectSessions(data.targetProjectId) });\r\n queryClient.invalidateQueries({ queryKey: queryKeys.projectMemory(data.targetProjectId) });\r\n queryClient.invalidateQueries({ queryKey: queryKeys.diskUsage() });\r\n },\r\n });\r\n\r\n function loadBundle() {\r\n if (bundleDir.trim() === '') return;\r\n setPreview(null);\r\n commitMutation.reset();\r\n previewMutation.mutate({ targetCwd: undefined, collisionPolicy: policy });\r\n }\r\n\r\n function recheck(nextTarget: string, nextPolicy: ImportCollisionPolicy) {\r\n commitMutation.reset();\r\n previewMutation.mutate({\r\n targetCwd: nextTarget.trim() || undefined,\r\n collisionPolicy: nextPolicy,\r\n });\r\n }\r\n\r\n function changePolicy(p: ImportCollisionPolicy) {\r\n setPolicy(p);\r\n if (preview) recheck(targetCwd, p);\r\n }\r\n\r\n const result = commitMutation.data;\r\n const busy = previewMutation.isPending;\r\n\r\n return (\r\n <section>\r\n <div className=\"surface-card p-6\">\r\n <PageHeader eyebrow={t('nav.import')} title={t('import.title')} />\r\n <p className=\"mt-2 max-w-2xl text-sm text-[var(--color-fg-muted)]\">\r\n {t('import.tagline')}\r\n </p>\r\n\r\n <div className=\"mt-5 flex flex-col gap-2 sm:flex-row\">\r\n <input\r\n type=\"text\"\r\n value={bundleDir}\r\n onChange={(e) => setBundleDir(e.target.value)}\r\n onKeyDown={(e) => e.key === 'Enter' && loadBundle()}\r\n placeholder={t('import.bundlePlaceholder')}\r\n spellCheck={false}\r\n aria-label={t('import.bundleLabel')}\r\n className=\"min-w-0 flex-1 rounded-[var(--radius-input)] border border-[var(--color-hairline-strong)] bg-[var(--color-canvas)] px-3 py-2 font-mono text-sm text-[var(--color-fg-primary)] outline-none focus:border-[var(--color-accent)]\"\r\n />\r\n <button\r\n type=\"button\"\r\n onClick={loadBundle}\r\n disabled={bundleDir.trim() === '' || busy}\r\n className=\"rounded-[var(--radius-control)] bg-[var(--color-fg-primary)] px-4 py-2 text-sm font-medium text-[var(--color-canvas)] shadow-[var(--shadow-rise)] hover:opacity-90 disabled:cursor-not-allowed disabled:opacity-50\"\r\n >\r\n {busy ? t('import.btn.loading') : preview ? t('import.btn.recheck') : t('import.btn.load')}\r\n </button>\r\n </div>\r\n\r\n {previewMutation.error && (\r\n <p className=\"mt-3 rounded-md border border-[var(--color-danger)]/40 bg-[var(--color-danger-soft)] px-3 py-2 text-sm text-[var(--color-danger)]\">\r\n {(previewMutation.error as Error).message}\r\n </p>\r\n )}\r\n\r\n {!preview && !previewMutation.error && (\r\n <p className=\"mt-4 text-sm text-[var(--color-fg-muted)]\">{t('import.empty')}</p>\r\n )}\r\n </div>\r\n\r\n {preview && (\r\n <div className=\"surface-card mt-6 space-y-6 p-6\">\r\n <p className=\"break-all font-mono text-xs text-[var(--color-fg-muted)]\">\r\n {t('import.source', { platform: preview.source.platform, cwd: preview.source.cwd })}\r\n </p>\r\n\r\n {/* target */}\r\n <div>\r\n <span className=\"eyebrow\">{t('import.targetLabel')}</span>\r\n <div className=\"mt-1.5 flex flex-col gap-2 sm:flex-row\">\r\n <input\r\n type=\"text\"\r\n value={targetCwd}\r\n onChange={(e) => setTargetCwd(e.target.value)}\r\n onKeyDown={(e) => e.key === 'Enter' && recheck(targetCwd, policy)}\r\n spellCheck={false}\r\n aria-label={t('import.targetLabel')}\r\n className=\"min-w-0 flex-1 rounded-[var(--radius-input)] border border-[var(--color-hairline-strong)] bg-[var(--color-canvas)] px-3 py-2 font-mono text-sm text-[var(--color-fg-primary)] outline-none focus:border-[var(--color-accent)]\"\r\n />\r\n <button\r\n type=\"button\"\r\n onClick={() => recheck(targetCwd, policy)}\r\n disabled={busy}\r\n className=\"rounded-[var(--radius-control)] border border-[var(--color-hairline-strong)] px-4 py-2 text-sm text-[var(--color-fg-secondary)] hover:bg-[var(--color-sunken)] disabled:opacity-50\"\r\n >\r\n {t('import.btn.recheck')}\r\n </button>\r\n </div>\r\n <p className=\"mt-1.5 text-xs text-[var(--color-fg-muted)]\">{t('import.targetHint')}</p>\r\n <p className=\"mt-1 font-mono text-[11px] text-[var(--color-fg-faint)]\">\r\n {t('import.targetId', { id: preview.remap.targetProjectId })}\r\n </p>\r\n\r\n {preview.suggestions.length > 0 && (\r\n <div className=\"mt-2 flex flex-wrap items-center gap-1.5\">\r\n <span className=\"eyebrow mr-1\">{t('import.suggestions')}</span>\r\n {preview.suggestions.map((s) => (\r\n <button\r\n key={s.projectId}\r\n type=\"button\"\r\n onClick={() => {\r\n setTargetCwd(s.cwd);\r\n recheck(s.cwd, policy);\r\n }}\r\n className=\"inline-flex items-center gap-1.5 rounded-[var(--radius-control)] border border-[var(--color-hairline-strong)] bg-[var(--color-surface)] px-2.5 py-1 font-mono text-[11px] text-[var(--color-fg-secondary)] hover:border-[var(--color-accent)] hover:text-[var(--color-accent-ink)] dark:hover:text-[var(--color-accent)]\"\r\n title={t(SUGGEST_KEY[s.reason])}\r\n >\r\n <span className=\"max-w-[20rem] truncate\">{s.cwd}</span>\r\n <span className=\"text-[var(--color-fg-faint)]\">· {t(SUGGEST_KEY[s.reason])}</span>\r\n </button>\r\n ))}\r\n </div>\r\n )}\r\n </div>\r\n\r\n {/* policy */}\r\n <div>\r\n <span className=\"eyebrow\">{t('import.policyLabel')}</span>\r\n <div className=\"mt-1.5 inline-flex flex-wrap gap-1 rounded-[var(--radius-input)] border border-[var(--color-hairline)] bg-[var(--color-sunken)] p-1\">\r\n {POLICIES.map((p) => (\r\n <button\r\n key={p}\r\n type=\"button\"\r\n onClick={() => changePolicy(p)}\r\n aria-pressed={policy === p}\r\n className={\r\n 'rounded-[var(--radius-control)] px-3 py-1.5 text-xs font-medium transition ' +\r\n (policy === p\r\n ? 'bg-[var(--color-surface)] text-[var(--color-fg-primary)] shadow-[var(--shadow-rise)]'\r\n : 'text-[var(--color-fg-muted)] hover:text-[var(--color-fg-primary)]')\r\n }\r\n >\r\n {t(POLICY_KEY[p])}\r\n </button>\r\n ))}\r\n </div>\r\n </div>\r\n\r\n {/* sessions */}\r\n <div>\r\n <div className=\"flex items-baseline justify-between\">\r\n <span className=\"eyebrow\">{t('import.sessions.heading')}</span>\r\n <span className=\"font-mono text-[11px] text-[var(--color-fg-faint)]\">\r\n {t('import.history', { n: preview.historyLinesToAdd })}\r\n </span>\r\n </div>\r\n {preview.sessions.length === 0 ? (\r\n <p className=\"mt-2 text-sm text-[var(--color-fg-muted)]\">\r\n {t('import.sessions.empty')}\r\n </p>\r\n ) : (\r\n <ul className=\"mt-2 space-y-1.5\">\r\n {preview.sessions.map((s) => (\r\n <li\r\n key={s.sessionId}\r\n className=\"flex items-center gap-3 rounded-md border border-[var(--color-hairline)] bg-[var(--color-canvas)] px-3 py-2\"\r\n >\r\n <span\r\n className={\r\n 'shrink-0 rounded-[var(--radius-control)] border px-2 py-0.5 text-[10px] font-medium uppercase tracking-[0.12em] ' +\r\n actionTone(s.action)\r\n }\r\n >\r\n {t(ACTION_KEY[s.action])}\r\n </span>\r\n <span className=\"min-w-0 flex-1\">\r\n <span className=\"block truncate text-sm text-[var(--color-fg-primary)]\">\r\n {s.title}\r\n </span>\r\n <span className=\"block truncate font-mono text-[10.5px] text-[var(--color-fg-faint)]\">\r\n {s.newSessionId ?? s.sessionId}\r\n </span>\r\n </span>\r\n {s.reason && (\r\n <span className=\"shrink-0 text-[11px] text-[var(--color-fg-muted)]\">\r\n {s.reason}\r\n </span>\r\n )}\r\n </li>\r\n ))}\r\n </ul>\r\n )}\r\n </div>\r\n\r\n {/* memory */}\r\n {preview.memory.length > 0 && (\r\n <div>\r\n <span className=\"eyebrow\">{t('import.memory.heading')}</span>\r\n <ul className=\"mt-2 flex flex-wrap gap-1.5\">\r\n {preview.memory.map((m) => (\r\n <li\r\n key={m.filename}\r\n className=\"inline-flex items-center gap-1.5 rounded-[var(--radius-control)] border border-[var(--color-hairline)] bg-[var(--color-canvas)] px-2.5 py-1 font-mono text-[11px] text-[var(--color-fg-secondary)]\"\r\n >\r\n <span className=\"text-[var(--color-fg-primary)]\">{m.filename}</span>\r\n <span className=\"text-[var(--color-fg-faint)]\">\r\n ·{' '}\r\n {m.action === 'conflict'\r\n ? t('import.memory.conflict', { name: m.writtenAs ?? '' })\r\n : t(MEM_KEY[m.action])}\r\n </span>\r\n </li>\r\n ))}\r\n </ul>\r\n </div>\r\n )}\r\n\r\n {commitMutation.error && (\r\n <p className=\"rounded-md border border-[var(--color-danger)]/40 bg-[var(--color-danger-soft)] px-3 py-2 text-sm text-[var(--color-danger)]\">\r\n {(commitMutation.error as Error).message}\r\n </p>\r\n )}\r\n\r\n {result ? (\r\n <div className=\"space-y-3 rounded-[var(--radius-card)] border border-[var(--color-moss)]/40 bg-[var(--color-moss-soft)] px-4 py-3\">\r\n <p className=\"font-display text-lg font-light text-[var(--color-fg-primary)]\">\r\n {t('import.result.title')}\r\n </p>\r\n <p className=\"text-sm text-[var(--color-fg-secondary)]\">\r\n {t('import.result.summary', {\r\n n: result.imported.length,\r\n skipped: result.skipped.length,\r\n memory: result.memoryWritten.length,\r\n lines: result.historyLinesAdded,\r\n })}\r\n </p>\r\n <Link\r\n to={`/projects/${encodeURIComponent(result.targetProjectId)}`}\r\n className=\"inline-flex w-fit items-center gap-2 rounded-[var(--radius-control)] bg-[var(--color-fg-primary)] px-4 py-1.5 text-sm font-medium text-[var(--color-canvas)] hover:opacity-90\"\r\n >\r\n {t('import.result.viewProject')}\r\n </Link>\r\n </div>\r\n ) : (\r\n <div className=\"flex justify-end border-t border-[var(--color-hairline)] pt-4\">\r\n <button\r\n type=\"button\"\r\n onClick={() => commitMutation.mutate()}\r\n disabled={targetCwd.trim() === '' || busy || commitMutation.isPending}\r\n className=\"rounded-[var(--radius-control)] bg-[var(--color-fg-primary)] px-5 py-2 text-sm font-medium text-[var(--color-canvas)] shadow-[var(--shadow-rise)] hover:opacity-90 disabled:cursor-not-allowed disabled:opacity-50\"\r\n >\r\n {commitMutation.isPending ? t('import.btn.committing') : t('import.btn.commit')}\r\n </button>\r\n </div>\r\n )}\r\n </div>\r\n )}\r\n </section>\r\n );\r\n}\r\n"],"names":["POLICIES","POLICY_KEY","ACTION_KEY","SUGGEST_KEY","MEM_KEY","actionTone","action","ImportPage","t","useT","queryClient","useQueryClient","bundleDir","setBundleDir","useState","targetCwd","setTargetCwd","policy","setPolicy","preview","setPreview","previewMutation","useMutation","vars","api","data","commitMutation","queryKeys","loadBundle","recheck","nextTarget","nextPolicy","changePolicy","p","result","busy","jsxs","jsx","PageHeader","e","s","m","Link"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ProjectMemory-Q4XX40j_.js","sources":["../../web/src/routes/ProjectMemory.tsx"],"sourcesContent":["import { useQuery } from '@tanstack/react-query';\r\nimport { useEffect, useMemo, useRef, useState } from 'react';\r\nimport { useParams, useSearchParams } from 'react-router-dom';\r\nimport Breadcrumbs, { BreadcrumbFolderIcon } from '../components/Breadcrumbs.tsx';\r\nimport { Loading } from '../components/Loading.tsx';\r\nimport PageHeader, { MetaItem, Sep } from '../components/PageHeader.tsx';\r\nimport {\r\n api,\r\n type MemoryEntry,\r\n type MemoryResponse,\r\n type MemoryType,\r\n type ProjectSummary,\r\n} from '../lib/api.ts';\r\nimport { formatBytes, formatRelativeTime } from '../lib/format.ts';\r\nimport { useT } from '../lib/i18n.ts';\r\nimport { queryKeys } from '../lib/query-keys.ts';\r\n\r\ntype GroupKey = MemoryType | 'other';\r\n\r\ninterface ParsedLink {\r\n title: string;\r\n href: string;\r\n hook: string;\r\n}\r\ninterface IndexLine {\r\n raw: string;\r\n link: ParsedLink | null;\r\n}\r\n\r\ntype Row =\r\n | { kind: 'entry'; entry: MemoryEntry; hook: string }\r\n | { kind: 'missing'; title: string; hook: string }\r\n | { kind: 'heading'; text: string }\r\n | { kind: 'text'; text: string }\r\n | { kind: 'spacer' };\r\n\r\nconst LINK_RE = /^[\\s*-]*\\[(?<title>[^\\]]+)\\]\\((?<href>[^)]+)\\)\\s*[—–\\-:]?\\s*(?<hook>.*)$/;\r\n\r\nexport default function ProjectMemoryRoute() {\r\n const t = useT();\r\n const { projectId } = useParams<{ projectId: string }>();\r\n const id = projectId ?? '';\r\n const [searchParams, setSearchParams] = useSearchParams();\r\n\r\n const memoryQuery = useQuery({\r\n queryKey: queryKeys.projectMemory(id),\r\n queryFn: () => api<MemoryResponse>(`/api/projects/${encodeURIComponent(id)}/memory`),\r\n enabled: !!id,\r\n });\r\n\r\n const projectsQuery = useQuery({\r\n queryKey: queryKeys.projects(),\r\n queryFn: () => api<ProjectSummary[]>('/api/projects'),\r\n });\r\n const project = useMemo(\r\n () => projectsQuery.data?.find((p) => p.id === id),\r\n [projectsQuery.data, id],\r\n );\r\n\r\n const data = memoryQuery.data;\r\n const entries = useMemo(() => data?.entries ?? [], [data?.entries]);\r\n const indexLines = useMemo(() => parseIndex(data?.index ?? null), [data?.index]);\r\n\r\n const hookByFilename = useMemo(() => {\r\n const m = new Map<string, string>();\r\n for (const line of indexLines) {\r\n if (line.link) m.set(line.link.href, line.link.hook);\r\n }\r\n return m;\r\n }, [indexLines]);\r\n\r\n const { rows, orphans } = useMemo(\r\n () => buildRows(indexLines, entries),\r\n [indexLines, entries],\r\n );\r\n\r\n // URL-driven drawer state\r\n const drawerEntry = searchParams.get('entry');\r\n const drawerView = searchParams.get('view');\r\n const drawerOpen = drawerEntry !== null || drawerView === 'raw';\r\n\r\n function openEntry(filename: string) {\r\n const next = new URLSearchParams(searchParams);\r\n next.set('entry', filename);\r\n next.delete('view');\r\n setSearchParams(next);\r\n }\r\n function openRaw() {\r\n const next = new URLSearchParams(searchParams);\r\n next.set('view', 'raw');\r\n next.delete('entry');\r\n setSearchParams(next);\r\n }\r\n function closeDrawer() {\r\n const next = new URLSearchParams(searchParams);\r\n next.delete('entry');\r\n next.delete('view');\r\n setSearchParams(next);\r\n }\r\n\r\n const drawerTarget = useMemo(() => {\r\n if (drawerView === 'raw') return { kind: 'raw' as const };\r\n if (drawerEntry) {\r\n const entry = entries.find((e) => e.filename === drawerEntry) ?? null;\r\n return { kind: 'entry' as const, entry, filename: drawerEntry };\r\n }\r\n return null;\r\n }, [drawerEntry, drawerView, entries]);\r\n\r\n const [query, setQuery] = useState('');\r\n const trimmed = query.trim().toLowerCase();\r\n const searchActive = trimmed.length > 0;\r\n\r\n const filteredRows: Row[] = useMemo(() => {\r\n if (!searchActive) return rows;\r\n return rows.filter((r) => r.kind === 'entry' && matchEntry(r.entry, r.hook, trimmed));\r\n }, [rows, searchActive, trimmed]);\r\n\r\n const filteredOrphans = useMemo(\r\n () => (searchActive ? orphans.filter((e) => matchEntry(e, '', trimmed)) : orphans),\r\n [orphans, searchActive, trimmed],\r\n );\r\n\r\n const totalEntries = entries.length;\r\n const indexAvailable = !!data?.index;\r\n const hasContent = totalEntries > 0 || indexAvailable;\r\n\r\n const totalMatched =\r\n filteredRows.filter((r) => r.kind === 'entry').length + filteredOrphans.length;\r\n\r\n const cwd = project?.decodedCwd ?? id;\r\n const parts = cwd.split(/[\\\\/]+/).filter(Boolean);\r\n const tail = parts.at(-1) ?? cwd;\r\n const head = parts.slice(0, -1).join('/');\r\n\r\n const lastUpdate = useMemo(() => {\r\n let latest: number | null = null;\r\n for (const e of entries) {\r\n if (!e.mtime) continue;\r\n const t = Date.parse(e.mtime);\r\n if (Number.isFinite(t) && (latest === null || t > latest)) latest = t;\r\n }\r\n return latest ? new Date(latest).toISOString() : null;\r\n }, [entries]);\r\n\r\n const typeCount = useMemo(() => {\r\n const s = new Set<GroupKey>();\r\n for (const e of entries) s.add((e.type ?? 'other') as GroupKey);\r\n return s.size;\r\n }, [entries]);\r\n\r\n return (\r\n <section>\r\n <Breadcrumbs\r\n items={[\r\n { label: t('session.crumbProjects'), to: '/' },\r\n {\r\n label: tail,\r\n to: `/projects/${encodeURIComponent(id)}`,\r\n mono: true,\r\n icon: <BreadcrumbFolderIcon />,\r\n },\r\n { label: t('memory.title') },\r\n ]}\r\n />\r\n\r\n <div className=\"surface-card mt-6 p-6\">\r\n <PageHeader\r\n eyebrow={\r\n <span className=\"inline-flex items-center gap-2\">\r\n {head ? (\r\n <span className=\"font-mono normal-case tracking-normal\">{head}/</span>\r\n ) : (\r\n t('memory.action.open')\r\n )}\r\n </span>\r\n }\r\n title={t('memory.title')}\r\n meta={\r\n data ? (\r\n <>\r\n <MetaItem label={t('memory.meta.entries')} value={totalEntries} />\r\n {typeCount > 0 && (\r\n <>\r\n <Sep />\r\n <MetaItem label={t('memory.meta.types')} value={typeCount} />\r\n </>\r\n )}\r\n {lastUpdate && (\r\n <>\r\n <Sep />\r\n <MetaItem\r\n label={t('memory.meta.lastUpdate')}\r\n value={formatRelativeTime(lastUpdate)}\r\n />\r\n </>\r\n )}\r\n </>\r\n ) : null\r\n }\r\n />\r\n </div>\r\n\r\n {memoryQuery.isLoading && <Loading label={t('memory.loading')} className=\"mt-6\" />}\r\n {memoryQuery.error && (\r\n <p className=\"mt-6 rounded-md border border-[var(--color-danger)]/40 bg-[var(--color-danger-soft)] px-4 py-3 text-sm text-[var(--color-danger)]\">\r\n {t('common.failedMemory')}: {(memoryQuery.error as Error).message}\r\n </p>\r\n )}\r\n\r\n {data && !hasContent && <EmptyState />}\r\n\r\n {data && hasContent && (\r\n <IndexCard\r\n rows={filteredRows}\r\n orphans={filteredOrphans}\r\n totalMatched={totalMatched}\r\n totalEntries={totalEntries}\r\n query={query}\r\n onQuery={setQuery}\r\n searchActive={searchActive}\r\n indexAvailable={indexAvailable}\r\n onOpenEntry={openEntry}\r\n onOpenRaw={openRaw}\r\n />\r\n )}\r\n\r\n {drawerOpen && drawerTarget && (\r\n <Drawer\r\n target={drawerTarget}\r\n rawIndex={data?.index ?? ''}\r\n hookForEntry={\r\n drawerTarget.kind === 'entry' && drawerTarget.entry\r\n ? hookByFilename.get(drawerTarget.entry.filename) ?? null\r\n : null\r\n }\r\n onClose={closeDrawer}\r\n onJumpToCover={() => {\r\n closeDrawer();\r\n requestAnimationFrame(() => {\r\n const cover = document.getElementById('memo-index-card');\r\n cover?.scrollIntoView({ behavior: 'smooth', block: 'start' });\r\n });\r\n }}\r\n />\r\n )}\r\n </section>\r\n );\r\n}\r\n\r\nfunction IndexCard({\r\n rows,\r\n orphans,\r\n totalMatched,\r\n totalEntries,\r\n query,\r\n onQuery,\r\n searchActive,\r\n indexAvailable,\r\n onOpenEntry,\r\n onOpenRaw,\r\n}: {\r\n rows: Row[];\r\n orphans: MemoryEntry[];\r\n totalMatched: number;\r\n totalEntries: number;\r\n query: string;\r\n onQuery: (v: string) => void;\r\n searchActive: boolean;\r\n indexAvailable: boolean;\r\n onOpenEntry: (filename: string) => void;\r\n onOpenRaw: () => void;\r\n}) {\r\n const t = useT();\r\n const noResults = searchActive && totalMatched === 0;\r\n\r\n return (\r\n <div id=\"memo-index-card\" className=\"surface-card mt-6 px-7 py-6\">\r\n <div className=\"flex items-baseline justify-between gap-3\">\r\n <div>\r\n <div className=\"eyebrow\">{t('memory.cover.title')}</div>\r\n <h2 className=\"mt-0.5 font-display text-[18px] font-medium tracking-tight text-[var(--color-fg-primary)]\">\r\n {t('memory.cover.subtitle')}\r\n </h2>\r\n </div>\r\n {indexAvailable && (\r\n <button\r\n type=\"button\"\r\n onClick={onOpenRaw}\r\n className=\"font-mono text-[11px] uppercase tracking-[0.16em] text-[var(--color-fg-muted)] hover:text-[var(--color-accent-ink)] dark:hover:text-[var(--color-accent)]\"\r\n >\r\n {t('memory.cover.viewRaw')} ↗\r\n </button>\r\n )}\r\n </div>\r\n\r\n <div className=\"mt-4 flex flex-wrap items-center gap-3\">\r\n <div className=\"flex flex-1 min-w-[14rem] items-center gap-2 border-b border-[var(--color-hairline)] py-1.5 transition focus-within:border-[var(--color-accent)]\">\r\n <SearchIcon className=\"text-[var(--color-fg-muted)]\" />\r\n <input\r\n type=\"search\"\r\n value={query}\r\n onChange={(e) => onQuery(e.target.value)}\r\n placeholder={t('memory.search.placeholder')}\r\n className=\"w-full bg-transparent text-sm text-[var(--color-fg-primary)] placeholder:text-[var(--color-fg-faint)] focus:outline-none\"\r\n />\r\n </div>\r\n <span className=\"font-mono text-[10.5px] uppercase tracking-[0.18em] tabular-nums text-[var(--color-fg-faint)]\">\r\n {searchActive\r\n ? t('memory.list.count', { n: totalMatched, total: totalEntries })\r\n : `${totalEntries} ${t('memory.meta.entries').toLowerCase()}`}\r\n </span>\r\n </div>\r\n\r\n <div className=\"rule-dotted mt-5\" aria-hidden />\r\n\r\n {noResults ? (\r\n <p className=\"mt-6 text-sm text-[var(--color-fg-muted)]\">{t('memory.list.noResults')}</p>\r\n ) : (\r\n <ul className=\"mt-3\">\r\n {rows.map((row, i) => (\r\n <RowItem key={i} row={row} onOpenEntry={onOpenEntry} />\r\n ))}\r\n\r\n {orphans.length > 0 && (\r\n <>\r\n {!searchActive && rows.length > 0 && (\r\n <li aria-hidden className=\"h-3\" />\r\n )}\r\n <li className=\"pt-3 pb-2\">\r\n <div className=\"flex items-baseline gap-3\">\r\n <span className=\"font-mono text-[10.5px] uppercase tracking-[0.18em] text-[var(--color-fg-faint)]\">\r\n {t('memory.cover.orphan')}\r\n </span>\r\n <span className=\"font-mono text-[10.5px] tabular-nums text-[var(--color-fg-faint)]\">\r\n · {orphans.length}\r\n </span>\r\n <span aria-hidden className=\"ml-2 h-px flex-1 bg-[var(--color-hairline)]\" />\r\n </div>\r\n </li>\r\n {orphans.map((e) => (\r\n <RowItem\r\n key={e.filename}\r\n row={{ kind: 'entry', entry: e, hook: '' }}\r\n onOpenEntry={onOpenEntry}\r\n />\r\n ))}\r\n </>\r\n )}\r\n </ul>\r\n )}\r\n </div>\r\n );\r\n}\r\n\r\nfunction RowItem({\r\n row,\r\n onOpenEntry,\r\n}: {\r\n row: Row;\r\n onOpenEntry: (filename: string) => void;\r\n}) {\r\n const t = useT();\r\n\r\n if (row.kind === 'spacer') {\r\n return <li aria-hidden className=\"h-2\" />;\r\n }\r\n if (row.kind === 'heading') {\r\n return (\r\n <li className=\"pt-4 pb-1\">\r\n <div className=\"font-mono text-[10.5px] uppercase tracking-[0.18em] text-[var(--color-fg-muted)]\">\r\n {row.text}\r\n </div>\r\n </li>\r\n );\r\n }\r\n if (row.kind === 'text') {\r\n return (\r\n <li className=\"px-1 py-0.5 text-[12.5px] text-[var(--color-fg-faint)] whitespace-pre-wrap break-words\">\r\n {row.text}\r\n </li>\r\n );\r\n }\r\n if (row.kind === 'missing') {\r\n return (\r\n <li\r\n title={t('memory.cover.missingTooltip')}\r\n className=\"flex items-baseline gap-3 px-2 py-1.5 text-[var(--color-fg-faint)]\"\r\n >\r\n <span className=\"text-[14px] font-medium line-through decoration-[var(--color-fg-faint)]/50\">\r\n {row.title}\r\n </span>\r\n {row.hook && <span className=\"truncate text-[12px]\">{row.hook}</span>}\r\n </li>\r\n );\r\n }\r\n\r\n const entry = row.entry;\r\n const typeKey: GroupKey = entry.type ?? 'other';\r\n const title = entry.name ?? entry.filename;\r\n const hookText = row.hook || entry.description || '';\r\n return (\r\n <li>\r\n <button\r\n type=\"button\"\r\n onClick={() => onOpenEntry(entry.filename)}\r\n className={`memo-row memo-type-${typeKey}`}\r\n >\r\n <span aria-hidden className=\"memo-row-dot\" />\r\n <div className=\"memo-row-content\">\r\n <div className=\"memo-row-headline\">\r\n <span className=\"memo-row-title\">{title}</span>\r\n {entry.mtime && (\r\n <span className=\"memo-row-meta-inline\">{formatRelativeTime(entry.mtime)}</span>\r\n )}\r\n <TypeChip k={typeKey} />\r\n </div>\r\n {hookText && <p className=\"memo-row-hook\">{hookText}</p>}\r\n </div>\r\n <span aria-hidden className=\"memo-row-chevron\">↗</span>\r\n </button>\r\n </li>\r\n );\r\n}\r\n\r\nfunction TypeChip({ k }: { k: GroupKey }) {\r\n const t = useT();\r\n const label =\r\n k === 'user'\r\n ? t('memory.type.user')\r\n : k === 'feedback'\r\n ? t('memory.type.feedback')\r\n : k === 'project'\r\n ? t('memory.type.project')\r\n : k === 'reference'\r\n ? t('memory.type.reference')\r\n : t('memory.type.other');\r\n return <span className=\"memo-chip\">{label}</span>;\r\n}\r\n\r\ntype DrawerTarget =\r\n | { kind: 'entry'; entry: MemoryEntry | null; filename: string }\r\n | { kind: 'raw' };\r\n\r\nfunction Drawer({\r\n target,\r\n rawIndex,\r\n hookForEntry,\r\n onClose,\r\n onJumpToCover,\r\n}: {\r\n target: DrawerTarget;\r\n rawIndex: string;\r\n hookForEntry: string | null;\r\n onClose: () => void;\r\n onJumpToCover: () => void;\r\n}) {\r\n const t = useT();\r\n const panelRef = useRef<HTMLDivElement | null>(null);\r\n\r\n useEffect(() => {\r\n const onKey = (e: KeyboardEvent) => {\r\n if (e.key === 'Escape') {\r\n e.preventDefault();\r\n onClose();\r\n }\r\n };\r\n window.addEventListener('keydown', onKey);\r\n const prevOverflow = document.body.style.overflow;\r\n document.body.style.overflow = 'hidden';\r\n requestAnimationFrame(() => panelRef.current?.focus());\r\n return () => {\r\n window.removeEventListener('keydown', onKey);\r\n document.body.style.overflow = prevOverflow;\r\n };\r\n }, [onClose]);\r\n\r\n const typeKey: GroupKey =\r\n target.kind === 'entry' ? (target.entry?.type ?? 'other') : 'reference';\r\n\r\n return (\r\n <>\r\n <div className=\"memo-drawer-backdrop\" onClick={onClose} aria-hidden />\r\n <div\r\n ref={panelRef}\r\n role=\"dialog\"\r\n aria-modal=\"true\"\r\n tabIndex={-1}\r\n className={`memo-drawer-panel memo-type-${typeKey} focus:outline-none`}\r\n >\r\n <div className=\"flex items-start justify-between gap-3 border-b border-[var(--color-hairline)] px-7 pt-7 pb-5\">\r\n <div className=\"min-w-0 flex-1\">\r\n {target.kind === 'entry' ? (\r\n <>\r\n <TypeChip k={typeKey} />\r\n {target.entry ? (\r\n <>\r\n <h2 className=\"mt-3 font-display text-[24px] font-light leading-tight tracking-tight text-[var(--color-fg-primary)]\">\r\n {target.entry.name ?? target.entry.filename}\r\n </h2>\r\n <p className=\"mt-1.5 font-mono text-[11px] uppercase tracking-[0.16em] text-[var(--color-fg-faint)]\">\r\n {target.entry.filename} · {formatBytes(target.entry.bytes)}\r\n {target.entry.mtime ? ` · ${formatRelativeTime(target.entry.mtime)}` : ''}\r\n </p>\r\n </>\r\n ) : (\r\n <>\r\n <h2 className=\"mt-3 font-display text-[22px] font-light leading-tight text-[var(--color-fg-primary)]\">\r\n {t('memory.drawer.notFound.title')}\r\n </h2>\r\n <p className=\"mt-1.5 font-mono text-[11px] uppercase tracking-[0.16em] text-[var(--color-fg-faint)]\">\r\n {target.filename}\r\n </p>\r\n </>\r\n )}\r\n </>\r\n ) : (\r\n <>\r\n <span className=\"memo-chip memo-type-reference\">{t('memory.cover.title')}</span>\r\n <h2 className=\"mt-3 font-display text-[24px] font-light leading-tight tracking-tight text-[var(--color-fg-primary)]\">\r\n {t('memory.raw.title')}\r\n </h2>\r\n <p className=\"mt-1.5 font-mono text-[11px] uppercase tracking-[0.16em] text-[var(--color-fg-faint)]\">\r\n {t('memory.raw.subtitle')}\r\n </p>\r\n </>\r\n )}\r\n </div>\r\n <button\r\n type=\"button\"\r\n onClick={onClose}\r\n aria-label={t('memory.drawer.close')}\r\n className=\"rounded-md p-2 text-[var(--color-fg-muted)] hover:bg-[var(--color-sunken)] hover:text-[var(--color-fg-primary)]\"\r\n >\r\n <CloseIcon />\r\n </button>\r\n </div>\r\n\r\n <div className=\"flex-1 overflow-y-auto px-7 py-6\">\r\n {target.kind === 'entry' && target.entry ? (\r\n <EntryDrawerBody\r\n entry={target.entry}\r\n hookForEntry={hookForEntry}\r\n onJumpToCover={onJumpToCover}\r\n />\r\n ) : target.kind === 'entry' ? (\r\n <NotFoundDrawerBody filename={target.filename} onJumpToCover={onJumpToCover} />\r\n ) : (\r\n <RawDrawerBody source={rawIndex} />\r\n )}\r\n </div>\r\n </div>\r\n </>\r\n );\r\n}\r\n\r\nfunction EntryDrawerBody({\r\n entry,\r\n hookForEntry,\r\n onJumpToCover,\r\n}: {\r\n entry: MemoryEntry;\r\n hookForEntry: string | null;\r\n onJumpToCover: () => void;\r\n}) {\r\n const t = useT();\r\n const body = entry.body.trim();\r\n return (\r\n <div>\r\n {entry.description && (\r\n <p className=\"text-[14px] text-[var(--color-fg-secondary)]\">{entry.description}</p>\r\n )}\r\n <pre\r\n className={\r\n 'whitespace-pre-wrap break-words rounded-[var(--radius-input)] border border-[var(--color-hairline)] bg-[var(--color-sunken)] px-4 py-3 font-mono text-[12.5px] leading-[1.65] text-[var(--color-fg-primary)] ' +\r\n (entry.description ? 'mt-5' : '')\r\n }\r\n >\r\n {body || '—'}\r\n </pre>\r\n {hookForEntry && (\r\n <div className=\"mt-7\">\r\n <div className=\"rule-dotted\" aria-hidden />\r\n <div className=\"mt-4 flex items-baseline justify-between gap-3\">\r\n <div className=\"eyebrow\">{t('memory.drawer.indexHook')}</div>\r\n <button\r\n type=\"button\"\r\n onClick={onJumpToCover}\r\n className=\"font-mono text-[10.5px] uppercase tracking-[0.16em] text-[var(--color-fg-muted)] hover:text-[var(--color-accent-ink)] dark:hover:text-[var(--color-accent)]\"\r\n >\r\n {t('memory.cover.title')} ↑\r\n </button>\r\n </div>\r\n <p className=\"mt-1.5 text-[13px] text-[var(--color-fg-secondary)]\">{hookForEntry}</p>\r\n </div>\r\n )}\r\n </div>\r\n );\r\n}\r\n\r\nfunction NotFoundDrawerBody({\r\n filename,\r\n onJumpToCover,\r\n}: {\r\n filename: string;\r\n onJumpToCover: () => void;\r\n}) {\r\n const t = useT();\r\n return (\r\n <div>\r\n <p className=\"text-sm text-[var(--color-fg-secondary)]\">{t('memory.drawer.notFound.body')}</p>\r\n <p className=\"mt-3 font-mono text-[12px] text-[var(--color-fg-faint)]\">{filename}</p>\r\n <button\r\n type=\"button\"\r\n onClick={onJumpToCover}\r\n className=\"mt-5 inline-flex items-center gap-1.5 rounded-[var(--radius-control)] border border-[var(--color-hairline)] px-3 py-1.5 text-[11px] font-medium uppercase tracking-[0.14em] text-[var(--color-fg-secondary)] hover:border-[var(--color-hairline-strong)] hover:text-[var(--color-fg-primary)]\"\r\n >\r\n {t('memory.cover.title')} ↑\r\n </button>\r\n </div>\r\n );\r\n}\r\n\r\nfunction RawDrawerBody({ source }: { source: string }) {\r\n const body = source.trim();\r\n return (\r\n <pre className=\"whitespace-pre-wrap break-words rounded-[var(--radius-input)] border border-[var(--color-hairline)] bg-[var(--color-sunken)] px-4 py-3 font-mono text-[12.5px] leading-[1.65] text-[var(--color-fg-primary)]\">\r\n {body || '—'}\r\n </pre>\r\n );\r\n}\r\n\r\nfunction EmptyState() {\r\n const t = useT();\r\n return (\r\n <div className=\"surface-card mt-6 px-8 py-14 text-center\">\r\n <div className=\"mx-auto flex h-12 w-12 items-center justify-center rounded-full border border-[var(--color-hairline)] bg-[var(--color-sunken)] text-[var(--color-fg-muted)]\">\r\n <BookmarkIcon />\r\n </div>\r\n <h2 className=\"mt-5 font-display text-[20px] font-light tracking-tight text-[var(--color-fg-primary)]\">\r\n {t('memory.empty.title')}\r\n </h2>\r\n <p className=\"mx-auto mt-3 max-w-xl text-[13px] leading-relaxed text-[var(--color-fg-secondary)]\">\r\n {t('memory.empty.body')}\r\n </p>\r\n </div>\r\n );\r\n}\r\n\r\nfunction SearchIcon({ className = '' }: { className?: string }) {\r\n return (\r\n <svg\r\n width=\"14\"\r\n height=\"14\"\r\n viewBox=\"0 0 24 24\"\r\n fill=\"none\"\r\n stroke=\"currentColor\"\r\n strokeWidth=\"1.7\"\r\n strokeLinecap=\"round\"\r\n className={className}\r\n aria-hidden\r\n >\r\n <circle cx=\"11\" cy=\"11\" r=\"6.2\" />\r\n <path d=\"M20 20l-4.3-4.3\" />\r\n </svg>\r\n );\r\n}\r\n\r\nfunction CloseIcon() {\r\n return (\r\n <svg\r\n width=\"16\"\r\n height=\"16\"\r\n viewBox=\"0 0 24 24\"\r\n fill=\"none\"\r\n stroke=\"currentColor\"\r\n strokeWidth=\"1.8\"\r\n strokeLinecap=\"round\"\r\n aria-hidden\r\n >\r\n <path d=\"M6 6l12 12M18 6L6 18\" />\r\n </svg>\r\n );\r\n}\r\n\r\nfunction BookmarkIcon() {\r\n return (\r\n <svg\r\n width=\"20\"\r\n height=\"20\"\r\n viewBox=\"0 0 24 24\"\r\n fill=\"none\"\r\n stroke=\"currentColor\"\r\n strokeWidth=\"1.6\"\r\n strokeLinecap=\"round\"\r\n strokeLinejoin=\"round\"\r\n aria-hidden\r\n >\r\n <path d=\"M6 4h12v17l-6-4-6 4z\" />\r\n </svg>\r\n );\r\n}\r\n\r\nfunction matchEntry(entry: MemoryEntry, hook: string, q: string): boolean {\r\n const fields = [\r\n entry.name ?? '',\r\n entry.filename,\r\n entry.description ?? '',\r\n entry.body,\r\n hook,\r\n ];\r\n return fields.some((f) => f.toLowerCase().includes(q));\r\n}\r\n\r\nfunction buildRows(\r\n indexLines: IndexLine[],\r\n entries: MemoryEntry[],\r\n): { rows: Row[]; orphans: MemoryEntry[] } {\r\n const filenameToEntry = new Map(entries.map((e) => [e.filename, e]));\r\n const seen = new Set<string>();\r\n const rows: Row[] = [];\r\n\r\n for (const line of indexLines) {\r\n if (line.link) {\r\n const entry = filenameToEntry.get(line.link.href);\r\n if (entry) {\r\n rows.push({ kind: 'entry', entry, hook: line.link.hook });\r\n seen.add(entry.filename);\r\n } else {\r\n rows.push({ kind: 'missing', title: line.link.title, hook: line.link.hook });\r\n }\r\n continue;\r\n }\r\n const txt = line.raw.trim();\r\n if (!txt) {\r\n rows.push({ kind: 'spacer' });\r\n continue;\r\n }\r\n const headingMatch = /^(#{1,6})\\s+(.+?)\\s*$/.exec(txt);\r\n if (headingMatch) {\r\n rows.push({ kind: 'heading', text: headingMatch[2]! });\r\n } else {\r\n rows.push({ kind: 'text', text: line.raw });\r\n }\r\n }\r\n\r\n const orphans = entries.filter((e) => !seen.has(e.filename));\r\n return { rows, orphans };\r\n}\r\n\r\nfunction parseIndex(raw: string | null): IndexLine[] {\r\n if (!raw) return [];\r\n const out: IndexLine[] = [];\r\n for (const rawLine of raw.split(/\\r?\\n/)) {\r\n const line = rawLine.trimEnd();\r\n if (line.trim() === '') {\r\n const last = out[out.length - 1];\r\n if (last && (last.link || last.raw.trim() !== '')) {\r\n out.push({ raw: '', link: null });\r\n }\r\n continue;\r\n }\r\n const m = LINK_RE.exec(line);\r\n const title = m?.groups?.title;\r\n const href = m?.groups?.href;\r\n if (m && title && href) {\r\n out.push({\r\n raw: line,\r\n link: { title: title.trim(), href: href.trim(), hook: (m.groups?.hook ?? '').trim() },\r\n });\r\n } else {\r\n out.push({ raw: line, link: null });\r\n }\r\n }\r\n while (out.length > 0) {\r\n const last = out[out.length - 1];\r\n if (last && !last.link && last.raw.trim() === '') out.pop();\r\n else break;\r\n }\r\n return out;\r\n}\r\n"],"names":["LINK_RE","ProjectMemoryRoute","useT","projectId","useParams","id","searchParams","setSearchParams","useSearchParams","memoryQuery","useQuery","queryKeys","api","projectsQuery","project","useMemo","_a","data","entries","indexLines","parseIndex","hookByFilename","m","line","rows","orphans","buildRows","drawerEntry","drawerView","drawerOpen","openEntry","filename","next","openRaw","closeDrawer","drawerTarget","e","query","setQuery","useState","trimmed","searchActive","filteredRows","r","matchEntry","filteredOrphans","totalEntries","indexAvailable","hasContent","totalMatched","cwd","parts","tail","head","lastUpdate","latest","t","typeCount","s","jsx","Breadcrumbs","BreadcrumbFolderIcon","PageHeader","jsxs","Fragment","MetaItem","Sep","formatRelativeTime","Loading","EmptyState","IndexCard","Drawer","cover","onQuery","onOpenEntry","onOpenRaw","noResults","SearchIcon","row","i","RowItem","entry","typeKey","title","hookText","TypeChip","k","label","target","rawIndex","hookForEntry","onClose","onJumpToCover","panelRef","useRef","useEffect","onKey","prevOverflow","formatBytes","CloseIcon","EntryDrawerBody","NotFoundDrawerBody","RawDrawerBody","body","source","BookmarkIcon","className","hook","q","f","filenameToEntry","seen","txt","headingMatch","raw","out","rawLine","last","href","_b","_c"],"mappings":"uRAoCA,MAAMA,GAAU,2EAEhB,SAAwBC,IAAqB,CAC3C,MAAM,EAAIC,EAAA,EACJ,CAAE,UAAAC,CAAA,EAAcC,GAAA,EAChBC,EAAKF,GAAa,GAClB,CAACG,EAAcC,CAAe,EAAIC,GAAA,EAElCC,EAAcC,EAAS,CAC3B,SAAUC,EAAU,cAAcN,CAAE,EACpC,QAAS,IAAMO,EAAoB,iBAAiB,mBAAmBP,CAAE,CAAC,SAAS,EACnF,QAAS,CAAC,CAACA,CAAA,CACZ,EAEKQ,EAAgBH,EAAS,CAC7B,SAAUC,EAAU,SAAA,EACpB,QAAS,IAAMC,EAAsB,eAAe,CAAA,CACrD,EACKE,EAAUC,EAAAA,QACd,IAAA,OAAM,OAAAC,EAAAH,EAAc,OAAd,YAAAG,EAAoB,KAAM,GAAM,EAAE,KAAOX,IAC/C,CAACQ,EAAc,KAAMR,CAAE,CAAA,EAGnBY,EAAOR,EAAY,KACnBS,EAAUH,EAAAA,QAAQ,KAAME,GAAA,YAAAA,EAAM,UAAW,GAAI,CAACA,GAAA,YAAAA,EAAM,OAAO,CAAC,EAC5DE,EAAaJ,EAAAA,QAAQ,IAAMK,IAAWH,GAAA,YAAAA,EAAM,QAAS,IAAI,EAAG,CAACA,GAAA,YAAAA,EAAM,KAAK,CAAC,EAEzEI,EAAiBN,EAAAA,QAAQ,IAAM,CACnC,MAAMO,MAAQ,IACd,UAAWC,KAAQJ,EACbI,EAAK,MAAMD,EAAE,IAAIC,EAAK,KAAK,KAAMA,EAAK,KAAK,IAAI,EAErD,OAAOD,CACT,EAAG,CAACH,CAAU,CAAC,EAET,CAAE,KAAAK,EAAM,QAAAC,CAAA,EAAYV,EAAAA,QACxB,IAAMW,GAAUP,EAAYD,CAAO,EACnC,CAACC,EAAYD,CAAO,CAAA,EAIhBS,EAAcrB,EAAa,IAAI,OAAO,EACtCsB,EAAatB,EAAa,IAAI,MAAM,EACpCuB,EAAaF,IAAgB,MAAQC,IAAe,MAE1D,SAASE,EAAUC,EAAkB,CACnC,MAAMC,EAAO,IAAI,gBAAgB1B,CAAY,EAC7C0B,EAAK,IAAI,QAASD,CAAQ,EAC1BC,EAAK,OAAO,MAAM,EAClBzB,EAAgByB,CAAI,CACtB,CACA,SAASC,GAAU,CACjB,MAAMD,EAAO,IAAI,gBAAgB1B,CAAY,EAC7C0B,EAAK,IAAI,OAAQ,KAAK,EACtBA,EAAK,OAAO,OAAO,EACnBzB,EAAgByB,CAAI,CACtB,CACA,SAASE,GAAc,CACrB,MAAMF,EAAO,IAAI,gBAAgB1B,CAAY,EAC7C0B,EAAK,OAAO,OAAO,EACnBA,EAAK,OAAO,MAAM,EAClBzB,EAAgByB,CAAI,CACtB,CAEA,MAAMG,EAAepB,EAAAA,QAAQ,IACvBa,IAAe,MAAc,CAAE,KAAM,KAAA,EACrCD,EAEK,CAAE,KAAM,QAAkB,MADnBT,EAAQ,KAAMkB,GAAMA,EAAE,WAAaT,CAAW,GAAK,KACzB,SAAUA,CAAA,EAE7C,KACN,CAACA,EAAaC,EAAYV,CAAO,CAAC,EAE/B,CAACmB,EAAOC,CAAQ,EAAIC,EAAAA,SAAS,EAAE,EAC/BC,EAAUH,EAAM,KAAA,EAAO,YAAA,EACvBI,EAAeD,EAAQ,OAAS,EAEhCE,EAAsB3B,EAAAA,QAAQ,IAC7B0B,EACEjB,EAAK,OAAQmB,GAAMA,EAAE,OAAS,SAAWC,EAAWD,EAAE,MAAOA,EAAE,KAAMH,CAAO,CAAC,EAD1DhB,EAEzB,CAACA,EAAMiB,EAAcD,CAAO,CAAC,EAE1BK,EAAkB9B,EAAAA,QACtB,IAAO0B,EAAehB,EAAQ,OAAQW,GAAMQ,EAAWR,EAAG,GAAII,CAAO,CAAC,EAAIf,EAC1E,CAACA,EAASgB,EAAcD,CAAO,CAAA,EAG3BM,EAAe5B,EAAQ,OACvB6B,EAAiB,CAAC,EAAC9B,GAAA,MAAAA,EAAM,OACzB+B,EAAaF,EAAe,GAAKC,EAEjCE,EACJP,EAAa,OAAQC,GAAMA,EAAE,OAAS,OAAO,EAAE,OAASE,EAAgB,OAEpEK,GAAMpC,GAAA,YAAAA,EAAS,aAAcT,EAC7B8C,EAAQD,EAAI,MAAM,QAAQ,EAAE,OAAO,OAAO,EAC1CE,EAAOD,EAAM,GAAG,EAAE,GAAKD,EACvBG,EAAOF,EAAM,MAAM,EAAG,EAAE,EAAE,KAAK,GAAG,EAElCG,EAAavC,EAAAA,QAAQ,IAAM,CAC/B,IAAIwC,EAAwB,KAC5B,UAAWnB,KAAKlB,EAAS,CACvB,GAAI,CAACkB,EAAE,MAAO,SACd,MAAMoB,EAAI,KAAK,MAAMpB,EAAE,KAAK,EACxB,OAAO,SAASoB,CAAC,IAAMD,IAAW,MAAQC,EAAID,KAASA,EAASC,EACtE,CACA,OAAOD,EAAS,IAAI,KAAKA,CAAM,EAAE,cAAgB,IACnD,EAAG,CAACrC,CAAO,CAAC,EAENuC,EAAY1C,EAAAA,QAAQ,IAAM,CAC9B,MAAM2C,MAAQ,IACd,UAAWtB,KAAKlB,EAASwC,EAAE,IAAKtB,EAAE,MAAQ,OAAoB,EAC9D,OAAOsB,EAAE,IACX,EAAG,CAACxC,CAAO,CAAC,EAEZ,cACG,UAAA,CACC,SAAA,CAAAyC,EAAAA,IAACC,EAAA,CACC,MAAO,CACL,CAAE,MAAO,EAAE,uBAAuB,EAAG,GAAI,GAAA,EACzC,CACE,MAAOR,EACP,GAAI,aAAa,mBAAmB/C,CAAE,CAAC,GACvC,KAAM,GACN,WAAOwD,EAAA,CAAA,CAAqB,CAAA,EAE9B,CAAE,MAAO,EAAE,cAAc,CAAA,CAAE,CAC7B,CAAA,EAGFF,EAAAA,IAAC,MAAA,CAAI,UAAU,wBACb,SAAAA,EAAAA,IAACG,GAAA,CACC,cACG,OAAA,CAAK,UAAU,iCACb,SAAAT,EACCU,EAAAA,KAAC,OAAA,CAAK,UAAU,wCAAyC,SAAA,CAAAV,EAAK,GAAA,CAAA,CAAC,EAE/D,EAAE,oBAAoB,EAE1B,EAEF,MAAO,EAAE,cAAc,EACvB,KACEpC,EACE8C,EAAAA,KAAAC,EAAAA,SAAA,CACE,SAAA,CAAAL,MAACM,GAAS,MAAO,EAAE,qBAAqB,EAAG,MAAOnB,EAAc,EAC/DW,EAAY,GACXM,EAAAA,KAAAC,EAAAA,SAAA,CACE,SAAA,CAAAL,EAAAA,IAACO,EAAA,EAAI,QACJD,EAAA,CAAS,MAAO,EAAE,mBAAmB,EAAG,MAAOR,CAAA,CAAW,CAAA,EAC7D,EAEDH,GACCS,EAAAA,KAAAC,WAAA,CACE,SAAA,CAAAL,EAAAA,IAACO,EAAA,EAAI,EACLP,EAAAA,IAACM,EAAA,CACC,MAAO,EAAE,wBAAwB,EACjC,MAAOE,EAAmBb,CAAU,CAAA,CAAA,CACtC,CAAA,CACF,CAAA,CAAA,CAEJ,EACE,IAAA,CAAA,EAGV,EAEC7C,EAAY,WAAakD,MAACS,GAAA,CAAQ,MAAO,EAAE,gBAAgB,EAAG,UAAU,OAAO,EAC/E3D,EAAY,OACXsD,OAAC,IAAA,CAAE,UAAU,oIACV,SAAA,CAAA,EAAE,qBAAqB,EAAE,KAAItD,EAAY,MAAgB,OAAA,EAC5D,EAGDQ,GAAQ,CAAC+B,GAAcW,MAACU,GAAA,CAAA,CAAW,EAEnCpD,GAAQ+B,GACPW,EAAAA,IAACW,GAAA,CACC,KAAM5B,EACN,QAASG,EACT,aAAAI,EACA,aAAAH,EACA,MAAAT,EACA,QAASC,EACT,aAAAG,EACA,eAAAM,EACA,YAAajB,EACb,UAAWG,CAAA,CAAA,EAIdJ,GAAcM,GACbwB,EAAAA,IAACY,GAAA,CACC,OAAQpC,EACR,UAAUlB,GAAA,YAAAA,EAAM,QAAS,GACzB,aACEkB,EAAa,OAAS,SAAWA,EAAa,MAC1Cd,EAAe,IAAIc,EAAa,MAAM,QAAQ,GAAK,KACnD,KAEN,QAASD,EACT,cAAe,IAAM,CACnBA,EAAA,EACA,sBAAsB,IAAM,CAC1B,MAAMsC,EAAQ,SAAS,eAAe,iBAAiB,EACvDA,GAAA,MAAAA,EAAO,eAAe,CAAE,SAAU,SAAU,MAAO,SACrD,CAAC,CACH,CAAA,CAAA,CACF,EAEJ,CAEJ,CAEA,SAASF,GAAU,CACjB,KAAA9C,EACA,QAAAC,EACA,aAAAwB,EACA,aAAAH,EACA,MAAAT,EACA,QAAAoC,EACA,aAAAhC,EACA,eAAAM,EACA,YAAA2B,EACA,UAAAC,CACF,EAWG,CACD,MAAMnB,EAAItD,EAAA,EACJ0E,EAAYnC,GAAgBQ,IAAiB,EAEnD,OACEc,EAAAA,KAAC,MAAA,CAAI,GAAG,kBAAkB,UAAU,8BAClC,SAAA,CAAAA,EAAAA,KAAC,MAAA,CAAI,UAAU,4CACb,SAAA,CAAAA,OAAC,MAAA,CACC,SAAA,CAAAJ,MAAC,MAAA,CAAI,UAAU,UAAW,SAAAH,EAAE,oBAAoB,EAAE,QACjD,KAAA,CAAG,UAAU,4FACX,SAAAA,EAAE,uBAAuB,CAAA,CAC5B,CAAA,EACF,EACCT,GACCgB,EAAAA,KAAC,SAAA,CACC,KAAK,SACL,QAASY,EACT,UAAU,4JAET,SAAA,CAAAnB,EAAE,sBAAsB,EAAE,IAAA,CAAA,CAAA,CAC7B,EAEJ,EAEAO,EAAAA,KAAC,MAAA,CAAI,UAAU,yCACb,SAAA,CAAAA,EAAAA,KAAC,MAAA,CAAI,UAAU,mJACb,SAAA,CAAAJ,EAAAA,IAACkB,GAAA,CAAW,UAAU,8BAAA,CAA+B,EACrDlB,EAAAA,IAAC,QAAA,CACC,KAAK,SACL,MAAOtB,EACP,SAAWD,GAAMqC,EAAQrC,EAAE,OAAO,KAAK,EACvC,YAAaoB,EAAE,2BAA2B,EAC1C,UAAU,0HAAA,CAAA,CACZ,EACF,EACAG,MAAC,QAAK,UAAU,gGACb,WACGH,EAAE,oBAAqB,CAAE,EAAGP,EAAc,MAAOH,EAAc,EAC/D,GAAGA,CAAY,IAAIU,EAAE,qBAAqB,EAAE,YAAA,CAAa,EAAA,CAC/D,CAAA,EACF,EAEAG,EAAAA,IAAC,MAAA,CAAI,UAAU,mBAAmB,cAAW,GAAC,EAE7CiB,EACCjB,EAAAA,IAAC,IAAA,CAAE,UAAU,4CAA6C,SAAAH,EAAE,uBAAuB,CAAA,CAAE,EAErFO,EAAAA,KAAC,KAAA,CAAG,UAAU,OACX,SAAA,CAAAvC,EAAK,IAAI,CAACsD,EAAKC,UACbC,EAAA,CAAgB,IAAAF,EAAU,YAAAJ,CAAA,EAAbK,CAAuC,CACtD,EAEAtD,EAAQ,OAAS,GAChBsC,EAAAA,KAAAC,EAAAA,SAAA,CACG,SAAA,CAAA,CAACvB,GAAgBjB,EAAK,OAAS,SAC7B,KAAA,CAAG,cAAW,GAAC,UAAU,KAAA,CAAM,QAEjC,KAAA,CAAG,UAAU,YACZ,SAAAuC,EAAAA,KAAC,MAAA,CAAI,UAAU,4BACb,SAAA,CAAAJ,MAAC,OAAA,CAAK,UAAU,mFACb,SAAAH,EAAE,qBAAqB,EAC1B,EACAO,EAAAA,KAAC,OAAA,CAAK,UAAU,oEAAoE,SAAA,CAAA,KAC/EtC,EAAQ,MAAA,EACb,EACAkC,EAAAA,IAAC,OAAA,CAAK,cAAW,GAAC,UAAU,6CAAA,CAA8C,CAAA,CAAA,CAC5E,CAAA,CACF,EACClC,EAAQ,IAAKW,GACZuB,EAAAA,IAACqB,EAAA,CAEC,IAAK,CAAE,KAAM,QAAS,MAAO5C,EAAG,KAAM,EAAA,EACtC,YAAAsC,CAAA,EAFKtC,EAAE,QAAA,CAIV,CAAA,CAAA,CACH,CAAA,CAAA,CAEJ,CAAA,EAEJ,CAEJ,CAEA,SAAS4C,EAAQ,CACf,IAAAF,EACA,YAAAJ,CACF,EAGG,CACD,MAAMlB,EAAItD,EAAA,EAEV,GAAI4E,EAAI,OAAS,SACf,OAAOnB,EAAAA,IAAC,KAAA,CAAG,cAAW,GAAC,UAAU,MAAM,EAEzC,GAAImB,EAAI,OAAS,UACf,OACEnB,EAAAA,IAAC,KAAA,CAAG,UAAU,YACZ,SAAAA,EAAAA,IAAC,OAAI,UAAU,mFACZ,SAAAmB,EAAI,IAAA,CACP,EACF,EAGJ,GAAIA,EAAI,OAAS,OACf,OACEnB,EAAAA,IAAC,KAAA,CAAG,UAAU,yFACX,WAAI,KACP,EAGJ,GAAImB,EAAI,OAAS,UACf,OACEf,EAAAA,KAAC,KAAA,CACC,MAAOP,EAAE,6BAA6B,EACtC,UAAU,qEAEV,SAAA,CAAAG,EAAAA,IAAC,OAAA,CAAK,UAAU,6EACb,SAAAmB,EAAI,MACP,EACCA,EAAI,MAAQnB,EAAAA,IAAC,QAAK,UAAU,uBAAwB,WAAI,IAAA,CAAK,CAAA,CAAA,CAAA,EAKpE,MAAMsB,EAAQH,EAAI,MACZI,EAAoBD,EAAM,MAAQ,QAClCE,EAAQF,EAAM,MAAQA,EAAM,SAC5BG,EAAWN,EAAI,MAAQG,EAAM,aAAe,GAClD,aACG,KAAA,CACC,SAAAlB,EAAAA,KAAC,SAAA,CACC,KAAK,SACL,QAAS,IAAMW,EAAYO,EAAM,QAAQ,EACzC,UAAW,sBAAsBC,CAAO,GAExC,SAAA,CAAAvB,EAAAA,IAAC,OAAA,CAAK,cAAW,GAAC,UAAU,eAAe,EAC3CI,EAAAA,KAAC,MAAA,CAAI,UAAU,mBACb,SAAA,CAAAA,EAAAA,KAAC,MAAA,CAAI,UAAU,oBACb,SAAA,CAAAJ,EAAAA,IAAC,OAAA,CAAK,UAAU,iBAAkB,SAAAwB,EAAM,EACvCF,EAAM,OACLtB,MAAC,OAAA,CAAK,UAAU,uBAAwB,SAAAQ,EAAmBc,EAAM,KAAK,CAAA,CAAE,EAE1EtB,EAAAA,IAAC0B,EAAA,CAAS,EAAGH,CAAA,CAAS,CAAA,EACxB,EACCE,GAAYzB,EAAAA,IAAC,IAAA,CAAE,UAAU,gBAAiB,SAAAyB,CAAA,CAAS,CAAA,EACtD,QACC,OAAA,CAAK,cAAW,GAAC,UAAU,mBAAmB,SAAA,GAAA,CAAC,CAAA,CAAA,CAAA,EAEpD,CAEJ,CAEA,SAASC,EAAS,CAAE,EAAAC,GAAsB,CACxC,MAAM9B,EAAItD,EAAA,EACJqF,EAEA/B,EADJ8B,IAAM,OACA,mBACFA,IAAM,WACF,uBACFA,IAAM,UACF,sBACFA,IAAM,YACF,wBACA,mBAPY,EAQ1B,OAAO3B,EAAAA,IAAC,OAAA,CAAK,UAAU,YAAa,SAAA4B,EAAM,CAC5C,CAMA,SAAShB,GAAO,CACd,OAAAiB,EACA,SAAAC,EACA,aAAAC,EACA,QAAAC,EACA,cAAAC,CACF,EAMG,OACD,MAAMpC,EAAItD,EAAA,EACJ2F,EAAWC,EAAAA,OAA8B,IAAI,EAEnDC,EAAAA,UAAU,IAAM,CACd,MAAMC,EAAS5D,GAAqB,CAC9BA,EAAE,MAAQ,WACZA,EAAE,eAAA,EACFuD,EAAA,EAEJ,EACA,OAAO,iBAAiB,UAAWK,CAAK,EACxC,MAAMC,EAAe,SAAS,KAAK,MAAM,SACzC,gBAAS,KAAK,MAAM,SAAW,SAC/B,sBAAsB,IAAA,OAAM,OAAAjF,EAAA6E,EAAS,UAAT,YAAA7E,EAAkB,QAAO,EAC9C,IAAM,CACX,OAAO,oBAAoB,UAAWgF,CAAK,EAC3C,SAAS,KAAK,MAAM,SAAWC,CACjC,CACF,EAAG,CAACN,CAAO,CAAC,EAEZ,MAAMT,EACJM,EAAO,OAAS,UAAWxE,EAAAwE,EAAO,QAAP,YAAAxE,EAAc,OAAQ,QAAW,YAE9D,OACE+C,EAAAA,KAAAC,WAAA,CACE,SAAA,CAAAL,MAAC,OAAI,UAAU,uBAAuB,QAASgC,EAAS,cAAW,GAAC,EACpE5B,EAAAA,KAAC,MAAA,CACC,IAAK8B,EACL,KAAK,SACL,aAAW,OACX,SAAU,GACV,UAAW,+BAA+BX,CAAO,sBAEjD,SAAA,CAAAnB,EAAAA,KAAC,MAAA,CAAI,UAAU,gGACb,SAAA,CAAAJ,EAAAA,IAAC,OAAI,UAAU,iBACZ,SAAA6B,EAAO,OAAS,QACfzB,EAAAA,KAAAC,EAAAA,SAAA,CACE,SAAA,CAAAL,EAAAA,IAAC0B,EAAA,CAAS,EAAGH,CAAA,CAAS,EACrBM,EAAO,MACNzB,EAAAA,KAAAC,EAAAA,SAAA,CACE,SAAA,CAAAL,EAAAA,IAAC,KAAA,CAAG,UAAU,uGACX,SAAA6B,EAAO,MAAM,MAAQA,EAAO,MAAM,QAAA,CACrC,EACAzB,EAAAA,KAAC,IAAA,CAAE,UAAU,wFACV,SAAA,CAAAyB,EAAO,MAAM,SAAS,MAAIU,GAAYV,EAAO,MAAM,KAAK,EACxDA,EAAO,MAAM,MAAQ,MAAMrB,EAAmBqB,EAAO,MAAM,KAAK,CAAC,GAAK,EAAA,CAAA,CACzE,CAAA,CAAA,CACF,EAEAzB,EAAAA,KAAAC,EAAAA,SAAA,CACE,SAAA,CAAAL,MAAC,KAAA,CAAG,UAAU,wFACX,SAAAH,EAAE,8BAA8B,EACnC,EACAG,EAAAA,IAAC,IAAA,CAAE,UAAU,wFACV,WAAO,QAAA,CACV,CAAA,CAAA,CACF,CAAA,CAAA,CAEJ,EAEAI,EAAAA,KAAAC,EAAAA,SAAA,CACE,SAAA,CAAAL,MAAC,OAAA,CAAK,UAAU,gCAAiC,SAAAH,EAAE,oBAAoB,EAAE,QACxE,KAAA,CAAG,UAAU,uGACX,SAAAA,EAAE,kBAAkB,EACvB,QACC,IAAA,CAAE,UAAU,wFACV,SAAAA,EAAE,qBAAqB,CAAA,CAC1B,CAAA,CAAA,CACF,CAAA,CAEJ,EACAG,EAAAA,IAAC,SAAA,CACC,KAAK,SACL,QAASgC,EACT,aAAYnC,EAAE,qBAAqB,EACnC,UAAU,kHAEV,eAAC2C,GAAA,CAAA,CAAU,CAAA,CAAA,CACb,EACF,EAEAxC,EAAAA,IAAC,OAAI,UAAU,mCACZ,WAAO,OAAS,SAAW6B,EAAO,MACjC7B,EAAAA,IAACyC,GAAA,CACC,MAAOZ,EAAO,MACd,aAAAE,EACA,cAAAE,CAAA,CAAA,EAEAJ,EAAO,OAAS,cACjBa,GAAA,CAAmB,SAAUb,EAAO,SAAU,cAAAI,EAA8B,EAE7EjC,MAAC2C,GAAA,CAAc,OAAQb,EAAU,CAAA,CAErC,CAAA,CAAA,CAAA,CACF,EACF,CAEJ,CAEA,SAASW,GAAgB,CACvB,MAAAnB,EACA,aAAAS,EACA,cAAAE,CACF,EAIG,CACD,MAAMpC,EAAItD,EAAA,EACJqG,EAAOtB,EAAM,KAAK,KAAA,EACxB,cACG,MAAA,CACE,SAAA,CAAAA,EAAM,aACLtB,EAAAA,IAAC,IAAA,CAAE,UAAU,+CAAgD,WAAM,YAAY,EAEjFA,EAAAA,IAAC,MAAA,CACC,UACE,iNACCsB,EAAM,YAAc,OAAS,IAG/B,SAAAsB,GAAQ,GAAA,CAAA,EAEVb,GACC3B,EAAAA,KAAC,MAAA,CAAI,UAAU,OACb,SAAA,CAAAJ,EAAAA,IAAC,MAAA,CAAI,UAAU,cAAc,cAAW,GAAC,EACzCI,EAAAA,KAAC,MAAA,CAAI,UAAU,iDACb,SAAA,CAAAJ,MAAC,MAAA,CAAI,UAAU,UAAW,SAAAH,EAAE,yBAAyB,EAAE,EACvDO,EAAAA,KAAC,SAAA,CACC,KAAK,SACL,QAAS6B,EACT,UAAU,8JAET,SAAA,CAAApC,EAAE,oBAAoB,EAAE,IAAA,CAAA,CAAA,CAC3B,EACF,EACAG,EAAAA,IAAC,IAAA,CAAE,UAAU,sDAAuD,SAAA+B,CAAA,CAAa,CAAA,CAAA,CACnF,CAAA,EAEJ,CAEJ,CAEA,SAASW,GAAmB,CAC1B,SAAAtE,EACA,cAAA6D,CACF,EAGG,CACD,MAAMpC,EAAItD,EAAA,EACV,cACG,MAAA,CACC,SAAA,CAAAyD,MAAC,IAAA,CAAE,UAAU,2CAA4C,SAAAH,EAAE,6BAA6B,EAAE,EAC1FG,EAAAA,IAAC,IAAA,CAAE,UAAU,0DAA2D,SAAA5B,EAAS,EACjFgC,EAAAA,KAAC,SAAA,CACC,KAAK,SACL,QAAS6B,EACT,UAAU,gSAET,SAAA,CAAApC,EAAE,oBAAoB,EAAE,IAAA,CAAA,CAAA,CAC3B,EACF,CAEJ,CAEA,SAAS8C,GAAc,CAAE,OAAAE,GAA8B,CACrD,MAAMD,EAAOC,EAAO,KAAA,EACpB,OACE7C,EAAAA,IAAC,MAAA,CAAI,UAAU,+MACZ,YAAQ,IACX,CAEJ,CAEA,SAASU,IAAa,CACpB,MAAM,EAAInE,EAAA,EACV,OACE6D,EAAAA,KAAC,MAAA,CAAI,UAAU,2CACb,SAAA,CAAAJ,MAAC,MAAA,CAAI,UAAU,8JACb,SAAAA,MAAC8C,KAAa,EAChB,QACC,KAAA,CAAG,UAAU,yFACX,SAAA,EAAE,oBAAoB,EACzB,QACC,IAAA,CAAE,UAAU,qFACV,SAAA,EAAE,mBAAmB,CAAA,CACxB,CAAA,EACF,CAEJ,CAEA,SAAS5B,GAAW,CAAE,UAAA6B,EAAY,IAA8B,CAC9D,OACE3C,EAAAA,KAAC,MAAA,CACC,MAAM,KACN,OAAO,KACP,QAAQ,YACR,KAAK,OACL,OAAO,eACP,YAAY,MACZ,cAAc,QACd,UAAA2C,EACA,cAAW,GAEX,SAAA,CAAA/C,MAAC,UAAO,GAAG,KAAK,GAAG,KAAK,EAAE,MAAM,EAChCA,EAAAA,IAAC,OAAA,CAAK,EAAE,iBAAA,CAAkB,CAAA,CAAA,CAAA,CAGhC,CAEA,SAASwC,IAAY,CACnB,OACExC,EAAAA,IAAC,MAAA,CACC,MAAM,KACN,OAAO,KACP,QAAQ,YACR,KAAK,OACL,OAAO,eACP,YAAY,MACZ,cAAc,QACd,cAAW,GAEX,SAAAA,EAAAA,IAAC,OAAA,CAAK,EAAE,sBAAA,CAAuB,CAAA,CAAA,CAGrC,CAEA,SAAS8C,IAAe,CACtB,OACE9C,EAAAA,IAAC,MAAA,CACC,MAAM,KACN,OAAO,KACP,QAAQ,YACR,KAAK,OACL,OAAO,eACP,YAAY,MACZ,cAAc,QACd,eAAe,QACf,cAAW,GAEX,SAAAA,EAAAA,IAAC,OAAA,CAAK,EAAE,sBAAA,CAAuB,CAAA,CAAA,CAGrC,CAEA,SAASf,EAAWqC,EAAoB0B,EAAcC,EAAoB,CAQxE,MAPe,CACb3B,EAAM,MAAQ,GACdA,EAAM,SACNA,EAAM,aAAe,GACrBA,EAAM,KACN0B,CAAA,EAEY,KAAME,GAAMA,EAAE,YAAA,EAAc,SAASD,CAAC,CAAC,CACvD,CAEA,SAASlF,GACPP,EACAD,EACyC,CACzC,MAAM4F,EAAkB,IAAI,IAAI5F,EAAQ,IAAKkB,GAAM,CAACA,EAAE,SAAUA,CAAC,CAAC,CAAC,EAC7D2E,MAAW,IACXvF,EAAc,CAAA,EAEpB,UAAWD,KAAQJ,EAAY,CAC7B,GAAII,EAAK,KAAM,CACb,MAAM0D,EAAQ6B,EAAgB,IAAIvF,EAAK,KAAK,IAAI,EAC5C0D,GACFzD,EAAK,KAAK,CAAE,KAAM,QAAS,MAAAyD,EAAO,KAAM1D,EAAK,KAAK,KAAM,EACxDwF,EAAK,IAAI9B,EAAM,QAAQ,GAEvBzD,EAAK,KAAK,CAAE,KAAM,UAAW,MAAOD,EAAK,KAAK,MAAO,KAAMA,EAAK,KAAK,IAAA,CAAM,EAE7E,QACF,CACA,MAAMyF,EAAMzF,EAAK,IAAI,KAAA,EACrB,GAAI,CAACyF,EAAK,CACRxF,EAAK,KAAK,CAAE,KAAM,QAAA,CAAU,EAC5B,QACF,CACA,MAAMyF,EAAe,wBAAwB,KAAKD,CAAG,EACjDC,EACFzF,EAAK,KAAK,CAAE,KAAM,UAAW,KAAMyF,EAAa,CAAC,EAAI,EAErDzF,EAAK,KAAK,CAAE,KAAM,OAAQ,KAAMD,EAAK,IAAK,CAE9C,CAEA,MAAME,EAAUP,EAAQ,OAAQkB,GAAM,CAAC2E,EAAK,IAAI3E,EAAE,QAAQ,CAAC,EAC3D,MAAO,CAAE,KAAAZ,EAAM,QAAAC,CAAA,CACjB,CAEA,SAASL,GAAW8F,EAAiC,WACnD,GAAI,CAACA,EAAK,MAAO,CAAA,EACjB,MAAMC,EAAmB,CAAA,EACzB,UAAWC,KAAWF,EAAI,MAAM,OAAO,EAAG,CACxC,MAAM3F,EAAO6F,EAAQ,QAAA,EACrB,GAAI7F,EAAK,KAAA,IAAW,GAAI,CACtB,MAAM8F,EAAOF,EAAIA,EAAI,OAAS,CAAC,EAC3BE,IAASA,EAAK,MAAQA,EAAK,IAAI,KAAA,IAAW,KAC5CF,EAAI,KAAK,CAAE,IAAK,GAAI,KAAM,KAAM,EAElC,QACF,CACA,MAAM7F,EAAItB,GAAQ,KAAKuB,CAAI,EACrB4D,GAAQnE,EAAAM,GAAA,YAAAA,EAAG,SAAH,YAAAN,EAAW,MACnBsG,GAAOC,EAAAjG,GAAA,YAAAA,EAAG,SAAH,YAAAiG,EAAW,KACpBjG,GAAK6D,GAASmC,EAChBH,EAAI,KAAK,CACP,IAAK5F,EACL,KAAM,CAAE,MAAO4D,EAAM,KAAA,EAAQ,KAAMmC,EAAK,KAAA,EAAQ,QAAOE,EAAAlG,EAAE,SAAF,YAAAkG,EAAU,OAAQ,IAAI,MAAK,CAAE,CACrF,EAEDL,EAAI,KAAK,CAAE,IAAK5F,EAAM,KAAM,KAAM,CAEtC,CACA,KAAO4F,EAAI,OAAS,GAAG,CACrB,MAAME,EAAOF,EAAIA,EAAI,OAAS,CAAC,EAC/B,GAAIE,GAAQ,CAACA,EAAK,MAAQA,EAAK,IAAI,SAAW,GAAIF,EAAI,IAAA,MACjD,MACP,CACA,OAAOA,CACT"}
|