@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/README.md +1 -1
- package/lib/client.cjs +663 -16
- package/lib/client.cjs.map +1 -1
- package/lib/client.d.cts +224 -3
- package/lib/client.js +663 -16
- package/lib/client.js.map +1 -1
- package/lib/index.js +160 -2
- package/lib/index.js.map +1 -1
- package/package.json +1 -1
package/lib/client.js
CHANGED
|
@@ -16,7 +16,73 @@ import React2, {
|
|
|
16
16
|
import ReactDOM from "react-dom";
|
|
17
17
|
|
|
18
18
|
// src/client/api.ts
|
|
19
|
+
var TASKS_LIMIT_CAP = 200;
|
|
20
|
+
function normalizeExtractionTask(raw) {
|
|
21
|
+
if (!raw || typeof raw !== "object") return null;
|
|
22
|
+
const taskId = typeof raw.task_id === "string" && raw.task_id || typeof raw.id === "string" && raw.id || "";
|
|
23
|
+
if (!taskId) return null;
|
|
24
|
+
const statusRaw = typeof raw.status === "string" ? raw.status : "";
|
|
25
|
+
const status = statusRaw === "running" || statusRaw === "pending" || statusRaw === "completed" || statusRaw === "failed" ? statusRaw : "pending";
|
|
26
|
+
const result = raw.result ?? {};
|
|
27
|
+
const extracted = result.memories_extracted ?? {};
|
|
28
|
+
const numberOf = (v) => typeof v === "number" && Number.isFinite(v) ? v : void 0;
|
|
29
|
+
const tokenUsageRaw = result.token_usage ?? raw.token_usage;
|
|
30
|
+
const tokenUsage = typeof tokenUsageRaw === "number" ? tokenUsageRaw : numberOf(
|
|
31
|
+
tokenUsageRaw?.total_tokens
|
|
32
|
+
);
|
|
33
|
+
const errorRaw = raw.error;
|
|
34
|
+
const errorMsg = typeof errorRaw === "string" ? errorRaw : typeof errorRaw?.message === "string" ? errorRaw.message : void 0;
|
|
35
|
+
return {
|
|
36
|
+
task_id: taskId,
|
|
37
|
+
status,
|
|
38
|
+
resource_id: typeof raw.resource_id === "string" ? raw.resource_id : void 0,
|
|
39
|
+
created_at: typeof raw.created_at === "string" ? raw.created_at : void 0,
|
|
40
|
+
updated_at: typeof raw.updated_at === "string" ? raw.updated_at : void 0,
|
|
41
|
+
memory_write: numberOf(extracted.memory_write ?? extracted.written),
|
|
42
|
+
memory_edit: numberOf(extracted.memory_edit ?? extracted.edited),
|
|
43
|
+
token_usage: tokenUsage,
|
|
44
|
+
error: errorMsg
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
function computeBreakdown(tasks) {
|
|
48
|
+
const b = {
|
|
49
|
+
running: 0,
|
|
50
|
+
pending: 0,
|
|
51
|
+
completed: 0,
|
|
52
|
+
failed: 0,
|
|
53
|
+
total: tasks.length,
|
|
54
|
+
firstRunning: null,
|
|
55
|
+
lastCompleted: null,
|
|
56
|
+
lastFailed: null
|
|
57
|
+
};
|
|
58
|
+
for (const t of tasks) {
|
|
59
|
+
if (t.status === "running") {
|
|
60
|
+
b.running += 1;
|
|
61
|
+
if (!b.firstRunning) b.firstRunning = t;
|
|
62
|
+
} else if (t.status === "pending") b.pending += 1;
|
|
63
|
+
else if (t.status === "completed") {
|
|
64
|
+
b.completed += 1;
|
|
65
|
+
if (!b.lastCompleted) b.lastCompleted = t;
|
|
66
|
+
} else if (t.status === "failed") {
|
|
67
|
+
b.failed += 1;
|
|
68
|
+
if (!b.lastFailed) b.lastFailed = t;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
return b;
|
|
72
|
+
}
|
|
73
|
+
function normalizeExecutionEvent(raw) {
|
|
74
|
+
return {
|
|
75
|
+
seq: typeof raw.seq === "number" ? raw.seq : void 0,
|
|
76
|
+
recorded_at: typeof raw.recorded_at === "string" ? raw.recorded_at : void 0,
|
|
77
|
+
kind: typeof raw.kind === "string" ? raw.kind : void 0,
|
|
78
|
+
status: typeof raw.status === "string" ? raw.status : void 0,
|
|
79
|
+
stage: typeof raw.stage === "string" ? raw.stage : null,
|
|
80
|
+
operation: typeof raw.operation === "string" ? raw.operation : null,
|
|
81
|
+
error: typeof raw.error === "string" ? raw.error : null
|
|
82
|
+
};
|
|
83
|
+
}
|
|
19
84
|
var DEFAULT_OPENVIKING_ENDPOINT = "http://127.0.0.1:1933";
|
|
85
|
+
var PROXY_OPENVIKING_ENDPOINT = "/openviking-status/api";
|
|
20
86
|
function resolveEndpoint(endpoint) {
|
|
21
87
|
if (endpoint && endpoint.trim().length > 0) {
|
|
22
88
|
return endpoint.trim().replace(/\/+$/, "");
|
|
@@ -26,6 +92,7 @@ function resolveEndpoint(endpoint) {
|
|
|
26
92
|
if (typeof win.__OPENVIKING_ENDPOINT__ === "string" && win.__OPENVIKING_ENDPOINT__.trim()) {
|
|
27
93
|
return win.__OPENVIKING_ENDPOINT__.trim().replace(/\/+$/, "");
|
|
28
94
|
}
|
|
95
|
+
return PROXY_OPENVIKING_ENDPOINT;
|
|
29
96
|
}
|
|
30
97
|
if (typeof localStorage !== "undefined") {
|
|
31
98
|
try {
|
|
@@ -322,7 +389,9 @@ var OpenVikingClient = class {
|
|
|
322
389
|
const data = await res.json().catch(() => ({}));
|
|
323
390
|
return {
|
|
324
391
|
ok: data.ok === true,
|
|
325
|
-
error: typeof data.error === "string" ? data.error : void 0
|
|
392
|
+
error: typeof data.error === "string" ? data.error : void 0,
|
|
393
|
+
task_id: typeof data.task_id === "string" ? data.task_id : void 0,
|
|
394
|
+
resource_id: typeof data.resource_id === "string" ? data.resource_id : void 0
|
|
326
395
|
};
|
|
327
396
|
} catch (err) {
|
|
328
397
|
return {
|
|
@@ -354,7 +423,14 @@ var OpenVikingClient = class {
|
|
|
354
423
|
return { ok: false, error: String(errorMsg) };
|
|
355
424
|
}
|
|
356
425
|
this.resolvedSessionIds.set(sessionId.trim(), candidateId);
|
|
357
|
-
|
|
426
|
+
const okBody = await res.json().catch(() => ({}));
|
|
427
|
+
const container = okBody.result ?? okBody.data ?? okBody;
|
|
428
|
+
const taskId = container.task_id ?? container.id;
|
|
429
|
+
return {
|
|
430
|
+
ok: true,
|
|
431
|
+
task_id: typeof taskId === "string" && taskId.trim() ? taskId.trim() : void 0,
|
|
432
|
+
resource_id: candidateId
|
|
433
|
+
};
|
|
358
434
|
} catch (err) {
|
|
359
435
|
return {
|
|
360
436
|
ok: false,
|
|
@@ -364,7 +440,193 @@ var OpenVikingClient = class {
|
|
|
364
440
|
}
|
|
365
441
|
return { ok: false, error: lastError };
|
|
366
442
|
}
|
|
443
|
+
/**
|
|
444
|
+
* Список задач Phase 2 (Memory Extraction) текущей сессии со сводной
|
|
445
|
+
* разбивкой по статусам.
|
|
446
|
+
*
|
|
447
|
+
* Через прокси: один запрос `GET /tasks?session=<id>`, разбивка считается
|
|
448
|
+
* здесь. Напрямую: разрешаем `resource_id` через кандидатов и запрашиваем
|
|
449
|
+
* `GET /api/v1/tasks?resource_id=<id>&task_type=session_commit&limit=200`.
|
|
450
|
+
*/
|
|
451
|
+
async listTasks(sessionId) {
|
|
452
|
+
if (!sessionId || !sessionId.trim()) {
|
|
453
|
+
return { status: "missing" };
|
|
454
|
+
}
|
|
455
|
+
if (this.isProxy()) {
|
|
456
|
+
try {
|
|
457
|
+
const res = await fetch(
|
|
458
|
+
`${this.endpoint}/tasks?session=${encodeURIComponent(
|
|
459
|
+
sessionId.trim()
|
|
460
|
+
)}&limit=${TASKS_LIMIT_CAP}`,
|
|
461
|
+
{ method: "GET", headers: this.getHeaders() }
|
|
462
|
+
);
|
|
463
|
+
if (res.status === 401 || res.status === 403) {
|
|
464
|
+
return { status: "unauthorized" };
|
|
465
|
+
}
|
|
466
|
+
if (!res.ok) {
|
|
467
|
+
return { status: "error", detail: `HTTP ${res.status}` };
|
|
468
|
+
}
|
|
469
|
+
const data = await res.json();
|
|
470
|
+
if (data.status === "unauthorized") return { status: "unauthorized" };
|
|
471
|
+
if (data.status === "missing") return { status: "missing" };
|
|
472
|
+
if (data.status === "unreachable")
|
|
473
|
+
return {
|
|
474
|
+
status: "unreachable",
|
|
475
|
+
detail: typeof data.detail === "string" ? data.detail : void 0
|
|
476
|
+
};
|
|
477
|
+
if (data.status === "error")
|
|
478
|
+
return {
|
|
479
|
+
status: "error",
|
|
480
|
+
detail: typeof data.detail === "string" ? data.detail : void 0
|
|
481
|
+
};
|
|
482
|
+
const tasks = normalizeTaskList(data.tasks);
|
|
483
|
+
return { status: "ok", breakdown: computeBreakdown(tasks), tasks };
|
|
484
|
+
} catch (err) {
|
|
485
|
+
return {
|
|
486
|
+
status: "unreachable",
|
|
487
|
+
detail: err instanceof Error ? err.message : String(err)
|
|
488
|
+
};
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
const candidates = this.getCandidateSessionIds(sessionId);
|
|
492
|
+
let resourceId = null;
|
|
493
|
+
for (const candidateId of candidates) {
|
|
494
|
+
try {
|
|
495
|
+
const probe = await fetch(
|
|
496
|
+
`${this.endpoint}/api/v1/sessions/${encodeURIComponent(candidateId)}`,
|
|
497
|
+
{ method: "GET", headers: this.getHeaders() }
|
|
498
|
+
);
|
|
499
|
+
if (probe.status === 404) continue;
|
|
500
|
+
if (probe.status === 401 || probe.status === 403) {
|
|
501
|
+
return { status: "unauthorized" };
|
|
502
|
+
}
|
|
503
|
+
if (probe.ok) {
|
|
504
|
+
resourceId = candidateId;
|
|
505
|
+
this.resolvedSessionIds.set(sessionId.trim(), candidateId);
|
|
506
|
+
break;
|
|
507
|
+
}
|
|
508
|
+
} catch (err) {
|
|
509
|
+
return {
|
|
510
|
+
status: "unreachable",
|
|
511
|
+
detail: err instanceof Error ? err.message : String(err)
|
|
512
|
+
};
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
if (!resourceId) return { status: "missing" };
|
|
516
|
+
try {
|
|
517
|
+
const query = new URLSearchParams({
|
|
518
|
+
resource_id: resourceId,
|
|
519
|
+
task_type: "session_commit",
|
|
520
|
+
limit: String(TASKS_LIMIT_CAP)
|
|
521
|
+
});
|
|
522
|
+
const res = await fetch(
|
|
523
|
+
`${this.endpoint}/api/v1/tasks?${query.toString()}`,
|
|
524
|
+
{ method: "GET", headers: this.getHeaders() }
|
|
525
|
+
);
|
|
526
|
+
if (res.status === 401 || res.status === 403) {
|
|
527
|
+
return { status: "unauthorized" };
|
|
528
|
+
}
|
|
529
|
+
if (!res.ok) {
|
|
530
|
+
return { status: "error", detail: `HTTP ${res.status}` };
|
|
531
|
+
}
|
|
532
|
+
const data = await res.json();
|
|
533
|
+
const items = data?.items ?? data?.tasks ?? data?.result?.items ?? (Array.isArray(data) ? data : []);
|
|
534
|
+
const tasks = normalizeTaskList(items);
|
|
535
|
+
return { status: "ok", breakdown: computeBreakdown(tasks), tasks };
|
|
536
|
+
} catch (err) {
|
|
537
|
+
return {
|
|
538
|
+
status: "unreachable",
|
|
539
|
+
detail: err instanceof Error ? err.message : String(err)
|
|
540
|
+
};
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
/**
|
|
544
|
+
* Лениво загрузить одну задачу с лентой `execution_events` для «Show log».
|
|
545
|
+
*/
|
|
546
|
+
async fetchTaskEvents(taskId) {
|
|
547
|
+
if (!taskId || !taskId.trim()) {
|
|
548
|
+
return { status: "missing" };
|
|
549
|
+
}
|
|
550
|
+
const buildOk = (taskRaw) => {
|
|
551
|
+
const task = normalizeExtractionTask(taskRaw);
|
|
552
|
+
const eventsContainer = taskRaw.execution_events ?? {};
|
|
553
|
+
const rawEvents = eventsContainer.items ?? (Array.isArray(taskRaw.execution_events) ? taskRaw.execution_events : []);
|
|
554
|
+
const events = (Array.isArray(rawEvents) ? rawEvents : []).filter(
|
|
555
|
+
(e) => !!e && typeof e === "object"
|
|
556
|
+
).map(normalizeExecutionEvent);
|
|
557
|
+
if (!task) return { status: "error", detail: "malformed task" };
|
|
558
|
+
return { status: "ok", task, events };
|
|
559
|
+
};
|
|
560
|
+
if (this.isProxy()) {
|
|
561
|
+
try {
|
|
562
|
+
const res = await fetch(
|
|
563
|
+
`${this.endpoint}/task?id=${encodeURIComponent(
|
|
564
|
+
taskId.trim()
|
|
565
|
+
)}&events=1`,
|
|
566
|
+
{ method: "GET", headers: this.getHeaders() }
|
|
567
|
+
);
|
|
568
|
+
if (res.status === 401 || res.status === 403) {
|
|
569
|
+
return { status: "unauthorized" };
|
|
570
|
+
}
|
|
571
|
+
if (!res.ok) {
|
|
572
|
+
return { status: "error", detail: `HTTP ${res.status}` };
|
|
573
|
+
}
|
|
574
|
+
const data = await res.json();
|
|
575
|
+
if (data.status === "unauthorized") return { status: "unauthorized" };
|
|
576
|
+
if (data.status === "missing") return { status: "missing" };
|
|
577
|
+
if (data.status === "unreachable")
|
|
578
|
+
return {
|
|
579
|
+
status: "unreachable",
|
|
580
|
+
detail: typeof data.detail === "string" ? data.detail : void 0
|
|
581
|
+
};
|
|
582
|
+
if (data.status === "error")
|
|
583
|
+
return {
|
|
584
|
+
status: "error",
|
|
585
|
+
detail: typeof data.detail === "string" ? data.detail : void 0
|
|
586
|
+
};
|
|
587
|
+
return buildOk(data.task ?? {});
|
|
588
|
+
} catch (err) {
|
|
589
|
+
return {
|
|
590
|
+
status: "unreachable",
|
|
591
|
+
detail: err instanceof Error ? err.message : String(err)
|
|
592
|
+
};
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
try {
|
|
596
|
+
const res = await fetch(
|
|
597
|
+
`${this.endpoint}/api/v1/tasks/${encodeURIComponent(
|
|
598
|
+
taskId.trim()
|
|
599
|
+
)}?include_events=true`,
|
|
600
|
+
{ method: "GET", headers: this.getHeaders() }
|
|
601
|
+
);
|
|
602
|
+
if (res.status === 404) return { status: "missing" };
|
|
603
|
+
if (res.status === 401 || res.status === 403) {
|
|
604
|
+
return { status: "unauthorized" };
|
|
605
|
+
}
|
|
606
|
+
if (!res.ok) {
|
|
607
|
+
return { status: "error", detail: `HTTP ${res.status}` };
|
|
608
|
+
}
|
|
609
|
+
const data = await res.json();
|
|
610
|
+
const taskRaw = data?.result ?? data?.data ?? data;
|
|
611
|
+
return buildOk(taskRaw);
|
|
612
|
+
} catch (err) {
|
|
613
|
+
return {
|
|
614
|
+
status: "unreachable",
|
|
615
|
+
detail: err instanceof Error ? err.message : String(err)
|
|
616
|
+
};
|
|
617
|
+
}
|
|
618
|
+
}
|
|
367
619
|
};
|
|
620
|
+
function normalizeTaskList(raw) {
|
|
621
|
+
if (!Array.isArray(raw)) return [];
|
|
622
|
+
const tasks = [];
|
|
623
|
+
for (const entry of raw) {
|
|
624
|
+
if (!entry || typeof entry !== "object") continue;
|
|
625
|
+
const task = normalizeExtractionTask(entry);
|
|
626
|
+
if (task) tasks.push(task);
|
|
627
|
+
}
|
|
628
|
+
return tasks;
|
|
629
|
+
}
|
|
368
630
|
var defaultOpenVikingClient = new OpenVikingClient();
|
|
369
631
|
function checkHealth(endpoint, apiKey) {
|
|
370
632
|
const client = endpoint || apiKey ? new OpenVikingClient(endpoint, apiKey) : defaultOpenVikingClient;
|
|
@@ -738,6 +1000,39 @@ function dshIcon(name2) {
|
|
|
738
1000
|
return null;
|
|
739
1001
|
}
|
|
740
1002
|
}
|
|
1003
|
+
function formatDuration(startIso, endIso) {
|
|
1004
|
+
if (!startIso || !endIso) return void 0;
|
|
1005
|
+
const start = new Date(startIso).getTime();
|
|
1006
|
+
const end = new Date(endIso).getTime();
|
|
1007
|
+
if (isNaN(start) || isNaN(end) || end < start) return void 0;
|
|
1008
|
+
const ms = end - start;
|
|
1009
|
+
const sec = ms / 1e3;
|
|
1010
|
+
if (sec < 60) {
|
|
1011
|
+
return `${sec < 10 ? sec.toFixed(1) : Math.round(sec)}s`;
|
|
1012
|
+
}
|
|
1013
|
+
const min = Math.floor(sec / 60);
|
|
1014
|
+
const rem = Math.round(sec % 60);
|
|
1015
|
+
return `${min}m ${rem}s`;
|
|
1016
|
+
}
|
|
1017
|
+
function formatExtractionSummary(task, now = Date.now()) {
|
|
1018
|
+
const write = task.memory_write ?? 0;
|
|
1019
|
+
const edit = task.memory_edit ?? 0;
|
|
1020
|
+
const parts = [`${write} written, ${edit} edited`];
|
|
1021
|
+
const duration = formatDuration(task.created_at, task.updated_at);
|
|
1022
|
+
if (duration) parts.push(duration);
|
|
1023
|
+
const rel = formatRelativeTime(task.updated_at, now);
|
|
1024
|
+
if (rel) parts.push(rel);
|
|
1025
|
+
return parts.join(" \xB7 ");
|
|
1026
|
+
}
|
|
1027
|
+
function formatBacklog(breakdown) {
|
|
1028
|
+
if (!breakdown) return null;
|
|
1029
|
+
const { pending, failed } = breakdown;
|
|
1030
|
+
if (pending <= 0 && failed <= 0) return null;
|
|
1031
|
+
const parts = [];
|
|
1032
|
+
if (pending > 0) parts.push(`${pending} pending`);
|
|
1033
|
+
if (failed > 0) parts.push(`${failed} failed`);
|
|
1034
|
+
return parts.join(" / ");
|
|
1035
|
+
}
|
|
741
1036
|
function getProgressBarPercent(pendingTokens, threshold = COMMIT_THRESHOLD) {
|
|
742
1037
|
if (!threshold || threshold <= 0) return 0;
|
|
743
1038
|
const ratio = (pendingTokens || 0) / threshold;
|
|
@@ -784,10 +1079,10 @@ function formatMemoryLeafName(uri) {
|
|
|
784
1079
|
return segments[0] || clean;
|
|
785
1080
|
}
|
|
786
1081
|
function formatEndpoint(endpoint) {
|
|
787
|
-
if (!endpoint || !endpoint.trim()) {
|
|
1082
|
+
if (!endpoint || !endpoint.trim() || endpoint.startsWith("/")) {
|
|
788
1083
|
return "127.0.0.1:1933";
|
|
789
1084
|
}
|
|
790
|
-
return endpoint.trim().replace(/^https?:\/\//, "");
|
|
1085
|
+
return endpoint.trim().replace(/^https?:\/\//, "").replace(/\/+$/, "");
|
|
791
1086
|
}
|
|
792
1087
|
function truncateSessionId(id, maxLen = 16) {
|
|
793
1088
|
if (!id) return "";
|
|
@@ -804,6 +1099,229 @@ function handleEscapeKey(event, onClose) {
|
|
|
804
1099
|
}
|
|
805
1100
|
return false;
|
|
806
1101
|
}
|
|
1102
|
+
function ExtractionSection({
|
|
1103
|
+
breakdown,
|
|
1104
|
+
client
|
|
1105
|
+
}) {
|
|
1106
|
+
const [showLog, setShowLog] = useState(false);
|
|
1107
|
+
const [events, setEvents] = useState(null);
|
|
1108
|
+
const [logError, setLogError] = useState(null);
|
|
1109
|
+
const [loadingLog, setLoadingLog] = useState(false);
|
|
1110
|
+
if (!breakdown) return null;
|
|
1111
|
+
const isRunning = breakdown.running >= 1;
|
|
1112
|
+
const lastCompleted = breakdown.lastCompleted;
|
|
1113
|
+
const lastFailed = breakdown.lastFailed;
|
|
1114
|
+
const backlog = formatBacklog(breakdown);
|
|
1115
|
+
const failedActive = !isRunning && breakdown.failed >= 1;
|
|
1116
|
+
const logTaskId = (isRunning ? breakdown.firstRunning?.task_id : null) ?? (failedActive ? lastFailed?.task_id : null) ?? lastCompleted?.task_id ?? lastFailed?.task_id ?? null;
|
|
1117
|
+
const mutedStyle = { color: themeVar("labelTertiary") };
|
|
1118
|
+
const toggleLog = useCallback(async () => {
|
|
1119
|
+
const next = !showLog;
|
|
1120
|
+
setShowLog(next);
|
|
1121
|
+
if (next && events === null && logTaskId && client) {
|
|
1122
|
+
setLoadingLog(true);
|
|
1123
|
+
setLogError(null);
|
|
1124
|
+
const res = await client.fetchTaskEvents(logTaskId);
|
|
1125
|
+
setLoadingLog(false);
|
|
1126
|
+
if (res.status === "ok") {
|
|
1127
|
+
setEvents(res.events);
|
|
1128
|
+
} else {
|
|
1129
|
+
setLogError(
|
|
1130
|
+
res.status === "unauthorized" ? "No access to task log" : "Could not load log"
|
|
1131
|
+
);
|
|
1132
|
+
}
|
|
1133
|
+
}
|
|
1134
|
+
}, [showLog, events, logTaskId, client]);
|
|
1135
|
+
if (!isRunning && !failedActive && !lastCompleted && !backlog) {
|
|
1136
|
+
return null;
|
|
1137
|
+
}
|
|
1138
|
+
return /* @__PURE__ */ jsxs("div", { "data-testid": "extraction-section", style: { marginBottom: "12px" }, children: [
|
|
1139
|
+
/* @__PURE__ */ jsx(
|
|
1140
|
+
"div",
|
|
1141
|
+
{
|
|
1142
|
+
style: {
|
|
1143
|
+
marginBottom: "4px",
|
|
1144
|
+
color: themeVar("labelPrimary"),
|
|
1145
|
+
fontWeight: 500
|
|
1146
|
+
},
|
|
1147
|
+
children: "Memory Extraction"
|
|
1148
|
+
}
|
|
1149
|
+
),
|
|
1150
|
+
isRunning ? /* @__PURE__ */ jsxs("div", { children: [
|
|
1151
|
+
/* @__PURE__ */ jsxs(
|
|
1152
|
+
"div",
|
|
1153
|
+
{
|
|
1154
|
+
style: {
|
|
1155
|
+
display: "flex",
|
|
1156
|
+
alignItems: "center",
|
|
1157
|
+
gap: "6px",
|
|
1158
|
+
marginBottom: "4px"
|
|
1159
|
+
},
|
|
1160
|
+
children: [
|
|
1161
|
+
/* @__PURE__ */ jsx(
|
|
1162
|
+
"span",
|
|
1163
|
+
{
|
|
1164
|
+
"data-testid": "extraction-status-dot",
|
|
1165
|
+
"aria-hidden": "true",
|
|
1166
|
+
style: {
|
|
1167
|
+
width: "6px",
|
|
1168
|
+
height: "6px",
|
|
1169
|
+
borderRadius: "50%",
|
|
1170
|
+
background: themeVar("stateSuccess"),
|
|
1171
|
+
animation: "ov-pulse 1.2s ease-in-out infinite",
|
|
1172
|
+
flexShrink: 0
|
|
1173
|
+
}
|
|
1174
|
+
}
|
|
1175
|
+
),
|
|
1176
|
+
/* @__PURE__ */ jsx("span", { "data-testid": "extraction-running-label", children: "Extracting\u2026" })
|
|
1177
|
+
]
|
|
1178
|
+
}
|
|
1179
|
+
),
|
|
1180
|
+
/* @__PURE__ */ jsx(
|
|
1181
|
+
"div",
|
|
1182
|
+
{
|
|
1183
|
+
"data-testid": "extraction-indeterminate-track",
|
|
1184
|
+
style: {
|
|
1185
|
+
width: "100%",
|
|
1186
|
+
height: "6px",
|
|
1187
|
+
borderRadius: "3px",
|
|
1188
|
+
backgroundColor: themeVar("insetSurface"),
|
|
1189
|
+
overflow: "hidden",
|
|
1190
|
+
position: "relative"
|
|
1191
|
+
},
|
|
1192
|
+
children: /* @__PURE__ */ jsx(
|
|
1193
|
+
"div",
|
|
1194
|
+
{
|
|
1195
|
+
"data-testid": "extraction-indeterminate-fill",
|
|
1196
|
+
style: {
|
|
1197
|
+
position: "absolute",
|
|
1198
|
+
left: 0,
|
|
1199
|
+
top: 0,
|
|
1200
|
+
height: "100%",
|
|
1201
|
+
width: "40%",
|
|
1202
|
+
borderRadius: "3px",
|
|
1203
|
+
backgroundColor: themeVar("stateSuccess"),
|
|
1204
|
+
animation: "ov-indeterminate 1.2s ease-in-out infinite"
|
|
1205
|
+
}
|
|
1206
|
+
}
|
|
1207
|
+
)
|
|
1208
|
+
}
|
|
1209
|
+
)
|
|
1210
|
+
] }) : failedActive && lastFailed ? /* @__PURE__ */ jsxs(
|
|
1211
|
+
"div",
|
|
1212
|
+
{
|
|
1213
|
+
"data-testid": "extraction-failed-line",
|
|
1214
|
+
style: {
|
|
1215
|
+
display: "flex",
|
|
1216
|
+
alignItems: "center",
|
|
1217
|
+
gap: "6px",
|
|
1218
|
+
color: themeVar("stateWarning")
|
|
1219
|
+
},
|
|
1220
|
+
children: [
|
|
1221
|
+
/* @__PURE__ */ jsx(
|
|
1222
|
+
"span",
|
|
1223
|
+
{
|
|
1224
|
+
"aria-hidden": "true",
|
|
1225
|
+
style: { display: "inline-flex", flexShrink: 0 },
|
|
1226
|
+
children: /* @__PURE__ */ jsx(WarningGlyph, { size: 12, testId: "extraction-warning-glyph" })
|
|
1227
|
+
}
|
|
1228
|
+
),
|
|
1229
|
+
/* @__PURE__ */ jsx("span", { "data-testid": "extraction-failed-text", children: lastFailed.error || "extraction failed" })
|
|
1230
|
+
]
|
|
1231
|
+
}
|
|
1232
|
+
) : lastCompleted ? /* @__PURE__ */ jsxs(
|
|
1233
|
+
"div",
|
|
1234
|
+
{
|
|
1235
|
+
style: {
|
|
1236
|
+
display: "flex",
|
|
1237
|
+
alignItems: "center",
|
|
1238
|
+
gap: "6px"
|
|
1239
|
+
},
|
|
1240
|
+
children: [
|
|
1241
|
+
/* @__PURE__ */ jsx(
|
|
1242
|
+
"span",
|
|
1243
|
+
{
|
|
1244
|
+
"data-testid": "extraction-status-dot",
|
|
1245
|
+
"aria-hidden": "true",
|
|
1246
|
+
style: {
|
|
1247
|
+
width: "6px",
|
|
1248
|
+
height: "6px",
|
|
1249
|
+
borderRadius: "50%",
|
|
1250
|
+
background: themeVar("stateSuccess"),
|
|
1251
|
+
flexShrink: 0
|
|
1252
|
+
}
|
|
1253
|
+
}
|
|
1254
|
+
),
|
|
1255
|
+
/* @__PURE__ */ jsx("span", { "data-testid": "extraction-last-line", children: formatExtractionSummary(lastCompleted) })
|
|
1256
|
+
]
|
|
1257
|
+
}
|
|
1258
|
+
) : null,
|
|
1259
|
+
backlog && /* @__PURE__ */ jsx(
|
|
1260
|
+
"div",
|
|
1261
|
+
{
|
|
1262
|
+
"data-testid": "extraction-backlog-line",
|
|
1263
|
+
style: { ...mutedStyle, marginTop: "4px" },
|
|
1264
|
+
children: backlog
|
|
1265
|
+
}
|
|
1266
|
+
),
|
|
1267
|
+
logTaskId && client && /* @__PURE__ */ jsxs("div", { style: { marginTop: "6px" }, children: [
|
|
1268
|
+
/* @__PURE__ */ jsx(
|
|
1269
|
+
"button",
|
|
1270
|
+
{
|
|
1271
|
+
type: "button",
|
|
1272
|
+
"data-testid": "extraction-show-log-btn",
|
|
1273
|
+
onClick: () => void toggleLog(),
|
|
1274
|
+
style: {
|
|
1275
|
+
background: "none",
|
|
1276
|
+
border: "none",
|
|
1277
|
+
padding: 0,
|
|
1278
|
+
cursor: "pointer",
|
|
1279
|
+
font: "inherit",
|
|
1280
|
+
color: themeVar("labelTertiary"),
|
|
1281
|
+
textDecoration: "underline"
|
|
1282
|
+
},
|
|
1283
|
+
"aria-expanded": showLog,
|
|
1284
|
+
children: showLog ? "Hide log" : "Show log"
|
|
1285
|
+
}
|
|
1286
|
+
),
|
|
1287
|
+
showLog && /* @__PURE__ */ jsxs(
|
|
1288
|
+
"div",
|
|
1289
|
+
{
|
|
1290
|
+
"data-testid": "extraction-log",
|
|
1291
|
+
style: {
|
|
1292
|
+
marginTop: "6px",
|
|
1293
|
+
display: "flex",
|
|
1294
|
+
flexDirection: "column",
|
|
1295
|
+
gap: "2px",
|
|
1296
|
+
maxHeight: "120px",
|
|
1297
|
+
overflowY: "auto"
|
|
1298
|
+
},
|
|
1299
|
+
children: [
|
|
1300
|
+
loadingLog && /* @__PURE__ */ jsx("div", { "data-testid": "extraction-log-loading", style: mutedStyle, children: "Loading\u2026" }),
|
|
1301
|
+
logError && /* @__PURE__ */ jsx("div", { "data-testid": "extraction-log-error", style: mutedStyle, children: logError }),
|
|
1302
|
+
events && events.length === 0 && !loadingLog && !logError && /* @__PURE__ */ jsx("div", { "data-testid": "extraction-log-empty", style: mutedStyle, children: "No events" }),
|
|
1303
|
+
events?.map((ev, idx) => /* @__PURE__ */ jsxs(
|
|
1304
|
+
"div",
|
|
1305
|
+
{
|
|
1306
|
+
"data-testid": "extraction-log-event",
|
|
1307
|
+
style: {
|
|
1308
|
+
display: "flex",
|
|
1309
|
+
justifyContent: "space-between",
|
|
1310
|
+
gap: "8px"
|
|
1311
|
+
},
|
|
1312
|
+
children: [
|
|
1313
|
+
/* @__PURE__ */ jsx("span", { children: ev.status || ev.kind || "event" }),
|
|
1314
|
+
/* @__PURE__ */ jsx("span", { style: mutedStyle, children: formatRelativeTime(ev.recorded_at) || "" })
|
|
1315
|
+
]
|
|
1316
|
+
},
|
|
1317
|
+
`${ev.seq ?? idx}-${ev.recorded_at ?? idx}`
|
|
1318
|
+
))
|
|
1319
|
+
]
|
|
1320
|
+
}
|
|
1321
|
+
)
|
|
1322
|
+
] })
|
|
1323
|
+
] });
|
|
1324
|
+
}
|
|
807
1325
|
function OpenVikingStatusPopover({
|
|
808
1326
|
sessionId,
|
|
809
1327
|
health,
|
|
@@ -813,6 +1331,8 @@ function OpenVikingStatusPopover({
|
|
|
813
1331
|
endpoint,
|
|
814
1332
|
isCommitting = false,
|
|
815
1333
|
commitError = null,
|
|
1334
|
+
breakdown = null,
|
|
1335
|
+
client,
|
|
816
1336
|
onCommitNow,
|
|
817
1337
|
onClose,
|
|
818
1338
|
className,
|
|
@@ -893,7 +1413,7 @@ function OpenVikingStatusPopover({
|
|
|
893
1413
|
...style
|
|
894
1414
|
},
|
|
895
1415
|
children: [
|
|
896
|
-
/* @__PURE__ */ jsx("style", { children: `@keyframes ov-spin { from { transform: rotate(0deg); } to { transform: rotate(360deg); } }` }),
|
|
1416
|
+
/* @__PURE__ */ jsx("style", { children: `@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%; } }` }),
|
|
897
1417
|
/* @__PURE__ */ jsxs(
|
|
898
1418
|
"div",
|
|
899
1419
|
{
|
|
@@ -914,7 +1434,7 @@ function OpenVikingStatusPopover({
|
|
|
914
1434
|
{
|
|
915
1435
|
"data-testid": "endpoint-label",
|
|
916
1436
|
style: { ...mutedStyle, ...monoStyle, fontWeight: 400 },
|
|
917
|
-
children: formatEndpoint(endpoint)
|
|
1437
|
+
children: formatEndpoint(health?.endpoint || endpoint)
|
|
918
1438
|
}
|
|
919
1439
|
)
|
|
920
1440
|
] }),
|
|
@@ -1090,7 +1610,7 @@ function OpenVikingStatusPopover({
|
|
|
1090
1610
|
marginBottom: "12px",
|
|
1091
1611
|
color: themeVar("labelTertiary")
|
|
1092
1612
|
},
|
|
1093
|
-
children: unauthorized ? "The daemon requires an API key.
|
|
1613
|
+
children: unauthorized ? "The daemon requires an API key. Configure it in DSH Settings \u2192 OpenViking." : "Session counters are unavailable right now."
|
|
1094
1614
|
}
|
|
1095
1615
|
),
|
|
1096
1616
|
/* @__PURE__ */ jsxs("div", { style: { marginBottom: "12px" }, children: [
|
|
@@ -1176,6 +1696,7 @@ function OpenVikingStatusPopover({
|
|
|
1176
1696
|
}
|
|
1177
1697
|
)
|
|
1178
1698
|
] }),
|
|
1699
|
+
/* @__PURE__ */ jsx(ExtractionSection, { breakdown, client }),
|
|
1179
1700
|
commitError && /* @__PURE__ */ jsx(
|
|
1180
1701
|
"div",
|
|
1181
1702
|
{
|
|
@@ -1233,6 +1754,77 @@ function OpenVikingStatusPopover({
|
|
|
1233
1754
|
// src/client/OpenVikingStatusChip.tsx
|
|
1234
1755
|
import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
1235
1756
|
var COMMIT_THRESHOLD = 2e4;
|
|
1757
|
+
var POLL_INTERVAL_IDLE_MS = 15e3;
|
|
1758
|
+
var POLL_INTERVAL_ACTIVE_MS = 2500;
|
|
1759
|
+
function getChipDotState({
|
|
1760
|
+
isOnline,
|
|
1761
|
+
sessionUnreadable,
|
|
1762
|
+
breakdown
|
|
1763
|
+
}) {
|
|
1764
|
+
if (!isOnline) return "offline";
|
|
1765
|
+
if (sessionUnreadable) return "session-unreadable";
|
|
1766
|
+
if (breakdown && breakdown.running >= 1) return "busy";
|
|
1767
|
+
if (breakdown && breakdown.failed >= 1) return "extraction-failed";
|
|
1768
|
+
return "online-idle";
|
|
1769
|
+
}
|
|
1770
|
+
function WarningGlyph({
|
|
1771
|
+
size = 11,
|
|
1772
|
+
testId = "extraction-warning-glyph"
|
|
1773
|
+
}) {
|
|
1774
|
+
return /* @__PURE__ */ jsxs2(
|
|
1775
|
+
"svg",
|
|
1776
|
+
{
|
|
1777
|
+
"data-testid": testId,
|
|
1778
|
+
width: size,
|
|
1779
|
+
height: size,
|
|
1780
|
+
viewBox: "0 0 16 16",
|
|
1781
|
+
fill: "none",
|
|
1782
|
+
"aria-hidden": "true",
|
|
1783
|
+
style: { flexShrink: 0, display: "block" },
|
|
1784
|
+
children: [
|
|
1785
|
+
/* @__PURE__ */ jsx2("circle", { cx: "8", cy: "8", r: "6.5", stroke: "currentColor", strokeWidth: "1.5" }),
|
|
1786
|
+
/* @__PURE__ */ jsx2(
|
|
1787
|
+
"path",
|
|
1788
|
+
{
|
|
1789
|
+
d: "M8 5v3.5",
|
|
1790
|
+
stroke: "currentColor",
|
|
1791
|
+
strokeWidth: "1.5",
|
|
1792
|
+
strokeLinecap: "round"
|
|
1793
|
+
}
|
|
1794
|
+
),
|
|
1795
|
+
/* @__PURE__ */ jsx2("circle", { cx: "8", cy: "11", r: "0.9", fill: "currentColor" })
|
|
1796
|
+
]
|
|
1797
|
+
}
|
|
1798
|
+
);
|
|
1799
|
+
}
|
|
1800
|
+
function seedRunningTask(prev, taskId, resourceId) {
|
|
1801
|
+
const existing = prev && prev.status === "ok" ? prev.tasks : [];
|
|
1802
|
+
if (existing.some((t) => t.task_id === taskId)) {
|
|
1803
|
+
return prev;
|
|
1804
|
+
}
|
|
1805
|
+
const seeded = {
|
|
1806
|
+
task_id: taskId,
|
|
1807
|
+
status: "running",
|
|
1808
|
+
resource_id: resourceId,
|
|
1809
|
+
updated_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
1810
|
+
};
|
|
1811
|
+
const tasks = [seeded, ...existing];
|
|
1812
|
+
return { status: "ok", breakdown: computeBreakdown(tasks), tasks };
|
|
1813
|
+
}
|
|
1814
|
+
function getDotColorForState(state) {
|
|
1815
|
+
switch (state) {
|
|
1816
|
+
case "offline":
|
|
1817
|
+
return themeVar("stateError");
|
|
1818
|
+
case "session-unreadable":
|
|
1819
|
+
case "extraction-failed":
|
|
1820
|
+
return themeVar("stateWarning");
|
|
1821
|
+
case "busy":
|
|
1822
|
+
return themeVar("stateSuccess");
|
|
1823
|
+
case "online-idle":
|
|
1824
|
+
default:
|
|
1825
|
+
return themeVar("stateSuccess");
|
|
1826
|
+
}
|
|
1827
|
+
}
|
|
1236
1828
|
function formatPendingTokens(pendingTokens) {
|
|
1237
1829
|
const k = Math.round((pendingTokens || 0) / 1e3);
|
|
1238
1830
|
return `${k}k pend`;
|
|
@@ -1335,6 +1927,7 @@ function StatusChipView({
|
|
|
1335
1927
|
initialHealth,
|
|
1336
1928
|
initialSessionData,
|
|
1337
1929
|
initialSessionRead,
|
|
1930
|
+
initialTasksRead,
|
|
1338
1931
|
initialOpen = false
|
|
1339
1932
|
}) {
|
|
1340
1933
|
const [health, setHealth] = useState2(
|
|
@@ -1343,6 +1936,9 @@ function StatusChipView({
|
|
|
1343
1936
|
const [sessionRead, setSessionRead] = useState2(
|
|
1344
1937
|
initialSessionRead ?? (initialSessionData ? { status: "ok", session: initialSessionData } : null)
|
|
1345
1938
|
);
|
|
1939
|
+
const [tasksRead, setTasksRead] = useState2(
|
|
1940
|
+
initialTasksRead ?? null
|
|
1941
|
+
);
|
|
1346
1942
|
const [isOpen, setIsOpen] = useState2(initialOpen);
|
|
1347
1943
|
const [isCommitting, setIsCommitting] = useState2(false);
|
|
1348
1944
|
const [commitError, setCommitError] = useState2(null);
|
|
@@ -1378,16 +1974,24 @@ function StatusChipView({
|
|
|
1378
1974
|
if (!healthRes.ok) {
|
|
1379
1975
|
return;
|
|
1380
1976
|
}
|
|
1381
|
-
|
|
1977
|
+
const [session, tasks] = await Promise.all([
|
|
1978
|
+
apiClient.readSession(sessionId),
|
|
1979
|
+
apiClient.listTasks(sessionId)
|
|
1980
|
+
]);
|
|
1981
|
+
setSessionRead(session);
|
|
1982
|
+
setTasksRead(tasks);
|
|
1382
1983
|
} catch {
|
|
1383
1984
|
setHealth({ ok: false });
|
|
1384
1985
|
}
|
|
1385
1986
|
}, [sessionId, apiClient]);
|
|
1987
|
+
const breakdown = tasksRead?.status === "ok" ? tasksRead.breakdown : null;
|
|
1988
|
+
const hasRunning = (breakdown?.running ?? 0) >= 1;
|
|
1386
1989
|
useEffect2(() => {
|
|
1387
1990
|
fetchStatus();
|
|
1388
|
-
const
|
|
1991
|
+
const interval = hasRunning ? POLL_INTERVAL_ACTIVE_MS : POLL_INTERVAL_IDLE_MS;
|
|
1992
|
+
const timer = setInterval(fetchStatus, interval);
|
|
1389
1993
|
return () => clearInterval(timer);
|
|
1390
|
-
}, [fetchStatus]);
|
|
1994
|
+
}, [fetchStatus, hasRunning]);
|
|
1391
1995
|
useEffect2(() => {
|
|
1392
1996
|
function handleClickOutside(event) {
|
|
1393
1997
|
if (popoverRef.current && !popoverRef.current.contains(event.target)) {
|
|
@@ -1417,6 +2021,11 @@ function StatusChipView({
|
|
|
1417
2021
|
keep_recent_count: 10
|
|
1418
2022
|
});
|
|
1419
2023
|
if (res.ok) {
|
|
2024
|
+
if (res.task_id) {
|
|
2025
|
+
setTasksRead(
|
|
2026
|
+
(prev) => seedRunningTask(prev, res.task_id, res.resource_id)
|
|
2027
|
+
);
|
|
2028
|
+
}
|
|
1420
2029
|
await fetchStatus();
|
|
1421
2030
|
onCommit?.();
|
|
1422
2031
|
} else {
|
|
@@ -1435,11 +2044,15 @@ function StatusChipView({
|
|
|
1435
2044
|
const sessionUnreadable = isOnline && sessionRead !== null && sessionRead.status !== "ok";
|
|
1436
2045
|
const pendingTokens = sessionData?.pending_tokens ?? 0;
|
|
1437
2046
|
const recalledCount = recalledResult.recalledCount;
|
|
1438
|
-
const
|
|
2047
|
+
const rawDotState = getChipDotState({
|
|
1439
2048
|
isOnline,
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
);
|
|
2049
|
+
sessionUnreadable,
|
|
2050
|
+
breakdown
|
|
2051
|
+
});
|
|
2052
|
+
const dotState = isCommitting && (rawDotState === "online-idle" || rawDotState === "busy") ? "busy" : rawDotState;
|
|
2053
|
+
const dotBusy = dotState === "busy";
|
|
2054
|
+
const dotFailed = dotState === "extraction-failed";
|
|
2055
|
+
const statusColor = getDotColorForState(dotState);
|
|
1443
2056
|
const tooltipTitle = formatTooltipTitle({
|
|
1444
2057
|
isOnline,
|
|
1445
2058
|
isCommitting,
|
|
@@ -1456,6 +2069,7 @@ function StatusChipView({
|
|
|
1456
2069
|
style: { minWidth: 0, display: "inline-flex", position: "relative" },
|
|
1457
2070
|
ref: popoverRef,
|
|
1458
2071
|
children: [
|
|
2072
|
+
/* @__PURE__ */ jsx2("style", { children: `@keyframes ov-pulse { 0%, 100% { opacity: 1; transform: scale(1); } 50% { opacity: 0.35; transform: scale(0.72); } }` }),
|
|
1459
2073
|
/* @__PURE__ */ jsxs2(
|
|
1460
2074
|
"button",
|
|
1461
2075
|
{
|
|
@@ -1486,17 +2100,32 @@ function StatusChipView({
|
|
|
1486
2100
|
title: tooltipTitle,
|
|
1487
2101
|
"aria-label": tooltipTitle,
|
|
1488
2102
|
children: [
|
|
1489
|
-
/* @__PURE__ */ jsx2(
|
|
2103
|
+
dotFailed ? /* @__PURE__ */ jsx2(
|
|
1490
2104
|
"span",
|
|
1491
2105
|
{
|
|
1492
2106
|
"data-testid": "status-dot",
|
|
2107
|
+
"data-dot-state": dotState,
|
|
2108
|
+
"aria-hidden": "true",
|
|
2109
|
+
style: {
|
|
2110
|
+
display: "inline-flex",
|
|
2111
|
+
color: statusColor,
|
|
2112
|
+
flexShrink: 0
|
|
2113
|
+
},
|
|
2114
|
+
children: /* @__PURE__ */ jsx2(WarningGlyph, { size: 11, testId: "chip-warning-glyph" })
|
|
2115
|
+
}
|
|
2116
|
+
) : /* @__PURE__ */ jsx2(
|
|
2117
|
+
"span",
|
|
2118
|
+
{
|
|
2119
|
+
"data-testid": "status-dot",
|
|
2120
|
+
"data-dot-state": dotBusy ? "busy" : dotState,
|
|
1493
2121
|
"aria-hidden": "true",
|
|
1494
2122
|
style: {
|
|
1495
2123
|
width: "6px",
|
|
1496
2124
|
height: "6px",
|
|
1497
2125
|
borderRadius: "50%",
|
|
1498
2126
|
background: statusColor,
|
|
1499
|
-
flexShrink: 0
|
|
2127
|
+
flexShrink: 0,
|
|
2128
|
+
...dotBusy ? { animation: "ov-pulse 1.2s ease-in-out infinite" } : {}
|
|
1500
2129
|
}
|
|
1501
2130
|
}
|
|
1502
2131
|
),
|
|
@@ -1515,6 +2144,8 @@ function StatusChipView({
|
|
|
1515
2144
|
endpoint: apiClient.endpoint,
|
|
1516
2145
|
isCommitting,
|
|
1517
2146
|
commitError,
|
|
2147
|
+
breakdown,
|
|
2148
|
+
client: apiClient,
|
|
1518
2149
|
onCommitNow: handleCommitNow,
|
|
1519
2150
|
onClose: () => setIsOpen(false)
|
|
1520
2151
|
}
|
|
@@ -2128,25 +2759,37 @@ function apply(ctx) {
|
|
|
2128
2759
|
export {
|
|
2129
2760
|
COMMIT_THRESHOLD,
|
|
2130
2761
|
DEFAULT_OPENVIKING_ENDPOINT,
|
|
2762
|
+
ExtractionSection,
|
|
2131
2763
|
OpenVikingClient,
|
|
2132
2764
|
OpenVikingSettingsSection,
|
|
2133
2765
|
OpenVikingStatusChip,
|
|
2134
2766
|
OpenVikingStatusPopover,
|
|
2767
|
+
POLL_INTERVAL_ACTIVE_MS,
|
|
2768
|
+
POLL_INTERVAL_IDLE_MS,
|
|
2769
|
+
PROXY_OPENVIKING_ENDPOINT,
|
|
2770
|
+
TASKS_LIMIT_CAP,
|
|
2135
2771
|
THEME,
|
|
2772
|
+
WarningGlyph,
|
|
2136
2773
|
apply,
|
|
2137
2774
|
chatNodesToText,
|
|
2138
2775
|
checkHealth,
|
|
2139
2776
|
commitSession,
|
|
2777
|
+
computeBreakdown,
|
|
2140
2778
|
defaultOpenVikingClient,
|
|
2141
2779
|
fetchSession,
|
|
2780
|
+
formatBacklog,
|
|
2142
2781
|
formatDaemonVersion,
|
|
2782
|
+
formatDuration,
|
|
2143
2783
|
formatEndpoint,
|
|
2784
|
+
formatExtractionSummary,
|
|
2144
2785
|
formatMemoryLeafName,
|
|
2145
2786
|
formatPendingTokens,
|
|
2146
2787
|
formatRelativeTime,
|
|
2147
2788
|
formatStatusLabel,
|
|
2148
2789
|
formatTooltipTitle,
|
|
2149
2790
|
getCategoryBadgeStyle,
|
|
2791
|
+
getChipDotState,
|
|
2792
|
+
getDotColorForState,
|
|
2150
2793
|
getProgressBarColor,
|
|
2151
2794
|
getProgressBarPercent,
|
|
2152
2795
|
getSession,
|
|
@@ -2155,9 +2798,13 @@ export {
|
|
|
2155
2798
|
inferCategory,
|
|
2156
2799
|
inject,
|
|
2157
2800
|
name,
|
|
2801
|
+
normalizeExecutionEvent,
|
|
2802
|
+
normalizeExtractionTask,
|
|
2803
|
+
normalizeTaskList,
|
|
2158
2804
|
parseRecalledMemories,
|
|
2159
2805
|
resolveApiKey,
|
|
2160
2806
|
resolveEndpoint,
|
|
2807
|
+
seedRunningTask,
|
|
2161
2808
|
themeVar,
|
|
2162
2809
|
truncateSessionId
|
|
2163
2810
|
};
|