feat: add image hash-based OCR caching with 100MB size limit

- Implement SHA-256 image hashing to cache OCR results and avoid re-processing identical images
- Add 100MB file size limit for image uploads with user-friendly error messages
- Clear ghost suggestions when uploading new images to prevent interference
- Optimize size limit calculation in copilot plugin to include OCR context
- Remove debug logging from production code
- Add image processing optimization plan document

BREAKING CHANGE: Image upload size limit is now enforced at 100MB (previously unlimited)
This commit is contained in:
2026-02-15 22:17:37 +08:00
parent 190bb2b756
commit 1e58c18bbc
7 changed files with 161 additions and 96 deletions
+10 -13
View File
@@ -9,7 +9,6 @@ import { getOcrCache, OCR_SIZE_LIMIT, extractTextFromOCR } from '../utils/ocrCac
const COPILOT_PLUGIN_KEY = new PluginKey('milkdown-copilot')
const DEBOUNCE_MS = 1000
const SIZE_LIMIT = OCR_SIZE_LIMIT
const DEBUG = true
const IMAGE_NODE_TYPES = new Set(['image', 'image-block', 'imageBlock'])
interface CopilotState {
@@ -334,13 +333,8 @@ function scheduleFetch(view: EditorView, runtime: CopilotRuntime, pos: number) {
const doc = view.state.doc
const schema = view.state.schema
const overLimit = doc.content.size > SIZE_LIMIT
if (overLimit) {
setCopilotEnabled(view, false)
return
}
const baseSize = doc.content.size
const serializer = runtime.ctx.get(serializerCtx)
let prefixMarkdown = ''
let suffixMarkdown = ''
@@ -362,12 +356,15 @@ function scheduleFetch(view: EditorView, runtime: CopilotRuntime, pos: number) {
}
const requestPrefix = `${prefixMarkdown}${buildOcrContextForRequest(doc, pos)}`
const totalTextLen = (prefixMarkdown + suffixMarkdown).length
const ocrContextLen = requestPrefix.length - prefixMarkdown.length
const totalWithOcr = totalTextLen + ocrContextLen
const overLimit = totalWithOcr > SIZE_LIMIT
if (DEBUG) {
console.log('[Copilot] ===== LLM Request =====')
console.log('[Copilot] PREFIX:', requestPrefix)
console.log('[Copilot] SUFFIX:', suffixMarkdown)
console.log('[Copilot] ======================')
if (overLimit) {
setCopilotEnabled(view, false)
return
}
if (runtime.debounceTimer) {