refactor(ai-vault): consolidate owner imports and isolate path absence

This commit is contained in:
Neil
2026-11-12 03:20:08 -08:00
parent bba12cec71
commit 2ed3d013fb
14 changed files with 37 additions and 38 deletions
@@ -14,9 +14,11 @@ import {
type ExecutionHostId
} from '../../../shared/execution-host'
import { isPathInsideOrEqual } from '../../../shared/cross-platform-path'
import { AI_VAULT_AGENT_SOURCES } from '../discovery/session-scanner-agent-sources'
import {
AI_VAULT_AGENT_SOURCES,
sessionRowRootDirs
} from '../discovery/session-scanner-agent-sources'
import { isDiscoverableSessionFile } from '../discovery/session-file-discovery'
import { sessionRowRootDirs } from '../discovery/session-scanner-agent-sources'
import { subagentTranscriptsDirFor } from '../scanners/claude/session-scanner-subagent-transcripts'
import type { AiVaultScanOptions } from '../session-scanner-types'
@@ -0,0 +1,13 @@
import { WslTranscriptFsError } from '../../native-chat/wsl-transcript-fs-error'
/** A missing file or folder is absence, not a refusal; WSL gate errors are always refusals. */
export function isMissingTranscriptPathError(error: unknown): boolean {
if (error instanceof WslTranscriptFsError) {
return false
}
const code =
error && typeof error === 'object' && 'code' in error && typeof error.code === 'string'
? error.code
: null
return code === 'ENOENT' || code === 'ENOTDIR'
}
@@ -5,8 +5,10 @@ import { PrioritySemaphore } from '../../../shared/priority-semaphore'
import { isWslUncPath } from '../../../shared/wsl-paths'
import { SessionNewestFiles } from './session-newest-files'
import type { SessionSidecarObservation } from '../parse-cache/session-sidecar-stat'
import type { AiVaultAgent } from '../../../shared/ai-vault/contracts/ai-vault-types'
import type { AiVaultScanIssue } from '../../../shared/ai-vault/contracts/ai-vault-types'
import type {
AiVaultAgent,
AiVaultScanIssue
} from '../../../shared/ai-vault/contracts/ai-vault-types'
import { wslGatedReaddir, wslGatedStat } from '../../native-chat/wsl-transcript-fs-access'
import { WslTranscriptFsError } from '../../native-chat/wsl-transcript-fs-error'
import { recordSessionScanIssue, scanIssueTextFromError } from '../parsing/session-scan-issues'
@@ -23,6 +25,7 @@ import {
noteAiVaultScanWorkChanged,
openAiVaultScanSource
} from '../scan-lifecycle/ai-vault-scan-progress'
import { isMissingTranscriptPathError } from './session-path-absence'
const NATIVE_DISCOVERY_CONCURRENCY = 4
const NATIVE_DISCOVERY_BATCH_SIZE = 16
@@ -251,18 +254,6 @@ async function observeSessionSidecar(
}
}
/** A missing file or folder is absence, not a refusal; WSL gate errors are always refusals. */
export function isMissingTranscriptPathError(error: unknown): boolean {
if (error instanceof WslTranscriptFsError) {
return false
}
const code =
error && typeof error === 'object' && 'code' in error && typeof error.code === 'string'
? error.code
: null
return code === 'ENOENT' || code === 'ENOTDIR'
}
/** Collecting form for callers that want every match; bounded scans stream. */
export async function walkSessionFiles(
dirPath: string,
@@ -2,9 +2,12 @@ import { homedir } from 'node:os'
import { join } from 'node:path'
import { describe, expect, it } from 'vitest'
import { extractFullFirstUserPromptText } from '../prompts/session-scanner-first-user-prompt'
import { extractPreviewContentText } from './session-scanner-text-normalization'
import {
extractPreviewContentText,
normalizePreviewText,
normalizeTitleText
} from './session-scanner-text-normalization'
import { primeAgentSessionsDirFromEnv } from '../discovery/agent-session-directories'
import { normalizePreviewText, normalizeTitleText } from './session-scanner-text-normalization'
describe('AI Vault session scanner text values', () => {
it('normalizes compact title text without surfacing hidden context blocks', () => {
@@ -14,9 +14,8 @@ import {
import { addSessionContent } from '../../parsing/session-scanner-messages'
import type { FileWithMtime, SessionAccumulator } from '../../session-scanner-types'
import type { TranscriptMessageSink } from '../../transcripts/session-transcript-consumers'
import { arrayValue } from '../../parsing/session-record-fields'
import { arrayValue, asRecord } from '../../parsing/session-record-fields'
import { extractString } from '../../../../shared/trimmed-string'
import { asRecord } from '../../parsing/session-record-fields'
import {
extractContentText,
normalizeTitleText
@@ -37,8 +37,7 @@ import {
normalizeCodexUsage,
subtractCodexUsage
} from '../../parsing/session-scanner-token-values'
import { asRecord } from '../../parsing/session-record-fields'
import { extractGitBranch, extractModel } from '../../parsing/session-record-fields'
import { asRecord, extractGitBranch, extractModel } from '../../parsing/session-record-fields'
import { extractString } from '../../../../shared/trimmed-string'
import { parseJsonObject } from '../../parsing/session-json-object'
import { readCodexTimelineOnlyRecord } from './session-scanner-codex-record-fast-path'
@@ -15,9 +15,8 @@ import {
decodeSessionMessage,
type DecodedSessionMessage
} from '../../transcripts/session-decoded-message'
import { arrayValue } from '../../parsing/session-record-fields'
import { arrayValue, asRecord } from '../../parsing/session-record-fields'
import { extractString } from '../../../../shared/trimmed-string'
import { asRecord } from '../../parsing/session-record-fields'
import { extractContentText } from '../../parsing/session-scanner-text-normalization'
import { numberValue } from '../../parsing/session-scanner-token-values'
@@ -18,10 +18,9 @@ import {
updateTimeline
} from '../../parsing/session-scanner-accumulator'
import { addSessionContent } from '../../parsing/session-scanner-messages'
import { arrayValue } from '../../parsing/session-record-fields'
import { arrayValue, asRecord } from '../../parsing/session-record-fields'
import { extractString } from '../../../../shared/trimmed-string'
import { parseJsonObject } from '../../parsing/session-json-object'
import { asRecord } from '../../parsing/session-record-fields'
import { extractContentText } from '../../parsing/session-scanner-text-normalization'
import { tokenTotal } from '../../parsing/session-scanner-token-values'
@@ -11,9 +11,8 @@ import {
updateTimeline
} from '../../parsing/session-scanner-accumulator'
import { addSessionContent } from '../../parsing/session-scanner-messages'
import { arrayValue } from '../../parsing/session-record-fields'
import { arrayValue, asRecord } from '../../parsing/session-record-fields'
import { extractString } from '../../../../shared/trimmed-string'
import { asRecord } from '../../parsing/session-record-fields'
import { extractContentText } from '../../parsing/session-scanner-text-normalization'
import { numberValue } from '../../parsing/session-scanner-token-values'
@@ -11,9 +11,8 @@ import {
updateTimeline
} from '../../parsing/session-scanner-accumulator'
import { addSessionContent } from '../../parsing/session-scanner-messages'
import { arrayValue } from '../../parsing/session-record-fields'
import { arrayValue, asRecord } from '../../parsing/session-record-fields'
import { extractString } from '../../../../shared/trimmed-string'
import { asRecord } from '../../parsing/session-record-fields'
import {
extractContentText,
normalizeTitleText
@@ -15,10 +15,9 @@ import { consumeCompleteJsonlLines } from '../../parsing/session-scanner-jsonl-r
import type { FileWithMtime, SessionAccumulator } from '../../session-scanner-types'
import type { TranscriptMessageSink } from '../../transcripts/session-transcript-consumers'
import type { SkippedTranscriptRecord } from '../../transcripts/session-transcript-record-budget'
import { arrayValue } from '../../parsing/session-record-fields'
import { arrayValue, asRecord } from '../../parsing/session-record-fields'
import { extractString } from '../../../../shared/trimmed-string'
import { parseJsonObject } from '../../parsing/session-json-object'
import { asRecord } from '../../parsing/session-record-fields'
import { normalizeTitleText } from '../../parsing/session-scanner-text-normalization'
type ParserSessionOptions = {
@@ -12,11 +12,10 @@ import {
} from '../../parsing/session-scanner-accumulator'
import { addSessionContent } from '../../parsing/session-scanner-messages'
import { museSessionIdFromFilePath } from './session-scanner-muse-paths'
import { arrayValue } from '../../parsing/session-record-fields'
import { arrayValue, asRecord } from '../../parsing/session-record-fields'
import { extractString } from '../../../../shared/trimmed-string'
import { parseJsonObject } from '../../parsing/session-json-object'
import { timestampMs } from '../../parsing/session-record-time'
import { asRecord } from '../../parsing/session-record-fields'
import { normalizeTitleText } from '../../parsing/session-scanner-text-normalization'
import { numberValue } from '../../parsing/session-scanner-token-values'
@@ -32,12 +32,10 @@ import {
updateTimeline
} from '../parsing/session-scanner-accumulator'
import { addSessionContent } from '../parsing/session-scanner-messages'
import { arrayValue } from '../parsing/session-record-fields'
import { arrayValue, firstString, asRecord } from '../parsing/session-record-fields'
import { extractString } from '../../../shared/trimmed-string'
import { firstString } from '../parsing/session-record-fields'
import { parseJsonObject } from '../parsing/session-json-object'
import { readJsonObjectIfExists } from '../discovery/session-json-file'
import { asRecord } from '../parsing/session-record-fields'
import {
extractContentText,
extractMessageText
@@ -18,7 +18,7 @@ import type { FileWithMtime } from '../session-scanner-types'
import { extractString } from '../../../shared/trimmed-string'
import { parseJsonObject } from '../parsing/session-json-object'
import { scanIssueTextFromError } from '../parsing/session-scan-issues'
import { isMissingTranscriptPathError } from '../discovery/session-scanner-discovery'
import { isMissingTranscriptPathError } from '../discovery/session-path-absence'
import { noteAiVaultScanFileFound } from '../scan-lifecycle/ai-vault-scan-progress'
// Limit representative probing when a bucket contains transcripts without cwd records.