token-furnace 0.1.1 → 0.1.2
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/cli.d.ts +5 -2
- package/dist/cli.js +42 -18
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.d.ts
CHANGED
|
@@ -11,8 +11,11 @@ interface SessionRepository {
|
|
|
11
11
|
* gone from disk are dropped. The repository keeps the rest as they are.
|
|
12
12
|
*/
|
|
13
13
|
changed(files: SourceFile[]): SourceFile[];
|
|
14
|
-
/**
|
|
15
|
-
|
|
14
|
+
/**
|
|
15
|
+
* Every session held, in scan order: the order the analysis ranks ties by. With a cutoff, each
|
|
16
|
+
* session keeps only the turns at or after it, so the report reads no turn the analysis skips.
|
|
17
|
+
*/
|
|
18
|
+
all(cutoff?: Date): SessionInput[];
|
|
16
19
|
/** Store one parsed file, with its size: the two fields that say when to reparse it. */
|
|
17
20
|
save(session: SessionInput, size: number): void;
|
|
18
21
|
}
|
package/dist/cli.js
CHANGED
|
@@ -33,8 +33,12 @@ var MemorySessionRepository = class {
|
|
|
33
33
|
for (const path of [...this.sessions.keys()]) if (!seen.has(path)) this.sessions.delete(path);
|
|
34
34
|
return out;
|
|
35
35
|
}
|
|
36
|
-
all() {
|
|
37
|
-
|
|
36
|
+
all(cutoff) {
|
|
37
|
+
const ms = cutoff?.getTime();
|
|
38
|
+
const filtered = ms !== void 0 && !Number.isNaN(ms);
|
|
39
|
+
return [...this.sessions.values()].map(
|
|
40
|
+
(held) => filtered ? { ...held.session, turns: held.session.turns.filter((turn) => turn.when.getTime() >= ms) } : held.session
|
|
41
|
+
);
|
|
38
42
|
}
|
|
39
43
|
save(session, size) {
|
|
40
44
|
this.sessions.set(session.path, { session, size });
|
|
@@ -85,6 +89,7 @@ var SqliteSessionRepository = class {
|
|
|
85
89
|
stmtInsertTurn = null;
|
|
86
90
|
stmtAllFiles = null;
|
|
87
91
|
stmtAllTurns = null;
|
|
92
|
+
stmtAllTurnsSince = null;
|
|
88
93
|
constructor(dbPath) {
|
|
89
94
|
this.dbPath = dbPath;
|
|
90
95
|
this.ensureDb();
|
|
@@ -102,6 +107,9 @@ var SqliteSessionRepository = class {
|
|
|
102
107
|
this.stmtAllTurns = this.db.prepare(
|
|
103
108
|
"SELECT path, seq, project, session, model, at, base_in, cache_read, cache_write, output, tools, reads, wakes FROM turns ORDER BY path, seq;"
|
|
104
109
|
);
|
|
110
|
+
this.stmtAllTurnsSince = this.db.prepare(
|
|
111
|
+
"SELECT path, seq, project, session, model, at, base_in, cache_read, cache_write, output, tools, reads, wakes FROM turns WHERE at >= ? ORDER BY path, seq;"
|
|
112
|
+
);
|
|
105
113
|
}
|
|
106
114
|
openDb(path) {
|
|
107
115
|
const db = new DatabaseSync(path);
|
|
@@ -185,11 +193,13 @@ var SqliteSessionRepository = class {
|
|
|
185
193
|
}
|
|
186
194
|
return out;
|
|
187
195
|
}
|
|
188
|
-
all() {
|
|
196
|
+
all(cutoff) {
|
|
189
197
|
this.ensureDb();
|
|
190
198
|
if (!this.db || !this.stmtAllFiles || !this.stmtAllTurns) return [];
|
|
199
|
+
const ms = cutoff?.getTime();
|
|
200
|
+
const filtered = ms !== void 0 && !Number.isNaN(ms);
|
|
191
201
|
const fileRows = this.stmtAllFiles.all();
|
|
192
|
-
const turnRows = this.stmtAllTurns.iterate();
|
|
202
|
+
const turnRows = filtered && this.stmtAllTurnsSince ? this.stmtAllTurnsSince.iterate(ms) : this.stmtAllTurns.iterate();
|
|
193
203
|
const turnsByPath = /* @__PURE__ */ new Map();
|
|
194
204
|
for (const r of turnRows) {
|
|
195
205
|
let list = turnsByPath.get(r.path);
|
|
@@ -1608,12 +1618,13 @@ var ReportService = class {
|
|
|
1608
1618
|
const now = opts.now ?? /* @__PURE__ */ new Date();
|
|
1609
1619
|
const live = this.live(source);
|
|
1610
1620
|
if (!live.length) return null;
|
|
1621
|
+
const cutoff = new Date(now.getTime() - days * 864e5);
|
|
1611
1622
|
return buildReport({
|
|
1612
1623
|
now,
|
|
1613
1624
|
days,
|
|
1614
1625
|
weeklyBudget: opts.weeklyBudget,
|
|
1615
1626
|
live,
|
|
1616
|
-
sessions: this.repo.all().sort((a, b) => (this.order.get(a.path) ?? Infinity) - (this.order.get(b.path) ?? Infinity)),
|
|
1627
|
+
sessions: this.repo.all(cutoff).sort((a, b) => (this.order.get(a.path) ?? Infinity) - (this.order.get(b.path) ?? Infinity)),
|
|
1617
1628
|
config: this.readConfig(live),
|
|
1618
1629
|
planWeek: opts.planWeek ?? null,
|
|
1619
1630
|
codexWeek: live.includes("codex") ? this.sources.find((s) => s.name === "codex")?.week?.(now) ?? null : null
|
|
@@ -1983,6 +1994,30 @@ LoopbackHostOnly = __decorateClass([
|
|
|
1983
1994
|
Middleware({ type: "before", priority: 100 })
|
|
1984
1995
|
], LoopbackHostOnly);
|
|
1985
1996
|
function reportController(app, options, page) {
|
|
1997
|
+
let quota = null;
|
|
1998
|
+
let fetching = null;
|
|
1999
|
+
const plan = (now) => quota && quota.resets > now ? Promise.resolve(quota) : planWeek(app.env, now, false);
|
|
2000
|
+
const refresh = () => {
|
|
2001
|
+
fetching ??= planWeek(app.env, app.now(), true).then((week) => {
|
|
2002
|
+
if (week && week.resets > app.now()) quota = week;
|
|
2003
|
+
}).catch(() => {
|
|
2004
|
+
}).finally(() => {
|
|
2005
|
+
fetching = null;
|
|
2006
|
+
});
|
|
2007
|
+
};
|
|
2008
|
+
async function build(query) {
|
|
2009
|
+
const now = app.now();
|
|
2010
|
+
const days = positiveInt(query.days, options.days);
|
|
2011
|
+
const source = query.source === "claude" || query.source === "codex" ? query.source : options.source;
|
|
2012
|
+
rescan(app);
|
|
2013
|
+
const report = app.reports.getRaw(days, source, {
|
|
2014
|
+
weeklyBudget: options.weeklyBudget,
|
|
2015
|
+
planWeek: await plan(now),
|
|
2016
|
+
now
|
|
2017
|
+
});
|
|
2018
|
+
if (options.planUsage) setImmediate(refresh);
|
|
2019
|
+
return report;
|
|
2020
|
+
}
|
|
1986
2021
|
let ReportController = class {
|
|
1987
2022
|
status(res) {
|
|
1988
2023
|
if (!app.reports.hasScanned) warm(app);
|
|
@@ -1993,7 +2028,7 @@ function reportController(app, options, page) {
|
|
|
1993
2028
|
warm(app);
|
|
1994
2029
|
return res.status(202).json({ status: "scanning", progress: app.reports.progress });
|
|
1995
2030
|
}
|
|
1996
|
-
const report = await build(
|
|
2031
|
+
const report = await build(req.query);
|
|
1997
2032
|
return res.type("application/json").send(JSON.stringify(report ? reportView(report, app.now()) : null));
|
|
1998
2033
|
}
|
|
1999
2034
|
dashboard(res) {
|
|
@@ -2004,7 +2039,7 @@ function reportController(app, options, page) {
|
|
|
2004
2039
|
warm(app);
|
|
2005
2040
|
return res.type("text/html").send(loadingPage());
|
|
2006
2041
|
}
|
|
2007
|
-
const report = await build(
|
|
2042
|
+
const report = await build(req.query);
|
|
2008
2043
|
return res.type("text/html").send(report ? renderHtml(report, app.now(), page) : "No assistant turns.");
|
|
2009
2044
|
}
|
|
2010
2045
|
};
|
|
@@ -2037,17 +2072,6 @@ function warm(app) {
|
|
|
2037
2072
|
function rescan(app) {
|
|
2038
2073
|
if (Date.now() - app.reports.progress.updatedAt > 5e3) warm(app);
|
|
2039
2074
|
}
|
|
2040
|
-
async function build(app, options, query) {
|
|
2041
|
-
const now = app.now();
|
|
2042
|
-
const days = positiveInt(query.days, options.days);
|
|
2043
|
-
const source = query.source === "claude" || query.source === "codex" ? query.source : options.source;
|
|
2044
|
-
rescan(app);
|
|
2045
|
-
return app.reports.getRaw(days, source, {
|
|
2046
|
-
weeklyBudget: options.weeklyBudget,
|
|
2047
|
-
planWeek: await planWeek(app.env, now, options.planUsage),
|
|
2048
|
-
now
|
|
2049
|
-
});
|
|
2050
|
-
}
|
|
2051
2075
|
function positiveInt(value, fallback) {
|
|
2052
2076
|
const parsed = Number.parseInt(String(value ?? ""), 10);
|
|
2053
2077
|
return parsed > 0 ? parsed : fallback;
|