@dipertq/dsh-openviking-status 0.2.1 → 0.2.2
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/README.md +1 -1
- package/lib/client.cjs +7 -4
- package/lib/client.cjs.map +1 -1
- package/lib/client.d.cts +6 -1
- package/lib/client.js +7 -4
- package/lib/client.js.map +1 -1
- package/lib/index.js +1 -1
- package/lib/index.js.map +1 -1
- package/package.json +1 -1
package/lib/client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/client/OpenVikingStatusChip.tsx","../src/client/api.ts","../src/client/theme.ts","../src/client/recallParser.ts","../src/client/OpenVikingStatusPopover.tsx","../src/client/OpenVikingSettingsSection.tsx","../src/client/index.tsx"],"sourcesContent":["import React, {\n useState,\n useEffect,\n useCallback,\n useRef,\n useMemo,\n} from \"react\";\nimport ReactDOM from \"react-dom\";\nimport {\n HealthStatus,\n SessionStatus,\n SessionReadResult,\n OpenVikingClient,\n defaultOpenVikingClient,\n} from \"./api\";\nimport { themeVar } from \"./theme\";\nimport { RecalledMemoriesResult, parseRecalledMemories } from \"./recallParser\";\nimport { OpenVikingStatusPopover } from \"./OpenVikingStatusPopover\";\n\nexport const COMMIT_THRESHOLD = 20000;\n\n/**\n * Селектор поверх снимка диалога — стандартный проп слотов со скоупом сессии.\n * Штатные чипы статистики DSH читают узлы ровно так же.\n */\nexport type UseChat = (selector: (snapshot: any) => any) => any;\n\nexport interface OpenVikingStatusChipProps {\n sessionId: string;\n /** Стандартный проп слота: доступ к снимку текущего диалога. */\n useChat?: UseChat;\n /** Узлы диалога напрямую — для вызова вне слота и для тестов. */\n messages?: unknown;\n /** Готовый текст диалога; приоритетнее остальных источников. */\n contextText?: string;\n client?: OpenVikingClient;\n onCommit?: () => void;\n className?: string;\n initialHealth?: HealthStatus;\n initialSessionData?: SessionStatus;\n initialSessionRead?: SessionReadResult;\n initialOpen?: boolean;\n}\n\n/**\n * Форматирование количества токенов в килотокены (Math.round(tokens / 1000)k pend).\n */\nexport function formatPendingTokens(pendingTokens: number): string {\n const k = Math.round((pendingTokens || 0) / 1000);\n return `${k}k pend`;\n}\n\n/**\n * Формирование текстового ярлыка статусного чипа.\n * В онлайне: \"OV: <recalled> rec · <pending>k pend\"\n * В офлайне: \"OV offline\"\n */\nexport function formatStatusLabel(\n isOnline: boolean,\n recalledCount: number,\n pendingTokens: number\n): string {\n if (!isOnline) {\n return \"OV offline\";\n }\n return `OV: ${recalledCount} rec · ${formatPendingTokens(pendingTokens)}`;\n}\n\n/**\n * Формирование доступного заголовка / подсказки (title / aria-label).\n */\nexport function formatTooltipTitle({\n isOnline,\n isCommitting = false,\n recalledCount,\n pendingTokens,\n sessionUnreadable = false,\n}: {\n isOnline: boolean;\n isCommitting?: boolean;\n recalledCount: number;\n pendingTokens: number;\n sessionUnreadable?: boolean;\n}): string {\n if (!isOnline) {\n return \"OpenViking: Offline\";\n }\n if (sessionUnreadable) {\n return \"OpenViking: session unreadable — the daemon requires an API key\";\n }\n const countLabel = `${recalledCount} recalled`;\n const tokenLabel = `${(pendingTokens || 0).toLocaleString()} pending tokens`;\n if (isCommitting) {\n return `OpenViking: Committing... (${countLabel}, ${tokenLabel})`;\n }\n return `OpenViking: Online (${countLabel}, ${tokenLabel})`;\n}\n\n/**\n * Состояние индикатора: офлайн, нечитаемая сессия, коммит или норма.\n */\nexport function getStatusIndicatorColor(\n isOnline: boolean,\n isCommitting: boolean = false,\n sessionUnreadable: boolean = false\n): string {\n if (!isOnline) {\n return themeVar(\"stateError\");\n }\n if (isCommitting || sessionUnreadable) {\n return themeVar(\"stateWarning\");\n }\n return themeVar(\"stateSuccess\");\n}\n\n/**\n * Извлечение текста из снимка диалога DSH.\n *\n * Узлы разнородны: текст лежит то в `content` строкой, то массивом блоков, то\n * в `text`. Парсер воспоминаний работает по тексту, поэтому снимок сводится к\n * одной строке, а неизвестные формы просто пропускаются.\n */\nexport function chatNodesToText(nodes: unknown): string {\n if (!nodes) return \"\";\n\n const source = Array.isArray(nodes)\n ? nodes\n : typeof nodes === \"object\"\n ? Object.values(nodes as Record<string, unknown>)\n : [];\n\n const parts: string[] = [];\n\n const visit = (value: unknown, depth = 0): void => {\n if (depth > 4 || value === null || value === undefined) return;\n if (typeof value === \"string\") {\n parts.push(value);\n return;\n }\n if (Array.isArray(value)) {\n for (const item of value) visit(item, depth + 1);\n return;\n }\n if (typeof value === \"object\") {\n const record = value as Record<string, unknown>;\n for (const key of [\"content\", \"text\", \"data\", \"body\"]) {\n if (key in record) visit(record[key], depth + 1);\n }\n }\n };\n\n for (const node of source) visit(node);\n\n return parts.join(\"\\n\");\n}\n\n/**\n * Status Chip: состояние памяти OpenViking в строке статистики под композером.\n *\n * Внешняя обёртка над {@link StatusChipView}: выбирает источник диалога.\n * `useChat` — стандартный проп слота и сам по себе хук, поэтому вызывать его\n * условно нельзя; развилка сделана выбором компонента, а не условием внутри\n * одного.\n */\nexport function OpenVikingStatusChip(props: OpenVikingStatusChipProps) {\n const { useChat, ...rest } = props;\n if (\n useChat &&\n rest.contextText === undefined &&\n rest.messages === undefined\n ) {\n // Плагин делит строку статистики с чужими ячейками, поэтому сбой чтения\n // диалога не должен уронить её целиком: граница оставляет чип живым, но\n // без счётчика воспоминаний.\n return (\n <ChatReadBoundary fallback={<StatusChipView {...rest} />}>\n <ChatBackedStatusChip useChat={useChat} {...rest} />\n </ChatReadBoundary>\n );\n }\n return <StatusChipView {...rest} />;\n}\n\n/** Граница ошибок вокруг чтения снимка диалога. */\nclass ChatReadBoundary extends React.Component<\n { children: React.ReactNode; fallback: React.ReactNode },\n { failed: boolean }\n> {\n state = { failed: false };\n\n static getDerivedStateFromError() {\n return { failed: true };\n }\n\n render() {\n return this.state.failed ? this.props.fallback : this.props.children;\n }\n}\n\n/**\n * Вариант чипа, читающий диалог из снимка слота.\n *\n * `useChat` вызывается на верхнем уровне — так же, как в штатных чипах\n * статистики DSH.\n */\nfunction ChatBackedStatusChip({\n useChat,\n ...rest\n}: OpenVikingStatusChipProps & { useChat: UseChat }) {\n // Селектор защищён от неожиданной формы снимка: сбой при чтении диалога\n // стоит счётчика воспоминаний, но не должен ронять чужую строку статистики.\n const nodes = useChat((snapshot: any) => {\n try {\n return snapshot?.legacy?.nodes !== undefined\n ? snapshot.legacy.nodes\n : snapshot?.nodes;\n } catch {\n return undefined;\n }\n });\n return <StatusChipView {...rest} messages={nodes} />;\n}\n\n/** Собственно чип: отрисовка и опрос демона. */\nfunction StatusChipView({\n sessionId,\n messages,\n contextText,\n client,\n onCommit,\n className,\n initialHealth,\n initialSessionData,\n initialSessionRead,\n initialOpen = false,\n}: OpenVikingStatusChipProps) {\n const [health, setHealth] = useState<HealthStatus | null>(\n initialHealth ?? null\n );\n const [sessionRead, setSessionRead] = useState<SessionReadResult | null>(\n initialSessionRead ??\n (initialSessionData\n ? { status: \"ok\", session: initialSessionData }\n : null)\n );\n const [isOpen, setIsOpen] = useState(initialOpen);\n const [isCommitting, setIsCommitting] = useState(false);\n const [commitError, setCommitError] = useState<string | null>(null);\n const [isHovered, setIsHovered] = useState(false);\n const [statsHost, setStatsHost] = useState<Element | null>(null);\n const popoverRef = useRef<HTMLDivElement>(null);\n\n const apiClient = client ?? defaultOpenVikingClient;\n\n useEffect(() => {\n if (typeof document === \"undefined\") return;\n\n function findHost() {\n const el = document.querySelector(\"[data-composer-stats]\");\n setStatsHost((prev) => (prev !== el ? el : prev));\n }\n\n findHost();\n\n const observer = new MutationObserver(() => {\n findHost();\n });\n observer.observe(document.body, { childList: true, subtree: true });\n return () => observer.disconnect();\n }, []);\n\n // Источник текста диалога: готовая строка либо переданные узлы. Вариант с\n // `useChat` живёт в отдельном компоненте: этот проп сам является хуком, и\n // вызывать его условно нельзя.\n const conversationText = useMemo(() => {\n if (typeof contextText === \"string\") return contextText;\n return chatNodesToText(messages);\n }, [contextText, messages]);\n\n const recalledResult: RecalledMemoriesResult = useMemo(\n () => parseRecalledMemories(conversationText),\n [conversationText]\n );\n\n const fetchStatus = useCallback(async () => {\n try {\n const healthRes = await apiClient.checkHealth();\n setHealth(healthRes);\n\n if (!healthRes.ok) {\n return;\n }\n\n setSessionRead(await apiClient.readSession(sessionId));\n } catch {\n setHealth({ ok: false });\n }\n }, [sessionId, apiClient]);\n\n useEffect(() => {\n fetchStatus();\n const timer = setInterval(fetchStatus, 15000);\n return () => clearInterval(timer);\n }, [fetchStatus]);\n\n // Закрытие всплывающего окна при клике вне области виджета\n useEffect(() => {\n function handleClickOutside(event: MouseEvent) {\n if (\n popoverRef.current &&\n !popoverRef.current.contains(event.target as Node)\n ) {\n setIsOpen(false);\n }\n }\n function handleKeyDown(event: KeyboardEvent) {\n if (event.key === \"Escape\") {\n setIsOpen(false);\n }\n }\n if (isOpen) {\n document.addEventListener(\"mousedown\", handleClickOutside);\n document.addEventListener(\"keydown\", handleKeyDown);\n }\n return () => {\n document.removeEventListener(\"mousedown\", handleClickOutside);\n document.removeEventListener(\"keydown\", handleKeyDown);\n };\n }, [isOpen]);\n\n const handleCommitNow = async () => {\n if (isCommitting) return;\n setIsCommitting(true);\n setCommitError(null);\n try {\n const res = await apiClient.commitSession(sessionId, {\n keep_recent_count: 10,\n });\n if (res.ok) {\n await fetchStatus();\n onCommit?.();\n } else {\n setCommitError(res.error || \"Commit failed\");\n }\n } catch (e) {\n const msg = e instanceof Error ? e.message : String(e);\n setCommitError(msg || \"Failed to commit session\");\n console.error(\"[dsh-openviking-status] Failed to commit session:\", e);\n } finally {\n setIsCommitting(false);\n }\n };\n\n const isOnline = health?.ok === true;\n const sessionData = sessionRead?.status === \"ok\" ? sessionRead.session : null;\n // Отказ авторизации или недоступность — это «неизвестно», а не «ноль».\n const sessionUnreadable =\n isOnline && sessionRead !== null && sessionRead.status !== \"ok\";\n const pendingTokens = sessionData?.pending_tokens ?? 0;\n const recalledCount = recalledResult.recalledCount;\n\n const statusColor = getStatusIndicatorColor(\n isOnline,\n isCommitting,\n sessionUnreadable\n );\n const tooltipTitle = formatTooltipTitle({\n isOnline,\n isCommitting,\n recalledCount,\n pendingTokens,\n sessionUnreadable,\n });\n\n /** Текст справа от индикатора. */\n const label = !isOnline\n ? \"OV offline\"\n : sessionUnreadable\n ? `OV: ${recalledCount} rec · no access`\n : `OV: ${recalledCount} rec · ${Math.round(pendingTokens / 1000)}k pend`;\n\n const chipElement = (\n <span\n className={className}\n data-openviking-status=\"true\"\n style={{ minWidth: 0, display: \"inline-flex\", position: \"relative\" }}\n ref={popoverRef}\n >\n <button\n type=\"button\"\n onClick={() => setIsOpen(!isOpen)}\n onMouseEnter={() => setIsHovered(true)}\n onMouseLeave={() => setIsHovered(false)}\n aria-expanded={isOpen}\n aria-haspopup=\"dialog\"\n style={{\n boxSizing: \"border-box\",\n maxWidth: \"100%\",\n color: isHovered\n ? themeVar(\"labelSecondary\")\n : themeVar(\"labelTertiary\"),\n fontFamily: \"var(--dsw-font-family, system-ui)\",\n fontSize: \"var(--dsh-content-font-size-secondary, 13px)\",\n lineHeight:\n \"calc(20px + var(--dsh-content-font-delta-secondary, 0px))\",\n fontVariantNumeric: \"tabular-nums\",\n whiteSpace: \"nowrap\",\n background: isHovered ? themeVar(\"hoverBackground\") : \"transparent\",\n border: \"none\",\n borderRadius: \"24px\",\n alignItems: \"center\",\n gap: \"6px\",\n padding: \"1px 8px\",\n display: \"inline-flex\",\n cursor: \"pointer\",\n }}\n title={tooltipTitle}\n aria-label={tooltipTitle}\n >\n <span\n data-testid=\"status-dot\"\n aria-hidden=\"true\"\n style={{\n width: \"6px\",\n height: \"6px\",\n borderRadius: \"50%\",\n background: statusColor,\n flexShrink: 0,\n }}\n />\n <span style={{ textOverflow: \"ellipsis\", minWidth: 0 }}>{label}</span>\n </button>\n\n {isOpen && (\n <OpenVikingStatusPopover\n sessionId={sessionId}\n health={health}\n sessionData={sessionData}\n sessionRead={sessionRead}\n recalledResult={recalledResult}\n endpoint={apiClient.endpoint}\n isCommitting={isCommitting}\n commitError={commitError}\n onCommitNow={handleCommitNow}\n onClose={() => setIsOpen(false)}\n />\n )}\n </span>\n );\n\n if (statsHost && typeof document !== \"undefined\") {\n return ReactDOM.createPortal(chipElement, statsHost);\n }\n\n return (\n <div\n style={{\n maxWidth: \"var(--dsh-chat-content-width, 748px)\",\n boxSizing: \"border-box\",\n width: \"100%\",\n padding: \"4px calc(var(--dsh-composer-side-clearance, 0px) + 16px) 0px\",\n fontSize: \"var(--dsh-content-font-size-secondary, 13px)\",\n lineHeight: \"calc(20px + var(--dsh-content-font-delta-secondary, 0px))\",\n justifyContent: \"center\",\n gap: \"12px\",\n margin: \"0 auto\",\n display: \"flex\",\n }}\n >\n {chipElement}\n </div>\n );\n}\n","/**\n * Клиент OpenViking Session REST API и доменные типы.\n * Поддерживает проверку здоровья сервиса, получение состояния сессии\n * с разрешением префиксов идентификаторов (dsh-session-* / dsh-*) и выполнение коммита.\n */\n\n/**\n * Статус подключения и здоровья сервиса OpenViking\n */\nexport interface HealthStatus {\n ok: boolean;\n version?: string;\n storage?: string;\n error?: string;\n}\n\n/**\n * Состояние активной сессии OpenViking в соответствии с CONTEXT.md\n */\nexport interface SessionStatus {\n session_id: string;\n peer_id?: string;\n pending_tokens: number;\n message_count?: number;\n commit_count?: number;\n last_commit_at?: string;\n created_at?: string;\n updated_at?: string;\n}\n\n/**\n * Параметры операции коммита сессии\n */\nexport interface CommitOptions {\n keep_recent_count?: number;\n}\n\n/**\n * Результат операции коммита сессии\n */\nexport interface CommitResult {\n ok: boolean;\n error?: string;\n}\n\n/**\n * Исход попытки прочитать сессию.\n *\n * Причина неудачи важна: при `auth_mode: api_key` демон отвечает на `/health`\n * и отказывает на сессии, и «нечитаемо» нельзя показывать как «накоплено ноль».\n */\nexport type SessionReadResult =\n /** Сессия прочитана. */\n | { status: \"ok\"; session: SessionStatus }\n /** Демон требует ключ, которого у клиента нет. */\n | { status: \"unauthorized\" }\n /** Демон не знает такой сессии. */\n | { status: \"missing\" }\n /** До демона не удалось достучаться. */\n | { status: \"unreachable\"; detail?: string }\n /** Демон ответил ошибкой или неожиданным телом. */\n | { status: \"error\"; detail?: string };\n\n/**\n * Синонимы доменных понятий из CONTEXT.md\n */\nexport type PendingTokens = number;\nexport type PeerId = string;\n\n/**\n * Базовый URL по умолчанию для локального демона OpenViking\n */\nexport const DEFAULT_OPENVIKING_ENDPOINT = \"http://127.0.0.1:1933\";\n\n/**\n * Определение эндпоинта OpenViking из параметров, глобального контекста или localStorage\n */\nexport function resolveEndpoint(endpoint?: string): string {\n if (endpoint && endpoint.trim().length > 0) {\n return endpoint.trim().replace(/\\/+$/, \"\");\n }\n\n if (typeof window !== \"undefined\") {\n const win = window as unknown as Record<string, unknown>;\n if (\n typeof win.__OPENVIKING_ENDPOINT__ === \"string\" &&\n win.__OPENVIKING_ENDPOINT__.trim()\n ) {\n return win.__OPENVIKING_ENDPOINT__.trim().replace(/\\/+$/, \"\");\n }\n }\n\n if (typeof localStorage !== \"undefined\") {\n try {\n const stored =\n localStorage.getItem(\"openviking_endpoint\") ||\n localStorage.getItem(\"OPENVIKING_ENDPOINT\");\n if (stored && stored.trim()) {\n return stored.trim().replace(/\\/+$/, \"\");\n }\n } catch {\n // Игнорируем ошибки доступа к хранилищу (security sandbox, incognito)\n }\n }\n\n return DEFAULT_OPENVIKING_ENDPOINT;\n}\n\n/**\n * Определение API-ключа из параметров, глобального контекста или localStorage\n */\nexport function resolveApiKey(apiKey?: string): string | undefined {\n if (apiKey && apiKey.trim().length > 0) {\n return apiKey.trim();\n }\n\n if (typeof window !== \"undefined\") {\n const win = window as unknown as Record<string, unknown>;\n if (\n typeof win.__OPENVIKING_API_KEY__ === \"string\" &&\n win.__OPENVIKING_API_KEY__.trim()\n ) {\n return win.__OPENVIKING_API_KEY__.trim();\n }\n }\n\n if (typeof localStorage !== \"undefined\") {\n try {\n const stored =\n localStorage.getItem(\"openviking_api_key\") ||\n localStorage.getItem(\"OPENVIKING_API_KEY\");\n if (stored && stored.trim()) {\n return stored.trim();\n }\n } catch {\n // Игнорируем ошибки доступа к хранилищу\n }\n }\n\n return undefined;\n}\n\n/**\n * Клиент REST API для взаимодействия с сессиями демона OpenViking\n */\nexport class OpenVikingClient {\n endpoint: string;\n apiKey?: string;\n private resolvedSessionIds = new Map<string, string>();\n\n constructor(endpoint?: string, apiKey?: string) {\n this.endpoint = resolveEndpoint(endpoint);\n this.apiKey = resolveApiKey(apiKey);\n }\n\n /**\n * Обновление конфигурации клиента на лету (например, после сохранения настроек в UI).\n */\n updateConfig(config: { endpoint?: string; apiKey?: string }): void {\n if (config.endpoint && config.endpoint.trim()) {\n this.endpoint = resolveEndpoint(config.endpoint);\n }\n if (config.apiKey !== undefined) {\n this.apiKey = resolveApiKey(config.apiKey);\n }\n this.resolvedSessionIds.clear();\n }\n\n /**\n * Очистить кэш разрешенных идентификаторов сессий.\n */\n clearResolvedSessions(): void {\n this.resolvedSessionIds.clear();\n }\n\n /**\n * Проверка, работает ли клиент через DSH Web Server proxy.\n */\n private isProxy(): boolean {\n return (\n this.endpoint.startsWith(\"/\") ||\n this.endpoint.includes(\"/openviking-status/api\")\n );\n }\n\n /**\n * Формирование заголовков запроса, включая опциональный заголовок авторизации\n */\n private getHeaders(\n customHeaders?: Record<string, string>\n ): Record<string, string> {\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n ...customHeaders,\n };\n if (this.apiKey) {\n headers[\"Authorization\"] = `Bearer ${this.apiKey}`;\n }\n return headers;\n }\n\n /**\n * Генерация кандидатов ID сессии для fallback-разрешения:\n * dsh-session-${id} <-> dsh-${id}\n */\n private getCandidateSessionIds(sessionId: string): string[] {\n const raw = sessionId.trim();\n const candidates: string[] = [];\n\n const cached = this.resolvedSessionIds.get(raw);\n if (cached) {\n candidates.push(cached);\n }\n\n if (raw.startsWith(\"dsh-session-\")) {\n const suffix = raw.slice(\"dsh-session-\".length);\n candidates.push(raw, `dsh-${suffix}`);\n } else if (raw.startsWith(\"dsh-\")) {\n const suffix = raw.slice(\"dsh-\".length);\n candidates.push(raw, `dsh-session-${suffix}`);\n } else if (raw.startsWith(\"session-\")) {\n // DSH отдаёт `session-<uuid>`, OpenViking хранит `dsh-session-<uuid>`:\n // достаточно приписать `dsh-`. Общая ветка ниже добавила бы ещё один\n // `session-`, и первый запрос на каждом опросе гарантированно давал 404.\n candidates.push(`dsh-${raw}`, raw);\n } else {\n // Если префикс dsh- отсутствует, сначала пробуем dsh-session-, затем dsh-, затем исходный raw\n candidates.push(`dsh-session-${raw}`, `dsh-${raw}`, raw);\n }\n\n // Удаление дубликатов с сохранением порядка следования\n return Array.from(new Set(candidates));\n }\n\n /**\n * Проверка доступности и состояния сервиса OpenViking\n */\n async checkHealth(): Promise<HealthStatus> {\n if (this.isProxy()) {\n try {\n const res = await fetch(`${this.endpoint}/health`, {\n method: \"GET\",\n headers: this.getHeaders(),\n });\n\n if (!res.ok) {\n return {\n ok: false,\n error: `HTTP ${res.status}: ${res.statusText}`,\n };\n }\n\n const body = (await res.json().catch(() => ({}))) as Record<\n string,\n unknown\n >;\n const isOk =\n body.ok !== false &&\n body.status !== \"error\" &&\n (body.ok === true ||\n body.status === \"ok\" ||\n body.status === \"healthy\" ||\n res.ok);\n\n return {\n ok: isOk,\n version: typeof body.version === \"string\" ? body.version : undefined,\n storage: typeof body.storage === \"string\" ? body.storage : undefined,\n };\n } catch (err) {\n return {\n ok: false,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n }\n\n try {\n const res = await fetch(`${this.endpoint}/health`, {\n method: \"GET\",\n headers: this.getHeaders(),\n });\n\n if (!res.ok) {\n return {\n ok: false,\n error: `HTTP ${res.status}: ${res.statusText}`,\n };\n }\n\n const body = (await res.json().catch(() => ({}))) as Record<\n string,\n unknown\n >;\n const isOk =\n body.ok !== false &&\n body.status !== \"error\" &&\n (body.ok === true ||\n body.status === \"ok\" ||\n body.status === \"healthy\" ||\n res.ok);\n\n return {\n ok: isOk,\n version: typeof body.version === \"string\" ? body.version : undefined,\n storage: typeof body.storage === \"string\" ? body.storage : undefined,\n };\n } catch (err) {\n return {\n ok: false,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n }\n\n /**\n * Чтение метаданных сессии с явной причиной неудачи.\n *\n * Демон может работать с `auth_mode: api_key`: тогда `/health` остаётся\n * открытым, а сессия отвечает 401. Схлопывать это в «нет данных» нельзя —\n * иначе интерфейс покажет живой индикатор рядом с нулями и умолчит о том,\n * что счётчики просто недоступны.\n */\n async readSession(sessionId: string): Promise<SessionReadResult> {\n if (!sessionId || !sessionId.trim()) {\n return { status: \"missing\" };\n }\n\n if (this.isProxy()) {\n try {\n const res = await fetch(\n `${this.endpoint}/session?id=${encodeURIComponent(sessionId.trim())}`,\n {\n method: \"GET\",\n headers: this.getHeaders(),\n }\n );\n\n if (res.status === 401 || res.status === 403) {\n return { status: \"unauthorized\" };\n }\n\n if (!res.ok) {\n return { status: \"error\", detail: `HTTP ${res.status}` };\n }\n\n const data = (await res.json()) as Record<string, unknown>;\n if (data.status === \"unauthorized\") return { status: \"unauthorized\" };\n if (data.status === \"missing\") return { status: \"missing\" };\n if (data.status === \"unreachable\")\n return {\n status: \"unreachable\",\n detail: typeof data.detail === \"string\" ? data.detail : undefined,\n };\n if (data.status === \"error\")\n return {\n status: \"error\",\n detail: typeof data.detail === \"string\" ? data.detail : undefined,\n };\n if (data.status === \"ok\" && data.session) {\n return {\n status: \"ok\",\n session: data.session as SessionStatus,\n };\n }\n return { status: \"error\", detail: \"malformed response from proxy\" };\n } catch (err) {\n return {\n status: \"unreachable\",\n detail: err instanceof Error ? err.message : String(err),\n };\n }\n }\n\n const candidates = this.getCandidateSessionIds(sessionId);\n\n for (const candidateId of candidates) {\n try {\n const res = await fetch(\n `${this.endpoint}/api/v1/sessions/${encodeURIComponent(candidateId)}`,\n {\n method: \"GET\",\n headers: this.getHeaders(),\n }\n );\n\n if (res.status === 404) {\n // Пробуем альтернативный формат идентификатора сессии\n continue;\n }\n\n if (res.status === 401 || res.status === 403) {\n return { status: \"unauthorized\" };\n }\n\n if (!res.ok) {\n return { status: \"error\", detail: `HTTP ${res.status}` };\n }\n\n const data = (await res.json()) as Record<string, unknown>;\n const raw = (data?.result ?? data?.data ?? data) as Record<\n string,\n unknown\n >;\n\n if (!raw || typeof raw !== \"object\") {\n return { status: \"error\", detail: \"malformed response body\" };\n }\n\n // Запоминаем успешно разрешенный идентификатор\n this.resolvedSessionIds.set(sessionId.trim(), candidateId);\n\n return {\n status: \"ok\",\n session: {\n session_id:\n typeof raw.session_id === \"string\" ? raw.session_id : candidateId,\n peer_id: typeof raw.peer_id === \"string\" ? raw.peer_id : undefined,\n pending_tokens:\n typeof raw.pending_tokens === \"number\" ? raw.pending_tokens : 0,\n message_count:\n typeof raw.message_count === \"number\"\n ? raw.message_count\n : undefined,\n commit_count:\n typeof raw.commit_count === \"number\"\n ? raw.commit_count\n : undefined,\n last_commit_at:\n typeof raw.last_commit_at === \"string\"\n ? raw.last_commit_at\n : typeof raw.last_commit === \"string\"\n ? raw.last_commit\n : undefined,\n created_at:\n typeof raw.created_at === \"string\" ? raw.created_at : undefined,\n updated_at:\n typeof raw.updated_at === \"string\" ? raw.updated_at : undefined,\n },\n };\n } catch (err) {\n return {\n status: \"unreachable\",\n detail: err instanceof Error ? err.message : String(err),\n };\n }\n }\n\n return { status: \"missing\" };\n }\n\n /**\n * Получение метаданных сессии по идентификатору.\n * Обёртка над {@link readSession} для вызывающих, которым причина неудачи\n * не нужна: любая неудача сводится к null.\n */\n async fetchSession(sessionId: string): Promise<SessionStatus | null> {\n const result = await this.readSession(sessionId);\n return result.status === \"ok\" ? result.session : null;\n }\n\n /**\n * Алиас для fetchSession\n */\n async getSession(sessionId: string): Promise<SessionStatus | null> {\n return this.fetchSession(sessionId);\n }\n\n /**\n * Инициация фиксации (коммита) накопленных токенов сессии в долговременную память\n */\n async commitSession(\n sessionId: string,\n options?: CommitOptions\n ): Promise<CommitResult> {\n if (!sessionId || !sessionId.trim()) {\n return { ok: false, error: \"Missing sessionId\" };\n }\n\n if (this.isProxy()) {\n try {\n const res = await fetch(`${this.endpoint}/session/commit`, {\n method: \"POST\",\n headers: this.getHeaders(),\n body: JSON.stringify({\n sessionId: sessionId.trim(),\n ...(options ?? { keep_recent_count: 10 }),\n }),\n });\n\n if (!res.ok) {\n return { ok: false, error: `HTTP ${res.status}` };\n }\n\n const data = (await res.json().catch(() => ({}))) as Record<\n string,\n unknown\n >;\n return {\n ok: data.ok === true,\n error: typeof data.error === \"string\" ? data.error : undefined,\n };\n } catch (err) {\n return {\n ok: false,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n }\n\n const candidates = this.getCandidateSessionIds(sessionId);\n const bodyPayload = JSON.stringify(options ?? { keep_recent_count: 10 });\n let lastError = \"Session commit failed\";\n\n for (const candidateId of candidates) {\n try {\n const res = await fetch(\n `${this.endpoint}/api/v1/sessions/${encodeURIComponent(candidateId)}/commit`,\n {\n method: \"POST\",\n headers: this.getHeaders(),\n body: bodyPayload,\n }\n );\n\n if (res.status === 404) {\n lastError = `Session not found: ${candidateId}`;\n continue;\n }\n\n if (!res.ok) {\n const errBody = (await res.json().catch(() => null)) as Record<\n string,\n unknown\n > | null;\n const errorMsg =\n (errBody?.error as Record<string, unknown>)?.message ||\n errBody?.message ||\n errBody?.error ||\n `HTTP ${res.status}: ${res.statusText}`;\n return { ok: false, error: String(errorMsg) };\n }\n\n this.resolvedSessionIds.set(sessionId.trim(), candidateId);\n return { ok: true };\n } catch (err) {\n return {\n ok: false,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n }\n\n return { ok: false, error: lastError };\n }\n}\n\n/**\n * Экземпляр клиента по умолчанию с автоматическим определением конфигурации\n */\nexport const defaultOpenVikingClient = new OpenVikingClient();\n\n/**\n * Вспомогательная функция проверки доступности OpenViking\n */\nexport function checkHealth(\n endpoint?: string,\n apiKey?: string\n): Promise<HealthStatus> {\n const client =\n endpoint || apiKey\n ? new OpenVikingClient(endpoint, apiKey)\n : defaultOpenVikingClient;\n return client.checkHealth();\n}\n\n/**\n * Вспомогательная функция получения состояния сессии\n */\nexport function fetchSession(\n sessionId: string,\n endpoint?: string,\n apiKey?: string\n): Promise<SessionStatus | null> {\n const client =\n endpoint || apiKey\n ? new OpenVikingClient(endpoint, apiKey)\n : defaultOpenVikingClient;\n return client.fetchSession(sessionId);\n}\n\n/**\n * Синоним для fetchSession\n */\nexport function getSession(\n sessionId: string,\n endpoint?: string,\n apiKey?: string\n): Promise<SessionStatus | null> {\n return fetchSession(sessionId, endpoint, apiKey);\n}\n\n/**\n * Вспомогательная функция выполнения коммита сессии\n */\nexport function commitSession(\n sessionId: string,\n options?: CommitOptions,\n endpoint?: string,\n apiKey?: string\n): Promise<CommitResult> {\n const client =\n endpoint || apiKey\n ? new OpenVikingClient(endpoint, apiKey)\n : defaultOpenVikingClient;\n return client.commitSession(sessionId, options);\n}\n","/**\n * Соответствие «визуальная роль → свойство темы DSH».\n *\n * Плагин стилизуется инлайново, поэтому каждое обращение к теме — строка\n * `var(--dsw-…)`. CSS-переменные падают на fallback молча, и опечатка в имени\n * выглядит как работающий код: именно так плагин однажды уехал на шестнадцать\n * несуществующих свойств и перестал следовать теме вовсе, сохранив осмысленный\n * вид.\n *\n * Единая таблица делает набор имён проверяемым как данные (`tests/theme.test.ts`\n * сверяет их с тем, что объявляет `@deepseek-ai/dsh-client-ui-theme`), а заодно\n * не даёт разойтись значениям между чипом и поповером.\n *\n * Значения подобраны по штатным компонентам DSH: чип повторяет `StatsPills`,\n * панель — диалог статистики сессии из `@deepseek-ai/dsh-client-ui-chat`.\n */\nexport const THEME = {\n /** Фон всплывающей панели — тот же, что у меню и диалогов DSH. */\n panelSurface: \"--dsw-specific-menu\",\n /** Тень панели. */\n panelElevation: \"--dsw-elevation-prominent\",\n /** Контур панели; задаётся через переменную тени, а не через border. */\n panelStroke: \"--dsw-alias-border-l1\",\n\n /** Заголовки и акцентный текст. */\n labelPrimary: \"--dsw-alias-label-primary\",\n /** Основной текст панели. */\n labelSecondary: \"--dsw-alias-label-secondary\",\n /** Приглушённый текст: подписи, значения, текст чипа в покое. */\n labelTertiary: \"--dsw-alias-label-tertiary\",\n\n /** Разделительная линия внутри панели. */\n hairline: \"--dsw-alias-border-l2\",\n\n /** Подсветка интерактивного элемента под курсором. */\n hoverBackground: \"--dsw-alias-interactive-bg-hover\",\n /** Подсветка нажатого элемента. */\n activeBackground: \"--dsw-alias-interactive-bg-active\",\n\n /** Демон доступен. */\n stateSuccess: \"--dsw-alias-state-success-primary\",\n /** Демон недоступен или сессия нечитаема. */\n stateError: \"--dsw-alias-state-error-primary\",\n /** Идёт коммит, либо накоплено близко к порогу. */\n stateWarning: \"--dsw-alias-state-warn-primary\",\n\n /** Утопленная поверхность: дорожка прогресс-бара. */\n insetSurface: \"--dsw-alias-bg-layer-2\",\n\n /** Заливка основной кнопки действий. */\n buttonPrimaryFill: \"--dsw-alias-button-primary-fill\",\n /** Цвет текста на основной кнопке действий. */\n buttonPrimaryText: \"--dsw-alias-label-primary-inverted\",\n\n /** Моноширинный шрифт для идентификаторов и путей. */\n fontMono: \"--dsw-font-markdown-code-font-family\",\n} as const;\n\n/** Роль в карте темы. */\nexport type ThemeRole = keyof typeof THEME;\n\n/**\n * Ссылка на свойство темы для инлайнового стиля.\n *\n * Намеренно без fallback: подставленное значение скрыло бы отсутствующее\n * свойство и вернуло бы ровно тот сбой, ради которого заведена эта карта.\n */\nexport function themeVar(role: ThemeRole): string {\n return `var(${THEME[role]})`;\n}\n","export interface RecalledMemoryItem {\n uri: string;\n category?: string;\n source: \"profile\" | \"recall\";\n score?: number;\n abstract?: string;\n}\n\nexport interface RecalledMemoriesResult {\n recalledCount: number;\n items: RecalledMemoryItem[];\n profileItems: RecalledMemoryItem[];\n recallItems: RecalledMemoryItem[];\n}\n\nconst KNOWN_CATEGORIES = new Set([\n \"preferences\",\n \"entities\",\n \"events\",\n \"skills\",\n \"resources\",\n \"profile\",\n]);\n\n/**\n * Infer the memory category from a viking:// URI.\n * Examples:\n * - viking://user/dsh/memories/preferences/... -> preferences\n * - viking://user/dsh/memories/entities/... -> entities\n * - viking://user/dsh/peers/user@example.com/memories/events/... -> events\n * - viking://user/dsh/skills/... -> skills\n * - viking://user/dsh/resources/... -> resources\n */\nexport function inferCategory(uri: string): string | undefined {\n if (!uri || typeof uri !== \"string\") return undefined;\n\n // 1. Direct match on /memories/<category>/ or /memories/<category>$\n const memoriesMatch = uri.match(/\\/memories\\/([^/#?]+)/i);\n if (memoriesMatch && memoriesMatch[1]) {\n return memoriesMatch[1].toLowerCase();\n }\n\n // 2. Strip viking:// and inspect path segments\n const cleanUri = uri.replace(/^viking:\\/\\/?/i, \"\");\n const segments = cleanUri.split(\"/\").filter(Boolean);\n\n // Check if any path segment matches a known category\n for (const seg of segments) {\n const lower = seg.toLowerCase();\n if (KNOWN_CATEGORIES.has(lower)) {\n return lower;\n }\n }\n\n // 3. Pattern: user/<user_id>/<category>/...\n if (segments[0]?.toLowerCase() === \"user\" && segments.length >= 3) {\n return segments[2].toLowerCase();\n }\n\n // 4. Pattern: <category>/...\n if (segments.length >= 2) {\n return segments[0].toLowerCase();\n }\n\n return undefined;\n}\n\n/**\n * Safely extracts combined text from strings, message arrays, or objects.\n */\nfunction extractAllText(input: unknown): string {\n if (input == null) return \"\";\n if (typeof input === \"string\") return input;\n if (typeof input === \"number\" || typeof input === \"boolean\")\n return String(input);\n if (Array.isArray(input)) {\n return input.map(extractAllText).filter(Boolean).join(\"\\n\");\n }\n if (typeof input === \"object\") {\n const obj = input as Record<string, unknown>;\n const parts: string[] = [];\n if (\"content\" in obj && obj.content != null) {\n parts.push(extractAllText(obj.content));\n }\n if (\"text\" in obj && obj.text != null) {\n parts.push(extractAllText(obj.text));\n }\n if (\"message\" in obj && obj.message != null) {\n parts.push(extractAllText(obj.message));\n }\n if (parts.length > 0) {\n return parts.join(\"\\n\");\n }\n try {\n return Object.values(obj).map(extractAllText).filter(Boolean).join(\"\\n\");\n } catch {\n return \"\";\n }\n }\n return \"\";\n}\n\ninterface ContextBlock {\n isProfile: boolean;\n attributes: string;\n content: string;\n}\n\n/**\n * Identifies <openviking-context> blocks, handling malformed and unclosed tags.\n */\nfunction findContextBlocks(text: string): ContextBlock[] {\n const blocks: ContextBlock[] = [];\n const openTagRegex = /<openviking-context\\b([^>]*)>/gi;\n let match: RegExpExecArray | null;\n\n const tagPositions: Array<{\n index: number;\n endIndex: number;\n attrs: string;\n }> = [];\n while ((match = openTagRegex.exec(text)) !== null) {\n tagPositions.push({\n index: match.index,\n endIndex: match.index + match[0].length,\n attrs: match[1] || \"\",\n });\n }\n\n // Fallback: If no <openviking-context> tag found, check for inner tags\n if (tagPositions.length === 0) {\n if (/<available-memories\\b/i.test(text)) {\n blocks.push({\n isProfile: true,\n attributes: 'source=\"profile\"',\n content: text,\n });\n } else if (/<memory\\b/i.test(text)) {\n blocks.push({\n isProfile: false,\n attributes: \"\",\n content: text,\n });\n }\n return blocks;\n }\n\n for (let i = 0; i < tagPositions.length; i++) {\n const current = tagPositions[i];\n const nextStart =\n i + 1 < tagPositions.length ? tagPositions[i + 1].index : text.length;\n const blockText = text.slice(current.endIndex, nextStart);\n\n const closeIndex = blockText.search(/<\\/openviking-context>/i);\n const content =\n closeIndex !== -1 ? blockText.slice(0, closeIndex) : blockText;\n\n const isProfile = /\\bsource\\s*=\\s*[\"']profile[\"']/i.test(current.attrs);\n blocks.push({\n isProfile,\n attributes: current.attrs,\n content,\n });\n }\n\n return blocks;\n}\n\n/**\n * Normalizes URI by trimming whitespace and trailing slash (except for bare scheme).\n */\nfunction normalizeUri(uri: string): string {\n let clean = uri.trim();\n if (clean.endsWith(\"/\") && !clean.endsWith(\"://\")) {\n clean = clean.slice(0, -1);\n }\n return clean;\n}\n\n/**\n * Parses profile items from an <openviking-context source=\"profile\"> block.\n */\nfunction parseProfileItems(blockContent: string): RecalledMemoryItem[] {\n const items: RecalledMemoryItem[] = [];\n\n // Extract content inside <available-memories>...</available-memories> if present\n let memContent = blockContent;\n const availMatch = blockContent.match(\n /<available-memories\\b[^>]*>([\\s\\S]*?)(?:<\\/available-memories>|$)/i\n );\n if (availMatch && availMatch[1]) {\n memContent = availMatch[1];\n }\n\n const lines = memContent.split(/\\r?\\n/);\n let currentBaseUri: string | null = null;\n\n for (const rawLine of lines) {\n const trimmed = rawLine.trim();\n if (!trimmed) continue;\n\n // Pattern 1: Directory prefix line:\n // e.g. \"viking://user/dsh/memories/preferences/\"\n // or \"- viking://user/dsh/memories/preferences/\"\n const baseMatch = trimmed.match(\n /^[-*•]?\\s*(viking:\\/\\/[^\\s<>\"'`]+?\\/)\\s*$/i\n );\n if (baseMatch) {\n currentBaseUri = baseMatch[1];\n continue;\n }\n\n // Pattern 2: Relative path under currentBaseUri:\n // e.g. \" - user@example.com/backup_strategy.md\"\n // \" - user/development workflow.md\"\n const bulletMatch = trimmed.match(/^[-*•]\\s+([^\\s<>\"'`].*?)$/);\n if (\n bulletMatch &&\n currentBaseUri &&\n !bulletMatch[1].startsWith(\"viking://\")\n ) {\n let relPath = bulletMatch[1].trim();\n // Remove any markdown links e.g. [name](...)\n relPath = relPath.replace(/^\\[([^\\]]+)\\](?:\\([^)]*\\))?/, \"$1\");\n relPath = relPath.replace(/[.,;:)\\]]+$/, \"\").trim();\n if (relPath) {\n const cleanBase = currentBaseUri.endsWith(\"/\")\n ? currentBaseUri\n : currentBaseUri + \"/\";\n const fullUri = normalizeUri(cleanBase + relPath.replace(/^\\/+/, \"\"));\n items.push({\n uri: fullUri,\n category: inferCategory(fullUri),\n source: \"profile\",\n });\n continue;\n }\n }\n\n // Pattern 3: Full viking:// URI on bullet point (handles potential spaces in filenames)\n const fullBulletMatch = trimmed.match(\n /^[-*•]\\s+(viking:\\/\\/[^<>\"'`\\r\\n]+)/i\n );\n if (fullBulletMatch) {\n let uri = fullBulletMatch[1].trim().replace(/[.,;:)\\]]+$/, \"\");\n if (uri.endsWith(\"/\")) {\n currentBaseUri = uri;\n } else {\n uri = normalizeUri(uri);\n items.push({\n uri,\n category: inferCategory(uri),\n source: \"profile\",\n });\n continue;\n }\n }\n\n // Pattern 4: Inline viking://[^\\s<>\"'`]+ matches\n const inlineMatches = trimmed.matchAll(/viking:\\/\\/[^\\s<>\"'`]+/gi);\n for (const m of inlineMatches) {\n let uri = m[0].replace(/[.,;:)\\]]+$/, \"\");\n if (uri.endsWith(\"/\")) {\n currentBaseUri = uri;\n } else {\n uri = normalizeUri(uri);\n items.push({\n uri,\n category: inferCategory(uri),\n source: \"profile\",\n });\n }\n }\n }\n\n return items;\n}\n\n/**\n * Parses recall items from an <openviking-context> block.\n */\nfunction parseRecallItems(blockContent: string): RecalledMemoryItem[] {\n const items: RecalledMemoryItem[] = [];\n\n // Match <memory ...> tags, handles self-closing and inner content\n const memoryTagRegex =\n /<memory\\b([^>]*?)(?:\\/>|>([\\s\\S]*?)(?:<\\/memory>|(?=<memory\\b)|$))/gi;\n let memMatch: RegExpExecArray | null;\n\n while ((memMatch = memoryTagRegex.exec(blockContent)) !== null) {\n const attrsString = memMatch[1] || \"\";\n const innerContent = memMatch[2] || \"\";\n\n // 1. Extract URI\n const uriMatch = attrsString.match(\n /\\buri\\s*=\\s*(?:[\"'](viking:\\/\\/[^\"']+)[\"']|(viking:\\/\\/[^\\s>]+))/i\n );\n if (!uriMatch) continue;\n const rawUri = uriMatch[1] || uriMatch[2];\n const uri = normalizeUri(rawUri);\n\n // 2. Extract score\n const scoreMatch = attrsString.match(\n /\\bscore\\s*=\\s*(?:[\"']([^\"']+)[\"']|([0-9.]+))/i\n );\n let score: number | undefined;\n const scoreStr = scoreMatch ? scoreMatch[1] || scoreMatch[2] : undefined;\n if (scoreStr) {\n const parsed = parseFloat(scoreStr);\n if (Number.isFinite(parsed)) {\n score = parsed;\n }\n }\n\n // 3. Extract explicit category/type attribute\n const typeMatch = attrsString.match(\n /\\b(?:type|category)\\s*=\\s*[\"']([^\"']+)[\"']/i\n );\n const explicitCategory = typeMatch ? typeMatch[1].trim() : undefined;\n const category = inferCategory(uri) || explicitCategory;\n\n // 4. Extract abstract (attribute or inner content)\n let abstractText: string | undefined;\n const abstractAttrMatch = attrsString.match(\n /\\babstract\\s*=\\s*[\"']([^\"']+)[\"']/i\n );\n if (abstractAttrMatch) {\n abstractText = abstractAttrMatch[1].trim();\n } else {\n const trimmedContent = innerContent.trim();\n if (trimmedContent) {\n abstractText = trimmedContent;\n }\n }\n\n items.push({\n uri,\n category,\n source: \"recall\",\n score,\n abstract: abstractText,\n });\n }\n\n return items;\n}\n\n/**\n * Parses conversation messages or text context to extract recalled OpenViking memories.\n *\n * Requirements:\n * - Extract profile items from <openviking-context source=\"profile\">...<available-memories>\n * - Extract recall items from <openviking-context>...<memory uri=\"...\">\n * - Infer category from URI\n * - Deduplicate by URI: if an item appears in both recall and profile, mark source: \"recall\"\n * - Ensure recalledCount === items.length\n */\nexport function parseRecalledMemories(\n input: string | any[] | null | undefined\n): RecalledMemoriesResult {\n if (input == null) {\n return {\n recalledCount: 0,\n items: [],\n profileItems: [],\n recallItems: [],\n };\n }\n\n const text = extractAllText(input);\n if (!text.trim()) {\n return {\n recalledCount: 0,\n items: [],\n profileItems: [],\n recallItems: [],\n };\n }\n\n const blocks = findContextBlocks(text);\n const rawProfileItems: RecalledMemoryItem[] = [];\n const rawRecallItems: RecalledMemoryItem[] = [];\n\n for (const block of blocks) {\n if (block.isProfile) {\n rawProfileItems.push(...parseProfileItems(block.content));\n } else {\n rawRecallItems.push(...parseRecallItems(block.content));\n }\n }\n\n // Deduplicate recall items by URI\n const recallMap = new Map<string, RecalledMemoryItem>();\n for (const item of rawRecallItems) {\n const existing = recallMap.get(item.uri);\n if (!existing) {\n recallMap.set(item.uri, { ...item });\n } else {\n if (existing.score === undefined && item.score !== undefined) {\n existing.score = item.score;\n } else if (existing.score !== undefined && item.score !== undefined) {\n existing.score = Math.max(existing.score, item.score);\n }\n if (!existing.abstract && item.abstract) {\n existing.abstract = item.abstract;\n }\n if (!existing.category && item.category) {\n existing.category = item.category;\n }\n }\n }\n\n // Deduplicate profile items by URI\n const profileMap = new Map<string, RecalledMemoryItem>();\n for (const item of rawProfileItems) {\n if (!profileMap.has(item.uri)) {\n profileMap.set(item.uri, { ...item });\n }\n }\n\n // Cross-deduplicate: if an item appears in both recall and profile, mark source: \"recall\"\n const itemsMap = new Map<string, RecalledMemoryItem>();\n\n // Add profile items first\n for (const [uri, item] of profileMap.entries()) {\n itemsMap.set(uri, item);\n }\n\n // Overlay recall items (promotes source to \"recall\" and attaches score/abstract)\n for (const [uri, item] of recallMap.entries()) {\n itemsMap.set(uri, item);\n }\n\n const items = Array.from(itemsMap.values());\n const profileItems = items.filter((it) => it.source === \"profile\");\n const recallItems = items.filter((it) => it.source === \"recall\");\n\n return {\n recalledCount: items.length,\n items,\n profileItems,\n recallItems,\n };\n}\n","import React, { useState, useEffect, useCallback, useRef } from \"react\";\nimport { HealthStatus, SessionStatus, SessionReadResult } from \"./api\";\nimport { themeVar } from \"./theme\";\nimport { RecalledMemoriesResult, RecalledMemoryItem } from \"./recallParser\";\nimport { COMMIT_THRESHOLD } from \"./OpenVikingStatusChip\";\n\n/**\n * `require`, который модульная система DSH передаёт фабрике бандла. Объявлен\n * здесь, потому что пакет собирается для браузера и типов Node не подключает.\n */\ndeclare const require: ((specifier: string) => any) | undefined;\n\n/**\n * Иконки DSH, доступные клиентскому плагину.\n *\n * Зависимости приходят через `require` внутри фабрики бандла — тем же путём,\n * что и react. Если пакет почему-то недоступен, иконка молча опускается:\n * отсутствие декоративного глифа лучше сломанной панели.\n */\nfunction dshIcon(name: string): React.ComponentType<{ size?: number }> | null {\n try {\n const primitives =\n typeof require === \"function\"\n ? require(\"@deepseek-ai/dsh-client-ui-primitives\")\n : null;\n const icon = primitives?.[name];\n return typeof icon === \"function\" ? icon : null;\n } catch {\n return null;\n }\n}\n\nexport interface OpenVikingStatusPopoverProps {\n sessionId: string;\n health: HealthStatus | null;\n sessionData: SessionStatus | null;\n /** Исход чтения сессии: отличает «нет доступа» от «накоплено ноль». */\n sessionRead?: SessionReadResult | null;\n recalledResult?: RecalledMemoriesResult;\n endpoint?: string;\n isCommitting?: boolean;\n commitError?: string | null;\n onCommitNow?: () => Promise<void> | void;\n onClose?: () => void;\n className?: string;\n style?: React.CSSProperties;\n}\n\n/**\n * Расчет процента заполнения пула накопленных токенов (0% - 100%).\n */\nexport function getProgressBarPercent(\n pendingTokens: number,\n threshold: number = COMMIT_THRESHOLD\n): number {\n if (!threshold || threshold <= 0) return 0;\n const ratio = (pendingTokens || 0) / threshold;\n return Math.min(100, Math.max(0, Math.round(ratio * 100)));\n}\n\n/**\n * Цветовой сдвиг шкалы токенов: предупреждение при приближении к порогу.\n */\nexport function getProgressBarColor(percent: number): string {\n if (percent >= 80) {\n return themeVar(\"stateWarning\");\n }\n return themeVar(\"stateSuccess\");\n}\n\n/**\n * Версия демона для показа в бейдже.\n *\n * OpenViking отдаёт `version` уже с префиксом (`v0.4.20`), а собственный `v`\n * сверху давал `vv0.4.20`. Нормализуем, а не срезаем: префикс добавляется\n * только если его нет, поэтому оба соглашения демона выглядят одинаково.\n */\nexport function formatDaemonVersion(version?: string): string | undefined {\n const value = version?.trim();\n if (!value) return undefined;\n return /^v/i.test(value) ? value : `v${value}`;\n}\n\n/**\n * Форматирование относительного времени для метки последнего коммита (например, \"2m ago\").\n */\nexport function formatRelativeTime(\n isoOrTimestamp?: string | number | null,\n now: number = Date.now()\n): string | undefined {\n if (!isoOrTimestamp) return undefined;\n const date = new Date(isoOrTimestamp);\n const time = date.getTime();\n if (isNaN(time)) return String(isoOrTimestamp);\n\n const diffMs = now - time;\n if (diffMs < 0) return \"just now\";\n\n const diffSec = Math.floor(diffMs / 1000);\n if (diffSec < 60) return \"just now\";\n\n const diffMin = Math.floor(diffSec / 60);\n if (diffMin < 60) return `${diffMin}m ago`;\n\n const diffHour = Math.floor(diffMin / 60);\n if (diffHour < 24) return `${diffHour}h ago`;\n\n const diffDay = Math.floor(diffHour / 24);\n return `${diffDay}d ago`;\n}\n\n/**\n * Извлечение имени конечного файла или относительного пути из viking:// URI.\n */\nexport function formatMemoryLeafName(uri: string): string {\n if (!uri) return \"\";\n const clean = uri.replace(/^viking:\\/\\/?/i, \"\");\n const memMatch = clean.match(/memories\\/[^/]+\\/(.+)$/i);\n if (memMatch && memMatch[1]) {\n return memMatch[1];\n }\n const segments = clean.split(\"/\").filter(Boolean);\n if (segments.length >= 2) {\n return segments.slice(-2).join(\"/\");\n }\n return segments[0] || clean;\n}\n\n/**\n * Форматирование адреса эндпоинта для отображения (удаляет протокол).\n */\nexport function formatEndpoint(endpoint?: string): string {\n if (!endpoint || !endpoint.trim()) {\n return \"127.0.0.1:1933\";\n }\n return endpoint.trim().replace(/^https?:\\/\\//, \"\");\n}\n\n/**\n * Усечение идентификатора сессии для компактного отображения.\n */\nexport function truncateSessionId(id: string, maxLen: number = 16): string {\n if (!id) return \"\";\n if (id.length <= maxLen) return id;\n return `${id.slice(0, maxLen)}...`;\n}\n\n/**\n * Стиль бейджа категории.\n *\n * Эталонная панель DSH не кодирует категории цветом, а подходящих цветовых\n * свойств тема не объявляет — поэтому все бейджи одинаковые и приглушённые.\n */\nexport function getCategoryBadgeStyle(_category?: string): React.CSSProperties {\n return { color: themeVar(\"labelTertiary\") };\n}\n\n/**\n * Обработка нажатия клавиши Escape для закрытия панели.\n */\nexport function handleEscapeKey(\n event: { key: string },\n onClose?: () => void\n): boolean {\n if (event.key === \"Escape\") {\n onClose?.();\n return true;\n }\n return false;\n}\n\n/**\n * Панель детального состояния контекстной памяти OpenViking (Status Popover).\n *\n * Оформление повторяет диалог статистики сессии DSH: та же поверхность, тень,\n * радиус, отступы и кегль.\n */\nexport function OpenVikingStatusPopover({\n sessionId,\n health,\n sessionData,\n sessionRead,\n recalledResult,\n endpoint,\n isCommitting = false,\n commitError = null,\n onCommitNow,\n onClose,\n className,\n style,\n}: OpenVikingStatusPopoverProps) {\n const [copied, setCopied] = useState(false);\n const copyTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n // Очистка таймера сброса статуса копирования при размонтировании\n useEffect(() => {\n return () => {\n if (copyTimeoutRef.current) {\n clearTimeout(copyTimeoutRef.current);\n }\n };\n }, []);\n\n const isOnline = health?.ok === true;\n const sessionUnreadable =\n isOnline && sessionRead != null && sessionRead.status !== \"ok\";\n const unauthorized = sessionRead?.status === \"unauthorized\";\n\n const statusColor = isOnline\n ? sessionUnreadable\n ? themeVar(\"stateWarning\")\n : themeVar(\"stateSuccess\")\n : themeVar(\"stateError\");\n\n const displaySessionId = sessionData?.session_id || sessionId || \"\";\n const pendingTokens = sessionData?.pending_tokens ?? 0;\n const progressPercent = getProgressBarPercent(pendingTokens);\n const progressBarColor = getProgressBarColor(progressPercent);\n\n const memoryItems: RecalledMemoryItem[] = recalledResult?.items || [];\n const recalledCount = recalledResult?.recalledCount ?? memoryItems.length;\n\n const CopyIcon = dshIcon(\"IconCopyOutline16\");\n const CheckIcon = dshIcon(\"IconCheckOutline16\");\n\n const handleCopySessionId = useCallback(() => {\n if (!displaySessionId) return;\n if (typeof navigator !== \"undefined\" && navigator.clipboard) {\n navigator.clipboard.writeText(displaySessionId).catch(() => {});\n setCopied(true);\n if (copyTimeoutRef.current) {\n clearTimeout(copyTimeoutRef.current);\n }\n copyTimeoutRef.current = setTimeout(() => {\n setCopied(false);\n copyTimeoutRef.current = null;\n }, 1500);\n }\n }, [displaySessionId]);\n\n const isCommitDisabled =\n isCommitting || !isOnline || sessionUnreadable || pendingTokens === 0;\n\n /** Подпись в строке «Pending Tokens». */\n const pendingLabel = sessionUnreadable\n ? \"unavailable\"\n : `${pendingTokens.toLocaleString()} / ${COMMIT_THRESHOLD.toLocaleString()}`;\n\n const rowStyle: React.CSSProperties = {\n display: \"flex\",\n justifyContent: \"space-between\",\n alignItems: \"center\",\n };\n const mutedStyle: React.CSSProperties = { color: themeVar(\"labelTertiary\") };\n const monoStyle: React.CSSProperties = { fontFamily: themeVar(\"fontMono\") };\n\n return (\n <div\n role=\"dialog\"\n aria-label=\"OpenViking Memory Details\"\n className={className}\n style={{\n position: \"absolute\",\n bottom: \"calc(100% + 8px)\",\n right: 0,\n zIndex: 1100,\n boxSizing: \"border-box\",\n width: \"max-content\",\n minWidth: \"min(300px, 100vw - 24px)\",\n maxWidth: \"min(440px, 100vw - 24px)\",\n background: themeVar(\"panelSurface\"),\n boxShadow: themeVar(\"panelElevation\"),\n color: themeVar(\"labelSecondary\"),\n cursor: \"default\",\n border: 0,\n borderRadius: \"12px\",\n padding: \"16px\",\n fontSize: \"12px\",\n lineHeight: \"18px\",\n ...({\n \"--dsw-elevation-stroke-color\": themeVar(\"panelStroke\"),\n } as React.CSSProperties),\n ...style,\n }}\n >\n <style>{`@keyframes ov-spin { from { transform: rotate(0deg); } to { transform: rotate(360deg); } }`}</style>\n\n {/* Заголовок: название, эндпоинт, бейдж состояния */}\n <div\n style={{\n display: \"flex\",\n justifyContent: \"space-between\",\n gap: \"16px\",\n marginBottom: \"8px\",\n color: themeVar(\"labelPrimary\"),\n fontWeight: 500,\n }}\n >\n <span style={{ minWidth: 0 }}>\n OpenViking Memory{\" \"}\n <span\n data-testid=\"endpoint-label\"\n style={{ ...mutedStyle, ...monoStyle, fontWeight: 400 }}\n >\n {formatEndpoint(endpoint)}\n </span>\n </span>\n\n <span\n data-testid=\"status-badge\"\n style={{\n display: \"inline-flex\",\n alignItems: \"center\",\n gap: \"6px\",\n color: statusColor,\n flexShrink: 0,\n }}\n >\n <span\n data-testid=\"status-badge-dot\"\n aria-hidden=\"true\"\n style={{\n width: \"6px\",\n height: \"6px\",\n borderRadius: \"50%\",\n backgroundColor: statusColor,\n flexShrink: 0,\n }}\n />\n <span>\n {isOnline\n ? [\n \"ONLINE\",\n formatDaemonVersion(health?.version),\n sessionUnreadable ? \"· no session access\" : null,\n ]\n .filter(Boolean)\n .join(\" \")\n : \"OFFLINE\"}\n </span>\n </span>\n </div>\n\n <div\n style={{\n borderTop: `.5px solid ${themeVar(\"hairline\")}`,\n marginBottom: \"10px\",\n }}\n aria-hidden=\"true\"\n />\n\n {/* Метаданные сессии */}\n <div\n style={{\n display: \"flex\",\n flexDirection: \"column\",\n gap: \"6px\",\n marginBottom: \"10px\",\n }}\n >\n <div style={rowStyle}>\n <span style={mutedStyle}>Session ID:</span>\n <span style={{ display: \"flex\", alignItems: \"center\", gap: \"4px\" }}>\n <span\n data-testid=\"session-id-value\"\n role=\"button\"\n tabIndex={0}\n onKeyDown={(e) => {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n handleCopySessionId();\n }\n }}\n aria-label=\"Click to copy Session ID\"\n style={{ ...monoStyle, cursor: \"pointer\" }}\n title={displaySessionId}\n onClick={handleCopySessionId}\n >\n {truncateSessionId(displaySessionId)}\n </span>\n <button\n type=\"button\"\n data-testid=\"copy-session-btn\"\n onClick={handleCopySessionId}\n title={copied ? \"Copied!\" : \"Copy Session ID\"}\n aria-label={copied ? \"Copied!\" : \"Copy Session ID\"}\n style={{\n background: \"none\",\n border: \"none\",\n cursor: \"pointer\",\n padding: \"2px\",\n display: \"inline-flex\",\n alignItems: \"center\",\n color: copied\n ? themeVar(\"stateSuccess\")\n : themeVar(\"labelTertiary\"),\n }}\n >\n {copied\n ? CheckIcon && <CheckIcon size={14} />\n : CopyIcon && <CopyIcon size={14} />}\n </button>\n </span>\n </div>\n\n {sessionData?.peer_id && (\n <div style={rowStyle}>\n <span style={mutedStyle}>Peer ID:</span>\n <span\n data-testid=\"peer-id-value\"\n style={{\n ...monoStyle,\n maxWidth: \"180px\",\n overflow: \"hidden\",\n textOverflow: \"ellipsis\",\n whiteSpace: \"nowrap\",\n }}\n title={sessionData.peer_id}\n >\n {sessionData.peer_id}\n </span>\n </div>\n )}\n\n {sessionData?.last_commit_at && (\n <div style={rowStyle}>\n <span style={mutedStyle}>Last Commit:</span>\n <span\n data-testid=\"last-commit-value\"\n title={sessionData.last_commit_at}\n >\n {formatRelativeTime(sessionData.last_commit_at) ||\n sessionData.last_commit_at}\n </span>\n </div>\n )}\n </div>\n\n {/* Накопленные токены */}\n <div style={{ marginBottom: \"12px\" }}>\n <div style={{ ...rowStyle, marginBottom: \"4px\" }}>\n <span style={mutedStyle}>Pending Tokens:</span>\n <span data-testid=\"pending-tokens-label\">{pendingLabel}</span>\n </div>\n {!sessionUnreadable && (\n <div\n data-testid=\"progress-bar-track\"\n style={{\n width: \"100%\",\n height: \"6px\",\n borderRadius: \"3px\",\n backgroundColor: themeVar(\"insetSurface\"),\n overflow: \"hidden\",\n }}\n >\n <div\n data-testid=\"progress-bar-fill\"\n style={{\n width: `${progressPercent}%`,\n height: \"100%\",\n backgroundColor: progressBarColor,\n transition: \"width 0.3s ease, background-color 0.3s ease\",\n }}\n />\n </div>\n )}\n </div>\n\n {/* Причина недоступности счётчиков */}\n {sessionUnreadable && (\n <div\n data-testid=\"session-unreadable-notice\"\n style={{\n marginBottom: \"12px\",\n color: themeVar(\"labelTertiary\"),\n }}\n >\n {unauthorized\n ? \"The daemon requires an API key. Set openviking_api_key in localStorage to read session counters.\"\n : \"Session counters are unavailable right now.\"}\n </div>\n )}\n\n {/* Подмешанные воспоминания */}\n <div style={{ marginBottom: \"12px\" }}>\n <div\n style={{\n marginBottom: \"4px\",\n color: themeVar(\"labelPrimary\"),\n fontWeight: 500,\n }}\n >\n {`Recalled Memories (${recalledCount})`}\n </div>\n\n {memoryItems.length === 0 ? (\n <div\n data-testid=\"empty-memories-message\"\n style={{ ...mutedStyle, padding: \"4px 0\" }}\n >\n No memories recalled in this session\n </div>\n ) : (\n <div\n data-testid=\"recalled-memories-list\"\n style={{\n maxHeight: \"140px\",\n overflowY: \"auto\",\n display: \"flex\",\n flexDirection: \"column\",\n gap: \"4px\",\n paddingRight: \"2px\",\n }}\n >\n {memoryItems.map((item, idx) => (\n <div\n key={`${item.uri}-${idx}`}\n data-testid=\"recalled-memory-item\"\n title={item.uri}\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: \"6px\",\n minWidth: 0,\n }}\n >\n <span\n data-testid=\"memory-category-badge\"\n style={{\n textTransform: \"uppercase\",\n flexShrink: 0,\n ...getCategoryBadgeStyle(item.category),\n }}\n >\n {item.category || \"memory\"}\n </span>\n\n <span\n data-testid=\"memory-source-badge\"\n style={{ ...mutedStyle, flexShrink: 0 }}\n >\n {item.source}\n </span>\n\n <span\n data-testid=\"memory-leaf-name\"\n style={{\n overflow: \"hidden\",\n textOverflow: \"ellipsis\",\n whiteSpace: \"nowrap\",\n minWidth: 0,\n }}\n >\n {formatMemoryLeafName(item.uri)}\n </span>\n </div>\n ))}\n </div>\n )}\n </div>\n\n {commitError && (\n <div\n data-testid=\"commit-error-message\"\n style={{ marginBottom: \"8px\", color: themeVar(\"stateError\") }}\n >\n {commitError}\n </div>\n )}\n\n <button\n type=\"button\"\n data-testid=\"commit-now-btn\"\n onClick={() => void onCommitNow?.()}\n disabled={isCommitDisabled}\n style={{\n width: \"100%\",\n padding: \"6px 10px\",\n borderRadius: \"8px\",\n border: `.5px solid ${themeVar(\"hairline\")}`,\n background: isCommitDisabled\n ? \"transparent\"\n : themeVar(\"hoverBackground\"),\n color: isCommitDisabled\n ? themeVar(\"labelTertiary\")\n : themeVar(\"labelPrimary\"),\n cursor: isCommitDisabled ? \"default\" : \"pointer\",\n font: \"inherit\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n gap: \"6px\",\n }}\n >\n {isCommitting ? (\n <>\n <span\n aria-hidden=\"true\"\n style={{\n display: \"inline-block\",\n width: \"10px\",\n height: \"10px\",\n borderRadius: \"50%\",\n border: `2px solid ${themeVar(\"stateWarning\")}`,\n borderTopColor: \"transparent\",\n animation: \"ov-spin 1s linear infinite\",\n }}\n />\n <span>Committing...</span>\n </>\n ) : (\n <span>Commit To Memory Now</span>\n )}\n </button>\n </div>\n );\n}\n","import React, { useState, useEffect } from \"react\";\nimport { themeVar } from \"./theme\";\nimport { defaultOpenVikingClient } from \"./api\";\n\nexport interface OpenVikingConfigData {\n endpoint: string;\n hasApiKey: boolean;\n source: \"env\" | \"ovcli\" | \"ov\" | \"settings\" | \"default\";\n}\n\nexport interface OpenVikingSettingsSectionProps {\n initialConfig?: OpenVikingConfigData;\n onConfigSaved?: (config: OpenVikingConfigData) => void;\n className?: string;\n style?: React.CSSProperties;\n}\n\nconst API_CONFIG = \"/openviking-status/api/config\";\nconst API_TEST = \"/openviking-status/api/test-connection\";\n\nconst SOURCE_LABELS: Record<string, string> = {\n ovcli: \"Auto-detected from ~/.openviking/ovcli.conf\",\n env: \"Auto-detected from environment variables\",\n ov: \"Auto-detected from ~/.openviking/ov.conf\",\n settings: \"Custom override in DSH settings.yaml\",\n default: \"Default local configuration\",\n};\n\nexport function OpenVikingSettingsSection({\n initialConfig,\n onConfigSaved,\n className,\n style,\n}: OpenVikingSettingsSectionProps) {\n const [endpoint, setEndpoint] = useState(\n initialConfig?.endpoint || \"http://127.0.0.1:1933\"\n );\n const [apiKey, setApiKey] = useState(\"\");\n const [showKey, setShowKey] = useState(false);\n const [source, setSource] = useState<string>(\n initialConfig?.source || \"default\"\n );\n const [hasStoredKey, setHasStoredKey] = useState(\n initialConfig?.hasApiKey || false\n );\n const [loading, setLoading] = useState(!initialConfig);\n const [testing, setTesting] = useState(false);\n const [saving, setSaving] = useState(false);\n const [testResult, setTestResult] = useState<{\n ok: boolean;\n version?: string;\n storage?: string;\n authenticated?: boolean;\n error?: string;\n } | null>(null);\n const [flash, setFlash] = useState<{\n kind: \"ok\" | \"err\";\n message: string;\n } | null>(null);\n\n useEffect(() => {\n if (initialConfig) return;\n let active = true;\n\n async function fetchConfig() {\n try {\n setLoading(true);\n const res = await fetch(API_CONFIG, { cache: \"no-store\" });\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\n const data = (await res.json()) as OpenVikingConfigData;\n if (!active) return;\n const newEp = data.endpoint || \"http://127.0.0.1:1933\";\n setEndpoint(newEp);\n setSource(data.source || \"default\");\n setHasStoredKey(data.hasApiKey);\n defaultOpenVikingClient.clearResolvedSessions();\n } catch {\n // Fallback to local default if endpoint unreachable\n } finally {\n if (active) setLoading(false);\n }\n }\n\n void fetchConfig();\n return () => {\n active = false;\n };\n }, [initialConfig]);\n\n async function handleTestConnection() {\n setTesting(true);\n setTestResult(null);\n setFlash(null);\n try {\n const res = await fetch(API_TEST, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n endpoint: endpoint.trim(),\n apiKey: apiKey.trim() || undefined,\n }),\n });\n const data = await res.json();\n setTestResult(data);\n } catch (err) {\n setTestResult({\n ok: false,\n authenticated: false,\n error: String(err instanceof Error ? err.message : err),\n });\n } finally {\n setTesting(false);\n }\n }\n\n async function handleSave() {\n setSaving(true);\n setFlash(null);\n try {\n const res = await fetch(API_CONFIG, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n endpoint: endpoint.trim(),\n apiKey: apiKey.trim() || undefined,\n }),\n });\n const data = await res.json();\n if (!res.ok || data.error) {\n throw new Error(data.error || `HTTP ${res.status}`);\n }\n setFlash({ kind: \"ok\", message: \"Settings saved successfully\" });\n setSource(\"settings\");\n defaultOpenVikingClient.clearResolvedSessions();\n if (apiKey.trim()) {\n setHasStoredKey(true);\n setApiKey(\"\");\n }\n onConfigSaved?.(\n data.config || {\n endpoint,\n hasApiKey: hasStoredKey || Boolean(apiKey.trim()),\n source: \"settings\",\n }\n );\n } catch (err) {\n setFlash({\n kind: \"err\",\n message: `Failed to save: ${err instanceof Error ? err.message : String(err)}`,\n });\n } finally {\n setSaving(false);\n }\n }\n\n async function handleReset() {\n setSaving(true);\n setFlash(null);\n setTestResult(null);\n try {\n const res = await fetch(API_CONFIG, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ reset: true }),\n });\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\n // Re-fetch auto-detected configuration\n const cfgRes = await fetch(API_CONFIG, { cache: \"no-store\" });\n if (cfgRes.ok) {\n const data = (await cfgRes.json()) as OpenVikingConfigData;\n const newEp = data.endpoint || \"http://127.0.0.1:1933\";\n setEndpoint(newEp);\n setSource(data.source || \"default\");\n setHasStoredKey(data.hasApiKey);\n setApiKey(\"\");\n defaultOpenVikingClient.clearResolvedSessions();\n setFlash({\n kind: \"ok\",\n message: \"Reset to auto-detected local settings\",\n });\n onConfigSaved?.(data);\n }\n } catch (err) {\n setFlash({\n kind: \"err\",\n message: `Failed to reset: ${err instanceof Error ? err.message : String(err)}`,\n });\n } finally {\n setSaving(false);\n }\n }\n\n const sourceBadgeText = SOURCE_LABELS[source] || SOURCE_LABELS[\"default\"]!;\n\n return (\n <div\n className={`ov-settings-root ${className || \"\"}`}\n style={{\n display: \"flex\",\n flexDirection: \"column\",\n gap: 20,\n maxWidth: 720,\n padding: \"24px 28px\",\n color: themeVar(\"labelPrimary\"),\n fontSize: 14,\n lineHeight: 1.6,\n ...style,\n }}\n >\n {/* Header */}\n <div>\n <div\n style={{\n display: \"flex\",\n alignItems: \"baseline\",\n gap: 12,\n marginBottom: 6,\n }}\n >\n <h2\n style={{\n fontSize: 20,\n fontWeight: 600,\n margin: 0,\n color: themeVar(\"labelPrimary\"),\n }}\n >\n OpenViking Status\n </h2>\n <span\n style={{\n fontSize: 12,\n fontWeight: 500,\n padding: \"2px 8px\",\n borderRadius: 6,\n background: themeVar(\"insetSurface\"),\n border: `1px solid ${themeVar(\"hairline\")}`,\n color: themeVar(\"labelSecondary\"),\n }}\n >\n {sourceBadgeText}\n </span>\n </div>\n <p\n style={{ margin: 0, color: themeVar(\"labelSecondary\"), fontSize: 13 }}\n >\n Configure connection credentials for monitoring OpenViking persistent\n memory and session status.\n </p>\n </div>\n\n {/* Main Settings Card */}\n <div\n style={{\n border: `1px solid ${themeVar(\"hairline\")}`,\n borderRadius: 12,\n padding: 20,\n background: themeVar(\"insetSurface\"),\n display: \"flex\",\n flexDirection: \"column\",\n gap: 16,\n }}\n >\n {/* Endpoint Input */}\n <div>\n <label\n style={{\n display: \"block\",\n fontSize: 13,\n fontWeight: 600,\n marginBottom: 6,\n color: themeVar(\"labelPrimary\"),\n }}\n >\n Daemon Endpoint\n </label>\n <input\n type=\"text\"\n value={endpoint}\n onChange={(e) => setEndpoint(e.target.value)}\n placeholder=\"http://127.0.0.1:1933\"\n style={{\n width: \"100%\",\n boxSizing: \"border-box\",\n padding: \"9px 12px\",\n fontSize: 14,\n fontFamily: themeVar(\"fontMono\"),\n borderRadius: 8,\n border: `1px solid ${themeVar(\"hairline\")}`,\n background: themeVar(\"panelSurface\"),\n color: themeVar(\"labelPrimary\"),\n outline: \"none\",\n }}\n />\n <span\n style={{\n fontSize: 12,\n color: themeVar(\"labelTertiary\"),\n marginTop: 4,\n display: \"block\",\n }}\n >\n The URL of the local or remote OpenViking HTTP server. Resolved from\n the DSH host.\n </span>\n </div>\n\n {/* API Key Input */}\n <div>\n <div\n style={{\n display: \"flex\",\n justifyContent: \"space-between\",\n alignItems: \"center\",\n marginBottom: 6,\n }}\n >\n <label\n style={{\n fontSize: 13,\n fontWeight: 600,\n color: themeVar(\"labelPrimary\"),\n }}\n >\n API Token (Authentication)\n </label>\n {hasStoredKey && !apiKey && (\n <span\n style={{\n fontSize: 12,\n color: themeVar(\"stateSuccess\"),\n fontWeight: 500,\n }}\n >\n ● Active token configured\n </span>\n )}\n </div>\n <div style={{ display: \"flex\", gap: 8 }}>\n <input\n type={showKey ? \"text\" : \"password\"}\n value={apiKey}\n onChange={(e) => setApiKey(e.target.value)}\n placeholder={\n hasStoredKey\n ? \"(Token stored — leave blank to keep unchanged)\"\n : \"Optional or required if daemon uses auth_mode: api_key\"\n }\n style={{\n flex: 1,\n padding: \"9px 12px\",\n fontSize: 14,\n fontFamily: themeVar(\"fontMono\"),\n borderRadius: 8,\n border: `1px solid ${themeVar(\"hairline\")}`,\n background: themeVar(\"panelSurface\"),\n color: themeVar(\"labelPrimary\"),\n outline: \"none\",\n }}\n />\n <button\n type=\"button\"\n onClick={() => setShowKey((v) => !v)}\n style={{\n padding: \"0 14px\",\n fontSize: 13,\n fontWeight: 500,\n borderRadius: 8,\n border: `1px solid ${themeVar(\"hairline\")}`,\n background: themeVar(\"panelSurface\"),\n color: themeVar(\"labelSecondary\"),\n cursor: \"pointer\",\n }}\n >\n {showKey ? \"Hide\" : \"Show\"}\n </button>\n </div>\n <span\n style={{\n fontSize: 12,\n color: themeVar(\"labelTertiary\"),\n marginTop: 4,\n display: \"block\",\n }}\n >\n Required when the daemon runs with auth_mode: api_key. Local tokens\n are typically found in ~/.openviking/ovcli.conf.\n </span>\n </div>\n\n {/* Test Connection Banner */}\n {testResult && (\n <div\n style={{\n padding: \"10px 14px\",\n borderRadius: 8,\n fontSize: 13,\n display: \"flex\",\n alignItems: \"center\",\n gap: 8,\n border: `1px solid ${testResult.ok && testResult.authenticated ? themeVar(\"stateSuccess\") : themeVar(\"stateError\")}`,\n background: themeVar(\"panelSurface\"),\n color:\n testResult.ok && testResult.authenticated\n ? themeVar(\"stateSuccess\")\n : themeVar(\"stateError\"),\n }}\n >\n <span>{testResult.ok && testResult.authenticated ? \"●\" : \"✕\"}</span>\n <div style={{ flex: 1 }}>\n {testResult.ok && testResult.authenticated ? (\n <div>\n <strong>Connected successfully</strong>\n {testResult.version && <span> · {testResult.version}</span>}\n {testResult.storage && (\n <span> (storage: {testResult.storage})</span>\n )}\n </div>\n ) : (\n <div>\n <strong>Connection failed: </strong>\n <span>\n {testResult.error ||\n \"Unable to reach daemon or token unauthorized\"}\n </span>\n </div>\n )}\n </div>\n </div>\n )}\n\n {/* Action Buttons */}\n <div\n style={{\n display: \"flex\",\n flexWrap: \"wrap\",\n alignItems: \"center\",\n gap: 10,\n paddingTop: 4,\n }}\n >\n <button\n type=\"button\"\n disabled={testing || loading}\n onClick={() => void handleTestConnection()}\n style={{\n padding: \"8px 16px\",\n fontSize: 13,\n fontWeight: 500,\n borderRadius: 8,\n border: `1px solid ${themeVar(\"hairline\")}`,\n background: themeVar(\"panelSurface\"),\n color: themeVar(\"labelPrimary\"),\n cursor: testing ? \"not-allowed\" : \"pointer\",\n opacity: testing ? 0.6 : 1,\n }}\n >\n {testing ? \"Testing...\" : \"Test Connection\"}\n </button>\n\n <button\n type=\"button\"\n disabled={saving || loading}\n onClick={() => void handleSave()}\n style={{\n padding: \"8px 18px\",\n fontSize: 13,\n fontWeight: 600,\n borderRadius: 8,\n border: \"none\",\n background: themeVar(\"buttonPrimaryFill\"),\n color: themeVar(\"buttonPrimaryText\"),\n cursor: saving ? \"not-allowed\" : \"pointer\",\n opacity: saving ? 0.6 : 1,\n }}\n >\n {saving ? \"Saving...\" : \"Save Settings\"}\n </button>\n\n {source === \"settings\" && (\n <button\n type=\"button\"\n disabled={saving || loading}\n onClick={() => void handleReset()}\n style={{\n padding: \"8px 14px\",\n fontSize: 13,\n fontWeight: 500,\n borderRadius: 8,\n border: `1px solid ${themeVar(\"hairline\")}`,\n background: \"transparent\",\n color: themeVar(\"labelSecondary\"),\n cursor: \"pointer\",\n marginLeft: \"auto\",\n }}\n >\n Reset to Auto-detected\n </button>\n )}\n\n {flash && (\n <span\n style={{\n fontSize: 13,\n color:\n flash.kind === \"ok\"\n ? themeVar(\"stateSuccess\")\n : themeVar(\"stateError\"),\n fontWeight: 500,\n }}\n >\n {flash.message}\n </span>\n )}\n </div>\n </div>\n\n {/* Info Notice */}\n <div\n style={{\n border: `1px solid ${themeVar(\"hairline\")}`,\n borderRadius: 10,\n padding: \"14px 18px\",\n background: themeVar(\"panelSurface\"),\n fontSize: 13,\n color: themeVar(\"labelSecondary\"),\n lineHeight: 1.5,\n }}\n >\n <p\n style={{\n margin: \"0 0 6px 0\",\n fontWeight: 600,\n color: themeVar(\"labelPrimary\"),\n }}\n >\n How OpenViking connection works:\n </p>\n <ul style={{ margin: 0, paddingLeft: 18 }}>\n <li style={{ marginBottom: 4 }}>\n All requests to OpenViking proxy through the DSH Desktop host,\n making it work seamlessly even when managing DSH remotely over\n Tailscale, mobile, or LAN.\n </li>\n <li style={{ marginBottom: 4 }}>\n If OpenViking runs locally on the standard port (1933), the plugin\n auto-detects credentials from <code>~/.openviking/ovcli.conf</code>.\n </li>\n <li>\n Custom values saved here are persisted in{\" \"}\n <code>~/.dsh/settings.yaml</code> under the{\" \"}\n <code>openviking-status</code> namespace.\n </li>\n </ul>\n </div>\n </div>\n );\n}\n","import { OpenVikingStatusChip } from \"./OpenVikingStatusChip\";\nimport { OpenVikingSettingsSection } from \"./OpenVikingSettingsSection\";\n\nexport * from \"./api\";\nexport * from \"./theme\";\nexport * from \"./recallParser\";\nexport * from \"./OpenVikingStatusChip\";\nexport * from \"./OpenVikingStatusPopover\";\nexport * from \"./OpenVikingSettingsSection\";\n\nexport type OpenVikingSessionData = import(\"./api\").SessionStatus;\nexport type OpenVikingHealth = import(\"./api\").HealthStatus;\n\n/** Имя пакета, под которым DSH регистрирует клиентскую половину плагина. */\nexport const name = \"@dipertq/dsh-openviking-status\";\n\n/** Сервисы Cordis, которые должны быть готовы до вызова `apply`. */\nexport const inject = [\"slots\"];\n\n/**\n * Точка входа клиентского плагина DSH.\n *\n * 1. Занимает ячейку в `conversation.composer.dock` — чип со статусом OpenViking\n * под композером чата.\n * 2. Регистрирует раздел `settings.section` — страницу настроек OpenViking Status\n * в меню настроек DSH Desktop и Web.\n */\nexport function apply(ctx: any) {\n ctx.effect(\n () =>\n ctx.slots.inject(\"conversation.composer.dock\", () =>\n ctx.slots.register(\n {\n name: \"conversation.composer.dock\",\n id: \"openviking-status\",\n order: 50,\n label: \"OpenViking\",\n },\n OpenVikingStatusChip\n )\n ),\n \"openviking-status: composer stats chip\"\n );\n\n ctx.effect(\n () =>\n ctx.slots.inject(\"settings.section\", () =>\n ctx.slots.register(\n {\n name: \"settings.section\",\n id: \"openviking-status\",\n order: 35,\n label: () => \"OpenViking\",\n },\n OpenVikingSettingsSection\n )\n ),\n \"openviking-status: settings section\"\n );\n}\n"],"mappings":"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","names":["React","useState","useEffect","useCallback","useRef","name","jsx","jsxs","React","useState","useRef","useEffect","useCallback","useState","useEffect","jsx","jsxs","useState","useEffect"]}
|
|
1
|
+
{"version":3,"sources":["../src/client/OpenVikingStatusChip.tsx","../src/client/api.ts","../src/client/theme.ts","../src/client/recallParser.ts","../src/client/OpenVikingStatusPopover.tsx","../src/client/OpenVikingSettingsSection.tsx","../src/client/index.tsx"],"sourcesContent":["import React, {\n useState,\n useEffect,\n useCallback,\n useRef,\n useMemo,\n} from \"react\";\nimport ReactDOM from \"react-dom\";\nimport {\n HealthStatus,\n SessionStatus,\n SessionReadResult,\n OpenVikingClient,\n defaultOpenVikingClient,\n} from \"./api\";\nimport { themeVar } from \"./theme\";\nimport { RecalledMemoriesResult, parseRecalledMemories } from \"./recallParser\";\nimport { OpenVikingStatusPopover } from \"./OpenVikingStatusPopover\";\n\nexport const COMMIT_THRESHOLD = 20000;\n\n/**\n * Селектор поверх снимка диалога — стандартный проп слотов со скоупом сессии.\n * Штатные чипы статистики DSH читают узлы ровно так же.\n */\nexport type UseChat = (selector: (snapshot: any) => any) => any;\n\nexport interface OpenVikingStatusChipProps {\n sessionId: string;\n /** Стандартный проп слота: доступ к снимку текущего диалога. */\n useChat?: UseChat;\n /** Узлы диалога напрямую — для вызова вне слота и для тестов. */\n messages?: unknown;\n /** Готовый текст диалога; приоритетнее остальных источников. */\n contextText?: string;\n client?: OpenVikingClient;\n onCommit?: () => void;\n className?: string;\n initialHealth?: HealthStatus;\n initialSessionData?: SessionStatus;\n initialSessionRead?: SessionReadResult;\n initialOpen?: boolean;\n}\n\n/**\n * Форматирование количества токенов в килотокены (Math.round(tokens / 1000)k pend).\n */\nexport function formatPendingTokens(pendingTokens: number): string {\n const k = Math.round((pendingTokens || 0) / 1000);\n return `${k}k pend`;\n}\n\n/**\n * Формирование текстового ярлыка статусного чипа.\n * В онлайне: \"OV: <recalled> rec · <pending>k pend\"\n * В офлайне: \"OV offline\"\n */\nexport function formatStatusLabel(\n isOnline: boolean,\n recalledCount: number,\n pendingTokens: number\n): string {\n if (!isOnline) {\n return \"OV offline\";\n }\n return `OV: ${recalledCount} rec · ${formatPendingTokens(pendingTokens)}`;\n}\n\n/**\n * Формирование доступного заголовка / подсказки (title / aria-label).\n */\nexport function formatTooltipTitle({\n isOnline,\n isCommitting = false,\n recalledCount,\n pendingTokens,\n sessionUnreadable = false,\n}: {\n isOnline: boolean;\n isCommitting?: boolean;\n recalledCount: number;\n pendingTokens: number;\n sessionUnreadable?: boolean;\n}): string {\n if (!isOnline) {\n return \"OpenViking: Offline\";\n }\n if (sessionUnreadable) {\n return \"OpenViking: session unreadable — the daemon requires an API key\";\n }\n const countLabel = `${recalledCount} recalled`;\n const tokenLabel = `${(pendingTokens || 0).toLocaleString()} pending tokens`;\n if (isCommitting) {\n return `OpenViking: Committing... (${countLabel}, ${tokenLabel})`;\n }\n return `OpenViking: Online (${countLabel}, ${tokenLabel})`;\n}\n\n/**\n * Состояние индикатора: офлайн, нечитаемая сессия, коммит или норма.\n */\nexport function getStatusIndicatorColor(\n isOnline: boolean,\n isCommitting: boolean = false,\n sessionUnreadable: boolean = false\n): string {\n if (!isOnline) {\n return themeVar(\"stateError\");\n }\n if (isCommitting || sessionUnreadable) {\n return themeVar(\"stateWarning\");\n }\n return themeVar(\"stateSuccess\");\n}\n\n/**\n * Извлечение текста из снимка диалога DSH.\n *\n * Узлы разнородны: текст лежит то в `content` строкой, то массивом блоков, то\n * в `text`. Парсер воспоминаний работает по тексту, поэтому снимок сводится к\n * одной строке, а неизвестные формы просто пропускаются.\n */\nexport function chatNodesToText(nodes: unknown): string {\n if (!nodes) return \"\";\n\n const source = Array.isArray(nodes)\n ? nodes\n : typeof nodes === \"object\"\n ? Object.values(nodes as Record<string, unknown>)\n : [];\n\n const parts: string[] = [];\n\n const visit = (value: unknown, depth = 0): void => {\n if (depth > 4 || value === null || value === undefined) return;\n if (typeof value === \"string\") {\n parts.push(value);\n return;\n }\n if (Array.isArray(value)) {\n for (const item of value) visit(item, depth + 1);\n return;\n }\n if (typeof value === \"object\") {\n const record = value as Record<string, unknown>;\n for (const key of [\"content\", \"text\", \"data\", \"body\"]) {\n if (key in record) visit(record[key], depth + 1);\n }\n }\n };\n\n for (const node of source) visit(node);\n\n return parts.join(\"\\n\");\n}\n\n/**\n * Status Chip: состояние памяти OpenViking в строке статистики под композером.\n *\n * Внешняя обёртка над {@link StatusChipView}: выбирает источник диалога.\n * `useChat` — стандартный проп слота и сам по себе хук, поэтому вызывать его\n * условно нельзя; развилка сделана выбором компонента, а не условием внутри\n * одного.\n */\nexport function OpenVikingStatusChip(props: OpenVikingStatusChipProps) {\n const { useChat, ...rest } = props;\n if (\n useChat &&\n rest.contextText === undefined &&\n rest.messages === undefined\n ) {\n // Плагин делит строку статистики с чужими ячейками, поэтому сбой чтения\n // диалога не должен уронить её целиком: граница оставляет чип живым, но\n // без счётчика воспоминаний.\n return (\n <ChatReadBoundary fallback={<StatusChipView {...rest} />}>\n <ChatBackedStatusChip useChat={useChat} {...rest} />\n </ChatReadBoundary>\n );\n }\n return <StatusChipView {...rest} />;\n}\n\n/** Граница ошибок вокруг чтения снимка диалога. */\nclass ChatReadBoundary extends React.Component<\n { children: React.ReactNode; fallback: React.ReactNode },\n { failed: boolean }\n> {\n state = { failed: false };\n\n static getDerivedStateFromError() {\n return { failed: true };\n }\n\n render() {\n return this.state.failed ? this.props.fallback : this.props.children;\n }\n}\n\n/**\n * Вариант чипа, читающий диалог из снимка слота.\n *\n * `useChat` вызывается на верхнем уровне — так же, как в штатных чипах\n * статистики DSH.\n */\nfunction ChatBackedStatusChip({\n useChat,\n ...rest\n}: OpenVikingStatusChipProps & { useChat: UseChat }) {\n // Селектор защищён от неожиданной формы снимка: сбой при чтении диалога\n // стоит счётчика воспоминаний, но не должен ронять чужую строку статистики.\n const nodes = useChat((snapshot: any) => {\n try {\n return snapshot?.legacy?.nodes !== undefined\n ? snapshot.legacy.nodes\n : snapshot?.nodes;\n } catch {\n return undefined;\n }\n });\n return <StatusChipView {...rest} messages={nodes} />;\n}\n\n/** Собственно чип: отрисовка и опрос демона. */\nfunction StatusChipView({\n sessionId,\n messages,\n contextText,\n client,\n onCommit,\n className,\n initialHealth,\n initialSessionData,\n initialSessionRead,\n initialOpen = false,\n}: OpenVikingStatusChipProps) {\n const [health, setHealth] = useState<HealthStatus | null>(\n initialHealth ?? null\n );\n const [sessionRead, setSessionRead] = useState<SessionReadResult | null>(\n initialSessionRead ??\n (initialSessionData\n ? { status: \"ok\", session: initialSessionData }\n : null)\n );\n const [isOpen, setIsOpen] = useState(initialOpen);\n const [isCommitting, setIsCommitting] = useState(false);\n const [commitError, setCommitError] = useState<string | null>(null);\n const [isHovered, setIsHovered] = useState(false);\n const [statsHost, setStatsHost] = useState<Element | null>(null);\n const popoverRef = useRef<HTMLDivElement>(null);\n\n const apiClient = client ?? defaultOpenVikingClient;\n\n useEffect(() => {\n if (typeof document === \"undefined\") return;\n\n function findHost() {\n const el = document.querySelector(\"[data-composer-stats]\");\n setStatsHost((prev) => (prev !== el ? el : prev));\n }\n\n findHost();\n\n const observer = new MutationObserver(() => {\n findHost();\n });\n observer.observe(document.body, { childList: true, subtree: true });\n return () => observer.disconnect();\n }, []);\n\n // Источник текста диалога: готовая строка либо переданные узлы. Вариант с\n // `useChat` живёт в отдельном компоненте: этот проп сам является хуком, и\n // вызывать его условно нельзя.\n const conversationText = useMemo(() => {\n if (typeof contextText === \"string\") return contextText;\n return chatNodesToText(messages);\n }, [contextText, messages]);\n\n const recalledResult: RecalledMemoriesResult = useMemo(\n () => parseRecalledMemories(conversationText),\n [conversationText]\n );\n\n const fetchStatus = useCallback(async () => {\n try {\n const healthRes = await apiClient.checkHealth();\n setHealth(healthRes);\n\n if (!healthRes.ok) {\n return;\n }\n\n setSessionRead(await apiClient.readSession(sessionId));\n } catch {\n setHealth({ ok: false });\n }\n }, [sessionId, apiClient]);\n\n useEffect(() => {\n fetchStatus();\n const timer = setInterval(fetchStatus, 15000);\n return () => clearInterval(timer);\n }, [fetchStatus]);\n\n // Закрытие всплывающего окна при клике вне области виджета\n useEffect(() => {\n function handleClickOutside(event: MouseEvent) {\n if (\n popoverRef.current &&\n !popoverRef.current.contains(event.target as Node)\n ) {\n setIsOpen(false);\n }\n }\n function handleKeyDown(event: KeyboardEvent) {\n if (event.key === \"Escape\") {\n setIsOpen(false);\n }\n }\n if (isOpen) {\n document.addEventListener(\"mousedown\", handleClickOutside);\n document.addEventListener(\"keydown\", handleKeyDown);\n }\n return () => {\n document.removeEventListener(\"mousedown\", handleClickOutside);\n document.removeEventListener(\"keydown\", handleKeyDown);\n };\n }, [isOpen]);\n\n const handleCommitNow = async () => {\n if (isCommitting) return;\n setIsCommitting(true);\n setCommitError(null);\n try {\n const res = await apiClient.commitSession(sessionId, {\n keep_recent_count: 10,\n });\n if (res.ok) {\n await fetchStatus();\n onCommit?.();\n } else {\n setCommitError(res.error || \"Commit failed\");\n }\n } catch (e) {\n const msg = e instanceof Error ? e.message : String(e);\n setCommitError(msg || \"Failed to commit session\");\n console.error(\"[dsh-openviking-status] Failed to commit session:\", e);\n } finally {\n setIsCommitting(false);\n }\n };\n\n const isOnline = health?.ok === true;\n const sessionData = sessionRead?.status === \"ok\" ? sessionRead.session : null;\n // Отказ авторизации или недоступность — это «неизвестно», а не «ноль».\n const sessionUnreadable =\n isOnline && sessionRead !== null && sessionRead.status !== \"ok\";\n const pendingTokens = sessionData?.pending_tokens ?? 0;\n const recalledCount = recalledResult.recalledCount;\n\n const statusColor = getStatusIndicatorColor(\n isOnline,\n isCommitting,\n sessionUnreadable\n );\n const tooltipTitle = formatTooltipTitle({\n isOnline,\n isCommitting,\n recalledCount,\n pendingTokens,\n sessionUnreadable,\n });\n\n /** Текст справа от индикатора. */\n const label = !isOnline\n ? \"OV offline\"\n : sessionUnreadable\n ? `OV: ${recalledCount} rec · no access`\n : `OV: ${recalledCount} rec · ${Math.round(pendingTokens / 1000)}k pend`;\n\n const chipElement = (\n <span\n className={className}\n data-openviking-status=\"true\"\n style={{ minWidth: 0, display: \"inline-flex\", position: \"relative\" }}\n ref={popoverRef}\n >\n <button\n type=\"button\"\n onClick={() => setIsOpen(!isOpen)}\n onMouseEnter={() => setIsHovered(true)}\n onMouseLeave={() => setIsHovered(false)}\n aria-expanded={isOpen}\n aria-haspopup=\"dialog\"\n style={{\n boxSizing: \"border-box\",\n maxWidth: \"100%\",\n color: isHovered\n ? themeVar(\"labelSecondary\")\n : themeVar(\"labelTertiary\"),\n fontFamily: \"var(--dsw-font-family, system-ui)\",\n fontSize: \"var(--dsh-content-font-size-secondary, 13px)\",\n lineHeight:\n \"calc(20px + var(--dsh-content-font-delta-secondary, 0px))\",\n fontVariantNumeric: \"tabular-nums\",\n whiteSpace: \"nowrap\",\n background: isHovered ? themeVar(\"hoverBackground\") : \"transparent\",\n border: \"none\",\n borderRadius: \"24px\",\n alignItems: \"center\",\n gap: \"6px\",\n padding: \"1px 8px\",\n display: \"inline-flex\",\n cursor: \"pointer\",\n }}\n title={tooltipTitle}\n aria-label={tooltipTitle}\n >\n <span\n data-testid=\"status-dot\"\n aria-hidden=\"true\"\n style={{\n width: \"6px\",\n height: \"6px\",\n borderRadius: \"50%\",\n background: statusColor,\n flexShrink: 0,\n }}\n />\n <span style={{ textOverflow: \"ellipsis\", minWidth: 0 }}>{label}</span>\n </button>\n\n {isOpen && (\n <OpenVikingStatusPopover\n sessionId={sessionId}\n health={health}\n sessionData={sessionData}\n sessionRead={sessionRead}\n recalledResult={recalledResult}\n endpoint={apiClient.endpoint}\n isCommitting={isCommitting}\n commitError={commitError}\n onCommitNow={handleCommitNow}\n onClose={() => setIsOpen(false)}\n />\n )}\n </span>\n );\n\n if (statsHost && typeof document !== \"undefined\") {\n return ReactDOM.createPortal(chipElement, statsHost);\n }\n\n return (\n <div\n style={{\n maxWidth: \"var(--dsh-chat-content-width, 748px)\",\n boxSizing: \"border-box\",\n width: \"100%\",\n padding: \"4px calc(var(--dsh-composer-side-clearance, 0px) + 16px) 0px\",\n fontSize: \"var(--dsh-content-font-size-secondary, 13px)\",\n lineHeight: \"calc(20px + var(--dsh-content-font-delta-secondary, 0px))\",\n justifyContent: \"center\",\n gap: \"12px\",\n margin: \"0 auto\",\n display: \"flex\",\n }}\n >\n {chipElement}\n </div>\n );\n}\n","/**\n * Клиент OpenViking Session REST API и доменные типы.\n * Поддерживает проверку здоровья сервиса, получение состояния сессии\n * с разрешением префиксов идентификаторов (dsh-session-* / dsh-*) и выполнение коммита.\n */\n\n/**\n * Статус подключения и здоровья сервиса OpenViking\n */\nexport interface HealthStatus {\n ok: boolean;\n version?: string;\n storage?: string;\n endpoint?: string;\n error?: string;\n}\n\n/**\n * Состояние активной сессии OpenViking в соответствии с CONTEXT.md\n */\nexport interface SessionStatus {\n session_id: string;\n peer_id?: string;\n pending_tokens: number;\n message_count?: number;\n commit_count?: number;\n last_commit_at?: string;\n created_at?: string;\n updated_at?: string;\n}\n\n/**\n * Параметры операции коммита сессии\n */\nexport interface CommitOptions {\n keep_recent_count?: number;\n}\n\n/**\n * Результат операции коммита сессии\n */\nexport interface CommitResult {\n ok: boolean;\n error?: string;\n}\n\n/**\n * Исход попытки прочитать сессию.\n *\n * Причина неудачи важна: при `auth_mode: api_key` демон отвечает на `/health`\n * и отказывает на сессии, и «нечитаемо» нельзя показывать как «накоплено ноль».\n */\nexport type SessionReadResult =\n /** Сессия прочитана. */\n | { status: \"ok\"; session: SessionStatus }\n /** Демон требует ключ, которого у клиента нет. */\n | { status: \"unauthorized\" }\n /** Демон не знает такой сессии. */\n | { status: \"missing\" }\n /** До демона не удалось достучаться. */\n | { status: \"unreachable\"; detail?: string }\n /** Демон ответил ошибкой или неожиданным телом. */\n | { status: \"error\"; detail?: string };\n\n/**\n * Синонимы доменных понятий из CONTEXT.md\n */\nexport type PendingTokens = number;\nexport type PeerId = string;\n\n/**\n * Базовый URL по умолчанию для локального демона OpenViking\n */\nexport const DEFAULT_OPENVIKING_ENDPOINT = \"http://127.0.0.1:1933\";\n\n/**\n * Относительный маршрут хостового прокси на DSH Web Server\n */\nexport const PROXY_OPENVIKING_ENDPOINT = \"/openviking-status/api\";\n\n/**\n * Определение эндпоинта OpenViking из параметров, глобального контекста или localStorage\n */\nexport function resolveEndpoint(endpoint?: string): string {\n if (endpoint && endpoint.trim().length > 0) {\n return endpoint.trim().replace(/\\/+$/, \"\");\n }\n\n if (typeof window !== \"undefined\") {\n const win = window as unknown as Record<string, unknown>;\n if (\n typeof win.__OPENVIKING_ENDPOINT__ === \"string\" &&\n win.__OPENVIKING_ENDPOINT__.trim()\n ) {\n return win.__OPENVIKING_ENDPOINT__.trim().replace(/\\/+$/, \"\");\n }\n // В браузере внутри DSH запросы по умолчанию всегда идут через хостовый прокси\n return PROXY_OPENVIKING_ENDPOINT;\n }\n\n if (typeof localStorage !== \"undefined\") {\n try {\n const stored =\n localStorage.getItem(\"openviking_endpoint\") ||\n localStorage.getItem(\"OPENVIKING_ENDPOINT\");\n if (stored && stored.trim()) {\n return stored.trim().replace(/\\/+$/, \"\");\n }\n } catch {\n // Игнорируем ошибки доступа к хранилищу (security sandbox, incognito)\n }\n }\n\n return DEFAULT_OPENVIKING_ENDPOINT;\n}\n\n/**\n * Определение API-ключа из параметров, глобального контекста или localStorage\n */\nexport function resolveApiKey(apiKey?: string): string | undefined {\n if (apiKey && apiKey.trim().length > 0) {\n return apiKey.trim();\n }\n\n if (typeof window !== \"undefined\") {\n const win = window as unknown as Record<string, unknown>;\n if (\n typeof win.__OPENVIKING_API_KEY__ === \"string\" &&\n win.__OPENVIKING_API_KEY__.trim()\n ) {\n return win.__OPENVIKING_API_KEY__.trim();\n }\n }\n\n if (typeof localStorage !== \"undefined\") {\n try {\n const stored =\n localStorage.getItem(\"openviking_api_key\") ||\n localStorage.getItem(\"OPENVIKING_API_KEY\");\n if (stored && stored.trim()) {\n return stored.trim();\n }\n } catch {\n // Игнорируем ошибки доступа к хранилищу\n }\n }\n\n return undefined;\n}\n\n/**\n * Клиент REST API для взаимодействия с сессиями демона OpenViking\n */\nexport class OpenVikingClient {\n endpoint: string;\n apiKey?: string;\n private resolvedSessionIds = new Map<string, string>();\n\n constructor(endpoint?: string, apiKey?: string) {\n this.endpoint = resolveEndpoint(endpoint);\n this.apiKey = resolveApiKey(apiKey);\n }\n\n /**\n * Обновление конфигурации клиента на лету (например, после сохранения настроек в UI).\n */\n updateConfig(config: { endpoint?: string; apiKey?: string }): void {\n if (config.endpoint && config.endpoint.trim()) {\n this.endpoint = resolveEndpoint(config.endpoint);\n }\n if (config.apiKey !== undefined) {\n this.apiKey = resolveApiKey(config.apiKey);\n }\n this.resolvedSessionIds.clear();\n }\n\n /**\n * Очистить кэш разрешенных идентификаторов сессий.\n */\n clearResolvedSessions(): void {\n this.resolvedSessionIds.clear();\n }\n\n /**\n * Проверка, работает ли клиент через DSH Web Server proxy.\n */\n private isProxy(): boolean {\n return (\n this.endpoint.startsWith(\"/\") ||\n this.endpoint.includes(\"/openviking-status/api\")\n );\n }\n\n /**\n * Формирование заголовков запроса, включая опциональный заголовок авторизации\n */\n private getHeaders(\n customHeaders?: Record<string, string>\n ): Record<string, string> {\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n ...customHeaders,\n };\n if (this.apiKey) {\n headers[\"Authorization\"] = `Bearer ${this.apiKey}`;\n }\n return headers;\n }\n\n /**\n * Генерация кандидатов ID сессии для fallback-разрешения:\n * dsh-session-${id} <-> dsh-${id}\n */\n private getCandidateSessionIds(sessionId: string): string[] {\n const raw = sessionId.trim();\n const candidates: string[] = [];\n\n const cached = this.resolvedSessionIds.get(raw);\n if (cached) {\n candidates.push(cached);\n }\n\n if (raw.startsWith(\"dsh-session-\")) {\n const suffix = raw.slice(\"dsh-session-\".length);\n candidates.push(raw, `dsh-${suffix}`);\n } else if (raw.startsWith(\"dsh-\")) {\n const suffix = raw.slice(\"dsh-\".length);\n candidates.push(raw, `dsh-session-${suffix}`);\n } else if (raw.startsWith(\"session-\")) {\n // DSH отдаёт `session-<uuid>`, OpenViking хранит `dsh-session-<uuid>`:\n // достаточно приписать `dsh-`. Общая ветка ниже добавила бы ещё один\n // `session-`, и первый запрос на каждом опросе гарантированно давал 404.\n candidates.push(`dsh-${raw}`, raw);\n } else {\n // Если префикс dsh- отсутствует, сначала пробуем dsh-session-, затем dsh-, затем исходный raw\n candidates.push(`dsh-session-${raw}`, `dsh-${raw}`, raw);\n }\n\n // Удаление дубликатов с сохранением порядка следования\n return Array.from(new Set(candidates));\n }\n\n /**\n * Проверка доступности и состояния сервиса OpenViking\n */\n async checkHealth(): Promise<HealthStatus> {\n if (this.isProxy()) {\n try {\n const res = await fetch(`${this.endpoint}/health`, {\n method: \"GET\",\n headers: this.getHeaders(),\n });\n\n if (!res.ok) {\n return {\n ok: false,\n error: `HTTP ${res.status}: ${res.statusText}`,\n };\n }\n\n const body = (await res.json().catch(() => ({}))) as Record<\n string,\n unknown\n >;\n const isOk =\n body.ok !== false &&\n body.status !== \"error\" &&\n (body.ok === true ||\n body.status === \"ok\" ||\n body.status === \"healthy\" ||\n res.ok);\n\n return {\n ok: isOk,\n version: typeof body.version === \"string\" ? body.version : undefined,\n storage: typeof body.storage === \"string\" ? body.storage : undefined,\n };\n } catch (err) {\n return {\n ok: false,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n }\n\n try {\n const res = await fetch(`${this.endpoint}/health`, {\n method: \"GET\",\n headers: this.getHeaders(),\n });\n\n if (!res.ok) {\n return {\n ok: false,\n error: `HTTP ${res.status}: ${res.statusText}`,\n };\n }\n\n const body = (await res.json().catch(() => ({}))) as Record<\n string,\n unknown\n >;\n const isOk =\n body.ok !== false &&\n body.status !== \"error\" &&\n (body.ok === true ||\n body.status === \"ok\" ||\n body.status === \"healthy\" ||\n res.ok);\n\n return {\n ok: isOk,\n version: typeof body.version === \"string\" ? body.version : undefined,\n storage: typeof body.storage === \"string\" ? body.storage : undefined,\n };\n } catch (err) {\n return {\n ok: false,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n }\n\n /**\n * Чтение метаданных сессии с явной причиной неудачи.\n *\n * Демон может работать с `auth_mode: api_key`: тогда `/health` остаётся\n * открытым, а сессия отвечает 401. Схлопывать это в «нет данных» нельзя —\n * иначе интерфейс покажет живой индикатор рядом с нулями и умолчит о том,\n * что счётчики просто недоступны.\n */\n async readSession(sessionId: string): Promise<SessionReadResult> {\n if (!sessionId || !sessionId.trim()) {\n return { status: \"missing\" };\n }\n\n if (this.isProxy()) {\n try {\n const res = await fetch(\n `${this.endpoint}/session?id=${encodeURIComponent(sessionId.trim())}`,\n {\n method: \"GET\",\n headers: this.getHeaders(),\n }\n );\n\n if (res.status === 401 || res.status === 403) {\n return { status: \"unauthorized\" };\n }\n\n if (!res.ok) {\n return { status: \"error\", detail: `HTTP ${res.status}` };\n }\n\n const data = (await res.json()) as Record<string, unknown>;\n if (data.status === \"unauthorized\") return { status: \"unauthorized\" };\n if (data.status === \"missing\") return { status: \"missing\" };\n if (data.status === \"unreachable\")\n return {\n status: \"unreachable\",\n detail: typeof data.detail === \"string\" ? data.detail : undefined,\n };\n if (data.status === \"error\")\n return {\n status: \"error\",\n detail: typeof data.detail === \"string\" ? data.detail : undefined,\n };\n if (data.status === \"ok\" && data.session) {\n return {\n status: \"ok\",\n session: data.session as SessionStatus,\n };\n }\n return { status: \"error\", detail: \"malformed response from proxy\" };\n } catch (err) {\n return {\n status: \"unreachable\",\n detail: err instanceof Error ? err.message : String(err),\n };\n }\n }\n\n const candidates = this.getCandidateSessionIds(sessionId);\n\n for (const candidateId of candidates) {\n try {\n const res = await fetch(\n `${this.endpoint}/api/v1/sessions/${encodeURIComponent(candidateId)}`,\n {\n method: \"GET\",\n headers: this.getHeaders(),\n }\n );\n\n if (res.status === 404) {\n // Пробуем альтернативный формат идентификатора сессии\n continue;\n }\n\n if (res.status === 401 || res.status === 403) {\n return { status: \"unauthorized\" };\n }\n\n if (!res.ok) {\n return { status: \"error\", detail: `HTTP ${res.status}` };\n }\n\n const data = (await res.json()) as Record<string, unknown>;\n const raw = (data?.result ?? data?.data ?? data) as Record<\n string,\n unknown\n >;\n\n if (!raw || typeof raw !== \"object\") {\n return { status: \"error\", detail: \"malformed response body\" };\n }\n\n // Запоминаем успешно разрешенный идентификатор\n this.resolvedSessionIds.set(sessionId.trim(), candidateId);\n\n return {\n status: \"ok\",\n session: {\n session_id:\n typeof raw.session_id === \"string\" ? raw.session_id : candidateId,\n peer_id: typeof raw.peer_id === \"string\" ? raw.peer_id : undefined,\n pending_tokens:\n typeof raw.pending_tokens === \"number\" ? raw.pending_tokens : 0,\n message_count:\n typeof raw.message_count === \"number\"\n ? raw.message_count\n : undefined,\n commit_count:\n typeof raw.commit_count === \"number\"\n ? raw.commit_count\n : undefined,\n last_commit_at:\n typeof raw.last_commit_at === \"string\"\n ? raw.last_commit_at\n : typeof raw.last_commit === \"string\"\n ? raw.last_commit\n : undefined,\n created_at:\n typeof raw.created_at === \"string\" ? raw.created_at : undefined,\n updated_at:\n typeof raw.updated_at === \"string\" ? raw.updated_at : undefined,\n },\n };\n } catch (err) {\n return {\n status: \"unreachable\",\n detail: err instanceof Error ? err.message : String(err),\n };\n }\n }\n\n return { status: \"missing\" };\n }\n\n /**\n * Получение метаданных сессии по идентификатору.\n * Обёртка над {@link readSession} для вызывающих, которым причина неудачи\n * не нужна: любая неудача сводится к null.\n */\n async fetchSession(sessionId: string): Promise<SessionStatus | null> {\n const result = await this.readSession(sessionId);\n return result.status === \"ok\" ? result.session : null;\n }\n\n /**\n * Алиас для fetchSession\n */\n async getSession(sessionId: string): Promise<SessionStatus | null> {\n return this.fetchSession(sessionId);\n }\n\n /**\n * Инициация фиксации (коммита) накопленных токенов сессии в долговременную память\n */\n async commitSession(\n sessionId: string,\n options?: CommitOptions\n ): Promise<CommitResult> {\n if (!sessionId || !sessionId.trim()) {\n return { ok: false, error: \"Missing sessionId\" };\n }\n\n if (this.isProxy()) {\n try {\n const res = await fetch(`${this.endpoint}/session/commit`, {\n method: \"POST\",\n headers: this.getHeaders(),\n body: JSON.stringify({\n sessionId: sessionId.trim(),\n ...(options ?? { keep_recent_count: 10 }),\n }),\n });\n\n if (!res.ok) {\n return { ok: false, error: `HTTP ${res.status}` };\n }\n\n const data = (await res.json().catch(() => ({}))) as Record<\n string,\n unknown\n >;\n return {\n ok: data.ok === true,\n error: typeof data.error === \"string\" ? data.error : undefined,\n };\n } catch (err) {\n return {\n ok: false,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n }\n\n const candidates = this.getCandidateSessionIds(sessionId);\n const bodyPayload = JSON.stringify(options ?? { keep_recent_count: 10 });\n let lastError = \"Session commit failed\";\n\n for (const candidateId of candidates) {\n try {\n const res = await fetch(\n `${this.endpoint}/api/v1/sessions/${encodeURIComponent(candidateId)}/commit`,\n {\n method: \"POST\",\n headers: this.getHeaders(),\n body: bodyPayload,\n }\n );\n\n if (res.status === 404) {\n lastError = `Session not found: ${candidateId}`;\n continue;\n }\n\n if (!res.ok) {\n const errBody = (await res.json().catch(() => null)) as Record<\n string,\n unknown\n > | null;\n const errorMsg =\n (errBody?.error as Record<string, unknown>)?.message ||\n errBody?.message ||\n errBody?.error ||\n `HTTP ${res.status}: ${res.statusText}`;\n return { ok: false, error: String(errorMsg) };\n }\n\n this.resolvedSessionIds.set(sessionId.trim(), candidateId);\n return { ok: true };\n } catch (err) {\n return {\n ok: false,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n }\n\n return { ok: false, error: lastError };\n }\n}\n\n/**\n * Экземпляр клиента по умолчанию с автоматическим определением конфигурации\n */\nexport const defaultOpenVikingClient = new OpenVikingClient();\n\n/**\n * Вспомогательная функция проверки доступности OpenViking\n */\nexport function checkHealth(\n endpoint?: string,\n apiKey?: string\n): Promise<HealthStatus> {\n const client =\n endpoint || apiKey\n ? new OpenVikingClient(endpoint, apiKey)\n : defaultOpenVikingClient;\n return client.checkHealth();\n}\n\n/**\n * Вспомогательная функция получения состояния сессии\n */\nexport function fetchSession(\n sessionId: string,\n endpoint?: string,\n apiKey?: string\n): Promise<SessionStatus | null> {\n const client =\n endpoint || apiKey\n ? new OpenVikingClient(endpoint, apiKey)\n : defaultOpenVikingClient;\n return client.fetchSession(sessionId);\n}\n\n/**\n * Синоним для fetchSession\n */\nexport function getSession(\n sessionId: string,\n endpoint?: string,\n apiKey?: string\n): Promise<SessionStatus | null> {\n return fetchSession(sessionId, endpoint, apiKey);\n}\n\n/**\n * Вспомогательная функция выполнения коммита сессии\n */\nexport function commitSession(\n sessionId: string,\n options?: CommitOptions,\n endpoint?: string,\n apiKey?: string\n): Promise<CommitResult> {\n const client =\n endpoint || apiKey\n ? new OpenVikingClient(endpoint, apiKey)\n : defaultOpenVikingClient;\n return client.commitSession(sessionId, options);\n}\n","/**\n * Соответствие «визуальная роль → свойство темы DSH».\n *\n * Плагин стилизуется инлайново, поэтому каждое обращение к теме — строка\n * `var(--dsw-…)`. CSS-переменные падают на fallback молча, и опечатка в имени\n * выглядит как работающий код: именно так плагин однажды уехал на шестнадцать\n * несуществующих свойств и перестал следовать теме вовсе, сохранив осмысленный\n * вид.\n *\n * Единая таблица делает набор имён проверяемым как данные (`tests/theme.test.ts`\n * сверяет их с тем, что объявляет `@deepseek-ai/dsh-client-ui-theme`), а заодно\n * не даёт разойтись значениям между чипом и поповером.\n *\n * Значения подобраны по штатным компонентам DSH: чип повторяет `StatsPills`,\n * панель — диалог статистики сессии из `@deepseek-ai/dsh-client-ui-chat`.\n */\nexport const THEME = {\n /** Фон всплывающей панели — тот же, что у меню и диалогов DSH. */\n panelSurface: \"--dsw-specific-menu\",\n /** Тень панели. */\n panelElevation: \"--dsw-elevation-prominent\",\n /** Контур панели; задаётся через переменную тени, а не через border. */\n panelStroke: \"--dsw-alias-border-l1\",\n\n /** Заголовки и акцентный текст. */\n labelPrimary: \"--dsw-alias-label-primary\",\n /** Основной текст панели. */\n labelSecondary: \"--dsw-alias-label-secondary\",\n /** Приглушённый текст: подписи, значения, текст чипа в покое. */\n labelTertiary: \"--dsw-alias-label-tertiary\",\n\n /** Разделительная линия внутри панели. */\n hairline: \"--dsw-alias-border-l2\",\n\n /** Подсветка интерактивного элемента под курсором. */\n hoverBackground: \"--dsw-alias-interactive-bg-hover\",\n /** Подсветка нажатого элемента. */\n activeBackground: \"--dsw-alias-interactive-bg-active\",\n\n /** Демон доступен. */\n stateSuccess: \"--dsw-alias-state-success-primary\",\n /** Демон недоступен или сессия нечитаема. */\n stateError: \"--dsw-alias-state-error-primary\",\n /** Идёт коммит, либо накоплено близко к порогу. */\n stateWarning: \"--dsw-alias-state-warn-primary\",\n\n /** Утопленная поверхность: дорожка прогресс-бара. */\n insetSurface: \"--dsw-alias-bg-layer-2\",\n\n /** Заливка основной кнопки действий. */\n buttonPrimaryFill: \"--dsw-alias-button-primary-fill\",\n /** Цвет текста на основной кнопке действий. */\n buttonPrimaryText: \"--dsw-alias-label-primary-inverted\",\n\n /** Моноширинный шрифт для идентификаторов и путей. */\n fontMono: \"--dsw-font-markdown-code-font-family\",\n} as const;\n\n/** Роль в карте темы. */\nexport type ThemeRole = keyof typeof THEME;\n\n/**\n * Ссылка на свойство темы для инлайнового стиля.\n *\n * Намеренно без fallback: подставленное значение скрыло бы отсутствующее\n * свойство и вернуло бы ровно тот сбой, ради которого заведена эта карта.\n */\nexport function themeVar(role: ThemeRole): string {\n return `var(${THEME[role]})`;\n}\n","export interface RecalledMemoryItem {\n uri: string;\n category?: string;\n source: \"profile\" | \"recall\";\n score?: number;\n abstract?: string;\n}\n\nexport interface RecalledMemoriesResult {\n recalledCount: number;\n items: RecalledMemoryItem[];\n profileItems: RecalledMemoryItem[];\n recallItems: RecalledMemoryItem[];\n}\n\nconst KNOWN_CATEGORIES = new Set([\n \"preferences\",\n \"entities\",\n \"events\",\n \"skills\",\n \"resources\",\n \"profile\",\n]);\n\n/**\n * Infer the memory category from a viking:// URI.\n * Examples:\n * - viking://user/dsh/memories/preferences/... -> preferences\n * - viking://user/dsh/memories/entities/... -> entities\n * - viking://user/dsh/peers/user@example.com/memories/events/... -> events\n * - viking://user/dsh/skills/... -> skills\n * - viking://user/dsh/resources/... -> resources\n */\nexport function inferCategory(uri: string): string | undefined {\n if (!uri || typeof uri !== \"string\") return undefined;\n\n // 1. Direct match on /memories/<category>/ or /memories/<category>$\n const memoriesMatch = uri.match(/\\/memories\\/([^/#?]+)/i);\n if (memoriesMatch && memoriesMatch[1]) {\n return memoriesMatch[1].toLowerCase();\n }\n\n // 2. Strip viking:// and inspect path segments\n const cleanUri = uri.replace(/^viking:\\/\\/?/i, \"\");\n const segments = cleanUri.split(\"/\").filter(Boolean);\n\n // Check if any path segment matches a known category\n for (const seg of segments) {\n const lower = seg.toLowerCase();\n if (KNOWN_CATEGORIES.has(lower)) {\n return lower;\n }\n }\n\n // 3. Pattern: user/<user_id>/<category>/...\n if (segments[0]?.toLowerCase() === \"user\" && segments.length >= 3) {\n return segments[2].toLowerCase();\n }\n\n // 4. Pattern: <category>/...\n if (segments.length >= 2) {\n return segments[0].toLowerCase();\n }\n\n return undefined;\n}\n\n/**\n * Safely extracts combined text from strings, message arrays, or objects.\n */\nfunction extractAllText(input: unknown): string {\n if (input == null) return \"\";\n if (typeof input === \"string\") return input;\n if (typeof input === \"number\" || typeof input === \"boolean\")\n return String(input);\n if (Array.isArray(input)) {\n return input.map(extractAllText).filter(Boolean).join(\"\\n\");\n }\n if (typeof input === \"object\") {\n const obj = input as Record<string, unknown>;\n const parts: string[] = [];\n if (\"content\" in obj && obj.content != null) {\n parts.push(extractAllText(obj.content));\n }\n if (\"text\" in obj && obj.text != null) {\n parts.push(extractAllText(obj.text));\n }\n if (\"message\" in obj && obj.message != null) {\n parts.push(extractAllText(obj.message));\n }\n if (parts.length > 0) {\n return parts.join(\"\\n\");\n }\n try {\n return Object.values(obj).map(extractAllText).filter(Boolean).join(\"\\n\");\n } catch {\n return \"\";\n }\n }\n return \"\";\n}\n\ninterface ContextBlock {\n isProfile: boolean;\n attributes: string;\n content: string;\n}\n\n/**\n * Identifies <openviking-context> blocks, handling malformed and unclosed tags.\n */\nfunction findContextBlocks(text: string): ContextBlock[] {\n const blocks: ContextBlock[] = [];\n const openTagRegex = /<openviking-context\\b([^>]*)>/gi;\n let match: RegExpExecArray | null;\n\n const tagPositions: Array<{\n index: number;\n endIndex: number;\n attrs: string;\n }> = [];\n while ((match = openTagRegex.exec(text)) !== null) {\n tagPositions.push({\n index: match.index,\n endIndex: match.index + match[0].length,\n attrs: match[1] || \"\",\n });\n }\n\n // Fallback: If no <openviking-context> tag found, check for inner tags\n if (tagPositions.length === 0) {\n if (/<available-memories\\b/i.test(text)) {\n blocks.push({\n isProfile: true,\n attributes: 'source=\"profile\"',\n content: text,\n });\n } else if (/<memory\\b/i.test(text)) {\n blocks.push({\n isProfile: false,\n attributes: \"\",\n content: text,\n });\n }\n return blocks;\n }\n\n for (let i = 0; i < tagPositions.length; i++) {\n const current = tagPositions[i];\n const nextStart =\n i + 1 < tagPositions.length ? tagPositions[i + 1].index : text.length;\n const blockText = text.slice(current.endIndex, nextStart);\n\n const closeIndex = blockText.search(/<\\/openviking-context>/i);\n const content =\n closeIndex !== -1 ? blockText.slice(0, closeIndex) : blockText;\n\n const isProfile = /\\bsource\\s*=\\s*[\"']profile[\"']/i.test(current.attrs);\n blocks.push({\n isProfile,\n attributes: current.attrs,\n content,\n });\n }\n\n return blocks;\n}\n\n/**\n * Normalizes URI by trimming whitespace and trailing slash (except for bare scheme).\n */\nfunction normalizeUri(uri: string): string {\n let clean = uri.trim();\n if (clean.endsWith(\"/\") && !clean.endsWith(\"://\")) {\n clean = clean.slice(0, -1);\n }\n return clean;\n}\n\n/**\n * Parses profile items from an <openviking-context source=\"profile\"> block.\n */\nfunction parseProfileItems(blockContent: string): RecalledMemoryItem[] {\n const items: RecalledMemoryItem[] = [];\n\n // Extract content inside <available-memories>...</available-memories> if present\n let memContent = blockContent;\n const availMatch = blockContent.match(\n /<available-memories\\b[^>]*>([\\s\\S]*?)(?:<\\/available-memories>|$)/i\n );\n if (availMatch && availMatch[1]) {\n memContent = availMatch[1];\n }\n\n const lines = memContent.split(/\\r?\\n/);\n let currentBaseUri: string | null = null;\n\n for (const rawLine of lines) {\n const trimmed = rawLine.trim();\n if (!trimmed) continue;\n\n // Pattern 1: Directory prefix line:\n // e.g. \"viking://user/dsh/memories/preferences/\"\n // or \"- viking://user/dsh/memories/preferences/\"\n const baseMatch = trimmed.match(\n /^[-*•]?\\s*(viking:\\/\\/[^\\s<>\"'`]+?\\/)\\s*$/i\n );\n if (baseMatch) {\n currentBaseUri = baseMatch[1];\n continue;\n }\n\n // Pattern 2: Relative path under currentBaseUri:\n // e.g. \" - user@example.com/backup_strategy.md\"\n // \" - user/development workflow.md\"\n const bulletMatch = trimmed.match(/^[-*•]\\s+([^\\s<>\"'`].*?)$/);\n if (\n bulletMatch &&\n currentBaseUri &&\n !bulletMatch[1].startsWith(\"viking://\")\n ) {\n let relPath = bulletMatch[1].trim();\n // Remove any markdown links e.g. [name](...)\n relPath = relPath.replace(/^\\[([^\\]]+)\\](?:\\([^)]*\\))?/, \"$1\");\n relPath = relPath.replace(/[.,;:)\\]]+$/, \"\").trim();\n if (relPath) {\n const cleanBase = currentBaseUri.endsWith(\"/\")\n ? currentBaseUri\n : currentBaseUri + \"/\";\n const fullUri = normalizeUri(cleanBase + relPath.replace(/^\\/+/, \"\"));\n items.push({\n uri: fullUri,\n category: inferCategory(fullUri),\n source: \"profile\",\n });\n continue;\n }\n }\n\n // Pattern 3: Full viking:// URI on bullet point (handles potential spaces in filenames)\n const fullBulletMatch = trimmed.match(\n /^[-*•]\\s+(viking:\\/\\/[^<>\"'`\\r\\n]+)/i\n );\n if (fullBulletMatch) {\n let uri = fullBulletMatch[1].trim().replace(/[.,;:)\\]]+$/, \"\");\n if (uri.endsWith(\"/\")) {\n currentBaseUri = uri;\n } else {\n uri = normalizeUri(uri);\n items.push({\n uri,\n category: inferCategory(uri),\n source: \"profile\",\n });\n continue;\n }\n }\n\n // Pattern 4: Inline viking://[^\\s<>\"'`]+ matches\n const inlineMatches = trimmed.matchAll(/viking:\\/\\/[^\\s<>\"'`]+/gi);\n for (const m of inlineMatches) {\n let uri = m[0].replace(/[.,;:)\\]]+$/, \"\");\n if (uri.endsWith(\"/\")) {\n currentBaseUri = uri;\n } else {\n uri = normalizeUri(uri);\n items.push({\n uri,\n category: inferCategory(uri),\n source: \"profile\",\n });\n }\n }\n }\n\n return items;\n}\n\n/**\n * Parses recall items from an <openviking-context> block.\n */\nfunction parseRecallItems(blockContent: string): RecalledMemoryItem[] {\n const items: RecalledMemoryItem[] = [];\n\n // Match <memory ...> tags, handles self-closing and inner content\n const memoryTagRegex =\n /<memory\\b([^>]*?)(?:\\/>|>([\\s\\S]*?)(?:<\\/memory>|(?=<memory\\b)|$))/gi;\n let memMatch: RegExpExecArray | null;\n\n while ((memMatch = memoryTagRegex.exec(blockContent)) !== null) {\n const attrsString = memMatch[1] || \"\";\n const innerContent = memMatch[2] || \"\";\n\n // 1. Extract URI\n const uriMatch = attrsString.match(\n /\\buri\\s*=\\s*(?:[\"'](viking:\\/\\/[^\"']+)[\"']|(viking:\\/\\/[^\\s>]+))/i\n );\n if (!uriMatch) continue;\n const rawUri = uriMatch[1] || uriMatch[2];\n const uri = normalizeUri(rawUri);\n\n // 2. Extract score\n const scoreMatch = attrsString.match(\n /\\bscore\\s*=\\s*(?:[\"']([^\"']+)[\"']|([0-9.]+))/i\n );\n let score: number | undefined;\n const scoreStr = scoreMatch ? scoreMatch[1] || scoreMatch[2] : undefined;\n if (scoreStr) {\n const parsed = parseFloat(scoreStr);\n if (Number.isFinite(parsed)) {\n score = parsed;\n }\n }\n\n // 3. Extract explicit category/type attribute\n const typeMatch = attrsString.match(\n /\\b(?:type|category)\\s*=\\s*[\"']([^\"']+)[\"']/i\n );\n const explicitCategory = typeMatch ? typeMatch[1].trim() : undefined;\n const category = inferCategory(uri) || explicitCategory;\n\n // 4. Extract abstract (attribute or inner content)\n let abstractText: string | undefined;\n const abstractAttrMatch = attrsString.match(\n /\\babstract\\s*=\\s*[\"']([^\"']+)[\"']/i\n );\n if (abstractAttrMatch) {\n abstractText = abstractAttrMatch[1].trim();\n } else {\n const trimmedContent = innerContent.trim();\n if (trimmedContent) {\n abstractText = trimmedContent;\n }\n }\n\n items.push({\n uri,\n category,\n source: \"recall\",\n score,\n abstract: abstractText,\n });\n }\n\n return items;\n}\n\n/**\n * Parses conversation messages or text context to extract recalled OpenViking memories.\n *\n * Requirements:\n * - Extract profile items from <openviking-context source=\"profile\">...<available-memories>\n * - Extract recall items from <openviking-context>...<memory uri=\"...\">\n * - Infer category from URI\n * - Deduplicate by URI: if an item appears in both recall and profile, mark source: \"recall\"\n * - Ensure recalledCount === items.length\n */\nexport function parseRecalledMemories(\n input: string | any[] | null | undefined\n): RecalledMemoriesResult {\n if (input == null) {\n return {\n recalledCount: 0,\n items: [],\n profileItems: [],\n recallItems: [],\n };\n }\n\n const text = extractAllText(input);\n if (!text.trim()) {\n return {\n recalledCount: 0,\n items: [],\n profileItems: [],\n recallItems: [],\n };\n }\n\n const blocks = findContextBlocks(text);\n const rawProfileItems: RecalledMemoryItem[] = [];\n const rawRecallItems: RecalledMemoryItem[] = [];\n\n for (const block of blocks) {\n if (block.isProfile) {\n rawProfileItems.push(...parseProfileItems(block.content));\n } else {\n rawRecallItems.push(...parseRecallItems(block.content));\n }\n }\n\n // Deduplicate recall items by URI\n const recallMap = new Map<string, RecalledMemoryItem>();\n for (const item of rawRecallItems) {\n const existing = recallMap.get(item.uri);\n if (!existing) {\n recallMap.set(item.uri, { ...item });\n } else {\n if (existing.score === undefined && item.score !== undefined) {\n existing.score = item.score;\n } else if (existing.score !== undefined && item.score !== undefined) {\n existing.score = Math.max(existing.score, item.score);\n }\n if (!existing.abstract && item.abstract) {\n existing.abstract = item.abstract;\n }\n if (!existing.category && item.category) {\n existing.category = item.category;\n }\n }\n }\n\n // Deduplicate profile items by URI\n const profileMap = new Map<string, RecalledMemoryItem>();\n for (const item of rawProfileItems) {\n if (!profileMap.has(item.uri)) {\n profileMap.set(item.uri, { ...item });\n }\n }\n\n // Cross-deduplicate: if an item appears in both recall and profile, mark source: \"recall\"\n const itemsMap = new Map<string, RecalledMemoryItem>();\n\n // Add profile items first\n for (const [uri, item] of profileMap.entries()) {\n itemsMap.set(uri, item);\n }\n\n // Overlay recall items (promotes source to \"recall\" and attaches score/abstract)\n for (const [uri, item] of recallMap.entries()) {\n itemsMap.set(uri, item);\n }\n\n const items = Array.from(itemsMap.values());\n const profileItems = items.filter((it) => it.source === \"profile\");\n const recallItems = items.filter((it) => it.source === \"recall\");\n\n return {\n recalledCount: items.length,\n items,\n profileItems,\n recallItems,\n };\n}\n","import React, { useState, useEffect, useCallback, useRef } from \"react\";\nimport { HealthStatus, SessionStatus, SessionReadResult } from \"./api\";\nimport { themeVar } from \"./theme\";\nimport { RecalledMemoriesResult, RecalledMemoryItem } from \"./recallParser\";\nimport { COMMIT_THRESHOLD } from \"./OpenVikingStatusChip\";\n\n/**\n * `require`, который модульная система DSH передаёт фабрике бандла. Объявлен\n * здесь, потому что пакет собирается для браузера и типов Node не подключает.\n */\ndeclare const require: ((specifier: string) => any) | undefined;\n\n/**\n * Иконки DSH, доступные клиентскому плагину.\n *\n * Зависимости приходят через `require` внутри фабрики бандла — тем же путём,\n * что и react. Если пакет почему-то недоступен, иконка молча опускается:\n * отсутствие декоративного глифа лучше сломанной панели.\n */\nfunction dshIcon(name: string): React.ComponentType<{ size?: number }> | null {\n try {\n const primitives =\n typeof require === \"function\"\n ? require(\"@deepseek-ai/dsh-client-ui-primitives\")\n : null;\n const icon = primitives?.[name];\n return typeof icon === \"function\" ? icon : null;\n } catch {\n return null;\n }\n}\n\nexport interface OpenVikingStatusPopoverProps {\n sessionId: string;\n health: HealthStatus | null;\n sessionData: SessionStatus | null;\n /** Исход чтения сессии: отличает «нет доступа» от «накоплено ноль». */\n sessionRead?: SessionReadResult | null;\n recalledResult?: RecalledMemoriesResult;\n endpoint?: string;\n isCommitting?: boolean;\n commitError?: string | null;\n onCommitNow?: () => Promise<void> | void;\n onClose?: () => void;\n className?: string;\n style?: React.CSSProperties;\n}\n\n/**\n * Расчет процента заполнения пула накопленных токенов (0% - 100%).\n */\nexport function getProgressBarPercent(\n pendingTokens: number,\n threshold: number = COMMIT_THRESHOLD\n): number {\n if (!threshold || threshold <= 0) return 0;\n const ratio = (pendingTokens || 0) / threshold;\n return Math.min(100, Math.max(0, Math.round(ratio * 100)));\n}\n\n/**\n * Цветовой сдвиг шкалы токенов: предупреждение при приближении к порогу.\n */\nexport function getProgressBarColor(percent: number): string {\n if (percent >= 80) {\n return themeVar(\"stateWarning\");\n }\n return themeVar(\"stateSuccess\");\n}\n\n/**\n * Версия демона для показа в бейдже.\n *\n * OpenViking отдаёт `version` уже с префиксом (`v0.4.20`), а собственный `v`\n * сверху давал `vv0.4.20`. Нормализуем, а не срезаем: префикс добавляется\n * только если его нет, поэтому оба соглашения демона выглядят одинаково.\n */\nexport function formatDaemonVersion(version?: string): string | undefined {\n const value = version?.trim();\n if (!value) return undefined;\n return /^v/i.test(value) ? value : `v${value}`;\n}\n\n/**\n * Форматирование относительного времени для метки последнего коммита (например, \"2m ago\").\n */\nexport function formatRelativeTime(\n isoOrTimestamp?: string | number | null,\n now: number = Date.now()\n): string | undefined {\n if (!isoOrTimestamp) return undefined;\n const date = new Date(isoOrTimestamp);\n const time = date.getTime();\n if (isNaN(time)) return String(isoOrTimestamp);\n\n const diffMs = now - time;\n if (diffMs < 0) return \"just now\";\n\n const diffSec = Math.floor(diffMs / 1000);\n if (diffSec < 60) return \"just now\";\n\n const diffMin = Math.floor(diffSec / 60);\n if (diffMin < 60) return `${diffMin}m ago`;\n\n const diffHour = Math.floor(diffMin / 60);\n if (diffHour < 24) return `${diffHour}h ago`;\n\n const diffDay = Math.floor(diffHour / 24);\n return `${diffDay}d ago`;\n}\n\n/**\n * Извлечение имени конечного файла или относительного пути из viking:// URI.\n */\nexport function formatMemoryLeafName(uri: string): string {\n if (!uri) return \"\";\n const clean = uri.replace(/^viking:\\/\\/?/i, \"\");\n const memMatch = clean.match(/memories\\/[^/]+\\/(.+)$/i);\n if (memMatch && memMatch[1]) {\n return memMatch[1];\n }\n const segments = clean.split(\"/\").filter(Boolean);\n if (segments.length >= 2) {\n return segments.slice(-2).join(\"/\");\n }\n return segments[0] || clean;\n}\n\n/**\n * Форматирование адреса эндпоинта для отображения (удаляет протокол).\n */\nexport function formatEndpoint(endpoint?: string): string {\n if (!endpoint || !endpoint.trim() || endpoint.startsWith(\"/\")) {\n return \"127.0.0.1:1933\";\n }\n return endpoint\n .trim()\n .replace(/^https?:\\/\\//, \"\")\n .replace(/\\/+$/, \"\");\n}\n\n/**\n * Усечение идентификатора сессии для компактного отображения.\n */\nexport function truncateSessionId(id: string, maxLen: number = 16): string {\n if (!id) return \"\";\n if (id.length <= maxLen) return id;\n return `${id.slice(0, maxLen)}...`;\n}\n\n/**\n * Стиль бейджа категории.\n *\n * Эталонная панель DSH не кодирует категории цветом, а подходящих цветовых\n * свойств тема не объявляет — поэтому все бейджи одинаковые и приглушённые.\n */\nexport function getCategoryBadgeStyle(_category?: string): React.CSSProperties {\n return { color: themeVar(\"labelTertiary\") };\n}\n\n/**\n * Обработка нажатия клавиши Escape для закрытия панели.\n */\nexport function handleEscapeKey(\n event: { key: string },\n onClose?: () => void\n): boolean {\n if (event.key === \"Escape\") {\n onClose?.();\n return true;\n }\n return false;\n}\n\n/**\n * Панель детального состояния контекстной памяти OpenViking (Status Popover).\n *\n * Оформление повторяет диалог статистики сессии DSH: та же поверхность, тень,\n * радиус, отступы и кегль.\n */\nexport function OpenVikingStatusPopover({\n sessionId,\n health,\n sessionData,\n sessionRead,\n recalledResult,\n endpoint,\n isCommitting = false,\n commitError = null,\n onCommitNow,\n onClose,\n className,\n style,\n}: OpenVikingStatusPopoverProps) {\n const [copied, setCopied] = useState(false);\n const copyTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n // Очистка таймера сброса статуса копирования при размонтировании\n useEffect(() => {\n return () => {\n if (copyTimeoutRef.current) {\n clearTimeout(copyTimeoutRef.current);\n }\n };\n }, []);\n\n const isOnline = health?.ok === true;\n const sessionUnreadable =\n isOnline && sessionRead != null && sessionRead.status !== \"ok\";\n const unauthorized = sessionRead?.status === \"unauthorized\";\n\n const statusColor = isOnline\n ? sessionUnreadable\n ? themeVar(\"stateWarning\")\n : themeVar(\"stateSuccess\")\n : themeVar(\"stateError\");\n\n const displaySessionId = sessionData?.session_id || sessionId || \"\";\n const pendingTokens = sessionData?.pending_tokens ?? 0;\n const progressPercent = getProgressBarPercent(pendingTokens);\n const progressBarColor = getProgressBarColor(progressPercent);\n\n const memoryItems: RecalledMemoryItem[] = recalledResult?.items || [];\n const recalledCount = recalledResult?.recalledCount ?? memoryItems.length;\n\n const CopyIcon = dshIcon(\"IconCopyOutline16\");\n const CheckIcon = dshIcon(\"IconCheckOutline16\");\n\n const handleCopySessionId = useCallback(() => {\n if (!displaySessionId) return;\n if (typeof navigator !== \"undefined\" && navigator.clipboard) {\n navigator.clipboard.writeText(displaySessionId).catch(() => {});\n setCopied(true);\n if (copyTimeoutRef.current) {\n clearTimeout(copyTimeoutRef.current);\n }\n copyTimeoutRef.current = setTimeout(() => {\n setCopied(false);\n copyTimeoutRef.current = null;\n }, 1500);\n }\n }, [displaySessionId]);\n\n const isCommitDisabled =\n isCommitting || !isOnline || sessionUnreadable || pendingTokens === 0;\n\n /** Подпись в строке «Pending Tokens». */\n const pendingLabel = sessionUnreadable\n ? \"unavailable\"\n : `${pendingTokens.toLocaleString()} / ${COMMIT_THRESHOLD.toLocaleString()}`;\n\n const rowStyle: React.CSSProperties = {\n display: \"flex\",\n justifyContent: \"space-between\",\n alignItems: \"center\",\n };\n const mutedStyle: React.CSSProperties = { color: themeVar(\"labelTertiary\") };\n const monoStyle: React.CSSProperties = { fontFamily: themeVar(\"fontMono\") };\n\n return (\n <div\n role=\"dialog\"\n aria-label=\"OpenViking Memory Details\"\n className={className}\n style={{\n position: \"absolute\",\n bottom: \"calc(100% + 8px)\",\n right: 0,\n zIndex: 1100,\n boxSizing: \"border-box\",\n width: \"max-content\",\n minWidth: \"min(300px, 100vw - 24px)\",\n maxWidth: \"min(440px, 100vw - 24px)\",\n background: themeVar(\"panelSurface\"),\n boxShadow: themeVar(\"panelElevation\"),\n color: themeVar(\"labelSecondary\"),\n cursor: \"default\",\n border: 0,\n borderRadius: \"12px\",\n padding: \"16px\",\n fontSize: \"12px\",\n lineHeight: \"18px\",\n ...({\n \"--dsw-elevation-stroke-color\": themeVar(\"panelStroke\"),\n } as React.CSSProperties),\n ...style,\n }}\n >\n <style>{`@keyframes ov-spin { from { transform: rotate(0deg); } to { transform: rotate(360deg); } }`}</style>\n\n {/* Заголовок: название, эндпоинт, бейдж состояния */}\n <div\n style={{\n display: \"flex\",\n justifyContent: \"space-between\",\n gap: \"16px\",\n marginBottom: \"8px\",\n color: themeVar(\"labelPrimary\"),\n fontWeight: 500,\n }}\n >\n <span style={{ minWidth: 0 }}>\n OpenViking Memory{\" \"}\n <span\n data-testid=\"endpoint-label\"\n style={{ ...mutedStyle, ...monoStyle, fontWeight: 400 }}\n >\n {formatEndpoint(health?.endpoint || endpoint)}\n </span>\n </span>\n\n <span\n data-testid=\"status-badge\"\n style={{\n display: \"inline-flex\",\n alignItems: \"center\",\n gap: \"6px\",\n color: statusColor,\n flexShrink: 0,\n }}\n >\n <span\n data-testid=\"status-badge-dot\"\n aria-hidden=\"true\"\n style={{\n width: \"6px\",\n height: \"6px\",\n borderRadius: \"50%\",\n backgroundColor: statusColor,\n flexShrink: 0,\n }}\n />\n <span>\n {isOnline\n ? [\n \"ONLINE\",\n formatDaemonVersion(health?.version),\n sessionUnreadable ? \"· no session access\" : null,\n ]\n .filter(Boolean)\n .join(\" \")\n : \"OFFLINE\"}\n </span>\n </span>\n </div>\n\n <div\n style={{\n borderTop: `.5px solid ${themeVar(\"hairline\")}`,\n marginBottom: \"10px\",\n }}\n aria-hidden=\"true\"\n />\n\n {/* Метаданные сессии */}\n <div\n style={{\n display: \"flex\",\n flexDirection: \"column\",\n gap: \"6px\",\n marginBottom: \"10px\",\n }}\n >\n <div style={rowStyle}>\n <span style={mutedStyle}>Session ID:</span>\n <span style={{ display: \"flex\", alignItems: \"center\", gap: \"4px\" }}>\n <span\n data-testid=\"session-id-value\"\n role=\"button\"\n tabIndex={0}\n onKeyDown={(e) => {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n handleCopySessionId();\n }\n }}\n aria-label=\"Click to copy Session ID\"\n style={{ ...monoStyle, cursor: \"pointer\" }}\n title={displaySessionId}\n onClick={handleCopySessionId}\n >\n {truncateSessionId(displaySessionId)}\n </span>\n <button\n type=\"button\"\n data-testid=\"copy-session-btn\"\n onClick={handleCopySessionId}\n title={copied ? \"Copied!\" : \"Copy Session ID\"}\n aria-label={copied ? \"Copied!\" : \"Copy Session ID\"}\n style={{\n background: \"none\",\n border: \"none\",\n cursor: \"pointer\",\n padding: \"2px\",\n display: \"inline-flex\",\n alignItems: \"center\",\n color: copied\n ? themeVar(\"stateSuccess\")\n : themeVar(\"labelTertiary\"),\n }}\n >\n {copied\n ? CheckIcon && <CheckIcon size={14} />\n : CopyIcon && <CopyIcon size={14} />}\n </button>\n </span>\n </div>\n\n {sessionData?.peer_id && (\n <div style={rowStyle}>\n <span style={mutedStyle}>Peer ID:</span>\n <span\n data-testid=\"peer-id-value\"\n style={{\n ...monoStyle,\n maxWidth: \"180px\",\n overflow: \"hidden\",\n textOverflow: \"ellipsis\",\n whiteSpace: \"nowrap\",\n }}\n title={sessionData.peer_id}\n >\n {sessionData.peer_id}\n </span>\n </div>\n )}\n\n {sessionData?.last_commit_at && (\n <div style={rowStyle}>\n <span style={mutedStyle}>Last Commit:</span>\n <span\n data-testid=\"last-commit-value\"\n title={sessionData.last_commit_at}\n >\n {formatRelativeTime(sessionData.last_commit_at) ||\n sessionData.last_commit_at}\n </span>\n </div>\n )}\n </div>\n\n {/* Накопленные токены */}\n <div style={{ marginBottom: \"12px\" }}>\n <div style={{ ...rowStyle, marginBottom: \"4px\" }}>\n <span style={mutedStyle}>Pending Tokens:</span>\n <span data-testid=\"pending-tokens-label\">{pendingLabel}</span>\n </div>\n {!sessionUnreadable && (\n <div\n data-testid=\"progress-bar-track\"\n style={{\n width: \"100%\",\n height: \"6px\",\n borderRadius: \"3px\",\n backgroundColor: themeVar(\"insetSurface\"),\n overflow: \"hidden\",\n }}\n >\n <div\n data-testid=\"progress-bar-fill\"\n style={{\n width: `${progressPercent}%`,\n height: \"100%\",\n backgroundColor: progressBarColor,\n transition: \"width 0.3s ease, background-color 0.3s ease\",\n }}\n />\n </div>\n )}\n </div>\n\n {/* Причина недоступности счётчиков */}\n {sessionUnreadable && (\n <div\n data-testid=\"session-unreadable-notice\"\n style={{\n marginBottom: \"12px\",\n color: themeVar(\"labelTertiary\"),\n }}\n >\n {unauthorized\n ? \"The daemon requires an API key. Configure it in DSH Settings → OpenViking.\"\n : \"Session counters are unavailable right now.\"}\n </div>\n )}\n\n {/* Подмешанные воспоминания */}\n <div style={{ marginBottom: \"12px\" }}>\n <div\n style={{\n marginBottom: \"4px\",\n color: themeVar(\"labelPrimary\"),\n fontWeight: 500,\n }}\n >\n {`Recalled Memories (${recalledCount})`}\n </div>\n\n {memoryItems.length === 0 ? (\n <div\n data-testid=\"empty-memories-message\"\n style={{ ...mutedStyle, padding: \"4px 0\" }}\n >\n No memories recalled in this session\n </div>\n ) : (\n <div\n data-testid=\"recalled-memories-list\"\n style={{\n maxHeight: \"140px\",\n overflowY: \"auto\",\n display: \"flex\",\n flexDirection: \"column\",\n gap: \"4px\",\n paddingRight: \"2px\",\n }}\n >\n {memoryItems.map((item, idx) => (\n <div\n key={`${item.uri}-${idx}`}\n data-testid=\"recalled-memory-item\"\n title={item.uri}\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: \"6px\",\n minWidth: 0,\n }}\n >\n <span\n data-testid=\"memory-category-badge\"\n style={{\n textTransform: \"uppercase\",\n flexShrink: 0,\n ...getCategoryBadgeStyle(item.category),\n }}\n >\n {item.category || \"memory\"}\n </span>\n\n <span\n data-testid=\"memory-source-badge\"\n style={{ ...mutedStyle, flexShrink: 0 }}\n >\n {item.source}\n </span>\n\n <span\n data-testid=\"memory-leaf-name\"\n style={{\n overflow: \"hidden\",\n textOverflow: \"ellipsis\",\n whiteSpace: \"nowrap\",\n minWidth: 0,\n }}\n >\n {formatMemoryLeafName(item.uri)}\n </span>\n </div>\n ))}\n </div>\n )}\n </div>\n\n {commitError && (\n <div\n data-testid=\"commit-error-message\"\n style={{ marginBottom: \"8px\", color: themeVar(\"stateError\") }}\n >\n {commitError}\n </div>\n )}\n\n <button\n type=\"button\"\n data-testid=\"commit-now-btn\"\n onClick={() => void onCommitNow?.()}\n disabled={isCommitDisabled}\n style={{\n width: \"100%\",\n padding: \"6px 10px\",\n borderRadius: \"8px\",\n border: `.5px solid ${themeVar(\"hairline\")}`,\n background: isCommitDisabled\n ? \"transparent\"\n : themeVar(\"hoverBackground\"),\n color: isCommitDisabled\n ? themeVar(\"labelTertiary\")\n : themeVar(\"labelPrimary\"),\n cursor: isCommitDisabled ? \"default\" : \"pointer\",\n font: \"inherit\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n gap: \"6px\",\n }}\n >\n {isCommitting ? (\n <>\n <span\n aria-hidden=\"true\"\n style={{\n display: \"inline-block\",\n width: \"10px\",\n height: \"10px\",\n borderRadius: \"50%\",\n border: `2px solid ${themeVar(\"stateWarning\")}`,\n borderTopColor: \"transparent\",\n animation: \"ov-spin 1s linear infinite\",\n }}\n />\n <span>Committing...</span>\n </>\n ) : (\n <span>Commit To Memory Now</span>\n )}\n </button>\n </div>\n );\n}\n","import React, { useState, useEffect } from \"react\";\nimport { themeVar } from \"./theme\";\nimport { defaultOpenVikingClient } from \"./api\";\n\nexport interface OpenVikingConfigData {\n endpoint: string;\n hasApiKey: boolean;\n source: \"env\" | \"ovcli\" | \"ov\" | \"settings\" | \"default\";\n}\n\nexport interface OpenVikingSettingsSectionProps {\n initialConfig?: OpenVikingConfigData;\n onConfigSaved?: (config: OpenVikingConfigData) => void;\n className?: string;\n style?: React.CSSProperties;\n}\n\nconst API_CONFIG = \"/openviking-status/api/config\";\nconst API_TEST = \"/openviking-status/api/test-connection\";\n\nconst SOURCE_LABELS: Record<string, string> = {\n ovcli: \"Auto-detected from ~/.openviking/ovcli.conf\",\n env: \"Auto-detected from environment variables\",\n ov: \"Auto-detected from ~/.openviking/ov.conf\",\n settings: \"Custom override in DSH settings.yaml\",\n default: \"Default local configuration\",\n};\n\nexport function OpenVikingSettingsSection({\n initialConfig,\n onConfigSaved,\n className,\n style,\n}: OpenVikingSettingsSectionProps) {\n const [endpoint, setEndpoint] = useState(\n initialConfig?.endpoint || \"http://127.0.0.1:1933\"\n );\n const [apiKey, setApiKey] = useState(\"\");\n const [showKey, setShowKey] = useState(false);\n const [source, setSource] = useState<string>(\n initialConfig?.source || \"default\"\n );\n const [hasStoredKey, setHasStoredKey] = useState(\n initialConfig?.hasApiKey || false\n );\n const [loading, setLoading] = useState(!initialConfig);\n const [testing, setTesting] = useState(false);\n const [saving, setSaving] = useState(false);\n const [testResult, setTestResult] = useState<{\n ok: boolean;\n version?: string;\n storage?: string;\n authenticated?: boolean;\n error?: string;\n } | null>(null);\n const [flash, setFlash] = useState<{\n kind: \"ok\" | \"err\";\n message: string;\n } | null>(null);\n\n useEffect(() => {\n if (initialConfig) return;\n let active = true;\n\n async function fetchConfig() {\n try {\n setLoading(true);\n const res = await fetch(API_CONFIG, { cache: \"no-store\" });\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\n const data = (await res.json()) as OpenVikingConfigData;\n if (!active) return;\n const newEp = data.endpoint || \"http://127.0.0.1:1933\";\n setEndpoint(newEp);\n setSource(data.source || \"default\");\n setHasStoredKey(data.hasApiKey);\n defaultOpenVikingClient.clearResolvedSessions();\n } catch {\n // Fallback to local default if endpoint unreachable\n } finally {\n if (active) setLoading(false);\n }\n }\n\n void fetchConfig();\n return () => {\n active = false;\n };\n }, [initialConfig]);\n\n async function handleTestConnection() {\n setTesting(true);\n setTestResult(null);\n setFlash(null);\n try {\n const res = await fetch(API_TEST, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n endpoint: endpoint.trim(),\n apiKey: apiKey.trim() || undefined,\n }),\n });\n const data = await res.json();\n setTestResult(data);\n } catch (err) {\n setTestResult({\n ok: false,\n authenticated: false,\n error: String(err instanceof Error ? err.message : err),\n });\n } finally {\n setTesting(false);\n }\n }\n\n async function handleSave() {\n setSaving(true);\n setFlash(null);\n try {\n const res = await fetch(API_CONFIG, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n endpoint: endpoint.trim(),\n apiKey: apiKey.trim() || undefined,\n }),\n });\n const data = await res.json();\n if (!res.ok || data.error) {\n throw new Error(data.error || `HTTP ${res.status}`);\n }\n setFlash({ kind: \"ok\", message: \"Settings saved successfully\" });\n setSource(\"settings\");\n defaultOpenVikingClient.clearResolvedSessions();\n if (apiKey.trim()) {\n setHasStoredKey(true);\n setApiKey(\"\");\n }\n onConfigSaved?.(\n data.config || {\n endpoint,\n hasApiKey: hasStoredKey || Boolean(apiKey.trim()),\n source: \"settings\",\n }\n );\n } catch (err) {\n setFlash({\n kind: \"err\",\n message: `Failed to save: ${err instanceof Error ? err.message : String(err)}`,\n });\n } finally {\n setSaving(false);\n }\n }\n\n async function handleReset() {\n setSaving(true);\n setFlash(null);\n setTestResult(null);\n try {\n const res = await fetch(API_CONFIG, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ reset: true }),\n });\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\n // Re-fetch auto-detected configuration\n const cfgRes = await fetch(API_CONFIG, { cache: \"no-store\" });\n if (cfgRes.ok) {\n const data = (await cfgRes.json()) as OpenVikingConfigData;\n const newEp = data.endpoint || \"http://127.0.0.1:1933\";\n setEndpoint(newEp);\n setSource(data.source || \"default\");\n setHasStoredKey(data.hasApiKey);\n setApiKey(\"\");\n defaultOpenVikingClient.clearResolvedSessions();\n setFlash({\n kind: \"ok\",\n message: \"Reset to auto-detected local settings\",\n });\n onConfigSaved?.(data);\n }\n } catch (err) {\n setFlash({\n kind: \"err\",\n message: `Failed to reset: ${err instanceof Error ? err.message : String(err)}`,\n });\n } finally {\n setSaving(false);\n }\n }\n\n const sourceBadgeText = SOURCE_LABELS[source] || SOURCE_LABELS[\"default\"]!;\n\n return (\n <div\n className={`ov-settings-root ${className || \"\"}`}\n style={{\n display: \"flex\",\n flexDirection: \"column\",\n gap: 20,\n maxWidth: 720,\n padding: \"24px 28px\",\n color: themeVar(\"labelPrimary\"),\n fontSize: 14,\n lineHeight: 1.6,\n ...style,\n }}\n >\n {/* Header */}\n <div>\n <div\n style={{\n display: \"flex\",\n alignItems: \"baseline\",\n gap: 12,\n marginBottom: 6,\n }}\n >\n <h2\n style={{\n fontSize: 20,\n fontWeight: 600,\n margin: 0,\n color: themeVar(\"labelPrimary\"),\n }}\n >\n OpenViking Status\n </h2>\n <span\n style={{\n fontSize: 12,\n fontWeight: 500,\n padding: \"2px 8px\",\n borderRadius: 6,\n background: themeVar(\"insetSurface\"),\n border: `1px solid ${themeVar(\"hairline\")}`,\n color: themeVar(\"labelSecondary\"),\n }}\n >\n {sourceBadgeText}\n </span>\n </div>\n <p\n style={{ margin: 0, color: themeVar(\"labelSecondary\"), fontSize: 13 }}\n >\n Configure connection credentials for monitoring OpenViking persistent\n memory and session status.\n </p>\n </div>\n\n {/* Main Settings Card */}\n <div\n style={{\n border: `1px solid ${themeVar(\"hairline\")}`,\n borderRadius: 12,\n padding: 20,\n background: themeVar(\"insetSurface\"),\n display: \"flex\",\n flexDirection: \"column\",\n gap: 16,\n }}\n >\n {/* Endpoint Input */}\n <div>\n <label\n style={{\n display: \"block\",\n fontSize: 13,\n fontWeight: 600,\n marginBottom: 6,\n color: themeVar(\"labelPrimary\"),\n }}\n >\n Daemon Endpoint\n </label>\n <input\n type=\"text\"\n value={endpoint}\n onChange={(e) => setEndpoint(e.target.value)}\n placeholder=\"http://127.0.0.1:1933\"\n style={{\n width: \"100%\",\n boxSizing: \"border-box\",\n padding: \"9px 12px\",\n fontSize: 14,\n fontFamily: themeVar(\"fontMono\"),\n borderRadius: 8,\n border: `1px solid ${themeVar(\"hairline\")}`,\n background: themeVar(\"panelSurface\"),\n color: themeVar(\"labelPrimary\"),\n outline: \"none\",\n }}\n />\n <span\n style={{\n fontSize: 12,\n color: themeVar(\"labelTertiary\"),\n marginTop: 4,\n display: \"block\",\n }}\n >\n The URL of the local or remote OpenViking HTTP server. Resolved from\n the DSH host.\n </span>\n </div>\n\n {/* API Key Input */}\n <div>\n <div\n style={{\n display: \"flex\",\n justifyContent: \"space-between\",\n alignItems: \"center\",\n marginBottom: 6,\n }}\n >\n <label\n style={{\n fontSize: 13,\n fontWeight: 600,\n color: themeVar(\"labelPrimary\"),\n }}\n >\n API Token (Authentication)\n </label>\n {hasStoredKey && !apiKey && (\n <span\n style={{\n fontSize: 12,\n color: themeVar(\"stateSuccess\"),\n fontWeight: 500,\n }}\n >\n ● Active token configured\n </span>\n )}\n </div>\n <div style={{ display: \"flex\", gap: 8 }}>\n <input\n type={showKey ? \"text\" : \"password\"}\n value={apiKey}\n onChange={(e) => setApiKey(e.target.value)}\n placeholder={\n hasStoredKey\n ? \"(Token stored — leave blank to keep unchanged)\"\n : \"Optional or required if daemon uses auth_mode: api_key\"\n }\n style={{\n flex: 1,\n padding: \"9px 12px\",\n fontSize: 14,\n fontFamily: themeVar(\"fontMono\"),\n borderRadius: 8,\n border: `1px solid ${themeVar(\"hairline\")}`,\n background: themeVar(\"panelSurface\"),\n color: themeVar(\"labelPrimary\"),\n outline: \"none\",\n }}\n />\n <button\n type=\"button\"\n onClick={() => setShowKey((v) => !v)}\n style={{\n padding: \"0 14px\",\n fontSize: 13,\n fontWeight: 500,\n borderRadius: 8,\n border: `1px solid ${themeVar(\"hairline\")}`,\n background: themeVar(\"panelSurface\"),\n color: themeVar(\"labelSecondary\"),\n cursor: \"pointer\",\n }}\n >\n {showKey ? \"Hide\" : \"Show\"}\n </button>\n </div>\n <span\n style={{\n fontSize: 12,\n color: themeVar(\"labelTertiary\"),\n marginTop: 4,\n display: \"block\",\n }}\n >\n Required when the daemon runs with auth_mode: api_key. Local tokens\n are typically found in ~/.openviking/ovcli.conf.\n </span>\n </div>\n\n {/* Test Connection Banner */}\n {testResult && (\n <div\n style={{\n padding: \"10px 14px\",\n borderRadius: 8,\n fontSize: 13,\n display: \"flex\",\n alignItems: \"center\",\n gap: 8,\n border: `1px solid ${testResult.ok && testResult.authenticated ? themeVar(\"stateSuccess\") : themeVar(\"stateError\")}`,\n background: themeVar(\"panelSurface\"),\n color:\n testResult.ok && testResult.authenticated\n ? themeVar(\"stateSuccess\")\n : themeVar(\"stateError\"),\n }}\n >\n <span>{testResult.ok && testResult.authenticated ? \"●\" : \"✕\"}</span>\n <div style={{ flex: 1 }}>\n {testResult.ok && testResult.authenticated ? (\n <div>\n <strong>Connected successfully</strong>\n {testResult.version && <span> · {testResult.version}</span>}\n {testResult.storage && (\n <span> (storage: {testResult.storage})</span>\n )}\n </div>\n ) : (\n <div>\n <strong>Connection failed: </strong>\n <span>\n {testResult.error ||\n \"Unable to reach daemon or token unauthorized\"}\n </span>\n </div>\n )}\n </div>\n </div>\n )}\n\n {/* Action Buttons */}\n <div\n style={{\n display: \"flex\",\n flexWrap: \"wrap\",\n alignItems: \"center\",\n gap: 10,\n paddingTop: 4,\n }}\n >\n <button\n type=\"button\"\n disabled={testing || loading}\n onClick={() => void handleTestConnection()}\n style={{\n padding: \"8px 16px\",\n fontSize: 13,\n fontWeight: 500,\n borderRadius: 8,\n border: `1px solid ${themeVar(\"hairline\")}`,\n background: themeVar(\"panelSurface\"),\n color: themeVar(\"labelPrimary\"),\n cursor: testing ? \"not-allowed\" : \"pointer\",\n opacity: testing ? 0.6 : 1,\n }}\n >\n {testing ? \"Testing...\" : \"Test Connection\"}\n </button>\n\n <button\n type=\"button\"\n disabled={saving || loading}\n onClick={() => void handleSave()}\n style={{\n padding: \"8px 18px\",\n fontSize: 13,\n fontWeight: 600,\n borderRadius: 8,\n border: \"none\",\n background: themeVar(\"buttonPrimaryFill\"),\n color: themeVar(\"buttonPrimaryText\"),\n cursor: saving ? \"not-allowed\" : \"pointer\",\n opacity: saving ? 0.6 : 1,\n }}\n >\n {saving ? \"Saving...\" : \"Save Settings\"}\n </button>\n\n {source === \"settings\" && (\n <button\n type=\"button\"\n disabled={saving || loading}\n onClick={() => void handleReset()}\n style={{\n padding: \"8px 14px\",\n fontSize: 13,\n fontWeight: 500,\n borderRadius: 8,\n border: `1px solid ${themeVar(\"hairline\")}`,\n background: \"transparent\",\n color: themeVar(\"labelSecondary\"),\n cursor: \"pointer\",\n marginLeft: \"auto\",\n }}\n >\n Reset to Auto-detected\n </button>\n )}\n\n {flash && (\n <span\n style={{\n fontSize: 13,\n color:\n flash.kind === \"ok\"\n ? themeVar(\"stateSuccess\")\n : themeVar(\"stateError\"),\n fontWeight: 500,\n }}\n >\n {flash.message}\n </span>\n )}\n </div>\n </div>\n\n {/* Info Notice */}\n <div\n style={{\n border: `1px solid ${themeVar(\"hairline\")}`,\n borderRadius: 10,\n padding: \"14px 18px\",\n background: themeVar(\"panelSurface\"),\n fontSize: 13,\n color: themeVar(\"labelSecondary\"),\n lineHeight: 1.5,\n }}\n >\n <p\n style={{\n margin: \"0 0 6px 0\",\n fontWeight: 600,\n color: themeVar(\"labelPrimary\"),\n }}\n >\n How OpenViking connection works:\n </p>\n <ul style={{ margin: 0, paddingLeft: 18 }}>\n <li style={{ marginBottom: 4 }}>\n All requests to OpenViking proxy through the DSH Desktop host,\n making it work seamlessly even when managing DSH remotely over\n Tailscale, mobile, or LAN.\n </li>\n <li style={{ marginBottom: 4 }}>\n If OpenViking runs locally on the standard port (1933), the plugin\n auto-detects credentials from <code>~/.openviking/ovcli.conf</code>.\n </li>\n <li>\n Custom values saved here are persisted in{\" \"}\n <code>~/.dsh/settings.yaml</code> under the{\" \"}\n <code>openviking-status</code> namespace.\n </li>\n </ul>\n </div>\n </div>\n );\n}\n","import { OpenVikingStatusChip } from \"./OpenVikingStatusChip\";\nimport { OpenVikingSettingsSection } from \"./OpenVikingSettingsSection\";\n\nexport * from \"./api\";\nexport * from \"./theme\";\nexport * from \"./recallParser\";\nexport * from \"./OpenVikingStatusChip\";\nexport * from \"./OpenVikingStatusPopover\";\nexport * from \"./OpenVikingSettingsSection\";\n\nexport type OpenVikingSessionData = import(\"./api\").SessionStatus;\nexport type OpenVikingHealth = import(\"./api\").HealthStatus;\n\n/** Имя пакета, под которым DSH регистрирует клиентскую половину плагина. */\nexport const name = \"@dipertq/dsh-openviking-status\";\n\n/** Сервисы Cordis, которые должны быть готовы до вызова `apply`. */\nexport const inject = [\"slots\"];\n\n/**\n * Точка входа клиентского плагина DSH.\n *\n * 1. Занимает ячейку в `conversation.composer.dock` — чип со статусом OpenViking\n * под композером чата.\n * 2. Регистрирует раздел `settings.section` — страницу настроек OpenViking Status\n * в меню настроек DSH Desktop и Web.\n */\nexport function apply(ctx: any) {\n ctx.effect(\n () =>\n ctx.slots.inject(\"conversation.composer.dock\", () =>\n ctx.slots.register(\n {\n name: \"conversation.composer.dock\",\n id: \"openviking-status\",\n order: 50,\n label: \"OpenViking\",\n },\n OpenVikingStatusChip\n )\n ),\n \"openviking-status: composer stats chip\"\n );\n\n ctx.effect(\n () =>\n ctx.slots.inject(\"settings.section\", () =>\n ctx.slots.register(\n {\n name: \"settings.section\",\n id: \"openviking-status\",\n order: 35,\n label: () => \"OpenViking\",\n },\n OpenVikingSettingsSection\n )\n ),\n \"openviking-status: settings section\"\n );\n}\n"],"mappings":"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","names":["React","useState","useEffect","useCallback","useRef","name","jsx","jsxs","React","useState","useRef","useEffect","useCallback","useState","useEffect","jsx","jsxs","useState","useEffect"]}
|