Skip to content
Open
49 changes: 49 additions & 0 deletions packages/shared/data/api/schemas/fileProcessing.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/**
* File Processing API Schema definitions
*
* Contains file processing endpoints for:
* - Listing available processors
* - Reading and updating processor configuration
*/

import type { FileProcessorId } from '@shared/data/preference/preferenceTypes'
import type { FileProcessorMerged, FileProcessorOverride } from '@shared/data/presets/file-processing'

// ============================================================================
// API Schema Definitions
// ============================================================================

/**
* File Processing API Schema definitions
*/
export interface FileProcessingSchemas {
/**
* List available processors
* @example GET /file-processing/processors
*/
'/file-processing/processors': {
/** Get list of available processors */
GET: {
response: FileProcessorMerged[]
}
}

/**
* Get or update processor configuration
* @example GET /file-processing/processors/tesseract
* @example PATCH /file-processing/processors/tesseract { "apiKeys": ["xxx"] }
*/
'/file-processing/processors/:id': {
/** Get processor configuration */
GET: {
params: { id: FileProcessorId }
response: FileProcessorMerged
}
/** Update processor configuration */
PATCH: {
params: { id: FileProcessorId }
body: FileProcessorOverride
response: FileProcessorMerged
}
}
}
3 changes: 2 additions & 1 deletion packages/shared/data/api/schemas/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
*/

import type { AssertValidSchemas } from '../apiTypes'
import type { FileProcessingSchemas } from './fileProcessing'
import type { MessageSchemas } from './messages'
import type { TestSchemas } from './test'
import type { TopicSchemas } from './topics'
Expand All @@ -36,4 +37,4 @@ import type { TopicSchemas } from './topics'
* 1. Create the schema file (e.g., topic.ts)
* 2. Import and add to intersection below
*/
export type ApiSchemas = AssertValidSchemas<TestSchemas & TopicSchemas & MessageSchemas>
export type ApiSchemas = AssertValidSchemas<TestSchemas & TopicSchemas & MessageSchemas & FileProcessingSchemas>
15 changes: 12 additions & 3 deletions packages/shared/data/preference/preferenceSchemas.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/**
* Auto-generated preferences configuration
* Generated at: 2026-01-23T10:31:39.487Z
* Generated at: 2026-03-09T06:17:20.448Z
*
* This file is automatically generated from classification.json
* To update this file, modify classification.json and run:
Expand Down Expand Up @@ -382,6 +382,12 @@ export interface PreferenceSchemas {
'feature.translate.model_prompt': string
// redux/settings/targetLanguage
'feature.translate.target_language': string
// redux/preprocess/defaultProvider
'file_processing.default.markdown_conversion': PreferenceTypes.FileProcessorId
// redux/ocr/imageProviderId
'file_processing.default.text_extraction': PreferenceTypes.FileProcessorId | null
// target-key-definitions/complex/complex
'file_processing.overrides': PreferenceTypes.FileProcessorOverrides
// redux/shortcuts/shortcuts.exit_fullscreen
'shortcut.app.exit_fullscreen': Record<string, unknown>
// redux/shortcuts/shortcuts.search_message
Expand Down Expand Up @@ -650,6 +656,9 @@ export const DefaultPreferences: PreferenceSchemas = {
'feature.selection.trigger_mode': PreferenceTypes.SelectionTriggerMode.Selected,
'feature.translate.model_prompt': TRANSLATE_PROMPT,
'feature.translate.target_language': 'en-us',
'file_processing.default.markdown_conversion': 'mineru',
'file_processing.default.text_extraction': null,
'file_processing.overrides': {} as PreferenceTypes.FileProcessorOverrides,
'shortcut.app.exit_fullscreen': { editable: false, enabled: true, key: ['Escape'], system: true },
'shortcut.app.search_message': {
editable: true,
Expand Down Expand Up @@ -718,8 +727,8 @@ export const DefaultPreferences: PreferenceSchemas = {

/**
* 生成统计:
* - 总配置项: 204
* - 总配置项: 207
* - electronStore项: 1
* - redux项: 203
* - redux项: 205
* - localStorage项: 0
*/
6 changes: 6 additions & 0 deletions packages/shared/data/preference/preferenceTypes.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import type { FileProcessorOverride, PRESETS_FILE_PROCESSORS } from '@shared/data/presets/file-processing'

