176 lines
4.9 KiB
TypeScript
176 lines
4.9 KiB
TypeScript
import {
|
|
mkdtemp,
|
|
readFile,
|
|
readdir,
|
|
rm,
|
|
writeFile
|
|
} from 'node:fs/promises'
|
|
import { tmpdir } from 'node:os'
|
|
import { join } from 'node:path'
|
|
import { afterEach, describe, expect, it } from 'vitest'
|
|
import {
|
|
defaultDocumentParsingSettings,
|
|
DocumentParsingSettingsStore
|
|
} from './document-parsing-settings-store'
|
|
|
|
const temporaryDirectories: string[] = []
|
|
|
|
async function createStore(): Promise<{
|
|
directory: string
|
|
filePath: string
|
|
store: DocumentParsingSettingsStore
|
|
}> {
|
|
const directory = await mkdtemp(
|
|
join(tmpdir(), 'goodbuddy-document-parsing-settings-')
|
|
)
|
|
temporaryDirectories.push(directory)
|
|
const filePath = join(directory, 'document-parsing-settings.json')
|
|
return {
|
|
directory,
|
|
filePath,
|
|
store: new DocumentParsingSettingsStore(filePath)
|
|
}
|
|
}
|
|
|
|
afterEach(async () => {
|
|
await Promise.all(
|
|
temporaryDirectories.splice(0).map((directory) =>
|
|
rm(directory, { recursive: true, force: true })
|
|
)
|
|
)
|
|
})
|
|
|
|
describe('DocumentParsingSettingsStore', () => {
|
|
it('returns local-first defaults without creating a file', async () => {
|
|
const { directory, store } = await createStore()
|
|
|
|
await expect(store.get()).resolves.toEqual(
|
|
defaultDocumentParsingSettings
|
|
)
|
|
expect(store.getWarnings()).toEqual([])
|
|
await expect(readdir(directory)).resolves.toEqual([])
|
|
})
|
|
|
|
it('persists a complete versioned settings document', async () => {
|
|
const { filePath, store } = await createStore()
|
|
const settings = {
|
|
...defaultDocumentParsingSettings,
|
|
chatWorkflow: 'fast-text' as const,
|
|
maximumPages: 42
|
|
}
|
|
|
|
await expect(store.update(settings)).resolves.toEqual(settings)
|
|
expect(JSON.parse(await readFile(filePath, 'utf8'))).toEqual({
|
|
version: 3,
|
|
...settings
|
|
})
|
|
await expect(
|
|
new DocumentParsingSettingsStore(filePath).get()
|
|
).resolves.toEqual(settings)
|
|
})
|
|
|
|
it('migrates version 2 OCR switches into scenario modes', async () => {
|
|
const { filePath, store } = await createStore()
|
|
await writeFile(
|
|
filePath,
|
|
JSON.stringify({
|
|
version: 2,
|
|
chatWorkflow: 'auto',
|
|
knowledgeWorkflow: 'complete-index',
|
|
pdfOcrMode: 'always',
|
|
ocrProvider: 'local',
|
|
localOcrEnabled: true,
|
|
localOcrModelId: 'pp-ocrv6-small',
|
|
maximumPages: 42,
|
|
ocrConcurrency: 4,
|
|
pageTimeoutSeconds: 90
|
|
}),
|
|
'utf8'
|
|
)
|
|
|
|
await expect(store.get()).resolves.toEqual({
|
|
chatWorkflow: 'high-fidelity',
|
|
knowledgeWorkflow: 'high-fidelity',
|
|
localOcrModelId: 'pp-ocrv6-small',
|
|
maximumPages: 42,
|
|
pageTimeoutSeconds: 90
|
|
})
|
|
})
|
|
|
|
it('migrates version 1 cloud settings into local scenario modes', async () => {
|
|
const { filePath, store } = await createStore()
|
|
await writeFile(
|
|
filePath,
|
|
JSON.stringify({
|
|
version: 1,
|
|
chatWorkflow: 'auto',
|
|
knowledgeWorkflow: 'complete-index',
|
|
pdfOcrMode: 'auto',
|
|
localOcrEnabled: false,
|
|
localOcrModelId: 'pp-ocrv6-tiny',
|
|
maximumPages: 100,
|
|
ocrConcurrency: 1,
|
|
pageTimeoutSeconds: 60,
|
|
chatCloudPermission: 'always',
|
|
knowledgeCloudPermission: 'never'
|
|
}),
|
|
'utf8'
|
|
)
|
|
|
|
await expect(store.get()).resolves.toEqual({
|
|
...defaultDocumentParsingSettings,
|
|
chatWorkflow: 'fast-text',
|
|
knowledgeWorkflow: 'fast-index'
|
|
})
|
|
})
|
|
|
|
it('rejects incomplete or out-of-range settings', async () => {
|
|
const { directory, store } = await createStore()
|
|
|
|
await expect(store.update({})).rejects.toThrow()
|
|
await expect(
|
|
store.update({
|
|
...defaultDocumentParsingSettings,
|
|
maximumPages: 0
|
|
})
|
|
).rejects.toThrow()
|
|
await expect(readdir(directory)).resolves.toEqual([])
|
|
})
|
|
|
|
it('isolates corrupt settings and restores defaults', async () => {
|
|
const { directory, filePath, store } = await createStore()
|
|
await writeFile(filePath, '{not-json', 'utf8')
|
|
|
|
await expect(store.get()).resolves.toEqual(
|
|
defaultDocumentParsingSettings
|
|
)
|
|
expect(store.getWarnings()).toEqual([
|
|
{ code: 'document-parsing-settings-recovered' }
|
|
])
|
|
const entries = await readdir(directory)
|
|
expect(entries).toHaveLength(1)
|
|
expect(entries[0]).toMatch(
|
|
/^document-parsing-settings\.json\.corrupt-\d+-[a-f0-9]{12}$/u
|
|
)
|
|
})
|
|
|
|
it('preserves settings created by a newer unsupported version', async () => {
|
|
const { directory, filePath, store } = await createStore()
|
|
const futureSettings = JSON.stringify({
|
|
version: 99,
|
|
futureField: 'keep-me'
|
|
})
|
|
await writeFile(filePath, futureSettings, 'utf8')
|
|
|
|
await expect(store.get()).rejects.toThrow(
|
|
'不支持文档解析设置版本 99'
|
|
)
|
|
expect(await readFile(filePath, 'utf8')).toBe(futureSettings)
|
|
expect(
|
|
(await readdir(directory)).some((name) =>
|
|
name.startsWith('document-parsing-settings.json.corrupt-')
|
|
)
|
|
).toBe(false)
|
|
})
|
|
})
|