@dipertq/dsh-openviking-status 0.2.1 → 0.3.0

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.d.cts CHANGED
@@ -12,6 +12,7 @@ interface HealthStatus {
12
12
  ok: boolean;
13
13
  version?: string;
14
14
  storage?: string;
15
+ endpoint?: string;
15
16
  error?: string;
16
17
  }
17
18
  /**
@@ -34,12 +35,124 @@ interface CommitOptions {
34
35
  keep_recent_count?: number;
35
36
  }
36
37
  /**
37
- * Результат операции коммита сессии
38
+ * Результат операции коммита сессии.
39
+ *
40
+ * Коммит двухфазный: `task_id` — идентификатор фоновой задачи Phase 2
41
+ * (Memory Extraction). Пробрасывается из ответа демона как оптимизация —
42
+ * позволяет чипу мгновенно привязаться к задаче, не дожидаясь опроса списка.
38
43
  */
39
44
  interface CommitResult {
40
45
  ok: boolean;
41
46
  error?: string;
47
+ /** Идентификатор фоновой задачи извлечения (Phase 2), если демон его вернул. */
48
+ task_id?: string;
49
+ /** Разрешённый `resource_id` формы `dsh-session-<uuid>`. */
50
+ resource_id?: string;
51
+ }
52
+ /**
53
+ * Статус жизненного цикла фоновой задачи извлечения (Phase 2).
54
+ * Дробного прогресса *внутри* задачи демон не отдаёт — только эти состояния.
55
+ */
56
+ type ExtractionTaskStatus = "pending" | "running" | "completed" | "failed";
57
+ /**
58
+ * Одна фоновая задача Phase 2 (`task_type: session_commit`).
59
+ *
60
+ * Промежуточные `stage`/`operation`/`meta` демон держит пустыми (`null`/`{}`);
61
+ * `result`/`token_usage` заполняются только по завершении.
62
+ */
63
+ interface ExtractionTask {
64
+ task_id: string;
65
+ status: ExtractionTaskStatus;
66
+ resource_id?: string;
67
+ created_at?: string;
68
+ updated_at?: string;
69
+ /** Итог завершённой задачи: сколько воспоминаний записано/отредактировано. */
70
+ memory_write?: number;
71
+ memory_edit?: number;
72
+ /** Расход токенов завершённой задачи. */
73
+ token_usage?: number;
74
+ /** Текст ошибки для `failed`. */
75
+ error?: string;
76
+ }
77
+ /**
78
+ * Разбивка задач сессии по статусам. Считается на клиенте из одного списка —
79
+ * `running` и `pending` учитываются раздельно (демон их не схлопывает).
80
+ */
81
+ interface ExtractionBreakdown {
82
+ running: number;
83
+ pending: number;
84
+ completed: number;
85
+ failed: number;
86
+ total: number;
87
+ /** Первая *выполняющаяся* задача (для «Show log» живого извлечения). */
88
+ firstRunning: ExtractionTask | null;
89
+ /** Последняя *завершённая* задача (для строки last extraction). */
90
+ lastCompleted: ExtractionTask | null;
91
+ /** Последняя *провалившаяся* задача (для warning-глифа и текста ошибки). */
92
+ lastFailed: ExtractionTask | null;
93
+ }
94
+ /** Одно событие ленты `execution_events` задачи (для «Show log»). */
95
+ interface ExecutionEvent {
96
+ seq?: number;
97
+ recorded_at?: string;
98
+ kind?: string;
99
+ status?: string;
100
+ stage?: string | null;
101
+ operation?: string | null;
102
+ error?: string | null;
42
103
  }
