doc2vec 2.11.0 → 2.12.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/dist/controller/chunk-inspector.js +209 -0
- package/dist/controller/server.js +29 -0
- package/dist/database.js +64 -19
- package/dist/doc2vec.js +84 -19
- package/dist/types.js +12 -0
- package/dist/ui/assets/index-CZSZsL3G.css +1 -0
- package/dist/ui/assets/{index-D-QOw3rk.js → index-vglJgkwy.js} +78 -78
- package/dist/ui/index.html +2 -2
- package/package.json +1 -1
- package/dist/ui/assets/index-BVg6n7Si.css +0 -1
package/dist/doc2vec.js
CHANGED
|
@@ -53,6 +53,7 @@ const logger_1 = require("./logger");
|
|
|
53
53
|
const utils_1 = require("./utils");
|
|
54
54
|
const database_1 = require("./database");
|
|
55
55
|
const content_processor_1 = require("./content-processor");
|
|
56
|
+
const types_1 = require("./types");
|
|
56
57
|
const client_s3_1 = require("@aws-sdk/client-s3");
|
|
57
58
|
const markdown_store_1 = require("./markdown-store");
|
|
58
59
|
const GITHUB_TOKEN = process.env.GITHUB_PERSONAL_ACCESS_TOKEN;
|
|
@@ -61,6 +62,9 @@ dotenv.config();
|
|
|
61
62
|
class Doc2Vec {
|
|
62
63
|
constructor(configPath) {
|
|
63
64
|
this.brokenLinksByWebsite = {};
|
|
65
|
+
// Change counters for the source currently being processed by run().
|
|
66
|
+
// Sources are processed sequentially, so a single slot is sufficient.
|
|
67
|
+
this.counters = (0, types_1.newSourceRunCounters)('items');
|
|
64
68
|
this.logger = new logger_1.Logger('Doc2Vec', {
|
|
65
69
|
level: logger_1.LogLevel.DEBUG,
|
|
66
70
|
useTimestamp: true,
|
|
@@ -183,6 +187,15 @@ class Doc2Vec {
|
|
|
183
187
|
const startTime = Date.now();
|
|
184
188
|
let ok = true;
|
|
185
189
|
let errorMessage;
|
|
190
|
+
const itemsKindByType = {
|
|
191
|
+
website: 'pages',
|
|
192
|
+
github: 'issues',
|
|
193
|
+
local_directory: 'files',
|
|
194
|
+
code: 'files',
|
|
195
|
+
s3: 'objects',
|
|
196
|
+
zendesk: 'items',
|
|
197
|
+
};
|
|
198
|
+
this.counters = (0, types_1.newSourceRunCounters)(itemsKindByType[sourceConfig.type] ?? 'items');
|
|
186
199
|
try {
|
|
187
200
|
if (sourceConfig.type === 'github') {
|
|
188
201
|
await this.processGithubRepo(sourceConfig, sourceLogger);
|
|
@@ -219,7 +232,8 @@ class Doc2Vec {
|
|
|
219
232
|
version: sourceConfig.version,
|
|
220
233
|
duration_ms: Date.now() - startTime,
|
|
221
234
|
ok,
|
|
222
|
-
...(errorMessage && { error: errorMessage })
|
|
235
|
+
...(errorMessage && { error: errorMessage }),
|
|
236
|
+
counters: this.counters
|
|
223
237
|
});
|
|
224
238
|
}
|
|
225
239
|
// Close the Postgres markdown store connection pool
|
|
@@ -380,11 +394,19 @@ class Doc2Vec {
|
|
|
380
394
|
// ones would otherwise linger — leaving stale state ("open") and missing
|
|
381
395
|
// the latest comments in search results. All chunks for an issue share
|
|
382
396
|
// its unique url, so delete-by-url reconciles them exactly.
|
|
397
|
+
let removedChunks = 0;
|
|
383
398
|
if (dbConnection.type === 'sqlite') {
|
|
384
|
-
database_1.DatabaseManager.removeChunksByUrlSQLite(dbConnection.db, url, logger);
|
|
399
|
+
removedChunks = database_1.DatabaseManager.removeChunksByUrlSQLite(dbConnection.db, url, logger);
|
|
385
400
|
}
|
|
386
401
|
else if (dbConnection.type === 'qdrant') {
|
|
387
|
-
await database_1.DatabaseManager.removeChunksByUrlQdrant(dbConnection, url, logger);
|
|
402
|
+
removedChunks = await database_1.DatabaseManager.removeChunksByUrlQdrant(dbConnection, url, logger);
|
|
403
|
+
}
|
|
404
|
+
if (removedChunks > 0) {
|
|
405
|
+
this.counters.items_updated++;
|
|
406
|
+
this.counters.chunks_deleted += removedChunks;
|
|
407
|
+
}
|
|
408
|
+
else {
|
|
409
|
+
this.counters.items_new++;
|
|
388
410
|
}
|
|
389
411
|
// Process and store each chunk immediately
|
|
390
412
|
for (const chunk of chunks) {
|
|
@@ -400,6 +422,7 @@ class Doc2Vec {
|
|
|
400
422
|
const embeddings = await this.createEmbeddings([chunk.content]);
|
|
401
423
|
if (embeddings.length) {
|
|
402
424
|
database_1.DatabaseManager.insertVectorsSQLite(dbConnection.db, chunk, embeddings[0], logger, chunkHash);
|
|
425
|
+
this.counters.chunks_added++;
|
|
403
426
|
logger.debug(`Stored chunk ${chunkId} in SQLite`);
|
|
404
427
|
}
|
|
405
428
|
else {
|
|
@@ -430,6 +453,7 @@ class Doc2Vec {
|
|
|
430
453
|
const embeddings = await this.createEmbeddings([chunk.content]);
|
|
431
454
|
if (embeddings.length) {
|
|
432
455
|
await database_1.DatabaseManager.storeChunkInQdrant(dbConnection, chunk, embeddings[0], chunkHash);
|
|
456
|
+
this.counters.chunks_added++;
|
|
433
457
|
logger.debug(`Stored chunk ${chunkId} in Qdrant (${dbConnection.collectionName})`);
|
|
434
458
|
}
|
|
435
459
|
else {
|
|
@@ -579,11 +603,16 @@ class Doc2Vec {
|
|
|
579
603
|
}
|
|
580
604
|
// Vector DB chunks
|
|
581
605
|
try {
|
|
606
|
+
let removedChunks = 0;
|
|
582
607
|
if (dbConnection.type === 'sqlite') {
|
|
583
|
-
database_1.DatabaseManager.removeChunksByUrlSQLite(dbConnection.db, url, logger);
|
|
608
|
+
removedChunks = database_1.DatabaseManager.removeChunksByUrlSQLite(dbConnection.db, url, logger);
|
|
584
609
|
}
|
|
585
610
|
else if (dbConnection.type === 'qdrant') {
|
|
586
|
-
await database_1.DatabaseManager.removeChunksByUrlQdrant(dbConnection, url, logger);
|
|
611
|
+
removedChunks = await database_1.DatabaseManager.removeChunksByUrlQdrant(dbConnection, url, logger);
|
|
612
|
+
}
|
|
613
|
+
if (removedChunks > 0) {
|
|
614
|
+
this.counters.items_deleted++;
|
|
615
|
+
this.counters.chunks_deleted += removedChunks;
|
|
587
616
|
}
|
|
588
617
|
}
|
|
589
618
|
catch (dbError) {
|
|
@@ -603,14 +632,17 @@ class Doc2Vec {
|
|
|
603
632
|
await database_1.DatabaseManager.setMetadataValue(dbConnection, syncCompleteKey, 'true', logger, this.embeddingDimension);
|
|
604
633
|
logger.info('Full sync completed successfully — subsequent runs will use normal caching');
|
|
605
634
|
}
|
|
635
|
+
let removed = { items: 0, chunks: 0 };
|
|
606
636
|
if (dbConnection.type === 'sqlite') {
|
|
607
637
|
logger.info(`Running SQLite cleanup for ${urlPrefix}`);
|
|
608
|
-
database_1.DatabaseManager.removeObsoleteChunksSQLite(dbConnection.db, visitedUrls, urlPrefix, logger);
|
|
638
|
+
removed = database_1.DatabaseManager.removeObsoleteChunksSQLite(dbConnection.db, visitedUrls, urlPrefix, logger);
|
|
609
639
|
}
|
|
610
640
|
else if (dbConnection.type === 'qdrant') {
|
|
611
641
|
logger.info(`Running Qdrant cleanup for ${urlPrefix} in collection ${dbConnection.collectionName}`);
|
|
612
|
-
await database_1.DatabaseManager.removeObsoleteChunksQdrant(dbConnection, visitedUrls, urlPrefix, logger);
|
|
642
|
+
removed = await database_1.DatabaseManager.removeObsoleteChunksQdrant(dbConnection, visitedUrls, urlPrefix, logger);
|
|
613
643
|
}
|
|
644
|
+
this.counters.items_deleted += removed.items;
|
|
645
|
+
this.counters.chunks_deleted += removed.chunks;
|
|
614
646
|
}
|
|
615
647
|
logger.info(`Finished processing website: ${config.url}`);
|
|
616
648
|
}
|
|
@@ -698,14 +730,17 @@ class Doc2Vec {
|
|
|
698
730
|
}
|
|
699
731
|
}, logger);
|
|
700
732
|
logger.section('CLEANUP');
|
|
733
|
+
let removed = { items: 0, chunks: 0 };
|
|
701
734
|
if (dbConnection.type === 'sqlite') {
|
|
702
735
|
logger.info(`Running SQLite cleanup for local directory ${config.path}`);
|
|
703
|
-
database_1.DatabaseManager.removeObsoleteFilesSQLite(dbConnection.db, processedFiles, config, logger);
|
|
736
|
+
removed = database_1.DatabaseManager.removeObsoleteFilesSQLite(dbConnection.db, processedFiles, config, logger);
|
|
704
737
|
}
|
|
705
738
|
else if (dbConnection.type === 'qdrant') {
|
|
706
739
|
logger.info(`Running Qdrant cleanup for local directory ${config.path} in collection ${dbConnection.collectionName}`);
|
|
707
|
-
await database_1.DatabaseManager.removeObsoleteFilesQdrant(dbConnection, processedFiles, config, logger);
|
|
740
|
+
removed = await database_1.DatabaseManager.removeObsoleteFilesQdrant(dbConnection, processedFiles, config, logger);
|
|
708
741
|
}
|
|
742
|
+
this.counters.items_deleted += removed.items;
|
|
743
|
+
this.counters.chunks_deleted += removed.chunks;
|
|
709
744
|
logger.info(`Finished processing local directory: ${config.path}`);
|
|
710
745
|
}
|
|
711
746
|
async processS3(config, parentLogger) {
|
|
@@ -886,11 +921,16 @@ class Doc2Vec {
|
|
|
886
921
|
else {
|
|
887
922
|
fileUrl = `s3://${config.bucket}/${deletedKey}`;
|
|
888
923
|
}
|
|
924
|
+
let removedChunks = 0;
|
|
889
925
|
if (dbConnection.type === 'sqlite') {
|
|
890
|
-
database_1.DatabaseManager.removeChunksByUrlSQLite(dbConnection.db, fileUrl, logger);
|
|
926
|
+
removedChunks = database_1.DatabaseManager.removeChunksByUrlSQLite(dbConnection.db, fileUrl, logger);
|
|
891
927
|
}
|
|
892
928
|
else if (dbConnection.type === 'qdrant') {
|
|
893
|
-
await database_1.DatabaseManager.removeChunksByUrlQdrant(dbConnection, fileUrl, logger);
|
|
929
|
+
removedChunks = await database_1.DatabaseManager.removeChunksByUrlQdrant(dbConnection, fileUrl, logger);
|
|
930
|
+
}
|
|
931
|
+
if (removedChunks > 0) {
|
|
932
|
+
this.counters.items_deleted++;
|
|
933
|
+
this.counters.chunks_deleted += removedChunks;
|
|
894
934
|
}
|
|
895
935
|
}
|
|
896
936
|
}
|
|
@@ -1025,11 +1065,16 @@ class Doc2Vec {
|
|
|
1025
1065
|
if (deleteUrls.length > 0) {
|
|
1026
1066
|
logger.info(`Cleaning up ${deleteUrls.length} deleted/renamed files`);
|
|
1027
1067
|
for (const url of deleteUrls) {
|
|
1068
|
+
let removedChunks = 0;
|
|
1028
1069
|
if (dbConnection.type === 'sqlite') {
|
|
1029
|
-
database_1.DatabaseManager.removeChunksByUrlSQLite(dbConnection.db, url, logger);
|
|
1070
|
+
removedChunks = database_1.DatabaseManager.removeChunksByUrlSQLite(dbConnection.db, url, logger);
|
|
1030
1071
|
}
|
|
1031
1072
|
else if (dbConnection.type === 'qdrant') {
|
|
1032
|
-
await database_1.DatabaseManager.removeChunksByUrlQdrant(dbConnection, url, logger);
|
|
1073
|
+
removedChunks = await database_1.DatabaseManager.removeChunksByUrlQdrant(dbConnection, url, logger);
|
|
1074
|
+
}
|
|
1075
|
+
if (removedChunks > 0) {
|
|
1076
|
+
this.counters.items_deleted++;
|
|
1077
|
+
this.counters.chunks_deleted += removedChunks;
|
|
1033
1078
|
}
|
|
1034
1079
|
}
|
|
1035
1080
|
}
|
|
@@ -1043,11 +1088,16 @@ class Doc2Vec {
|
|
|
1043
1088
|
const deletedFiles = previousList.filter((filePath) => !trackedFiles?.has(filePath));
|
|
1044
1089
|
for (const deletedFile of deletedFiles) {
|
|
1045
1090
|
const url = this.buildCodeFileUrl(deletedFile, basePath, config, repoUrlPrefix);
|
|
1091
|
+
let removedChunks = 0;
|
|
1046
1092
|
if (dbConnection.type === 'sqlite') {
|
|
1047
|
-
database_1.DatabaseManager.removeChunksByUrlSQLite(dbConnection.db, url, logger);
|
|
1093
|
+
removedChunks = database_1.DatabaseManager.removeChunksByUrlSQLite(dbConnection.db, url, logger);
|
|
1048
1094
|
}
|
|
1049
1095
|
else if (dbConnection.type === 'qdrant') {
|
|
1050
|
-
await database_1.DatabaseManager.removeChunksByUrlQdrant(dbConnection, url, logger);
|
|
1096
|
+
removedChunks = await database_1.DatabaseManager.removeChunksByUrlQdrant(dbConnection, url, logger);
|
|
1097
|
+
}
|
|
1098
|
+
if (removedChunks > 0) {
|
|
1099
|
+
this.counters.items_deleted++;
|
|
1100
|
+
this.counters.chunks_deleted += removedChunks;
|
|
1051
1101
|
}
|
|
1052
1102
|
}
|
|
1053
1103
|
await database_1.DatabaseManager.setMetadataValue(dbConnection, fileListKey, JSON.stringify(currentList), logger, this.embeddingDimension);
|
|
@@ -1058,14 +1108,17 @@ class Doc2Vec {
|
|
|
1058
1108
|
}
|
|
1059
1109
|
}
|
|
1060
1110
|
else {
|
|
1111
|
+
let removed = { items: 0, chunks: 0 };
|
|
1061
1112
|
if (dbConnection.type === 'sqlite') {
|
|
1062
1113
|
logger.info(`Running SQLite cleanup for code source ${basePath}`);
|
|
1063
|
-
database_1.DatabaseManager.removeObsoleteFilesSQLite(dbConnection.db, processedFiles, cleanupPathConfig, logger);
|
|
1114
|
+
removed = database_1.DatabaseManager.removeObsoleteFilesSQLite(dbConnection.db, processedFiles, cleanupPathConfig, logger);
|
|
1064
1115
|
}
|
|
1065
1116
|
else if (dbConnection.type === 'qdrant') {
|
|
1066
1117
|
logger.info(`Running Qdrant cleanup for code source ${basePath} in collection ${dbConnection.collectionName}`);
|
|
1067
|
-
await database_1.DatabaseManager.removeObsoleteFilesQdrant(dbConnection, processedFiles, cleanupPathConfig, logger);
|
|
1118
|
+
removed = await database_1.DatabaseManager.removeObsoleteFilesQdrant(dbConnection, processedFiles, cleanupPathConfig, logger);
|
|
1068
1119
|
}
|
|
1120
|
+
this.counters.items_deleted += removed.items;
|
|
1121
|
+
this.counters.chunks_deleted += removed.chunks;
|
|
1069
1122
|
}
|
|
1070
1123
|
if (config.source === 'github' && basePath && repoBranch) {
|
|
1071
1124
|
const headSha = await this.getRepoHeadSha(basePath, logger);
|
|
@@ -1333,11 +1386,16 @@ class Doc2Vec {
|
|
|
1333
1386
|
// Deleted tickets — remove their chunks and stop
|
|
1334
1387
|
if (ticket.status === 'deleted') {
|
|
1335
1388
|
logger.info(`Ticket #${ticketId} was deleted in Zendesk — removing its chunks`);
|
|
1389
|
+
let removedChunks = 0;
|
|
1336
1390
|
if (dbConnection.type === 'sqlite') {
|
|
1337
|
-
database_1.DatabaseManager.removeChunksByUrlSQLite(dbConnection.db, url, logger);
|
|
1391
|
+
removedChunks = database_1.DatabaseManager.removeChunksByUrlSQLite(dbConnection.db, url, logger);
|
|
1338
1392
|
}
|
|
1339
1393
|
else {
|
|
1340
|
-
await database_1.DatabaseManager.removeChunksByUrlQdrant(dbConnection, url, logger);
|
|
1394
|
+
removedChunks = await database_1.DatabaseManager.removeChunksByUrlQdrant(dbConnection, url, logger);
|
|
1395
|
+
}
|
|
1396
|
+
if (removedChunks > 0) {
|
|
1397
|
+
this.counters.items_deleted++;
|
|
1398
|
+
this.counters.chunks_deleted += removedChunks;
|
|
1341
1399
|
}
|
|
1342
1400
|
return;
|
|
1343
1401
|
}
|
|
@@ -1599,6 +1657,7 @@ class Doc2Vec {
|
|
|
1599
1657
|
newHashesSorted.every((h, i) => h === existingHashesSorted[i]);
|
|
1600
1658
|
if (unchanged) {
|
|
1601
1659
|
logger.info(`Skipping unchanged URL (${chunks.length} chunks): ${url}`);
|
|
1660
|
+
this.counters.items_unchanged++;
|
|
1602
1661
|
return 0;
|
|
1603
1662
|
}
|
|
1604
1663
|
// 4. Content changed — delete all existing chunks for this URL
|
|
@@ -1610,6 +1669,11 @@ class Doc2Vec {
|
|
|
1610
1669
|
else {
|
|
1611
1670
|
await database_1.DatabaseManager.removeChunksByUrlQdrant(dbConnection, url, logger);
|
|
1612
1671
|
}
|
|
1672
|
+
this.counters.items_updated++;
|
|
1673
|
+
this.counters.chunks_deleted += existingHashesSorted.length;
|
|
1674
|
+
}
|
|
1675
|
+
else {
|
|
1676
|
+
this.counters.items_new++;
|
|
1613
1677
|
}
|
|
1614
1678
|
// 5. Embed and insert all new chunks
|
|
1615
1679
|
let embeddedCount = 0;
|
|
@@ -1637,6 +1701,7 @@ class Doc2Vec {
|
|
|
1637
1701
|
}
|
|
1638
1702
|
}
|
|
1639
1703
|
chunkProgress.complete();
|
|
1704
|
+
this.counters.chunks_added += embeddedCount;
|
|
1640
1705
|
return embeddedCount;
|
|
1641
1706
|
}
|
|
1642
1707
|
async createEmbeddings(texts) {
|
package/dist/types.js
CHANGED
|
@@ -1,2 +1,14 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.newSourceRunCounters = newSourceRunCounters;
|
|
4
|
+
function newSourceRunCounters(itemsKind) {
|
|
5
|
+
return {
|
|
6
|
+
items_kind: itemsKind,
|
|
7
|
+
items_new: 0,
|
|
8
|
+
items_updated: 0,
|
|
9
|
+
items_unchanged: 0,
|
|
10
|
+
items_deleted: 0,
|
|
11
|
+
chunks_added: 0,
|
|
12
|
+
chunks_deleted: 0,
|
|
13
|
+
};
|
|
14
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-space-y-reverse:0;--tw-border-style:solid;--tw-leading:initial;--tw-font-weight:initial;--tw-tracking:initial;--tw-ordinal:initial;--tw-slashed-zero:initial;--tw-numeric-figure:initial;--tw-numeric-spacing:initial;--tw-numeric-fraction:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000}}}@layer theme{:root,:host{--font-mono:ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;--color-white:#fff;--spacing:.25rem;--container-xs:20rem;--container-md:28rem;--container-2xl:42rem;--container-6xl:72rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--text-lg:1.125rem;--text-lg--line-height:calc(1.75 / 1.125);--text-xl:1.25rem;--text-xl--line-height:calc(1.75 / 1.25);--text-2xl:1.5rem;--text-2xl--line-height:calc(2 / 1.5);--font-weight-normal:400;--font-weight-medium:500;--font-weight-semibold:600;--tracking-tight:-.025em;--tracking-wide:.025em;--radius-md:.375rem;--radius-lg:.5rem;--animate-pulse:pulse 2s cubic-bezier(.4, 0, .6, 1) infinite;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1);--default-font-family:system-ui, -apple-system, "Segoe UI", sans-serif;--default-mono-font-family:var(--font-mono)}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab,red,red)){::placeholder{color:color-mix(in oklab,currentcolor 50%,transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}}@layer components;@layer utilities{.mx-auto{margin-inline:auto}.mt-0\.5{margin-top:calc(var(--spacing) * .5)}.mt-1{margin-top:var(--spacing)}.mt-1\.5{margin-top:calc(var(--spacing) * 1.5)}.mt-2{margin-top:calc(var(--spacing) * 2)}.mt-3{margin-top:calc(var(--spacing) * 3)}.mt-4{margin-top:calc(var(--spacing) * 4)}.-mb-px{margin-bottom:-1px}.mb-1{margin-bottom:var(--spacing)}.mb-2{margin-bottom:calc(var(--spacing) * 2)}.mb-3{margin-bottom:calc(var(--spacing) * 3)}.mb-4{margin-bottom:calc(var(--spacing) * 4)}.ml-1{margin-left:var(--spacing)}.ml-2{margin-left:calc(var(--spacing) * 2)}.ml-auto{margin-left:auto}.block{display:block}.flex{display:flex}.grid{display:grid}.hidden{display:none}.inline-block{display:inline-block}.inline-flex{display:inline-flex}.h-2{height:calc(var(--spacing) * 2)}.h-4{height:calc(var(--spacing) * 4)}.max-h-96{max-height:calc(var(--spacing) * 96)}.max-h-\[560px\]{max-height:560px}.min-h-screen{min-height:100vh}.w-2{width:calc(var(--spacing) * 2)}.w-4{width:calc(var(--spacing) * 4)}.w-10{width:calc(var(--spacing) * 10)}.w-44{width:calc(var(--spacing) * 44)}.w-72{width:calc(var(--spacing) * 72)}.w-full{width:100%}.max-w-2xl{max-width:var(--container-2xl)}.max-w-6xl{max-width:var(--container-6xl)}.max-w-md{max-width:var(--container-md)}.max-w-xs{max-width:var(--container-xs)}.min-w-48{min-width:calc(var(--spacing) * 48)}.flex-1{flex:1}.shrink-0{flex-shrink:0}.animate-pulse{animation:var(--animate-pulse)}.cursor-pointer{cursor:pointer}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.flex-wrap{flex-wrap:wrap}.items-baseline{align-items:baseline}.items-center{align-items:center}.items-start{align-items:flex-start}.justify-between{justify-content:space-between}.gap-1{gap:var(--spacing)}.gap-1\.5{gap:calc(var(--spacing) * 1.5)}.gap-2{gap:calc(var(--spacing) * 2)}.gap-3{gap:calc(var(--spacing) * 3)}.gap-4{gap:calc(var(--spacing) * 4)}.gap-6{gap:calc(var(--spacing) * 6)}:where(.space-y-2>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 2) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 2) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-3>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 3) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 3) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-4>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 4) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 4) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-6>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 6) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 6) * calc(1 - var(--tw-space-y-reverse)))}.gap-x-4{column-gap:calc(var(--spacing) * 4)}.gap-x-6{column-gap:calc(var(--spacing) * 6)}.gap-x-8{column-gap:calc(var(--spacing) * 8)}.gap-y-1{row-gap:var(--spacing)}.gap-y-2{row-gap:calc(var(--spacing) * 2)}.gap-y-3{row-gap:calc(var(--spacing) * 3)}.self-center{align-self:center}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.rounded{border-radius:.25rem}.rounded-full{border-radius:3.40282e38px}.rounded-lg{border-radius:var(--radius-lg)}.rounded-md{border-radius:var(--radius-md)}.border{border-style:var(--tw-border-style);border-width:1px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-b-2{border-bottom-style:var(--tw-border-style);border-bottom-width:2px}.border-dashed{--tw-border-style:dashed;border-style:dashed}.border-accent,.border-accent\/30{border-color:var(--accent)}@supports (color:color-mix(in lab,red,red)){.border-accent\/30{border-color:color-mix(in oklab,var(--accent) 30%,transparent)}}.border-accent\/40{border-color:var(--accent)}@supports (color:color-mix(in lab,red,red)){.border-accent\/40{border-color:color-mix(in oklab,var(--accent) 40%,transparent)}}.border-critical\/40{border-color:var(--status-critical)}@supports (color:color-mix(in lab,red,red)){.border-critical\/40{border-color:color-mix(in oklab,var(--status-critical) 40%,transparent)}}.border-critical\/50{border-color:var(--status-critical)}@supports (color:color-mix(in lab,red,red)){.border-critical\/50{border-color:color-mix(in oklab,var(--status-critical) 50%,transparent)}}.border-current{border-color:currentColor}.border-edge,.border-edge\/60{border-color:var(--border)}@supports (color:color-mix(in lab,red,red)){.border-edge\/60{border-color:color-mix(in oklab,var(--border) 60%,transparent)}}.border-good\/40{border-color:var(--status-good)}@supports (color:color-mix(in lab,red,red)){.border-good\/40{border-color:color-mix(in oklab,var(--status-good) 40%,transparent)}}.border-transparent{border-color:#0000}.border-warning\/40{border-color:var(--status-warning)}@supports (color:color-mix(in lab,red,red)){.border-warning\/40{border-color:color-mix(in oklab,var(--status-warning) 40%,transparent)}}.border-warning\/50{border-color:var(--status-warning)}@supports (color:color-mix(in lab,red,red)){.border-warning\/50{border-color:color-mix(in oklab,var(--status-warning) 50%,transparent)}}.bg-accent{background-color:var(--accent)}.bg-edge\/10{background-color:var(--border)}@supports (color:color-mix(in lab,red,red)){.bg-edge\/10{background-color:color-mix(in oklab,var(--border) 10%,transparent)}}.bg-page{background-color:var(--page)}.bg-surface{background-color:var(--surface-1)}.p-3{padding:calc(var(--spacing) * 3)}.p-4{padding:calc(var(--spacing) * 4)}.px-1{padding-inline:var(--spacing)}.px-2{padding-inline:calc(var(--spacing) * 2)}.px-2\.5{padding-inline:calc(var(--spacing) * 2.5)}.px-3{padding-inline:calc(var(--spacing) * 3)}.px-3\.5{padding-inline:calc(var(--spacing) * 3.5)}.px-4{padding-inline:calc(var(--spacing) * 4)}.px-6{padding-inline:calc(var(--spacing) * 6)}.py-0\.5{padding-block:calc(var(--spacing) * .5)}.py-1{padding-block:var(--spacing)}.py-1\.5{padding-block:calc(var(--spacing) * 1.5)}.py-2{padding-block:calc(var(--spacing) * 2)}.py-2\.5{padding-block:calc(var(--spacing) * 2.5)}.py-3{padding-block:calc(var(--spacing) * 3)}.py-4{padding-block:calc(var(--spacing) * 4)}.py-8{padding-block:calc(var(--spacing) * 8)}.py-10{padding-block:calc(var(--spacing) * 10)}.pr-4{padding-right:calc(var(--spacing) * 4)}.pb-2{padding-bottom:calc(var(--spacing) * 2)}.text-center{text-align:center}.text-left{text-align:left}.text-right{text-align:right}.font-mono{font-family:var(--font-mono)}.text-2xl{font-size:var(--text-2xl);line-height:var(--tw-leading,var(--text-2xl--line-height))}.text-lg{font-size:var(--text-lg);line-height:var(--tw-leading,var(--text-lg--line-height))}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xl{font-size:var(--text-xl);line-height:var(--tw-leading,var(--text-xl--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.text-\[10px\]{font-size:10px}.leading-5{--tw-leading:calc(var(--spacing) * 5);line-height:calc(var(--spacing) * 5)}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-normal{--tw-font-weight:var(--font-weight-normal);font-weight:var(--font-weight-normal)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.tracking-tight{--tw-tracking:var(--tracking-tight);letter-spacing:var(--tracking-tight)}.tracking-wide{--tw-tracking:var(--tracking-wide);letter-spacing:var(--tracking-wide)}.break-all{word-break:break-all}.whitespace-nowrap{white-space:nowrap}.whitespace-pre-wrap{white-space:pre-wrap}.text-accent{color:var(--accent)}.text-critical{color:var(--status-critical)}.text-good-text{color:var(--good-text)}.text-ink{color:var(--text-primary)}.text-ink-muted{color:var(--text-muted)}.text-ink-secondary{color:var(--text-secondary)}.text-warning{color:var(--status-warning)}.text-white{color:var(--color-white)}.capitalize{text-transform:capitalize}.uppercase{text-transform:uppercase}.tabular-nums{--tw-numeric-spacing:tabular-nums;font-variant-numeric:var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,)}.underline-offset-2{text-underline-offset:2px}.accent-\(--accent\){accent-color:var(--accent)}.opacity-30{opacity:.3}.shadow-sm{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.transition{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to,opacity,box-shadow,transform,translate,scale,rotate,filter,-webkit-backdrop-filter,backdrop-filter,display,content-visibility,overlay,pointer-events;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.outline-none{--tw-outline-style:none;outline-style:none}.select-none{-webkit-user-select:none;user-select:none}.placeholder\:text-ink-muted\/60::placeholder{color:var(--text-muted)}@supports (color:color-mix(in lab,red,red)){.placeholder\:text-ink-muted\/60::placeholder{color:color-mix(in oklab,var(--text-muted) 60%,transparent)}}.last\:border-0:last-child{border-style:var(--tw-border-style);border-width:0}@media(hover:hover){.hover\:border-accent:hover,.hover\:border-accent\/50:hover{border-color:var(--accent)}@supports (color:color-mix(in lab,red,red)){.hover\:border-accent\/50:hover{border-color:color-mix(in oklab,var(--accent) 50%,transparent)}}.hover\:bg-critical\/10:hover{background-color:var(--status-critical)}@supports (color:color-mix(in lab,red,red)){.hover\:bg-critical\/10:hover{background-color:color-mix(in oklab,var(--status-critical) 10%,transparent)}}.hover\:bg-edge\/20:hover{background-color:var(--border)}@supports (color:color-mix(in lab,red,red)){.hover\:bg-edge\/20:hover{background-color:color-mix(in oklab,var(--border) 20%,transparent)}}.hover\:bg-ink\/\[0\.03\]:hover{background-color:var(--text-primary)}@supports (color:color-mix(in lab,red,red)){.hover\:bg-ink\/\[0\.03\]:hover{background-color:color-mix(in oklab,var(--text-primary) 3%,transparent)}}.hover\:text-accent:hover{color:var(--accent)}.hover\:text-critical:hover{color:var(--status-critical)}.hover\:text-ink-secondary:hover{color:var(--text-secondary)}.hover\:underline:hover{text-decoration-line:underline}.hover\:opacity-90:hover{opacity:.9}}.focus\:border-accent:focus{border-color:var(--accent)}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:opacity-40:disabled{opacity:.4}@media(min-width:40rem){.sm\:col-span-2{grid-column:span 2/span 2}.sm\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.sm\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}}@media(min-width:48rem){.md\:grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}}@media(min-width:64rem){.lg\:grid-cols-6{grid-template-columns:repeat(6,minmax(0,1fr))}}}:root{--page:#f9f9f7;--surface-1:#fcfcfb;--text-primary:#0b0b0b;--text-secondary:#52514e;--text-muted:#898781;--gridline:#e1e0d9;--baseline:#c3c2b7;--border:#0b0b0b1a;--series-1:#2a78d6;--status-good:#0ca30c;--status-warning:#fab219;--status-critical:#d03b3b;--good-text:#006300;--accent:#2a78d6}@media(prefers-color-scheme:dark){:root{--page:#0d0d0d;--surface-1:#1a1a19;--text-primary:#fff;--text-secondary:#c3c2b7;--text-muted:#898781;--gridline:#2c2c2a;--baseline:#383835;--border:#ffffff1a;--series-1:#3987e5;--status-good:#0ca30c;--status-warning:#fab219;--status-critical:#d03b3b;--good-text:#0ca30c;--accent:#3987e5}}html{background:var(--page);color:var(--text-primary);font-family:system-ui,-apple-system,Segoe UI,sans-serif}.log-scroll::-webkit-scrollbar{width:10px;height:10px}.log-scroll::-webkit-scrollbar-thumb{background:var(--baseline);border-radius:5px}@property --tw-space-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-tracking{syntax:"*";inherits:false}@property --tw-ordinal{syntax:"*";inherits:false}@property --tw-slashed-zero{syntax:"*";inherits:false}@property --tw-numeric-figure{syntax:"*";inherits:false}@property --tw-numeric-spacing{syntax:"*";inherits:false}@property --tw-numeric-fraction{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@keyframes pulse{50%{opacity:.5}}
|