@dipertq/dsh-openviking-status 0.2.2 → 0.3.1

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/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 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"]}
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 ExtractionBreakdown,\n ExtractionTask,\n TasksReadResult,\n computeBreakdown,\n} from \"./api\";\nimport { themeVar } from \"./theme\";\nimport { RecalledMemoriesResult, parseRecalledMemories } from \"./recallParser\";\nimport { OpenVikingStatusPopover } from \"./OpenVikingStatusPopover\";\n\nexport const COMMIT_THRESHOLD = 20000;\n\n/** Интервалы адаптивного поллинга: покой vs активная фаза извлечения. */\nexport const POLL_INTERVAL_IDLE_MS = 15000;\nexport const POLL_INTERVAL_ACTIVE_MS = 2500;\n\n/**\n * Определяет, находится ли опрос в активной фазе (2.5с вместо 15с).\n *\n * Активная фаза включается как при выполнении (`running >= 1`), так и при\n * наличии задач в очереди (`pending >= 1`), чтобы успеть поймать запуск\n * до завершения быстрой задачи.\n */\nexport function shouldPollActive(\n breakdown?: ExtractionBreakdown | null\n): boolean {\n if (!breakdown) return false;\n return breakdown.running >= 1 || breakdown.pending >= 1;\n}\n\n/**\n * Состояние точки статуса (StateDot).\n *\n * - `offline` — демон недоступен (красный).\n * - `session-unreadable` — сессия за ключом, счётчики недоступны (жёлтый статичный).\n * - `busy` — идёт извлечение памяти (`running >= 1`): акцентный пульс.\n * - `extraction-failed` — последняя задача провалилась: жёлтый + warning-глиф.\n * - `online-idle` — норма (зелёный).\n *\n * Мигание завязано *строго* на `running`: `pending`-only не пульсирует.\n */\nexport type ChipDotState =\n | \"offline\"\n | \"session-unreadable\"\n | \"busy\"\n | \"extraction-failed\"\n | \"online-idle\";\n\n/**\n * Свести состояние демона, сессии и разбивку задач Phase 2 к состоянию точки.\n *\n * Приоритет: недоступность демона → нечитаемая сессия → активное извлечение →\n * провал последней задачи → норма. Провал показываем только когда *хвост*\n * непуст (есть свежий `failed`) и при этом ничего не выполняется.\n */\nexport function getChipDotState({\n isOnline,\n sessionUnreadable,\n breakdown,\n}: {\n isOnline: boolean;\n sessionUnreadable: boolean;\n breakdown?: ExtractionBreakdown | null;\n}): ChipDotState {\n if (!isOnline) return \"offline\";\n if (sessionUnreadable) return \"session-unreadable\";\n if (breakdown && breakdown.running >= 1) return \"busy\";\n if (breakdown && breakdown.failed >= 1) return \"extraction-failed\";\n return \"online-idle\";\n}\n\n/**\n * Warning-глиф (circle-alert) для состояния `extraction-failed`.\n *\n * Инлайновый SVG, а не иконка из примитивов DSH: набор экспортируемых имён у\n * примитивов не гарантирован, а отсутствующий глиф молча стал бы невидимым —\n * ровно тот отказ, который прячется под работающим кодом. `currentColor`\n * наследует цвет предупреждения от родителя.\n */\nexport function WarningGlyph({\n size = 11,\n testId = \"extraction-warning-glyph\",\n}: {\n size?: number;\n testId?: string;\n}) {\n return (\n <svg\n data-testid={testId}\n width={size}\n height={size}\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n aria-hidden=\"true\"\n style={{ flexShrink: 0, display: \"block\" }}\n >\n <circle cx=\"8\" cy=\"8\" r=\"6.5\" stroke=\"currentColor\" strokeWidth=\"1.5\" />\n <path\n d=\"M8 5v3.5\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n strokeLinecap=\"round\"\n />\n <circle cx=\"8\" cy=\"11\" r=\"0.9\" fill=\"currentColor\" />\n </svg>\n );\n}\n\n/**\n * Оптимистично добавить `running`-задачу в разбивку после коммита.\n *\n * Точка пульсирует мгновенно по `task_id` из ответа коммита; следующий опрос\n * списка заменит эту заглушку реальной задачей. Если такой `task_id` уже есть в\n * списке (гонка с опросом) — оставляем как есть.\n */\nexport function seedRunningTask(\n prev: TasksReadResult | null,\n taskId: string,\n resourceId?: string\n): TasksReadResult {\n const existing =\n prev && prev.status === \"ok\" ? prev.tasks : ([] as ExtractionTask[]);\n if (existing.some((t) => t.task_id === taskId)) {\n return prev as TasksReadResult;\n }\n const seeded: ExtractionTask = {\n task_id: taskId,\n status: \"running\",\n resource_id: resourceId,\n updated_at: new Date().toISOString(),\n };\n const tasks = [seeded, ...existing];\n return { status: \"ok\", breakdown: computeBreakdown(tasks), tasks };\n}\n\n/** Цвет точки для состояния StateDot. */\nexport function getDotColorForState(state: ChipDotState): string {\n switch (state) {\n case \"offline\":\n return themeVar(\"stateError\");\n case \"session-unreadable\":\n case \"extraction-failed\":\n return themeVar(\"stateWarning\");\n case \"busy\":\n return themeVar(\"stateSuccess\");\n case \"online-idle\":\n default:\n return themeVar(\"stateSuccess\");\n }\n}\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 /** Стартовая разбивка задач Phase 2 — для рендера вне слота и тестов. */\n initialTasksRead?: TasksReadResult;\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 initialTasksRead,\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 [tasksRead, setTasksRead] = useState<TasksReadResult | null>(\n initialTasksRead ?? 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 const [session, tasks] = await Promise.all([\n apiClient.readSession(sessionId),\n apiClient.listTasks(sessionId),\n ]);\n setSessionRead(session);\n setTasksRead(tasks);\n } catch {\n setHealth({ ok: false });\n }\n }, [sessionId, apiClient]);\n\n const breakdown = tasksRead?.status === \"ok\" ? tasksRead.breakdown : null;\n const hasActivePhase = shouldPollActive(breakdown);\n\n // Адаптивный поллинг: покой 15с, активная фаза (running или pending) ~2.5с.\n // Терминальный статус возвращает опрос к покою автоматически, потому что\n // интервал пересобирается при каждой смене `hasActivePhase`.\n useEffect(() => {\n fetchStatus();\n const interval = hasActivePhase\n ? POLL_INTERVAL_ACTIVE_MS\n : POLL_INTERVAL_IDLE_MS;\n const timer = setInterval(fetchStatus, interval);\n return () => clearInterval(timer);\n }, [fetchStatus, hasActivePhase]);\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 // Мгновенная привязка: `task_id` из ответа коммита позволяет показать\n // «извлекается» сразу, не дожидаясь, пока опрос списка увидит задачу.\n if (res.task_id) {\n setTasksRead((prev) =>\n seedRunningTask(prev, res.task_id!, res.resource_id)\n );\n }\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 rawDotState = getChipDotState({\n isOnline,\n sessionUnreadable,\n breakdown,\n });\n // Коммит в полёте — тоже активная фаза: точка должна пульсировать сразу, не\n // дожидаясь, пока следующий опрос увидит `running`-задачу. Сворачиваем это в\n // само состояние, чтобы цвет считался одной картой (getDotColorForState).\n const dotState: ChipDotState =\n isCommitting && (rawDotState === \"online-idle\" || rawDotState === \"busy\")\n ? \"busy\"\n : rawDotState;\n const dotBusy = dotState === \"busy\";\n const dotFailed = dotState === \"extraction-failed\";\n const statusColor = getDotColorForState(dotState);\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 <style>{`@keyframes ov-pulse { 0%, 100% { opacity: 1; transform: scale(1); } 50% { opacity: 0.35; transform: scale(0.72); } }`}</style>\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 {dotFailed ? (\n <span\n data-testid=\"status-dot\"\n data-dot-state={dotState}\n aria-hidden=\"true\"\n style={{\n display: \"inline-flex\",\n color: statusColor,\n flexShrink: 0,\n }}\n >\n <WarningGlyph size={11} testId=\"chip-warning-glyph\" />\n </span>\n ) : (\n <span\n data-testid=\"status-dot\"\n data-dot-state={dotBusy ? \"busy\" : dotState}\n aria-hidden=\"true\"\n style={{\n width: \"6px\",\n height: \"6px\",\n borderRadius: \"50%\",\n background: statusColor,\n flexShrink: 0,\n ...(dotBusy\n ? { animation: \"ov-pulse 1.2s ease-in-out infinite\" }\n : {}),\n }}\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 breakdown={breakdown}\n client={apiClient}\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 *\n * Коммит двухфазный: `task_id` — идентификатор фоновой задачи Phase 2\n * (Memory Extraction). Пробрасывается из ответа демона как оптимизация —\n * позволяет чипу мгновенно привязаться к задаче, не дожидаясь опроса списка.\n */\nexport interface CommitResult {\n ok: boolean;\n error?: string;\n /** Идентификатор фоновой задачи извлечения (Phase 2), если демон его вернул. */\n task_id?: string;\n /** Разрешённый `resource_id` формы `dsh-session-<uuid>`. */\n resource_id?: string;\n}\n\n/**\n * Статус жизненного цикла фоновой задачи извлечения (Phase 2).\n * Дробного прогресса *внутри* задачи демон не отдаёт — только эти состояния.\n */\nexport type ExtractionTaskStatus =\n \"pending\" | \"running\" | \"completed\" | \"failed\";\n\n/**\n * Одна фоновая задача Phase 2 (`task_type: session_commit`).\n *\n * Промежуточные `stage`/`operation`/`meta` демон держит пустыми (`null`/`{}`);\n * `result`/`token_usage` заполняются только по завершении.\n */\nexport interface ExtractionTask {\n task_id: string;\n status: ExtractionTaskStatus;\n resource_id?: string;\n created_at?: string;\n updated_at?: string;\n /** Итог завершённой задачи: сколько воспоминаний записано/отредактировано. */\n memory_write?: number;\n memory_edit?: number;\n /** Расход токенов завершённой задачи. */\n token_usage?: number;\n /** Текст ошибки для `failed`. */\n error?: string;\n}\n\n/**\n * Разбивка задач сессии по статусам. Считается на клиенте из одного списка —\n * `running` и `pending` учитываются раздельно (демон их не схлопывает).\n */\nexport interface ExtractionBreakdown {\n running: number;\n pending: number;\n completed: number;\n failed: number;\n total: number;\n /** Первая *выполняющаяся* задача (для «Show log» живого извлечения). */\n firstRunning: ExtractionTask | null;\n /** Последняя *завершённая* задача (для строки last extraction). */\n lastCompleted: ExtractionTask | null;\n /** Последняя *провалившаяся* задача (для warning-глифа и текста ошибки). */\n lastFailed: ExtractionTask | null;\n}\n\n/** Одно событие ленты `execution_events` задачи (для «Show log»). */\nexport interface ExecutionEvent {\n seq?: number;\n recorded_at?: string;\n kind?: string;\n status?: string;\n stage?: string | null;\n operation?: string | null;\n error?: string | null;\n}\n\n/** Исход чтения списка задач сессии. */\nexport type TasksReadResult =\n | { status: \"ok\"; breakdown: ExtractionBreakdown; tasks: ExtractionTask[] }\n | { status: \"unauthorized\" }\n | { status: \"missing\" }\n | { status: \"unreachable\"; detail?: string }\n | { status: \"error\"; detail?: string };\n\n/** Исход чтения одной задачи с лентой событий. */\nexport type TaskEventsResult =\n | { status: \"ok\"; task: ExtractionTask; events: ExecutionEvent[] }\n | { status: \"unauthorized\" }\n | { status: \"missing\" }\n | { status: \"unreachable\"; detail?: string }\n | { status: \"error\"; detail?: string };\n\n/** Верхняя граница `limit` списка задач у демона. */\nexport const TASKS_LIMIT_CAP = 200;\n\n/**\n * Нормализовать временную метку в ISO-строку.\n *\n * Демон OpenViking отдаёт `created_at` / `updated_at` как числом секунд\n * (Unix timestamp), так и ISO-строками в `created_at_iso` / `updated_at_iso`.\n */\nexport function normalizeTimestamp(\n ts: unknown,\n isoFallback?: unknown\n): string | undefined {\n if (typeof isoFallback === \"string\" && isoFallback.trim()) {\n return isoFallback.trim();\n }\n if (typeof ts === \"string\" && ts.trim()) {\n return ts.trim();\n }\n if (typeof ts === \"number\" && Number.isFinite(ts) && ts > 0) {\n const ms = ts < 1e11 ? ts * 1000 : ts;\n return new Date(ms).toISOString();\n }\n return undefined;\n}\n\n/**\n * Извлечь массив сырых задач из ответа демона OpenViking.\n *\n * OpenViking GET /api/v1/tasks возвращает `{ status: \"ok\", result: [ ... ] }`,\n * где `result` — сам массив задач. Также поддерживаются варианты с `items`,\n * `tasks`, вложенным `result.items` или плоским массивом в корне.\n */\nexport function extractTaskList(data: unknown): unknown[] {\n if (!data || typeof data !== \"object\") return [];\n if (Array.isArray(data)) return data;\n const obj = data as Record<string, unknown>;\n if (Array.isArray(obj.result)) return obj.result;\n if (Array.isArray(obj.items)) return obj.items;\n if (Array.isArray(obj.tasks)) return obj.tasks;\n if (obj.result && typeof obj.result === \"object\") {\n const res = obj.result as Record<string, unknown>;\n if (Array.isArray(res.items)) return res.items;\n if (Array.isArray(res.tasks)) return res.tasks;\n }\n return [];\n}\n\n/**\n * Привести сырую задачу демона к {@link ExtractionTask}.\n *\n * `result` завершённой задачи несёт `memories_extracted{memory_write,memory_edit}`\n * и `token_usage`; форма может лежать как в корне, так и во вложенном `result`.\n */\nexport function normalizeExtractionTask(\n raw: Record<string, unknown>\n): ExtractionTask | null {\n if (!raw || typeof raw !== \"object\") return null;\n const taskId =\n (typeof raw.task_id === \"string\" && raw.task_id) ||\n (typeof raw.id === \"string\" && raw.id) ||\n \"\";\n if (!taskId) return null;\n\n const statusRaw = typeof raw.status === \"string\" ? raw.status : \"\";\n const status: ExtractionTaskStatus =\n statusRaw === \"running\" ||\n statusRaw === \"pending\" ||\n statusRaw === \"completed\" ||\n statusRaw === \"failed\"\n ? statusRaw\n : \"pending\";\n\n const result = (raw.result ?? {}) as Record<string, unknown>;\n const extracted = (result.memories_extracted ?? {}) as Record<\n string,\n unknown\n >;\n const numberOf = (v: unknown): number | undefined =>\n typeof v === \"number\" && Number.isFinite(v) ? v : undefined;\n\n const tokenUsageRaw = (result.token_usage ?? raw.token_usage) as\n Record<string, unknown> | number | undefined;\n const tokenUsage =\n typeof tokenUsageRaw === \"number\"\n ? tokenUsageRaw\n : numberOf(\n (tokenUsageRaw as Record<string, unknown> | undefined)?.total_tokens\n );\n\n const errorRaw = raw.error;\n const errorMsg =\n typeof errorRaw === \"string\"\n ? errorRaw\n : typeof (errorRaw as Record<string, unknown>)?.message === \"string\"\n ? ((errorRaw as Record<string, unknown>).message as string)\n : undefined;\n\n return {\n task_id: taskId,\n status,\n resource_id:\n typeof raw.resource_id === \"string\" ? raw.resource_id : undefined,\n created_at: normalizeTimestamp(raw.created_at, raw.created_at_iso),\n updated_at: normalizeTimestamp(raw.updated_at, raw.updated_at_iso),\n memory_write: numberOf(extracted.memory_write ?? extracted.written),\n memory_edit: numberOf(extracted.memory_edit ?? extracted.edited),\n token_usage: tokenUsage,\n error: errorMsg,\n };\n}\n\n/**\n * Свести список задач в разбивку по статусам.\n *\n * Список приходит отсортированным по убыванию времени, поэтому первая\n * `completed`/`failed` — самая свежая. `running` и `pending` считаются\n * раздельно: мигание чипа завязано строго на `running`, backlog — на\n * `pending`/`failed`.\n */\nexport function computeBreakdown(tasks: ExtractionTask[]): ExtractionBreakdown {\n const b: ExtractionBreakdown = {\n running: 0,\n pending: 0,\n completed: 0,\n failed: 0,\n total: tasks.length,\n firstRunning: null,\n lastCompleted: null,\n lastFailed: null,\n };\n for (const t of tasks) {\n if (t.status === \"running\") {\n b.running += 1;\n if (!b.firstRunning) b.firstRunning = t;\n } else if (t.status === \"pending\") b.pending += 1;\n else if (t.status === \"completed\") {\n b.completed += 1;\n if (!b.lastCompleted) b.lastCompleted = t;\n } else if (t.status === \"failed\") {\n b.failed += 1;\n if (!b.lastFailed) b.lastFailed = t;\n }\n }\n return b;\n}\n\n/** Нормализовать одно сырое событие ленты `execution_events`. */\nexport function normalizeExecutionEvent(\n raw: Record<string, unknown>\n): ExecutionEvent {\n return {\n seq: typeof raw.seq === \"number\" ? raw.seq : undefined,\n recorded_at: normalizeTimestamp(raw.recorded_at, raw.recorded_at_iso),\n kind: typeof raw.kind === \"string\" ? raw.kind : undefined,\n status: typeof raw.status === \"string\" ? raw.status : undefined,\n stage: typeof raw.stage === \"string\" ? raw.stage : null,\n operation: typeof raw.operation === \"string\" ? raw.operation : null,\n error: typeof raw.error === \"string\" ? raw.error : null,\n };\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 task_id: typeof data.task_id === \"string\" ? data.task_id : undefined,\n resource_id:\n typeof data.resource_id === \"string\" ? data.resource_id : 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 const okBody = (await res.json().catch(() => ({}))) as Record<\n string,\n unknown\n >;\n const container = (okBody.result ?? okBody.data ?? okBody) as Record<\n string,\n unknown\n >;\n const taskId = container.task_id ?? container.id;\n return {\n ok: true,\n task_id:\n typeof taskId === \"string\" && taskId.trim()\n ? taskId.trim()\n : undefined,\n resource_id: candidateId,\n };\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 * Список задач Phase 2 (Memory Extraction) текущей сессии со сводной\n * разбивкой по статусам.\n *\n * Через прокси: один запрос `GET /tasks?session=<id>`, разбивка считается\n * здесь. Напрямую: разрешаем `resource_id` через кандидатов и запрашиваем\n * `GET /api/v1/tasks?resource_id=<id>&task_type=session_commit&limit=200`.\n */\n async listTasks(sessionId: string): Promise<TasksReadResult> {\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}/tasks?session=${encodeURIComponent(\n sessionId.trim()\n )}&limit=${TASKS_LIMIT_CAP}`,\n { method: \"GET\", headers: this.getHeaders() }\n );\n if (res.status === 401 || res.status === 403) {\n return { status: \"unauthorized\" };\n }\n if (!res.ok) {\n return { status: \"error\", detail: `HTTP ${res.status}` };\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 const tasks = normalizeTaskList(extractTaskList(data.tasks ?? data));\n return { status: \"ok\", breakdown: computeBreakdown(tasks), tasks };\n } catch (err) {\n return {\n status: \"unreachable\",\n detail: err instanceof Error ? err.message : String(err),\n };\n }\n }\n\n // Прямой доступ: сперва разрешаем resource_id через кандидатов.\n // getCandidateSessionIds уже ставит ранее разрешённый id первым, поэтому\n // повторный опрос обычно попадает с первой попытки.\n const candidates = this.getCandidateSessionIds(sessionId);\n let resourceId: string | null = null;\n for (const candidateId of candidates) {\n try {\n const probe = await fetch(\n `${this.endpoint}/api/v1/sessions/${encodeURIComponent(candidateId)}`,\n { method: \"GET\", headers: this.getHeaders() }\n );\n if (probe.status === 404) continue;\n if (probe.status === 401 || probe.status === 403) {\n return { status: \"unauthorized\" };\n }\n if (probe.ok) {\n resourceId = candidateId;\n this.resolvedSessionIds.set(sessionId.trim(), candidateId);\n break;\n }\n } catch (err) {\n return {\n status: \"unreachable\",\n detail: err instanceof Error ? err.message : String(err),\n };\n }\n }\n\n if (!resourceId) return { status: \"missing\" };\n\n try {\n const query = new URLSearchParams({\n resource_id: resourceId,\n task_type: \"session_commit\",\n limit: String(TASKS_LIMIT_CAP),\n });\n const res = await fetch(\n `${this.endpoint}/api/v1/tasks?${query.toString()}`,\n { method: \"GET\", headers: this.getHeaders() }\n );\n if (res.status === 401 || res.status === 403) {\n return { status: \"unauthorized\" };\n }\n if (!res.ok) {\n return { status: \"error\", detail: `HTTP ${res.status}` };\n }\n const data = (await res.json()) as Record<string, unknown>;\n const tasks = normalizeTaskList(extractTaskList(data));\n return { status: \"ok\", breakdown: computeBreakdown(tasks), tasks };\n } catch (err) {\n return {\n status: \"unreachable\",\n detail: err instanceof Error ? err.message : String(err),\n };\n }\n }\n\n /**\n * Лениво загрузить одну задачу с лентой `execution_events` для «Show log».\n */\n async fetchTaskEvents(taskId: string): Promise<TaskEventsResult> {\n if (!taskId || !taskId.trim()) {\n return { status: \"missing\" };\n }\n\n const buildOk = (taskRaw: Record<string, unknown>): TaskEventsResult => {\n const task = normalizeExtractionTask(taskRaw);\n const eventsContainer = (taskRaw.execution_events ?? {}) as Record<\n string,\n unknown\n >;\n const rawEvents =\n (eventsContainer.items as unknown[]) ??\n (Array.isArray(taskRaw.execution_events)\n ? (taskRaw.execution_events as unknown[])\n : []);\n const events = (Array.isArray(rawEvents) ? rawEvents : [])\n .filter(\n (e): e is Record<string, unknown> => !!e && typeof e === \"object\"\n )\n .map(normalizeExecutionEvent);\n if (!task) return { status: \"error\", detail: \"malformed task\" };\n return { status: \"ok\", task, events };\n };\n\n if (this.isProxy()) {\n try {\n const res = await fetch(\n `${this.endpoint}/task?id=${encodeURIComponent(\n taskId.trim()\n )}&events=1`,\n { method: \"GET\", headers: this.getHeaders() }\n );\n if (res.status === 401 || res.status === 403) {\n return { status: \"unauthorized\" };\n }\n if (!res.ok) {\n return { status: \"error\", detail: `HTTP ${res.status}` };\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 return buildOk((data.task ?? {}) as Record<string, unknown>);\n } catch (err) {\n return {\n status: \"unreachable\",\n detail: err instanceof Error ? err.message : String(err),\n };\n }\n }\n\n try {\n const res = await fetch(\n `${this.endpoint}/api/v1/tasks/${encodeURIComponent(\n taskId.trim()\n )}?include_events=true`,\n { method: \"GET\", headers: this.getHeaders() }\n );\n if (res.status === 404) return { status: \"missing\" };\n if (res.status === 401 || res.status === 403) {\n return { status: \"unauthorized\" };\n }\n if (!res.ok) {\n return { status: \"error\", detail: `HTTP ${res.status}` };\n }\n const data = (await res.json()) as Record<string, unknown>;\n const taskRaw = (data?.result ?? data?.data ?? data) as Record<\n string,\n unknown\n >;\n return buildOk(taskRaw);\n } catch (err) {\n return {\n status: \"unreachable\",\n detail: err instanceof Error ? err.message : String(err),\n };\n }\n }\n}\n\n/**\n * Нормализовать массив сырых задач, отбросив нераспознанные записи.\n */\nexport function normalizeTaskList(raw: unknown): ExtractionTask[] {\n if (!Array.isArray(raw)) return [];\n const tasks: ExtractionTask[] = [];\n for (const entry of raw) {\n if (!entry || typeof entry !== \"object\") continue;\n const task = normalizeExtractionTask(entry as Record<string, unknown>);\n if (task) tasks.push(task);\n }\n return tasks;\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 {\n HealthStatus,\n SessionStatus,\n SessionReadResult,\n ExtractionBreakdown,\n ExtractionTask,\n ExecutionEvent,\n OpenVikingClient,\n} from \"./api\";\nimport { themeVar } from \"./theme\";\nimport { RecalledMemoriesResult, RecalledMemoryItem } from \"./recallParser\";\nimport { COMMIT_THRESHOLD, WarningGlyph } 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 /** Разбивка задач Phase 2 (Memory Extraction) текущей сессии. */\n breakdown?: ExtractionBreakdown | null;\n /** Клиент для ленивой загрузки `execution_events` в «Show log». */\n client?: OpenVikingClient;\n onCommitNow?: () => Promise<void> | void;\n onClose?: () => void;\n className?: string;\n style?: React.CSSProperties;\n}\n\n/**\n * Длительность задачи между двумя таймстампами, человекочитаемо (`4.2s`, `1m 12s`).\n */\nexport function formatDuration(\n startIso?: string,\n endIso?: string\n): string | undefined {\n if (!startIso || !endIso) return undefined;\n const start = new Date(startIso).getTime();\n const end = new Date(endIso).getTime();\n if (isNaN(start) || isNaN(end) || end < start) return undefined;\n const ms = end - start;\n const sec = ms / 1000;\n if (sec < 60) {\n return `${sec < 10 ? sec.toFixed(1) : Math.round(sec)}s`;\n }\n const min = Math.floor(sec / 60);\n const rem = Math.round(sec % 60);\n return `${min}m ${rem}s`;\n}\n\n/**\n * Строка last extraction для завершённой задачи:\n * `<write> written, <edit> edited · <duration> · <relative-time>`.\n *\n * Части опускаются, если данных нет: длительность требует обоих таймстампов,\n * относительное время — `updated_at`.\n */\nexport function formatExtractionSummary(\n task: ExtractionTask,\n now: number = Date.now()\n): string {\n const write = task.memory_write ?? 0;\n const edit = task.memory_edit ?? 0;\n const parts: string[] = [`${write} written, ${edit} edited`];\n const duration = formatDuration(task.created_at, task.updated_at);\n if (duration) parts.push(duration);\n const rel = formatRelativeTime(task.updated_at, now);\n if (rel) parts.push(rel);\n return parts.join(\" · \");\n}\n\n/**\n * Строка backlog `N pending / M failed`, только когда хвост непуст.\n * Возвращает `null`, когда всё завершено (строку рисовать не нужно).\n */\nexport function formatBacklog(\n breakdown?: ExtractionBreakdown | null\n): string | null {\n if (!breakdown) return null;\n const { pending, failed } = breakdown;\n if (pending <= 0 && failed <= 0) return null;\n const parts: string[] = [];\n if (pending > 0) parts.push(`${pending} pending`);\n if (failed > 0) parts.push(`${failed} failed`);\n return parts.join(\" / \");\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 * Блок Phase 2 (Memory Extraction) рядом с `Commit Now`.\n *\n * - `running` → indeterminate-бар + `Extracting…` (без фейкового процента).\n * - `completed` → строка last extraction + ровная зелёная точка.\n * - backlog `N pending / M failed` — только когда хвост непуст.\n * - `failed` → warning-глиф + текст ошибки.\n * - «Show log» лениво тянет `execution_events` и рендерит ленту переходов.\n *\n * Глобальную очередь демона (Requeued и т.п.) блок не показывает намеренно.\n */\nexport function ExtractionSection({\n breakdown,\n client,\n}: {\n breakdown?: ExtractionBreakdown | null;\n client?: OpenVikingClient;\n}) {\n const [showLog, setShowLog] = useState(false);\n const [events, setEvents] = useState<ExecutionEvent[] | null>(null);\n const [logError, setLogError] = useState<string | null>(null);\n const [loadingLog, setLoadingLog] = useState(false);\n\n if (!breakdown) return null;\n\n const isRunning = breakdown.running >= 1;\n const lastCompleted = breakdown.lastCompleted;\n const lastFailed = breakdown.lastFailed;\n const backlog = formatBacklog(breakdown);\n const failedActive = !isRunning && breakdown.failed >= 1;\n\n // Задача для «Show log»: то, что показано в блоке — живое извлечение важнее\n // прошлых итогов, поэтому running-задача имеет приоритет. Так лента\n // `created → running → …` доступна прямо во время извлечения.\n const logTaskId =\n (isRunning ? breakdown.firstRunning?.task_id : null) ??\n (failedActive ? lastFailed?.task_id : null) ??\n lastCompleted?.task_id ??\n lastFailed?.task_id ??\n null;\n\n const mutedStyle: React.CSSProperties = { color: themeVar(\"labelTertiary\") };\n\n const toggleLog = useCallback(async () => {\n const next = !showLog;\n setShowLog(next);\n if (next && events === null && logTaskId && client) {\n setLoadingLog(true);\n setLogError(null);\n const res = await client.fetchTaskEvents(logTaskId);\n setLoadingLog(false);\n if (res.status === \"ok\") {\n setEvents(res.events);\n } else {\n setLogError(\n res.status === \"unauthorized\"\n ? \"No access to task log\"\n : \"Could not load log\"\n );\n }\n }\n }, [showLog, events, logTaskId, client]);\n\n // Ничего показывать не нужно: нет активной задачи, хвоста и завершённых.\n if (!isRunning && !failedActive && !lastCompleted && !backlog) {\n return null;\n }\n\n return (\n <div data-testid=\"extraction-section\" style={{ marginBottom: \"12px\" }}>\n <div\n style={{\n marginBottom: \"4px\",\n color: themeVar(\"labelPrimary\"),\n fontWeight: 500,\n }}\n >\n Memory Extraction\n </div>\n\n {isRunning ? (\n <div>\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: \"6px\",\n marginBottom: \"4px\",\n }}\n >\n <span\n data-testid=\"extraction-status-dot\"\n aria-hidden=\"true\"\n style={{\n width: \"6px\",\n height: \"6px\",\n borderRadius: \"50%\",\n background: themeVar(\"stateSuccess\"),\n animation: \"ov-pulse 1.2s ease-in-out infinite\",\n flexShrink: 0,\n }}\n />\n <span data-testid=\"extraction-running-label\">Extracting…</span>\n </div>\n <div\n data-testid=\"extraction-indeterminate-track\"\n style={{\n width: \"100%\",\n height: \"6px\",\n borderRadius: \"3px\",\n backgroundColor: themeVar(\"insetSurface\"),\n overflow: \"hidden\",\n position: \"relative\",\n }}\n >\n <div\n data-testid=\"extraction-indeterminate-fill\"\n style={{\n position: \"absolute\",\n left: 0,\n top: 0,\n height: \"100%\",\n width: \"40%\",\n borderRadius: \"3px\",\n backgroundColor: themeVar(\"stateSuccess\"),\n animation: \"ov-indeterminate 1.2s ease-in-out infinite\",\n }}\n />\n </div>\n </div>\n ) : failedActive && lastFailed ? (\n <div\n data-testid=\"extraction-failed-line\"\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: \"6px\",\n color: themeVar(\"stateWarning\"),\n }}\n >\n <span\n aria-hidden=\"true\"\n style={{ display: \"inline-flex\", flexShrink: 0 }}\n >\n <WarningGlyph size={12} testId=\"extraction-warning-glyph\" />\n </span>\n <span data-testid=\"extraction-failed-text\">\n {lastFailed.error || \"extraction failed\"}\n </span>\n </div>\n ) : lastCompleted ? (\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: \"6px\",\n }}\n >\n <span\n data-testid=\"extraction-status-dot\"\n aria-hidden=\"true\"\n style={{\n width: \"6px\",\n height: \"6px\",\n borderRadius: \"50%\",\n background: themeVar(\"stateSuccess\"),\n flexShrink: 0,\n }}\n />\n <span data-testid=\"extraction-last-line\">\n {formatExtractionSummary(lastCompleted)}\n </span>\n </div>\n ) : null}\n\n {backlog && (\n <div\n data-testid=\"extraction-backlog-line\"\n style={{ ...mutedStyle, marginTop: \"4px\" }}\n >\n {backlog}\n </div>\n )}\n\n {logTaskId && client && (\n <div style={{ marginTop: \"6px\" }}>\n <button\n type=\"button\"\n data-testid=\"extraction-show-log-btn\"\n onClick={() => void toggleLog()}\n style={{\n background: \"none\",\n border: \"none\",\n padding: 0,\n cursor: \"pointer\",\n font: \"inherit\",\n color: themeVar(\"labelTertiary\"),\n textDecoration: \"underline\",\n }}\n aria-expanded={showLog}\n >\n {showLog ? \"Hide log\" : \"Show log\"}\n </button>\n\n {showLog && (\n <div\n data-testid=\"extraction-log\"\n style={{\n marginTop: \"6px\",\n display: \"flex\",\n flexDirection: \"column\",\n gap: \"2px\",\n maxHeight: \"120px\",\n overflowY: \"auto\",\n }}\n >\n {loadingLog && (\n <div data-testid=\"extraction-log-loading\" style={mutedStyle}>\n Loading…\n </div>\n )}\n {logError && (\n <div data-testid=\"extraction-log-error\" style={mutedStyle}>\n {logError}\n </div>\n )}\n {events && events.length === 0 && !loadingLog && !logError && (\n <div data-testid=\"extraction-log-empty\" style={mutedStyle}>\n No events\n </div>\n )}\n {events?.map((ev, idx) => (\n <div\n key={`${ev.seq ?? idx}-${ev.recorded_at ?? idx}`}\n data-testid=\"extraction-log-event\"\n style={{\n display: \"flex\",\n justifyContent: \"space-between\",\n gap: \"8px\",\n }}\n >\n <span>{ev.status || ev.kind || \"event\"}</span>\n <span style={mutedStyle}>\n {formatRelativeTime(ev.recorded_at) || \"\"}\n </span>\n </div>\n ))}\n </div>\n )}\n </div>\n )}\n </div>\n );\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 breakdown = null,\n client,\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); } } @keyframes ov-pulse { 0%, 100% { opacity: 1; transform: scale(1); } 50% { opacity: 0.35; transform: scale(0.72); } } @keyframes ov-indeterminate { 0% { left: -40%; } 100% { left: 100%; } }`}</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 {/* Phase 2: Memory Extraction */}\n <ExtractionSection breakdown={breakdown} client={client} />\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"]}