104
+ /** Исход чтения списка задач сессии. */
105
+ type TasksReadResult = {
106
+ status: "ok";
107
+ breakdown: ExtractionBreakdown;
108
+ tasks: ExtractionTask[];
109
+ } | {
110
+ status: "unauthorized";
111
+ } | {
112
+ status: "missing";
113
+ } | {
114
+ status: "unreachable";
115
+ detail?: string;
116
+ } | {
117
+ status: "error";
118
+ detail?: string;
119
+ };
120
+ /** Исход чтения одной задачи с лентой событий. */
121
+ type TaskEventsResult = {
122
+ status: "ok";
123
+ task: ExtractionTask;
124
+ events: ExecutionEvent[];
125
+ } | {
126
+ status: "unauthorized";
127
+ } | {
128
+ status: "missing";
129
+ } | {
130
+ status: "unreachable";
131
+ detail?: string;
132
+ } | {
133
+ status: "error";
134
+ detail?: string;
135
+ };
136
+ /** Верхняя граница `limit` списка задач у демона. */
137
+ declare const TASKS_LIMIT_CAP = 200;
138
+ /**
139
+ * Привести сырую задачу демона к {@link ExtractionTask}.
140
+ *
141
+ * `result` завершённой задачи несёт `memories_extracted{memory_write,memory_edit}`
142
+ * и `token_usage`; форма может лежать как в корне, так и во вложенном `result`.
143
+ */
144
+ declare function normalizeExtractionTask(raw: Record<string, unknown>): ExtractionTask | null;
145
+ /**
146
+ * Свести список задач в разбивку по статусам.
147
+ *
148
+ * Список приходит отсортированным по убыванию времени, поэтому первая
149
+ * `completed`/`failed` — самая свежая. `running` и `pending` считаются
150
+ * раздельно: мигание чипа завязано строго на `running`, backlog — на
151
+ * `pending`/`failed`.
152
+ */
153
+ declare function computeBreakdown(tasks: ExtractionTask[]): ExtractionBreakdown;
154
+ /** Нормализовать одно сырое событие ленты `execution_events`. */
155
+ declare function normalizeExecutionEvent(raw: Record<string, unknown>): ExecutionEvent;
43
156
  /**
44
157
  * Исход попытки прочитать сессию.
45
158
  *
@@ -79,6 +192,10 @@ type PeerId = string;
79
192
  * Базовый URL по умолчанию для локального демона OpenViking
80
193
  */
81
194
  declare const DEFAULT_OPENVIKING_ENDPOINT = "http://127.0.0.1:1933";
195
+ /**
196
+ * Относительный маршрут хостового прокси на DSH Web Server
197
+ */
198
+ declare const PROXY_OPENVIKING_ENDPOINT = "/openviking-status/api";
82
199
  /**
83
200
  * Определение эндпоинта OpenViking из параметров, глобального контекста или localStorage
84
201
  */
@@ -146,7 +263,24 @@ declare class OpenVikingClient {
146
263
  * Инициация фиксации (коммита) накопленных токенов сессии в долговременную память
147
264
  */
148
265
  commitSession(sessionId: string, options?: CommitOptions): Promise<CommitResult>;
266
+ /**
267
+ * Список задач Phase 2 (Memory Extraction) текущей сессии со сводной
268
+ * разбивкой по статусам.
269
+ *
270
+ * Через прокси: один запрос `GET /tasks?session=<id>`, разбивка считается
271
+ * здесь. Напрямую: разрешаем `resource_id` через кандидатов и запрашиваем
272
+ * `GET /api/v1/tasks?resource_id=<id>&task_type=session_commit&limit=200`.
273
+ */
274
+ listTasks(sessionId: string): Promise<TasksReadResult>;
275
+ /**
276
+ * Лениво загрузить одну задачу с лентой `execution_events` для «Show log».
277
+ */
278
+ fetchTaskEvents(taskId: string): Promise<TaskEventsResult>;
149
279
  }
280
+ /**
281
+ * Нормализовать массив сырых задач, отбросив нераспознанные записи.
282
+ */
283
+ declare function normalizeTaskList(raw: unknown): ExtractionTask[];
150
284
  /**
151
285
  * Экземпляр клиента по умолчанию с автоматическим определением конфигурации
152
286
  */
@@ -264,6 +398,55 @@ declare function inferCategory(uri: string): string | undefined;
264
398
  declare function parseRecalledMemories(input: string | any[] | null | undefined): RecalledMemoriesResult;
265
399
 
266
400
  declare const COMMIT_THRESHOLD = 20000;
