Merge remote-tracking branch 'origin/master' into codex/status-bar-token-metrics
Conflict resolution notes: - StatsLine: master redesigned the row into pipe-separated groups with LLM and tool wall times. Kept that design and swapped only the token accounting source, so counts and durations stay window-scoped while billing and context occupancy read the durable projections. - Generated artifacts (cordis catalog, module graph, event producer/consumer, i18n pairing hashes) and web snapshots took master's side; they are regenerated and re-recorded after this merge. - Web e2e goldens and details-panel/timeline assertions took master's side: that evolution is unrelated to this branch. - ui-conversation package.json: kept master's devDependency ordering, re-adding only the token-meter entry this branch needs.
This commit is contained in:
@@ -353,6 +353,7 @@ const attachments = new WeakMap<Session, SessionEntry>()
|
||||
*
|
||||
* Plain class (not a Service) — create instances via `ctx.sessions.create()`.
|
||||
* Seeding with an existing event log replays/forks a session.
|
||||
* @typert object
|
||||
*/
|
||||
export class Session {
|
||||
private log: SessionEvent[] = []
|
||||
@@ -620,7 +621,7 @@ export class Session {
|
||||
for (const seq of nodes.slice(this.derivedNodes)) {
|
||||
// Surface sequences are built from this.log — seq is always a valid
|
||||
// index by construction. The non-null assertion expresses that invariant.
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
// oxlint-disable-next-line typescript/no-non-null-assertion
|
||||
const msg = this.deriveEventMessage(this.log[seq]!)
|
||||
// A surface node is one of the five message-producing types, but an
|
||||
// empty-content assistant/message (a max-tokens step that hosts only
|
||||
@@ -935,7 +936,7 @@ export class SessionStore extends Service {
|
||||
} catch (error: unknown) {
|
||||
// Preserve the listener's exact rejection value; flush is a caller-owned
|
||||
// failure boundary, and Cordis listeners may throw arbitrary values.
|
||||
// eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors
|
||||
// oxlint-disable-next-line typescript/prefer-promise-reject-errors
|
||||
return Promise.reject(error)
|
||||
}
|
||||
}))
|
||||
|
||||
@@ -340,7 +340,7 @@ export class SurfaceManager implements SessionSurface {
|
||||
/** Fold events appended since the previous access. */
|
||||
private _processDelta(): void {
|
||||
for (let i = this._lastProcessedSeq + 1; i < this.log.length; i++) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- bounded by the loop condition
|
||||
// oxlint-disable-next-line typescript/no-non-null-assertion -- bounded by the loop condition
|
||||
applySurfaceEvent(this._state, this.log[i]!, i, this.log)
|
||||
this._lastProcessedSeq = i
|
||||
}
|
||||
|
||||
@@ -86,7 +86,7 @@ describe('packChunkRuns', () => {
|
||||
['a block-index switch', [...deltaRun('text-delta', 2), ...deltaRun('text-delta', 1, 2, 7)]],
|
||||
['a step switch', deltaRun('text-delta', 3).map((e, k) => k === 2 ? chunkEvent(e.seq, e.time, (e.data as { chunk: StreamChunk }).chunk, 1, 2) : e)],
|
||||
])('breaks a run on %s (both halves too short to pack)', (_label, events) => {
|
||||
expect(packChunkRuns(events as SessionEvent[])).toStrictEqual(events)
|
||||
expect(packChunkRuns(events)).toStrictEqual(events)
|
||||
})
|
||||
|
||||
it('breaks a tool-call run on call-id or name change', () => {
|
||||
|
||||
Reference in New Issue
Block a user