@hasna/economy 0.5.7 → 0.5.9
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/CHANGELOG.md +15 -0
- package/dist/chunks/{billing-22az60hy.js → billing-7twygmtj.js} +2 -2
- package/dist/chunks/{config-hsp7ndhj.js → config-mjgbekxj.js} +2 -2
- package/dist/chunks/{index-9wa1f2kv.js → index-7ek4r0ww.js} +1 -1
- package/dist/chunks/{index-z2n5y111.js → index-92x56q4h.js} +5 -4
- package/dist/chunks/{index-wq7c4wqs.js → index-970htsxe.js} +2 -2
- package/dist/chunks/{index-vajzfzgv.js → index-ep1pkyr3.js} +1 -1
- package/dist/chunks/{index-dk5rq1rq.js → index-gtjqy0kd.js} +1 -1
- package/dist/chunks/{index-b6c649mq.js → index-spwpgdbb.js} +82 -7
- package/dist/chunks/{index-c7h2rxx1.js → index-t0n32g8r.js} +1 -1
- package/dist/chunks/{index-6yr4hb72.js → index-twkdyrw4.js} +2 -2
- package/dist/chunks/{index-f5jv6q5q.js → index-zgvmrqyc.js} +1 -1
- package/dist/chunks/{open-projects-8qm46m3d.js → open-projects-bj561k5j.js} +1 -1
- package/dist/chunks/{pricing-k9wsjwbz.js → pricing-bkgvzpe9.js} +1 -1
- package/dist/chunks/{pricing-462f8xkm.js → pricing-bn88mhqk.js} +1 -1
- package/dist/chunks/{pricing-vxejj1qa.js → pricing-nt31hf53.js} +1 -1
- package/dist/chunks/{serve-ms8dvf7e.js → serve-tmv8zgvh.js} +14 -8
- package/dist/chunks/{sqlite-store-ht6frztj.js → sqlite-store-8t4anw98.js} +2 -2
- package/dist/chunks/{sqlite-store-13nhr1z0.js → sqlite-store-jfy0e8b6.js} +2 -2
- package/dist/chunks/{sqlite-store-gamn65xp.js → sqlite-store-r219qrjt.js} +2 -2
- package/dist/chunks/{tui-9t7340wd.js → tui-j8brj3wf.js} +4 -4
- package/dist/chunks/{watch-t6ssnx30.js → watch-ksn2mezm.js} +5 -5
- package/dist/chunks/{webhooks-nw4daw9y.js → webhooks-td46p6gk.js} +2 -2
- package/dist/cli/index.js +38 -32
- package/dist/cost-imports/contract.d.ts +84 -0
- package/dist/cost-imports/contract.d.ts.map +1 -0
- package/dist/cost-imports/decimal.d.ts +6 -0
- package/dist/cost-imports/decimal.d.ts.map +1 -0
- package/dist/cost-imports/providers.d.ts +4 -0
- package/dist/cost-imports/providers.d.ts.map +1 -0
- package/dist/index.js +72 -12
- package/dist/lib/analytics.d.ts +3 -0
- package/dist/lib/analytics.d.ts.map +1 -1
- package/dist/lib/comparison-contract.d.ts +8 -0
- package/dist/lib/comparison-contract.d.ts.map +1 -0
- package/dist/lib/comparison-test-contract.d.ts +3 -0
- package/dist/lib/comparison-test-contract.d.ts.map +1 -0
- package/dist/lib/ingest-journal-maintenance.d.ts.map +1 -1
- package/dist/lib/store/index.d.ts.map +1 -1
- package/dist/mcp/index.js +75 -15
- package/dist/otel/index.js +7 -5
- package/dist/server/index.js +40 -6
- package/dist/server/service-operations.d.ts.map +1 -1
- package/dist/server/service-worker.js +40 -6
- package/docs/comparison-coverage.md +30 -0
- package/docs/ingest-journal.md +5 -1
- package/native/README.md +48 -0
- package/native/Tools/pair-qr.py +6 -1
- package/native/Tools/pair-qr.swift +19 -1
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -4,26 +4,28 @@ import {
|
|
|
4
4
|
syncAnthropicBilling,
|
|
5
5
|
syncGeminiBilling,
|
|
6
6
|
syncOpenAIBilling
|
|
7
|
-
} from "../chunks/index-
|
|
7
|
+
} from "../chunks/index-gtjqy0kd.js";
|
|
8
8
|
import {
|
|
9
9
|
buildStatusLine,
|
|
10
10
|
gatherStatusData
|
|
11
|
-
} from "../chunks/index-
|
|
11
|
+
} from "../chunks/index-twkdyrw4.js";
|
|
12
12
|
import"../chunks/index-w3bvv0ns.js";
|
|
13
13
|
import {
|
|
14
14
|
agentPaths,
|
|
15
15
|
syncAll
|
|
16
|
-
} from "../chunks/index-
|
|
16
|
+
} from "../chunks/index-970htsxe.js";
|
|
17
17
|
import {
|
|
18
18
|
getStore,
|
|
19
19
|
isCloudStore
|
|
20
|
-
} from "../chunks/index-
|
|
20
|
+
} from "../chunks/index-92x56q4h.js";
|
|
21
21
|
import {
|
|
22
22
|
billingDriftCheck,
|
|
23
|
+
comparisonValueChange,
|
|
23
24
|
economyCloudStorage,
|
|
24
25
|
economyTransportReport,
|
|
26
|
+
formatComparisonValue,
|
|
25
27
|
packageMetadata
|
|
26
|
-
} from "../chunks/index-
|
|
28
|
+
} from "../chunks/index-spwpgdbb.js";
|
|
27
29
|
import {
|
|
28
30
|
AGENTS,
|
|
29
31
|
MAX_INGEST_BYTES,
|
|
@@ -46,7 +48,7 @@ import {
|
|
|
46
48
|
setIngestState,
|
|
47
49
|
stableJson,
|
|
48
50
|
validateIngest
|
|
49
|
-
} from "../chunks/index-
|
|
51
|
+
} from "../chunks/index-zgvmrqyc.js";
|
|
50
52
|
import {
|
|
51
53
|
__require
|
|
52
54
|
} from "../chunks/index-p35cyhc4.js";
|
|
@@ -1279,7 +1281,7 @@ function registerExtendedCommands(program) {
|
|
|
1279
1281
|
}
|
|
1280
1282
|
}
|
|
1281
1283
|
if (!cloud) {
|
|
1282
|
-
const { openDatabase } = await import("../chunks/sqlite-store-
|
|
1284
|
+
const { openDatabase } = await import("../chunks/sqlite-store-r219qrjt.js");
|
|
1283
1285
|
const db = openDatabase();
|
|
1284
1286
|
ensurePricingSeeded(db);
|
|
1285
1287
|
const zeroCostBuckets = queryZeroCostTokenizedModels(db, 5);
|
|
@@ -1357,23 +1359,23 @@ function registerExtendedCommands(program) {
|
|
|
1357
1359
|
console.log();
|
|
1358
1360
|
});
|
|
1359
1361
|
program.command("tui").description("Terminal status dashboard (Linux/SSH friendly)").option("--watch", "Live refresh").option("--interval <seconds>", "Refresh interval", "30").action(async (opts) => {
|
|
1360
|
-
const { runTui } = await import("../chunks/tui-
|
|
1362
|
+
const { runTui } = await import("../chunks/tui-j8brj3wf.js");
|
|
1361
1363
|
await runTui({
|
|
1362
1364
|
watch: Boolean(opts.watch),
|
|
1363
1365
|
interval: Number(opts.interval ?? 30)
|
|
1364
1366
|
});
|
|
1365
1367
|
});
|
|
1366
1368
|
program.command("waybar").description("Print waybar-compatible JSON status line").action(async () => {
|
|
1367
|
-
const { printWaybarJson } = await import("../chunks/tui-
|
|
1369
|
+
const { printWaybarJson } = await import("../chunks/tui-j8brj3wf.js");
|
|
1368
1370
|
await printWaybarJson();
|
|
1369
1371
|
});
|
|
1370
1372
|
const barCmd = program.command("bar").description("Status bar helpers (Linux)");
|
|
1371
1373
|
barCmd.command("tui").description("Alias for economy tui").option("--watch", "Live refresh").action(async (opts) => {
|
|
1372
|
-
const { runTui } = await import("../chunks/tui-
|
|
1374
|
+
const { runTui } = await import("../chunks/tui-j8brj3wf.js");
|
|
1373
1375
|
await runTui({ watch: Boolean(opts.watch) });
|
|
1374
1376
|
});
|
|
1375
1377
|
barCmd.command("waybar").description("Alias for economy waybar").action(async () => {
|
|
1376
|
-
const { printWaybarJson } = await import("../chunks/tui-
|
|
1378
|
+
const { printWaybarJson } = await import("../chunks/tui-j8brj3wf.js");
|
|
1377
1379
|
await printWaybarJson();
|
|
1378
1380
|
});
|
|
1379
1381
|
program.command("estimate").description("Estimate cost for token counts").requiredOption("--model <model>", "Model name").option("--input <n>", "Input tokens", "0").option("--output <n>", "Output tokens", "0").action(async (opts) => {
|
|
@@ -2022,18 +2024,19 @@ class IngestJournalMaintenance {
|
|
|
2022
2024
|
throw new Error("Journal maintenance limit must be 1\u201332");
|
|
2023
2025
|
await this.recover();
|
|
2024
2026
|
await verifyJournalAuthority(this.journal, this.cloud);
|
|
2025
|
-
const
|
|
2027
|
+
const sweepDeadline = Date.now() + 30000;
|
|
2026
2028
|
let retired = 0, bytes = 0;
|
|
2027
2029
|
let backend;
|
|
2028
2030
|
try {
|
|
2029
2031
|
const names = this.journal.names();
|
|
2030
2032
|
for (const name of names.filter((n) => n.endsWith(".intent.json"))) {
|
|
2031
|
-
if (retired >= limit || Date.now() >=
|
|
2033
|
+
if (retired >= limit || Date.now() >= sweepDeadline || retired > 0 && bytes >= 1048576)
|
|
2032
2034
|
break;
|
|
2033
2035
|
if (!names.includes(name.replace(".intent.", ".receipt.")))
|
|
2034
2036
|
continue;
|
|
2035
2037
|
const intent = this.journal.intent(name), receipt = this.journal.receipt(intent.command);
|
|
2036
|
-
|
|
2038
|
+
const deadline = Date.now() + 30000;
|
|
2039
|
+
backend = await this.backend(deadline);
|
|
2037
2040
|
const m = {
|
|
2038
2041
|
version: 1,
|
|
2039
2042
|
target: this.journal.target,
|
|
@@ -2069,7 +2072,8 @@ class IngestJournalMaintenance {
|
|
|
2069
2072
|
try {
|
|
2070
2073
|
await this.maintain();
|
|
2071
2074
|
} catch (error) {
|
|
2072
|
-
|
|
2075
|
+
const deferrable = error instanceof JournalMaintenanceError && ["recovery_not_configured", "self_host_trash_authority_required", "trash_version_mismatch", "recovery_authority_unavailable"].includes(error.reason);
|
|
2076
|
+
if (!deferrable || exists(this.control) || !this.journal.canStage(command))
|
|
2073
2077
|
throw error;
|
|
2074
2078
|
}
|
|
2075
2079
|
if (!this.journal.canStage(command))
|
|
@@ -2335,7 +2339,7 @@ function backfillMachineId(db) {
|
|
|
2335
2339
|
return { requests: Number(reqCount.changes), sessions: Number(sessCount.changes) };
|
|
2336
2340
|
}
|
|
2337
2341
|
async function recalculateZeroCostRequests(db) {
|
|
2338
|
-
const { assessCostFromDb } = await import("../chunks/pricing-
|
|
2342
|
+
const { assessCostFromDb } = await import("../chunks/pricing-bn88mhqk.js");
|
|
2339
2343
|
const zeroRows = db.prepare(`SELECT id, model, input_tokens, output_tokens, cache_read_tokens, cache_create_tokens, cache_create_5m_tokens, cache_create_1h_tokens
|
|
2340
2344
|
FROM requests
|
|
2341
2345
|
WHERE cost_usd = 0
|
|
@@ -2544,7 +2548,7 @@ async function postIngest(cloud, body) {
|
|
|
2544
2548
|
}
|
|
2545
2549
|
async function syncAllToCloud(cloud, opts = {}) {
|
|
2546
2550
|
await runIngestJournalOperation(cloud, { action: "reconcile" });
|
|
2547
|
-
const { openDatabase } = await import("../chunks/sqlite-store-
|
|
2551
|
+
const { openDatabase } = await import("../chunks/sqlite-store-r219qrjt.js");
|
|
2548
2552
|
const scratch = openDatabase(":memory:", true);
|
|
2549
2553
|
ensurePricingSeeded(scratch);
|
|
2550
2554
|
const cachePath = opts.cachePath ?? getIngestCachePath();
|
|
@@ -2571,7 +2575,7 @@ async function syncAllToCloud(cloud, opts = {}) {
|
|
|
2571
2575
|
}
|
|
2572
2576
|
async function billingSyncToCloud(cloud, opts = {}) {
|
|
2573
2577
|
await runIngestJournalOperation(cloud, { action: "reconcile" });
|
|
2574
|
-
const { openDatabase } = await import("../chunks/sqlite-store-
|
|
2578
|
+
const { openDatabase } = await import("../chunks/sqlite-store-r219qrjt.js");
|
|
2575
2579
|
const scratch = openDatabase(":memory:", true);
|
|
2576
2580
|
try {
|
|
2577
2581
|
const days = opts.days ?? 31;
|
|
@@ -2630,7 +2634,7 @@ function autosyncIntervalMs(env = process.env) {
|
|
|
2630
2634
|
return Math.round(seconds * 1000);
|
|
2631
2635
|
}
|
|
2632
2636
|
async function autosyncMarkerStore(env = process.env) {
|
|
2633
|
-
const { openDatabase } = await import("../chunks/sqlite-store-
|
|
2637
|
+
const { openDatabase } = await import("../chunks/sqlite-store-r219qrjt.js");
|
|
2634
2638
|
if (isCloudStore(env))
|
|
2635
2639
|
return openDatabase(getIngestCachePath());
|
|
2636
2640
|
return openDatabase();
|
|
@@ -2663,7 +2667,7 @@ async function autoSync(opts = {}) {
|
|
|
2663
2667
|
return;
|
|
2664
2668
|
if (!await autoSyncDue(undefined, process.env))
|
|
2665
2669
|
return;
|
|
2666
|
-
const { openDatabase } = await import("../chunks/sqlite-store-
|
|
2670
|
+
const { openDatabase } = await import("../chunks/sqlite-store-r219qrjt.js");
|
|
2667
2671
|
const db = openDatabase();
|
|
2668
2672
|
ensurePricingSeeded(db);
|
|
2669
2673
|
await syncAll(db, opts);
|
|
@@ -2931,13 +2935,13 @@ program.command("sync").description("Ingest cost data from all coding agents").o
|
|
|
2931
2935
|
}
|
|
2932
2936
|
return;
|
|
2933
2937
|
}
|
|
2934
|
-
const { openDatabase } = await import("../chunks/sqlite-store-
|
|
2938
|
+
const { openDatabase } = await import("../chunks/sqlite-store-r219qrjt.js");
|
|
2935
2939
|
const db = openDatabase();
|
|
2936
2940
|
ensurePricingSeeded(db);
|
|
2937
2941
|
const anySpecific = opts.claude || opts.takumi || opts.codex || opts.gemini || opts.opencode || opts.cursor || opts.pi || opts.hermes || opts.loops;
|
|
2938
2942
|
if (!anySpecific || opts.verbose) {
|
|
2939
2943
|
try {
|
|
2940
|
-
const { syncOpenProjectsRegistry } = await import("../chunks/open-projects-
|
|
2944
|
+
const { syncOpenProjectsRegistry } = await import("../chunks/open-projects-bj561k5j.js");
|
|
2941
2945
|
const p = await syncOpenProjectsRegistry(db);
|
|
2942
2946
|
if (opts.verbose)
|
|
2943
2947
|
console.log(chalk3.dim(`Synced open-projects registry: ${p.imported} imported, ${p.skipped} skipped`));
|
|
@@ -2972,7 +2976,7 @@ program.command("sync").description("Ingest cost data from all coding agents").o
|
|
|
2972
2976
|
console.log(chalk3.cyan(`\u2192 Backfilled machine_id='${machine}': ${r.requests} requests, ${r.sessions} sessions`));
|
|
2973
2977
|
}
|
|
2974
2978
|
if (opts.recalculate) {
|
|
2975
|
-
const { getPricingFromDb: getPricingFromDb2 } = await import("../chunks/pricing-
|
|
2979
|
+
const { getPricingFromDb: getPricingFromDb2 } = await import("../chunks/pricing-bn88mhqk.js");
|
|
2976
2980
|
const r = await recalculateZeroCostRequests(db);
|
|
2977
2981
|
console.log(chalk3.cyan(`\u2192 Recalculated: ${r.fixed}/${r.total} zero-cost requests now have pricing`));
|
|
2978
2982
|
const zeroCostBuckets = r.buckets;
|
|
@@ -2987,7 +2991,7 @@ program.command("sync").description("Ingest cost data from all coding agents").o
|
|
|
2987
2991
|
}
|
|
2988
2992
|
}
|
|
2989
2993
|
try {
|
|
2990
|
-
const { checkAndFireWebhooks } = await import("../chunks/webhooks-
|
|
2994
|
+
const { checkAndFireWebhooks } = await import("../chunks/webhooks-td46p6gk.js");
|
|
2991
2995
|
await checkAndFireWebhooks(db);
|
|
2992
2996
|
} catch {}
|
|
2993
2997
|
for (const line of syncOutcomeLines(result))
|
|
@@ -3198,7 +3202,7 @@ program.command("accounts [period]").description("List account usage by email ad
|
|
|
3198
3202
|
console.log();
|
|
3199
3203
|
});
|
|
3200
3204
|
program.command("watch").description("Live stream of incoming costs").option("--interval <seconds>", "Poll interval in seconds", "10").option("--daemon", "Watch agent data directories and sync on change").option("--agent <agent>", `Filter by agent (${AGENTS.join("|")})`).option("--notify <amount>", "Fire macOS notification when cumulative cost crosses this USD threshold").action(async (opts) => {
|
|
3201
|
-
const { watchCosts } = await import("../chunks/watch-
|
|
3205
|
+
const { watchCosts } = await import("../chunks/watch-ksn2mezm.js");
|
|
3202
3206
|
await watchCosts({
|
|
3203
3207
|
interval: parsePositiveCliInteger(opts.interval ?? "10", "--interval"),
|
|
3204
3208
|
daemon: Boolean(opts.daemon),
|
|
@@ -3339,16 +3343,16 @@ projectCmd.command("show <nameOrPath>").description("Detailed project breakdown
|
|
|
3339
3343
|
});
|
|
3340
3344
|
var configCmd = program.command("config").description("Manage economy configuration");
|
|
3341
3345
|
configCmd.command("set <key> <value>").description("Set a config value").action(async (_key, _value) => {
|
|
3342
|
-
const { setConfigValue } = await import("../chunks/config-
|
|
3346
|
+
const { setConfigValue } = await import("../chunks/config-mjgbekxj.js");
|
|
3343
3347
|
setConfigValue(_key, _value);
|
|
3344
3348
|
console.log(chalk3.green(`\u2713 ${_key} = ${_value}`));
|
|
3345
3349
|
});
|
|
3346
3350
|
configCmd.command("get <key>").description("Get a config value").action(async (key) => {
|
|
3347
|
-
const { getConfigValue } = await import("../chunks/config-
|
|
3351
|
+
const { getConfigValue } = await import("../chunks/config-mjgbekxj.js");
|
|
3348
3352
|
console.log(getConfigValue(key) ?? chalk3.dim("(not set)"));
|
|
3349
3353
|
});
|
|
3350
3354
|
configCmd.command("webhook-test").description("Send a test payload to the configured webhook URL").action(async () => {
|
|
3351
|
-
const { loadConfig } = await import("../chunks/config-
|
|
3355
|
+
const { loadConfig } = await import("../chunks/config-mjgbekxj.js");
|
|
3352
3356
|
const config = loadConfig();
|
|
3353
3357
|
const url = config["webhook-url"];
|
|
3354
3358
|
if (!url) {
|
|
@@ -3382,7 +3386,7 @@ configCmd.command("webhook-test").description("Send a test payload to the config
|
|
|
3382
3386
|
}
|
|
3383
3387
|
});
|
|
3384
3388
|
configCmd.action(async () => {
|
|
3385
|
-
const { loadConfig } = await import("../chunks/config-
|
|
3389
|
+
const { loadConfig } = await import("../chunks/config-mjgbekxj.js");
|
|
3386
3390
|
const config = loadConfig();
|
|
3387
3391
|
console.log();
|
|
3388
3392
|
printTable(["Key", "Value"], Object.entries(config).map(([k, v]) => [k, String(v)]));
|
|
@@ -3434,7 +3438,7 @@ pricingCmd.command("remove <model>").description("Remove pricing for a model").a
|
|
|
3434
3438
|
});
|
|
3435
3439
|
program.command("serve").description("Start the REST API server").option("-p, --port <port>", "Port", "3456").action(async (opts) => {
|
|
3436
3440
|
const port = parseCliPort(opts.port ?? "3456", "--port");
|
|
3437
|
-
const { startServer } = await import("../chunks/serve-
|
|
3441
|
+
const { startServer } = await import("../chunks/serve-tmv8zgvh.js");
|
|
3438
3442
|
startServer(port);
|
|
3439
3443
|
});
|
|
3440
3444
|
program.command("mcp").description("Show MCP server install commands").option("--claude", "Install into Claude Code").option("--codex", "Install into Codex").option("--gemini", "Install into Gemini CLI").option("--all", "Install into all agents").action(async (opts) => {
|
|
@@ -3614,11 +3618,13 @@ program.command("compare <period1> <period2>").description("Compare two periods
|
|
|
3614
3618
|
console.log(chalk3.bold.cyan(` ${p1} vs ${p2}`));
|
|
3615
3619
|
console.log();
|
|
3616
3620
|
printTable(["Metric", p1, p2, "Change"], [
|
|
3617
|
-
["
|
|
3621
|
+
["Usage value", formatComparisonValue(a), formatComparisonValue(b), comparisonValueChange(a, b)],
|
|
3618
3622
|
["Sessions", fmtCount(a.sessions), fmtCount(b.sessions), delta(a.sessions, b.sessions)],
|
|
3619
3623
|
["Requests", fmtCount(a.requests), fmtCount(b.requests), delta(a.requests, b.requests)],
|
|
3620
3624
|
["Tokens", fmtTokens2(a.tokens), fmtTokens2(b.tokens), delta(a.tokens, b.tokens)]
|
|
3621
3625
|
]);
|
|
3626
|
+
console.log(`${p1}: ${formatSummaryCoverage(a.money)}`);
|
|
3627
|
+
console.log(`${p2}: ${formatSummaryCoverage(b.money)}`);
|
|
3622
3628
|
console.log();
|
|
3623
3629
|
});
|
|
3624
3630
|
program.command("forecast").description("Project end-of-month cost based on current burn rate").action(async () => {
|
|
@@ -3795,7 +3801,7 @@ billingCmd.command("sync").description("Sync actual billing from Anthropic, Open
|
|
|
3795
3801
|
console.log(chalk3.green(`\u2713 pushed ${result.total} billing rows to the shared API`));
|
|
3796
3802
|
return;
|
|
3797
3803
|
}
|
|
3798
|
-
const { openDatabase } = await import("../chunks/sqlite-store-
|
|
3804
|
+
const { openDatabase } = await import("../chunks/sqlite-store-r219qrjt.js");
|
|
3799
3805
|
const db = openDatabase();
|
|
3800
3806
|
const doAll = !opts.anthropic && !opts.openai && !opts.gemini;
|
|
3801
3807
|
if (opts.anthropic || doAll) {
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
export type Provider = 'github' | 'aws' | 'blacksmith';
|
|
2
|
+
export interface Window {
|
|
3
|
+
start: string;
|
|
4
|
+
endExclusive: string;
|
|
5
|
+
timeZone: string;
|
|
6
|
+
}
|
|
7
|
+
/** Metadata from a trusted read/export, not a credential or authorization grant. */
|
|
8
|
+
export interface Capture {
|
|
9
|
+
provider: Provider;
|
|
10
|
+
account: string;
|
|
11
|
+
sourceId: string;
|
|
12
|
+
revision: string;
|
|
13
|
+
supersedes?: string;
|
|
14
|
+
observedAt: string;
|
|
15
|
+
window: Window;
|
|
16
|
+
currency: string;
|
|
17
|
+
currencySource: string;
|
|
18
|
+
complete: boolean;
|
|
19
|
+
awsQuery?: {
|
|
20
|
+
metric: 'UnblendedCost';
|
|
21
|
+
groupBy: 'SERVICE';
|
|
22
|
+
granularity: 'MONTHLY';
|
|
23
|
+
filter: null;
|
|
24
|
+
};
|
|
25
|
+
pages: Array<{
|
|
26
|
+
cursor: string | null;
|
|
27
|
+
nextCursor: string | null;
|
|
28
|
+
body: string;
|
|
29
|
+
}>;
|
|
30
|
+
}
|
|
31
|
+
export interface Authority {
|
|
32
|
+
provider: Provider;
|
|
33
|
+
account: string;
|
|
34
|
+
currency: string;
|
|
35
|
+
}
|
|
36
|
+
export interface CostRow {
|
|
37
|
+
id: string;
|
|
38
|
+
date: string;
|
|
39
|
+
dimensions: Record<string, string>;
|
|
40
|
+
kind: 'usage' | 'tax' | 'credit' | 'subscription' | 'included';
|
|
41
|
+
net: string;
|
|
42
|
+
gross?: string;
|
|
43
|
+
discount?: string;
|
|
44
|
+
quantity?: string;
|
|
45
|
+
unit?: string;
|
|
46
|
+
estimated: boolean;
|
|
47
|
+
}
|
|
48
|
+
export interface Snapshot {
|
|
49
|
+
schemaVersion: 1;
|
|
50
|
+
provider: Provider;
|
|
51
|
+
account: string;
|
|
52
|
+
sourceId: string;
|
|
53
|
+
revision: string;
|
|
54
|
+
supersedes: string | null;
|
|
55
|
+
observedAt: string;
|
|
56
|
+
window: Window;
|
|
57
|
+
currency: string;
|
|
58
|
+
currencySource: string;
|
|
59
|
+
basis: 'usage_report' | 'cost_explorer' | 'invoice';
|
|
60
|
+
scopeId: string;
|
|
61
|
+
contentHash: string;
|
|
62
|
+
snapshotId: string;
|
|
63
|
+
pageHashes: string[];
|
|
64
|
+
rows: CostRow[];
|
|
65
|
+
excludedRows: number;
|
|
66
|
+
total: string;
|
|
67
|
+
tax: string | null;
|
|
68
|
+
paymentStatus: 'unknown';
|
|
69
|
+
}
|
|
70
|
+
export declare function fail(code: string): never;
|
|
71
|
+
export declare function object(value: unknown): Record<string, unknown>;
|
|
72
|
+
export declare function list(value: unknown): unknown[];
|
|
73
|
+
/** Bounded metadata labels; URLs and control characters are refused. Not a secret scanner. */
|
|
74
|
+
export declare function label(value: unknown): string;
|
|
75
|
+
export declare function date(value: unknown): string;
|
|
76
|
+
export declare function stable(value: unknown): string;
|
|
77
|
+
export declare const hash: (value: string) => string;
|
|
78
|
+
export declare function validateCapture(c: Capture, authority: Authority): Record<string, unknown>[];
|
|
79
|
+
export declare function inWindow(day: unknown, c: Capture): string;
|
|
80
|
+
export declare function finish(c: Capture, rows: CostRow[], basis: Snapshot['basis'], excludedRows?: number): Snapshot;
|
|
81
|
+
export declare function admitRevision(history: readonly Snapshot[], next: Snapshot): 'append' | 'replay';
|
|
82
|
+
/** Totals stay partitioned by provider/account/currency/basis/window; no grand total. */
|
|
83
|
+
export declare function reconcile(history: readonly Snapshot[]): Snapshot[];
|
|
84
|
+
//# sourceMappingURL=contract.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contract.d.ts","sourceRoot":"","sources":["../../src/cost-imports/contract.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/** Exact, bounded decimal arithmetic. Provider precision is retained until display. */
|
|
2
|
+
export declare function decimal(value: unknown): string;
|
|
3
|
+
export declare function add(...values: string[]): string;
|
|
4
|
+
export declare function negate(value: string): string;
|
|
5
|
+
export declare function within(left: string, right: string, tolerance?: string): boolean;
|
|
6
|
+
//# sourceMappingURL=decimal.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decimal.d.ts","sourceRoot":"","sources":["../../src/cost-imports/decimal.ts"],"names":[],"mappings":"AAAA,uFAAuF;AACvF,wBAAgB,OAAO,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAc9C;AAKD,wBAAgB,GAAG,CAAC,GAAG,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,CAK/C;AACD,wBAAgB,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAAyE;AACtH,wBAAgB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,SAAM,GAAG,OAAO,CAI5E"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { type Capture, type Authority, type Snapshot } from './contract.js';
|
|
2
|
+
/** No HTTP or state access: normalize one fully captured provider report. */
|
|
3
|
+
export declare function normalizeCostImport(capture: Capture, authority: Authority): Snapshot;
|
|
4
|
+
//# sourceMappingURL=providers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"providers.d.ts","sourceRoot":"","sources":["../../src/cost-imports/providers.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,OAAO,EAAE,KAAK,SAAS,EAAgB,KAAK,QAAQ,EAA8E,MAAM,eAAe,CAAA;AAUrK,6EAA6E;AAC7E,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,GAAG,QAAQ,CAKpF"}
|
package/dist/index.js
CHANGED
|
@@ -4,6 +4,7 @@ import {
|
|
|
4
4
|
COST_BASIS,
|
|
5
5
|
MAX_INGEST_BYTES,
|
|
6
6
|
__require,
|
|
7
|
+
buildCostSummary,
|
|
7
8
|
cacheDir,
|
|
8
9
|
calendarPeriodBounds,
|
|
9
10
|
calendarPeriodWhere,
|
|
@@ -56,13 +57,61 @@ import {
|
|
|
56
57
|
upsertSubscription,
|
|
57
58
|
usageSnapshotFilterForPeriod,
|
|
58
59
|
validateIngest
|
|
59
|
-
} from "./chunks/index-
|
|
60
|
+
} from "./chunks/index-t0n32g8r.js";
|
|
61
|
+
// src/lib/comparison-contract.ts
|
|
62
|
+
function comparisonDateBounds(from, to) {
|
|
63
|
+
const valid = (value) => /^\d{4}-\d{2}-\d{2}$/.test(value) && Number.isFinite(Date.parse(value + "T00:00:00Z")) && new Date(value + "T00:00:00Z").toISOString().slice(0, 10) === value;
|
|
64
|
+
if (!valid(from) || !valid(to) || from > to) {
|
|
65
|
+
throw new RangeError("from and to must be real YYYY-MM-DD UTC dates with from <= to");
|
|
66
|
+
}
|
|
67
|
+
const end = new Date(to + "T00:00:00Z");
|
|
68
|
+
end.setUTCDate(end.getUTCDate() + 1);
|
|
69
|
+
const exclusive = end.toISOString().slice(0, 10);
|
|
70
|
+
if (!valid(exclusive))
|
|
71
|
+
throw new RangeError("to exceeds the supported UTC date range");
|
|
72
|
+
return { time_zone: "UTC", start_date: from, end_date_exclusive: exclusive };
|
|
73
|
+
}
|
|
74
|
+
function requireCurrentRangeStats(value, from, to) {
|
|
75
|
+
if (!value || typeof value !== "object")
|
|
76
|
+
throw new Error("COMPARISON_REPORT_UNAVAILABLE: Invalid response");
|
|
77
|
+
const report = value;
|
|
78
|
+
let money;
|
|
79
|
+
try {
|
|
80
|
+
money = requireCurrentCostSummary(report.money);
|
|
81
|
+
} catch {
|
|
82
|
+
throw new Error("COMPARISON_REPORT_UNAVAILABLE: The service must support comparison coverage");
|
|
83
|
+
}
|
|
84
|
+
for (const key of ["sessions", "requests", "tokens"]) {
|
|
85
|
+
if (!Number.isSafeInteger(report[key]) || report[key] < 0)
|
|
86
|
+
throw new Error("COMPARISON_REPORT_UNAVAILABLE: Invalid " + key);
|
|
87
|
+
}
|
|
88
|
+
if (report.cost !== money.total_usd || report.requests !== money.request_rows || report.tokens !== money.tokens || money.session_only_sessions !== 0 || money.session_only_value_usd !== 0 || money.requests !== money.request_rows) {
|
|
89
|
+
throw new Error("COMPARISON_REPORT_UNAVAILABLE: Inconsistent monetary coverage");
|
|
90
|
+
}
|
|
91
|
+
const knownRows = money.request_rows - money.unknown_price_requests;
|
|
92
|
+
const completeness = money.request_rows === 0 ? "no_records" : money.unknown_price_requests === 0 ? "complete" : knownRows > 0 ? "partial" : "unavailable";
|
|
93
|
+
if (money.completeness !== completeness || knownRows === 0 && money.total_usd !== 0 || money.sessions > money.request_rows || money.request_rows === 0 && money.tokens !== 0) {
|
|
94
|
+
throw new Error("COMPARISON_REPORT_UNAVAILABLE: Inconsistent request coverage");
|
|
95
|
+
}
|
|
96
|
+
const bounds = money.period_bounds;
|
|
97
|
+
if (!bounds.start_date || !bounds.end_date_exclusive || bounds.start_date >= bounds.end_date_exclusive) {
|
|
98
|
+
throw new Error("COMPARISON_REPORT_UNAVAILABLE: Missing comparison dates");
|
|
99
|
+
}
|
|
100
|
+
if (from !== undefined || to !== undefined) {
|
|
101
|
+
const expected = comparisonDateBounds(from, to);
|
|
102
|
+
if (bounds.start_date !== expected.start_date || bounds.end_date_exclusive !== expected.end_date_exclusive) {
|
|
103
|
+
throw new Error("COMPARISON_REPORT_UNAVAILABLE: Response dates do not match the requested range");
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
return report;
|
|
107
|
+
}
|
|
108
|
+
|
|
60
109
|
// src/lib/store/index.ts
|
|
61
110
|
import { randomUUID } from "crypto";
|
|
62
111
|
// package.json
|
|
63
112
|
var package_default = {
|
|
64
113
|
name: "@hasna/economy",
|
|
65
|
-
version: "0.5.
|
|
114
|
+
version: "0.5.9",
|
|
66
115
|
description: "AI coding cost tracker \u2014 CLI + MCP server + REST API for Claude Code, Codex, OpenCode, Cursor, Pi, and Hermes, with legacy Gemini CLI session and Gemini API billing ingestion",
|
|
67
116
|
repository: {
|
|
68
117
|
type: "git",
|
|
@@ -1121,11 +1170,20 @@ function queryExportRows(db, type, period) {
|
|
|
1121
1170
|
return db.prepare(`SELECT * FROM economy_effective_sessions WHERE ${where} ORDER BY started_at DESC`).all();
|
|
1122
1171
|
}
|
|
1123
1172
|
function queryRangeStats(db, from, to) {
|
|
1124
|
-
const
|
|
1125
|
-
|
|
1126
|
-
|
|
1173
|
+
const bounds = comparisonDateBounds(from, to);
|
|
1174
|
+
const groups = db.prepare(`
|
|
1175
|
+
SELECT cost_basis, model, CASE WHEN cost_usd = 0 THEN 1 WHEN cost_usd < 0 THEN 2 ELSE 0 END AS zero_cost,
|
|
1176
|
+
SUM(cost_usd) AS cost_usd, COUNT(*) AS requests,
|
|
1177
|
+
COALESCE(SUM(input_tokens),0) AS input_tokens, COALESCE(SUM(output_tokens),0) AS output_tokens,
|
|
1178
|
+
COALESCE(SUM(cache_read_tokens),0) AS cache_read_tokens, COALESCE(SUM(cache_create_tokens),0) AS cache_create_tokens,
|
|
1179
|
+
COALESCE(SUM(cache_create_1h_tokens),0) AS cache_create_1h_tokens
|
|
1180
|
+
FROM economy_effective_requests WHERE DATE(timestamp) BETWEEN ? AND ?
|
|
1181
|
+
GROUP BY cost_basis, model, CASE WHEN cost_usd = 0 THEN 1 WHEN cost_usd < 0 THEN 2 ELSE 0 END
|
|
1182
|
+
`).all(from, to);
|
|
1183
|
+
const requestSessions = db.prepare("SELECT COUNT(DISTINCT session_id) AS sessions FROM economy_effective_requests WHERE DATE(timestamp) BETWEEN ? AND ?").get(from, to);
|
|
1184
|
+
const money = buildCostSummary("all", bounds, groups, { sessions: 0, requests: 0, tokens: 0, cost_usd: 0 }, requestSessions.sessions, listModelPricing(db));
|
|
1127
1185
|
const s = db.prepare(`SELECT COUNT(*) as sessions FROM economy_effective_sessions WHERE DATE(started_at) BETWEEN ? AND ?`).get(from, to);
|
|
1128
|
-
return { cost:
|
|
1186
|
+
return { cost: money.total_usd, money, requests: money.request_rows, tokens: money.tokens, sessions: s.sessions };
|
|
1129
1187
|
}
|
|
1130
1188
|
function queryForecast(db, now = new Date) {
|
|
1131
1189
|
const month = resolveReportingInterval({ kind: "calendar", period: "month" }, now);
|
|
@@ -1340,7 +1398,7 @@ class LocalStore {
|
|
|
1340
1398
|
_db;
|
|
1341
1399
|
async db() {
|
|
1342
1400
|
if (!this._db) {
|
|
1343
|
-
const { openDatabase } = await import("./chunks/sqlite-store-
|
|
1401
|
+
const { openDatabase } = await import("./chunks/sqlite-store-8t4anw98.js");
|
|
1344
1402
|
this._db = openDatabase();
|
|
1345
1403
|
ensurePricingSeeded(this._db);
|
|
1346
1404
|
}
|
|
@@ -1617,7 +1675,7 @@ class ApiStore {
|
|
|
1617
1675
|
return cloudListItems(this.cloud, "export", q({ type, period }));
|
|
1618
1676
|
}
|
|
1619
1677
|
async rangeStats(from, to) {
|
|
1620
|
-
return cloudObject(this.cloud, "/compare", q({ from, to }));
|
|
1678
|
+
return requireCurrentRangeStats(await cloudObject(this.cloud, "/compare", q({ from, to })), from, to);
|
|
1621
1679
|
}
|
|
1622
1680
|
async forecast() {
|
|
1623
1681
|
return cloudObject(this.cloud, "/forecast");
|
|
@@ -2287,18 +2345,19 @@ class IngestJournalMaintenance {
|
|
|
2287
2345
|
throw new Error("Journal maintenance limit must be 1\u201332");
|
|
2288
2346
|
await this.recover();
|
|
2289
2347
|
await verifyJournalAuthority(this.journal, this.cloud);
|
|
2290
|
-
const
|
|
2348
|
+
const sweepDeadline = Date.now() + 30000;
|
|
2291
2349
|
let retired = 0, bytes = 0;
|
|
2292
2350
|
let backend;
|
|
2293
2351
|
try {
|
|
2294
2352
|
const names = this.journal.names();
|
|
2295
2353
|
for (const name of names.filter((n) => n.endsWith(".intent.json"))) {
|
|
2296
|
-
if (retired >= limit || Date.now() >=
|
|
2354
|
+
if (retired >= limit || Date.now() >= sweepDeadline || retired > 0 && bytes >= 1048576)
|
|
2297
2355
|
break;
|
|
2298
2356
|
if (!names.includes(name.replace(".intent.", ".receipt.")))
|
|
2299
2357
|
continue;
|
|
2300
2358
|
const intent = this.journal.intent(name), receipt = this.journal.receipt(intent.command);
|
|
2301
|
-
|
|
2359
|
+
const deadline = Date.now() + 30000;
|
|
2360
|
+
backend = await this.backend(deadline);
|
|
2302
2361
|
const m = {
|
|
2303
2362
|
version: 1,
|
|
2304
2363
|
target: this.journal.target,
|
|
@@ -2334,7 +2393,8 @@ class IngestJournalMaintenance {
|
|
|
2334
2393
|
try {
|
|
2335
2394
|
await this.maintain();
|
|
2336
2395
|
} catch (error) {
|
|
2337
|
-
|
|
2396
|
+
const deferrable = error instanceof JournalMaintenanceError && ["recovery_not_configured", "self_host_trash_authority_required", "trash_version_mismatch", "recovery_authority_unavailable"].includes(error.reason);
|
|
2397
|
+
if (!deferrable || exists(this.control) || !this.journal.canStage(command))
|
|
2338
2398
|
throw error;
|
|
2339
2399
|
}
|
|
2340
2400
|
if (!this.journal.canStage(command))
|
package/dist/lib/analytics.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { CostSummary } from '../types/index.js';
|
|
1
2
|
import type { SqliteAdapter as Database } from '../db/sqlite-adapter.js';
|
|
2
3
|
export interface ProjectDetailModel {
|
|
3
4
|
model: string;
|
|
@@ -28,7 +29,9 @@ export type ExportType = 'sessions' | 'requests';
|
|
|
28
29
|
/** Raw rows for a CSV export. CSV formatting stays in the caller. */
|
|
29
30
|
export declare function queryExportRows(db: Database, type: ExportType, period: string): Array<Record<string, unknown>>;
|
|
30
31
|
export interface RangeStats {
|
|
32
|
+
/** Known selected-request usage value subtotal. Use money.complete_total_usd for a complete total, never payment. */
|
|
31
33
|
cost: number;
|
|
34
|
+
money: CostSummary;
|
|
32
35
|
requests: number;
|
|
33
36
|
tokens: number;
|
|
34
37
|
sessions: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"analytics.d.ts","sourceRoot":"","sources":["../../src/lib/analytics.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"analytics.d.ts","sourceRoot":"","sources":["../../src/lib/analytics.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AASpD,OAAO,KAAK,EAAE,aAAa,IAAI,QAAQ,EAAE,MAAM,yBAAyB,CAAA;AAIxE,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,EAAE,MAAM,CAAA;CACjB;AAED,MAAM,WAAW,oBAAoB;IACnC,EAAE,EAAE,MAAM,CAAA;IACV,cAAc,EAAE,MAAM,CAAA;IACtB,UAAU,EAAE,MAAM,CAAA;CACnB;AAED,MAAM,WAAW,aAAa;IAC5B,YAAY,EAAE,MAAM,CAAA;IACpB,YAAY,EAAE,MAAM,CAAA;IACpB,cAAc,EAAE,MAAM,CAAA;IACtB,YAAY,EAAE,MAAM,CAAA;IACpB,QAAQ,EAAE,MAAM,CAAA;IAChB,KAAK,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IAChD,MAAM,EAAE,kBAAkB,EAAE,CAAA;IAC5B,YAAY,EAAE,oBAAoB,EAAE,CAAA;CACrC;AAED,iFAAiF;AACjF,wBAAgB,kBAAkB,CAAC,EAAE,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,EAAE,GAAG,OAAa,GAAG,aAAa,GAAG,IAAI,CAoD3G;AAID,MAAM,MAAM,UAAU,GAAG,UAAU,GAAG,UAAU,CAAA;AAShD,qEAAqE;AACrE,wBAAgB,eAAe,CAC7B,EAAE,EAAE,QAAQ,EACZ,IAAI,EAAE,UAAU,EAChB,MAAM,EAAE,MAAM,GACb,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAOhC;AAID,MAAM,WAAW,UAAU;IACzB,qHAAqH;IACrH,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,WAAW,CAAA;IAClB,QAAQ,EAAE,MAAM,CAAA;IAChB,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,MAAM,CAAA;CACjB;AAED,+EAA+E;AAC/E,wBAAgB,eAAe,CAAC,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,UAAU,CAqBlF;AAID,MAAM,WAAW,YAAY;IAC3B,YAAY,EAAE,MAAM,CAAA;IACpB,aAAa,EAAE,MAAM,CAAA;IACrB,gBAAgB,EAAE,MAAM,CAAA;IACxB,aAAa,EAAE,MAAM,CAAA;IACrB,aAAa,EAAE,MAAM,CAAA;IACrB,mBAAmB,EAAE,MAAM,CAAA;IAC3B,mBAAmB,EAAE,MAAM,CAAA;IAC3B,YAAY,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAA;IACvD,kBAAkB,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAA;CAC9D;AAED,0DAA0D;AAC1D,wBAAgB,aAAa,CAAC,EAAE,EAAE,QAAQ,EAAE,GAAG,GAAE,IAAiB,GAAG,YAAY,CAiChF;AAID,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;IACd,UAAU,EAAE,MAAM,CAAA;IAClB,WAAW,EAAE,MAAM,CAAA;IACnB,QAAQ,EAAE,MAAM,CAAA;IAChB,IAAI,EAAE,MAAM,CAAA;CACb;AAED,iFAAiF;AACjF,wBAAgB,oBAAoB,CAAC,EAAE,EAAE,QAAQ,GAAG,eAAe,EAAE,CAWpE"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { RangeStats } from './analytics.js';
|
|
2
|
+
import type { CalendarPeriodBounds } from './periods.js';
|
|
3
|
+
export declare function comparisonDateBounds(from: string, to: string): CalendarPeriodBounds;
|
|
4
|
+
/** Old servers' bare cost sums cannot satisfy the comparison coverage contract. */
|
|
5
|
+
export declare function requireCurrentRangeStats(value: unknown, from?: string, to?: string): RangeStats;
|
|
6
|
+
export declare function formatComparisonValue(report: RangeStats): string;
|
|
7
|
+
export declare function comparisonValueChange(left: RangeStats, right: RangeStats): string;
|
|
8
|
+
//# sourceMappingURL=comparison-contract.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"comparison-contract.d.ts","sourceRoot":"","sources":["../../src/lib/comparison-contract.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAA;AAChD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAA;AAGxD,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,oBAAoB,CAYnF;AAED,mFAAmF;AACnF,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,MAAM,GAAG,UAAU,CAiC/F;AAED,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,CAEhE;AAED,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,UAAU,GAAG,MAAM,CASjF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"comparison-test-contract.d.ts","sourceRoot":"","sources":["../../src/lib/comparison-test-contract.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAA;AAM5D,wBAAsB,wBAAwB,CAAC,EAAE,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAwF/E"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ingest-journal-maintenance.d.ts","sourceRoot":"","sources":["../../src/lib/ingest-journal-maintenance.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"ingest-journal-maintenance.d.ts","sourceRoot":"","sources":["../../src/lib/ingest-journal-maintenance.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,oBAAoB,CAAA;AACnE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAA;AACtD,OAAO,EAAe,aAAa,EAAqF,MAAM,qBAAqB,CAAA;AAKnJ,qBAAa,uBAAwB,SAAQ,KAAK;IAEpC,QAAQ,CAAC,MAAM,EAAE,MAAM;IAAE,QAAQ,CAAC,MAAM,EAAE,MAAM;IAD5D,QAAQ,CAAC,IAAI,yCAAwC;gBAChC,MAAM,EAAE,MAAM,EAAW,MAAM,EAAE,MAAM;CAI7D;AACD,UAAU,KAAK;IAAG,EAAE,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE;AACrJ,UAAU,SAAS;IAAG,EAAE,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE;AAC7J,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,CAAA;IAC1C,MAAM,IAAI,OAAO,CAAC;QAAE,OAAO,EAAE;YAAE,EAAE,EAAE,MAAM,CAAA;SAAE,GAAG,IAAI,CAAC;QAAC,aAAa,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IAC5E,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IAC3E,OAAO,EAAE;QAAE,IAAI,CAAC,EAAE,EAAE,MAAM,GAAG,SAAS,CAAA;KAAE,CAAA;IACxC,GAAG,EAAE;QAAE,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,CAAA;KAAE,CAAA;IACxC,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,aAAa,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,KAAK,CAAC,CAAA;IACvE,OAAO,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE;QAAE,iBAAiB,EAAE,OAAO,CAAA;KAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;CAC/E;AACD,MAAM,MAAM,sBAAsB,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,KAAK,OAAO,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,eAAe,CAAC,CAAA;AAkCrK;iFACiF;AACjF,wBAAsB,sBAAsB,CAAC,OAAO,EAAE,aAAa,EAAE,KAAK,EAAE,yBAAyB,GAAG,OAAO,CAAC,IAAI,CAAC,CAWpH;AAED;uEACuE;AACvE,wBAAgB,eAAe,CAAC,KAAK,EAAE,yBAAyB,EAAE,GAAG,oBAAc,GAAG,sBAAsB,CAgB3G;AAED;;oEAEoE;AACpE,qBAAa,wBAAwB;IAGvB,QAAQ,CAAC,OAAO,EAAE,aAAa;IAAE,QAAQ,CAAC,KAAK,EAAE,yBAAyB;IACpF,QAAQ,CAAC,OAAO;IAHlB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAA;gBACT,OAAO,EAAE,aAAa,EAAW,KAAK,EAAE,yBAAyB,EAC3E,OAAO,yBAAyB;IAK3C,OAAO,CAAC,QAAQ;IAahB,OAAO,CAAC,OAAO;YAKD,OAAO;YAsBP,KAAK;YAML,QAAQ;IA2BtB,gFAAgF;IAC1E,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;YAQhB,MAAM;IA+Bd,QAAQ,CAAC,KAAK,SAAK,GAAG,OAAO,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;IAoCrE,KAAK,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;CAcjD"}
|