| 364 | } |
| 365 | |
| 366 | class SqliteSessionStore implements SessionAuthorityStore { |
| 367 | private readonly metadata: SqliteSessionMetadataStore; |
| 368 | private readonly workspaceRoot: string; |
| 369 | private readonly transcriptChangeListeners = new Set<(sessionId: string) => void>(); |
| 370 | private closePromise: Promise<void> | null = null; |
| 371 | |
| 372 | constructor(workspaceRoot: string) { |
| 373 | this.workspaceRoot = workspaceRoot; |
| 374 | const databaseLease = acquireOperationalStateDatabase(workspaceRoot); |
| 375 | this.metadata = createSqliteSessionMetadataStore( |
| 376 | join(workspaceRoot, OPERATIONAL_STATE_DATABASE_NAME), |
| 377 | { databaseLease }, |
| 378 | ); |
| 379 | } |
| 380 | |
| 381 | private ensureReady(): Promise<void> { |
| 382 | return Promise.resolve(); |
| 383 | } |
| 384 | |
| 385 | ready(): Promise<void> { |
| 386 | return this.ensureReady(); |
| 387 | } |
| 388 | |
| 389 | async create( |
| 390 | input: CreateSessionInput, |
| 391 | initialBoundary?: ExecutionBoundary, |
| 392 | ): Promise<SessionHeader> { |
| 393 | await this.ensureReady(); |
| 394 | assertNoConversationCopyMetadata(input); |
| 395 | if (input.subagentSpawn) { |
| 396 | throw new Error('Subagent spawn metadata requires createSubagent()'); |
| 397 | } |
| 398 | return ( |
| 399 | await this.metadata.create(buildSessionHeader(this.workspaceRoot, input), initialBoundary) |
| 400 | ).header; |
| 401 | } |
| 402 | |
| 403 | async createImportedSession( |
| 404 | input: CreateSessionInput, |
| 405 | messages: readonly StoredMessage[], |
| 406 | ): Promise<SessionHeader> { |
| 407 | await this.ensureReady(); |
| 408 | assertNoConversationCopyMetadata(input); |
| 409 | if (input.subagentSpawn) { |
| 410 | throw new Error('Subagent spawn metadata requires createSubagent()'); |
| 411 | } |
| 412 | const canonicalMessages = messages.map((message) => |
| 413 | decodeStoredMessage(JSON.parse(JSON.stringify(message)) as unknown), |
| 414 | ); |
| 415 | const header: SessionHeader = { |
| 416 | ...buildSessionHeader(this.workspaceRoot, input), |
| 417 | transcriptLedgerVersion: 0, |
| 418 | }; |
| 419 | const outcome = await this.metadata.importSession( |
| 420 | header, |
| 421 | canonicalMessages, |
| 422 | projectSessionCatalogMessages(canonicalMessages), |
| 423 | ); |
nothing calls this directly
no outgoing calls
no test coverage detected