@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/README.md +1 -1
- package/lib/client.cjs +689 -12
- package/lib/client.cjs.map +1 -1
- package/lib/client.d.cts +242 -3
- package/lib/client.js +689 -12
- package/lib/client.js.map +1 -1
- package/lib/index.js +173 -1
- package/lib/index.js.map +1 -1
- package/package.json +1 -1
package/lib/client.js
CHANGED
|
@@ -16,6 +16,98 @@ 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 normalizeTimestamp(ts, isoFallback) {
|
|
21
|
+
if (typeof isoFallback === "string" && isoFallback.trim()) {
|
|
22
|
+
return isoFallback.trim();
|
|
23
|
+
}
|
|
24
|
+
if (typeof ts === "string" && ts.trim()) {
|
|
25
|
+
return ts.trim();
|
|
26
|
+
}
|
|
27
|
+
if (typeof ts === "number" && Number.isFinite(ts) && ts > 0) {
|
|
28
|
+
const ms = ts < 1e11 ? ts * 1e3 : ts;
|
|
29
|
+
return new Date(ms).toISOString();
|
|
30
|
+
}
|
|
31
|
+
return void 0;
|
|
32
|
+
}
|
|
33
|
+
function extractTaskList(data) {
|
|
34
|
+
if (!data || typeof data !== "object") return [];
|
|
35
|
+
if (Array.isArray(data)) return data;
|
|
36
|
+
const obj = data;
|
|
37
|
+
if (Array.isArray(obj.result)) return obj.result;
|
|
38
|
+
if (Array.isArray(obj.items)) return obj.items;
|
|
39
|
+
if (Array.isArray(obj.tasks)) return obj.tasks;
|
|
40
|
+
if (obj.result && typeof obj.result === "object") {
|
|
41
|
+
const res = obj.result;
|
|
42
|
+
if (Array.isArray(res.items)) return res.items;
|
|
43
|
+
if (Array.isArray(res.tasks)) return res.tasks;
|
|
44
|
+
}
|
|
45
|
+
return [];
|
|
46
|
+
}
|
|
47
|
+
function normalizeExtractionTask(raw) {
|
|
48
|
+
if (!raw || typeof raw !== "object") return null;
|
|
49
|
+
const taskId = typeof raw.task_id === "string" && raw.task_id || typeof raw.id === "string" && raw.id || "";
|
|
50
|
+
if (!taskId) return null;
|
|
51
|
+
const statusRaw = typeof raw.status === "string" ? raw.status : "";
|
|
52
|
+
const status = statusRaw === "running" || statusRaw === "pending" || statusRaw === "completed" || statusRaw === "failed" ? statusRaw : "pending";
|
|
53
|
+
const result = raw.result ?? {};
|
|
54
|
+
const extracted = result.memories_extracted ?? {};
|
|
55
|
+
const numberOf = (v) => typeof v === "number" && Number.isFinite(v) ? v : void 0;
|
|
56
|
+
const tokenUsageRaw = result.token_usage ?? raw.token_usage;
|
|
57
|
+
const tokenUsage = typeof tokenUsageRaw === "number" ? tokenUsageRaw : numberOf(
|
|
58
|
+
tokenUsageRaw?.total_tokens
|
|
59
|
+
);
|
|
60
|
+
const errorRaw = raw.error;
|
|
61
|
+
const errorMsg = typeof errorRaw === "string" ? errorRaw : typeof errorRaw?.message === "string" ? errorRaw.message : void 0;
|
|
62
|
+
return {
|
|
63
|
+
task_id: taskId,
|
|
64
|
+
status,
|
|
65
|
+
resource_id: typeof raw.resource_id === "string" ? raw.resource_id : void 0,
|
|
66
|
+
created_at: normalizeTimestamp(raw.created_at, raw.created_at_iso),
|
|
67
|
+
updated_at: normalizeTimestamp(raw.updated_at, raw.updated_at_iso),
|
|
68
|
+
memory_write: numberOf(extracted.memory_write ?? extracted.written),
|
|
69
|
+
memory_edit: numberOf(extracted.memory_edit ?? extracted.edited),
|
|
70
|
+
token_usage: tokenUsage,
|
|
71
|
+
error: errorMsg
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
function computeBreakdown(tasks) {
|
|
75
|
+
const b = {
|
|
76
|
+
running: 0,
|
|
77
|
+
pending: 0,
|
|
78
|
+
completed: 0,
|
|
79
|
+
failed: 0,
|
|
80
|
+
total: tasks.length,
|
|
81
|
+
firstRunning: null,
|
|
82
|
+
lastCompleted: null,
|
|
83
|
+
lastFailed: null
|
|
84
|
+
};
|
|
85
|
+
for (const t of tasks) {
|
|
86
|
+
if (t.status === "running") {
|
|
87
|
+
b.running += 1;
|
|
88
|
+
if (!b.firstRunning) b.firstRunning = t;
|
|
89
|
+
} else if (t.status === "pending") b.pending += 1;
|
|
90
|
+
else if (t.status === "completed") {
|
|
91
|
+
b.completed += 1;
|
|
92
|
+
if (!b.lastCompleted) b.lastCompleted = t;
|
|
93
|
+
} else if (t.status === "failed") {
|
|
94
|
+
b.failed += 1;
|
|
95
|
+
if (!b.lastFailed) b.lastFailed = t;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
return b;
|
|
99
|
+
}
|
|
100
|
+
function normalizeExecutionEvent(raw) {
|
|
101
|
+
return {
|
|
102
|
+
seq: typeof raw.seq === "number" ? raw.seq : void 0,
|
|
103
|
+
recorded_at: normalizeTimestamp(raw.recorded_at, raw.recorded_at_iso),
|
|
104
|
+
kind: typeof raw.kind === "string" ? raw.kind : void 0,
|
|
105
|
+
status: typeof raw.status === "string" ? raw.status : void 0,
|
|
106
|
+
stage: typeof raw.stage === "string" ? raw.stage : null,
|
|
107
|
+
operation: typeof raw.operation === "string" ? raw.operation : null,
|
|
108
|
+
error: typeof raw.error === "string" ? raw.error : null
|
|
109
|
+
};
|
|
110
|
+
}
|
|
19
111
|
var DEFAULT_OPENVIKING_ENDPOINT = "http://127.0.0.1:1933";
|
|
20
112
|
var PROXY_OPENVIKING_ENDPOINT = "/openviking-status/api";
|
|
21
113
|
function resolveEndpoint(endpoint) {
|
|
@@ -324,7 +416,9 @@ var OpenVikingClient = class {
|
|
|
324
416
|
const data = await res.json().catch(() => ({}));
|
|
325
417
|
return {
|
|
326
418
|
ok: data.ok === true,
|
|
327
|
-
error: typeof data.error === "string" ? data.error : void 0
|
|
419
|
+
error: typeof data.error === "string" ? data.error : void 0,
|
|
420
|
+
task_id: typeof data.task_id === "string" ? data.task_id : void 0,
|
|
421
|
+
resource_id: typeof data.resource_id === "string" ? data.resource_id : void 0
|
|
328
422
|
};
|
|
329
423
|
} catch (err) {
|
|
330
424
|
return {
|
|
@@ -356,7 +450,14 @@ var OpenVikingClient = class {
|
|
|
356
450
|
return { ok: false, error: String(errorMsg) };
|
|
357
451
|
}
|
|
358
452
|
this.resolvedSessionIds.set(sessionId.trim(), candidateId);
|
|
359
|
-
|
|
453
|
+
const okBody = await res.json().catch(() => ({}));
|
|
454
|
+
const container = okBody.result ?? okBody.data ?? okBody;
|
|
455
|
+
const taskId = container.task_id ?? container.id;
|
|
456
|
+
return {
|
|
457
|
+
ok: true,
|
|
458
|
+
task_id: typeof taskId === "string" && taskId.trim() ? taskId.trim() : void 0,
|
|
459
|
+
resource_id: candidateId
|
|
460
|
+
};
|
|
360
461
|
} catch (err) {
|
|
361
462
|
return {
|
|
362
463
|
ok: false,
|
|
@@ -366,7 +467,192 @@ var OpenVikingClient = class {
|
|
|
366
467
|
}
|
|
367
468
|
return { ok: false, error: lastError };
|
|
368
469
|
}
|
|
470
|
+
/**
|
|
471
|
+
* Список задач Phase 2 (Memory Extraction) текущей сессии со сводной
|
|
472
|
+
* разбивкой по статусам.
|
|
473
|
+
*
|
|
474
|
+
* Через прокси: один запрос `GET /tasks?session=<id>`, разбивка считается
|
|
475
|
+
* здесь. Напрямую: разрешаем `resource_id` через кандидатов и запрашиваем
|
|
476
|
+
* `GET /api/v1/tasks?resource_id=<id>&task_type=session_commit&limit=200`.
|
|
477
|
+
*/
|
|
478
|
+
async listTasks(sessionId) {
|
|
479
|
+
if (!sessionId || !sessionId.trim()) {
|
|
480
|
+
return { status: "missing" };
|
|
481
|
+
}
|
|
482
|
+
if (this.isProxy()) {
|
|
483
|
+
try {
|
|
484
|
+
const res = await fetch(
|
|
485
|
+
`${this.endpoint}/tasks?session=${encodeURIComponent(
|
|
486
|
+
sessionId.trim()
|
|
487
|
+
)}&limit=${TASKS_LIMIT_CAP}`,
|
|
488
|
+
{ method: "GET", headers: this.getHeaders() }
|
|
489
|
+
);
|
|
490
|
+
if (res.status === 401 || res.status === 403) {
|
|
491
|
+
return { status: "unauthorized" };
|
|
492
|
+
}
|
|
493
|
+
if (!res.ok) {
|
|
494
|
+
return { status: "error", detail: `HTTP ${res.status}` };
|
|
495
|
+
}
|
|
496
|
+
const data = await res.json();
|
|
497
|
+
if (data.status === "unauthorized") return { status: "unauthorized" };
|
|
498
|
+
if (data.status === "missing") return { status: "missing" };
|
|
499
|
+
if (data.status === "unreachable")
|
|
500
|
+
return {
|
|
501
|
+
status: "unreachable",
|
|
502
|
+
detail: typeof data.detail === "string" ? data.detail : void 0
|
|
503
|
+
};
|
|
504
|
+
if (data.status === "error")
|
|
505
|
+
return {
|
|
506
|
+
status: "error",
|
|
507
|
+
detail: typeof data.detail === "string" ? data.detail : void 0
|
|
508
|
+
};
|
|
509
|
+
const tasks = normalizeTaskList(extractTaskList(data.tasks ?? data));
|
|
510
|
+
return { status: "ok", breakdown: computeBreakdown(tasks), tasks };
|
|
511
|
+
} catch (err) {
|
|
512
|
+
return {
|
|
513
|
+
status: "unreachable",
|
|
514
|
+
detail: err instanceof Error ? err.message : String(err)
|
|
515
|
+
};
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
const candidates = this.getCandidateSessionIds(sessionId);
|
|
519
|
+
let resourceId = null;
|
|
520
|
+
for (const candidateId of candidates) {
|
|
521
|
+
try {
|
|
522
|
+
const probe = await fetch(
|
|
523
|
+
`${this.endpoint}/api/v1/sessions/${encodeURIComponent(candidateId)}`,
|
|
524
|
+
{ method: "GET", headers: this.getHeaders() }
|
|
525
|
+
);
|
|
526
|
+
if (probe.status === 404) continue;
|
|
527
|
+
if (probe.status === 401 || probe.status === 403) {
|
|
528
|
+
return { status: "unauthorized" };
|
|
529
|
+
}
|
|
530
|
+
if (probe.ok) {
|
|
531
|
+
resourceId = candidateId;
|
|
532
|
+
this.resolvedSessionIds.set(sessionId.trim(), candidateId);
|
|
533
|
+
break;
|
|
534
|
+
}
|
|
535
|
+
} catch (err) {
|
|
536
|
+
return {
|
|
537
|
+
status: "unreachable",
|
|
538
|
+
detail: err instanceof Error ? err.message : String(err)
|
|
539
|
+
};
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
if (!resourceId) return { status: "missing" };
|
|
543
|
+
try {
|
|
544
|
+
const query = new URLSearchParams({
|
|
545
|
+
resource_id: resourceId,
|
|
546
|
+
task_type: "session_commit",
|
|
547
|
+
limit: String(TASKS_LIMIT_CAP)
|
|
548
|
+
});
|
|
549
|
+
const res = await fetch(
|
|
550
|
+
`${this.endpoint}/api/v1/tasks?${query.toString()}`,
|
|
551
|
+
{ method: "GET", headers: this.getHeaders() }
|
|
552
|
+
);
|
|
553
|
+
if (res.status === 401 || res.status === 403) {
|
|
554
|
+
return { status: "unauthorized" };
|
|
555
|
+
}
|
|
556
|
+
if (!res.ok) {
|
|
557
|
+
return { status: "error", detail: `HTTP ${res.status}` };
|
|
558
|
+
}
|
|
559
|
+
const data = await res.json();
|
|
560
|
+
const tasks = normalizeTaskList(extractTaskList(data));
|
|
561
|
+
return { status: "ok", breakdown: computeBreakdown(tasks), tasks };
|
|
562
|
+
} catch (err) {
|
|
563
|
+
return {
|
|
564
|
+
status: "unreachable",
|
|
565
|
+
detail: err instanceof Error ? err.message : String(err)
|
|
566
|
+
};
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
/**
|
|
570
|
+
* Лениво загрузить одну задачу с лентой `execution_events` для «Show log».
|
|
571
|
+
*/
|
|
572
|
+
async fetchTaskEvents(taskId) {
|
|
573
|
+
if (!taskId || !taskId.trim()) {
|
|
574
|
+
return { status: "missing" };
|
|
575
|
+
}
|
|
576
|
+
const buildOk = (taskRaw) => {
|
|
577
|
+
const task = normalizeExtractionTask(taskRaw);
|
|
578
|
+
const eventsContainer = taskRaw.execution_events ?? {};
|
|
579
|
+
const rawEvents = eventsContainer.items ?? (Array.isArray(taskRaw.execution_events) ? taskRaw.execution_events : []);
|
|
580
|
+
const events = (Array.isArray(rawEvents) ? rawEvents : []).filter(
|
|
581
|
+
(e) => !!e && typeof e === "object"
|
|
582
|
+
).map(normalizeExecutionEvent);
|
|
583
|
+
if (!task) return { status: "error", detail: "malformed task" };
|
|
584
|
+
return { status: "ok", task, events };
|
|
585
|
+
};
|
|
586
|
+
if (this.isProxy()) {
|
|
587
|
+
try {
|
|
588
|
+
const res = await fetch(
|
|
589
|
+
`${this.endpoint}/task?id=${encodeURIComponent(
|
|
590
|
+
taskId.trim()
|
|
591
|
+
)}&events=1`,
|
|
592
|
+
{ method: "GET", headers: this.getHeaders() }
|
|
593
|
+
);
|
|
594
|
+
if (res.status === 401 || res.status === 403) {
|
|
595
|
+
return { status: "unauthorized" };
|
|
596
|
+
}
|
|
597
|
+
if (!res.ok) {
|
|
598
|
+
return { status: "error", detail: `HTTP ${res.status}` };
|
|
599
|
+
}
|
|
600
|
+
const data = await res.json();
|
|
601
|
+
if (data.status === "unauthorized") return { status: "unauthorized" };
|
|
602
|
+
if (data.status === "missing") return { status: "missing" };
|
|
603
|
+
if (data.status === "unreachable")
|
|
604
|
+
return {
|
|
605
|
+
status: "unreachable",
|
|
606
|
+
detail: typeof data.detail === "string" ? data.detail : void 0
|
|
607
|
+
};
|
|
608
|
+
if (data.status === "error")
|
|
609
|
+
return {
|
|
610
|
+
status: "error",
|
|
611
|
+
detail: typeof data.detail === "string" ? data.detail : void 0
|
|
612
|
+
};
|
|
613
|
+
return buildOk(data.task ?? {});
|
|
614
|
+
} catch (err) {
|
|
615
|
+
return {
|
|
616
|
+
status: "unreachable",
|
|
617
|
+
detail: err instanceof Error ? err.message : String(err)
|
|
618
|
+
};
|
|
619
|
+
}
|
|
620
|
+
}
|
|
621
|
+
try {
|
|
622
|
+
const res = await fetch(
|
|
623
|
+
`${this.endpoint}/api/v1/tasks/${encodeURIComponent(
|
|
624
|
+
taskId.trim()
|
|
625
|
+
)}?include_events=true`,
|
|
626
|
+
{ method: "GET", headers: this.getHeaders() }
|
|
627
|
+
);
|
|
628
|
+
if (res.status === 404) return { status: "missing" };
|
|
629
|
+
if (res.status === 401 || res.status === 403) {
|
|
630
|
+
return { status: "unauthorized" };
|
|
631
|
+
}
|
|
632
|
+
if (!res.ok) {
|
|
633
|
+
return { status: "error", detail: `HTTP ${res.status}` };
|
|
634
|
+
}
|
|
635
|
+
const data = await res.json();
|
|
636
|
+
const taskRaw = data?.result ?? data?.data ?? data;
|
|
637
|
+
return buildOk(taskRaw);
|
|
638
|
+
} catch (err) {
|
|
639
|
+
return {
|
|
640
|
+
status: "unreachable",
|
|
641
|
+
detail: err instanceof Error ? err.message : String(err)
|
|
642
|
+
};
|
|
643
|
+
}
|
|
644
|
+
}
|
|
369
645
|
};
|
|
646
|
+
function normalizeTaskList(raw) {
|
|
647
|
+
if (!Array.isArray(raw)) return [];
|
|
648
|
+
const tasks = [];
|
|
649
|
+
for (const entry of raw) {
|
|
650
|
+
if (!entry || typeof entry !== "object") continue;
|
|
651
|
+
const task = normalizeExtractionTask(entry);
|
|
652
|
+
if (task) tasks.push(task);
|
|
653
|
+
}
|
|
654
|
+
return tasks;
|
|
655
|
+
}
|
|
370
656
|
var defaultOpenVikingClient = new OpenVikingClient();
|
|
371
657
|
function checkHealth(endpoint, apiKey) {
|
|
372
658
|
const client = endpoint || apiKey ? new OpenVikingClient(endpoint, apiKey) : defaultOpenVikingClient;
|
|
@@ -740,6 +1026,39 @@ function dshIcon(name2) {
|
|
|
740
1026
|
return null;
|
|
741
1027
|
}
|
|
742
1028
|
}
|
|
1029
|
+
function formatDuration(startIso, endIso) {
|
|
1030
|
+
if (!startIso || !endIso) return void 0;
|
|
1031
|
+
const start = new Date(startIso).getTime();
|
|
1032
|
+
const end = new Date(endIso).getTime();
|
|
1033
|
+
if (isNaN(start) || isNaN(end) || end < start) return void 0;
|
|
1034
|
+
const ms = end - start;
|
|
1035
|
+
const sec = ms / 1e3;
|
|
1036
|
+
if (sec < 60) {
|
|
1037
|
+
return `${sec < 10 ? sec.toFixed(1) : Math.round(sec)}s`;
|
|
1038
|
+
}
|
|
1039
|
+
const min = Math.floor(sec / 60);
|
|
1040
|
+
const rem = Math.round(sec % 60);
|
|
1041
|
+
return `${min}m ${rem}s`;
|
|
1042
|
+
}
|
|
1043
|
+
function formatExtractionSummary(task, now = Date.now()) {
|
|
1044
|
+
const write = task.memory_write ?? 0;
|
|
1045
|
+
const edit = task.memory_edit ?? 0;
|
|
1046
|
+
const parts = [`${write} written, ${edit} edited`];
|
|
1047
|
+
const duration = formatDuration(task.created_at, task.updated_at);
|
|
1048
|
+
if (duration) parts.push(duration);
|
|
1049
|
+
const rel = formatRelativeTime(task.updated_at, now);
|
|
1050
|
+
if (rel) parts.push(rel);
|
|
1051
|
+
return parts.join(" \xB7 ");
|
|
1052
|
+
}
|
|
1053
|
+
function formatBacklog(breakdown) {
|
|
1054
|
+
if (!breakdown) return null;
|
|
1055
|
+
const { pending, failed } = breakdown;
|
|
1056
|
+
if (pending <= 0 && failed <= 0) return null;
|
|
1057
|
+
const parts = [];
|
|
1058
|
+
if (pending > 0) parts.push(`${pending} pending`);
|
|
1059
|
+
if (failed > 0) parts.push(`${failed} failed`);
|
|
1060
|
+
return parts.join(" / ");
|
|
1061
|
+
}
|
|
743
1062
|
function getProgressBarPercent(pendingTokens, threshold = COMMIT_THRESHOLD) {
|
|
744
1063
|
if (!threshold || threshold <= 0) return 0;
|
|
745
1064
|
const ratio = (pendingTokens || 0) / threshold;
|
|
@@ -806,6 +1125,229 @@ function handleEscapeKey(event, onClose) {
|
|
|
806
1125
|
}
|
|
807
1126
|
return false;
|
|
808
1127
|
}
|
|
1128
|
+
function ExtractionSection({
|
|
1129
|
+
breakdown,
|
|
1130
|
+
client
|
|
1131
|
+
}) {
|
|
1132
|
+
const [showLog, setShowLog] = useState(false);
|
|
1133
|
+
const [events, setEvents] = useState(null);
|
|
1134
|
+
const [logError, setLogError] = useState(null);
|
|
1135
|
+
const [loadingLog, setLoadingLog] = useState(false);
|
|
1136
|
+
if (!breakdown) return null;
|
|
1137
|
+
const isRunning = breakdown.running >= 1;
|
|
1138
|
+
const lastCompleted = breakdown.lastCompleted;
|
|
1139
|
+
const lastFailed = breakdown.lastFailed;
|
|
1140
|
+
const backlog = formatBacklog(breakdown);
|
|
1141
|
+
const failedActive = !isRunning && breakdown.failed >= 1;
|
|
1142
|
+
const logTaskId = (isRunning ? breakdown.firstRunning?.task_id : null) ?? (failedActive ? lastFailed?.task_id : null) ?? lastCompleted?.task_id ?? lastFailed?.task_id ?? null;
|
|
1143
|
+
const mutedStyle = { color: themeVar("labelTertiary") };
|
|
1144
|
+
const toggleLog = useCallback(async () => {
|
|
1145
|
+
const next = !showLog;
|
|
1146
|
+
setShowLog(next);
|
|
1147
|
+
if (next && events === null && logTaskId && client) {
|
|
1148
|
+
setLoadingLog(true);
|
|
1149
|
+
setLogError(null);
|
|
1150
|
+
const res = await client.fetchTaskEvents(logTaskId);
|
|
1151
|
+
setLoadingLog(false);
|
|
1152
|
+
if (res.status === "ok") {
|
|
1153
|
+
setEvents(res.events);
|
|
1154
|
+
} else {
|
|
1155
|
+
setLogError(
|
|
1156
|
+
res.status === "unauthorized" ? "No access to task log" : "Could not load log"
|
|
1157
|
+
);
|
|
1158
|
+
}
|
|
1159
|
+
}
|
|
1160
|
+
}, [showLog, events, logTaskId, client]);
|
|
1161
|
+
if (!isRunning && !failedActive && !lastCompleted && !backlog) {
|
|
1162
|
+
return null;
|
|
1163
|
+
}
|
|
1164
|
+
return /* @__PURE__ */ jsxs("div", { "data-testid": "extraction-section", style: { marginBottom: "12px" }, children: [
|
|
1165
|
+
/* @__PURE__ */ jsx(
|
|
1166
|
+
"div",
|
|
1167
|
+
{
|
|
1168
|
+
style: {
|
|
1169
|
+
marginBottom: "4px",
|
|
1170
|
+
color: themeVar("labelPrimary"),
|
|
1171
|
+
fontWeight: 500
|
|
1172
|
+
},
|
|
1173
|
+
children: "Memory Extraction"
|
|
1174
|
+
}
|
|
1175
|
+
),
|
|
1176
|
+
isRunning ? /* @__PURE__ */ jsxs("div", { children: [
|
|
1177
|
+
/* @__PURE__ */ jsxs(
|
|
1178
|
+
"div",
|
|
1179
|
+
{
|
|
1180
|
+
style: {
|
|
1181
|
+
display: "flex",
|
|
1182
|
+
alignItems: "center",
|
|
1183
|
+
gap: "6px",
|
|
1184
|
+
marginBottom: "4px"
|
|
1185
|
+
},
|
|
1186
|
+
children: [
|
|
1187
|
+
/* @__PURE__ */ jsx(
|
|
1188
|
+
"span",
|
|
1189
|
+
{
|
|
1190
|
+
"data-testid": "extraction-status-dot",
|
|
1191
|
+
"aria-hidden": "true",
|
|
1192
|
+
style: {
|
|
1193
|
+
width: "6px",
|
|
1194
|
+
height: "6px",
|
|
1195
|
+
borderRadius: "50%",
|
|
1196
|
+
background: themeVar("stateSuccess"),
|
|
1197
|
+
animation: "ov-pulse 1.2s ease-in-out infinite",
|
|
1198
|
+
flexShrink: 0
|
|
1199
|
+
}
|
|
1200
|
+
}
|
|
1201
|
+
),
|
|
1202
|
+
/* @__PURE__ */ jsx("span", { "data-testid": "extraction-running-label", children: "Extracting\u2026" })
|
|
1203
|
+
]
|
|
1204
|
+
}
|
|
1205
|
+
),
|
|
1206
|
+
/* @__PURE__ */ jsx(
|
|
1207
|
+
"div",
|
|
1208
|
+
{
|
|
1209
|
+
"data-testid": "extraction-indeterminate-track",
|
|
1210
|
+
style: {
|
|
1211
|
+
width: "100%",
|
|
1212
|
+
height: "6px",
|
|
1213
|
+
borderRadius: "3px",
|
|
1214
|
+
backgroundColor: themeVar("insetSurface"),
|
|
1215
|
+
overflow: "hidden",
|
|
1216
|
+
position: "relative"
|
|
1217
|
+
},
|
|
1218
|
+
children: /* @__PURE__ */ jsx(
|
|
1219
|
+
"div",
|
|
1220
|
+
{
|
|
1221
|
+
"data-testid": "extraction-indeterminate-fill",
|
|
1222
|
+
style: {
|
|
1223
|
+
position: "absolute",
|
|
1224
|
+
left: 0,
|
|
1225
|
+
top: 0,
|
|
1226
|
+
height: "100%",
|
|
1227
|
+
width: "40%",
|
|
1228
|
+
borderRadius: "3px",
|
|
1229
|
+
backgroundColor: themeVar("stateSuccess"),
|
|
1230
|
+
animation: "ov-indeterminate 1.2s ease-in-out infinite"
|
|
1231
|
+
}
|
|
1232
|
+
}
|
|
1233
|
+
)
|
|
1234
|
+
}
|
|
1235
|
+
)
|
|
1236
|
+
] }) : failedActive && lastFailed ? /* @__PURE__ */ jsxs(
|
|
1237
|
+
"div",
|
|
1238
|
+
{
|
|
1239
|
+
"data-testid": "extraction-failed-line",
|
|
1240
|
+
style: {
|
|
1241
|
+
display: "flex",
|
|
1242
|
+
alignItems: "center",
|
|
1243
|
+
gap: "6px",
|
|
1244
|
+
color: themeVar("stateWarning")
|
|
1245
|
+
},
|
|
1246
|
+
children: [
|
|
1247
|
+
/* @__PURE__ */ jsx(
|
|
1248
|
+
"span",
|
|
1249
|
+
{
|
|
1250
|
+
"aria-hidden": "true",
|
|
1251
|
+
style: { display: "inline-flex", flexShrink: 0 },
|
|
1252
|
+
children: /* @__PURE__ */ jsx(WarningGlyph, { size: 12, testId: "extraction-warning-glyph" })
|
|
1253
|
+
}
|
|
1254
|
+
),
|
|
1255
|
+
/* @__PURE__ */ jsx("span", { "data-testid": "extraction-failed-text", children: lastFailed.error || "extraction failed" })
|
|
1256
|
+
]
|
|
1257
|
+
}
|
|
1258
|
+
) : lastCompleted ? /* @__PURE__ */ jsxs(
|
|
1259
|
+
"div",
|
|
1260
|
+
{
|
|
1261
|
+
style: {
|
|
1262
|
+
display: "flex",
|
|
1263
|
+
alignItems: "center",
|
|
1264
|
+
gap: "6px"
|
|
1265
|
+
},
|
|
1266
|
+
children: [
|
|
1267
|
+
/* @__PURE__ */ jsx(
|
|
1268
|
+
"span",
|
|
1269
|
+
{
|
|
1270
|
+
"data-testid": "extraction-status-dot",
|
|
1271
|
+
"aria-hidden": "true",
|
|
1272
|
+
style: {
|
|
1273
|
+
width: "6px",
|
|
1274
|
+
height: "6px",
|
|
1275
|
+
borderRadius: "50%",
|
|
1276
|
+
background: themeVar("stateSuccess"),
|
|
1277
|
+
flexShrink: 0
|
|
1278
|
+
}
|
|
1279
|
+
}
|
|
1280
|
+
),
|
|
1281
|
+
/* @__PURE__ */ jsx("span", { "data-testid": "extraction-last-line", children: formatExtractionSummary(lastCompleted) })
|
|
1282
|
+
]
|
|
1283
|
+
}
|
|
1284
|
+
) : null,
|
|
1285
|
+
backlog && /* @__PURE__ */ jsx(
|
|
1286
|
+
"div",
|
|
1287
|
+
{
|
|
1288
|
+
"data-testid": "extraction-backlog-line",
|
|
1289
|
+
style: { ...mutedStyle, marginTop: "4px" },
|
|
1290
|
+
children: backlog
|
|
1291
|
+
}
|
|
1292
|
+
),
|
|
1293
|
+
logTaskId && client && /* @__PURE__ */ jsxs("div", { style: { marginTop: "6px" }, children: [
|
|
1294
|
+
/* @__PURE__ */ jsx(
|
|
1295
|
+
"button",
|
|
1296
|
+
{
|
|
1297
|
+
type: "button",
|
|
1298
|
+
"data-testid": "extraction-show-log-btn",
|
|
1299
|
+
onClick: () => void toggleLog(),
|
|
1300
|
+
style: {
|
|
1301
|
+
background: "none",
|
|
1302
|
+
border: "none",
|
|
1303
|
+
padding: 0,
|
|
1304
|
+
cursor: "pointer",
|
|
1305
|
+
font: "inherit",
|
|
1306
|
+
color: themeVar("labelTertiary"),
|
|
1307
|
+
textDecoration: "underline"
|
|
1308
|
+
},
|
|
1309
|
+
"aria-expanded": showLog,
|
|
1310
|
+
children: showLog ? "Hide log" : "Show log"
|
|
1311
|
+
}
|
|
1312
|
+
),
|
|
1313
|
+
showLog && /* @__PURE__ */ jsxs(
|
|
1314
|
+
"div",
|
|
1315
|
+
{
|
|
1316
|
+
"data-testid": "extraction-log",
|
|
1317
|
+
style: {
|
|
1318
|
+
marginTop: "6px",
|
|
1319
|
+
display: "flex",
|
|
1320
|
+
flexDirection: "column",
|
|
1321
|
+
gap: "2px",
|
|
1322
|
+
maxHeight: "120px",
|
|
1323
|
+
overflowY: "auto"
|
|
1324
|
+
},
|
|
1325
|
+
children: [
|
|
1326
|
+
loadingLog && /* @__PURE__ */ jsx("div", { "data-testid": "extraction-log-loading", style: mutedStyle, children: "Loading\u2026" }),
|
|
1327
|
+
logError && /* @__PURE__ */ jsx("div", { "data-testid": "extraction-log-error", style: mutedStyle, children: logError }),
|
|
1328
|
+
events && events.length === 0 && !loadingLog && !logError && /* @__PURE__ */ jsx("div", { "data-testid": "extraction-log-empty", style: mutedStyle, children: "No events" }),
|
|
1329
|
+
events?.map((ev, idx) => /* @__PURE__ */ jsxs(
|
|
1330
|
+
"div",
|
|
1331
|
+
{
|
|
1332
|
+
"data-testid": "extraction-log-event",
|
|
1333
|
+
style: {
|
|
1334
|
+
display: "flex",
|
|
1335
|
+
justifyContent: "space-between",
|
|
1336
|
+
gap: "8px"
|
|
1337
|
+
},
|
|
1338
|
+
children: [
|
|
1339
|
+
/* @__PURE__ */ jsx("span", { children: ev.status || ev.kind || "event" }),
|
|
1340
|
+
/* @__PURE__ */ jsx("span", { style: mutedStyle, children: formatRelativeTime(ev.recorded_at) || "" })
|
|
1341
|
+
]
|
|
1342
|
+
},
|
|
1343
|
+
`${ev.seq ?? idx}-${ev.recorded_at ?? idx}`
|
|
1344
|
+
))
|
|
1345
|
+
]
|
|
1346
|
+
}
|
|
1347
|
+
)
|
|
1348
|
+
] })
|
|
1349
|
+
] });
|
|
1350
|
+
}
|
|
809
1351
|
function OpenVikingStatusPopover({
|
|
810
1352
|
sessionId,
|
|
811
1353
|
health,
|
|
@@ -815,6 +1357,8 @@ function OpenVikingStatusPopover({
|
|
|
815
1357
|
endpoint,
|
|
816
1358
|
isCommitting = false,
|
|
817
1359
|
commitError = null,
|
|
1360
|
+
breakdown = null,
|
|
1361
|
+
client,
|
|
818
1362
|
onCommitNow,
|
|
819
1363
|
onClose,
|
|
820
1364
|
className,
|
|
@@ -895,7 +1439,7 @@ function OpenVikingStatusPopover({
|
|
|
895
1439
|
...style
|
|
896
1440
|
},
|
|
897
1441
|
children: [
|
|
898
|
-
/* @__PURE__ */ jsx("style", { children: `@keyframes ov-spin { from { transform: rotate(0deg); } to { transform: rotate(360deg); } }` }),
|
|
1442
|
+
/* @__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%; } }` }),
|
|
899
1443
|
/* @__PURE__ */ jsxs(
|
|
900
1444
|
"div",
|
|
901
1445
|
{
|
|
@@ -1178,6 +1722,7 @@ function OpenVikingStatusPopover({
|
|
|
1178
1722
|
}
|
|
1179
1723
|
)
|
|
1180
1724
|
] }),
|
|
1725
|
+
/* @__PURE__ */ jsx(ExtractionSection, { breakdown, client }),
|
|
1181
1726
|
commitError && /* @__PURE__ */ jsx(
|
|
1182
1727
|
"div",
|
|
1183
1728
|
{
|
|
@@ -1235,6 +1780,81 @@ function OpenVikingStatusPopover({
|
|
|
1235
1780
|
// src/client/OpenVikingStatusChip.tsx
|
|
1236
1781
|
import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
1237
1782
|
var COMMIT_THRESHOLD = 2e4;
|
|
1783
|
+
var POLL_INTERVAL_IDLE_MS = 15e3;
|
|
1784
|
+
var POLL_INTERVAL_ACTIVE_MS = 2500;
|
|
1785
|
+
function shouldPollActive(breakdown) {
|
|
1786
|
+
if (!breakdown) return false;
|
|
1787
|
+
return breakdown.running >= 1 || breakdown.pending >= 1;
|
|
1788
|
+
}
|
|
1789
|
+
function getChipDotState({
|
|
1790
|
+
isOnline,
|
|
1791
|
+
sessionUnreadable,
|
|
1792
|
+
breakdown
|
|
1793
|
+
}) {
|
|
1794
|
+
if (!isOnline) return "offline";
|
|
1795
|
+
if (sessionUnreadable) return "session-unreadable";
|
|
1796
|
+
if (breakdown && breakdown.running >= 1) return "busy";
|
|
1797
|
+
if (breakdown && breakdown.failed >= 1) return "extraction-failed";
|
|
1798
|
+
return "online-idle";
|
|
1799
|
+
}
|
|
1800
|
+
function WarningGlyph({
|
|
1801
|
+
size = 11,
|
|
1802
|
+
testId = "extraction-warning-glyph"
|
|
1803
|
+
}) {
|
|
1804
|
+
return /* @__PURE__ */ jsxs2(
|
|
1805
|
+
"svg",
|
|
1806
|
+
{
|
|
1807
|
+
"data-testid": testId,
|
|
1808
|
+
width: size,
|
|
1809
|
+
height: size,
|
|
1810
|
+
viewBox: "0 0 16 16",
|
|
1811
|
+
fill: "none",
|
|
1812
|
+
"aria-hidden": "true",
|
|
1813
|
+
style: { flexShrink: 0, display: "block" },
|
|
1814
|
+
children: [
|
|
1815
|
+
/* @__PURE__ */ jsx2("circle", { cx: "8", cy: "8", r: "6.5", stroke: "currentColor", strokeWidth: "1.5" }),
|
|
1816
|
+
/* @__PURE__ */ jsx2(
|
|
1817
|
+
"path",
|
|
1818
|
+
{
|
|
1819
|
+
d: "M8 5v3.5",
|
|
1820
|
+
stroke: "currentColor",
|
|
1821
|
+
strokeWidth: "1.5",
|
|
1822
|
+
strokeLinecap: "round"
|
|
1823
|
+
}
|
|
1824
|
+
),
|
|
1825
|
+
/* @__PURE__ */ jsx2("circle", { cx: "8", cy: "11", r: "0.9", fill: "currentColor" })
|
|
1826
|
+
]
|
|
1827
|
+
}
|
|
1828
|
+
);
|
|
1829
|
+
}
|
|
1830
|
+
function seedRunningTask(prev, taskId, resourceId) {
|
|
1831
|
+
const existing = prev && prev.status === "ok" ? prev.tasks : [];
|
|
1832
|
+
if (existing.some((t) => t.task_id === taskId)) {
|
|
1833
|
+
return prev;
|
|
1834
|
+
}
|
|
1835
|
+
const seeded = {
|
|
1836
|
+
task_id: taskId,
|
|
1837
|
+
status: "running",
|
|
1838
|
+
resource_id: resourceId,
|
|
1839
|
+
updated_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
1840
|
+
};
|
|
1841
|
+
const tasks = [seeded, ...existing];
|
|
1842
|
+
return { status: "ok", breakdown: computeBreakdown(tasks), tasks };
|
|
1843
|
+
}
|
|
1844
|
+
function getDotColorForState(state) {
|
|
1845
|
+
switch (state) {
|
|
1846
|
+
case "offline":
|
|
1847
|
+
return themeVar("stateError");
|
|
1848
|
+
case "session-unreadable":
|
|
1849
|
+
case "extraction-failed":
|
|
1850
|
+
return themeVar("stateWarning");
|
|
1851
|
+
case "busy":
|
|
1852
|
+
return themeVar("stateSuccess");
|
|
1853
|
+
case "online-idle":
|
|
1854
|
+
default:
|
|
1855
|
+
return themeVar("stateSuccess");
|
|
1856
|
+
}
|
|
1857
|
+
}
|
|
1238
1858
|
function formatPendingTokens(pendingTokens) {
|
|
1239
1859
|
const k = Math.round((pendingTokens || 0) / 1e3);
|
|
1240
1860
|
return `${k}k pend`;
|
|
@@ -1337,6 +1957,7 @@ function StatusChipView({
|
|
|
1337
1957
|
initialHealth,
|
|
1338
1958
|
initialSessionData,
|
|
1339
1959
|
initialSessionRead,
|
|
1960
|
+
initialTasksRead,
|
|
1340
1961
|
initialOpen = false
|
|
1341
1962
|
}) {
|
|
1342
1963
|
const [health, setHealth] = useState2(
|
|
@@ -1345,6 +1966,9 @@ function StatusChipView({
|
|
|
1345
1966
|
const [sessionRead, setSessionRead] = useState2(
|
|
1346
1967
|
initialSessionRead ?? (initialSessionData ? { status: "ok", session: initialSessionData } : null)
|
|
1347
1968
|
);
|
|
1969
|
+
const [tasksRead, setTasksRead] = useState2(
|
|
1970
|
+
initialTasksRead ?? null
|
|
1971
|
+
);
|
|
1348
1972
|
const [isOpen, setIsOpen] = useState2(initialOpen);
|
|
1349
1973
|
const [isCommitting, setIsCommitting] = useState2(false);
|
|
1350
1974
|
const [commitError, setCommitError] = useState2(null);
|
|
@@ -1380,16 +2004,24 @@ function StatusChipView({
|
|
|
1380
2004
|
if (!healthRes.ok) {
|
|
1381
2005
|
return;
|
|
1382
2006
|
}
|
|
1383
|
-
|
|
2007
|
+
const [session, tasks] = await Promise.all([
|
|
2008
|
+
apiClient.readSession(sessionId),
|
|
2009
|
+
apiClient.listTasks(sessionId)
|
|
2010
|
+
]);
|
|
2011
|
+
setSessionRead(session);
|
|
2012
|
+
setTasksRead(tasks);
|
|
1384
2013
|
} catch {
|
|
1385
2014
|
setHealth({ ok: false });
|
|
1386
2015
|
}
|
|
1387
2016
|
}, [sessionId, apiClient]);
|
|
2017
|
+
const breakdown = tasksRead?.status === "ok" ? tasksRead.breakdown : null;
|
|
2018
|
+
const hasActivePhase = shouldPollActive(breakdown);
|
|
1388
2019
|
useEffect2(() => {
|
|
1389
2020
|
fetchStatus();
|
|
1390
|
-
const
|
|
2021
|
+
const interval = hasActivePhase ? POLL_INTERVAL_ACTIVE_MS : POLL_INTERVAL_IDLE_MS;
|
|
2022
|
+
const timer = setInterval(fetchStatus, interval);
|
|
1391
2023
|
return () => clearInterval(timer);
|
|
1392
|
-
}, [fetchStatus]);
|
|
2024
|
+
}, [fetchStatus, hasActivePhase]);
|
|
1393
2025
|
useEffect2(() => {
|
|
1394
2026
|
function handleClickOutside(event) {
|
|
1395
2027
|
if (popoverRef.current && !popoverRef.current.contains(event.target)) {
|
|
@@ -1419,6 +2051,11 @@ function StatusChipView({
|
|
|
1419
2051
|
keep_recent_count: 10
|
|
1420
2052
|
});
|
|
1421
2053
|
if (res.ok) {
|
|
2054
|
+
if (res.task_id) {
|
|
2055
|
+
setTasksRead(
|
|
2056
|
+
(prev) => seedRunningTask(prev, res.task_id, res.resource_id)
|
|
2057
|
+
);
|
|
2058
|
+
}
|
|
1422
2059
|
await fetchStatus();
|
|
1423
2060
|
onCommit?.();
|
|
1424
2061
|
} else {
|
|
@@ -1437,11 +2074,15 @@ function StatusChipView({
|
|
|
1437
2074
|
const sessionUnreadable = isOnline && sessionRead !== null && sessionRead.status !== "ok";
|
|
1438
2075
|
const pendingTokens = sessionData?.pending_tokens ?? 0;
|
|
1439
2076
|
const recalledCount = recalledResult.recalledCount;
|
|
1440
|
-
const
|
|
2077
|
+
const rawDotState = getChipDotState({
|
|
1441
2078
|
isOnline,
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
);
|
|
2079
|
+
sessionUnreadable,
|
|
2080
|
+
breakdown
|
|
2081
|
+
});
|
|
2082
|
+
const dotState = isCommitting && (rawDotState === "online-idle" || rawDotState === "busy") ? "busy" : rawDotState;
|
|
2083
|
+
const dotBusy = dotState === "busy";
|
|
2084
|
+
const dotFailed = dotState === "extraction-failed";
|
|
2085
|
+
const statusColor = getDotColorForState(dotState);
|
|
1445
2086
|
const tooltipTitle = formatTooltipTitle({
|
|
1446
2087
|
isOnline,
|
|
1447
2088
|
isCommitting,
|
|
@@ -1458,6 +2099,7 @@ function StatusChipView({
|
|
|
1458
2099
|
style: { minWidth: 0, display: "inline-flex", position: "relative" },
|
|
1459
2100
|
ref: popoverRef,
|
|
1460
2101
|
children: [
|
|
2102
|
+
/* @__PURE__ */ jsx2("style", { children: `@keyframes ov-pulse { 0%, 100% { opacity: 1; transform: scale(1); } 50% { opacity: 0.35; transform: scale(0.72); } }` }),
|
|
1461
2103
|
/* @__PURE__ */ jsxs2(
|
|
1462
2104
|
"button",
|
|
1463
2105
|
{
|
|
@@ -1488,17 +2130,32 @@ function StatusChipView({
|
|
|
1488
2130
|
title: tooltipTitle,
|
|
1489
2131
|
"aria-label": tooltipTitle,
|
|
1490
2132
|
children: [
|
|
1491
|
-
/* @__PURE__ */ jsx2(
|
|
2133
|
+
dotFailed ? /* @__PURE__ */ jsx2(
|
|
1492
2134
|
"span",
|
|
1493
2135
|
{
|
|
1494
2136
|
"data-testid": "status-dot",
|
|
2137
|
+
"data-dot-state": dotState,
|
|
2138
|
+
"aria-hidden": "true",
|
|
2139
|
+
style: {
|
|
2140
|
+
display: "inline-flex",
|
|
2141
|
+
color: statusColor,
|
|
2142
|
+
flexShrink: 0
|
|
2143
|
+
},
|
|
2144
|
+
children: /* @__PURE__ */ jsx2(WarningGlyph, { size: 11, testId: "chip-warning-glyph" })
|
|
2145
|
+
}
|
|
2146
|
+
) : /* @__PURE__ */ jsx2(
|
|
2147
|
+
"span",
|
|
2148
|
+
{
|
|
2149
|
+
"data-testid": "status-dot",
|
|
2150
|
+
"data-dot-state": dotBusy ? "busy" : dotState,
|
|
1495
2151
|
"aria-hidden": "true",
|
|
1496
2152
|
style: {
|
|
1497
2153
|
width: "6px",
|
|
1498
2154
|
height: "6px",
|
|
1499
2155
|
borderRadius: "50%",
|
|
1500
2156
|
background: statusColor,
|
|
1501
|
-
flexShrink: 0
|
|
2157
|
+
flexShrink: 0,
|
|
2158
|
+
...dotBusy ? { animation: "ov-pulse 1.2s ease-in-out infinite" } : {}
|
|
1502
2159
|
}
|
|
1503
2160
|
}
|
|
1504
2161
|
),
|
|
@@ -1517,6 +2174,8 @@ function StatusChipView({
|
|
|
1517
2174
|
endpoint: apiClient.endpoint,
|
|
1518
2175
|
isCommitting,
|
|
1519
2176
|
commitError,
|
|
2177
|
+
breakdown,
|
|
2178
|
+
client: apiClient,
|
|
1520
2179
|
onCommitNow: handleCommitNow,
|
|
1521
2180
|
onClose: () => setIsOpen(false)
|
|
1522
2181
|
}
|
|
@@ -2130,26 +2789,38 @@ function apply(ctx) {
|
|
|
2130
2789
|
export {
|
|
2131
2790
|
COMMIT_THRESHOLD,
|
|
2132
2791
|
DEFAULT_OPENVIKING_ENDPOINT,
|
|
2792
|
+
ExtractionSection,
|
|
2133
2793
|
OpenVikingClient,
|
|
2134
2794
|
OpenVikingSettingsSection,
|
|
2135
2795
|
OpenVikingStatusChip,
|
|
2136
2796
|
OpenVikingStatusPopover,
|
|
2797
|
+
POLL_INTERVAL_ACTIVE_MS,
|
|
2798
|
+
POLL_INTERVAL_IDLE_MS,
|
|
2137
2799
|
PROXY_OPENVIKING_ENDPOINT,
|
|
2800
|
+
TASKS_LIMIT_CAP,
|
|
2138
2801
|
THEME,
|
|
2802
|
+
WarningGlyph,
|
|
2139
2803
|
apply,
|
|
2140
2804
|
chatNodesToText,
|
|
2141
2805
|
checkHealth,
|
|
2142
2806
|
commitSession,
|
|
2807
|
+
computeBreakdown,
|
|
2143
2808
|
defaultOpenVikingClient,
|
|
2809
|
+
extractTaskList,
|
|
2144
2810
|
fetchSession,
|
|
2811
|
+
formatBacklog,
|
|
2145
2812
|
formatDaemonVersion,
|
|
2813
|
+
formatDuration,
|
|
2146
2814
|
formatEndpoint,
|
|
2815
|
+
formatExtractionSummary,
|
|
2147
2816
|
formatMemoryLeafName,
|
|
2148
2817
|
formatPendingTokens,
|
|
2149
2818
|
formatRelativeTime,
|
|
2150
2819
|
formatStatusLabel,
|
|
2151
2820
|
formatTooltipTitle,
|
|
2152
2821
|
getCategoryBadgeStyle,
|
|
2822
|
+
getChipDotState,
|
|
2823
|
+
getDotColorForState,
|
|
2153
2824
|
getProgressBarColor,
|
|
2154
2825
|
getProgressBarPercent,
|
|
2155
2826
|
getSession,
|
|
@@ -2158,9 +2829,15 @@ export {
|
|
|
2158
2829
|
inferCategory,
|
|
2159
2830
|
inject,
|
|
2160
2831
|
name,
|
|
2832
|
+
normalizeExecutionEvent,
|
|
2833
|
+
normalizeExtractionTask,
|
|
2834
|
+
normalizeTaskList,
|
|
2835
|
+
normalizeTimestamp,
|
|
2161
2836
|
parseRecalledMemories,
|
|
2162
2837
|
resolveApiKey,
|
|
2163
2838
|
resolveEndpoint,
|
|
2839
|
+
seedRunningTask,
|
|
2840
|
+
shouldPollActive,
|
|
2164
2841
|
themeVar,
|
|
2165
2842
|
truncateSessionId
|
|
2166
2843
|
};
|