Merge latest master into subagent policy inheritance

This commit is contained in:
Tianyi Cui
2026-07-29 00:40:25 +08:00
167 changed files with 6507 additions and 953 deletions

View File

@@ -16,7 +16,7 @@ import { dirname, resolve } from 'node:path'
import {
SessionPersistence, SessionPersistenceRevision, PersistenceCoordinator,
type PersistenceBackend, type SessionLocation, type SessionPersistenceSnapshot,
type StoredPrefix,
type StoredPrefix, type StoredSuffix,
} from '@deepseek-ai/dsh-session-persistence'
import type { SessionEvent, SurfaceEventType, SessionId, SessionHeader } from '@deepseek-ai/dsh-session'
import {
@@ -161,6 +161,10 @@ export class SessionPersistenceSqlite extends SessionPersistence implements Pers
return this.coordinator.inspect(id, signal)
}
readFrom(id: SessionId, fromSeq: number, signal?: AbortSignal): Promise<{ meta: SessionHeader; events: SessionEvent[] }> {
return this.coordinator.readFrom(id, fromSeq, signal)
}
// One method serves both public `list` and the backend hook; delegating it to
// the coordinator would call this hook recursively.
@@ -171,6 +175,26 @@ export class SessionPersistenceSqlite extends SessionPersistence implements Pers
return this.readPrefix(id, signal)
}
/**
* Seek-capable suffix read: SQL selects `seq >= fromSeq` directly, so the
* read scales with the suffix, not the log. Torn rows past the preserved
* region are dropped, never repaired (non-mutating read).
*/
async loadStoredFrom(id: SessionId, fromSeq: number, signal?: AbortSignal): Promise<StoredSuffix | undefined> {
signal?.throwIfAborted()
await this.ready
signal?.throwIfAborted()
const row = this.rowFor(id)
if (row === undefined) return undefined
const meta = rowToMeta(row)
const eventRows = this.db
.prepare('SELECT seq, type, time, data, source_event_seqs, surface_op FROM events WHERE session_id = ? AND seq >= ? ORDER BY seq')
.all(id, fromSeq) as unknown as EventRow[]
signal?.throwIfAborted()
const { preserved } = scanRows(eventRows, fromSeq)
return { meta, events: preserved }
}
/**
* Read a session's row + ordered events into a {@link StoredPrefix}. The
* torn-tail marker is the seq from which a never-committed tail must be deleted

View File

@@ -213,10 +213,12 @@ export function rowToEvent(row: EventRow): SessionEvent {
* the committed region rejects.
*
* @param rows - one session's event rows, ordered by seq ascending.
* @param base - the seq the first row is expected to carry; `0` for a whole
* log, the requested `fromSeq` for a suffix read (`loadStoredFrom`).
* @returns the preserved event prefix, plus `tornFrom` — the seq the physical
* delete starts at — when a torn tail exists.
*/
export function scanRows(rows: readonly EventRow[]): { preserved: SessionEvent[]; tornFrom?: number } {
export function scanRows(rows: readonly EventRow[], base = 0): { preserved: SessionEvent[]; tornFrom?: number } {
// Pass 1: parse each row's data; a row whose data is not valid JSON is a hole.
// (The seq/type COLUMNS are always present even when `data` is corrupt.)
interface Parsed { ok: boolean; event?: SessionEvent }
@@ -244,8 +246,8 @@ export function scanRows(rows: readonly EventRow[]): { preserved: SessionEvent[]
if (i <= lastTurnEnd) throw new Error(`corrupt session log: unparsable committed event at seq ${rows[i]?.seq}`)
break // torn tail fragment after the last turn/end — stop, tolerate
}
if (p.event.seq !== i) {
if (i <= lastTurnEnd) throw new Error(`corrupt session log: seq gap in committed region (expected ${i}, got ${p.event.seq})`)
if (p.event.seq !== base + i) {
if (i <= lastTurnEnd) throw new Error(`corrupt session log: seq gap in committed region (expected ${base + i}, got ${p.event.seq})`)
break // gap after the last turn/end — torn tail, stop
}
preserved.push(p.event)
@@ -253,5 +255,5 @@ export function scanRows(rows: readonly EventRow[]): { preserved: SessionEvent[]
// Any rows past the preserved prefix are a never-committed torn tail; their
// first seq is the deletion point for load's physical repair.
return preserved.length < rows.length ? { preserved, tornFrom: preserved.length } : { preserved }
return preserved.length < rows.length ? { preserved, tornFrom: base + preserved.length } : { preserved }
}