refactor(session-query): narrow phase one to exact reads
This commit is contained in:
@@ -18,7 +18,7 @@ Everything else is documented on a **sub-page**, not here. The rule that draws t
|
||||
| [llm-streaming.md](llm-streaming.md) | the `StreamChunk` wire protocol + adapter contract, `BlockAssembler`, the `LlmAdapter` seam |
|
||||
| [session.md](session.md) | the full `SessionEventMap` variant catalog, `TurnTrigger`/`TurnEndReason`, `deriveMessages()`, the turn-enclosure invariant |
|
||||
| [persistence.md](persistence.md) | the durability seam: `SessionPersistence`, JSONL + SQLite backends, `session/flush`, crash recovery, `SessionHeader` |
|
||||
| [session-query.md](session-query.md) | the retrieval seam: logical session/event records, filters, traces, search pages, extractors, and provider synchronization types |
|
||||
| [session-query.md](session-query.md) | logical session/event records and bounded exact-event reads |
|
||||
| [tools.md](tools.md) | `ToolDefinition` full fields, the schema DSL, `ToolExecution`/`ToolResult`, tool-presentation UI types, the `tools/pre-execute`/`tools/post-execute` pipeline |
|
||||
| [user-interaction.md](user-interaction.md) | the UI-backed human question/answer seam: `AskUserQuestionRequest`, answer/options vocabulary, provider API, error taxonomy |
|
||||
| [bash.md](bash.md) | the bash executor seam: `BashExecRequest`/`Spec`, `BashRunResult`, background `BashTask`s |
|
||||
|
||||
@@ -73,20 +73,6 @@ interface CreateSessionOptions {
|
||||
|
||||
Replay/fork is therefore `ctx.sessions.create(id, { seed: seedEvents })`; resuming a *persisted* session into a live agent is `ctx.agents.resume({ resumeSessionId })`.
|
||||
|
||||
## `SessionPersistedChange` — committed-log notification range
|
||||
|
||||
The observe-only `session/persisted` event carries the canonical header and the committed range. A repair can report `toSeq < fromSeq` when it only removes a torn fragment.
|
||||
|
||||
Source: [`packages/session-persistence/session-persistence/src/index.ts`](../../packages/session-persistence/session-persistence/src/index.ts)
|
||||
|
||||
```ts type-equiv
|
||||
export interface SessionPersistedChange {
|
||||
kind: 'append' | 'repair'
|
||||
fromSeq: number
|
||||
toSeq: number
|
||||
}
|
||||
```
|
||||
|
||||
## The backends
|
||||
|
||||
Both implement the same abstract `SessionPersistence` (create/append/load/list over `SessionEvent`) and pass `runPersistenceContract`, proving the seam is genuinely backend-agnostic:
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
# Session Query
|
||||
|
||||
The provider-neutral retrieval seam over live and optionally persisted sessions. The [package contract](../../packages/session-query/session-query) owns resolution, lifecycle, synchronization, and error behavior; this page catalogs the public data exchanged by callers, extractors, and search providers.
|
||||
Exact reads over the live-preferred logical session corpus. The [package contract](../../packages/session-query/session-query) owns source precedence, dynamic optional persistence, cloning, surface classification, bounded windows, and typed failures. Full-text search is a separate proposed SQLite phase.
|
||||
|
||||
Source: [`packages/session-query/session-query/src/types.ts`](../../packages/session-query/session-query/src/types.ts)
|
||||
|
||||
## Logical records and filters
|
||||
## Logical records
|
||||
|
||||
`SessionRecord` exposes source availability independently from its live-preferred header. `SessionEventRecord` classifies every raw event against the folded surface.
|
||||
`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
|
||||
export type SessionEventSurface = 'current' | 'shadowed' | 'log-only'
|
||||
@@ -30,137 +30,9 @@ export interface SessionEventRecord {
|
||||
}
|
||||
```
|
||||
|
||||
Filters are serializable discriminated specs. Each spec is one transform in a chain; the literal types below are shared by in-memory filtering and provider pre-ranking requests.
|
||||
## Bounded event reads
|
||||
|
||||
```ts type-equiv
|
||||
export interface SessionQueryRange {
|
||||
from?: number
|
||||
to?: number
|
||||
}
|
||||
```
|
||||
|
||||
```ts type-equiv
|
||||
export type SessionResultFilter =
|
||||
| { kind: 'id'; values: readonly SessionId[] }
|
||||
| { kind: 'cwd'; values: readonly (string | null)[] }
|
||||
| { kind: 'created-at'; range: SessionQueryRange }
|
||||
| { kind: 'parent'; values: readonly (SessionId | null)[] }
|
||||
| { kind: 'availability'; values: readonly ('live' | 'persisted')[] }
|
||||
```
|
||||
|
||||
```ts type-equiv
|
||||
export type SessionEventResultFilter =
|
||||
| { kind: 'seq'; range: SessionQueryRange }
|
||||
| { kind: 'time'; range: SessionQueryRange }
|
||||
| { kind: 'type'; values: readonly SessionEventType[] }
|
||||
| { kind: 'surface'; values: readonly SessionEventSurface[] }
|
||||
```
|
||||
|
||||
## Search requests and pages
|
||||
|
||||
Both scopes use the same opaque-cursor page envelope. Session hits carry exactly one best event; event hits add only a plain-text snippet to the lightweight record.
|
||||
|
||||
```ts type-equiv
|
||||
export interface SessionQueryExecContext {
|
||||
readonly signal?: AbortSignal
|
||||
}
|
||||
```
|
||||
|
||||
```ts type-equiv
|
||||
export type SessionSearchProviderStatus =
|
||||
| { readonly available: true }
|
||||
| { readonly available: false; readonly reason: 'misconfigured' | 'unavailable' }
|
||||
```
|
||||
|
||||
```ts type-equiv
|
||||
export interface SessionSearchPageRequest {
|
||||
limit?: number
|
||||
cursor?: string
|
||||
}
|
||||
```
|
||||
|
||||
```ts type-equiv
|
||||
export interface SessionSearchRequest extends SessionSearchPageRequest {
|
||||
query: string
|
||||
sessionFilters?: readonly SessionResultFilter[]
|
||||
eventFilters?: readonly SessionEventResultFilter[]
|
||||
}
|
||||
```
|
||||
|
||||
```ts type-equiv
|
||||
export interface SessionEventSearchRequest extends SessionSearchPageRequest {
|
||||
sessionId: SessionId
|
||||
query: string
|
||||
filters?: readonly SessionEventResultFilter[]
|
||||
}
|
||||
```
|
||||
|
||||
The service resolves caller requests before crossing the provider seam, so provider implementations always receive a validated page limit.
|
||||
|
||||
```ts type-equiv
|
||||
export interface SessionSearchSpec extends SessionSearchRequest {
|
||||
limit: number
|
||||
}
|
||||
```
|
||||
|
||||
```ts type-equiv
|
||||
export interface SessionEventSearchSpec extends SessionEventSearchRequest {
|
||||
limit: number
|
||||
}
|
||||
```
|
||||
|
||||
```ts type-equiv
|
||||
export interface SessionEventSearchHit extends SessionEventRecord {
|
||||
snippet: string
|
||||
}
|
||||
```
|
||||
|
||||
```ts type-equiv
|
||||
export interface SessionSearchHit extends SessionRecord {
|
||||
bestMatch: SessionEventSearchHit
|
||||
}
|
||||
```
|
||||
|
||||
```ts type-equiv
|
||||
export interface SessionSearchPage<T> {
|
||||
providerId: string
|
||||
items: readonly T[]
|
||||
nextCursor?: string
|
||||
}
|
||||
```
|
||||
|
||||
## Errors
|
||||
|
||||
The service exposes a closed machine-routable error taxonomy; messages and causes provide detail but do not add codes.
|
||||
|
||||
```ts type-equiv
|
||||
export type SessionQueryErrorCode =
|
||||
| 'SESSION_QUERY_ABORTED'
|
||||
| 'SESSION_QUERY_DUPLICATE_EXTRACTOR'
|
||||
| 'SESSION_QUERY_DUPLICATE_PROVIDER'
|
||||
| 'SESSION_QUERY_EVENT_NOT_FOUND'
|
||||
| 'SESSION_QUERY_INDEX_FAILED'
|
||||
| 'SESSION_QUERY_INVALID_CONFIG'
|
||||
| 'SESSION_QUERY_INVALID_EXTRACTOR'
|
||||
| 'SESSION_QUERY_INVALID_FILTER'
|
||||
| 'SESSION_QUERY_INVALID_LIMIT'
|
||||
| 'SESSION_QUERY_INVALID_LINEAGE'
|
||||
| 'SESSION_QUERY_INVALID_QUERY'
|
||||
| 'SESSION_QUERY_INVALID_SURFACE'
|
||||
| 'SESSION_QUERY_INVALID_WINDOW'
|
||||
| 'SESSION_QUERY_PERSISTENCE_FAILED'
|
||||
| 'SESSION_QUERY_PROVIDER_AMBIGUOUS'
|
||||
| 'SESSION_QUERY_PROVIDER_CONFIGURED_MISSING'
|
||||
| 'SESSION_QUERY_PROVIDER_CONFIGURED_UNAVAILABLE'
|
||||
| 'SESSION_QUERY_PROVIDER_ERROR'
|
||||
| 'SESSION_QUERY_PROVIDER_UNAVAILABLE'
|
||||
| 'SESSION_QUERY_SESSION_NOT_FOUND'
|
||||
| 'SESSION_QUERY_SOURCE_CONFLICT'
|
||||
```
|
||||
|
||||
## Event reads and traces
|
||||
|
||||
An event read returns the full target plus a bounded raw-log window. Trace records retain lightweight seq links so callers choose which related event bodies to read.
|
||||
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
|
||||
export interface SessionEventReadRequest {
|
||||
@@ -173,7 +45,7 @@ export interface SessionEventReadRequest {
|
||||
|
||||
```ts type-equiv
|
||||
export interface SessionEventWindow {
|
||||
session: SessionRecord
|
||||
session: SessionHeader
|
||||
target: SessionEvent
|
||||
events: SessionEvent[]
|
||||
startSeq: number
|
||||
@@ -181,84 +53,17 @@ export interface SessionEventWindow {
|
||||
}
|
||||
```
|
||||
|
||||
```ts type-equiv
|
||||
export interface SessionLineageNode {
|
||||
session: SessionRecord
|
||||
children: SessionLineageNode[]
|
||||
}
|
||||
```
|
||||
## Errors
|
||||
|
||||
The closed code union distinguishes request validation, missing targets, malformed surface logs, optional-backend failure, and contradictory source metadata.
|
||||
|
||||
```ts type-equiv
|
||||
export interface SessionLineageTrace {
|
||||
target: SessionRecord
|
||||
parents: SessionRecord[]
|
||||
root?: SessionRecord
|
||||
unresolvedParentId?: SessionId
|
||||
children: SessionLineageNode[]
|
||||
}
|
||||
```
|
||||
|
||||
```ts type-equiv
|
||||
export interface SessionEventTrace {
|
||||
target: SessionEventRecord
|
||||
shadowedBy?: number
|
||||
replacementChain: number[]
|
||||
shadows: number[]
|
||||
references: number[]
|
||||
referencedBy: number[]
|
||||
}
|
||||
```
|
||||
|
||||
## Extraction and provider synchronization
|
||||
|
||||
Custom extractors are keyed by declaration-merged event or content discriminants and carry stable cache-invalidation versions. Providers receive complete event documents grouped into independently replaceable persisted and live snapshots.
|
||||
|
||||
```ts type-equiv
|
||||
export interface SessionEventTextExtractor<K extends SessionEventType = SessionEventType> {
|
||||
version: string
|
||||
extract(event: SessionEvent<K>): readonly string[]
|
||||
}
|
||||
```
|
||||
|
||||
```ts type-equiv
|
||||
export interface SessionContentTextExtractor<K extends ContentBlockType = ContentBlockType> {
|
||||
version: string
|
||||
extract(block: ContentBlockMap[K]): readonly string[]
|
||||
}
|
||||
```
|
||||
|
||||
```ts type-equiv
|
||||
export interface SessionIndexDocument extends SessionEventRecord {
|
||||
text: string
|
||||
}
|
||||
```
|
||||
|
||||
```ts type-equiv
|
||||
export interface SessionIndexSnapshot {
|
||||
session: SessionRecord
|
||||
fingerprint: string
|
||||
documents: readonly SessionIndexDocument[]
|
||||
}
|
||||
```
|
||||
|
||||
```ts type-equiv
|
||||
export interface SessionPersistedIndexEntry {
|
||||
sessionId: SessionId
|
||||
fingerprint: string
|
||||
}
|
||||
```
|
||||
|
||||
```ts type-equiv
|
||||
export interface SessionSearchProvider {
|
||||
readonly id: string
|
||||
status(): SessionSearchProviderStatus
|
||||
persistedInventory(): Promise<readonly SessionPersistedIndexEntry[]>
|
||||
setPersistedActive(active: boolean): Promise<void>
|
||||
replacePersisted(snapshot: SessionIndexSnapshot): Promise<void>
|
||||
removePersisted(sessionId: SessionId): Promise<void>
|
||||
replaceLive(snapshot: SessionIndexSnapshot): Promise<void>
|
||||
removeLive(sessionId: SessionId): Promise<void>
|
||||
searchSessions(request: SessionSearchSpec, exec?: SessionQueryExecContext): Promise<SessionSearchPage<SessionSearchHit>>
|
||||
searchEvents(request: SessionEventSearchSpec, exec?: SessionQueryExecContext): Promise<SessionSearchPage<SessionEventSearchHit>>
|
||||
}
|
||||
export type SessionQueryErrorCode =
|
||||
| 'SESSION_QUERY_EVENT_NOT_FOUND'
|
||||
| 'SESSION_QUERY_INVALID_CONFIG'
|
||||
| 'SESSION_QUERY_INVALID_SURFACE'
|
||||
| 'SESSION_QUERY_INVALID_WINDOW'
|
||||
| 'SESSION_QUERY_PERSISTENCE_FAILED'
|
||||
| 'SESSION_QUERY_SESSION_NOT_FOUND'
|
||||
| 'SESSION_QUERY_SOURCE_CONFLICT'
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user