import type { PreferenceSchemas } from './preferenceSchemas'

export type PreferenceDefaultScopeType = PreferenceSchemas['default']
Expand Down Expand Up @@ -104,3 +106,7 @@ export type ChatMessageNavigationMode = 'none' | 'buttons' | 'anchor'
export type MultiModelMessageStyle = 'horizontal' | 'vertical' | 'fold' | 'grid'

export type MultiModelGridPopoverTrigger = 'hover' | 'click'

export type FileProcessorOverrides = Record<string, FileProcessorOverride>

export type FileProcessorId = (typeof PRESETS_FILE_PROCESSORS)[number]['id']
273 changes: 273 additions & 0 deletions packages/shared/data/presets/file-processing.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,273 @@
/**
* File Processing Presets
*
* Templates are read-only metadata about processors.
* User overrides are stored separately in preferences.
*
* i18n: Display names use `processor.${id}.name`
*/

// ============================================================================
// Type Definitions
// ============================================================================

/**
* Processor service type
*/
export type FileProcessorType = 'api' | 'builtin'

/**
* Feature type
*/
export type FileProcessorFeature = 'text_extraction' | 'markdown_conversion'

/**
* Input type (category)
* Can be migrated to FileTypes enum in @types later
*/
export type FileProcessorInput = 'image' | 'document'

/**
* Output type
*/
export type FileProcessorOutput = 'text' | 'markdown'

/**
* Processor metadata (reserved for future use)
*/
export type FileProcessorMetadata = Record<string, never>

/**
* Feature capability definition
*
* Each capability binds a feature with its input/output and optional API settings.
*/
export type CapabilityMetadata = Record<string, unknown>

export type TextExtractionCapability = {
feature: 'text_extraction'
input: 'image' | 'document'
output: 'text'
apiHost?: string // API Host (template default, can be overridden)
modelId?: string // Model ID (template default, can be overridden)
metadata?: CapabilityMetadata
// supportedFormats?: string[] // Whitelist: only these formats supported (uncomment when needed)
// excludedFormats?: string[] // Blacklist: all formats except these (uncomment when needed)
}

export type MarkdownConversionCapability = {
feature: 'markdown_conversion'
input: 'document'
output: 'markdown'
apiHost?: string // API Host (template default, can be overridden)
modelId?: string // Model ID (template default, can be overridden)
metadata?: CapabilityMetadata
// supportedFormats?: string[] // Whitelist: only these formats supported (uncomment when needed)
// excludedFormats?: string[] // Blacklist: all formats except these (uncomment when needed)
}

export type FeatureCapability = TextExtractionCapability | MarkdownConversionCapability

/**
* Processor template (read-only metadata)
*
* Note: Display name is retrieved via i18n key `processor.${id}.name`
*/
export type FileProcessorTemplate = {
id: string // Unique identifier, also used for i18n key
type: FileProcessorType // 'api' | 'builtin'
metadata?: FileProcessorMetadata // Optional processor metadata
capabilities: FeatureCapability[] // Feature capabilities
}

// ============================================================================
// Override Types (for user customization)
// ============================================================================

/**
* Processor-specific configuration
*
* Uses a generic Record type without predefined structure.
* Each processor's configuration is interpreted by UI components based on processor.id.
*
* Known options fields:
* - Tesseract: { langs: string[] } // Array of enabled language codes
*
* Examples:
* - { langs: ['chi_sim', 'eng'] } // Tesseract language config
* - { quality: 'high', timeout: 30000 } // Other processor config
*/
export type FileProcessorOptions = Record<string, unknown>