401
+ /** Интервалы адаптивного поллинга: покой vs активная фаза извлечения. */
402
+ declare const POLL_INTERVAL_IDLE_MS = 15000;
403
+ declare const POLL_INTERVAL_ACTIVE_MS = 2500;
404
+ /**
405
+ * Состояние точки статуса (StateDot).
406
+ *
407
+ * - `offline` — демон недоступен (красный).
408
+ * - `session-unreadable` — сессия за ключом, счётчики недоступны (жёлтый статичный).
409
+ * - `busy` — идёт извлечение памяти (`running >= 1`): акцентный пульс.
410
+ * - `extraction-failed` — последняя задача провалилась: жёлтый + warning-глиф.
411
+ * - `online-idle` — норма (зелёный).
412
+ *
413
+ * Мигание завязано *строго* на `running`: `pending`-only не пульсирует.
414
+ */
415
+ type ChipDotState = "offline" | "session-unreadable" | "busy" | "extraction-failed" | "online-idle";
416
+ /**
417
+ * Свести состояние демона, сессии и разбивку задач Phase 2 к состоянию точки.
418
+ *
419
+ * Приоритет: недоступность демона → нечитаемая сессия → активное извлечение →
420
+ * провал последней задачи → норма. Провал показываем только когда *хвост*
421
+ * непуст (есть свежий `failed`) и при этом ничего не выполняется.
422
+ */
423
+ declare function getChipDotState({ isOnline, sessionUnreadable, breakdown, }: {
424
+ isOnline: boolean;
425
+ sessionUnreadable: boolean;
426
+ breakdown?: ExtractionBreakdown | null;
427
+ }): ChipDotState;
428
+ /**
429
+ * Warning-глиф (circle-alert) для состояния `extraction-failed`.
430
+ *
431
+ * Инлайновый SVG, а не иконка из примитивов DSH: набор экспортируемых имён у
432
+ * примитивов не гарантирован, а отсутствующий глиф молча стал бы невидимым —
433
+ * ровно тот отказ, который прячется под работающим кодом. `currentColor`
434
+ * наследует цвет предупреждения от родителя.
435
+ */
436
+ declare function WarningGlyph({ size, testId, }: {
437
+ size?: number;
438
+ testId?: string;
439
+ }): React.JSX.Element;
440
+ /**
441
+ * Оптимистично добавить `running`-задачу в разбивку после коммита.
442
+ *
443
+ * Точка пульсирует мгновенно по `task_id` из ответа коммита; следующий опрос
444
+ * списка заменит эту заглушку реальной задачей. Если такой `task_id` уже есть в
445
+ * списке (гонка с опросом) — оставляем как есть.
446
+ */
447
+ declare function seedRunningTask(prev: TasksReadResult | null, taskId: string, resourceId?: string): TasksReadResult;
448
+ /** Цвет точки для состояния StateDot. */
449
+ declare function getDotColorForState(state: ChipDotState): string;
267
450
  /**
268
451
  * Селектор поверх снимка диалога — стандартный проп слотов со скоупом сессии.
269
452
  * Штатные чипы статистики DSH читают узлы ровно так же.
@@ -283,6 +466,8 @@ interface OpenVikingStatusChipProps {
283
466
  initialHealth?: HealthStatus;
284
467
  initialSessionData?: SessionStatus;
285
468
  initialSessionRead?: SessionReadResult;
469
+ /** Стартовая разбивка задач Phase 2 — для рендера вне слота и тестов. */
470
+ initialTasksRead?: TasksReadResult;
286
471
  initialOpen?: boolean;
287
472
  }
288
473
  /**
@@ -337,11 +522,32 @@ interface OpenVikingStatusPopoverProps {
337
522
  endpoint?: string;
338
523
  isCommitting?: boolean;
339
524
  commitError?: string | null;
525
+ /** Разбивка задач Phase 2 (Memory Extraction) текущей сессии. */
526
+ breakdown?: ExtractionBreakdown | null;
527
+ /** Клиент для ленивой загрузки `execution_events` в «Show log». */
528
+ client?: OpenVikingClient;
340
529
  onCommitNow?: () => Promise<void> | void;
341
530
  onClose?: () => void;
342
531
  className?: string;
343
532
  style?: React.CSSProperties;
344
533
  }
534
+ /**
535
+ * Длительность задачи между двумя таймстампами, человекочитаемо (`4.2s`, `1m 12s`).
536
+ */
537
+ declare function formatDuration(startIso?: string, endIso?: string): string | undefined;
538
+ /**
539
+ * Строка last extraction для завершённой задачи:
540
+ * `<write> written, <edit> edited · <duration> · <relative-time>`.
541
+ *
542
+ * Части опускаются, если данных нет: длительность требует обоих таймстампов,
543
+ * относительное время — `updated_at`.
544
+ */
545
+ declare function formatExtractionSummary(task: ExtractionTask, now?: number): string;
546
+ /**
547
+ * Строка backlog `N pending / M failed`, только когда хвост непуст.
548
+ * Возвращает `null`, когда всё завершено (строку рисовать не нужно).
549
+ */
550
+ declare function formatBacklog(breakdown?: ExtractionBreakdown | null): string | null;
345
551
  /**
346
552
  * Расчет процента заполнения пула накопленных токенов (0% - 100%).
347
553
  */
@@ -387,13 +593,28 @@ declare function getCategoryBadgeStyle(_category?: string): React.CSSProperties;
387
593
  declare function handleEscapeKey(event: {
388
594
  key: string;
389
595
  }, onClose?: () => void): boolean;
