mirror of
https://github.com/stablyai/orca.git
synced 2026-09-24 16:02:41 +00:00
fix(ai-vault): fail an OpenCode capture it cannot read the message parts of
`readOpenCodeSessionMessages` returned an empty list when the message-part schema probe failed. The sink-aware reader treats that as a complete read, so the consumer committed nothing and marked the source `current`: the session stayed out of the index with nothing on its row to say why and no retry. The part limit a few lines below already throws for exactly this reason, so the two now agree. The preview path is unchanged and still degrades to no messages, which is what a list read should do. Also throws from the fixture's `appendOpenCodeSqliteTurn` when the session id names no row, instead of falling back to the fixture epoch and appending orphan messages a test would then assert over.
This commit is contained in:
@@ -173,7 +173,12 @@ export function readOpenCodeSessionMessages(
|
||||
sessionId: string
|
||||
): TranscriptMessage[] {
|
||||
if (!canReadOpenCodeMessageParts(db)) {
|
||||
return []
|
||||
// Thrown for the same reason the part limit below throws: an empty capture
|
||||
// returned here is committed under a complete-read cursor, so the session
|
||||
// stays out of search with nothing on its row to say why and no retry.
|
||||
throw new Error(
|
||||
`OpenCode session ${sessionId} uses an unreadable message-part schema; its transcript was not read.`
|
||||
)
|
||||
}
|
||||
const rows = db.prepare(buildCaptureQuery()).all(sessionId, OPENCODE_CAPTURE_PART_LIMIT + 1)
|
||||
if (rows.length > OPENCODE_CAPTURE_PART_LIMIT) {
|
||||
|
||||
@@ -210,8 +210,17 @@ export function appendOpenCodeSqliteTurn(
|
||||
}
|
||||
}
|
||||
|
||||
// Throws rather than falling back to the epoch: a mistyped id would otherwise
|
||||
// append orphan rows and update nothing, leaving a test asserting over a
|
||||
// transcript that no session owns.
|
||||
function currentUpdatedMs(db: SyncDatabase, sessionId: string): number {
|
||||
const row = db.prepare('SELECT time_updated FROM session WHERE id = ?').get(sessionId)
|
||||
const updated = row === undefined ? undefined : Object.values(row)[0]
|
||||
return typeof updated === 'number' ? updated : OPENCODE_FIXTURE_EPOCH_MS
|
||||
if (row === undefined) {
|
||||
throw new Error(`OpenCode fixture has no session ${sessionId} to append to`)
|
||||
}
|
||||
const updated = Object.values(row)[0]
|
||||
if (typeof updated !== 'number') {
|
||||
throw new Error(`OpenCode fixture session ${sessionId} has no numeric time_updated`)
|
||||
}
|
||||
return updated
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import Database from '../sqlite/sync-database'
|
||||
import { buildOpenCodeSqliteCandidatePath } from './session-scanner-opencode-sqlite-paths'
|
||||
import { listOpenCodeSqliteSessions } from './session-scanner-opencode-sqlite-discovery'
|
||||
import { parseOpenCodeSqliteSession } from './session-scanner-opencode-sqlite'
|
||||
import { captureOpenCodeSqliteSession } from './session-scanner-opencode-sqlite-capture'
|
||||
import { withFullFirstUserPromptCapture } from './session-scanner-first-user-prompt-capture'
|
||||
import type { AiVaultScanIssue } from '../../shared/ai-vault-types'
|
||||
|
||||
@@ -479,6 +480,20 @@ describe('parseOpenCodeSqliteSession', () => {
|
||||
expect(session!.previewMessages).toEqual([])
|
||||
})
|
||||
|
||||
// The preview may degrade to nothing, but the search index may not: an empty
|
||||
// capture is committed under a complete-read cursor, so the session would stay
|
||||
// unsearchable with nothing on its row to say why and no retry.
|
||||
it('refuses to capture a transcript it cannot read the message parts of', async () => {
|
||||
const { db, path } = createTempDb()
|
||||
applyMinimalOpenCodeSchema(db)
|
||||
db.prepare(`INSERT INTO session VALUES ('ses_minimal', 1777634000000, 1777634001000)`).run()
|
||||
db.close()
|
||||
|
||||
await expect(
|
||||
captureOpenCodeSqliteSession({ dbPath: path, sessionId: 'ses_minimal', platform: 'darwin' })
|
||||
).rejects.toThrow(/unreadable message-part schema/)
|
||||
})
|
||||
|
||||
it('extracts model from older modelID schema', async () => {
|
||||
const { db, path } = createTempDb()
|
||||
applyOpenCodeSchema(db)
|
||||
|
||||
Reference in New Issue
Block a user