# Session Query English | [中文](session-query.zh.md) Query vocabulary over the live-preferred logical session corpus. The [Service Definition package](../../packages/session-query/session-query) owns exact reads, source precedence, relationship tracing, semantic extraction, and provider-independent filters, while the [SQLite provider](../../packages/session-query/session-query-sqlite) owns the concrete full-text index lifecycle. Source: [`packages/session-query/session-query/src/types.ts`](../../packages/session-query/session-query/src/types.ts) ## Logical records `SessionRecord` is returned by the cross-corpus list. It exposes source availability independently from the cloned live-preferred header. `SessionEventRecord` is a lightweight raw-log projection; classification uses the same `foldSurface()` transitions as model-history derivation. ```ts type-equiv /** Whether an event is current model context, replaced context, or raw-log-only. */ type SessionEventSurface = 'current' | 'shadowed' | 'log-only' ``` ```ts type-equiv /** Lightweight identity and source availability for one logical session. */ interface SessionRecord { /** Cloned session header selected from the live-preferred corpus. */ header: SessionHeader /** Whether the id currently exists in `ctx.sessions`. */ live: boolean /** Whether the active persistence backend currently materializes the id. */ persisted: boolean } ``` `SessionLogSnapshot` is the complete detached, replay-validated raw log used by resume preflight. `SessionSurfaceSnapshot` is one exact-read surface observation rather than a retained subscription. ```ts type-equiv /** One validated detached observation of a logical session's complete raw log. */ interface SessionLogSnapshot { /** Cloned session header selected from the same observation as `events`. */ session: SessionHeader /** Cloned contiguous raw events after persistence repair and replay validation. */ events: SessionEvent[] } ``` ```ts type-equiv /** One atomic live-preferred observation of a session's current model surface. */ interface SessionSurfaceSnapshot { /** Cloned session header selected from the same corpus observation as `events`. */ session: SessionHeader /** Highest raw-log seq included in the observation, or `null` for an empty log. */ capturedThroughSeq: number | null /** Cloned current surface events in model-history order. */ events: SurfaceEvent[] } ``` `SessionTitleObservation` applies the same atomic-observation rule to title folding, so an authorization consumer can validate the source header that supplied the title. Batch reads return one ordered `SessionTitleObservationResult` per unique requested id: operational failures remain local to that id, while cancellation rejects the complete operation. ```ts type-equiv /** Latest folded title bound to the same session-header observation. */ interface SessionTitleObservation { /** Cloned header selected with the event log used for the title fold. */ session: SessionHeader /** Latest title snapshot, absent when the observed log has no title. */ title?: SessionTitleSnapshot } ``` ```ts type-equiv /** One ordered result from a batch title observation. */ type SessionTitleObservationResult = | { /** Requested session id. */ sessionId: SessionId /** Successful atomic header/title observation. */ status: 'fulfilled' /** Header and optional latest title from one logical source. */ value: SessionTitleObservation } | { /** Requested session id. */ sessionId: SessionId /** Operational failure isolated to this session. */ status: 'rejected' /** Original failure from logical-source resolution or title folding. */ reason: unknown } ``` ```ts type-equiv /** Lightweight metadata for one event within a logical session. */ interface SessionEventRecord { /** Session that owns the event. */ sessionId: SessionId /** Monotonic event seq within the session. */ seq: number /** Discriminant of the session event. */ type: SessionEventType /** Event timestamp in Unix epoch milliseconds. */ time: number /** Event placement in the folded session surface. */ surface: SessionEventSurface } ``` ## Provider-independent filters and documents Session and event filter arrays are ANDed; values inside one list clause are ORed. Ranges are inclusive. The event `text` clause is a literal Unicode case-insensitive, whitespace-flexible regular-expression scan over extracted semantic text, independent of full-text providers. ```ts type-equiv /** * One logical-session predicate. A filter array is ANDed; `values` within a * clause are ORed. */ type SessionResultFilter = | { kind: 'id'; values: readonly SessionId[] } | { kind: 'cwd'; values: readonly (string | null)[] } | ({ kind: 'created-at' } & SessionResultRange) | { kind: 'parent'; values: readonly (SessionId | null)[] } | { kind: 'availability'; values: readonly SessionAvailability[] } ``` ```ts type-equiv /** * One event predicate. A filter array is ANDed; list-valued clauses are ORed. * Text is a literal, case-insensitive, whitespace-flexible semantic-text scan. */ type SessionEventResultFilter = | ({ kind: 'seq' } & SessionResultRange) | ({ kind: 'time' } & SessionResultRange) | { kind: 'type'; values: readonly SessionEventType[] } | { kind: 'surface'; values: readonly SessionEventSurface[] } | { kind: 'text'; text: string } ``` ```ts type-equiv /** Searchable semantic document derived from one session event. */ interface SessionEventSearchDocument extends SessionEventRecord { /** First-party semantic text used by scan filters and full-text indexes. */ text: string } ``` `ctx.sessionQuery.filterSessions(filters)` applies `SessionResultFilter` to the complete logical corpus; `ctx.sessionQuery.filterEvents(sessionId, filters)` returns matching documents in ascending seq order. Messages, reasoning, tool calls/results, blocked prompts, todos, and failure/status detail contribute semantic text; structural events and stream chunks do not. ## Full-text search pages The combined `ctx.sessionQuery` seam has two full-text scopes. `searchSessions()` groups the corpus by strongest matching event; `searchEvents()` searches one session. Requests bind an opaque cursor to the normalized query, metadata filters, and limit. The event text scan is intentionally absent from provider metadata filters. ```ts type-equiv /** Provider-owned opaque continuation token returned by session search. */ type SessionSearchCursor = Branded<'SessionSearchCursor'> ``` ```ts type-equiv /** Cross-session full-text search request. */ interface SessionSearchRequest { /** Full-text query interpreted as data, never executable FTS syntax. */ query: string /** Logical-session predicates applied before event ranking. */ sessionFilters?: readonly SessionResultFilter[] /** Event predicates applied before event ranking. */ eventFilters?: readonly SessionEventMetadataFilter[] /** Maximum sessions in this page. */ limit?: number /** Opaque cursor returned for the identical normalized request. */ cursor?: SessionSearchCursor } ``` ```ts type-equiv /** Within-session full-text search request. */ interface SessionEventSearchRequest { /** Session whose live-preferred logical log is searched. */ sessionId: SessionId /** Full-text query interpreted as data, never executable FTS syntax. */ query: string /** Event predicates applied before ranking. */ filters?: readonly SessionEventMetadataFilter[] /** Maximum events in this page. */ limit?: number /** Opaque cursor returned for the identical normalized request. */ cursor?: SessionSearchCursor } ``` ```ts type-equiv /** One cursor-paginated result page. */ interface SessionSearchPage { /** Results for this page in contract-defined order. */ items: readonly T[] /** Opaque continuation cursor, absent on the final page. */ nextCursor?: SessionSearchCursor } ``` Unlike grouped cross-session hits, a within-session search must also expose its observed target header even when the page contains no hits. ```ts type-equiv /** Event-search results bound to the indexed target-session observation. */ interface SessionEventSearchPage extends SessionSearchPage { /** Cloned target header from the same indexed generation as `items`. */ session: SessionHeader } ``` ```ts type-equiv /** One event full-text search hit with a bounded plain-text excerpt. */ interface SessionEventSearchHit extends SessionEventRecord { /** Plain text excerpt selected around the match. */ snippet: string } ``` ```ts type-equiv /** One grouped cross-session hit, ranked by its strongest matching event. */ interface SessionSearchHit extends SessionRecord { /** Strongest matching event for this session. */ bestMatch: SessionEventSearchHit } ``` ## Session lineage `SessionLineageTrace` carries known parents in immediate-to-outward order and a forest of recursively nested direct descendants. The completeness discriminant makes a known root and a missing parent mutually exclusive. ```ts type-equiv /** Recursive descendant node in a session-lineage trace. */ interface SessionLineageNode { /** Detached logical-corpus record for this descendant. */ session: SessionRecord /** Direct children, each carrying its own recursive descendants. */ descendants: SessionLineageNode[] } ``` ```ts type-equiv /** Known ancestry and descendants for one logical session. */ type SessionLineageTrace = { /** Detached record for the session that was traced. */ target: SessionRecord /** Known parents from the immediate parent outward. */ ancestors: SessionRecord[] /** Complete known descendant trees rooted at the target's direct children. */ descendants: SessionLineageNode[] } & ( | { /** The complete parent chain is present in the logical corpus. */ complete: true /** Detached record at the top of the complete lineage. */ root: SessionRecord } | { /** The parent chain leaves the visible logical corpus. */ complete: false /** First parent id that is not present in the logical corpus. */ unresolvedParentId: SessionId } ) ``` ## Bounded event reads The request addresses one raw seq and optional neighboring counts. The result carries a `SessionHeader` rather than availability flags so a known live target can remain independent of persistence health. ```ts type-equiv /** Request for one event plus raw neighboring log context. */ interface SessionEventReadRequest { /** Session that owns the target event. */ sessionId: SessionId /** Target event seq. */ seq: number /** Number of preceding raw events to include. */ before?: number /** Number of following raw events to include. */ after?: number } ``` ```ts type-equiv /** Full target event and a bounded raw-log window. */ interface SessionEventWindow { /** Cloned header for the live-preferred source read. */ session: SessionHeader /** Full cloned target event. */ target: SessionEvent /** Full cloned events from `startSeq` through `endSeq`. */ events: SessionEvent[] /** First seq included in `events`. */ startSeq: number /** Last seq included in `events`. */ endSeq: number } ``` ## Event relationships Event traces distinguish positional surface replacement from events cited as sources. Every seq list contains direct links except `replacementChain`, which follows immediate replacers from the target to the final positional replacement. ```ts type-equiv /** Request for direct surface replacements and relationships to cited source events around one event. */ interface SessionEventTraceRequest { /** Session that owns the target event. */ sessionId: SessionId /** Target event seq. */ seq: number } ``` ```ts type-equiv /** Direct surface replacements and relationships to cited source events for one event. */ interface SessionEventTrace { /** Lightweight target record. */ target: SessionEventRecord /** Immediate positional replacement event, when the target was shadowed. */ replacedBy?: number /** Positional replacers from the immediate replacement to the final replacement. */ replacementChain: number[] /** Surface nodes directly removed when the target itself performed a replacement. */ replacedEventSeqs: number[] /** Earlier events cited directly as sources, in their recorded order. */ sourceEventSeqs: number[] /** Later events that directly cite the target as a source, in log order. */ derivedEventSeqs: number[] } ``` ```ts type-equiv /** Event relationships bound to the same session-header observation. */ interface SessionEventTraceObservation extends SessionEventTrace { /** Cloned header selected with the event log used for the trace. */ session: SessionHeader } ``` ## Errors The closed code union distinguishes request validation, missing targets, malformed surface logs, optional-backend failure, and contradictory source metadata. ```ts type-equiv /** Stable machine-routable failure taxonomy for session reads, traces, and search. */ type SessionQueryErrorCode = | 'SESSION_QUERY_ABORTED' | 'SESSION_QUERY_CORRUPT_SESSION' | 'SESSION_QUERY_EVENT_NOT_FOUND' | 'SESSION_QUERY_INDEX_FAILED' | 'SESSION_QUERY_INVALID_CONFIG' | 'SESSION_QUERY_INVALID_CURSOR' | 'SESSION_QUERY_INVALID_FILTER' | 'SESSION_QUERY_INVALID_LIMIT' | 'SESSION_QUERY_INVALID_QUERY' | 'SESSION_QUERY_INVALID_LINEAGE' | 'SESSION_QUERY_INVALID_SURFACE' | 'SESSION_QUERY_INVALID_WINDOW' | 'SESSION_QUERY_PERSISTENCE_FAILED' | 'SESSION_QUERY_SESSION_NOT_FOUND' | 'SESSION_QUERY_STALE_CURSOR' | 'SESSION_QUERY_SOURCE_CONFLICT' ``` ## Cordis API Generated from source by `scripts/gen-cordis-catalog.ts` (verified fresh by `pnpm run verify-cordis-catalog` in doc-sync; regenerate with `pnpm run gen-cordis-catalog`) — this section is byte-identical in both language sides of the page. Signature blocks use a `ts cordis-catalog` fence and keep the original source JSDoc; dispatch modes are defined in the [primer](../cordis-primer.md#dispatch-modes), and the framework-inherited `ctx` API lives in [cordis-api/inherited.md](../cordis-api/inherited.md). ### `ctx.sessionQuery` — `SessionQueryEngine` (abstract seam) Unified live-preferred session query service. Exact reads, filters, and traces are backend-independent concrete behavior. A backend implements full-text observation, reconciliation, ranking, cursor generations, and query execution on the same `ctx.sessionQuery` service. ```ts cordis-catalog /** * Search the live-preferred logical corpus and group by session. * @param request - query text, metadata filters, page size, and cursor. * @param exec - optional cancellation control. * @returns session hits ranked by their strongest matching event. */ abstract searchSessions( request: SessionSearchRequest, exec?: SessionSearchExecContext, ): Promise> /** * Search events within one live-preferred logical session. * @param request - target session, query text, filters, page size, and cursor. * @param exec - optional cancellation control. * @returns matching event hits and their target header from one indexed generation. */ abstract searchEvents( request: SessionEventSearchRequest, exec?: SessionSearchExecContext, ): Promise /** * List the complete logical corpus using live-preferred records. * @param signal - optional cancellation for persistence listing. * @returns deterministic newest-first cloned session records. */ listSessions(signal?: AbortSignal): Promise /** * Read and replay-validate one complete logical session log without making it live. * @param sessionId - live or persisted session id to read. * @returns cloned header and complete raw event log from one observation. * @throws when persistence, header compatibility, or replay validation fails. */ async readSession(sessionId: SessionId): Promise /** * Filter the complete logical corpus with provider-independent predicates. * @param filters - ANDed session metadata and availability clauses. * @param signal - optional cancellation for persistence listing. * @returns matching cloned records in deterministic newest-first order. */ async filterSessions( filters: readonly SessionResultFilter[], signal?: AbortSignal, ): Promise /** * Fold the latest log-backed title from one live-preferred logical session. * @param sessionId - live or persisted session id to read. * @param signal - optional cancellation for source resolution and title folding. * @returns latest title snapshot, or `undefined` when the log has no title event. */ async readTitle( sessionId: SessionId, signal?: AbortSignal, ): Promise /** * Fold the latest title and return its source header from one corpus observation. * @param sessionId - live or persisted session id to read. * @param signal - optional cancellation for source resolution and title folding. * @returns cloned source header and optional latest title snapshot. */ async readTitleSnapshot( sessionId: SessionId, signal?: AbortSignal, ): Promise /** * Fold titles for unique sessions from one cancellable corpus observation. * * Results preserve first-occurrence input order. Operational failures stay * isolated per session, while cancellation rejects the complete operation. * @param sessionIds - live or persisted session ids to observe. * @param signal - optional cancellation shared by all source reads. * @returns one fulfilled or rejected result per unique requested id. */ async readTitleSnapshots( sessionIds: readonly SessionId[], signal?: AbortSignal, ): Promise /** * List lightweight raw-log event records for one logical session. * @param sessionId - live-preferred session id to read. * @returns event records in ascending seq order. */ async listEvents(sessionId: SessionId): Promise /** * Scan first-party semantic event documents with provider-independent filters. * @param sessionId - live-preferred session id to scan. * @param filters - ANDed metadata and literal-text predicates. * @returns matching semantic documents in ascending seq order. */ async filterEvents( sessionId: SessionId, filters: readonly SessionEventResultFilter[], ): Promise /** * Read one session's complete current model surface from one corpus observation. * @param sessionId - live-preferred session id to read. * @returns cloned header, current surface, and the last sequence number included in the raw-log capture. * @throws when source resolution fails or the session surface is invalid. */ async readSurface(sessionId: SessionId): Promise /** * Trace known ancestry and descendants from one corpus observation. * @param sessionId - logical session id to trace. * @param signal - optional cancellation for persistence listing. * @returns a complete lineage or the first parent that could not be resolved. * @throws when corpus resolution fails, the target is absent, or its known ancestry cycles. */ async traceSession(sessionId: SessionId, signal?: AbortSignal): Promise /** * Trace one event's direct positional replacements and cited source events. * @param request - target session id and event seq. * @param signal - optional cancellation for persisted source resolution. * @returns source header, direct links, and the target's positional replacement chain. * @throws when source resolution fails, the target is absent, or surface/source-event validation fails. */ async traceEvent(request: SessionEventTraceRequest, signal?: AbortSignal): Promise /** * Read one full event plus a bounded raw-log context window. * @param request - target session/seq and context sizes. * @param signal - optional cancellation for persisted source resolution. * @returns cloned target and neighboring events. */ async readEvent(request: SessionEventReadRequest, signal?: AbortSignal): Promise ``` Types: [SessionId](core.md) · [SessionTitleSnapshot](session-title.md) Source: [`packages/session-query/session-query/src/index.ts:81`](../../packages/session-query/session-query/src/index.ts)