596
+ /**
597
+ * Блок Phase 2 (Memory Extraction) рядом с `Commit Now`.
598
+ *
599
+ * - `running` → indeterminate-бар + `Extracting…` (без фейкового процента).
600
+ * - `completed` → строка last extraction + ровная зелёная точка.
601
+ * - backlog `N pending / M failed` — только когда хвост непуст.
602
+ * - `failed` → warning-глиф + текст ошибки.
603
+ * - «Show log» лениво тянет `execution_events` и рендерит ленту переходов.
604
+ *
605
+ * Глобальную очередь демона (Requeued и т.п.) блок не показывает намеренно.
606
+ */
607
+ declare function ExtractionSection({ breakdown, client, }: {
608
+ breakdown?: ExtractionBreakdown | null;
609
+ client?: OpenVikingClient;
610
+ }): React.JSX.Element | null;
390
611
  /**
391
612
  * Панель детального состояния контекстной памяти OpenViking (Status Popover).
392
613
  *
393
614
  * Оформление повторяет диалог статистики сессии DSH: та же поверхность, тень,
394
615
  * радиус, отступы и кегль.
395
616
  */
396
- declare function OpenVikingStatusPopover({ sessionId, health, sessionData, sessionRead, recalledResult, endpoint, isCommitting, commitError, onCommitNow, onClose, className, style, }: OpenVikingStatusPopoverProps): React.JSX.Element;
617
+ declare function OpenVikingStatusPopover({ sessionId, health, sessionData, sessionRead, recalledResult, endpoint, isCommitting, commitError, breakdown, client, onCommitNow, onClose, className, style, }: OpenVikingStatusPopoverProps): React.JSX.Element;
397
618
 
398
619
  interface OpenVikingConfigData {
399
620
  endpoint: string;
@@ -424,4 +645,4 @@ declare const inject: string[];
424
645
  */
425
646
  declare function apply(ctx: any): void;
426
647
 
427
- export { COMMIT_THRESHOLD, type CommitOptions, type CommitResult, DEFAULT_OPENVIKING_ENDPOINT, type HealthStatus, OpenVikingClient, type OpenVikingConfigData, type OpenVikingHealth, type OpenVikingSessionData, OpenVikingSettingsSection, type OpenVikingSettingsSectionProps, OpenVikingStatusChip, type OpenVikingStatusChipProps, OpenVikingStatusPopover, type OpenVikingStatusPopoverProps, type PeerId, type PendingTokens, type RecalledMemoriesResult, type RecalledMemoryItem, type SessionReadResult, type SessionStatus, THEME, type ThemeRole, type UseChat, apply, chatNodesToText, checkHealth, commitSession, defaultOpenVikingClient, fetchSession, formatDaemonVersion, formatEndpoint, formatMemoryLeafName, formatPendingTokens, formatRelativeTime, formatStatusLabel, formatTooltipTitle, getCategoryBadgeStyle, getProgressBarColor, getProgressBarPercent, getSession, getStatusIndicatorColor, handleEscapeKey, inferCategory, inject, name, parseRecalledMemories, resolveApiKey, resolveEndpoint, themeVar, truncateSessionId };
648
+ export { COMMIT_THRESHOLD, type ChipDotState, type CommitOptions, type CommitResult, DEFAULT_OPENVIKING_ENDPOINT, type ExecutionEvent, type ExtractionBreakdown, ExtractionSection, type ExtractionTask, type ExtractionTaskStatus, type HealthStatus, OpenVikingClient, type OpenVikingConfigData, type OpenVikingHealth, type OpenVikingSessionData, OpenVikingSettingsSection, type OpenVikingSettingsSectionProps, OpenVikingStatusChip, type OpenVikingStatusChipProps, OpenVikingStatusPopover, type OpenVikingStatusPopoverProps, POLL_INTERVAL_ACTIVE_MS, POLL_INTERVAL_IDLE_MS, PROXY_OPENVIKING_ENDPOINT, type PeerId, type PendingTokens, type RecalledMemoriesResult, type RecalledMemoryItem, type SessionReadResult, type SessionStatus, TASKS_LIMIT_CAP, THEME, type TaskEventsResult, type TasksReadResult, type ThemeRole, type UseChat, WarningGlyph, apply, chatNodesToText, checkHealth, commitSession, computeBreakdown, defaultOpenVikingClient, fetchSession, formatBacklog, formatDaemonVersion, formatDuration, formatEndpoint, formatExtractionSummary, formatMemoryLeafName, formatPendingTokens, formatRelativeTime, formatStatusLabel, formatTooltipTitle, getCategoryBadgeStyle, getChipDotState, getDotColorForState, getProgressBarColor, getProgressBarPercent, getSession, getStatusIndicatorColor, handleEscapeKey, inferCategory, inject, name, normalizeExecutionEvent, normalizeExtractionTask, normalizeTaskList, parseRecalledMemories, resolveApiKey, resolveEndpoint, seedRunningTask, themeVar, truncateSessionId };