@sunasteriskrnd/takumi 1.0.0-dev.43 → 1.0.0-dev.44
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +139 -22
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -19815,7 +19815,7 @@ var package_default;
|
|
|
19815
19815
|
var init_package = __esm(() => {
|
|
19816
19816
|
package_default = {
|
|
19817
19817
|
name: "@sunasteriskrnd/takumi",
|
|
19818
|
-
version: "1.0.0-dev.
|
|
19818
|
+
version: "1.0.0-dev.44",
|
|
19819
19819
|
description: "CLI tool for bootstrapping and managing Takumi projects",
|
|
19820
19820
|
type: "module",
|
|
19821
19821
|
repository: {
|
|
@@ -53485,6 +53485,7 @@ function tryOpenBrowser(target) {
|
|
|
53485
53485
|
}
|
|
53486
53486
|
|
|
53487
53487
|
// src/domains/sessions/server.ts
|
|
53488
|
+
init_logger();
|
|
53488
53489
|
import * as http from "node:http";
|
|
53489
53490
|
|
|
53490
53491
|
// src/domains/sessions/analytics.ts
|
|
@@ -53521,16 +53522,26 @@ function accumulateTokens(a3, b3) {
|
|
|
53521
53522
|
a3.cacheRead += b3.cacheRead;
|
|
53522
53523
|
a3.cacheWrite += b3.cacheWrite;
|
|
53523
53524
|
}
|
|
53524
|
-
function
|
|
53525
|
+
function buildDenseWindow(byDay, startDayMs, endDayMs) {
|
|
53525
53526
|
const out = [];
|
|
53526
|
-
|
|
53527
|
-
|
|
53528
|
-
const date = dayKey(todayMs - i * DAY_MS);
|
|
53527
|
+
for (let ms = startDayMs;ms <= endDayMs; ms += DAY_MS) {
|
|
53528
|
+
const date = dayKey(ms);
|
|
53529
53529
|
out.push({ date, count: byDay.get(date) ?? 0 });
|
|
53530
53530
|
}
|
|
53531
53531
|
return out;
|
|
53532
53532
|
}
|
|
53533
|
-
function
|
|
53533
|
+
function windowBounds(now, range) {
|
|
53534
|
+
if (!range) {
|
|
53535
|
+
const todayMs = Date.parse(`${dayKey(now)}T00:00:00.000Z`);
|
|
53536
|
+
return { start: todayMs - (LAST_N_DAYS - 1) * DAY_MS, end: todayMs };
|
|
53537
|
+
}
|
|
53538
|
+
const lo = Math.min(range.from, range.to);
|
|
53539
|
+
const hi = Math.max(range.from, range.to);
|
|
53540
|
+
const end = Date.parse(`${dayKey(hi)}T00:00:00.000Z`);
|
|
53541
|
+
const start = Math.max(Date.parse(`${dayKey(lo)}T00:00:00.000Z`), end - (PER_DAY_MAX - 1) * DAY_MS);
|
|
53542
|
+
return { start, end };
|
|
53543
|
+
}
|
|
53544
|
+
function foldAnalytics(aggregates, now, range) {
|
|
53534
53545
|
const totals = { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 };
|
|
53535
53546
|
const eventsByDay = new Map;
|
|
53536
53547
|
const tokensByDow = new Map;
|
|
@@ -53585,7 +53596,8 @@ function foldAnalytics(aggregates, now) {
|
|
|
53585
53596
|
const perDay = [...eventsByDay.entries()].filter(([date]) => Date.parse(`${date}T00:00:00.000Z`) >= oldestAllowedMs).map(([date, count]) => ({ date, count })).sort((a3, b3) => a3.date.localeCompare(b3.date));
|
|
53586
53597
|
const byProjectAll = [...tokensByProject.entries()].map(([label, tokens]) => ({ label, tokens })).sort((a3, b3) => b3.tokens - a3.tokens || a3.label.localeCompare(b3.label));
|
|
53587
53598
|
const byProject = byProjectAll.slice(0, TOP_PROJECTS);
|
|
53588
|
-
const
|
|
53599
|
+
const { start: windowStart, end: windowEnd } = windowBounds(now, range);
|
|
53600
|
+
const daily = buildDenseWindow(tokensByDay, windowStart, windowEnd);
|
|
53589
53601
|
const rankedModels = [...tokensByModel.entries()].map(([label, tokens]) => ({ label, tokens, total: sumTokens(tokens) })).filter((m2) => m2.total > 0).sort((a3, b3) => b3.total - a3.total || a3.label.localeCompare(b3.label)).slice(0, TOP_PROJECTS);
|
|
53590
53602
|
const byModel = rankedModels.map(({ label, total }) => ({ label, tokens: total }));
|
|
53591
53603
|
const byModelDetailed = rankedModels.map(({ label, tokens }) => ({ label, tokens }));
|
|
@@ -53602,7 +53614,7 @@ function foldAnalytics(aggregates, now) {
|
|
|
53602
53614
|
events: {
|
|
53603
53615
|
total: eventTotal,
|
|
53604
53616
|
perDay,
|
|
53605
|
-
last30:
|
|
53617
|
+
last30: buildDenseWindow(eventsByDay, windowStart, windowEnd)
|
|
53606
53618
|
},
|
|
53607
53619
|
tokens: {
|
|
53608
53620
|
byType: { ...totals },
|
|
@@ -54912,6 +54924,24 @@ function invalidate() {
|
|
|
54912
54924
|
}
|
|
54913
54925
|
}
|
|
54914
54926
|
|
|
54927
|
+
// src/domains/sessions/session-meta-filter.ts
|
|
54928
|
+
function filterSessionMetas(metas, filter) {
|
|
54929
|
+
return metas.filter((m2) => {
|
|
54930
|
+
if (filter.project !== undefined && m2.project !== filter.project)
|
|
54931
|
+
return false;
|
|
54932
|
+
if (filter.from === undefined && filter.to === undefined)
|
|
54933
|
+
return true;
|
|
54934
|
+
const ms = m2.startedAt === null ? Number.NaN : Date.parse(m2.startedAt);
|
|
54935
|
+
if (Number.isNaN(ms))
|
|
54936
|
+
return false;
|
|
54937
|
+
if (filter.from !== undefined && ms < filter.from)
|
|
54938
|
+
return false;
|
|
54939
|
+
if (filter.to !== undefined && ms > filter.to)
|
|
54940
|
+
return false;
|
|
54941
|
+
return true;
|
|
54942
|
+
});
|
|
54943
|
+
}
|
|
54944
|
+
|
|
54915
54945
|
// src/domains/sessions/store/ingest.ts
|
|
54916
54946
|
import { createHash as createHash9 } from "node:crypto";
|
|
54917
54947
|
import { closeSync as closeSync4, openSync as openSync4, readSync as readSync4, readdirSync as readdirSync6, statSync as statSync5 } from "node:fs";
|
|
@@ -64676,6 +64706,32 @@ async function readStoreAggregates(db) {
|
|
|
64676
64706
|
get2(r2.session_id).agentCount += Number(r2.n ?? 0);
|
|
64677
64707
|
return map;
|
|
64678
64708
|
}
|
|
64709
|
+
async function attachSessionTokenTotals(db, list2) {
|
|
64710
|
+
const totals = await readSessionTokenTotals(db);
|
|
64711
|
+
return list2.map((s) => {
|
|
64712
|
+
const tokens = totals.get(s.id);
|
|
64713
|
+
return tokens ? { ...s, tokens } : s;
|
|
64714
|
+
});
|
|
64715
|
+
}
|
|
64716
|
+
async function readSessionTokenTotals(db) {
|
|
64717
|
+
const rows = await db.selectFrom("event").where("type", "=", "tokens").select((eb) => [
|
|
64718
|
+
"session_id",
|
|
64719
|
+
eb.fn.sum("input").as("input"),
|
|
64720
|
+
eb.fn.sum("output").as("output"),
|
|
64721
|
+
eb.fn.sum("cache_read").as("cache_read"),
|
|
64722
|
+
eb.fn.sum("cache_write").as("cache_write")
|
|
64723
|
+
]).groupBy("session_id").execute();
|
|
64724
|
+
const map = new Map;
|
|
64725
|
+
for (const r2 of rows) {
|
|
64726
|
+
map.set(r2.session_id, {
|
|
64727
|
+
input: Number(r2.input ?? 0),
|
|
64728
|
+
output: Number(r2.output ?? 0),
|
|
64729
|
+
cacheCreate: Number(r2.cache_write ?? 0),
|
|
64730
|
+
cacheRead: Number(r2.cache_read ?? 0)
|
|
64731
|
+
});
|
|
64732
|
+
}
|
|
64733
|
+
return map;
|
|
64734
|
+
}
|
|
64679
64735
|
function buildAggregatesFromStore(sessions, store) {
|
|
64680
64736
|
return sessions.map((s) => {
|
|
64681
64737
|
const a3 = store.get(s.id) ?? emptyStoreAggregate();
|
|
@@ -64692,30 +64748,52 @@ function buildAggregatesFromStore(sessions, store) {
|
|
|
64692
64748
|
}
|
|
64693
64749
|
|
|
64694
64750
|
// src/domains/sessions/analytics-source.ts
|
|
64695
|
-
var
|
|
64751
|
+
var DAY_MS2 = 24 * 60 * 60 * 1000;
|
|
64752
|
+
var DEFAULT_WINDOW_DAYS = 30;
|
|
64753
|
+
var cache2 = new Map;
|
|
64696
64754
|
var storeHandle = null;
|
|
64697
64755
|
function setStore(handle) {
|
|
64698
64756
|
storeHandle = handle;
|
|
64699
64757
|
}
|
|
64700
64758
|
function invalidate2() {
|
|
64701
|
-
cache2 =
|
|
64759
|
+
cache2 = new Map;
|
|
64702
64760
|
}
|
|
64703
|
-
|
|
64761
|
+
var cacheKey = (o2) => `${o2.from ?? ""}|${o2.to ?? ""}|${o2.project === undefined ? "" : `p:${o2.project}`}`;
|
|
64762
|
+
function rangeOf(o2, now) {
|
|
64763
|
+
if (o2.from === undefined && o2.to === undefined)
|
|
64764
|
+
return;
|
|
64765
|
+
const to = o2.to ?? now;
|
|
64766
|
+
const from = o2.from ?? to - (DEFAULT_WINDOW_DAYS - 1) * DAY_MS2;
|
|
64767
|
+
return { from, to };
|
|
64768
|
+
}
|
|
64769
|
+
async function computeFromStore(handle, opts, now) {
|
|
64770
|
+
const refresh2 = opts.refresh ?? false;
|
|
64704
64771
|
if (refresh2)
|
|
64705
64772
|
await ingestAll(handle, { refresh: true });
|
|
64706
64773
|
const sessions = await list({ refresh: refresh2 });
|
|
64774
|
+
const metas = filterSessionMetas(sessions.map((s) => ({ id: s.id, startedAt: s.startedAt, project: s.project })), { from: opts.from, to: opts.to, project: opts.project });
|
|
64707
64775
|
const storeAggs = await readStoreAggregates(handle.db);
|
|
64708
|
-
const
|
|
64709
|
-
return
|
|
64776
|
+
const payload = foldAnalytics(buildAggregatesFromStore(metas, storeAggs), now, rangeOf(opts, now));
|
|
64777
|
+
return {
|
|
64778
|
+
...payload,
|
|
64779
|
+
filters: {
|
|
64780
|
+
from: opts.from ?? null,
|
|
64781
|
+
to: opts.to ?? null,
|
|
64782
|
+
project: opts.project ?? null
|
|
64783
|
+
}
|
|
64784
|
+
};
|
|
64710
64785
|
}
|
|
64711
64786
|
async function getAnalytics(opts = {}) {
|
|
64712
|
-
|
|
64713
|
-
|
|
64787
|
+
const key = cacheKey(opts);
|
|
64788
|
+
const hit = cache2.get(key);
|
|
64789
|
+
if (hit && !opts.refresh)
|
|
64790
|
+
return hit;
|
|
64714
64791
|
if (!storeHandle)
|
|
64715
64792
|
throw new StoreUnavailableError;
|
|
64716
64793
|
const now = Date.now();
|
|
64717
|
-
|
|
64718
|
-
|
|
64794
|
+
const payload = await computeFromStore(storeHandle, opts, now);
|
|
64795
|
+
cache2.set(key, payload);
|
|
64796
|
+
return payload;
|
|
64719
64797
|
}
|
|
64720
64798
|
|
|
64721
64799
|
// src/domains/sessions/origin-allowlist.ts
|
|
@@ -64743,13 +64821,33 @@ function isAllowedOrigin(origin) {
|
|
|
64743
64821
|
return LOOPBACK_HOST_PATTERN.test(origin);
|
|
64744
64822
|
}
|
|
64745
64823
|
|
|
64824
|
+
// src/domains/sessions/range-params.ts
|
|
64825
|
+
function intParam(search, key) {
|
|
64826
|
+
const raw = search.get(key);
|
|
64827
|
+
if (raw === null || raw === "")
|
|
64828
|
+
return;
|
|
64829
|
+
const n = Number(raw);
|
|
64830
|
+
if (!Number.isInteger(n) || n < 0)
|
|
64831
|
+
return { error: `invalid ${key}: ${raw}` };
|
|
64832
|
+
return n;
|
|
64833
|
+
}
|
|
64834
|
+
function parseRangeProjectParams(search) {
|
|
64835
|
+
const from = intParam(search, "from");
|
|
64836
|
+
if (typeof from === "object")
|
|
64837
|
+
return from;
|
|
64838
|
+
const to = intParam(search, "to");
|
|
64839
|
+
if (typeof to === "object")
|
|
64840
|
+
return to;
|
|
64841
|
+
return { from, to, project: search.get("project") || undefined };
|
|
64842
|
+
}
|
|
64843
|
+
|
|
64746
64844
|
// src/domains/sessions/store/bridge-store.ts
|
|
64747
64845
|
init_logger();
|
|
64748
64846
|
|
|
64749
64847
|
// src/domains/sessions/store/prune.ts
|
|
64750
64848
|
import { existsSync as existsSync34, statSync as statSync6 } from "node:fs";
|
|
64751
64849
|
init_logger();
|
|
64752
|
-
var
|
|
64850
|
+
var DAY_MS3 = 24 * 60 * 60 * 1000;
|
|
64753
64851
|
var DEFAULT_RETENTION_DAYS = 180;
|
|
64754
64852
|
var SIZE_DELETE_BATCH = 500;
|
|
64755
64853
|
var SIZE_PRUNE_MAX_ITERS = 200;
|
|
@@ -64775,7 +64873,7 @@ async function runPrune(handle, opts = {}) {
|
|
|
64775
64873
|
const now = opts.now ?? Date.now();
|
|
64776
64874
|
const retentionDays = opts.retentionDays ?? DEFAULT_RETENTION_DAYS;
|
|
64777
64875
|
const dbPath = opts.dbPath ?? getConsoleStorePath();
|
|
64778
|
-
const cutoff = now - retentionDays *
|
|
64876
|
+
const cutoff = now - retentionDays * DAY_MS3;
|
|
64779
64877
|
await db.deleteFrom("event").where("ts", "<", cutoff).execute();
|
|
64780
64878
|
if (opts.maxSizeMb && opts.maxSizeMb > 0) {
|
|
64781
64879
|
const cap = opts.maxSizeMb * 1024 * 1024;
|
|
@@ -64953,6 +65051,17 @@ async function attachStore(deps = {}) {
|
|
|
64953
65051
|
}
|
|
64954
65052
|
|
|
64955
65053
|
// src/domains/sessions/server.ts
|
|
65054
|
+
var tokenStore = null;
|
|
65055
|
+
async function withTokenTotals(list2) {
|
|
65056
|
+
if (!tokenStore)
|
|
65057
|
+
return list2;
|
|
65058
|
+
try {
|
|
65059
|
+
return await attachSessionTokenTotals(tokenStore.db, list2);
|
|
65060
|
+
} catch (err) {
|
|
65061
|
+
logger.verbose(`console bridge: token totals enrichment failed (${String(err)})`);
|
|
65062
|
+
return list2;
|
|
65063
|
+
}
|
|
65064
|
+
}
|
|
64956
65065
|
var PORT_BUMP_MAX = 9;
|
|
64957
65066
|
function applyCorsHeaders(req, res) {
|
|
64958
65067
|
const origin = req.headers.origin;
|
|
@@ -65010,15 +65119,20 @@ async function route(req, res, version3) {
|
|
|
65010
65119
|
if (refresh2)
|
|
65011
65120
|
invalidate();
|
|
65012
65121
|
const list2 = await list({ refresh: refresh2 });
|
|
65013
|
-
sendJSON(res, 200, list2);
|
|
65122
|
+
sendJSON(res, 200, await withTokenTotals(list2));
|
|
65014
65123
|
return;
|
|
65015
65124
|
}
|
|
65016
65125
|
if (pathname === "/api/analytics") {
|
|
65017
65126
|
const refresh2 = url.searchParams.get("refresh") === "1";
|
|
65127
|
+
const rp = parseRangeProjectParams(url.searchParams);
|
|
65128
|
+
if ("error" in rp) {
|
|
65129
|
+
sendJSON(res, 400, { error: rp.error });
|
|
65130
|
+
return;
|
|
65131
|
+
}
|
|
65018
65132
|
if (refresh2)
|
|
65019
65133
|
invalidate2();
|
|
65020
65134
|
try {
|
|
65021
|
-
const payload = await getAnalytics({ refresh: refresh2 });
|
|
65135
|
+
const payload = await getAnalytics({ refresh: refresh2, ...rp });
|
|
65022
65136
|
sendJSON(res, 200, payload);
|
|
65023
65137
|
} catch (err) {
|
|
65024
65138
|
if (err instanceof StoreUnavailableError) {
|
|
@@ -65091,6 +65205,7 @@ function start(options2 = {}) {
|
|
|
65091
65205
|
close: async () => {
|
|
65092
65206
|
if (attached) {
|
|
65093
65207
|
setStore(null);
|
|
65208
|
+
tokenStore = null;
|
|
65094
65209
|
await attached.stop().catch(() => {});
|
|
65095
65210
|
}
|
|
65096
65211
|
await closeServer();
|
|
@@ -65101,8 +65216,10 @@ function start(options2 = {}) {
|
|
|
65101
65216
|
};
|
|
65102
65217
|
const doAttach = options2.attachStore ?? attachStore;
|
|
65103
65218
|
doAttach({ onInvalidate: () => invalidate2() }).then((attached) => {
|
|
65104
|
-
if (attached)
|
|
65219
|
+
if (attached) {
|
|
65105
65220
|
setStore(attached.handle);
|
|
65221
|
+
tokenStore = attached.handle;
|
|
65222
|
+
}
|
|
65106
65223
|
finish(attached);
|
|
65107
65224
|
}).catch(() => finish(null));
|
|
65108
65225
|
});
|