llm-usage-metrics 0.8.0 → 0.8.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 +3 -2
- package/dist/index.js +1319 -867
- package/package.json +17 -38
package/dist/index.js
CHANGED
|
@@ -6,11 +6,46 @@ import { isMainThread, workerData } from "worker_threads";
|
|
|
6
6
|
// src/config/runtime-overrides.ts
|
|
7
7
|
import { availableParallelism } from "os";
|
|
8
8
|
|
|
9
|
-
// src/persistence/event-store.ts
|
|
10
|
-
import { createHash } from "crypto";
|
|
9
|
+
// src/persistence/event-store-administration.ts
|
|
11
10
|
import { chmod, mkdir, open } from "fs/promises";
|
|
12
11
|
import path2 from "path";
|
|
13
12
|
|
|
13
|
+
// src/utils/as-record.ts
|
|
14
|
+
function isRecord(value) {
|
|
15
|
+
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
16
|
+
}
|
|
17
|
+
function asRecord(value) {
|
|
18
|
+
if (!isRecord(value)) {
|
|
19
|
+
return void 0;
|
|
20
|
+
}
|
|
21
|
+
return value;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// src/cli/normalize-skipped-row-reasons.ts
|
|
25
|
+
function toPositiveInteger(value) {
|
|
26
|
+
if (typeof value !== "number" || !Number.isFinite(value) || value <= 0) {
|
|
27
|
+
return void 0;
|
|
28
|
+
}
|
|
29
|
+
return Math.trunc(value);
|
|
30
|
+
}
|
|
31
|
+
function normalizeSkippedRowReasons(value) {
|
|
32
|
+
if (!Array.isArray(value)) {
|
|
33
|
+
return [];
|
|
34
|
+
}
|
|
35
|
+
return value.flatMap((entry) => {
|
|
36
|
+
const record = asRecord(entry);
|
|
37
|
+
if (!record) {
|
|
38
|
+
return [];
|
|
39
|
+
}
|
|
40
|
+
const reason = typeof record.reason === "string" ? record.reason.trim() : "";
|
|
41
|
+
const count = toPositiveInteger(record.count);
|
|
42
|
+
if (!reason || count === void 0) {
|
|
43
|
+
return [];
|
|
44
|
+
}
|
|
45
|
+
return [{ reason, count }];
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
|
|
14
49
|
// src/utils/compare-by-code-point.ts
|
|
15
50
|
function compareByCodePoint(left5, right4) {
|
|
16
51
|
if (left5 === right4) {
|
|
@@ -273,42 +308,6 @@ function isPriceableEvent(event) {
|
|
|
273
308
|
return hasBillableTokenBuckets(event);
|
|
274
309
|
}
|
|
275
310
|
|
|
276
|
-
// src/utils/as-record.ts
|
|
277
|
-
function isRecord(value) {
|
|
278
|
-
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
279
|
-
}
|
|
280
|
-
function asRecord(value) {
|
|
281
|
-
if (!isRecord(value)) {
|
|
282
|
-
return void 0;
|
|
283
|
-
}
|
|
284
|
-
return value;
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
// src/cli/normalize-skipped-row-reasons.ts
|
|
288
|
-
function toPositiveInteger(value) {
|
|
289
|
-
if (typeof value !== "number" || !Number.isFinite(value) || value <= 0) {
|
|
290
|
-
return void 0;
|
|
291
|
-
}
|
|
292
|
-
return Math.trunc(value);
|
|
293
|
-
}
|
|
294
|
-
function normalizeSkippedRowReasons(value) {
|
|
295
|
-
if (!Array.isArray(value)) {
|
|
296
|
-
return [];
|
|
297
|
-
}
|
|
298
|
-
return value.flatMap((entry) => {
|
|
299
|
-
const record = asRecord(entry);
|
|
300
|
-
if (!record) {
|
|
301
|
-
return [];
|
|
302
|
-
}
|
|
303
|
-
const reason = typeof record.reason === "string" ? record.reason.trim() : "";
|
|
304
|
-
const count = toPositiveInteger(record.count);
|
|
305
|
-
if (!reason || count === void 0) {
|
|
306
|
-
return [];
|
|
307
|
-
}
|
|
308
|
-
return [{ reason, count }];
|
|
309
|
-
});
|
|
310
|
-
}
|
|
311
|
-
|
|
312
311
|
// src/sources/opencode/node-sqlite-loader.ts
|
|
313
312
|
import { createRequire } from "module";
|
|
314
313
|
|
|
@@ -379,83 +378,14 @@ function getUserCacheRootDir(env = process.env, platform = process.platform, hom
|
|
|
379
378
|
return path.join(homedir, ".cache");
|
|
380
379
|
}
|
|
381
380
|
|
|
382
|
-
// src/persistence/event-store.ts
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
var CONTROL_CHARACTERS_PATTERN2 = new RegExp(String.raw`[\u0000-\u001F\u007F-\u009F]`, "u");
|
|
387
|
-
var NORMALIZED_TIMESTAMP_PATTERN = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/u;
|
|
388
|
-
var DAYS_IN_MONTH = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
|
|
389
|
-
var FAST_PATH_REJECT = /* @__PURE__ */ Symbol("fast path reject");
|
|
390
|
-
var loadEventStoreSqliteModule = () => loadNodeSqliteModule("Event store");
|
|
391
|
-
var EventStoreSchemaVersionError = class extends Error {
|
|
392
|
-
schemaVersion;
|
|
393
|
-
constructor(schemaVersion) {
|
|
394
|
-
const versionLabel = schemaVersion ? `v${schemaVersion}` : "an unknown schema version";
|
|
395
|
-
super(
|
|
396
|
-
`Event store uses ${versionLabel}, which is not supported by this version of llm-usage-metrics (supports v${EVENT_STORE_SCHEMA_VERSION}); leaving store untouched`
|
|
397
|
-
);
|
|
398
|
-
this.name = "EventStoreSchemaVersionError";
|
|
399
|
-
this.schemaVersion = schemaVersion;
|
|
400
|
-
}
|
|
401
|
-
};
|
|
402
|
-
function createSchemaSql() {
|
|
403
|
-
return `
|
|
404
|
-
CREATE TABLE IF NOT EXISTS meta (
|
|
405
|
-
key TEXT PRIMARY KEY,
|
|
406
|
-
value TEXT NOT NULL
|
|
407
|
-
);
|
|
408
|
-
CREATE TABLE IF NOT EXISTS files (
|
|
409
|
-
source TEXT NOT NULL,
|
|
410
|
-
file_path TEXT NOT NULL,
|
|
411
|
-
fingerprint TEXT NOT NULL,
|
|
412
|
-
skipped_rows INTEGER NOT NULL,
|
|
413
|
-
skipped_row_reasons TEXT,
|
|
414
|
-
ingested_at INTEGER NOT NULL,
|
|
415
|
-
PRIMARY KEY (source, file_path)
|
|
416
|
-
);
|
|
417
|
-
CREATE TABLE IF NOT EXISTS events (
|
|
418
|
-
id INTEGER PRIMARY KEY,
|
|
419
|
-
source TEXT NOT NULL,
|
|
420
|
-
file_path TEXT NOT NULL,
|
|
421
|
-
event_index INTEGER NOT NULL,
|
|
422
|
-
session_id TEXT NOT NULL,
|
|
423
|
-
timestamp TEXT NOT NULL,
|
|
424
|
-
model TEXT,
|
|
425
|
-
provider TEXT,
|
|
426
|
-
repo_root TEXT,
|
|
427
|
-
input_tokens INTEGER NOT NULL,
|
|
428
|
-
output_tokens INTEGER NOT NULL,
|
|
429
|
-
reasoning_tokens INTEGER NOT NULL,
|
|
430
|
-
cache_read_tokens INTEGER NOT NULL,
|
|
431
|
-
cache_write_tokens INTEGER NOT NULL,
|
|
432
|
-
total_tokens INTEGER NOT NULL,
|
|
433
|
-
content_hash TEXT,
|
|
434
|
-
cost_usd REAL,
|
|
435
|
-
cost_mode TEXT NOT NULL
|
|
436
|
-
);
|
|
437
|
-
CREATE INDEX IF NOT EXISTS events_file ON events(source, file_path, event_index);
|
|
438
|
-
CREATE INDEX IF NOT EXISTS events_content_hash ON events(content_hash);
|
|
439
|
-
`;
|
|
440
|
-
}
|
|
381
|
+
// src/persistence/event-store-codec.ts
|
|
382
|
+
import { createHash } from "crypto";
|
|
383
|
+
|
|
384
|
+
// src/persistence/event-store-database.ts
|
|
441
385
|
function isEventStoreSqliteModule(value) {
|
|
442
386
|
const moduleRecord = asRecord(value);
|
|
443
387
|
return typeof moduleRecord?.DatabaseSync === "function";
|
|
444
388
|
}
|
|
445
|
-
function normalizeStoreSource(source) {
|
|
446
|
-
const normalizedSource = normalizeSourceId(source)?.toLowerCase();
|
|
447
|
-
if (!normalizedSource) {
|
|
448
|
-
throw new Error("Event store source must be a non-empty string");
|
|
449
|
-
}
|
|
450
|
-
return normalizedSource;
|
|
451
|
-
}
|
|
452
|
-
function normalizeStoreFilePath(filePath) {
|
|
453
|
-
const normalizedFilePath = filePath.trim();
|
|
454
|
-
if (!normalizedFilePath) {
|
|
455
|
-
throw new Error("Event store file path must be a non-empty string");
|
|
456
|
-
}
|
|
457
|
-
return normalizedFilePath;
|
|
458
|
-
}
|
|
459
389
|
function toNonNegativeInteger(value) {
|
|
460
390
|
if (typeof value !== "number" || !Number.isFinite(value) || value < 0) {
|
|
461
391
|
return void 0;
|
|
@@ -475,77 +405,22 @@ function toText(value) {
|
|
|
475
405
|
const normalized = value.trim();
|
|
476
406
|
return normalized || void 0;
|
|
477
407
|
}
|
|
478
|
-
function
|
|
479
|
-
|
|
480
|
-
if (!dependencyPath) {
|
|
481
|
-
return void 0;
|
|
482
|
-
}
|
|
483
|
-
if (!value.exists) {
|
|
484
|
-
return {
|
|
485
|
-
path: dependencyPath,
|
|
486
|
-
exists: false
|
|
487
|
-
};
|
|
488
|
-
}
|
|
489
|
-
const size = toNonNegativeInteger(value.size);
|
|
490
|
-
const mtimeMs = toNonNegativeNumber(value.mtimeMs);
|
|
491
|
-
if (size === void 0 || mtimeMs === void 0) {
|
|
492
|
-
return void 0;
|
|
493
|
-
}
|
|
494
|
-
return {
|
|
495
|
-
path: dependencyPath,
|
|
496
|
-
exists: true,
|
|
497
|
-
size,
|
|
498
|
-
mtimeMs
|
|
499
|
-
};
|
|
500
|
-
}
|
|
501
|
-
function compareDependencyFingerprint(left5, right4) {
|
|
502
|
-
if (left5.path !== right4.path) {
|
|
503
|
-
return compareByCodePoint(left5.path, right4.path);
|
|
504
|
-
}
|
|
505
|
-
if (left5.exists !== right4.exists) {
|
|
506
|
-
return left5.exists ? 1 : -1;
|
|
507
|
-
}
|
|
508
|
-
if ((left5.size ?? -1) !== (right4.size ?? -1)) {
|
|
509
|
-
return (left5.size ?? -1) - (right4.size ?? -1);
|
|
510
|
-
}
|
|
511
|
-
return (left5.mtimeMs ?? -1) - (right4.mtimeMs ?? -1);
|
|
512
|
-
}
|
|
513
|
-
function normalizeEventStoreFingerprint(fingerprint) {
|
|
514
|
-
if (!Array.isArray(fingerprint.dependencies) || fingerprint.dependencies.length === 0) {
|
|
515
|
-
return void 0;
|
|
516
|
-
}
|
|
517
|
-
const dependencies = [];
|
|
518
|
-
for (const dependency of fingerprint.dependencies) {
|
|
519
|
-
const normalizedDependency = normalizeDependencyFingerprint(dependency);
|
|
520
|
-
if (!normalizedDependency) {
|
|
521
|
-
return void 0;
|
|
522
|
-
}
|
|
523
|
-
dependencies.push(normalizedDependency);
|
|
524
|
-
}
|
|
525
|
-
dependencies.sort(compareDependencyFingerprint);
|
|
526
|
-
return { dependencies };
|
|
527
|
-
}
|
|
528
|
-
function serializeEventStoreFingerprint(fingerprint) {
|
|
529
|
-
const normalizedFingerprint = normalizeEventStoreFingerprint(fingerprint);
|
|
530
|
-
if (!normalizedFingerprint) {
|
|
531
|
-
throw new Error("Event store fingerprint must include valid dependency fingerprints");
|
|
532
|
-
}
|
|
533
|
-
return JSON.stringify(normalizedFingerprint);
|
|
534
|
-
}
|
|
535
|
-
function parseSkippedRowReasons(value) {
|
|
536
|
-
if (typeof value !== "string") {
|
|
537
|
-
return [];
|
|
538
|
-
}
|
|
408
|
+
function runTransaction(database, task) {
|
|
409
|
+
database.exec("BEGIN IMMEDIATE");
|
|
539
410
|
try {
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
411
|
+
task();
|
|
412
|
+
database.exec("COMMIT");
|
|
413
|
+
} catch (error) {
|
|
414
|
+
database.exec("ROLLBACK");
|
|
415
|
+
throw error;
|
|
543
416
|
}
|
|
544
417
|
}
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
}
|
|
418
|
+
|
|
419
|
+
// src/persistence/event-store-codec.ts
|
|
420
|
+
var CONTROL_CHARACTERS_PATTERN2 = new RegExp(String.raw`[\u0000-\u001F\u007F-\u009F]`, "u");
|
|
421
|
+
var NORMALIZED_TIMESTAMP_PATTERN = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/u;
|
|
422
|
+
var DAYS_IN_MONTH = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
|
|
423
|
+
var FAST_PATH_REJECT = /* @__PURE__ */ Symbol("fast path reject");
|
|
549
424
|
function normalizeStoredEvent(row) {
|
|
550
425
|
return fastMaterializeStoredEvent(row) ?? slowNormalizeStoredEvent(row);
|
|
551
426
|
}
|
|
@@ -577,23 +452,63 @@ function slowNormalizeStoredEvent(row) {
|
|
|
577
452
|
}
|
|
578
453
|
}
|
|
579
454
|
function fastMaterializeStoredEvent(row) {
|
|
580
|
-
|
|
455
|
+
return materializeStoredEvent(
|
|
456
|
+
row.source,
|
|
457
|
+
row.session_id,
|
|
458
|
+
row.timestamp,
|
|
459
|
+
row.model,
|
|
460
|
+
row.provider,
|
|
461
|
+
row.repo_root,
|
|
462
|
+
row.input_tokens,
|
|
463
|
+
row.output_tokens,
|
|
464
|
+
row.reasoning_tokens,
|
|
465
|
+
row.cache_read_tokens,
|
|
466
|
+
row.cache_write_tokens,
|
|
467
|
+
row.total_tokens,
|
|
468
|
+
row.cost_usd,
|
|
469
|
+
row.cost_mode
|
|
470
|
+
);
|
|
471
|
+
}
|
|
472
|
+
function normalizeStoredEventTuple(row) {
|
|
473
|
+
const event = materializeStoredEvent(...row);
|
|
474
|
+
if (event) {
|
|
475
|
+
return event;
|
|
476
|
+
}
|
|
477
|
+
return slowNormalizeStoredEvent({
|
|
478
|
+
source: row[0],
|
|
479
|
+
session_id: row[1],
|
|
480
|
+
timestamp: row[2],
|
|
481
|
+
model: row[3],
|
|
482
|
+
provider: row[4],
|
|
483
|
+
repo_root: row[5],
|
|
484
|
+
input_tokens: row[6],
|
|
485
|
+
output_tokens: row[7],
|
|
486
|
+
reasoning_tokens: row[8],
|
|
487
|
+
cache_read_tokens: row[9],
|
|
488
|
+
cache_write_tokens: row[10],
|
|
489
|
+
total_tokens: row[11],
|
|
490
|
+
cost_usd: row[12],
|
|
491
|
+
cost_mode: row[13]
|
|
492
|
+
});
|
|
493
|
+
}
|
|
494
|
+
function materializeStoredEvent(sourceValue, sessionIdValue, timestampValue, modelValue, providerValue, repoRootValue, inputTokensValue, outputTokensValue, reasoningTokensValue, cacheReadTokensValue, cacheWriteTokensValue, totalTokensValue, costUsdValue, costModeValue) {
|
|
495
|
+
const costMode = costModeValue === "explicit" || costModeValue === "estimated" ? costModeValue : void 0;
|
|
581
496
|
if (!costMode) {
|
|
582
497
|
return void 0;
|
|
583
498
|
}
|
|
584
|
-
const source = toStoredRequiredText(
|
|
585
|
-
const sessionId = toStoredRequiredText(
|
|
586
|
-
const timestamp = toStoredTimestamp(
|
|
587
|
-
const repoRoot = toStoredOptionalText(
|
|
588
|
-
const provider = toStoredOptionalText(
|
|
589
|
-
const model = toStoredOptionalText(
|
|
590
|
-
const inputTokens = toStoredNonNegativeInteger(
|
|
591
|
-
const outputTokens = toStoredNonNegativeInteger(
|
|
592
|
-
const reasoningTokens = toStoredNonNegativeInteger(
|
|
593
|
-
const cacheReadTokens = toStoredNonNegativeInteger(
|
|
594
|
-
const cacheWriteTokens = toStoredNonNegativeInteger(
|
|
595
|
-
const totalTokens = toStoredNonNegativeInteger(
|
|
596
|
-
const costUsd = toStoredCostUsd(
|
|
499
|
+
const source = toStoredRequiredText(sourceValue);
|
|
500
|
+
const sessionId = toStoredRequiredText(sessionIdValue);
|
|
501
|
+
const timestamp = toStoredTimestamp(timestampValue);
|
|
502
|
+
const repoRoot = toStoredOptionalText(repoRootValue);
|
|
503
|
+
const provider = toStoredOptionalText(providerValue);
|
|
504
|
+
const model = toStoredOptionalText(modelValue);
|
|
505
|
+
const inputTokens = toStoredNonNegativeInteger(inputTokensValue);
|
|
506
|
+
const outputTokens = toStoredNonNegativeInteger(outputTokensValue);
|
|
507
|
+
const reasoningTokens = toStoredNonNegativeInteger(reasoningTokensValue);
|
|
508
|
+
const cacheReadTokens = toStoredNonNegativeInteger(cacheReadTokensValue);
|
|
509
|
+
const cacheWriteTokens = toStoredNonNegativeInteger(cacheWriteTokensValue);
|
|
510
|
+
const totalTokens = toStoredNonNegativeInteger(totalTokensValue);
|
|
511
|
+
const costUsd = toStoredCostUsd(costUsdValue, costMode);
|
|
597
512
|
if (!source || !sessionId || !timestamp || repoRoot === FAST_PATH_REJECT || provider === FAST_PATH_REJECT || model === FAST_PATH_REJECT || inputTokens === void 0 || outputTokens === void 0 || reasoningTokens === void 0 || cacheReadTokens === void 0 || cacheWriteTokens === void 0 || totalTokens === void 0 || costUsd === FAST_PATH_REJECT) {
|
|
598
513
|
return void 0;
|
|
599
514
|
}
|
|
@@ -675,6 +590,79 @@ function toStoredCostUsd(value, costMode) {
|
|
|
675
590
|
}
|
|
676
591
|
return value;
|
|
677
592
|
}
|
|
593
|
+
function computeEventContentHash(event) {
|
|
594
|
+
const fields = [
|
|
595
|
+
event.source.toLowerCase(),
|
|
596
|
+
event.sessionId,
|
|
597
|
+
event.timestamp,
|
|
598
|
+
event.model ?? "",
|
|
599
|
+
event.provider ?? "",
|
|
600
|
+
event.repoRoot ?? "",
|
|
601
|
+
event.inputTokens,
|
|
602
|
+
event.outputTokens,
|
|
603
|
+
event.reasoningTokens,
|
|
604
|
+
event.cacheReadTokens,
|
|
605
|
+
event.cacheWriteTokens,
|
|
606
|
+
event.totalTokens,
|
|
607
|
+
event.costMode,
|
|
608
|
+
event.costUsd ?? ""
|
|
609
|
+
];
|
|
610
|
+
return createHash("sha256").update(fields.map(String).join("")).digest("hex").slice(0, 16);
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
// src/persistence/event-store-schema.ts
|
|
614
|
+
var EVENT_STORE_SCHEMA_VERSION = "3";
|
|
615
|
+
var MIGRATION_BATCH_SIZE = 5e3;
|
|
616
|
+
var EventStoreSchemaVersionError = class extends Error {
|
|
617
|
+
schemaVersion;
|
|
618
|
+
constructor(schemaVersion) {
|
|
619
|
+
const versionLabel = schemaVersion ? `v${schemaVersion}` : "an unknown schema version";
|
|
620
|
+
super(
|
|
621
|
+
`Event store uses ${versionLabel}, which is not supported by this version of llm-usage-metrics (supports v${EVENT_STORE_SCHEMA_VERSION}); leaving store untouched`
|
|
622
|
+
);
|
|
623
|
+
this.name = "EventStoreSchemaVersionError";
|
|
624
|
+
this.schemaVersion = schemaVersion;
|
|
625
|
+
}
|
|
626
|
+
};
|
|
627
|
+
function createSchemaSql() {
|
|
628
|
+
return `
|
|
629
|
+
CREATE TABLE IF NOT EXISTS meta (
|
|
630
|
+
key TEXT PRIMARY KEY,
|
|
631
|
+
value TEXT NOT NULL
|
|
632
|
+
);
|
|
633
|
+
CREATE TABLE IF NOT EXISTS files (
|
|
634
|
+
source TEXT NOT NULL,
|
|
635
|
+
file_path TEXT NOT NULL,
|
|
636
|
+
fingerprint TEXT NOT NULL,
|
|
637
|
+
skipped_rows INTEGER NOT NULL,
|
|
638
|
+
skipped_row_reasons TEXT,
|
|
639
|
+
ingested_at INTEGER NOT NULL,
|
|
640
|
+
PRIMARY KEY (source, file_path)
|
|
641
|
+
);
|
|
642
|
+
CREATE TABLE IF NOT EXISTS events (
|
|
643
|
+
id INTEGER PRIMARY KEY,
|
|
644
|
+
source TEXT NOT NULL,
|
|
645
|
+
file_path TEXT NOT NULL,
|
|
646
|
+
event_index INTEGER NOT NULL,
|
|
647
|
+
session_id TEXT NOT NULL,
|
|
648
|
+
timestamp TEXT NOT NULL,
|
|
649
|
+
model TEXT,
|
|
650
|
+
provider TEXT,
|
|
651
|
+
repo_root TEXT,
|
|
652
|
+
input_tokens INTEGER NOT NULL,
|
|
653
|
+
output_tokens INTEGER NOT NULL,
|
|
654
|
+
reasoning_tokens INTEGER NOT NULL,
|
|
655
|
+
cache_read_tokens INTEGER NOT NULL,
|
|
656
|
+
cache_write_tokens INTEGER NOT NULL,
|
|
657
|
+
total_tokens INTEGER NOT NULL,
|
|
658
|
+
content_hash TEXT,
|
|
659
|
+
cost_usd REAL,
|
|
660
|
+
cost_mode TEXT NOT NULL
|
|
661
|
+
);
|
|
662
|
+
CREATE INDEX IF NOT EXISTS events_file ON events(source, file_path, event_index);
|
|
663
|
+
CREATE INDEX IF NOT EXISTS events_content_hash ON events(content_hash);
|
|
664
|
+
`;
|
|
665
|
+
}
|
|
678
666
|
function listUserTableNames(database) {
|
|
679
667
|
return database.prepare(
|
|
680
668
|
[
|
|
@@ -697,25 +685,6 @@ function createFreshSchema(database) {
|
|
|
697
685
|
database.exec(createSchemaSql());
|
|
698
686
|
database.prepare("INSERT OR REPLACE INTO meta (key, value) VALUES ('schemaVersion', ?)").run(EVENT_STORE_SCHEMA_VERSION);
|
|
699
687
|
}
|
|
700
|
-
function computeEventContentHash(event) {
|
|
701
|
-
const fields = [
|
|
702
|
-
event.source.toLowerCase(),
|
|
703
|
-
event.sessionId,
|
|
704
|
-
event.timestamp,
|
|
705
|
-
event.model ?? "",
|
|
706
|
-
event.provider ?? "",
|
|
707
|
-
event.repoRoot ?? "",
|
|
708
|
-
event.inputTokens,
|
|
709
|
-
event.outputTokens,
|
|
710
|
-
event.reasoningTokens,
|
|
711
|
-
event.cacheReadTokens,
|
|
712
|
-
event.cacheWriteTokens,
|
|
713
|
-
event.totalTokens,
|
|
714
|
-
event.costMode,
|
|
715
|
-
event.costUsd ?? ""
|
|
716
|
-
];
|
|
717
|
-
return createHash("sha256").update(fields.map(String).join("")).digest("hex").slice(0, 16);
|
|
718
|
-
}
|
|
719
688
|
function migrateSchemaV1ToV2(database) {
|
|
720
689
|
runTransaction(database, () => {
|
|
721
690
|
if (readSchemaVersion(database) !== "1") {
|
|
@@ -809,29 +778,105 @@ function initializeSchema(database) {
|
|
|
809
778
|
if (schemaVersion === EVENT_STORE_SCHEMA_VERSION) {
|
|
810
779
|
return;
|
|
811
780
|
}
|
|
812
|
-
if (schemaVersion === "1") {
|
|
813
|
-
migrateSchemaV1ToV2(database);
|
|
814
|
-
migrateSchemaV2ToV3(database);
|
|
815
|
-
return;
|
|
781
|
+
if (schemaVersion === "1") {
|
|
782
|
+
migrateSchemaV1ToV2(database);
|
|
783
|
+
migrateSchemaV2ToV3(database);
|
|
784
|
+
return;
|
|
785
|
+
}
|
|
786
|
+
if (schemaVersion === "2") {
|
|
787
|
+
migrateSchemaV2ToV3(database);
|
|
788
|
+
return;
|
|
789
|
+
}
|
|
790
|
+
throw new EventStoreSchemaVersionError(schemaVersion);
|
|
791
|
+
}
|
|
792
|
+
|
|
793
|
+
// src/persistence/event-store-administration.ts
|
|
794
|
+
var EVENT_STORE_OPEN_TIMEOUT_MS = 2e3;
|
|
795
|
+
var loadEventStoreSqliteModule = () => loadNodeSqliteModule("Event store");
|
|
796
|
+
function normalizeStoreSource(source) {
|
|
797
|
+
const normalizedSource = normalizeSourceId(source)?.toLowerCase();
|
|
798
|
+
if (!normalizedSource) {
|
|
799
|
+
throw new Error("Event store source must be a non-empty string");
|
|
800
|
+
}
|
|
801
|
+
return normalizedSource;
|
|
802
|
+
}
|
|
803
|
+
function normalizeStoreFilePath(filePath) {
|
|
804
|
+
const normalizedFilePath = filePath.trim();
|
|
805
|
+
if (!normalizedFilePath) {
|
|
806
|
+
throw new Error("Event store file path must be a non-empty string");
|
|
807
|
+
}
|
|
808
|
+
return normalizedFilePath;
|
|
809
|
+
}
|
|
810
|
+
function normalizeDependencyFingerprint(value) {
|
|
811
|
+
const dependencyPath = toText(value.path);
|
|
812
|
+
if (!dependencyPath) {
|
|
813
|
+
return void 0;
|
|
814
|
+
}
|
|
815
|
+
if (!value.exists) {
|
|
816
|
+
return {
|
|
817
|
+
path: dependencyPath,
|
|
818
|
+
exists: false
|
|
819
|
+
};
|
|
820
|
+
}
|
|
821
|
+
const size = toNonNegativeInteger(value.size);
|
|
822
|
+
const mtimeMs = toNonNegativeNumber(value.mtimeMs);
|
|
823
|
+
if (size === void 0 || mtimeMs === void 0) {
|
|
824
|
+
return void 0;
|
|
825
|
+
}
|
|
826
|
+
return {
|
|
827
|
+
path: dependencyPath,
|
|
828
|
+
exists: true,
|
|
829
|
+
size,
|
|
830
|
+
mtimeMs
|
|
831
|
+
};
|
|
832
|
+
}
|
|
833
|
+
function compareDependencyFingerprint(left5, right4) {
|
|
834
|
+
if (left5.path !== right4.path) {
|
|
835
|
+
return compareByCodePoint(left5.path, right4.path);
|
|
836
|
+
}
|
|
837
|
+
if (left5.exists !== right4.exists) {
|
|
838
|
+
return left5.exists ? 1 : -1;
|
|
839
|
+
}
|
|
840
|
+
if ((left5.size ?? -1) !== (right4.size ?? -1)) {
|
|
841
|
+
return (left5.size ?? -1) - (right4.size ?? -1);
|
|
842
|
+
}
|
|
843
|
+
return (left5.mtimeMs ?? -1) - (right4.mtimeMs ?? -1);
|
|
844
|
+
}
|
|
845
|
+
function normalizeEventStoreFingerprint(fingerprint) {
|
|
846
|
+
if (!Array.isArray(fingerprint.dependencies) || fingerprint.dependencies.length === 0) {
|
|
847
|
+
return void 0;
|
|
848
|
+
}
|
|
849
|
+
const dependencies = [];
|
|
850
|
+
for (const dependency of fingerprint.dependencies) {
|
|
851
|
+
const normalizedDependency = normalizeDependencyFingerprint(dependency);
|
|
852
|
+
if (!normalizedDependency) {
|
|
853
|
+
return void 0;
|
|
854
|
+
}
|
|
855
|
+
dependencies.push(normalizedDependency);
|
|
816
856
|
}
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
857
|
+
dependencies.sort(compareDependencyFingerprint);
|
|
858
|
+
return { dependencies };
|
|
859
|
+
}
|
|
860
|
+
function serializeEventStoreFingerprint(fingerprint) {
|
|
861
|
+
const normalizedFingerprint = normalizeEventStoreFingerprint(fingerprint);
|
|
862
|
+
if (!normalizedFingerprint) {
|
|
863
|
+
throw new Error("Event store fingerprint must include valid dependency fingerprints");
|
|
820
864
|
}
|
|
821
|
-
|
|
865
|
+
return JSON.stringify(normalizedFingerprint);
|
|
822
866
|
}
|
|
823
|
-
function
|
|
824
|
-
|
|
867
|
+
function parseSkippedRowReasons(value) {
|
|
868
|
+
if (typeof value !== "string") {
|
|
869
|
+
return [];
|
|
870
|
+
}
|
|
825
871
|
try {
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
database.exec("ROLLBACK");
|
|
830
|
-
throw error;
|
|
872
|
+
return normalizeSkippedRowReasons(JSON.parse(value));
|
|
873
|
+
} catch {
|
|
874
|
+
return [];
|
|
831
875
|
}
|
|
832
876
|
}
|
|
833
|
-
function
|
|
834
|
-
|
|
877
|
+
function stringifySkippedRowReasons(skippedRowReasons) {
|
|
878
|
+
const normalizedReasons = normalizeSkippedRowReasons(skippedRowReasons);
|
|
879
|
+
return normalizedReasons.length > 0 ? JSON.stringify(normalizedReasons) : null;
|
|
835
880
|
}
|
|
836
881
|
function getDefaultEventStorePath() {
|
|
837
882
|
return path2.join(getUserCacheRootDir(), "llm-usage-metrics", "events.db");
|
|
@@ -933,6 +978,9 @@ async function readEventStoreStoredFiles(filePath = getDefaultEventStorePath(),
|
|
|
933
978
|
database.close();
|
|
934
979
|
}
|
|
935
980
|
}
|
|
981
|
+
function deleteFileEntry(store, source, filePath) {
|
|
982
|
+
deleteStoredFiles(store, [{ source, filePath }]);
|
|
983
|
+
}
|
|
936
984
|
function getFileEntry(store, source, filePath) {
|
|
937
985
|
const normalizedSource = normalizeStoreSource(source);
|
|
938
986
|
const normalizedFilePath = normalizeStoreFilePath(filePath);
|
|
@@ -960,16 +1008,21 @@ function getFileEntry(store, source, filePath) {
|
|
|
960
1008
|
};
|
|
961
1009
|
}
|
|
962
1010
|
function selectFileEventRows(store, source, filePath) {
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
1011
|
+
let statement = store.statements.selectFileEvents;
|
|
1012
|
+
if (!statement) {
|
|
1013
|
+
statement = store.database.prepare(
|
|
1014
|
+
[
|
|
1015
|
+
"SELECT source, session_id, timestamp, model, provider, repo_root,",
|
|
1016
|
+
" input_tokens, output_tokens, reasoning_tokens, cache_read_tokens,",
|
|
1017
|
+
" cache_write_tokens, total_tokens, cost_usd, cost_mode",
|
|
1018
|
+
"FROM events",
|
|
1019
|
+
"WHERE source = ? AND file_path = ?",
|
|
1020
|
+
"ORDER BY event_index ASC"
|
|
1021
|
+
].join("\n")
|
|
1022
|
+
);
|
|
1023
|
+
statement.setReturnArrays(true);
|
|
1024
|
+
store.statements.selectFileEvents = statement;
|
|
1025
|
+
}
|
|
973
1026
|
return statement.all(source, filePath);
|
|
974
1027
|
}
|
|
975
1028
|
function readFileEvents(store, source, filePath) {
|
|
@@ -977,7 +1030,7 @@ function readFileEvents(store, source, filePath) {
|
|
|
977
1030
|
const normalizedFilePath = normalizeStoreFilePath(filePath);
|
|
978
1031
|
const events = [];
|
|
979
1032
|
for (const row of selectFileEventRows(store, normalizedSource, normalizedFilePath)) {
|
|
980
|
-
const event =
|
|
1033
|
+
const event = normalizeStoredEventTuple(row);
|
|
981
1034
|
if (!event) {
|
|
982
1035
|
deleteFileEntry(store, normalizedSource, normalizedFilePath);
|
|
983
1036
|
return void 0;
|
|
@@ -1214,105 +1267,13 @@ import { readFile as readFileFromFs } from "fs/promises";
|
|
|
1214
1267
|
import os3 from "os";
|
|
1215
1268
|
import path4 from "path";
|
|
1216
1269
|
|
|
1217
|
-
// node_modules/.pnpm/smol-toml@1.
|
|
1218
|
-
var DATE_TIME_RE = /^(\d{4}-\d{2}-\d{2})?[T ]?(?:(\d{2}):\d{2}(?::\d{2}(?:\.\d+)?)?)?(Z|[-+]\d{2}:\d{2})?$/i;
|
|
1219
|
-
var TomlDate = class _TomlDate extends Date {
|
|
1220
|
-
#hasDate = false;
|
|
1221
|
-
#hasTime = false;
|
|
1222
|
-
#offset = null;
|
|
1223
|
-
constructor(date) {
|
|
1224
|
-
let hasDate = true;
|
|
1225
|
-
let hasTime = true;
|
|
1226
|
-
let offset = "Z";
|
|
1227
|
-
if (typeof date === "string") {
|
|
1228
|
-
let match = date.match(DATE_TIME_RE);
|
|
1229
|
-
if (match) {
|
|
1230
|
-
if (!match[1]) {
|
|
1231
|
-
hasDate = false;
|
|
1232
|
-
date = `0000-01-01T${date}`;
|
|
1233
|
-
}
|
|
1234
|
-
hasTime = !!match[2];
|
|
1235
|
-
hasTime && date[10] === " " && (date = date.replace(" ", "T"));
|
|
1236
|
-
if (match[2] && +match[2] > 23) {
|
|
1237
|
-
date = "";
|
|
1238
|
-
} else {
|
|
1239
|
-
offset = match[3] || null;
|
|
1240
|
-
date = date.toUpperCase();
|
|
1241
|
-
if (!offset && hasTime)
|
|
1242
|
-
date += "Z";
|
|
1243
|
-
}
|
|
1244
|
-
} else {
|
|
1245
|
-
date = "";
|
|
1246
|
-
}
|
|
1247
|
-
}
|
|
1248
|
-
super(date);
|
|
1249
|
-
if (!isNaN(this.getTime())) {
|
|
1250
|
-
this.#hasDate = hasDate;
|
|
1251
|
-
this.#hasTime = hasTime;
|
|
1252
|
-
this.#offset = offset;
|
|
1253
|
-
}
|
|
1254
|
-
}
|
|
1255
|
-
isDateTime() {
|
|
1256
|
-
return this.#hasDate && this.#hasTime;
|
|
1257
|
-
}
|
|
1258
|
-
isLocal() {
|
|
1259
|
-
return !this.#hasDate || !this.#hasTime || !this.#offset;
|
|
1260
|
-
}
|
|
1261
|
-
isDate() {
|
|
1262
|
-
return this.#hasDate && !this.#hasTime;
|
|
1263
|
-
}
|
|
1264
|
-
isTime() {
|
|
1265
|
-
return this.#hasTime && !this.#hasDate;
|
|
1266
|
-
}
|
|
1267
|
-
isValid() {
|
|
1268
|
-
return this.#hasDate || this.#hasTime;
|
|
1269
|
-
}
|
|
1270
|
-
toISOString() {
|
|
1271
|
-
let iso = super.toISOString();
|
|
1272
|
-
if (this.isDate())
|
|
1273
|
-
return iso.slice(0, 10);
|
|
1274
|
-
if (this.isTime())
|
|
1275
|
-
return iso.slice(11, 23);
|
|
1276
|
-
if (this.#offset === null)
|
|
1277
|
-
return iso.slice(0, -1);
|
|
1278
|
-
if (this.#offset === "Z")
|
|
1279
|
-
return iso;
|
|
1280
|
-
let offset = +this.#offset.slice(1, 3) * 60 + +this.#offset.slice(4, 6);
|
|
1281
|
-
offset = this.#offset[0] === "-" ? offset : -offset;
|
|
1282
|
-
let offsetDate = new Date(this.getTime() - offset * 6e4);
|
|
1283
|
-
return offsetDate.toISOString().slice(0, -1) + this.#offset;
|
|
1284
|
-
}
|
|
1285
|
-
static wrapAsOffsetDateTime(jsDate, offset = "Z") {
|
|
1286
|
-
let date = new _TomlDate(jsDate);
|
|
1287
|
-
date.#offset = offset;
|
|
1288
|
-
return date;
|
|
1289
|
-
}
|
|
1290
|
-
static wrapAsLocalDateTime(jsDate) {
|
|
1291
|
-
let date = new _TomlDate(jsDate);
|
|
1292
|
-
date.#offset = null;
|
|
1293
|
-
return date;
|
|
1294
|
-
}
|
|
1295
|
-
static wrapAsLocalDate(jsDate) {
|
|
1296
|
-
let date = new _TomlDate(jsDate);
|
|
1297
|
-
date.#hasTime = false;
|
|
1298
|
-
date.#offset = null;
|
|
1299
|
-
return date;
|
|
1300
|
-
}
|
|
1301
|
-
static wrapAsLocalTime(jsDate) {
|
|
1302
|
-
let date = new _TomlDate(jsDate);
|
|
1303
|
-
date.#hasDate = false;
|
|
1304
|
-
date.#offset = null;
|
|
1305
|
-
return date;
|
|
1306
|
-
}
|
|
1307
|
-
};
|
|
1308
|
-
|
|
1309
|
-
// node_modules/.pnpm/smol-toml@1.7.0/node_modules/smol-toml/dist/error.js
|
|
1270
|
+
// node_modules/.pnpm/smol-toml@1.9.0/node_modules/smol-toml/dist/error.js
|
|
1310
1271
|
function getLineColFromPtr(string, ptr) {
|
|
1311
|
-
let lines = string.slice(0, ptr).split(/\r
|
|
1272
|
+
let lines = string.slice(0, ptr).split(/\r?\n/);
|
|
1312
1273
|
return [lines.length, lines.pop().length + 1];
|
|
1313
1274
|
}
|
|
1314
1275
|
function makeCodeBlock(string, line, column) {
|
|
1315
|
-
let lines = string.split(/\r
|
|
1276
|
+
let lines = string.split(/\r?\n/);
|
|
1316
1277
|
let codeblock = "";
|
|
1317
1278
|
let numberLen = (Math.log10(line + 1) | 0) + 1;
|
|
1318
1279
|
for (let i = line - 1; i <= line + 1; i++) {
|
|
@@ -1330,7 +1291,7 @@ function makeCodeBlock(string, line, column) {
|
|
|
1330
1291
|
}
|
|
1331
1292
|
return codeblock;
|
|
1332
1293
|
}
|
|
1333
|
-
var TomlError = class extends Error {
|
|
1294
|
+
var TomlError = class _TomlError extends Error {
|
|
1334
1295
|
line;
|
|
1335
1296
|
column;
|
|
1336
1297
|
codeblock;
|
|
@@ -1344,59 +1305,59 @@ ${codeblock}`, options);
|
|
|
1344
1305
|
this.column = column;
|
|
1345
1306
|
this.codeblock = codeblock;
|
|
1346
1307
|
}
|
|
1308
|
+
/** @internal */
|
|
1309
|
+
static x(message, ctx, ptr) {
|
|
1310
|
+
throw new _TomlError(message, { toml: ctx.s, ptr: ptr ?? ctx.p });
|
|
1311
|
+
}
|
|
1347
1312
|
};
|
|
1348
1313
|
|
|
1349
|
-
// node_modules/.pnpm/smol-toml@1.
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
function parseString(str, ptr) {
|
|
1354
|
-
let c = str[ptr++];
|
|
1314
|
+
// node_modules/.pnpm/smol-toml@1.9.0/node_modules/smol-toml/dist/primitive.js
|
|
1315
|
+
function parseString(ctx) {
|
|
1316
|
+
let startPtr = ctx.p;
|
|
1317
|
+
let c = ctx.s.charCodeAt(ctx.p++);
|
|
1355
1318
|
let first = c;
|
|
1356
|
-
let isLiteral = c ===
|
|
1357
|
-
let isMultiline = c ===
|
|
1319
|
+
let isLiteral = c === 39;
|
|
1320
|
+
let isMultiline = c === ctx.s.charCodeAt(ctx.p) && c === ctx.s.charCodeAt(ctx.p + 1);
|
|
1358
1321
|
if (isMultiline) {
|
|
1359
|
-
if (
|
|
1360
|
-
|
|
1361
|
-
else if (
|
|
1362
|
-
|
|
1322
|
+
if ((c = ctx.s.charCodeAt(ctx.p += 2)) === 10)
|
|
1323
|
+
ctx.p++;
|
|
1324
|
+
else if (c === 13 && ctx.s.charCodeAt(ctx.p + 1) === 10)
|
|
1325
|
+
ctx.p += 2;
|
|
1363
1326
|
}
|
|
1364
1327
|
let parsed = "";
|
|
1365
|
-
let sliceStart =
|
|
1328
|
+
let sliceStart = ctx.p;
|
|
1366
1329
|
let state = 0;
|
|
1367
|
-
for (
|
|
1368
|
-
c =
|
|
1369
|
-
if (isMultiline && (c ===
|
|
1330
|
+
for (; ctx.p < ctx.s.length; ctx.p++) {
|
|
1331
|
+
c = ctx.s.charCodeAt(ctx.p);
|
|
1332
|
+
if (isMultiline && (c === 10 || c === 13 && ctx.s.charCodeAt(ctx.p + 1) === 10)) {
|
|
1370
1333
|
state = state && 3;
|
|
1371
|
-
} else if (c <
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
ptr: i
|
|
1375
|
-
});
|
|
1376
|
-
} else if ((!state || state === 3) && c === first && (!isMultiline || str[i + 1] === first && str[i + 2] === first)) {
|
|
1334
|
+
} else if (c < 32 && c !== 9 || c === 127) {
|
|
1335
|
+
TomlError.x("control characters are not allowed in strings", ctx);
|
|
1336
|
+
} else if ((!state || state === 3) && c === first && (!isMultiline || ctx.s.charCodeAt(ctx.p + 1) === first && ctx.s.charCodeAt(ctx.p + 2) === first)) {
|
|
1377
1337
|
if (isMultiline) {
|
|
1378
|
-
if (
|
|
1379
|
-
|
|
1380
|
-
if (
|
|
1381
|
-
|
|
1338
|
+
if (ctx.s.charCodeAt(ctx.p + 3) === first)
|
|
1339
|
+
ctx.p++;
|
|
1340
|
+
if (ctx.s.charCodeAt(ctx.p + 3) === first)
|
|
1341
|
+
ctx.p++;
|
|
1382
1342
|
}
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1343
|
+
if (!state) {
|
|
1344
|
+
let s = ctx.s.slice(sliceStart, ctx.p);
|
|
1345
|
+
parsed = parsed ? parsed + s : s;
|
|
1346
|
+
}
|
|
1347
|
+
ctx.p += isMultiline ? 3 : 1;
|
|
1348
|
+
return parsed;
|
|
1389
1349
|
} else if (!state) {
|
|
1390
|
-
if (!isLiteral && c ===
|
|
1391
|
-
parsed +=
|
|
1350
|
+
if (!isLiteral && c === 92) {
|
|
1351
|
+
parsed += ctx.s.slice(sliceStart, sliceStart = ctx.p);
|
|
1392
1352
|
state = 1;
|
|
1393
1353
|
}
|
|
1394
1354
|
} else if (state === 1) {
|
|
1395
|
-
if (c ===
|
|
1355
|
+
if (c === 120 || c === 117 || c === 85) {
|
|
1356
|
+
let errPtr = ctx.p++ - 1;
|
|
1396
1357
|
let value = 0;
|
|
1397
|
-
let len = c ===
|
|
1398
|
-
for (let j = 0; j < len; j++,
|
|
1399
|
-
let hex =
|
|
1358
|
+
let len = c === 120 ? 2 : c === 117 ? 4 : 8;
|
|
1359
|
+
for (let j = 0; j < len; j++, ctx.p++) {
|
|
1360
|
+
let hex = ctx.s.charCodeAt(ctx.p);
|
|
1400
1361
|
let digit = (
|
|
1401
1362
|
/* 0-9 */
|
|
1402
1363
|
hex >= 48 && hex <= 57 ? hex - 48 : (
|
|
@@ -1408,369 +1369,517 @@ function parseString(str, ptr) {
|
|
|
1408
1369
|
)
|
|
1409
1370
|
);
|
|
1410
1371
|
if (digit < 0)
|
|
1411
|
-
|
|
1372
|
+
TomlError.x("invalid non-hex character in unicode escape", ctx);
|
|
1412
1373
|
value = value << 4 | digit;
|
|
1413
1374
|
}
|
|
1414
1375
|
if (value < 0 || value > 1114111 || value >= 55296 && value <= 57343) {
|
|
1415
|
-
|
|
1376
|
+
TomlError.x("invalid unicode escape", ctx, errPtr);
|
|
1416
1377
|
}
|
|
1417
1378
|
parsed += String.fromCodePoint(value);
|
|
1418
|
-
sliceStart =
|
|
1379
|
+
sliceStart = ctx.p--;
|
|
1419
1380
|
state = 0;
|
|
1420
|
-
} else if (c ===
|
|
1381
|
+
} else if (isMultiline && (c === 32 || c === 9)) {
|
|
1421
1382
|
state = 2;
|
|
1422
1383
|
} else {
|
|
1423
|
-
if (c ===
|
|
1384
|
+
if (c === 98)
|
|
1424
1385
|
parsed += "\b";
|
|
1425
|
-
else if (c ===
|
|
1386
|
+
else if (c === 116)
|
|
1426
1387
|
parsed += " ";
|
|
1427
|
-
else if (c ===
|
|
1388
|
+
else if (c === 110)
|
|
1428
1389
|
parsed += "\n";
|
|
1429
|
-
else if (c ===
|
|
1390
|
+
else if (c === 102)
|
|
1430
1391
|
parsed += "\f";
|
|
1431
|
-
else if (c ===
|
|
1392
|
+
else if (c === 114)
|
|
1432
1393
|
parsed += "\r";
|
|
1433
|
-
else if (c ===
|
|
1394
|
+
else if (c === 101)
|
|
1434
1395
|
parsed += "\x1B";
|
|
1435
|
-
else if (c ===
|
|
1396
|
+
else if (c === 34)
|
|
1436
1397
|
parsed += '"';
|
|
1437
|
-
else if (c ===
|
|
1398
|
+
else if (c === 92)
|
|
1438
1399
|
parsed += "\\";
|
|
1439
1400
|
else
|
|
1440
|
-
|
|
1441
|
-
sliceStart =
|
|
1401
|
+
TomlError.x("unrecognised escape sequence", ctx);
|
|
1402
|
+
sliceStart = ctx.p + 1;
|
|
1442
1403
|
state = 0;
|
|
1443
1404
|
}
|
|
1444
|
-
} else if (c !==
|
|
1445
|
-
if (state === 2)
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
});
|
|
1450
|
-
}
|
|
1451
|
-
state = !isLiteral && c === "\\" ? 1 : 0;
|
|
1452
|
-
sliceStart = i;
|
|
1405
|
+
} else if (c !== 32 && c !== 9) {
|
|
1406
|
+
if (state === 2)
|
|
1407
|
+
TomlError.x("invalid escape: only line-ending whitespace may be escaped", ctx, sliceStart);
|
|
1408
|
+
state = !isLiteral && c === 92 ? 1 : 0;
|
|
1409
|
+
sliceStart = ctx.p;
|
|
1453
1410
|
}
|
|
1454
1411
|
}
|
|
1455
|
-
|
|
1412
|
+
TomlError.x("unfinished string", ctx, startPtr);
|
|
1456
1413
|
}
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1414
|
+
|
|
1415
|
+
// node_modules/.pnpm/smol-toml@1.9.0/node_modules/smol-toml/dist/date.js
|
|
1416
|
+
var DATE_TIME_RE = /^(\d{4}-\d{2}-\d{2})?[Tt ]?(?:(\d{2}):\d{2}(?::\d{2}(?:\.\d+)?)?)?(Z|z|[-+]\d{2}:\d{2})?$/i;
|
|
1417
|
+
var TomlDate = class _TomlDate extends Date {
|
|
1418
|
+
#hasDate = false;
|
|
1419
|
+
#hasTime = false;
|
|
1420
|
+
#offset = null;
|
|
1421
|
+
constructor(date, fasttype, unsafeDelim) {
|
|
1422
|
+
let hasDate = true;
|
|
1423
|
+
let hasTime = true;
|
|
1424
|
+
let offset = "Z";
|
|
1425
|
+
let c;
|
|
1426
|
+
if (typeof date === "string") {
|
|
1427
|
+
if (fasttype)
|
|
1428
|
+
prep: {
|
|
1429
|
+
if (fasttype < 3) {
|
|
1430
|
+
if (+date.slice(11, 13) > 23) {
|
|
1431
|
+
date = "";
|
|
1432
|
+
break prep;
|
|
1433
|
+
}
|
|
1434
|
+
if (fasttype === 2) {
|
|
1435
|
+
offset = null;
|
|
1436
|
+
date += "Z";
|
|
1437
|
+
} else if ((c = date.charCodeAt(date.length - 1)) !== 90 && c !== 122) {
|
|
1438
|
+
offset = date.slice(date.length - 6);
|
|
1439
|
+
}
|
|
1440
|
+
if (unsafeDelim)
|
|
1441
|
+
date = date.slice(0, 10) + "T" + date.slice(11);
|
|
1442
|
+
} else if (fasttype === 4) {
|
|
1443
|
+
date = +date.slice(0, 2) > 23 ? "" : `0000-01-01T${date}Z`;
|
|
1444
|
+
}
|
|
1445
|
+
hasDate = fasttype !== 4;
|
|
1446
|
+
hasTime = fasttype !== 3;
|
|
1447
|
+
}
|
|
1448
|
+
else {
|
|
1449
|
+
let match = date.match(DATE_TIME_RE);
|
|
1450
|
+
if (match) {
|
|
1451
|
+
if (!match[1]) {
|
|
1452
|
+
hasDate = false;
|
|
1453
|
+
date = `0000-01-01T${date}`;
|
|
1454
|
+
}
|
|
1455
|
+
hasTime = !!match[2];
|
|
1456
|
+
hasTime && date[10] === " " && (date = date.replace(" ", "T"));
|
|
1457
|
+
if (match[2] && +match[2] > 23) {
|
|
1458
|
+
date = "";
|
|
1459
|
+
} else {
|
|
1460
|
+
offset = match[3] || null;
|
|
1461
|
+
if (!offset && hasTime)
|
|
1462
|
+
date += "Z";
|
|
1463
|
+
}
|
|
1464
|
+
} else {
|
|
1465
|
+
date = "";
|
|
1466
|
+
}
|
|
1492
1467
|
}
|
|
1493
|
-
if (isInt || integersAsBigInt === true)
|
|
1494
|
-
numeric = BigInt(value);
|
|
1495
1468
|
}
|
|
1496
|
-
|
|
1469
|
+
super(date);
|
|
1470
|
+
if (!isNaN(this.getTime())) {
|
|
1471
|
+
this.#hasDate = hasDate;
|
|
1472
|
+
this.#hasTime = hasTime;
|
|
1473
|
+
this.#offset = offset;
|
|
1474
|
+
}
|
|
1497
1475
|
}
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
throw new TomlError("invalid value", {
|
|
1501
|
-
toml,
|
|
1502
|
-
ptr
|
|
1503
|
-
});
|
|
1476
|
+
isDateTime() {
|
|
1477
|
+
return this.#hasDate && this.#hasTime;
|
|
1504
1478
|
}
|
|
1505
|
-
|
|
1506
|
-
|
|
1479
|
+
isLocal() {
|
|
1480
|
+
return !this.#hasDate || !this.#hasTime || !this.#offset;
|
|
1481
|
+
}
|
|
1482
|
+
isDate() {
|
|
1483
|
+
return this.#hasDate && !this.#hasTime;
|
|
1484
|
+
}
|
|
1485
|
+
isTime() {
|
|
1486
|
+
return this.#hasTime && !this.#hasDate;
|
|
1487
|
+
}
|
|
1488
|
+
isValid() {
|
|
1489
|
+
return this.#hasDate || this.#hasTime;
|
|
1490
|
+
}
|
|
1491
|
+
toISOString() {
|
|
1492
|
+
let iso = super.toISOString();
|
|
1493
|
+
if (this.isDate())
|
|
1494
|
+
return iso.slice(0, 10);
|
|
1495
|
+
if (this.isTime())
|
|
1496
|
+
return iso.slice(11, 23);
|
|
1497
|
+
if (this.#offset === null)
|
|
1498
|
+
return iso.slice(0, -1);
|
|
1499
|
+
if (this.#offset === "Z" || this.#offset === "z")
|
|
1500
|
+
return iso;
|
|
1501
|
+
let offset = +this.#offset.slice(1, 3) * 60 + +this.#offset.slice(4, 6);
|
|
1502
|
+
offset = this.#offset[0] === "-" ? offset : -offset;
|
|
1503
|
+
let offsetDate = new Date(this.getTime() - offset * 6e4);
|
|
1504
|
+
return offsetDate.toISOString().slice(0, -1) + this.#offset;
|
|
1505
|
+
}
|
|
1506
|
+
static wrapAsOffsetDateTime(jsDate, offset = "Z") {
|
|
1507
|
+
let date = new _TomlDate(jsDate);
|
|
1508
|
+
date.#offset = offset;
|
|
1509
|
+
return date;
|
|
1510
|
+
}
|
|
1511
|
+
static wrapAsLocalDateTime(jsDate) {
|
|
1512
|
+
let date = new _TomlDate(jsDate);
|
|
1513
|
+
date.#offset = null;
|
|
1514
|
+
return date;
|
|
1515
|
+
}
|
|
1516
|
+
static wrapAsLocalDate(jsDate) {
|
|
1517
|
+
let date = new _TomlDate(jsDate);
|
|
1518
|
+
date.#hasTime = false;
|
|
1519
|
+
date.#offset = null;
|
|
1520
|
+
return date;
|
|
1521
|
+
}
|
|
1522
|
+
static wrapAsLocalTime(jsDate) {
|
|
1523
|
+
let date = new _TomlDate(jsDate);
|
|
1524
|
+
date.#hasDate = false;
|
|
1525
|
+
date.#offset = null;
|
|
1526
|
+
return date;
|
|
1527
|
+
}
|
|
1528
|
+
};
|
|
1507
1529
|
|
|
1508
|
-
// node_modules/.pnpm/smol-toml@1.
|
|
1509
|
-
function
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
return
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
ptr
|
|
1526
|
-
});
|
|
1527
|
-
}
|
|
1530
|
+
// node_modules/.pnpm/smol-toml@1.9.0/node_modules/smol-toml/dist/extract.js
|
|
1531
|
+
function isDigit(char, base = 10) {
|
|
1532
|
+
return base === 16 ? char > 47 && char < 58 || char > 64 && char < 71 || char > 96 && char < 103 : char > 47 && char < 48 + base;
|
|
1533
|
+
}
|
|
1534
|
+
function isEndOfValue(char, delim) {
|
|
1535
|
+
return char === 32 || char === 9 || char === 10 || char === 13 || // Structure end or next value delimiter
|
|
1536
|
+
delim && (char === delim || char === 44) || // Comment
|
|
1537
|
+
char === 35;
|
|
1538
|
+
}
|
|
1539
|
+
function extractValue(ctx, end) {
|
|
1540
|
+
let errPtr = ctx.p;
|
|
1541
|
+
let c = ctx.s.charCodeAt(ctx.p);
|
|
1542
|
+
if (c === 91 || c === 123) {
|
|
1543
|
+
ctx.d-- || TomlError.x("document contains excessively nested structures. aborting.", ctx);
|
|
1544
|
+
let value = c === 91 ? parseArray(ctx) : parseInlineTable(ctx);
|
|
1545
|
+
ctx.d++;
|
|
1546
|
+
return value;
|
|
1528
1547
|
}
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1548
|
+
if (c === 34 || c === 39) {
|
|
1549
|
+
return parseString(ctx);
|
|
1550
|
+
}
|
|
1551
|
+
if (c === 116) {
|
|
1552
|
+
if (ctx.s.charCodeAt(++ctx.p) !== 114 || ctx.s.charCodeAt(++ctx.p) !== 117 || ctx.s.charCodeAt(++ctx.p) !== 101)
|
|
1553
|
+
TomlError.x("invalid value", ctx, errPtr);
|
|
1554
|
+
return ctx.p++, true;
|
|
1555
|
+
}
|
|
1556
|
+
if (c === 102) {
|
|
1557
|
+
if (ctx.s.charCodeAt(++ctx.p) !== 97 || ctx.s.charCodeAt(++ctx.p) !== 108 || ctx.s.charCodeAt(++ctx.p) !== 115 || ctx.s.charCodeAt(++ctx.p) !== 101)
|
|
1558
|
+
TomlError.x("invalid value", ctx, errPtr);
|
|
1559
|
+
return ctx.p++, false;
|
|
1539
1560
|
}
|
|
1540
|
-
|
|
1561
|
+
if (c === 43 || c === 45) {
|
|
1562
|
+
return parseNumber(ctx, ctx.p, ctx.s.charCodeAt(++ctx.p), 44 - c, end);
|
|
1563
|
+
}
|
|
1564
|
+
if (ctx.s.charCodeAt(ctx.p + 4) === 45 && ctx.s.charCodeAt(ctx.p + 7) === 45) {
|
|
1565
|
+
return parseDate(ctx, c, end);
|
|
1566
|
+
}
|
|
1567
|
+
if (ctx.s.charCodeAt(ctx.p + 2) === 58) {
|
|
1568
|
+
return parseTime(ctx, c, end);
|
|
1569
|
+
}
|
|
1570
|
+
return parseNumber(ctx, ctx.p, c, 0, end);
|
|
1541
1571
|
}
|
|
1542
|
-
function
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1572
|
+
function parseNumber(ctx, startPtr, startChr, sign, endChr) {
|
|
1573
|
+
let c = startChr;
|
|
1574
|
+
let state = 0;
|
|
1575
|
+
let hasUnderscores = false;
|
|
1576
|
+
if (c === 105) {
|
|
1577
|
+
if (ctx.s.charCodeAt(++ctx.p) !== 110 || ctx.s.charCodeAt(++ctx.p) !== 102)
|
|
1578
|
+
TomlError.x("invalid value", ctx, startPtr);
|
|
1579
|
+
return ctx.p++, (sign || 1) / 0;
|
|
1580
|
+
}
|
|
1581
|
+
if (c === 110) {
|
|
1582
|
+
if (ctx.s.charCodeAt(++ctx.p) !== 97 || ctx.s.charCodeAt(++ctx.p) !== 110)
|
|
1583
|
+
TomlError.x("invalid value", ctx, startPtr);
|
|
1584
|
+
return ctx.p++, NaN;
|
|
1585
|
+
}
|
|
1586
|
+
if (c === 48) {
|
|
1587
|
+
if (++ctx.p >= ctx.s.length || isEndOfValue(c = ctx.s.charCodeAt(ctx.p), endChr))
|
|
1588
|
+
return ctx.bi === true ? 0n : 0;
|
|
1589
|
+
if (!sign) {
|
|
1590
|
+
if (c === 120)
|
|
1591
|
+
return parseIntegerBaseN(ctx, startPtr, 16, endChr);
|
|
1592
|
+
else if (c === 98)
|
|
1593
|
+
return parseIntegerBaseN(ctx, startPtr, 2, endChr);
|
|
1594
|
+
else if (c === 111)
|
|
1595
|
+
return parseIntegerBaseN(ctx, startPtr, 8, endChr);
|
|
1596
|
+
}
|
|
1597
|
+
if (c === 46)
|
|
1598
|
+
state = 2;
|
|
1599
|
+
else if (c === 101 || c === 69)
|
|
1600
|
+
state = 4;
|
|
1601
|
+
else
|
|
1602
|
+
TomlError.x("illegal leading zero", ctx, startPtr);
|
|
1603
|
+
} else if (!isDigit(c))
|
|
1604
|
+
TomlError.x("invalid value", ctx, startPtr);
|
|
1605
|
+
while (++ctx.p < ctx.s.length && (c = ctx.s.charCodeAt(ctx.p), !isEndOfValue(c, endChr))) {
|
|
1606
|
+
if (!state)
|
|
1607
|
+
state = 1;
|
|
1608
|
+
if (c === 95) {
|
|
1609
|
+
if (!(state & 1))
|
|
1610
|
+
TomlError.x("illegal underscore", ctx);
|
|
1611
|
+
state += 11;
|
|
1612
|
+
hasUnderscores = true;
|
|
1613
|
+
} else if (state === 1 && c === 46)
|
|
1614
|
+
state = 2;
|
|
1615
|
+
else if ((state === 1 || state === 3) && (c === 101 || c === 69))
|
|
1616
|
+
state = 4;
|
|
1617
|
+
else if (state === 4 && (c === 43 || c === 45)) {
|
|
1618
|
+
} else if (!isDigit(c))
|
|
1619
|
+
TomlError.x(`illegal character in numeric literal`, ctx);
|
|
1620
|
+
else if (state > 9)
|
|
1621
|
+
state -= 11;
|
|
1622
|
+
else if (!(state & 1))
|
|
1623
|
+
state++;
|
|
1624
|
+
}
|
|
1625
|
+
if (!state) {
|
|
1626
|
+
let val = (startChr - 48) * (sign || 1);
|
|
1627
|
+
return ctx.bi === true ? BigInt(val) : val;
|
|
1628
|
+
}
|
|
1629
|
+
if (!(state & 1))
|
|
1630
|
+
TomlError.x("unfinished numeric value", ctx, startPtr);
|
|
1631
|
+
let str = ctx.s.slice(startPtr, ctx.p);
|
|
1632
|
+
if (hasUnderscores)
|
|
1633
|
+
str = str.replaceAll("_", "");
|
|
1634
|
+
return state > 1 ? parseFloat(str) : parseInteger(ctx, str, 10, startPtr);
|
|
1635
|
+
}
|
|
1636
|
+
function parseIntegerBaseN(ctx, startPtr, base, endChr) {
|
|
1637
|
+
let c, underscore = 1;
|
|
1638
|
+
while (++ctx.p < ctx.s.length && (c = ctx.s.charCodeAt(ctx.p), !isEndOfValue(c, endChr))) {
|
|
1639
|
+
if (c === 95) {
|
|
1640
|
+
if (underscore & 1)
|
|
1641
|
+
TomlError.x("illegal underscore", ctx);
|
|
1642
|
+
underscore = 3;
|
|
1643
|
+
} else if (!isDigit(c, base))
|
|
1644
|
+
TomlError.x(`illegal character in numeric literal`, ctx);
|
|
1645
|
+
else if (underscore & 1)
|
|
1646
|
+
underscore--;
|
|
1647
|
+
}
|
|
1648
|
+
if (underscore & 1)
|
|
1649
|
+
TomlError.x("unfinished numeric value", ctx);
|
|
1650
|
+
let str = ctx.s.slice(startPtr + 2, ctx.p);
|
|
1651
|
+
if (underscore)
|
|
1652
|
+
str = str.replaceAll("_", "");
|
|
1653
|
+
return parseInteger(ctx, str, base, startPtr);
|
|
1654
|
+
}
|
|
1655
|
+
function parseInteger(ctx, str, base, startPtr) {
|
|
1656
|
+
if (ctx.bi !== true)
|
|
1657
|
+
int: {
|
|
1658
|
+
let val = parseInt(str, base);
|
|
1659
|
+
if (!Number.isSafeInteger(val)) {
|
|
1660
|
+
if (ctx.bi)
|
|
1661
|
+
break int;
|
|
1662
|
+
TomlError.x("integer value cannot be represented losslessly", ctx, startPtr);
|
|
1663
|
+
}
|
|
1664
|
+
return val;
|
|
1665
|
+
}
|
|
1666
|
+
return base === 10 ? BigInt(str) : BigInt((base === 2 ? "0b" : base === 8 ? "0o" : "0x") + str);
|
|
1667
|
+
}
|
|
1668
|
+
function parseDate(ctx, c, endChr) {
|
|
1669
|
+
let startPtr = ctx.p++, unsafeSeparator;
|
|
1670
|
+
if (!isDigit(c) || !isDigit(ctx.s.charCodeAt(ctx.p++)) || !isDigit(ctx.s.charCodeAt(ctx.p++)) || !isDigit(ctx.s.charCodeAt(ctx.p++))) {
|
|
1671
|
+
return parseNumber(ctx, ctx.p = startPtr, c, 0, endChr);
|
|
1672
|
+
}
|
|
1673
|
+
ctx.p += 5;
|
|
1674
|
+
if (!isDigit(ctx.s.charCodeAt(ctx.p++)))
|
|
1675
|
+
TomlError.x("invalid date-time: date part is malformed", ctx, startPtr);
|
|
1676
|
+
if (ctx.p >= ctx.s.length || ((c = ctx.s.charCodeAt(ctx.p)) !== 32 || (unsafeSeparator = true, !isDigit(ctx.s.charCodeAt(ctx.p + 1)))) && c !== 84 && c !== 116) {
|
|
1677
|
+
let t2 = ctx.s.slice(startPtr, ctx.p);
|
|
1678
|
+
return readDate(ctx, t2, 3, false, startPtr);
|
|
1679
|
+
}
|
|
1680
|
+
if (ctx.s.charCodeAt(ctx.p += 3) !== 58)
|
|
1681
|
+
TomlError.x("invalid date-time: time part is malformed", ctx, startPtr);
|
|
1682
|
+
if (ctx.s.charCodeAt(ctx.p += 3) === 58)
|
|
1683
|
+
ctx.p += 3;
|
|
1684
|
+
if (ctx.s.charCodeAt(ctx.p) === 46)
|
|
1685
|
+
while (isDigit(ctx.s.charCodeAt(++ctx.p)))
|
|
1686
|
+
;
|
|
1687
|
+
if (c = ctx.s.charCodeAt(ctx.p)) {
|
|
1688
|
+
if (c === 90 || c === 122) {
|
|
1689
|
+
let t2 = ctx.s.slice(startPtr, ++ctx.p);
|
|
1690
|
+
return readDate(ctx, t2, 1, unsafeSeparator, startPtr, "[+00:00]");
|
|
1691
|
+
}
|
|
1692
|
+
if (c === 43 || c === 45) {
|
|
1693
|
+
let t2 = ctx.s.slice(startPtr, ctx.p += 6);
|
|
1694
|
+
return readDate(ctx, t2, 1, unsafeSeparator, startPtr, !ctx.ld && "[" + ctx.s.slice(ctx.p - 6, ctx.p) + "]");
|
|
1695
|
+
}
|
|
1696
|
+
}
|
|
1697
|
+
let t = ctx.s.slice(startPtr, ctx.p);
|
|
1698
|
+
return readDate(ctx, t, 2, unsafeSeparator, startPtr);
|
|
1699
|
+
}
|
|
1700
|
+
function parseTime(ctx, c, endChr) {
|
|
1701
|
+
let start = ctx.p;
|
|
1702
|
+
if (!isDigit(c) || !isDigit(ctx.s.charCodeAt(++ctx.p))) {
|
|
1703
|
+
return parseNumber(ctx, --ctx.p, c, 0, endChr);
|
|
1704
|
+
}
|
|
1705
|
+
if (ctx.s.charCodeAt(ctx.p += 4) === 58)
|
|
1706
|
+
ctx.p += 3;
|
|
1707
|
+
if (ctx.s.charCodeAt(ctx.p) === 46)
|
|
1708
|
+
while (isDigit(ctx.s.charCodeAt(++ctx.p)))
|
|
1709
|
+
;
|
|
1710
|
+
let t = ctx.s.slice(start, ctx.p);
|
|
1711
|
+
return readDate(ctx, t, 4, false, start);
|
|
1712
|
+
}
|
|
1713
|
+
function readDate(ctx, str, type, unsafeDelim, errPtr, temporalSuffix) {
|
|
1714
|
+
if (ctx.ld) {
|
|
1715
|
+
let date = new TomlDate(str, type, unsafeDelim);
|
|
1716
|
+
if (!date.isValid())
|
|
1717
|
+
TomlError.x("invalid date", ctx, errPtr);
|
|
1718
|
+
return date;
|
|
1546
1719
|
}
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1720
|
+
try {
|
|
1721
|
+
if (temporalSuffix)
|
|
1722
|
+
str += temporalSuffix;
|
|
1723
|
+
switch (type) {
|
|
1724
|
+
case 1:
|
|
1725
|
+
return Temporal.ZonedDateTime.from(str);
|
|
1726
|
+
case 2:
|
|
1727
|
+
return Temporal.PlainDateTime.from(str);
|
|
1728
|
+
case 3:
|
|
1729
|
+
return Temporal.PlainDate.from(str);
|
|
1730
|
+
case 4:
|
|
1731
|
+
return Temporal.PlainTime.from(str);
|
|
1555
1732
|
}
|
|
1733
|
+
} catch (e) {
|
|
1734
|
+
TomlError.x(e instanceof Error ? e.message : "" + e, ctx, errPtr);
|
|
1556
1735
|
}
|
|
1557
|
-
throw new TomlError("cannot find end of structure", {
|
|
1558
|
-
toml: str,
|
|
1559
|
-
ptr
|
|
1560
|
-
});
|
|
1561
1736
|
}
|
|
1562
1737
|
|
|
1563
|
-
// node_modules/.pnpm/smol-toml@1.
|
|
1564
|
-
function
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
}
|
|
1573
|
-
function extractValue(str, ptr, end, depth, integersAsBigInt) {
|
|
1574
|
-
if (depth === 0) {
|
|
1575
|
-
throw new TomlError("document contains excessively nested structures. aborting.", {
|
|
1576
|
-
toml: str,
|
|
1577
|
-
ptr
|
|
1578
|
-
});
|
|
1579
|
-
}
|
|
1580
|
-
let c = str[ptr];
|
|
1581
|
-
if (c === "[" || c === "{") {
|
|
1582
|
-
let [value, endPtr2] = c === "[" ? parseArray(str, ptr, depth, integersAsBigInt) : parseInlineTable(str, ptr, depth, integersAsBigInt);
|
|
1583
|
-
if (end) {
|
|
1584
|
-
endPtr2 = skipVoid(str, endPtr2);
|
|
1585
|
-
if (str[endPtr2] === ",")
|
|
1586
|
-
endPtr2++;
|
|
1587
|
-
else if (str[endPtr2] !== end) {
|
|
1588
|
-
throw new TomlError("expected comma or end of structure", {
|
|
1589
|
-
toml: str,
|
|
1590
|
-
ptr: endPtr2
|
|
1591
|
-
});
|
|
1592
|
-
}
|
|
1738
|
+
// node_modules/.pnpm/smol-toml@1.9.0/node_modules/smol-toml/dist/util.js
|
|
1739
|
+
function skipComment(ctx) {
|
|
1740
|
+
for (; ctx.p < ctx.s.length; ctx.p++) {
|
|
1741
|
+
let c = ctx.s.charCodeAt(ctx.p);
|
|
1742
|
+
if (c === 10)
|
|
1743
|
+
break;
|
|
1744
|
+
if (c === 13 && ctx.s.charCodeAt(ctx.p + 1) === 10) {
|
|
1745
|
+
ctx.p++;
|
|
1746
|
+
break;
|
|
1593
1747
|
}
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
if (c === '"' || c === "'") {
|
|
1597
|
-
let [parsed, endPtr2] = parseString(str, ptr);
|
|
1598
|
-
if (end) {
|
|
1599
|
-
endPtr2 = skipVoid(str, endPtr2);
|
|
1600
|
-
if (str[endPtr2] && str[endPtr2] !== "," && str[endPtr2] !== end && str[endPtr2] !== "\n" && str[endPtr2] !== "\r") {
|
|
1601
|
-
throw new TomlError("unexpected character encountered", {
|
|
1602
|
-
toml: str,
|
|
1603
|
-
ptr: endPtr2
|
|
1604
|
-
});
|
|
1605
|
-
}
|
|
1606
|
-
if (str[endPtr2] === ",")
|
|
1607
|
-
endPtr2++;
|
|
1748
|
+
if (c < 32 && c !== 9 || c === 127) {
|
|
1749
|
+
TomlError.x("control characters are not allowed in comments", ctx);
|
|
1608
1750
|
}
|
|
1609
|
-
return [parsed, endPtr2];
|
|
1610
|
-
}
|
|
1611
|
-
let endPtr = skipUntil(str, ptr, ",", end);
|
|
1612
|
-
let slice = sliceAndTrimEndOf(str, ptr, endPtr - (str[endPtr - 1] === "," ? 1 : 0));
|
|
1613
|
-
if (!slice[0]) {
|
|
1614
|
-
throw new TomlError("incomplete key-value declaration: no value specified", {
|
|
1615
|
-
toml: str,
|
|
1616
|
-
ptr
|
|
1617
|
-
});
|
|
1618
1751
|
}
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1752
|
+
}
|
|
1753
|
+
function skipVoid(ctx, banNewLines, banComments) {
|
|
1754
|
+
let c;
|
|
1755
|
+
while (ctx.p < ctx.s.length) {
|
|
1756
|
+
while (ctx.p < ctx.s.length && ((c = ctx.s.charCodeAt(ctx.p)) === 32 || c === 9 || !banNewLines && (c === 10 || c === 13 && ctx.s.charCodeAt(ctx.p + 1) === 10)))
|
|
1757
|
+
ctx.p++;
|
|
1758
|
+
if (banComments || c !== 35)
|
|
1759
|
+
break;
|
|
1760
|
+
skipComment(ctx);
|
|
1623
1761
|
}
|
|
1624
|
-
return [
|
|
1625
|
-
parseValue(slice[0], str, ptr, integersAsBigInt),
|
|
1626
|
-
endPtr
|
|
1627
|
-
];
|
|
1628
1762
|
}
|
|
1629
1763
|
|
|
1630
|
-
// node_modules/.pnpm/smol-toml@1.
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
let
|
|
1764
|
+
// node_modules/.pnpm/smol-toml@1.9.0/node_modules/smol-toml/dist/struct.js
|
|
1765
|
+
function parseKey(ctx, end = 61) {
|
|
1766
|
+
let startPtr;
|
|
1767
|
+
let state = 0;
|
|
1634
1768
|
let parsed = [];
|
|
1635
|
-
let
|
|
1636
|
-
|
|
1637
|
-
throw new TomlError("incomplete key-value: cannot find end of key", {
|
|
1638
|
-
toml: str,
|
|
1639
|
-
ptr
|
|
1640
|
-
});
|
|
1641
|
-
}
|
|
1769
|
+
let sliceStart;
|
|
1770
|
+
let c = ctx.s.charCodeAt(startPtr = ctx.p);
|
|
1642
1771
|
do {
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
ptr: eos
|
|
1666
|
-
});
|
|
1667
|
-
}
|
|
1668
|
-
if (endPtr < eos) {
|
|
1669
|
-
endPtr = str.indexOf(end, eos);
|
|
1670
|
-
if (endPtr < 0) {
|
|
1671
|
-
throw new TomlError("incomplete key-value: cannot find end of key", {
|
|
1672
|
-
toml: str,
|
|
1673
|
-
ptr
|
|
1674
|
-
});
|
|
1675
|
-
}
|
|
1676
|
-
}
|
|
1677
|
-
parsed.push(part);
|
|
1678
|
-
} else {
|
|
1679
|
-
dot = str.indexOf(".", ptr);
|
|
1680
|
-
let part = str.slice(ptr, dot < 0 || dot > endPtr ? endPtr : dot);
|
|
1681
|
-
if (!KEY_PART_RE.test(part)) {
|
|
1682
|
-
throw new TomlError("only letter, numbers, dashes and underscores are allowed in keys", {
|
|
1683
|
-
toml: str,
|
|
1684
|
-
ptr
|
|
1685
|
-
});
|
|
1686
|
-
}
|
|
1687
|
-
parsed.push(part.trimEnd());
|
|
1772
|
+
if (c === end) {
|
|
1773
|
+
if (!state)
|
|
1774
|
+
TomlError.x("unexpected end of key", ctx);
|
|
1775
|
+
if (state === 1)
|
|
1776
|
+
parsed.push(ctx.s.slice(sliceStart, ctx.p));
|
|
1777
|
+
return ctx.p++, parsed;
|
|
1778
|
+
} else if (c === 46) {
|
|
1779
|
+
if (!state)
|
|
1780
|
+
TomlError.x("illegal empty bare key", ctx);
|
|
1781
|
+
if (state === 1)
|
|
1782
|
+
parsed.push(ctx.s.slice(sliceStart, ctx.p));
|
|
1783
|
+
state = 0;
|
|
1784
|
+
} else if (!state && (c === 34 || c === 39)) {
|
|
1785
|
+
if (c === ctx.s.charCodeAt(ctx.p + 1) && c === ctx.s.charCodeAt(ctx.p + 2))
|
|
1786
|
+
TomlError.x("illegal quoted key: multiline strings are not allowed", ctx);
|
|
1787
|
+
parsed.push(parseString(ctx));
|
|
1788
|
+
state = 2;
|
|
1789
|
+
ctx.p--;
|
|
1790
|
+
} else if (c === 32 || c === 9) {
|
|
1791
|
+
if (state === 1) {
|
|
1792
|
+
parsed.push(ctx.s.slice(sliceStart, ctx.p));
|
|
1793
|
+
state = 2;
|
|
1688
1794
|
}
|
|
1795
|
+
} else if (state === 2 || c < 48 && c !== 45 || c > 57 && c < 65 || c > 90 && c < 97 && c !== 95 || c > 122) {
|
|
1796
|
+
TomlError.x("illegal character in key", ctx);
|
|
1797
|
+
} else if (!state) {
|
|
1798
|
+
state = 1;
|
|
1799
|
+
sliceStart = ctx.p;
|
|
1689
1800
|
}
|
|
1690
|
-
} while (
|
|
1691
|
-
|
|
1801
|
+
} while (c = ctx.s.charCodeAt(++ctx.p));
|
|
1802
|
+
TomlError.x("incomplete key-value: cannot find end of key", ctx, startPtr);
|
|
1692
1803
|
}
|
|
1693
|
-
function parseInlineTable(
|
|
1694
|
-
let
|
|
1804
|
+
function parseInlineTable(ctx) {
|
|
1805
|
+
let startPtr = ctx.p++;
|
|
1806
|
+
let res = /* @__PURE__ */ Object.create(null);
|
|
1695
1807
|
let seen = /* @__PURE__ */ new Set();
|
|
1696
1808
|
let c;
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
if (c ===
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
k = key[i];
|
|
1715
|
-
if ((hasOwn = Object.hasOwn(t, k)) && (typeof t[k] !== "object" || seen.has(t[k]))) {
|
|
1716
|
-
throw new TomlError("trying to redefine an already defined value", {
|
|
1717
|
-
toml: str,
|
|
1718
|
-
ptr
|
|
1719
|
-
});
|
|
1720
|
-
}
|
|
1721
|
-
if (!hasOwn && k === "__proto__") {
|
|
1722
|
-
Object.defineProperty(t, k, { enumerable: true, configurable: true, writable: true });
|
|
1723
|
-
}
|
|
1809
|
+
while (ctx.p < ctx.s.length) {
|
|
1810
|
+
skipVoid(ctx);
|
|
1811
|
+
if ((c = ctx.s.charCodeAt(ctx.p)) === 125) {
|
|
1812
|
+
ctx.p++;
|
|
1813
|
+
return res;
|
|
1814
|
+
}
|
|
1815
|
+
let k;
|
|
1816
|
+
let t = res;
|
|
1817
|
+
let hasOwn = false;
|
|
1818
|
+
let errPtr = ctx.p;
|
|
1819
|
+
let key = parseKey(ctx);
|
|
1820
|
+
for (let i = 0; i < key.length; i++) {
|
|
1821
|
+
if (i)
|
|
1822
|
+
t = hasOwn ? t[k] : t[k] = /* @__PURE__ */ Object.create(null);
|
|
1823
|
+
k = key[i];
|
|
1824
|
+
if ((hasOwn = Object.hasOwn(t, k)) && (typeof t[k] !== "object" || seen.has(t[k]))) {
|
|
1825
|
+
TomlError.x("trying to redefine an already defined value", ctx, errPtr);
|
|
1724
1826
|
}
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1827
|
+
let unsafe = k === "__proto__";
|
|
1828
|
+
if (ctx.uk && (unsafe || k === "constructor")) {
|
|
1829
|
+
t = ctx.uk !== 1 && TomlError.x("document contains an unsafe property", ctx, errPtr);
|
|
1830
|
+
break;
|
|
1831
|
+
}
|
|
1832
|
+
if (!hasOwn && unsafe) {
|
|
1833
|
+
Object.defineProperty(t, k, { enumerable: true, configurable: true, writable: true });
|
|
1730
1834
|
}
|
|
1731
|
-
|
|
1835
|
+
}
|
|
1836
|
+
if (hasOwn) {
|
|
1837
|
+
TomlError.x("trying to redefine an already defined value", ctx, errPtr);
|
|
1838
|
+
}
|
|
1839
|
+
skipVoid(ctx, true, true);
|
|
1840
|
+
let value = extractValue(
|
|
1841
|
+
ctx,
|
|
1842
|
+
125
|
|
1843
|
+
/* } */
|
|
1844
|
+
);
|
|
1845
|
+
if (t && typeof (t[k] = value) === "object")
|
|
1732
1846
|
seen.add(value);
|
|
1733
|
-
|
|
1734
|
-
|
|
1847
|
+
skipVoid(ctx);
|
|
1848
|
+
if ((c = ctx.s.charCodeAt(ctx.p++)) === 125) {
|
|
1849
|
+
return res;
|
|
1735
1850
|
}
|
|
1851
|
+
if (c !== 44)
|
|
1852
|
+
TomlError.x("expected comma or end of structure", ctx, ctx.p - 1);
|
|
1736
1853
|
}
|
|
1737
|
-
|
|
1738
|
-
throw new TomlError("unfinished table encountered", {
|
|
1739
|
-
toml: str,
|
|
1740
|
-
ptr
|
|
1741
|
-
});
|
|
1742
|
-
}
|
|
1743
|
-
return [res, ptr];
|
|
1854
|
+
TomlError.x("unfinished table", ctx, startPtr);
|
|
1744
1855
|
}
|
|
1745
|
-
function parseArray(
|
|
1856
|
+
function parseArray(ctx) {
|
|
1857
|
+
let startPtr = ctx.p++;
|
|
1746
1858
|
let res = [];
|
|
1747
1859
|
let c;
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
if (c ===
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
});
|
|
1768
|
-
}
|
|
1769
|
-
return [res, ptr];
|
|
1860
|
+
while (ctx.p < ctx.s.length) {
|
|
1861
|
+
skipVoid(ctx);
|
|
1862
|
+
if ((c = ctx.s.charCodeAt(ctx.p)) === 93) {
|
|
1863
|
+
ctx.p++;
|
|
1864
|
+
return res;
|
|
1865
|
+
}
|
|
1866
|
+
res.push(extractValue(
|
|
1867
|
+
ctx,
|
|
1868
|
+
93
|
|
1869
|
+
/* ] */
|
|
1870
|
+
));
|
|
1871
|
+
skipVoid(ctx);
|
|
1872
|
+
if ((c = ctx.s.charCodeAt(ctx.p++)) === 93) {
|
|
1873
|
+
return res;
|
|
1874
|
+
}
|
|
1875
|
+
if (c !== 44)
|
|
1876
|
+
TomlError.x("expected comma or end of structure", ctx, ctx.p - 1);
|
|
1877
|
+
}
|
|
1878
|
+
TomlError.x("unfinished array", ctx, startPtr);
|
|
1770
1879
|
}
|
|
1771
1880
|
|
|
1772
|
-
// node_modules/.pnpm/smol-toml@1.
|
|
1773
|
-
function peekTable(key, table, meta, type) {
|
|
1881
|
+
// node_modules/.pnpm/smol-toml@1.9.0/node_modules/smol-toml/dist/parse.js
|
|
1882
|
+
function peekTable(ctx, key, table, meta, type) {
|
|
1774
1883
|
let t = table;
|
|
1775
1884
|
let m = meta;
|
|
1776
1885
|
let k;
|
|
@@ -1778,7 +1887,7 @@ function peekTable(key, table, meta, type) {
|
|
|
1778
1887
|
let state;
|
|
1779
1888
|
for (let i = 0; i < key.length; i++) {
|
|
1780
1889
|
if (i) {
|
|
1781
|
-
t = hasOwn ? t[k] : t[k] =
|
|
1890
|
+
t = hasOwn ? t[k] : t[k] = /* @__PURE__ */ Object.create(null);
|
|
1782
1891
|
m = (state = m[k]).c;
|
|
1783
1892
|
if (type === 0 && (state.t === 1 || state.t === 2)) {
|
|
1784
1893
|
return null;
|
|
@@ -1794,7 +1903,10 @@ function peekTable(key, table, meta, type) {
|
|
|
1794
1903
|
return null;
|
|
1795
1904
|
}
|
|
1796
1905
|
if (!hasOwn) {
|
|
1797
|
-
|
|
1906
|
+
let unsafe = k === "__proto__";
|
|
1907
|
+
if (ctx.uk && (unsafe || k === "constructor"))
|
|
1908
|
+
return false;
|
|
1909
|
+
if (unsafe) {
|
|
1798
1910
|
Object.defineProperty(t, k, { enumerable: true, configurable: true, writable: true });
|
|
1799
1911
|
Object.defineProperty(m, k, { enumerable: true, configurable: true, writable: true });
|
|
1800
1912
|
}
|
|
@@ -1802,7 +1914,7 @@ function peekTable(key, table, meta, type) {
|
|
|
1802
1914
|
t: i < key.length - 1 && type === 2 ? 3 : type,
|
|
1803
1915
|
d: false,
|
|
1804
1916
|
i: 0,
|
|
1805
|
-
c:
|
|
1917
|
+
c: /* @__PURE__ */ Object.create(null)
|
|
1806
1918
|
};
|
|
1807
1919
|
}
|
|
1808
1920
|
}
|
|
@@ -1815,85 +1927,103 @@ function peekTable(key, table, meta, type) {
|
|
|
1815
1927
|
state.d = true;
|
|
1816
1928
|
t[k] = [];
|
|
1817
1929
|
}
|
|
1818
|
-
t[k].push(t =
|
|
1819
|
-
state.c[state.i++] = state = { t: 1, d: false, i: 0, c:
|
|
1930
|
+
t[k].push(t = /* @__PURE__ */ Object.create(null));
|
|
1931
|
+
state.c[state.i++] = state = { t: 1, d: false, i: 0, c: /* @__PURE__ */ Object.create(null) };
|
|
1820
1932
|
}
|
|
1821
1933
|
if (state.d) {
|
|
1822
1934
|
return null;
|
|
1823
1935
|
}
|
|
1824
1936
|
state.d = true;
|
|
1825
1937
|
if (type === 1) {
|
|
1826
|
-
t = hasOwn ? t[k] : t[k] =
|
|
1938
|
+
t = hasOwn ? t[k] : t[k] = /* @__PURE__ */ Object.create(null);
|
|
1827
1939
|
} else if (type === 0 && hasOwn) {
|
|
1828
1940
|
return null;
|
|
1829
1941
|
}
|
|
1830
1942
|
return [k, t, state.c];
|
|
1831
1943
|
}
|
|
1832
|
-
function
|
|
1833
|
-
|
|
1834
|
-
|
|
1944
|
+
function validateTablePeek(ctx, peek, ptr) {
|
|
1945
|
+
if (peek === null || ctx.uk === 2)
|
|
1946
|
+
TomlError.x(peek === null ? "trying to redefine an already defined table or value" : "document contains an unsafe property", ctx, ptr);
|
|
1947
|
+
}
|
|
1948
|
+
function parse(toml, options = {}) {
|
|
1949
|
+
let ctx = {
|
|
1950
|
+
s: toml,
|
|
1951
|
+
p: 0,
|
|
1952
|
+
d: options.maxDepth ?? 1e3,
|
|
1953
|
+
bi: options.integersAsBigInt ?? false,
|
|
1954
|
+
ld: options.useLegacyDate ?? true,
|
|
1955
|
+
uk: options.unsafeKeyBehaviour === "throw" ? 2 : options.unsafeKeyBehaviour === "drop" ? 1 : 0
|
|
1956
|
+
};
|
|
1957
|
+
let res = /* @__PURE__ */ Object.create(null);
|
|
1958
|
+
let meta = /* @__PURE__ */ Object.create(null);
|
|
1959
|
+
let tmp;
|
|
1960
|
+
let skipping = false;
|
|
1835
1961
|
let tbl = res;
|
|
1836
1962
|
let m = meta;
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1963
|
+
if (toml.charCodeAt(0) === 65279)
|
|
1964
|
+
ctx.p++;
|
|
1965
|
+
skipVoid(ctx);
|
|
1966
|
+
while (ctx.p < toml.length) {
|
|
1967
|
+
if (toml.charCodeAt(ctx.p) === 91) {
|
|
1968
|
+
let isTableArray = toml.charCodeAt(++ctx.p) === 91;
|
|
1969
|
+
tmp = ctx.p += +isTableArray;
|
|
1970
|
+
skipping = false;
|
|
1971
|
+
let k = parseKey(
|
|
1972
|
+
ctx,
|
|
1973
|
+
93
|
|
1974
|
+
/* ] */
|
|
1975
|
+
);
|
|
1841
1976
|
if (isTableArray) {
|
|
1842
|
-
if (toml
|
|
1843
|
-
|
|
1844
|
-
toml,
|
|
1845
|
-
ptr: k[1] - 1
|
|
1846
|
-
});
|
|
1977
|
+
if (toml.charCodeAt(ctx.p) !== 93) {
|
|
1978
|
+
TomlError.x("expected end of table array declaration", ctx);
|
|
1847
1979
|
}
|
|
1848
|
-
|
|
1980
|
+
ctx.p++;
|
|
1849
1981
|
}
|
|
1850
1982
|
let p = peekTable(
|
|
1851
|
-
|
|
1983
|
+
ctx,
|
|
1984
|
+
k,
|
|
1852
1985
|
res,
|
|
1853
1986
|
meta,
|
|
1854
1987
|
isTableArray ? 2 : 1
|
|
1855
1988
|
/* Type.EXPLICIT */
|
|
1856
1989
|
);
|
|
1857
1990
|
if (!p) {
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1991
|
+
validateTablePeek(ctx, p, tmp);
|
|
1992
|
+
skipping = true;
|
|
1993
|
+
} else {
|
|
1994
|
+
m = p[2];
|
|
1995
|
+
tbl = p[1];
|
|
1862
1996
|
}
|
|
1863
|
-
m = p[2];
|
|
1864
|
-
tbl = p[1];
|
|
1865
|
-
ptr = k[1];
|
|
1866
1997
|
} else {
|
|
1867
|
-
|
|
1998
|
+
tmp = ctx.p;
|
|
1999
|
+
let k = parseKey(ctx);
|
|
1868
2000
|
let p = peekTable(
|
|
1869
|
-
|
|
2001
|
+
ctx,
|
|
2002
|
+
k,
|
|
1870
2003
|
tbl,
|
|
1871
2004
|
m,
|
|
1872
2005
|
0
|
|
1873
2006
|
/* Type.DOTTED */
|
|
1874
2007
|
);
|
|
1875
|
-
if (!p)
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
ptr = skipVoid(toml, ptr, true);
|
|
1886
|
-
if (toml[ptr] && toml[ptr] !== "\n" && toml[ptr] !== "\r") {
|
|
1887
|
-
throw new TomlError("each key-value declaration must be followed by an end-of-line", {
|
|
1888
|
-
toml,
|
|
1889
|
-
ptr
|
|
1890
|
-
});
|
|
2008
|
+
if (!p && !skipping)
|
|
2009
|
+
validateTablePeek(ctx, p, tmp);
|
|
2010
|
+
skipVoid(ctx, true, true);
|
|
2011
|
+
let v = extractValue(ctx, void 0);
|
|
2012
|
+
if (p && !skipping)
|
|
2013
|
+
p[1][p[0]] = v;
|
|
2014
|
+
}
|
|
2015
|
+
skipVoid(ctx, true);
|
|
2016
|
+
if (ctx.p < toml.length && (tmp = toml.charCodeAt(ctx.p)) !== 10 && (tmp !== 13 || toml.charCodeAt(ctx.p + 1) !== 10)) {
|
|
2017
|
+
TomlError.x("each key-value declaration must be followed by an end-of-line", ctx);
|
|
1891
2018
|
}
|
|
1892
|
-
|
|
2019
|
+
skipVoid(ctx);
|
|
1893
2020
|
}
|
|
1894
2021
|
return res;
|
|
1895
2022
|
}
|
|
1896
2023
|
|
|
2024
|
+
// node_modules/.pnpm/smol-toml@1.9.0/node_modules/smol-toml/dist/stringify.js
|
|
2025
|
+
var HAS_WELLFORMED = !!"".isWellFormed;
|
|
2026
|
+
|
|
1897
2027
|
// src/utils/config-root-dir.ts
|
|
1898
2028
|
import os2 from "os";
|
|
1899
2029
|
import path3 from "path";
|
|
@@ -1944,7 +2074,8 @@ var USER_CONFIG_SOURCE_DIR_KEYS = [
|
|
|
1944
2074
|
"cline",
|
|
1945
2075
|
"roocode",
|
|
1946
2076
|
"kilocode",
|
|
1947
|
-
"antigravity"
|
|
2077
|
+
"antigravity",
|
|
2078
|
+
"dsh"
|
|
1948
2079
|
];
|
|
1949
2080
|
var knownTopLevelKeys = [
|
|
1950
2081
|
"eventStore",
|
|
@@ -2003,10 +2134,10 @@ function hasConfigPathOverride(env) {
|
|
|
2003
2134
|
function getLegacyJsonConfigPath(configPath) {
|
|
2004
2135
|
return path4.join(path4.dirname(configPath), "config.json");
|
|
2005
2136
|
}
|
|
2006
|
-
async function throwIfLegacyJsonConfigExists(tomlPath,
|
|
2137
|
+
async function throwIfLegacyJsonConfigExists(tomlPath, readFile9) {
|
|
2007
2138
|
const jsonPath = getLegacyJsonConfigPath(tomlPath);
|
|
2008
2139
|
try {
|
|
2009
|
-
await
|
|
2140
|
+
await readFile9(jsonPath);
|
|
2010
2141
|
} catch (error) {
|
|
2011
2142
|
if (isMissingFileError(error)) {
|
|
2012
2143
|
return;
|
|
@@ -2254,15 +2385,15 @@ function parseUserConfigRoot(filePath, content) {
|
|
|
2254
2385
|
}
|
|
2255
2386
|
return root;
|
|
2256
2387
|
}
|
|
2257
|
-
async function loadUserConfig(env = process.env,
|
|
2388
|
+
async function loadUserConfig(env = process.env, readFile9 = (filePath) => readFileFromFs(filePath, "utf8")) {
|
|
2258
2389
|
const configPath = resolveUserConfigPath(env);
|
|
2259
2390
|
let content;
|
|
2260
2391
|
try {
|
|
2261
|
-
content = await
|
|
2392
|
+
content = await readFile9(configPath);
|
|
2262
2393
|
} catch (error) {
|
|
2263
2394
|
if (isMissingFileError(error)) {
|
|
2264
2395
|
if (!hasConfigPathOverride(env)) {
|
|
2265
|
-
await throwIfLegacyJsonConfigExists(configPath,
|
|
2396
|
+
await throwIfLegacyJsonConfigExists(configPath, readFile9);
|
|
2266
2397
|
}
|
|
2267
2398
|
return {
|
|
2268
2399
|
config: {},
|
|
@@ -6781,16 +6912,310 @@ var DroidSourceAdapter = class {
|
|
|
6781
6912
|
}
|
|
6782
6913
|
};
|
|
6783
6914
|
|
|
6784
|
-
// src/sources/
|
|
6785
|
-
import
|
|
6915
|
+
// src/sources/dsh/dsh-source-adapter.ts
|
|
6916
|
+
import path17 from "path";
|
|
6917
|
+
|
|
6918
|
+
// src/sources/dsh/dsh-session-log-reader.ts
|
|
6919
|
+
import { readFile as readFile4 } from "fs/promises";
|
|
6920
|
+
import { Readable, Writable } from "stream";
|
|
6921
|
+
import { pipeline } from "stream/promises";
|
|
6922
|
+
import { createZstdDecompress } from "zlib";
|
|
6923
|
+
var DshSessionLogUnreadableError = class extends Error {
|
|
6924
|
+
constructor(message = "DSH session log could not be decompressed") {
|
|
6925
|
+
super(message);
|
|
6926
|
+
this.name = "DshSessionLogUnreadableError";
|
|
6927
|
+
}
|
|
6928
|
+
};
|
|
6929
|
+
var ZSTD_FRAME_MAGIC = Buffer.from([40, 181, 47, 253]);
|
|
6930
|
+
var UNDECODABLE_FRAME_REASON = "undecodable_jsonl_frame";
|
|
6931
|
+
function collectFrameSlices(compressed) {
|
|
6932
|
+
const frames = [];
|
|
6933
|
+
let damagedSlices = 0;
|
|
6934
|
+
let offset = 0;
|
|
6935
|
+
while (offset < compressed.length) {
|
|
6936
|
+
const nextOffset = compressed.indexOf(ZSTD_FRAME_MAGIC, offset + ZSTD_FRAME_MAGIC.length);
|
|
6937
|
+
const slice = nextOffset === -1 ? compressed.subarray(offset) : compressed.subarray(offset, nextOffset);
|
|
6938
|
+
if (slice.subarray(0, ZSTD_FRAME_MAGIC.length).equals(ZSTD_FRAME_MAGIC)) {
|
|
6939
|
+
frames.push(slice);
|
|
6940
|
+
} else {
|
|
6941
|
+
damagedSlices += 1;
|
|
6942
|
+
}
|
|
6943
|
+
if (nextOffset === -1) {
|
|
6944
|
+
break;
|
|
6945
|
+
}
|
|
6946
|
+
offset = nextOffset;
|
|
6947
|
+
}
|
|
6948
|
+
return { frames, damagedSlices };
|
|
6949
|
+
}
|
|
6950
|
+
async function decodeFrame(frameBytes) {
|
|
6951
|
+
const engine = createZstdDecompress();
|
|
6952
|
+
const chunks = [];
|
|
6953
|
+
await pipeline(
|
|
6954
|
+
Readable.from([frameBytes]),
|
|
6955
|
+
engine,
|
|
6956
|
+
new Writable({
|
|
6957
|
+
write(chunk, _encoding, callback) {
|
|
6958
|
+
chunks.push(chunk);
|
|
6959
|
+
callback();
|
|
6960
|
+
}
|
|
6961
|
+
})
|
|
6962
|
+
);
|
|
6963
|
+
const decoded = Buffer.concat(chunks);
|
|
6964
|
+
const frameConsumed = engine.bytesWritten === frameBytes.length;
|
|
6965
|
+
if (decoded.length === 0 || !frameConsumed) {
|
|
6966
|
+
throw new DshSessionLogUnreadableError("DSH session log frame is incomplete");
|
|
6967
|
+
}
|
|
6968
|
+
return decoded;
|
|
6969
|
+
}
|
|
6970
|
+
function splitJsonlLines(text) {
|
|
6971
|
+
const lines = [];
|
|
6972
|
+
for (const rawLine of text.split("\n")) {
|
|
6973
|
+
const line = rawLine.trim();
|
|
6974
|
+
if (line.length > 0) {
|
|
6975
|
+
lines.push(line);
|
|
6976
|
+
}
|
|
6977
|
+
}
|
|
6978
|
+
return lines;
|
|
6979
|
+
}
|
|
6980
|
+
async function readDshSessionLog(filePath) {
|
|
6981
|
+
const contents = await readFile4(filePath);
|
|
6982
|
+
if (!filePath.toLowerCase().endsWith(".zstd")) {
|
|
6983
|
+
return {
|
|
6984
|
+
lines: splitJsonlLines(contents.toString("utf8")),
|
|
6985
|
+
skippedRowReasons: []
|
|
6986
|
+
};
|
|
6987
|
+
}
|
|
6988
|
+
const lines = [];
|
|
6989
|
+
let decodedFrames = 0;
|
|
6990
|
+
const { frames, damagedSlices } = collectFrameSlices(contents);
|
|
6991
|
+
let undecodableFrames = damagedSlices;
|
|
6992
|
+
for (const frameBytes of frames) {
|
|
6993
|
+
try {
|
|
6994
|
+
const decoded = await decodeFrame(frameBytes);
|
|
6995
|
+
decodedFrames += 1;
|
|
6996
|
+
lines.push(...splitJsonlLines(decoded.toString("utf8")));
|
|
6997
|
+
} catch {
|
|
6998
|
+
undecodableFrames += 1;
|
|
6999
|
+
}
|
|
7000
|
+
}
|
|
7001
|
+
if (decodedFrames === 0) {
|
|
7002
|
+
throw new DshSessionLogUnreadableError();
|
|
7003
|
+
}
|
|
7004
|
+
return {
|
|
7005
|
+
lines,
|
|
7006
|
+
skippedRowReasons: undecodableFrames > 0 ? [{ reason: UNDECODABLE_FRAME_REASON, count: undecodableFrames }] : []
|
|
7007
|
+
};
|
|
7008
|
+
}
|
|
7009
|
+
|
|
7010
|
+
// src/sources/dsh/dsh-path-resolver.ts
|
|
6786
7011
|
import os11 from "os";
|
|
6787
7012
|
import path16 from "path";
|
|
6788
|
-
|
|
7013
|
+
function resolveDshHome(options) {
|
|
7014
|
+
const configuredHome = asTrimmedText(options.env.DSH_HOME);
|
|
7015
|
+
if (!configuredHome) {
|
|
7016
|
+
return path16.join(options.homeDir, ".dsh");
|
|
7017
|
+
}
|
|
7018
|
+
if (configuredHome === "~") {
|
|
7019
|
+
return options.homeDir;
|
|
7020
|
+
}
|
|
7021
|
+
if (configuredHome.startsWith("~/") || configuredHome.startsWith("~\\")) {
|
|
7022
|
+
return path16.join(options.homeDir, configuredHome.slice(2));
|
|
7023
|
+
}
|
|
7024
|
+
return configuredHome;
|
|
7025
|
+
}
|
|
7026
|
+
function getDefaultDshSessionsDir(options = {}) {
|
|
7027
|
+
const resolvedOptions = {
|
|
7028
|
+
env: options.env ?? process.env,
|
|
7029
|
+
homeDir: options.homeDir ?? os11.homedir()
|
|
7030
|
+
};
|
|
7031
|
+
return path16.join(resolveDshHome(resolvedOptions), "sessions");
|
|
7032
|
+
}
|
|
7033
|
+
|
|
7034
|
+
// src/sources/dsh/dsh-source-adapter.ts
|
|
7035
|
+
var DSH_SESSION_LOG_FILENAME_PATTERN = /^session(?:\.v[1-9][0-9]*)?\.jsonl(?:\.zstd)?$/u;
|
|
7036
|
+
var DSH_ASSISTANT_MESSAGE_LINE_PATTERN = /"type"\s*:\s*"assistant\/message"/u;
|
|
7037
|
+
var DSH_SESSION_LINE_PATTERN = /"type"\s*:\s*"session"/u;
|
|
7038
|
+
var DSH_TITLE_REQUEST_LINE_PATTERN = /"type"\s*:\s*"session\/title-llm-request"/u;
|
|
7039
|
+
function shouldParseDshJsonlLine(lineText) {
|
|
7040
|
+
return DSH_ASSISTANT_MESSAGE_LINE_PATTERN.test(lineText) || DSH_SESSION_LINE_PATTERN.test(lineText) || DSH_TITLE_REQUEST_LINE_PATTERN.test(lineText);
|
|
7041
|
+
}
|
|
7042
|
+
function isDshSessionLogFile(fileName) {
|
|
7043
|
+
return DSH_SESSION_LOG_FILENAME_PATTERN.test(fileName);
|
|
7044
|
+
}
|
|
7045
|
+
function getFallbackSessionId4(filePath) {
|
|
7046
|
+
const parentDirName = path17.basename(path17.dirname(filePath));
|
|
7047
|
+
if (parentDirName.startsWith("session-")) {
|
|
7048
|
+
return parentDirName;
|
|
7049
|
+
}
|
|
7050
|
+
return path17.basename(filePath).replace(/\.zstd$/u, "");
|
|
7051
|
+
}
|
|
7052
|
+
function resolveRoute(record) {
|
|
7053
|
+
const route = asRecord(record?.route) ?? record;
|
|
7054
|
+
return {
|
|
7055
|
+
provider: asTrimmedText(route?.provider),
|
|
7056
|
+
model: asTrimmedText(route?.model)
|
|
7057
|
+
};
|
|
7058
|
+
}
|
|
7059
|
+
function extractUsage2(usage) {
|
|
7060
|
+
const extracted = {
|
|
7061
|
+
inputTokens: toNumberLike(usage.inputTokens),
|
|
7062
|
+
outputTokens: toNumberLike(usage.outputTokens),
|
|
7063
|
+
reasoningTokens: toNumberLike(usage.reasoningTokens),
|
|
7064
|
+
cacheReadTokens: toNumberLike(usage.cacheReadTokens),
|
|
7065
|
+
cacheWriteTokens: toNumberLike(usage.cacheWriteTokens),
|
|
7066
|
+
totalTokens: toNumberLike(usage.totalTokens)
|
|
7067
|
+
};
|
|
7068
|
+
const usageCandidates = [
|
|
7069
|
+
extracted.inputTokens,
|
|
7070
|
+
extracted.outputTokens,
|
|
7071
|
+
extracted.reasoningTokens,
|
|
7072
|
+
extracted.cacheReadTokens,
|
|
7073
|
+
extracted.cacheWriteTokens,
|
|
7074
|
+
extracted.totalTokens
|
|
7075
|
+
];
|
|
7076
|
+
return hasPositiveUsageOrCostSignal(usageCandidates, void 0) ? extracted : void 0;
|
|
7077
|
+
}
|
|
7078
|
+
function resolveTimestamp3(line) {
|
|
7079
|
+
const time = line.time;
|
|
7080
|
+
if (typeof time !== "number" || !Number.isFinite(time)) {
|
|
7081
|
+
return void 0;
|
|
7082
|
+
}
|
|
7083
|
+
const date = new Date(time);
|
|
7084
|
+
return Number.isNaN(date.getTime()) ? void 0 : date.toISOString();
|
|
7085
|
+
}
|
|
7086
|
+
var DshSourceAdapter = class {
|
|
7087
|
+
id = "dsh";
|
|
7088
|
+
rootDirs;
|
|
7089
|
+
requireDir;
|
|
7090
|
+
constructor(options = {}) {
|
|
7091
|
+
this.rootDirs = resolveRootDirs(
|
|
7092
|
+
options.dir,
|
|
7093
|
+
options.defaultRootDirs ?? [
|
|
7094
|
+
getDefaultDshSessionsDir({ env: options.env, homeDir: options.homeDir })
|
|
7095
|
+
]
|
|
7096
|
+
);
|
|
7097
|
+
this.requireDir = options.requireDir ?? false;
|
|
7098
|
+
}
|
|
7099
|
+
async discoverFiles() {
|
|
7100
|
+
return discoverFilesAcrossRoots({
|
|
7101
|
+
rootDirs: this.rootDirs,
|
|
7102
|
+
requireDir: this.requireDir,
|
|
7103
|
+
directoryLabel: "DSH sessions directory",
|
|
7104
|
+
sortAcrossRoots: true,
|
|
7105
|
+
discoverInRoot: async (rootDir) => {
|
|
7106
|
+
const discovered = [
|
|
7107
|
+
...await discoverFiles(rootDir, { extension: ".jsonl" }),
|
|
7108
|
+
...await discoverFiles(rootDir, { extension: ".jsonl.zstd" })
|
|
7109
|
+
];
|
|
7110
|
+
return discovered.filter((filePath) => isDshSessionLogFile(path17.basename(filePath)));
|
|
7111
|
+
}
|
|
7112
|
+
});
|
|
7113
|
+
}
|
|
7114
|
+
async parseFile(filePath) {
|
|
7115
|
+
const { events } = await this.parseFileWithDiagnostics(filePath);
|
|
7116
|
+
return events;
|
|
7117
|
+
}
|
|
7118
|
+
async parseFileWithDiagnostics(filePath) {
|
|
7119
|
+
const events = [];
|
|
7120
|
+
const skippedRowReasons = /* @__PURE__ */ new Map();
|
|
7121
|
+
const state = { sessionId: getFallbackSessionId4(filePath) };
|
|
7122
|
+
let skippedRows = 0;
|
|
7123
|
+
let log;
|
|
7124
|
+
try {
|
|
7125
|
+
log = await readDshSessionLog(filePath);
|
|
7126
|
+
} catch (error) {
|
|
7127
|
+
if (error instanceof DshSessionLogUnreadableError) {
|
|
7128
|
+
return toParseDiagnostics(events, 1, /* @__PURE__ */ new Map([["file_parse_failed", 1]]));
|
|
7129
|
+
}
|
|
7130
|
+
throw error;
|
|
7131
|
+
}
|
|
7132
|
+
for (const reasonStat of log.skippedRowReasons) {
|
|
7133
|
+
incrementSkippedReason(skippedRowReasons, reasonStat.reason);
|
|
7134
|
+
skippedRows += reasonStat.count;
|
|
7135
|
+
}
|
|
7136
|
+
for (const lineText of log.lines) {
|
|
7137
|
+
if (!shouldParseDshJsonlLine(lineText)) {
|
|
7138
|
+
continue;
|
|
7139
|
+
}
|
|
7140
|
+
let line;
|
|
7141
|
+
try {
|
|
7142
|
+
const parsedLine = asRecord(JSON.parse(lineText));
|
|
7143
|
+
if (!parsedLine) {
|
|
7144
|
+
continue;
|
|
7145
|
+
}
|
|
7146
|
+
line = parsedLine;
|
|
7147
|
+
} catch {
|
|
7148
|
+
skippedRows++;
|
|
7149
|
+
incrementSkippedReason(skippedRowReasons, "json_parse_error");
|
|
7150
|
+
continue;
|
|
7151
|
+
}
|
|
7152
|
+
if (line.type === "session") {
|
|
7153
|
+
state.sessionId = asTrimmedText(line.id) ?? state.sessionId;
|
|
7154
|
+
state.repoRoot = asTrimmedText(line.cwd) ?? state.repoRoot;
|
|
7155
|
+
continue;
|
|
7156
|
+
}
|
|
7157
|
+
if (line.type === "session/title-llm-request") {
|
|
7158
|
+
const route = resolveRoute(asRecord(line.data));
|
|
7159
|
+
state.provider = route.provider ?? state.provider;
|
|
7160
|
+
state.model = route.model ?? state.model;
|
|
7161
|
+
continue;
|
|
7162
|
+
}
|
|
7163
|
+
if (line.type !== "assistant/message") {
|
|
7164
|
+
continue;
|
|
7165
|
+
}
|
|
7166
|
+
const data = asRecord(line.data);
|
|
7167
|
+
const message = asRecord(data?.message);
|
|
7168
|
+
const usage = asRecord(data?.usage);
|
|
7169
|
+
if (!usage) {
|
|
7170
|
+
continue;
|
|
7171
|
+
}
|
|
7172
|
+
const extractedUsage = extractUsage2(usage);
|
|
7173
|
+
if (!extractedUsage) {
|
|
7174
|
+
skippedRows++;
|
|
7175
|
+
incrementSkippedReason(skippedRowReasons, "no_token_usage");
|
|
7176
|
+
continue;
|
|
7177
|
+
}
|
|
7178
|
+
const timestamp = resolveTimestamp3(line);
|
|
7179
|
+
if (!timestamp || !state.sessionId) {
|
|
7180
|
+
skippedRows++;
|
|
7181
|
+
incrementSkippedReason(skippedRowReasons, "invalid_timestamp");
|
|
7182
|
+
continue;
|
|
7183
|
+
}
|
|
7184
|
+
const source = asRecord(message?.source);
|
|
7185
|
+
const provider = asTrimmedText(source?.provider) ?? state.provider;
|
|
7186
|
+
const model = asTrimmedText(source?.model) ?? state.model;
|
|
7187
|
+
try {
|
|
7188
|
+
events.push(
|
|
7189
|
+
createUsageEvent({
|
|
7190
|
+
source: this.id,
|
|
7191
|
+
sessionId: state.sessionId,
|
|
7192
|
+
timestamp,
|
|
7193
|
+
repoRoot: state.repoRoot,
|
|
7194
|
+
provider,
|
|
7195
|
+
model,
|
|
7196
|
+
...extractedUsage
|
|
7197
|
+
})
|
|
7198
|
+
);
|
|
7199
|
+
} catch {
|
|
7200
|
+
skippedRows++;
|
|
7201
|
+
incrementSkippedReason(skippedRowReasons, "event_creation_failed");
|
|
7202
|
+
continue;
|
|
7203
|
+
}
|
|
7204
|
+
}
|
|
7205
|
+
return toParseDiagnostics(events, skippedRows, skippedRowReasons);
|
|
7206
|
+
}
|
|
7207
|
+
};
|
|
7208
|
+
|
|
7209
|
+
// src/sources/gemini/gemini-source-adapter.ts
|
|
7210
|
+
import { readdir as readdir2, readFile as readFile5 } from "fs/promises";
|
|
7211
|
+
import os12 from "os";
|
|
7212
|
+
import path18 from "path";
|
|
7213
|
+
var defaultGeminiDir = path18.join(os12.homedir(), ".gemini");
|
|
6789
7214
|
function resolveDefaultGeminiDir(env) {
|
|
6790
7215
|
return asTrimmedText(env.GEMINI_CLI_HOME) ?? defaultGeminiDir;
|
|
6791
7216
|
}
|
|
6792
7217
|
function getProjectsJsonPath(geminiDir) {
|
|
6793
|
-
return
|
|
7218
|
+
return path18.join(geminiDir, "projects.json");
|
|
6794
7219
|
}
|
|
6795
7220
|
function parseProjectsJson(data) {
|
|
6796
7221
|
const mapping = /* @__PURE__ */ new Map();
|
|
@@ -6814,7 +7239,7 @@ function parseProjectsJson(data) {
|
|
|
6814
7239
|
async function loadProjectsJson(geminiDir) {
|
|
6815
7240
|
const projectsPath = getProjectsJsonPath(geminiDir);
|
|
6816
7241
|
try {
|
|
6817
|
-
const content = await
|
|
7242
|
+
const content = await readFile5(projectsPath, "utf8");
|
|
6818
7243
|
const parsed = JSON.parse(content);
|
|
6819
7244
|
return parseProjectsJson(parsed);
|
|
6820
7245
|
} catch (error) {
|
|
@@ -6825,7 +7250,7 @@ async function loadProjectsJson(geminiDir) {
|
|
|
6825
7250
|
}
|
|
6826
7251
|
}
|
|
6827
7252
|
async function discoverSessionFiles(geminiDir) {
|
|
6828
|
-
const tmpDir =
|
|
7253
|
+
const tmpDir = path18.join(geminiDir, "tmp");
|
|
6829
7254
|
let projectEntries;
|
|
6830
7255
|
try {
|
|
6831
7256
|
projectEntries = await readdir2(tmpDir, { withFileTypes: true, encoding: "utf8" });
|
|
@@ -6842,7 +7267,7 @@ async function discoverSessionFiles(geminiDir) {
|
|
|
6842
7267
|
if (!projectEntry.isDirectory() && !projectEntry.isSymbolicLink()) {
|
|
6843
7268
|
continue;
|
|
6844
7269
|
}
|
|
6845
|
-
const chatsDir =
|
|
7270
|
+
const chatsDir = path18.join(tmpDir, projectEntry.name, "chats");
|
|
6846
7271
|
const discoveredChatFiles = await discoverFiles(chatsDir, { extension: ".json" });
|
|
6847
7272
|
allSessionFiles.push(...discoveredChatFiles);
|
|
6848
7273
|
}
|
|
@@ -6856,9 +7281,9 @@ function resolveRepoRoot(filePath, sessionData, projectMapping) {
|
|
|
6856
7281
|
return mappedRoot;
|
|
6857
7282
|
}
|
|
6858
7283
|
}
|
|
6859
|
-
const chatsDir =
|
|
6860
|
-
const projectDir =
|
|
6861
|
-
const projectIdentifier =
|
|
7284
|
+
const chatsDir = path18.dirname(filePath);
|
|
7285
|
+
const projectDir = path18.dirname(chatsDir);
|
|
7286
|
+
const projectIdentifier = path18.basename(projectDir);
|
|
6862
7287
|
return projectMapping.get(projectIdentifier);
|
|
6863
7288
|
}
|
|
6864
7289
|
function toFiniteNumber3(value) {
|
|
@@ -6967,7 +7392,7 @@ var GeminiSourceAdapter = class {
|
|
|
6967
7392
|
incrementSkippedReason(skippedRowReasons, "invalid_session_data");
|
|
6968
7393
|
return toParseDiagnostics(events, skippedRows, skippedRowReasons);
|
|
6969
7394
|
}
|
|
6970
|
-
const sessionId = asTrimmedText(sessionDataRecord.sessionId) ??
|
|
7395
|
+
const sessionId = asTrimmedText(sessionDataRecord.sessionId) ?? path18.basename(filePath, ".json");
|
|
6971
7396
|
const projectMapping = await this.getProjectMappingForParse();
|
|
6972
7397
|
const repoRoot = resolveRepoRoot(filePath, sessionDataRecord, projectMapping);
|
|
6973
7398
|
if (!Array.isArray(sessionDataRecord.messages)) {
|
|
@@ -7024,8 +7449,8 @@ var GeminiSourceAdapter = class {
|
|
|
7024
7449
|
};
|
|
7025
7450
|
|
|
7026
7451
|
// src/sources/goose/goose-db-path-resolver.ts
|
|
7027
|
-
import
|
|
7028
|
-
import
|
|
7452
|
+
import os13 from "os";
|
|
7453
|
+
import path19 from "path";
|
|
7029
7454
|
function deduplicate(paths) {
|
|
7030
7455
|
return [...new Set(paths)];
|
|
7031
7456
|
}
|
|
@@ -7037,36 +7462,36 @@ function normalizeEnvPath3(value) {
|
|
|
7037
7462
|
return normalized || void 0;
|
|
7038
7463
|
}
|
|
7039
7464
|
function getGooseDbPath(rootDir) {
|
|
7040
|
-
return
|
|
7465
|
+
return path19.join(rootDir, "goose", "sessions", "sessions.db");
|
|
7041
7466
|
}
|
|
7042
7467
|
function getLinuxLikeCandidates(homeDir, env) {
|
|
7043
|
-
const xdgDataHome = normalizeEnvPath3(env.XDG_DATA_HOME) ??
|
|
7468
|
+
const xdgDataHome = normalizeEnvPath3(env.XDG_DATA_HOME) ?? path19.join(homeDir, ".local", "share");
|
|
7044
7469
|
return [
|
|
7045
7470
|
getGooseDbPath(xdgDataHome),
|
|
7046
|
-
|
|
7471
|
+
path19.join(homeDir, ".local", "share", "Block", "goose", "sessions", "sessions.db")
|
|
7047
7472
|
];
|
|
7048
7473
|
}
|
|
7049
7474
|
function getMacOsCandidates(homeDir) {
|
|
7050
7475
|
return [
|
|
7051
|
-
|
|
7052
|
-
|
|
7476
|
+
path19.join(homeDir, "Library", "Application Support", "goose", "sessions", "sessions.db"),
|
|
7477
|
+
path19.join(homeDir, ".local", "share", "Block", "goose", "sessions", "sessions.db")
|
|
7053
7478
|
];
|
|
7054
7479
|
}
|
|
7055
7480
|
function getWindowsCandidates(homeDir, env) {
|
|
7056
7481
|
const userProfile = normalizeEnvPath3(env.USERPROFILE);
|
|
7057
|
-
const roamingBase = normalizeEnvPath3(env.APPDATA) ?? normalizeEnvPath3(env.LOCALAPPDATA) ?? (userProfile ?
|
|
7482
|
+
const roamingBase = normalizeEnvPath3(env.APPDATA) ?? normalizeEnvPath3(env.LOCALAPPDATA) ?? (userProfile ? path19.join(userProfile, "AppData", "Roaming") : void 0);
|
|
7058
7483
|
const roamingCandidates = roamingBase ? [getGooseDbPath(roamingBase)] : [];
|
|
7059
7484
|
return [
|
|
7060
7485
|
...roamingCandidates,
|
|
7061
|
-
|
|
7486
|
+
path19.join(homeDir, ".local", "share", "Block", "goose", "sessions", "sessions.db")
|
|
7062
7487
|
];
|
|
7063
7488
|
}
|
|
7064
7489
|
function getDefaultGooseDbPathCandidates(options = {}) {
|
|
7065
7490
|
const platform = options.platform ?? process.platform;
|
|
7066
|
-
const homeDir = options.homeDir ??
|
|
7491
|
+
const homeDir = options.homeDir ?? os13.homedir();
|
|
7067
7492
|
const env = options.env ?? process.env;
|
|
7068
7493
|
const goosePathRoot = normalizeEnvPath3(env.GOOSE_PATH_ROOT);
|
|
7069
|
-
const envCandidates = goosePathRoot ? [
|
|
7494
|
+
const envCandidates = goosePathRoot ? [path19.join(goosePathRoot, "data", "sessions", "sessions.db")] : [];
|
|
7070
7495
|
switch (platform) {
|
|
7071
7496
|
case "win32":
|
|
7072
7497
|
return deduplicate([...envCandidates, ...getWindowsCandidates(homeDir, env)]);
|
|
@@ -7255,11 +7680,11 @@ var GooseSourceAdapter = class {
|
|
|
7255
7680
|
};
|
|
7256
7681
|
|
|
7257
7682
|
// src/sources/kimi/kimi-source-adapter.ts
|
|
7258
|
-
import { readFile as
|
|
7259
|
-
import
|
|
7260
|
-
import
|
|
7261
|
-
var defaultKimiCliSessionsDir =
|
|
7262
|
-
var defaultKimiCodeSessionsDir =
|
|
7683
|
+
import { readFile as readFile6 } from "fs/promises";
|
|
7684
|
+
import os14 from "os";
|
|
7685
|
+
import path20 from "path";
|
|
7686
|
+
var defaultKimiCliSessionsDir = path20.join(os14.homedir(), ".kimi", "sessions");
|
|
7687
|
+
var defaultKimiCodeSessionsDir = path20.join(os14.homedir(), ".kimi-code", "sessions");
|
|
7263
7688
|
var defaultRootDirs = [defaultKimiCliSessionsDir, defaultKimiCodeSessionsDir];
|
|
7264
7689
|
var KIMI_STATUS_UPDATE_LINE_TEXT = '"StatusUpdate"';
|
|
7265
7690
|
var KIMI_USAGE_RECORD_LINE_TEXT = '"usage.record"';
|
|
@@ -7306,18 +7731,18 @@ function incrementContextSkippedReason3(context, reason) {
|
|
|
7306
7731
|
incrementSkippedReason(context.skippedRowReasons, reason);
|
|
7307
7732
|
}
|
|
7308
7733
|
function getCliSessionId(filePath) {
|
|
7309
|
-
return
|
|
7734
|
+
return path20.basename(path20.dirname(filePath));
|
|
7310
7735
|
}
|
|
7311
7736
|
function getCliConfigPath(filePath) {
|
|
7312
|
-
const sessionsDir =
|
|
7313
|
-
return
|
|
7737
|
+
const sessionsDir = path20.dirname(path20.dirname(path20.dirname(filePath)));
|
|
7738
|
+
return path20.join(path20.dirname(sessionsDir), "config.json");
|
|
7314
7739
|
}
|
|
7315
7740
|
function isCodeWireFile(filePath) {
|
|
7316
|
-
return
|
|
7741
|
+
return path20.basename(path20.dirname(path20.dirname(filePath))) === "agents";
|
|
7317
7742
|
}
|
|
7318
7743
|
async function readCliConfigModel(filePath) {
|
|
7319
7744
|
try {
|
|
7320
|
-
const content = await
|
|
7745
|
+
const content = await readFile6(getCliConfigPath(filePath), "utf8");
|
|
7321
7746
|
return asTrimmedText(asRecord(JSON.parse(content))?.model);
|
|
7322
7747
|
} catch {
|
|
7323
7748
|
return void 0;
|
|
@@ -7327,10 +7752,10 @@ function getCliFallbackModel(timestamp) {
|
|
|
7327
7752
|
return Date.parse(timestamp) < KIMI_K2_6_CUTOFF_MS ? KIMI_K2_5_MODEL : KIMI_K2_6_MODEL;
|
|
7328
7753
|
}
|
|
7329
7754
|
function getCodeSessionId(filePath) {
|
|
7330
|
-
const agentDir =
|
|
7331
|
-
const agentsDir =
|
|
7332
|
-
const sessionDir =
|
|
7333
|
-
return
|
|
7755
|
+
const agentDir = path20.dirname(filePath);
|
|
7756
|
+
const agentsDir = path20.dirname(agentDir);
|
|
7757
|
+
const sessionDir = path20.dirname(agentsDir);
|
|
7758
|
+
return path20.basename(sessionDir);
|
|
7334
7759
|
}
|
|
7335
7760
|
function normalizeKimiCodeModel(model) {
|
|
7336
7761
|
const normalizedModel = asTrimmedText(model);
|
|
@@ -7431,7 +7856,7 @@ function parseUsageRecordLine(context, filePath, line) {
|
|
|
7431
7856
|
}
|
|
7432
7857
|
async function discoverWireFiles(rootDir) {
|
|
7433
7858
|
const jsonlFiles = await discoverFiles(rootDir, { extension: ".jsonl" });
|
|
7434
|
-
return jsonlFiles.filter((filePath) =>
|
|
7859
|
+
return jsonlFiles.filter((filePath) => path20.basename(filePath) === "wire.jsonl");
|
|
7435
7860
|
}
|
|
7436
7861
|
var KimiSourceAdapter = class {
|
|
7437
7862
|
id = "kimi";
|
|
@@ -7492,8 +7917,8 @@ var KimiSourceAdapter = class {
|
|
|
7492
7917
|
|
|
7493
7918
|
// src/sources/opencode/opencode-db-path-resolver.ts
|
|
7494
7919
|
import { readdirSync } from "fs";
|
|
7495
|
-
import
|
|
7496
|
-
import
|
|
7920
|
+
import os15 from "os";
|
|
7921
|
+
import path21 from "path";
|
|
7497
7922
|
var CHANNEL_DB_FILE_PATTERN = /^opencode-.+\.db$/u;
|
|
7498
7923
|
function deduplicate2(paths) {
|
|
7499
7924
|
return [...new Set(paths)];
|
|
@@ -7516,34 +7941,34 @@ function listChannelDbFileNames(directory) {
|
|
|
7516
7941
|
}
|
|
7517
7942
|
function getDirectoryCandidates(directory) {
|
|
7518
7943
|
return [
|
|
7519
|
-
|
|
7520
|
-
...listChannelDbFileNames(directory).map((fileName) =>
|
|
7521
|
-
|
|
7944
|
+
path21.join(directory, "opencode.db"),
|
|
7945
|
+
...listChannelDbFileNames(directory).map((fileName) => path21.join(directory, fileName)),
|
|
7946
|
+
path21.join(directory, "db.sqlite")
|
|
7522
7947
|
];
|
|
7523
7948
|
}
|
|
7524
7949
|
function getLinuxLikeCandidates2(homeDir, env) {
|
|
7525
|
-
const xdgDataHome = normalizeEnvPath4(env.XDG_DATA_HOME) ??
|
|
7950
|
+
const xdgDataHome = normalizeEnvPath4(env.XDG_DATA_HOME) ?? path21.join(homeDir, ".local", "share");
|
|
7526
7951
|
return [
|
|
7527
|
-
...getDirectoryCandidates(
|
|
7528
|
-
...getDirectoryCandidates(
|
|
7952
|
+
...getDirectoryCandidates(path21.join(xdgDataHome, "opencode")),
|
|
7953
|
+
...getDirectoryCandidates(path21.join(homeDir, ".opencode"))
|
|
7529
7954
|
];
|
|
7530
7955
|
}
|
|
7531
7956
|
function getMacOsCandidates2(homeDir) {
|
|
7532
|
-
const appSupportDir =
|
|
7957
|
+
const appSupportDir = path21.join(homeDir, "Library", "Application Support");
|
|
7533
7958
|
return [
|
|
7534
|
-
...getDirectoryCandidates(
|
|
7535
|
-
...getDirectoryCandidates(
|
|
7959
|
+
...getDirectoryCandidates(path21.join(appSupportDir, "opencode")),
|
|
7960
|
+
...getDirectoryCandidates(path21.join(homeDir, ".opencode"))
|
|
7536
7961
|
];
|
|
7537
7962
|
}
|
|
7538
7963
|
function getWindowsCandidates2(homeDir, env) {
|
|
7539
7964
|
const userProfile = normalizeEnvPath4(env.USERPROFILE);
|
|
7540
|
-
const roamingBase = normalizeEnvPath4(env.APPDATA) ?? normalizeEnvPath4(env.LOCALAPPDATA) ?? (userProfile ?
|
|
7541
|
-
const roamingCandidates = roamingBase ? getDirectoryCandidates(
|
|
7542
|
-
return [...roamingCandidates, ...getDirectoryCandidates(
|
|
7965
|
+
const roamingBase = normalizeEnvPath4(env.APPDATA) ?? normalizeEnvPath4(env.LOCALAPPDATA) ?? (userProfile ? path21.join(userProfile, "AppData", "Roaming") : void 0);
|
|
7966
|
+
const roamingCandidates = roamingBase ? getDirectoryCandidates(path21.join(roamingBase, "opencode")) : [];
|
|
7967
|
+
return [...roamingCandidates, ...getDirectoryCandidates(path21.join(homeDir, ".opencode"))];
|
|
7543
7968
|
}
|
|
7544
7969
|
function getDefaultOpenCodeDbPathCandidates(options = {}) {
|
|
7545
7970
|
const platform = options.platform ?? process.platform;
|
|
7546
|
-
const homeDir = options.homeDir ??
|
|
7971
|
+
const homeDir = options.homeDir ?? os15.homedir();
|
|
7547
7972
|
const env = options.env ?? process.env;
|
|
7548
7973
|
switch (platform) {
|
|
7549
7974
|
case "win32":
|
|
@@ -7556,7 +7981,7 @@ function getDefaultOpenCodeDbPathCandidates(options = {}) {
|
|
|
7556
7981
|
}
|
|
7557
7982
|
|
|
7558
7983
|
// src/sources/opencode/opencode-row-parser.ts
|
|
7559
|
-
function
|
|
7984
|
+
function resolveTimestamp4(rowTimestamp, messagePayload) {
|
|
7560
7985
|
const timestampCandidates = [
|
|
7561
7986
|
rowTimestamp,
|
|
7562
7987
|
messagePayload.timestamp,
|
|
@@ -7634,7 +8059,7 @@ function parseOpenCodeMessageRows(rows, sourceId) {
|
|
|
7634
8059
|
if (role?.toLowerCase() !== "assistant") {
|
|
7635
8060
|
continue;
|
|
7636
8061
|
}
|
|
7637
|
-
const timestamp =
|
|
8062
|
+
const timestamp = resolveTimestamp4(row.row_time, payload);
|
|
7638
8063
|
if (!timestamp) {
|
|
7639
8064
|
recordSkippedRow("missing_timestamp");
|
|
7640
8065
|
continue;
|
|
@@ -7979,11 +8404,11 @@ var OpenCodeSourceAdapter = class {
|
|
|
7979
8404
|
};
|
|
7980
8405
|
|
|
7981
8406
|
// src/sources/openclaw/openclaw-source-adapter.ts
|
|
7982
|
-
import
|
|
7983
|
-
import
|
|
8407
|
+
import os16 from "os";
|
|
8408
|
+
import path23 from "path";
|
|
7984
8409
|
|
|
7985
8410
|
// src/sources/openclaw/openclaw-session-parser.ts
|
|
7986
|
-
import
|
|
8411
|
+
import path22 from "path";
|
|
7987
8412
|
var SESSION_LINE_PATTERN = /"type"\s*:\s*"session"/u;
|
|
7988
8413
|
var MESSAGE_LINE_PATTERN = /"type"\s*:\s*"message"/u;
|
|
7989
8414
|
var MODEL_CHANGE_LINE_PATTERN = /"type"\s*:\s*"model_change"/u;
|
|
@@ -7993,8 +8418,8 @@ var PROVIDER_LINE_PATTERN = /"provider"\s*:/u;
|
|
|
7993
8418
|
function shouldParseOpenClawJsonlLine(lineText) {
|
|
7994
8419
|
return SESSION_LINE_PATTERN.test(lineText) || MESSAGE_LINE_PATTERN.test(lineText) || MODEL_CHANGE_LINE_PATTERN.test(lineText) || USAGE_LINE_PATTERN.test(lineText) || MODEL_LINE_PATTERN.test(lineText) || PROVIDER_LINE_PATTERN.test(lineText);
|
|
7995
8420
|
}
|
|
7996
|
-
function
|
|
7997
|
-
return
|
|
8421
|
+
function getFallbackSessionId5(filePath) {
|
|
8422
|
+
return path22.basename(filePath, ".jsonl");
|
|
7998
8423
|
}
|
|
7999
8424
|
function resolveRepoRootFromRecord(record) {
|
|
8000
8425
|
if (!record) {
|
|
@@ -8060,14 +8485,14 @@ function mergeUsageExtracts(primary, fallback) {
|
|
|
8060
8485
|
costUsd: primary.costUsd ?? fallback.costUsd
|
|
8061
8486
|
};
|
|
8062
8487
|
}
|
|
8063
|
-
function
|
|
8488
|
+
function extractUsage3(line, message) {
|
|
8064
8489
|
const lineUsage = asRecord(line.usage);
|
|
8065
8490
|
const messageUsage = asRecord(message.usage);
|
|
8066
8491
|
const extractedLineUsage = lineUsage ? extractUsageFromRecord(lineUsage) : void 0;
|
|
8067
8492
|
const extractedMessageUsage = messageUsage ? extractUsageFromRecord(messageUsage) : void 0;
|
|
8068
8493
|
return mergeUsageExtracts(extractedLineUsage, extractedMessageUsage);
|
|
8069
8494
|
}
|
|
8070
|
-
function
|
|
8495
|
+
function resolveTimestamp5(line, message, state, fallbackTimestamp) {
|
|
8071
8496
|
const candidates = [line.timestamp, message.timestamp, fallbackTimestamp, state.sessionTimestamp];
|
|
8072
8497
|
for (const candidate of candidates) {
|
|
8073
8498
|
const normalizedTimestamp = normalizeTimestampCandidate(candidate);
|
|
@@ -8103,7 +8528,7 @@ async function parseOpenClawSessionFile(sourceId, filePath) {
|
|
|
8103
8528
|
const fileStats = await pathStat(filePath);
|
|
8104
8529
|
const fallbackTimestamp = fileStats?.mtime.toISOString();
|
|
8105
8530
|
const state = {
|
|
8106
|
-
sessionId:
|
|
8531
|
+
sessionId: getFallbackSessionId5(filePath)
|
|
8107
8532
|
};
|
|
8108
8533
|
for await (const line of readJsonlObjects(filePath, {
|
|
8109
8534
|
shouldParseLine: shouldParseOpenClawJsonlLine,
|
|
@@ -8149,11 +8574,11 @@ async function parseOpenClawSessionFile(sourceId, filePath) {
|
|
|
8149
8574
|
updateRuntimeStateFromRecord(state, line, message);
|
|
8150
8575
|
const provider = rowProvider ?? state.provider;
|
|
8151
8576
|
const model = rowModel ?? state.model;
|
|
8152
|
-
const usage =
|
|
8577
|
+
const usage = extractUsage3(line, message);
|
|
8153
8578
|
if (!usage) {
|
|
8154
8579
|
continue;
|
|
8155
8580
|
}
|
|
8156
|
-
const timestamp =
|
|
8581
|
+
const timestamp = resolveTimestamp5(line, message, state, fallbackTimestamp);
|
|
8157
8582
|
if (!timestamp) {
|
|
8158
8583
|
continue;
|
|
8159
8584
|
}
|
|
@@ -8179,12 +8604,12 @@ async function parseOpenClawSessionFile(sourceId, filePath) {
|
|
|
8179
8604
|
}
|
|
8180
8605
|
|
|
8181
8606
|
// src/sources/openclaw/openclaw-source-adapter.ts
|
|
8182
|
-
var defaultAgentsDir =
|
|
8607
|
+
var defaultAgentsDir = path23.join(os16.homedir(), ".openclaw", "agents");
|
|
8183
8608
|
var defaultOpenClawRootDirs = [
|
|
8184
8609
|
defaultAgentsDir,
|
|
8185
|
-
|
|
8186
|
-
|
|
8187
|
-
|
|
8610
|
+
path23.join(os16.homedir(), ".clawdbot", "agents"),
|
|
8611
|
+
path23.join(os16.homedir(), ".moltbot", "agents"),
|
|
8612
|
+
path23.join(os16.homedir(), ".moldbot", "agents")
|
|
8188
8613
|
];
|
|
8189
8614
|
var OpenClawSourceAdapter = class {
|
|
8190
8615
|
id = "openclaw";
|
|
@@ -8214,12 +8639,12 @@ var OpenClawSourceAdapter = class {
|
|
|
8214
8639
|
};
|
|
8215
8640
|
|
|
8216
8641
|
// src/sources/pi/pi-source-adapter.ts
|
|
8217
|
-
import
|
|
8218
|
-
import
|
|
8219
|
-
var defaultSessionsDir3 =
|
|
8642
|
+
import os17 from "os";
|
|
8643
|
+
import path24 from "path";
|
|
8644
|
+
var defaultSessionsDir3 = path24.join(os17.homedir(), ".pi", "agent", "sessions");
|
|
8220
8645
|
var defaultPiRootDirs = [
|
|
8221
8646
|
defaultSessionsDir3,
|
|
8222
|
-
|
|
8647
|
+
path24.join(os17.homedir(), ".omp", "agent", "sessions")
|
|
8223
8648
|
];
|
|
8224
8649
|
var PI_MESSAGE_LINE_PATTERN = /"type"\s*:\s*"message"/u;
|
|
8225
8650
|
var PI_SESSION_LINE_PATTERN = /"type"\s*:\s*"session"/u;
|
|
@@ -8227,7 +8652,7 @@ var PI_MODEL_CHANGE_LINE_PATTERN = /"type"\s*:\s*"model_change"/u;
|
|
|
8227
8652
|
function shouldParsePiJsonlLine(lineText) {
|
|
8228
8653
|
return PI_MESSAGE_LINE_PATTERN.test(lineText) || PI_SESSION_LINE_PATTERN.test(lineText) || PI_MODEL_CHANGE_LINE_PATTERN.test(lineText);
|
|
8229
8654
|
}
|
|
8230
|
-
function
|
|
8655
|
+
function resolveTimestamp6(line, message, state) {
|
|
8231
8656
|
const candidates = [line.timestamp, message?.timestamp, state.sessionTimestamp];
|
|
8232
8657
|
for (const candidate of candidates) {
|
|
8233
8658
|
const normalizedTimestamp = normalizeTimestampCandidate(candidate);
|
|
@@ -8260,7 +8685,7 @@ function extractUsageFromRecord2(usage) {
|
|
|
8260
8685
|
];
|
|
8261
8686
|
return hasPositiveUsageOrCostSignal(usageCandidates, extracted.costUsd) ? extracted : void 0;
|
|
8262
8687
|
}
|
|
8263
|
-
function
|
|
8688
|
+
function extractUsage4(line, message) {
|
|
8264
8689
|
const lineUsage = asRecord(line.usage);
|
|
8265
8690
|
const messageUsage = asRecord(message?.usage);
|
|
8266
8691
|
if (lineUsage) {
|
|
@@ -8274,8 +8699,8 @@ function extractUsage3(line, message) {
|
|
|
8274
8699
|
}
|
|
8275
8700
|
return extractUsageFromRecord2(messageUsage);
|
|
8276
8701
|
}
|
|
8277
|
-
function
|
|
8278
|
-
return
|
|
8702
|
+
function getFallbackSessionId6(filePath) {
|
|
8703
|
+
return path24.basename(filePath, ".jsonl");
|
|
8279
8704
|
}
|
|
8280
8705
|
function resolveRepoRootFromRecord2(record) {
|
|
8281
8706
|
if (!record) {
|
|
@@ -8308,7 +8733,7 @@ var PiSourceAdapter = class {
|
|
|
8308
8733
|
const events = [];
|
|
8309
8734
|
let skippedRows = 0;
|
|
8310
8735
|
const skippedRowReasons = /* @__PURE__ */ new Map();
|
|
8311
|
-
const state = { sessionId:
|
|
8736
|
+
const state = { sessionId: getFallbackSessionId6(filePath) };
|
|
8312
8737
|
for await (const line of readJsonlObjects(filePath, {
|
|
8313
8738
|
shouldParseLine: shouldParsePiJsonlLine,
|
|
8314
8739
|
onMalformedLine: () => {
|
|
@@ -8332,7 +8757,7 @@ var PiSourceAdapter = class {
|
|
|
8332
8757
|
continue;
|
|
8333
8758
|
}
|
|
8334
8759
|
const message = asRecord(line.message);
|
|
8335
|
-
const usage =
|
|
8760
|
+
const usage = extractUsage4(line, message);
|
|
8336
8761
|
if (!usage) {
|
|
8337
8762
|
const hasUsageRecord = Boolean(asRecord(line.usage) ?? asRecord(message?.usage));
|
|
8338
8763
|
if (hasUsageRecord) {
|
|
@@ -8342,7 +8767,7 @@ var PiSourceAdapter = class {
|
|
|
8342
8767
|
continue;
|
|
8343
8768
|
}
|
|
8344
8769
|
const provider = asTrimmedText(line.provider) ?? asTrimmedText(message?.provider) ?? state.provider;
|
|
8345
|
-
const timestamp =
|
|
8770
|
+
const timestamp = resolveTimestamp6(line, message, state);
|
|
8346
8771
|
if (!timestamp || !state.sessionId) {
|
|
8347
8772
|
skippedRows++;
|
|
8348
8773
|
incrementSkippedReason(skippedRowReasons, "invalid_timestamp");
|
|
@@ -8373,9 +8798,9 @@ var PiSourceAdapter = class {
|
|
|
8373
8798
|
};
|
|
8374
8799
|
|
|
8375
8800
|
// src/sources/qwen/qwen-source-adapter.ts
|
|
8376
|
-
import
|
|
8377
|
-
import
|
|
8378
|
-
var defaultProjectsDir =
|
|
8801
|
+
import os18 from "os";
|
|
8802
|
+
import path25 from "path";
|
|
8803
|
+
var defaultProjectsDir = path25.join(os18.homedir(), ".qwen", "projects");
|
|
8379
8804
|
var QWEN_USAGE_LINE_TEXT = '"usageMetadata"';
|
|
8380
8805
|
function shouldParseQwenJsonlLine(lineText) {
|
|
8381
8806
|
return lineText.includes(QWEN_USAGE_LINE_TEXT);
|
|
@@ -8409,11 +8834,11 @@ function extractTokenUsage2(usageMetadata) {
|
|
|
8409
8834
|
}
|
|
8410
8835
|
return extractedUsage;
|
|
8411
8836
|
}
|
|
8412
|
-
function
|
|
8413
|
-
const chatsDir =
|
|
8414
|
-
const projectDir =
|
|
8415
|
-
const projectName =
|
|
8416
|
-
const fileStem =
|
|
8837
|
+
function getFallbackSessionId7(filePath) {
|
|
8838
|
+
const chatsDir = path25.dirname(filePath);
|
|
8839
|
+
const projectDir = path25.dirname(chatsDir);
|
|
8840
|
+
const projectName = path25.basename(projectDir);
|
|
8841
|
+
const fileStem = path25.basename(filePath, ".jsonl");
|
|
8417
8842
|
return `${projectName}-${fileStem}`;
|
|
8418
8843
|
}
|
|
8419
8844
|
var QwenSourceAdapter = class {
|
|
@@ -8448,7 +8873,7 @@ var QwenSourceAdapter = class {
|
|
|
8448
8873
|
const events = [];
|
|
8449
8874
|
let skippedRows = 0;
|
|
8450
8875
|
const skippedRowReasons = /* @__PURE__ */ new Map();
|
|
8451
|
-
const fallbackSessionId =
|
|
8876
|
+
const fallbackSessionId = getFallbackSessionId7(filePath);
|
|
8452
8877
|
for await (const line of readJsonlObjects(filePath, {
|
|
8453
8878
|
shouldParseLine: shouldParseQwenJsonlLine,
|
|
8454
8879
|
onMalformedLine: () => {
|
|
@@ -8517,8 +8942,8 @@ function parseSourceDirectoryOverrides(entries) {
|
|
|
8517
8942
|
}
|
|
8518
8943
|
|
|
8519
8944
|
// src/sources/create-default-adapters.ts
|
|
8520
|
-
var dirOptions = ({ path:
|
|
8521
|
-
dir:
|
|
8945
|
+
var dirOptions = ({ path: path32, requireExistingPath }) => ({
|
|
8946
|
+
dir: path32,
|
|
8522
8947
|
requireDir: requireExistingPath
|
|
8523
8948
|
});
|
|
8524
8949
|
var sourceRegistrations = [
|
|
@@ -8567,7 +8992,7 @@ var sourceRegistrations = [
|
|
|
8567
8992
|
flag: "--opencode-db <path>",
|
|
8568
8993
|
help: "Path to OpenCode SQLite DB"
|
|
8569
8994
|
},
|
|
8570
|
-
create: ({ path:
|
|
8995
|
+
create: ({ path: path32 }) => new OpenCodeSourceAdapter({ dbPath: path32 })
|
|
8571
8996
|
},
|
|
8572
8997
|
{
|
|
8573
8998
|
id: "openclaw",
|
|
@@ -8607,7 +9032,7 @@ var sourceRegistrations = [
|
|
|
8607
9032
|
format: "sqlite",
|
|
8608
9033
|
supportsSourceDir: false,
|
|
8609
9034
|
option: { key: "gooseDb", flag: "--goose-db <path>", help: "Path to Goose SQLite DB" },
|
|
8610
|
-
create: ({ path:
|
|
9035
|
+
create: ({ path: path32 }) => new GooseSourceAdapter({ dbPath: path32 })
|
|
8611
9036
|
},
|
|
8612
9037
|
{
|
|
8613
9038
|
id: "amp",
|
|
@@ -8681,6 +9106,17 @@ var sourceRegistrations = [
|
|
|
8681
9106
|
help: "Path to Antigravity conversations directory"
|
|
8682
9107
|
},
|
|
8683
9108
|
create: (resolved) => new AntigravitySourceAdapter(dirOptions(resolved))
|
|
9109
|
+
},
|
|
9110
|
+
{
|
|
9111
|
+
id: "dsh",
|
|
9112
|
+
format: "jsonl",
|
|
9113
|
+
supportsSourceDir: true,
|
|
9114
|
+
option: {
|
|
9115
|
+
key: "dshDir",
|
|
9116
|
+
flag: "--dsh-dir <path>",
|
|
9117
|
+
help: "Path to DeepSeek Harness sessions directory"
|
|
9118
|
+
},
|
|
9119
|
+
create: (resolved) => new DshSourceAdapter(dirOptions(resolved))
|
|
8684
9120
|
}
|
|
8685
9121
|
];
|
|
8686
9122
|
var dedicatedOptionOrderIds = [
|
|
@@ -8699,7 +9135,8 @@ var dedicatedOptionOrderIds = [
|
|
|
8699
9135
|
"cline",
|
|
8700
9136
|
"roocode",
|
|
8701
9137
|
"kilocode",
|
|
8702
|
-
"antigravity"
|
|
9138
|
+
"antigravity",
|
|
9139
|
+
"dsh"
|
|
8703
9140
|
];
|
|
8704
9141
|
function dedicatedFlagName(flag) {
|
|
8705
9142
|
return flag.split(" ")[0];
|
|
@@ -9009,7 +9446,8 @@ var sourceDirOptionByConfigKey = {
|
|
|
9009
9446
|
cline: "clineDir",
|
|
9010
9447
|
roocode: "roocodeDir",
|
|
9011
9448
|
kilocode: "kilocodeDir",
|
|
9012
|
-
antigravity: "antigravityDir"
|
|
9449
|
+
antigravity: "antigravityDir",
|
|
9450
|
+
dsh: "dshDir"
|
|
9013
9451
|
};
|
|
9014
9452
|
var sourceDirConfigKeys = [
|
|
9015
9453
|
"pi",
|
|
@@ -9027,7 +9465,8 @@ var sourceDirConfigKeys = [
|
|
|
9027
9465
|
"cline",
|
|
9028
9466
|
"roocode",
|
|
9029
9467
|
"kilocode",
|
|
9030
|
-
"antigravity"
|
|
9468
|
+
"antigravity",
|
|
9469
|
+
"dsh"
|
|
9031
9470
|
];
|
|
9032
9471
|
function formatConfigValue(value) {
|
|
9033
9472
|
if (Array.isArray(value)) {
|
|
@@ -9309,13 +9748,13 @@ function readLiveHashCounts(store) {
|
|
|
9309
9748
|
const rows = store.database.prepare(
|
|
9310
9749
|
[
|
|
9311
9750
|
"SELECT events.content_hash AS content_hash, COUNT(*) AS count",
|
|
9312
|
-
"FROM
|
|
9313
|
-
"JOIN history_discovered_files AS discovered",
|
|
9314
|
-
" ON events.source = discovered.source",
|
|
9315
|
-
" AND events.file_path = discovered.file_path",
|
|
9751
|
+
"FROM history_discovered_files AS discovered",
|
|
9316
9752
|
"JOIN history_selected_sources AS selected",
|
|
9317
|
-
" ON
|
|
9318
|
-
"
|
|
9753
|
+
" ON discovered.source = selected.source",
|
|
9754
|
+
"CROSS JOIN events",
|
|
9755
|
+
"WHERE events.source = discovered.source",
|
|
9756
|
+
" AND events.file_path = discovered.file_path",
|
|
9757
|
+
" AND events.content_hash IS NOT NULL",
|
|
9319
9758
|
"GROUP BY events.content_hash"
|
|
9320
9759
|
].join("\n")
|
|
9321
9760
|
).all();
|
|
@@ -9391,9 +9830,9 @@ function readDepartedHashMultisets(store) {
|
|
|
9391
9830
|
[
|
|
9392
9831
|
"SELECT events.source AS source, events.file_path AS file_path,",
|
|
9393
9832
|
" events.content_hash AS content_hash, COUNT(*) AS count",
|
|
9394
|
-
"FROM
|
|
9395
|
-
"JOIN
|
|
9396
|
-
"
|
|
9833
|
+
"FROM history_departed_files AS departed",
|
|
9834
|
+
"CROSS JOIN events",
|
|
9835
|
+
"WHERE events.source = departed.source",
|
|
9397
9836
|
" AND events.file_path = departed.file_path",
|
|
9398
9837
|
"GROUP BY events.source, events.file_path, events.content_hash"
|
|
9399
9838
|
].join("\n")
|
|
@@ -9458,9 +9897,9 @@ function loadServedEvents(store, servedFiles) {
|
|
|
9458
9897
|
" events.provider, events.repo_root, events.input_tokens, events.output_tokens,",
|
|
9459
9898
|
" events.reasoning_tokens, events.cache_read_tokens, events.cache_write_tokens,",
|
|
9460
9899
|
" events.total_tokens, events.cost_usd, events.cost_mode",
|
|
9461
|
-
"FROM
|
|
9462
|
-
"JOIN
|
|
9463
|
-
"
|
|
9900
|
+
"FROM history_served_files AS served",
|
|
9901
|
+
"CROSS JOIN events",
|
|
9902
|
+
"WHERE events.source = served.source",
|
|
9464
9903
|
" AND events.file_path = served.file_path",
|
|
9465
9904
|
"ORDER BY served.ordinal ASC, events.event_index ASC"
|
|
9466
9905
|
].join("\n")
|
|
@@ -10133,7 +10572,12 @@ async function parseAdapterEvents(adapter, maxParallelFileParsing, runWithParseB
|
|
|
10133
10572
|
fileIndices2,
|
|
10134
10573
|
(fileIndex) => resolveStoreHitOrWorkerMiss(fileIndex, missedFiles)
|
|
10135
10574
|
);
|
|
10136
|
-
missedFiles.sort((left5, right4) =>
|
|
10575
|
+
missedFiles.sort((left5, right4) => {
|
|
10576
|
+
if (left5.byteSize !== right4.byteSize) {
|
|
10577
|
+
return right4.byteSize - left5.byteSize;
|
|
10578
|
+
}
|
|
10579
|
+
return left5.fileIndex - right4.fileIndex;
|
|
10580
|
+
});
|
|
10137
10581
|
const missedBytes = missedFiles.reduce(
|
|
10138
10582
|
(sum, missedFile) => sum + Math.max(0, missedFile.byteSize),
|
|
10139
10583
|
0
|
|
@@ -10452,7 +10896,7 @@ function applyPricingToEvents(events, pricingSource) {
|
|
|
10452
10896
|
}
|
|
10453
10897
|
|
|
10454
10898
|
// src/pricing/pricing-override-source.ts
|
|
10455
|
-
import { readFile as
|
|
10899
|
+
import { readFile as readFile7 } from "fs/promises";
|
|
10456
10900
|
function toFiniteUsdRate(value) {
|
|
10457
10901
|
if (value === null || value === void 0) {
|
|
10458
10902
|
return void 0;
|
|
@@ -10508,7 +10952,7 @@ function normalizeOverrideFile(payload) {
|
|
|
10508
10952
|
return overrides;
|
|
10509
10953
|
}
|
|
10510
10954
|
async function loadPricingOverrides(filePath) {
|
|
10511
|
-
const fileContents = await
|
|
10955
|
+
const fileContents = await readFile7(filePath, "utf8");
|
|
10512
10956
|
const parsed = JSON.parse(fileContents);
|
|
10513
10957
|
return normalizeOverrideFile(parsed);
|
|
10514
10958
|
}
|
|
@@ -10535,8 +10979,8 @@ var PricingOverrideSource = class {
|
|
|
10535
10979
|
};
|
|
10536
10980
|
|
|
10537
10981
|
// src/pricing/litellm-pricing-fetcher.ts
|
|
10538
|
-
import { mkdir as mkdir3, readFile as
|
|
10539
|
-
import
|
|
10982
|
+
import { mkdir as mkdir3, readFile as readFile8, writeFile as writeFile2 } from "fs/promises";
|
|
10983
|
+
import path26 from "path";
|
|
10540
10984
|
|
|
10541
10985
|
// src/pricing/litellm-model-map.json
|
|
10542
10986
|
var litellm_model_map_default = {
|
|
@@ -10571,10 +11015,11 @@ var litellm_model_map_default = {
|
|
|
10571
11015
|
"anthropic/claude-sonnet-4.6": "claude-sonnet-4.6",
|
|
10572
11016
|
"anthropic.claude-sonnet-4-6": "claude-sonnet-4.6"
|
|
10573
11017
|
},
|
|
10574
|
-
neverFuzzyMatch: ["kimi-for-coding"],
|
|
11018
|
+
neverFuzzyMatch: ["deepseek-flash", "deepseek-v4.1-flash", "kimi-for-coding"],
|
|
10575
11019
|
notes: {
|
|
10576
11020
|
"gpt-5.3-codex-spark": "Alias to gpt-5.3-codex because upstream publishes token pricing on the gpt-5.3-codex key",
|
|
10577
11021
|
"gemini-3-flash-a": "Antigravity session data records gemini-3 models with an '-a' suffix (gemini-3-flash-a, gemini-3-pro-a); alias them to the canonical gemini-3 models",
|
|
11022
|
+
"deepseek-flash": "Deliberately NOT aliased: DeepSeek Harness reports its default route as deepseek-flash, which its catalog names DeepSeek-V41-Flash. LiteLLM publishes no v4.1 key (bundled snapshot or upstream main), and deepseek-v4-flash is the earlier V4 model at its own much lower rates, so any alias would silently bill V4.1 traffic at another model's prices. Fuzzy matching is blocked so the row stays visibly unpriced until a real key exists; the published V4.1 rate card is listed in site/src/content/docs/sources/dsh.mdx for use with --pricing-overrides",
|
|
10578
11023
|
"kimi-for-coding": "Deliberately NOT aliased: the managed kimi-for-coding endpoint maps to kimi-k2.5 or kimi-k2.6 depending on the event timestamp. The kimi adapter resolves that fallback itself; a config-provided kimi-for-coding model stays unpriced rather than mispriced"
|
|
10579
11024
|
},
|
|
10580
11025
|
preferredPricingKeyByCanonicalModel: {
|
|
@@ -21817,7 +22262,7 @@ function formatBundledSnapshotWarning(fetchedAt) {
|
|
|
21817
22262
|
return `Pricing: using the bundled LiteLLM snapshot from ${fetchedDate} (run online to refresh).`;
|
|
21818
22263
|
}
|
|
21819
22264
|
function getDefaultLiteLLMPricingCachePath() {
|
|
21820
|
-
return
|
|
22265
|
+
return path26.join(getUserCacheRootDir(), "llm-usage-metrics", "litellm-pricing-cache.json");
|
|
21821
22266
|
}
|
|
21822
22267
|
var LiteLLMPricingFetcher = class {
|
|
21823
22268
|
sourceUrl;
|
|
@@ -22027,7 +22472,7 @@ var LiteLLMPricingFetcher = class {
|
|
|
22027
22472
|
async readCachePayload() {
|
|
22028
22473
|
let content;
|
|
22029
22474
|
try {
|
|
22030
|
-
content = await
|
|
22475
|
+
content = await readFile8(this.cacheFilePath, "utf8");
|
|
22031
22476
|
} catch {
|
|
22032
22477
|
return void 0;
|
|
22033
22478
|
}
|
|
@@ -22040,7 +22485,7 @@ var LiteLLMPricingFetcher = class {
|
|
|
22040
22485
|
return normalizeLiteLLMCachePayload(parsedPayload);
|
|
22041
22486
|
}
|
|
22042
22487
|
async writeCache() {
|
|
22043
|
-
const directoryPath =
|
|
22488
|
+
const directoryPath = path26.dirname(this.cacheFilePath);
|
|
22044
22489
|
await mkdir3(directoryPath, { recursive: true });
|
|
22045
22490
|
const payload = {
|
|
22046
22491
|
fetchedAt: this.now(),
|
|
@@ -23039,9 +23484,9 @@ function emitEnvVarOverrides(activeEnvOverrides, diagnosticsLogger) {
|
|
|
23039
23484
|
import { spawn } from "child_process";
|
|
23040
23485
|
import { constants as constants2 } from "fs";
|
|
23041
23486
|
import { access as access2, writeFile as writeFile3 } from "fs/promises";
|
|
23042
|
-
import
|
|
23487
|
+
import path27 from "path";
|
|
23043
23488
|
async function writeShareSvgFile(fileName, svgContent) {
|
|
23044
|
-
const outputPath =
|
|
23489
|
+
const outputPath = path27.resolve(process.cwd(), fileName);
|
|
23045
23490
|
await writeFile3(outputPath, svgContent, "utf8");
|
|
23046
23491
|
return outputPath;
|
|
23047
23492
|
}
|
|
@@ -23069,10 +23514,10 @@ async function resolveBinaryPath(primaryPath, fallbackNames) {
|
|
|
23069
23514
|
if (await fileExists(primaryPath)) {
|
|
23070
23515
|
return primaryPath;
|
|
23071
23516
|
}
|
|
23072
|
-
const pathDirs = (process.env.PATH ?? "").split(
|
|
23517
|
+
const pathDirs = (process.env.PATH ?? "").split(path27.delimiter).filter(Boolean);
|
|
23073
23518
|
for (const fallbackName of fallbackNames) {
|
|
23074
23519
|
for (const dir of pathDirs) {
|
|
23075
|
-
const candidate =
|
|
23520
|
+
const candidate = path27.join(dir, fallbackName);
|
|
23076
23521
|
if (await fileExists(candidate)) {
|
|
23077
23522
|
return candidate;
|
|
23078
23523
|
}
|
|
@@ -23943,7 +24388,7 @@ function aggregateEfficiency(options) {
|
|
|
23943
24388
|
// src/efficiency/git-outcome-collector.ts
|
|
23944
24389
|
import { spawn as spawn2 } from "child_process";
|
|
23945
24390
|
import { createInterface } from "readline";
|
|
23946
|
-
import
|
|
24391
|
+
import path28 from "path";
|
|
23947
24392
|
import { stat as stat5 } from "fs/promises";
|
|
23948
24393
|
var GIT_COMMIT_MARKER = "";
|
|
23949
24394
|
var SHORTSTAT_PATTERN = /(\d+)\s+files?\s+changed(?:,\s+(\d+)\s+insertions?\(\+\))?(?:,\s+(\d+)\s+deletions?\(-\))?/u;
|
|
@@ -23963,13 +24408,13 @@ function resolveGitCommandFailureReason(result) {
|
|
|
23963
24408
|
}
|
|
23964
24409
|
function resolveRepoDir(repoDir) {
|
|
23965
24410
|
if (repoDir === void 0) {
|
|
23966
|
-
return
|
|
24411
|
+
return path28.resolve(process.cwd());
|
|
23967
24412
|
}
|
|
23968
24413
|
const normalizedRepoDir = repoDir.trim();
|
|
23969
24414
|
if (!normalizedRepoDir) {
|
|
23970
24415
|
throw new Error("--repo-dir must be a non-empty path");
|
|
23971
24416
|
}
|
|
23972
|
-
return
|
|
24417
|
+
return path28.resolve(normalizedRepoDir);
|
|
23973
24418
|
}
|
|
23974
24419
|
function getNodeErrorCode2(error) {
|
|
23975
24420
|
if (typeof error !== "object" || error === null || !("code" in error)) {
|
|
@@ -24350,21 +24795,21 @@ async function collectGitOutcomes(options, deps = {}) {
|
|
|
24350
24795
|
|
|
24351
24796
|
// src/efficiency/repo-attribution.ts
|
|
24352
24797
|
import { access as access3, constants as constants3, realpath as realpath3 } from "fs/promises";
|
|
24353
|
-
import
|
|
24798
|
+
import path29 from "path";
|
|
24354
24799
|
async function hasGitMarker(directoryPath) {
|
|
24355
24800
|
try {
|
|
24356
|
-
await access3(
|
|
24801
|
+
await access3(path29.join(directoryPath, ".git"), constants3.F_OK);
|
|
24357
24802
|
return true;
|
|
24358
24803
|
} catch {
|
|
24359
24804
|
return false;
|
|
24360
24805
|
}
|
|
24361
24806
|
}
|
|
24362
24807
|
function normalizeComparablePath(value) {
|
|
24363
|
-
const normalizedPath =
|
|
24808
|
+
const normalizedPath = path29.normalize(path29.resolve(value));
|
|
24364
24809
|
return process.platform === "win32" ? normalizedPath.toLowerCase() : normalizedPath;
|
|
24365
24810
|
}
|
|
24366
24811
|
async function resolveComparablePath(value) {
|
|
24367
|
-
const resolvedPath =
|
|
24812
|
+
const resolvedPath = path29.resolve(value);
|
|
24368
24813
|
try {
|
|
24369
24814
|
return normalizeComparablePath(await realpath3(resolvedPath));
|
|
24370
24815
|
} catch {
|
|
@@ -24376,12 +24821,12 @@ async function resolveRepoRootFromPathHint(pathHint) {
|
|
|
24376
24821
|
if (!trimmedPath) {
|
|
24377
24822
|
return void 0;
|
|
24378
24823
|
}
|
|
24379
|
-
let currentPath =
|
|
24824
|
+
let currentPath = path29.resolve(trimmedPath);
|
|
24380
24825
|
for (; ; ) {
|
|
24381
24826
|
if (await hasGitMarker(currentPath)) {
|
|
24382
24827
|
return currentPath;
|
|
24383
24828
|
}
|
|
24384
|
-
const parentPath =
|
|
24829
|
+
const parentPath = path29.dirname(currentPath);
|
|
24385
24830
|
if (parentPath === currentPath) {
|
|
24386
24831
|
return void 0;
|
|
24387
24832
|
}
|
|
@@ -24500,6 +24945,9 @@ function resolveScopeNote(options) {
|
|
|
24500
24945
|
if (hasActiveTextOption(options.antigravityDir)) {
|
|
24501
24946
|
activeFilters.push("--antigravity-dir");
|
|
24502
24947
|
}
|
|
24948
|
+
if (hasActiveTextOption(options.dshDir)) {
|
|
24949
|
+
activeFilters.push("--dsh-dir");
|
|
24950
|
+
}
|
|
24503
24951
|
if (hasActiveRepeatedFilter(options.sourceDir)) {
|
|
24504
24952
|
activeFilters.push("--source-dir");
|
|
24505
24953
|
}
|
|
@@ -25441,7 +25889,7 @@ async function runOptimizeReport(granularity, options) {
|
|
|
25441
25889
|
}
|
|
25442
25890
|
|
|
25443
25891
|
// src/render/render-session-report.ts
|
|
25444
|
-
import
|
|
25892
|
+
import path30 from "path";
|
|
25445
25893
|
import { markdownTable as markdownTable4 } from "markdown-table";
|
|
25446
25894
|
|
|
25447
25895
|
// src/render/format-duration.ts
|
|
@@ -25509,7 +25957,7 @@ function toSessionTableCells(row, options) {
|
|
|
25509
25957
|
return [
|
|
25510
25958
|
options.truncateSessionIds ? truncateSessionId(row.sessionId) : row.sessionId,
|
|
25511
25959
|
row.source,
|
|
25512
|
-
row.repoRoot ?
|
|
25960
|
+
row.repoRoot ? path30.basename(row.repoRoot) : "-",
|
|
25513
25961
|
getPeriodKey(row.lastActivity, "daily", options.timezone),
|
|
25514
25962
|
formatDuration(row.durationMs),
|
|
25515
25963
|
formatInteger4(row.totalTokens),
|
|
@@ -25519,7 +25967,7 @@ function toSessionTableCells(row, options) {
|
|
|
25519
25967
|
}
|
|
25520
25968
|
function toRepoTableCells(row, timezone) {
|
|
25521
25969
|
return [
|
|
25522
|
-
row.repoRoot ?
|
|
25970
|
+
row.repoRoot ? path30.basename(row.repoRoot) : "(no repo)",
|
|
25523
25971
|
formatInteger4(row.sessionCount),
|
|
25524
25972
|
getPeriodKey(row.lastActivity, "daily", timezone),
|
|
25525
25973
|
formatInteger4(row.totalTokens),
|
|
@@ -29144,7 +29592,7 @@ function createRootDescription() {
|
|
|
29144
29592
|
|
|
29145
29593
|
// src/cli/create-config-command.ts
|
|
29146
29594
|
import { access as access4, mkdir as mkdir4, writeFile as writeFile4 } from "fs/promises";
|
|
29147
|
-
import
|
|
29595
|
+
import path31 from "path";
|
|
29148
29596
|
import { Command as Command2 } from "commander";
|
|
29149
29597
|
var CONFIG_TEMPLATE_HEADER = `#:schema https://ayagmar.github.io/llm-usage-metrics/config-schema.json
|
|
29150
29598
|
# llm-usage-metrics configuration. Uncomment a key to override its default.
|
|
@@ -29195,7 +29643,7 @@ function isExistingFileError(error) {
|
|
|
29195
29643
|
return asRecord(error)?.code === "EEXIST";
|
|
29196
29644
|
}
|
|
29197
29645
|
async function writeConfigTemplate(configPath, options) {
|
|
29198
|
-
await mkdir4(
|
|
29646
|
+
await mkdir4(path31.dirname(configPath), { recursive: true });
|
|
29199
29647
|
try {
|
|
29200
29648
|
await writeFile4(configPath, USER_CONFIG_TEMPLATE, {
|
|
29201
29649
|
encoding: "utf8",
|
|
@@ -29347,6 +29795,10 @@ var config_schema_default = {
|
|
|
29347
29795
|
antigravity: {
|
|
29348
29796
|
description: "Default path for Antigravity conversations; maps to --antigravity-dir.",
|
|
29349
29797
|
type: "string"
|
|
29798
|
+
},
|
|
29799
|
+
dsh: {
|
|
29800
|
+
description: "Default path for DeepSeek Harness sessions; maps to --dsh-dir.",
|
|
29801
|
+
type: "string"
|
|
29350
29802
|
}
|
|
29351
29803
|
}
|
|
29352
29804
|
},
|
|
@@ -30827,11 +31279,11 @@ mainPromise.catch((error) => {
|
|
|
30827
31279
|
});
|
|
30828
31280
|
/*! Bundled license information:
|
|
30829
31281
|
|
|
30830
|
-
smol-toml/dist/date.js:
|
|
30831
31282
|
smol-toml/dist/error.js:
|
|
30832
31283
|
smol-toml/dist/primitive.js:
|
|
30833
|
-
smol-toml/dist/
|
|
31284
|
+
smol-toml/dist/date.js:
|
|
30834
31285
|
smol-toml/dist/extract.js:
|
|
31286
|
+
smol-toml/dist/util.js:
|
|
30835
31287
|
smol-toml/dist/struct.js:
|
|
30836
31288
|
smol-toml/dist/parse.js:
|
|
30837
31289
|
smol-toml/dist/stringify.js:
|