chore: v2.8.23 — workspace groups, inner repos in Changes (opt-in), sub-agent tokens counted
Workspace groups: named, foldable, ordered sidebar sections kept per account (agenthub.workspace.groups); a workspace joins one from its menu, a drop on the header, a drag under a row, or Alt+Up/Down past a group's edge; headers drag to reorder; a folded header shows its most urgent state; New workspace in this group; fold/unfold all. Inner repos: GET /api/lanes/:id/repos + ?repo= on git/fs routes; the Changes panel shows a parent folder's repos only when Settings -> Git -> Changes panel turns it on (agenthub.changes.innerRepos, off by default). Cost: the hook writer adds a session's sub-agent transcripts to its tokens and hours (server/lib/subagent-usage.js) — a sub-agent on the session's own model was never counted live (~8% of a week here); an imported session is re-raised on every pass, so a claude -p run first seen with an empty transcript no longer stays at $0 (~10%). A one-time raise-only catch-up (user_version 5) re-reads ~/.claude/projects. Also: omp install script may redirect to its exact install.redirect URL (#85, repo-links test exempts it), native paste in the terminal.
This commit is contained in:
+19
-20
@@ -1538,26 +1538,22 @@ function importSession(dbModule, session) {
|
||||
backfilled = true;
|
||||
}
|
||||
|
||||
// Reconcile token usage. The earlier importer dropped subagent tokens
|
||||
// entirely, so any session with subagent JSONLs has under-counted totals.
|
||||
// replaceTokenUsage's baseline-shift logic guarantees this can never
|
||||
// reduce a session's totals — at worst it's a no-op.
|
||||
if (
|
||||
session.parsedSubagents &&
|
||||
session.parsedSubagents.some(
|
||||
(s) =>
|
||||
s.tokensByModel &&
|
||||
Object.values(s.tokensByModel).some(
|
||||
(t) => (t.input || 0) + (t.output || 0) + (t.cacheRead || 0) + (t.cacheWrite || 0) > 0
|
||||
)
|
||||
)
|
||||
) {
|
||||
const written = writeSessionTokens(
|
||||
dbModule,
|
||||
session.sessionId,
|
||||
combineSessionTokens(session)
|
||||
// Reconcile token usage on every pass. A session first imported while its
|
||||
// transcript was still being written (a `claude -p` run with no hooks is
|
||||
// seen the moment its file appears) was stored with the usage of that
|
||||
// moment — often none — and its sub-agents' tokens arrive later still.
|
||||
// replaceTokenUsage keeps the highest total ever written, so this can only
|
||||
// raise a bucket, never inflate it; it counts as a backfill only when the
|
||||
// session's total actually grew.
|
||||
{
|
||||
const totalOf = db.prepare(
|
||||
`SELECT COALESCE(SUM(input_tokens + baseline_input + output_tokens + baseline_output
|
||||
+ cache_read_tokens + baseline_cache_read + cache_write_tokens + baseline_cache_write), 0) AS n
|
||||
FROM token_usage WHERE session_id = ?`
|
||||
);
|
||||
if (written > 0) backfilled = true;
|
||||
const before = totalOf.get(session.sessionId).n;
|
||||
writeSessionTokens(dbModule, session.sessionId, combineSessionTokens(session));
|
||||
if (totalOf.get(session.sessionId).n > before) backfilled = true;
|
||||
}
|
||||
|
||||
return backfilled ? { skipped: false, backfilled: true } : { skipped: true };
|
||||
@@ -2129,6 +2125,9 @@ async function syncDefaultProjects(dbModule, options = {}) {
|
||||
*/
|
||||
async function reconcileTokens(dbModule, options = {}) {
|
||||
const onProgress = typeof options.onProgress === "function" ? options.onProgress : () => {};
|
||||
// `exact: false` only raises (replaceTokenUsage's high-water mark): a repair
|
||||
// that adds what was never counted without touching anything already right.
|
||||
const exact = options.exact !== false;
|
||||
const counters = { reconciled: 0, sessionsTouched: 0, modelsWritten: 0, missingFiles: 0 };
|
||||
if (!fs.existsSync(getProjectsDir())) return counters;
|
||||
|
||||
@@ -2164,7 +2163,7 @@ async function reconcileTokens(dbModule, options = {}) {
|
||||
|
||||
const tx = dbModule.db.transaction((batch) => {
|
||||
for (const { sessionId, tokens } of batch) {
|
||||
const written = writeSessionTokens(dbModule, sessionId, tokens, { exact: true });
|
||||
const written = writeSessionTokens(dbModule, sessionId, tokens, { exact });
|
||||
if (written > 0) {
|
||||
counters.sessionsTouched++;
|
||||
counters.modelsWritten += written;
|
||||
|
||||
Reference in New Issue
Block a user