/**
* Capability override (user customization for a specific feature)
*
* Stored as Record<feature, CapabilityOverride> in FileProcessorOverride.
*/
export type CapabilityOverride = {
apiHost?: string
modelId?: string
metadata?: CapabilityMetadata
}

/**
* User-configured processor override (stored in Preference)
*
* Design principles:
* - Only stores user-modified fields
* - apiKey is shared across all features (processor-level)
* - apiHost/modelId are per-feature (in capabilities Record)
* - Field names use camelCase (consistent with TypeScript conventions)
*/
export type FileProcessorOverride = {
apiKeys?: string[] // API Keys (shared across all features)
capabilities?: Partial<Record<FileProcessorFeature, CapabilityOverride>> // Per-feature overrides
options?: FileProcessorOptions // Processor-specific config (generic type)
}

/**
* Merged processor configuration (template + user override)
*
* Used by both Renderer (UI display/editing) and Main (execution).
* Combines the read-only template with user-configured overrides.
*
* Note: capabilities is an array (from template) with overrides merged in,
* NOT a Record like in FileProcessorOverride.
*/
export type FileProcessorMerged = {
id: string
type: FileProcessorType
metadata?: FileProcessorMetadata
capabilities: FeatureCapability[] // Merged capabilities (array)
apiKeys?: string[]
options?: FileProcessorOptions
}

// ============================================================================
// Processor Presets
// ============================================================================

/**
* Built-in processor presets
*/
export const PRESETS_FILE_PROCESSORS = [
// === Image Processors (former OCR) ===
{
id: 'tesseract',
type: 'builtin',
capabilities: [
{
feature: 'text_extraction',
input: 'image',
output: 'text'
}
]
},
{
id: 'system',
type: 'builtin',
capabilities: [{ feature: 'text_extraction', input: 'image', output: 'text' }]
},
{
id: 'paddleocr',
type: 'api',
capabilities: [
{
feature: 'text_extraction',
input: 'image',
output: 'text',
apiHost: 'https://paddleocr.aistudio-app.com/',
modelId: 'PP-OCRv5',
metadata: {
optionalPayload: {
useDocOrientationClassify: false,
useDocUnwarping: false
}
}
},
{
feature: 'markdown_conversion',
input: 'document',
output: 'markdown',
apiHost: 'https://paddleocr.aistudio-app.com/',
modelId: 'PaddleOCR-VL-1.5',
metadata: {
optionalPayload: {
useDocOrientationClassify: false,
useDocUnwarping: false
}
}
}
]
},
{
id: 'ovocr',
type: 'builtin',
capabilities: [{ feature: 'text_extraction', input: 'image', output: 'text' }]
},

// === Document Processors (former Preprocess) ===
{
id: 'mineru',
type: 'api',
capabilities: [
{
feature: 'markdown_conversion',
input: 'document',
output: 'markdown',
apiHost: 'https://mineru.net',
metadata: {
optionalPayload: {
enable_formula: true,
enable_table: true,
is_ocr: true
}
}
}
]
},
{
id: 'doc2x',
type: 'api',
capabilities: [
{
feature: 'markdown_conversion',
input: 'document',
output: 'markdown',
apiHost: 'https://v2.doc2x.noedgeai.com'
}
]
},
{
id: 'mistral',
type: 'api',
capabilities: [
{
feature: 'text_extraction',
input: 'image',
output: 'text',
apiHost: 'https://api.mistral.ai',
modelId: 'mistral-ocr-latest'
},
{
feature: 'markdown_conversion',
input: 'document',
output: 'markdown',
apiHost: 'https://api.mistral.ai',
modelId: 'mistral-ocr-latest'
}
]
},
{
id: 'open-mineru',
type: 'api',
capabilities: [
{
feature: 'markdown_conversion',
input: 'document',
output: 'markdown',
apiHost: 'http://127.0.0.1:8000'
}
]
}
] as const satisfies readonly FileProcessorTemplate[]
Loading