495 lines
20 KiB
Markdown
495 lines
20 KiB
Markdown
# 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<T> {
|
|
/** 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<SessionEventSearchHit> {
|
|
/** 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'
|
|
```
|
|
|
|
<!-- BEGIN GENERATED cordis-surface (gen-cordis-catalog.ts) — do not edit between markers -->
|
|
|
|
<a id="cordis-surface"></a>
|
|
|
|
## 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).
|
|
|
|
<a id="ctxsessionquery--sessionqueryservice-abstract-seam"></a>
|
|
|
|
### `ctx.sessionQuery` — `SessionQueryService` (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<SessionSearchPage<SessionSearchHit>>
|
|
|
|
/**
|
|
* 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<SessionEventSearchPage>
|
|
|
|
/**
|
|
* 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<SessionRecord[]>
|
|
|
|
/**
|
|
* 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<SessionLogSnapshot>
|
|
|
|
/**
|
|
* 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<SessionRecord[]>
|
|
|
|
/**
|
|
* 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<SessionTitleSnapshot | undefined>
|
|
|
|
/**
|
|
* 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<SessionTitleObservation>
|
|
|
|
/**
|
|
* 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<SessionTitleObservationResult[]>
|
|
|
|
/**
|
|
* 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<SessionEventRecord[]>
|
|
|
|
/**
|
|
* 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<SessionEventSearchDocument[]>
|
|
|
|
/**
|
|
* 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<SessionSurfaceSnapshot>
|
|
|
|
/**
|
|
* 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<SessionLineageTrace>
|
|
|
|
/**
|
|
* 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<SessionEventTraceObservation>
|
|
|
|
/**
|
|
* 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<SessionEventWindow>
|
|
```
|
|
|
|
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)
|
|
<!-- END GENERATED cordis-surface -->
|