@rayadesu/dsh-llm-billing 0.3.12 → 0.3.13
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.i18n.yaml +2 -2
- package/README.md +17 -4
- package/README.zh.md +17 -4
- package/lib/index.js +302 -60
- package/lib/typert.host.js +79 -6
- package/lib/typert.remote-client.d.ts +3 -1
- package/lib/typert.remote-client.js +79 -6
- package/lib/types/balance.d.ts +22 -2
- package/lib/types/balance.js +19 -1
- package/lib/types/index.d.ts +2 -2
- package/lib/types/index.js +24 -5
- package/lib/types/today-spend.d.ts +192 -47
- package/lib/types/today-spend.js +270 -58
- package/lib/types/types.d.ts +50 -3
- package/package.json +20 -20
|
@@ -13,13 +13,23 @@
|
|
|
13
13
|
* every scan.
|
|
14
14
|
* - events path (plans A2/A3): collect and price only today's events in one
|
|
15
15
|
* pass (per-event Beijing-day filter during collection) with a hard cap,
|
|
16
|
-
*
|
|
17
|
-
*
|
|
16
|
+
* adopting the fold it already priced for a session whose persisted revision
|
|
17
|
+
* is unchanged since the last pass.
|
|
18
18
|
*
|
|
19
19
|
* Both strategies run behind the same {@link TodaySpendCache}, so a miss
|
|
20
20
|
* happens at most once per 60 seconds per process, and a manual refresh
|
|
21
21
|
* (`force`) bypasses the time window but keeps the revision caches — an
|
|
22
|
-
* unchanged log provably cannot change the aggregate.
|
|
22
|
+
* unchanged log provably cannot change the aggregate. That proof is what makes
|
|
23
|
+
* a revision gate a CACHE: both strategies therefore adopt the resolution they
|
|
24
|
+
* remember for an unchanged revision instead of skipping the session, so an
|
|
25
|
+
* unchanged log costs no I/O and still contributes its full spend (and title)
|
|
26
|
+
* to the aggregate and the ranking on every scan.
|
|
27
|
+
*
|
|
28
|
+
* The per-session ranking is a per-CONVERSATION ranking: a subagent child is
|
|
29
|
+
* work the delegating conversation paid for, not a session the user opened, so
|
|
30
|
+
* every subagent row is folded into the row of the top-level session at the
|
|
31
|
+
* root of its `parentSession` chain (see {@link rollUpSubagentSpend}). The
|
|
32
|
+
* aggregate is unaffected — it sums the same sessions either way.
|
|
23
33
|
*
|
|
24
34
|
* Forked sessions never double-count: a fork child's log opens with a
|
|
25
35
|
* verbatim copy of its source session's events (its inherited boundary), so
|
|
@@ -44,6 +54,7 @@
|
|
|
44
54
|
import type { SessionEvent, SessionId } from '@deepseek-ai/dsh-session';
|
|
45
55
|
import type { SessionPersistenceRevision } from '@deepseek-ai/dsh-session-persistence';
|
|
46
56
|
import type { ResolvedBilling } from './billing.ts';
|
|
57
|
+
import type { BillingFoldState } from './billing.ts';
|
|
47
58
|
import type { DeepSeekTodaySessionSpend, DeepSeekTodaySessionsSpend, DeepSeekTodaySpend } from './types.ts';
|
|
48
59
|
import { BILLING_UNIT_KEY, type BillingUnitFold, type BillingUnitState } from './projection.ts';
|
|
49
60
|
/**
|
|
@@ -55,6 +66,77 @@ import { BILLING_UNIT_KEY, type BillingUnitFold, type BillingUnitState } from '.
|
|
|
55
66
|
* @returns the session's current title, or `null` when untitled.
|
|
56
67
|
*/
|
|
57
68
|
export declare function foldSessionTitle(events: readonly SessionEvent[]): string | null;
|
|
69
|
+
/**
|
|
70
|
+
* Structural slice of a session's durable lineage: the header fields DSH
|
|
71
|
+
* stamps on a delegation child (`origin: 'subagent'`, the delegating session's
|
|
72
|
+
* id, and the depth that survives persistence). All three are read
|
|
73
|
+
* structurally, so the scanner works on every runtime family — a log written
|
|
74
|
+
* before the fields existed simply carries none of them and reads as a
|
|
75
|
+
* top-level session.
|
|
76
|
+
*/
|
|
77
|
+
export interface SessionLineage {
|
|
78
|
+
/** The session this one was forked from or delegated by; absent for a top-level session. */
|
|
79
|
+
readonly parentSession?: SessionId;
|
|
80
|
+
/** DSH's subagent-child classification (`childSessionMeta` stamps it). */
|
|
81
|
+
readonly origin?: 'subagent';
|
|
82
|
+
/** Delegation depth: absent (zero) at the top level, parent depth + 1 for a subagent child. */
|
|
83
|
+
readonly delegationDepth?: number;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Whether one session's durable header marks it as a subagent child. Either
|
|
87
|
+
* marker is enough: `origin` is DSH's navigation classification and
|
|
88
|
+
* `delegationDepth` is its persisted recursion budget, so a header carrying
|
|
89
|
+
* only the depth (or only the origin) is still a delegation child. A session
|
|
90
|
+
* created without either — an ordinary session, a user fork, or a cold resume
|
|
91
|
+
* — is top-level.
|
|
92
|
+
* @param header - the session's lineage slice; `undefined` reads as top-level.
|
|
93
|
+
* @returns true when the session was created as a subagent child.
|
|
94
|
+
*/
|
|
95
|
+
export declare function isSubagentSession(header: SessionLineage | undefined): boolean;
|
|
96
|
+
/**
|
|
97
|
+
* The top-level session one session's ranking row belongs to: the session
|
|
98
|
+
* itself for a top-level session, and for a subagent child the first ancestor
|
|
99
|
+
* up the `parentSession` chain that is not itself a subagent child. A
|
|
100
|
+
* multi-generation delegation (a subagent that spawned subagents) therefore
|
|
101
|
+
* lands on the same root row as its parent, and a child whose parent header is
|
|
102
|
+
* unknown is attributed to the parent id its own header names — the parent is
|
|
103
|
+
* authoritative even when its log is not part of this scan.
|
|
104
|
+
* @param id - the session whose row is being attributed.
|
|
105
|
+
* @param lineage - lineage of every session this scan saw, by id.
|
|
106
|
+
* @returns the session id whose ranking row the input belongs to.
|
|
107
|
+
*/
|
|
108
|
+
export declare function topLevelSessionOf(id: SessionId, lineage: ReadonlyMap<SessionId, SessionLineage>): SessionId;
|
|
109
|
+
/**
|
|
110
|
+
* Fold every subagent child's row into the top-level row it belongs to
|
|
111
|
+
* ({@link topLevelSessionOf}), so the ranking lists conversations rather than
|
|
112
|
+
* every delegation a conversation started. A child's spend is added to its
|
|
113
|
+
* ancestor's `total`; the ancestor's `ownTotal` keeps its own spend only. A
|
|
114
|
+
* top-level session whose own day was empty but whose subagents priced
|
|
115
|
+
* something still gets a row (with `ownTotal` 0), carrying the title the scan
|
|
116
|
+
* resolved for it in `titles`.
|
|
117
|
+
* @param rows - one row per session that priced something today (own spends).
|
|
118
|
+
* @param lineage - lineage of every session this scan saw, by id.
|
|
119
|
+
* @param titles - resolved display titles by session id; a session absent from
|
|
120
|
+
* the map has no resolved title and its created row reports `null`.
|
|
121
|
+
* @returns the merged rows, sorted by `total` descending.
|
|
122
|
+
*/
|
|
123
|
+
export declare function rollUpSubagentSpend(rows: readonly DeepSeekTodaySessionSpend[], lineage: ReadonlyMap<SessionId, SessionLineage>, titles?: ReadonlyMap<SessionId, string | null>): DeepSeekTodaySessionSpend[];
|
|
124
|
+
/**
|
|
125
|
+
* Structural slice of a live session's header: the fork boundary of both DSH
|
|
126
|
+
* runtime families plus the delegation lineage the ranking roll-up reads.
|
|
127
|
+
*/
|
|
128
|
+
export interface SessionHeaderSlice extends SessionLineage {
|
|
129
|
+
/** ≤ 0.1.1-rc.2: the durable fork boundary carried by the header; absent for an unseeded session. */
|
|
130
|
+
readonly seedLength?: number;
|
|
131
|
+
/** 0.1.2-alpha.4+: whether the session has a fork-inherited prefix. */
|
|
132
|
+
readonly isSeeded?: boolean;
|
|
133
|
+
/**
|
|
134
|
+
* Durable creation instant (epoch ms). The conversation read uses it to tell
|
|
135
|
+
* whether a session's spend can span more than the queried day; it is also
|
|
136
|
+
* part of the projection-cache record identity.
|
|
137
|
+
*/
|
|
138
|
+
readonly createdAt?: number;
|
|
139
|
+
}
|
|
58
140
|
/**
|
|
59
141
|
* Structural slice of a live session the scanner reads, accepting both DSH
|
|
60
142
|
* runtime families: the ≤ 0.1.1-rc.2 baseline exposes the log as
|
|
@@ -69,11 +151,8 @@ export interface ScannerSession {
|
|
|
69
151
|
snapshotEvents?(fromSeq?: number, toSeqExclusive?: number): readonly SessionEvent[];
|
|
70
152
|
/** 0.1.2-alpha.4+: the durable inherited-prefix length (0 for an unseeded session). */
|
|
71
153
|
readonly inheritedEventCount?: number;
|
|
72
|
-
/** Durable header slice: `seedLength` (older runtime) or `isSeeded` (newer runtime). */
|
|
73
|
-
readonly header?:
|
|
74
|
-
readonly seedLength?: number;
|
|
75
|
-
readonly isSeeded?: boolean;
|
|
76
|
-
};
|
|
154
|
+
/** Durable header slice: `seedLength` (older runtime) or `isSeeded` (newer runtime), plus lineage. */
|
|
155
|
+
readonly header?: SessionHeaderSlice;
|
|
77
156
|
}
|
|
78
157
|
/**
|
|
79
158
|
* Read one live session's complete event log across both runtime families.
|
|
@@ -83,16 +162,10 @@ export interface ScannerSession {
|
|
|
83
162
|
*/
|
|
84
163
|
export declare function liveSessionEvents(session: ScannerSession): readonly SessionEvent[];
|
|
85
164
|
/** Structural slice of a listed persisted session (the snapshot header is a full SessionHeader). */
|
|
86
|
-
export interface ScannerPersistedHeader {
|
|
165
|
+
export interface ScannerPersistedHeader extends SessionHeaderSlice {
|
|
87
166
|
readonly id: SessionId;
|
|
88
|
-
/** ≤ 0.1.1-rc.2: the durable fork boundary carried by the snapshot header; absent for an unseeded session. */
|
|
89
|
-
readonly seedLength?: number;
|
|
90
|
-
/** 0.1.2-alpha.4+: whether the session has a fork-inherited prefix (exact cut arrives with the inspect result). */
|
|
91
|
-
readonly isSeeded?: boolean;
|
|
92
167
|
/** Session format generation; part of the projection-cache record identity. */
|
|
93
168
|
readonly version?: number;
|
|
94
|
-
/** Session creation time; part of the projection-cache record identity. */
|
|
95
|
-
readonly createdAt?: number;
|
|
96
169
|
/** Working directory recorded on the header; part of the projection-cache record identity. */
|
|
97
170
|
readonly cwd?: string;
|
|
98
171
|
}
|
|
@@ -109,10 +182,7 @@ export interface ScannerPersistenceLegacy {
|
|
|
109
182
|
revision: SessionPersistenceRevision;
|
|
110
183
|
}[]>;
|
|
111
184
|
inspect(id: SessionId): Promise<{
|
|
112
|
-
meta?:
|
|
113
|
-
readonly seedLength?: number;
|
|
114
|
-
readonly isSeeded?: boolean;
|
|
115
|
-
};
|
|
185
|
+
meta?: SessionHeaderSlice;
|
|
116
186
|
/** 0.1.2-alpha.4+: the exact inherited cut travels beside, not inside, the header. */
|
|
117
187
|
inheritedEventCount?: number;
|
|
118
188
|
events: readonly SessionEvent[];
|
|
@@ -140,10 +210,7 @@ export interface ScannerPersistenceHandle {
|
|
|
140
210
|
revision: SessionPersistenceRevision;
|
|
141
211
|
}[]>;
|
|
142
212
|
open(id: SessionId, access: 'read'): Promise<{
|
|
143
|
-
readonly header?:
|
|
144
|
-
readonly seedLength?: number;
|
|
145
|
-
readonly isSeeded?: boolean;
|
|
146
|
-
};
|
|
213
|
+
readonly header?: SessionHeaderSlice;
|
|
147
214
|
/** 0.1.2-alpha.5+: the handle carries the exact inherited cut beside the header. */
|
|
148
215
|
readonly inheritedEventCount?: number;
|
|
149
216
|
read(): Promise<ScannerHandleRead>;
|
|
@@ -264,22 +331,86 @@ export interface TodaySpendDetail {
|
|
|
264
331
|
aggregate: DeepSeekTodaySpend;
|
|
265
332
|
/** Today's per-session rows, sorted by cost descending. */
|
|
266
333
|
sessions: DeepSeekTodaySessionSpend[];
|
|
334
|
+
/** The Beijing day this pass was computed for (the key its day filters used). */
|
|
335
|
+
dayKey: string;
|
|
336
|
+
/**
|
|
337
|
+
* WHOLE-session own spend of every session this pass priced, by id: all days
|
|
338
|
+
* the log covers, the fork prefix already excluded, subagents not yet merged.
|
|
339
|
+
* The ranking only reports the queried day, but the same fold carries the
|
|
340
|
+
* whole-session total, so a conversation read ({@link delegatedSpendOf}) costs
|
|
341
|
+
* no second scan.
|
|
342
|
+
*/
|
|
343
|
+
ownSpend: ReadonlyMap<SessionId, DeepSeekTodaySpend>;
|
|
344
|
+
/** Lineage of every session this pass saw, by id: the delegation tree's shape. */
|
|
345
|
+
lineage: ReadonlyMap<SessionId, SessionLineage>;
|
|
346
|
+
/**
|
|
347
|
+
* Durable creation instant of every session this pass saw, by id (absent when
|
|
348
|
+
* the header carried none). The panel's today share is gated on the session
|
|
349
|
+
* having been created BEFORE the queried day, which this answers without
|
|
350
|
+
* another read.
|
|
351
|
+
*/
|
|
352
|
+
createdAt: ReadonlyMap<SessionId, number>;
|
|
353
|
+
}
|
|
354
|
+
/**
|
|
355
|
+
* The merged whole-session spend of every subagent session delegated FROM one
|
|
356
|
+
* session, transitively: the subagent subtotal a conversation's own log cannot
|
|
357
|
+
* price. Only sessions DSH marked as delegation children count, so a user fork
|
|
358
|
+
* (which names a `parentSession` too) is never billed into its source. A
|
|
359
|
+
* malformed lineage that points back at the queried session is ignored rather
|
|
360
|
+
* than counted twice.
|
|
361
|
+
* @param id - the session whose delegated subtree to sum.
|
|
362
|
+
* @param ownSpend - whole-session own spend per session, from one scan pass.
|
|
363
|
+
* @param lineage - lineage per session, from the same pass.
|
|
364
|
+
* @returns the merged subtree spend; empty when the session delegated nothing priced.
|
|
365
|
+
*/
|
|
366
|
+
export declare function delegatedSpendOf(id: SessionId, ownSpend: ReadonlyMap<SessionId, DeepSeekTodaySpend>, lineage: ReadonlyMap<SessionId, SessionLineage>): DeepSeekTodaySpend;
|
|
367
|
+
/**
|
|
368
|
+
* One cold session's resolution, as {@link TodaySpendScanner} remembers it: the
|
|
369
|
+
* persisted revision the resolution read, the session's OWN-events billing fold
|
|
370
|
+
* (its fork boundary already applied), and the display title folded from the
|
|
371
|
+
* same read. The revision is the adoption gate — a later scan adopts the entry
|
|
372
|
+
* only while the session's persisted revision is unchanged, which is exactly
|
|
373
|
+
* the proof that re-reading the log could not change the fold.
|
|
374
|
+
*/
|
|
375
|
+
export interface ColdResolution {
|
|
376
|
+
/** The persisted revision this resolution read. */
|
|
377
|
+
readonly revision: SessionPersistenceRevision;
|
|
378
|
+
/** The session's own-events fold (`BillingUnitState` names the same shape). */
|
|
379
|
+
readonly fold: BillingFoldState;
|
|
380
|
+
/** The session's display title from the same read; `null` when untitled or unresolved. */
|
|
381
|
+
readonly title: string | null;
|
|
267
382
|
}
|
|
268
383
|
/**
|
|
269
384
|
* The aggregate computation behind a cache miss. Chooses the projection path
|
|
270
385
|
* when the projection registry is composed, the events path otherwise; both
|
|
271
|
-
* gate cold reads on persisted revisions
|
|
272
|
-
* sessions whose logs
|
|
386
|
+
* gate cold reads on persisted revisions AND adopt the fold they already hold
|
|
387
|
+
* for an unchanged log, so steady-state scans re-read only sessions whose logs
|
|
388
|
+
* actually changed while every unchanged session keeps contributing.
|
|
273
389
|
*/
|
|
274
390
|
export declare class TodaySpendScanner {
|
|
275
391
|
private readonly deps;
|
|
276
|
-
/**
|
|
392
|
+
/**
|
|
393
|
+
* Cold sessions resolved by either strategy: id → the persisted revision the
|
|
394
|
+
* resolution saw, the session's OWN-events fold, and its folded title.
|
|
395
|
+
*
|
|
396
|
+
* The two strategies differ in how they PRICE a cold log (an eager projection
|
|
397
|
+
* cell plus the cache ladder, or a local fold over the read log), never in
|
|
398
|
+
* what an unchanged log contributes to the day — so one memory serves both.
|
|
399
|
+
* The projection path reuses the resolved unit; the events path reuses the
|
|
400
|
+
* fold it priced on the previous pass. A strategy that skipped an unchanged
|
|
401
|
+
* log WITHOUT adopting its remembered fold would silently drop that session
|
|
402
|
+
* from the aggregate and the ranking on every scan after the first.
|
|
403
|
+
*/
|
|
277
404
|
private readonly coldResolved;
|
|
278
405
|
/** Cold sessions whose resolution failed: id → revision (retried only when the log changes). */
|
|
279
406
|
private readonly coldFailed;
|
|
280
|
-
/** Cold sessions resolved on the events path: id → revision (events were collected). */
|
|
281
|
-
private lastEventsScan;
|
|
282
407
|
constructor(deps: TodaySpendScannerDeps);
|
|
408
|
+
/**
|
|
409
|
+
* Remember one cold session's resolution, bounded by
|
|
410
|
+
* {@link COLD_RESOLVE_CACHE_LIMIT}: evicting the oldest entry (instead of
|
|
411
|
+
* clearing) keeps the other sessions' resolved state warm across scans.
|
|
412
|
+
*/
|
|
413
|
+
private rememberCold;
|
|
283
414
|
/**
|
|
284
415
|
* Compute today's aggregate for one Beijing day.
|
|
285
416
|
* @param dayKey - the Beijing-time calendar-day key to aggregate.
|
|
@@ -288,8 +419,11 @@ export declare class TodaySpendScanner {
|
|
|
288
419
|
scan(dayKey: string): Promise<DeepSeekTodaySpend>;
|
|
289
420
|
/**
|
|
290
421
|
* Compute today's per-session spend for one Beijing day, sorted by cost
|
|
291
|
-
* descending.
|
|
292
|
-
*
|
|
422
|
+
* descending. One row per top-level session: sessions with no priced usage
|
|
423
|
+
* on the day are omitted (unless their subagents priced something, which the
|
|
424
|
+
* roll-up merges into their row), every subagent session is folded into the
|
|
425
|
+
* top-level session that delegated it, and each row carries the session's
|
|
426
|
+
* durable title folded from its log.
|
|
293
427
|
* @param dayKey - the Beijing-time calendar-day key to aggregate.
|
|
294
428
|
* @returns today's per-session rows, highest first.
|
|
295
429
|
*/
|
|
@@ -300,12 +434,15 @@ export declare class TodaySpendScanner {
|
|
|
300
434
|
* read, unit fold, and title fold instead of scanning twice. Chooses the
|
|
301
435
|
* projection path when the projection registry is composed, the events path
|
|
302
436
|
* otherwise.
|
|
437
|
+
*
|
|
438
|
+
* The aggregate sums every priced session, subagents included — the ranking's
|
|
439
|
+
* subagent roll-up only regroups rows, so neither total moves.
|
|
303
440
|
* @param dayKey - the Beijing-time calendar-day key to aggregate.
|
|
304
441
|
* @returns the aggregate plus per-session rows sorted by cost descending.
|
|
305
442
|
*/
|
|
306
443
|
scanDetail(dayKey: string): Promise<TodaySpendDetail>;
|
|
307
444
|
/**
|
|
308
|
-
* Resolve one cold session's billing
|
|
445
|
+
* Resolve one cold session's billing fold state and display title.
|
|
309
446
|
*
|
|
310
447
|
* The zero-I/O projection-cache row answers the query directly whenever its
|
|
311
448
|
* own latest priced day is NOT the queried day: the row then proves the
|
|
@@ -323,7 +460,7 @@ export declare class TodaySpendScanner {
|
|
|
323
460
|
* @param header - the listed session header (the cache identity witness).
|
|
324
461
|
* @param seeded - whether the session carries a fork-inherited prefix.
|
|
325
462
|
* @param dayKey - the Beijing-time day being aggregated.
|
|
326
|
-
* @returns the resolved state and title, or `undefined` when unreadable.
|
|
463
|
+
* @returns the resolved fold state and title, or `undefined` when unreadable.
|
|
327
464
|
*/
|
|
328
465
|
private resolveCold;
|
|
329
466
|
/**
|
|
@@ -336,11 +473,11 @@ export declare class TodaySpendScanner {
|
|
|
336
473
|
/**
|
|
337
474
|
* Cold-ladder adopt: for every stored session not live, either the
|
|
338
475
|
* revision-gated resolution already in {@link coldResolved} is adopted
|
|
339
|
-
* (unchanged log costs nothing) or the session is queued
|
|
340
|
-
* parallel fan-out, resolved, remembered, and then adopted.
|
|
341
|
-
* resolution failed is remembered too (by revision), so an
|
|
342
|
-
* is not re-read on every scan; a changed revision retries it.
|
|
343
|
-
* unreadable session never blanks the whole-day aggregate.
|
|
476
|
+
* (unchanged log costs nothing and still counts) or the session is queued
|
|
477
|
+
* behind a bounded parallel fan-out, resolved, remembered, and then adopted.
|
|
478
|
+
* A session whose resolution failed is remembered too (by revision), so an
|
|
479
|
+
* unreadable log is not re-read on every scan; a changed revision retries it.
|
|
480
|
+
* One unreadable session never blanks the whole-day aggregate.
|
|
344
481
|
* @param liveIds - ids of sessions already folded from the live store.
|
|
345
482
|
* @param snapshots - stored snapshot list (either runtime family).
|
|
346
483
|
* @param dayKey - the Beijing-time day being aggregated.
|
|
@@ -350,14 +487,17 @@ export declare class TodaySpendScanner {
|
|
|
350
487
|
/**
|
|
351
488
|
* Events-path collection shared by both aggregate and per-session scans:
|
|
352
489
|
* fold each session's log with the shared pricing fold (attempt samples with
|
|
353
|
-
* same-step replacement) and announce the session's latest-day spend
|
|
354
|
-
*
|
|
355
|
-
*
|
|
356
|
-
*
|
|
357
|
-
*
|
|
358
|
-
*
|
|
490
|
+
* same-step replacement) and announce the session's latest-day spend. A
|
|
491
|
+
* persisted session whose log did not change since it was last resolved is
|
|
492
|
+
* answered from {@link coldResolved} instead of being re-read: it keeps
|
|
493
|
+
* counting toward the aggregate and the ranking at zero cost, which is what
|
|
494
|
+
* makes the revision gate a cache rather than a way to lose sessions. A fork
|
|
495
|
+
* child's inherited prefix (`seq < seedLength`) is skipped, so each model
|
|
496
|
+
* output is priced only in its source session. The hard cap counts the
|
|
497
|
+
* queried day's events; a truncated pass remembers nothing it read, so the
|
|
498
|
+
* next one re-reads whatever this one cut short.
|
|
359
499
|
* @param dayKey - the Beijing-time calendar-day key to aggregate.
|
|
360
|
-
* @param onSession -
|
|
500
|
+
* @param onSession - adopt one session's fold, title, and lineage.
|
|
361
501
|
* @returns whether the hard cap truncated the scan.
|
|
362
502
|
*/
|
|
363
503
|
private collectTodayEvents;
|
|
@@ -366,18 +506,23 @@ export declare class TodaySpendScanner {
|
|
|
366
506
|
* (title folded from the live log, so a rename is reflected immediately),
|
|
367
507
|
* revision-gated cold ladder for the rest (title resolved on inspect, `null`
|
|
368
508
|
* when answered from the projection cache). A fork child's cell covers its
|
|
369
|
-
* inherited prefix, so its own-events fold supplies both outputs.
|
|
509
|
+
* inherited prefix, so its own-events fold supplies both outputs. Lineage
|
|
510
|
+
* (which session delegated which) comes from the same headers the boundary
|
|
511
|
+
* does, so the ranking's subagent roll-up costs no extra read.
|
|
370
512
|
* @param dayKey - the Beijing-time calendar-day key to aggregate.
|
|
371
513
|
* @returns the aggregate plus per-session rows, sorted by cost descending.
|
|
372
514
|
*/
|
|
373
515
|
private scanDetailProjections;
|
|
374
516
|
/**
|
|
375
517
|
* Events path, one pass for both outputs: price today's events (per-event
|
|
376
|
-
* Beijing-day filter during collection, hard cap), gated
|
|
518
|
+
* Beijing-day filter during collection, hard cap), revision-gated so an
|
|
519
|
+
* unchanged log is adopted from {@link coldResolved} instead of re-read. A
|
|
377
520
|
* fork child's inherited prefix (`seq < seedLength`) is skipped, so each
|
|
378
521
|
* model output is priced only in its source session. Titles fold from each
|
|
379
522
|
* session's complete log — a `session/title` event can predate today — so a
|
|
380
|
-
* rename is reflected as soon as the session's log is re-read
|
|
523
|
+
* rename is reflected as soon as the session's log is re-read, and an
|
|
524
|
+
* unchanged session keeps the title its earlier read folded. Lineage comes
|
|
525
|
+
* from the same headers, which the ranking roll-up needs.
|
|
381
526
|
* @param dayKey - the Beijing-time calendar-day key to aggregate.
|
|
382
527
|
* @returns the aggregate plus per-session rows, sorted by cost descending.
|
|
383
528
|
*/
|