feat(ocr): integrate Light-OCR#2005
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughThis PR adds an offline Light OCR attachment pipeline: a helper process/protocol, extraction service, encrypted cache, and capability router, integrated into session/turn coordination, attachment preflight/blocking UI, OCR settings, CI packaging/size gates, shared contracts, and full localization. It also refreshes the ACP registry and model catalog (unrelated). ChangesOffline Light OCR Attachment Integration
Unrelated ACP Registry & Model Catalog Refresh
Estimated code review effort: 5 (Critical) | ~180 minutes Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 13
🧹 Nitpick comments (5)
src/renderer/src/components/chat/nodes/fileAttachment.ts (1)
41-46: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick winValidate parsed
requestedRepresentationwith the shared normalizer.
parseHTMLonly defaults to'auto'when the attribute is missing, not when it holds an invalid value.normalizeAttachmentRepresentationPreference(src/shared/utils/attachmentRepresentation.ts) already exists to validate/coerce this exact preference and is presumably relied on elsewhere in the attachment contract chain; using it here keeps deserialized HTML consistent with the rest of the pipeline.♻️ Proposed fix
+import { normalizeAttachmentRepresentationPreference } from '`@shared/utils/attachmentRepresentation`' ... requestedRepresentation: { default: 'auto', - parseHTML: (el) => el.getAttribute('data-requested-representation') || 'auto', + parseHTML: (el) => + normalizeAttachmentRepresentationPreference( + el.getAttribute('data-requested-representation') + ) ?? 'auto', renderHTML: (attrs) => ({ 'data-requested-representation': attrs.requestedRepresentation }) }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/renderer/src/components/chat/nodes/fileAttachment.ts` around lines 41 - 46, Update the requestedRepresentation parseHTML handler in the attachment node to pass the retrieved data-requested-representation value through normalizeAttachmentRepresentationPreference, preserving 'auto' as the fallback for missing or invalid values. Keep renderHTML unchanged.test/main/session/chatService.test.ts (1)
178-281: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick winSubmission-scoped abort is tested for
sendMessagebut not forsteerActiveTurn.L208-247 only covers
stopStream-triggered abort forsteerActiveTurn; L249-281 covers submission-scopedAbortControllerabort, but only forsendMessage. Consider adding an analogous submission-scoped-abort test forsteerActiveTurnto confirm it doesn't inadvertently cancel generation/session permissions either.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@test/main/session/chatService.test.ts` around lines 178 - 281, Add a submission-scoped AbortController test for steerActiveTurn, analogous to the existing sendMessage test. Keep the steer operation pending until the supplied signal aborts, then assert it rejects with AbortError without calling turn.cancelGeneration or sessionPermissionPort.clearSessionPermissions.test/main/routes/dispatcher.test.ts (2)
4255-4323: 🔒 Security & Privacy | 🔵 Trivial | ⚡ Quick winRenderer-ownership cancellation coverage exists only for
chat.sendMessage.This is a strong regression test for a real authorization boundary (blocking cross-renderer cancellation), but there's no analogous test exercising
chat.cancelSubmissionagainst an in-flightchat.steerActiveTurnorsessions.retryMessageattachment preflight, even though both now surfaceattachmentPreparation/blocking behavior in this same file. Consider extending this pattern to those two paths.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@test/main/routes/dispatcher.test.ts` around lines 4255 - 4323, Extend the renderer-ownership cancellation coverage from the existing chat.sendMessage test to both in-flight chat.steerActiveTurn and sessions.retryMessage attachment-preflight flows. For each path, await the preflight becoming blocked, verify chat.cancelSubmission from a different renderer returns { cancelled: false } without aborting it, then verify cancellation from the owning renderer succeeds and the operation rejects with AbortError; preserve the existing post-cancellation false result.
1-1: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick winSubmission-scoped cancellation is only fully tested for
chat.sendMessage, notsteerActiveTurn. Both files establish a solid pattern for verifying the new abort/attachment-preflight semantics, but the pattern isn't extended to the steer path at either layer.
test/main/routes/dispatcher.test.ts#L4255-4323: add an analogous renderer-ownershipchat.cancelSubmissiontest for an in-flightchat.steerActiveTurn(and ideallysessions.retryMessage, pending the separate signal-wiring verification) attachment preflight.test/main/session/chatService.test.ts#L178-281: add a submission-scopedAbortControllerabort test forsteerActiveTurn(mirroring the existingsendMessagetest at L249-281), distinct from the already-coveredstopStream-triggered abort at L208-247.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@test/main/routes/dispatcher.test.ts` at line 1, Extend the existing cancellation coverage to steerActiveTurn: in the dispatcher tests, add a renderer-ownership chat.cancelSubmission case for an in-flight steerActiveTurn attachment preflight, preserving the established sendMessage pattern; in chatService tests, add a submission-scoped AbortController abort test for steerActiveTurn, separate from the stopStream-triggered abort coverage. Also apply the analogous renderer test to sessions.retryMessage if its signal wiring is available.test/main/session/data/tables/deepchatPendingInputsTable.test.ts (1)
157-183: 🔒 Security & Privacy | 🔵 Trivial | ⚡ Quick winAdd a negative-case test for invalid/forged
resolvedRepresentation.This test only verifies the happy path where a valid
resolvedRepresentationis preserved. Given attachment data is treated as untrusted (per PR objectives) and this is the boundary where renderer-supplied payloads enter persisted pending-input state, add a companion case asserting that a forged/invalidresolvedRepresentation(e.g., unexpectedkind, extra fields, or a fakekind: 'image'used to bypass OCR) is rejected or stripped, mirroring how test 6 (lines 134-155) verifies blocking metadata is sanitized.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@test/main/session/data/tables/deepchatPendingInputsTable.test.ts` around lines 157 - 183, Add a companion negative-case test near the existing valid snapshot test for createQueueInput, supplying a forged or invalid resolvedRepresentation such as an unsupported kind or fake image representation with extra fields. Assert that the persisted pending payload rejects or strips the invalid representation, matching the sanitization expectations established by test 6.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@resources/model-db/providers.json`:
- Line 260229: Update the context value for the Meituan: LongCat 2.0 provider
entry from 1048756 to 1048576 in providers.json, leaving all other provider
configuration unchanged.
- Around line 236569-236573: The gemini-3.6-flash pricing entry has an incorrect
cache_read value. In its cost object, update cache_read from 1.5 to 0.15 while
preserving the input and output values.
- Around line 259585-259661: Update the `type` field in both OpenRouter entries,
`google/gemini-3.5-flash-lite` and `google/gemini-3.6-flash`, from
`imageGeneration` to `chat`; leave their existing modalities, reasoning, limits,
and other capabilities unchanged.
In `@src/main/agent/deepchat/runtime/contextBuilder.ts`:
- Around line 407-428: Update buildResolvedImageRepresentationContext to inspect
the ocr_text representation’s truncated flag and append a clear truncation note
to the generated OCR context when it is true. Preserve the existing unavailable,
empty-text, escaping, metadata, and non-truncated output behavior.
- Around line 430-432: Update escapeUntrustedOcrBlockDelimiters to escape every
angle bracket in the input, rather than pattern-matching only untrusted_ocr_data
tags. Ensure both “<” and “>” are encoded so any OCR text resembling an
HTML-like delimiter cannot bypass the trust boundary.
In `@src/main/ocr/ocrRuntimeAssetResolver.ts`:
- Around line 256-262: Update the escape guard in the runtime asset path
validation to also reject the exact parent-relative value (`relative === '..'`),
while preserving the existing checks for empty, nested-parent, and absolute
paths. Keep the change scoped to the validation logic surrounding `resolvedRoot`
and `resolvedPath`.
In `@src/main/session/data/pendingInputStore.ts`:
- Around line 145-154: Update updateQueueInput to validate the current row.state
before writing payload_json, matching the state-guard behavior of the sibling
mutators. Reject claimed or otherwise non-editable states before mutation, while
preserving the existing blocked-to-pending reset and normal update behavior for
allowed states.
In `@src/main/session/turn.ts`:
- Around line 281-287: In the ACP branch of the turn handling flow, move
commitRetryMessage so it runs only after runtime.send completes successfully.
Preserve the existing sessionId and prepared.sourceOrderSeq arguments, and
ensure send errors propagate without committing or deleting the prior
transcript.
In `@src/renderer/settings/components/OcrSettings.vue`:
- Line 256: Update the status polling error handling around statusErrorNotified
and the logic near status.value so failures after a prior successful poll are
surfaced instead of remaining silent; preserve deduplication by notifying only
on the first failure in each failure period, and reset that failure state when a
subsequent poll succeeds. Ensure the status card no longer presents stale
available data without an indication of polling failure.
In `@src/renderer/src/components/chat/ChatInputBox.vue`:
- Around line 558-563: Update handleKeydown so the non-editable guard does not
prevent Tab navigation or standard copy/select-all shortcuts (Ctrl/Cmd+Tab,
Ctrl/Cmd+C, and Ctrl/Cmd+A as applicable); allow those key-specific paths to
execute before returning for other editing commands. Preserve the existing
prevention behavior for actions that modify the draft while props.editable is
false.
In `@src/renderer/src/components/message/MessageItemUser.vue`:
- Around line 256-263: Update messageFileByKey and its fallback lookup in
MessageItemUser so exact file paths remain uniquely mapped, while basename
matching is only used when exactly one attachment has that name. Do not
overwrite basename candidates when duplicates exist; treat ambiguous names as
unmatched so inline blocks cannot receive incorrect file metadata or OCR
content.
In `@src/renderer/src/i18n/he-IL/chat.json`:
- Line 431: Update the Hebrew translations for image_limit_exceeded and the
corresponding message at line 440 to replace התור with a term clearly meaning
the current turn or round, while preserving the existing message meaning and
formatting.
In `@test/main/ocr/ocrArtifactStore.test.ts`:
- Around line 15-26: Ensure encrypted persistence tests cannot be silently
skipped in required CI: update the OCR artifact store test setup around
sqliteAvailable and persistentIt to honor DEEPCHAT_REQUIRE_NATIVE_SQLITE,
failing when the flag is set but better-sqlite3-multiple-ciphers is unavailable;
also configure that environment variable for the CI command running these tests
if needed.
---
Nitpick comments:
In `@src/renderer/src/components/chat/nodes/fileAttachment.ts`:
- Around line 41-46: Update the requestedRepresentation parseHTML handler in the
attachment node to pass the retrieved data-requested-representation value
through normalizeAttachmentRepresentationPreference, preserving 'auto' as the
fallback for missing or invalid values. Keep renderHTML unchanged.
In `@test/main/routes/dispatcher.test.ts`:
- Around line 4255-4323: Extend the renderer-ownership cancellation coverage
from the existing chat.sendMessage test to both in-flight chat.steerActiveTurn
and sessions.retryMessage attachment-preflight flows. For each path, await the
preflight becoming blocked, verify chat.cancelSubmission from a different
renderer returns { cancelled: false } without aborting it, then verify
cancellation from the owning renderer succeeds and the operation rejects with
AbortError; preserve the existing post-cancellation false result.
- Line 1: Extend the existing cancellation coverage to steerActiveTurn: in the
dispatcher tests, add a renderer-ownership chat.cancelSubmission case for an
in-flight steerActiveTurn attachment preflight, preserving the established
sendMessage pattern; in chatService tests, add a submission-scoped
AbortController abort test for steerActiveTurn, separate from the
stopStream-triggered abort coverage. Also apply the analogous renderer test to
sessions.retryMessage if its signal wiring is available.
In `@test/main/session/chatService.test.ts`:
- Around line 178-281: Add a submission-scoped AbortController test for
steerActiveTurn, analogous to the existing sendMessage test. Keep the steer
operation pending until the supplied signal aborts, then assert it rejects with
AbortError without calling turn.cancelGeneration or
sessionPermissionPort.clearSessionPermissions.
In `@test/main/session/data/tables/deepchatPendingInputsTable.test.ts`:
- Around line 157-183: Add a companion negative-case test near the existing
valid snapshot test for createQueueInput, supplying a forged or invalid
resolvedRepresentation such as an unsupported kind or fake image representation
with extra fields. Assert that the persisted pending payload rejects or strips
the invalid representation, matching the sanitization expectations established
by test 6.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: ee0267a3-1fb3-4f16-b76a-a4ee94389d34
⛔ Files ignored due to path filters (2)
src/renderer/src/lib/icons/icon-collections.generated.tsis excluded by!**/*.generated.*src/renderer/src/lib/icons/icon-whitelist.generated.tsis excluded by!**/*.generated.*
📒 Files selected for processing (234)
.github/actions/light-ocr-package-size/action.yml.github/workflows/build.yml.github/workflows/release.ymldocs/features/light-ocr-integration/plan.mddocs/features/light-ocr-integration/spec.mddocs/features/light-ocr-integration/tasks.mddocs/issues/light-ocr-follow-up-hardening/spec.mdelectron-builder.ymlelectron.vite.config.tspackage.jsonresources/acp-registry/registry.jsonresources/light-ocr-size-budgets.jsonresources/model-db/providers.jsonresources/runtime-versions.jsonscripts/afterPack.jsscripts/compare-light-ocr-package-size.mjsscripts/install-runtime.mjsscripts/smoke-light-ocr.jssrc/main/agent/deepchat/runtime/contextBuilder.tssrc/main/agent/deepchat/runtime/deepChatRuntimeCoordinator.tssrc/main/agent/deepchat/runtime/turnCoordinator.tssrc/main/agent/manager/deepChatAgentBackend.tssrc/main/agent/manager/directAcpAgentBackend.tssrc/main/agent/manager/sessionHandles.tssrc/main/agent/shared/agentSessionHandle.tssrc/main/agent/shared/agentSessionNormalization.tssrc/main/app/composition.tssrc/main/app/settingsRoutes.tssrc/main/data/databaseConnection.tssrc/main/data/schemaCatalog.tssrc/main/exporter/agentSessionExporter.tssrc/main/exporter/formats/conversationExporter.tssrc/main/exporter/formats/nowledgeMemExporter.tssrc/main/exporter/formats/userMessageText.tssrc/main/lightOcrHelperEntry.tssrc/main/ocr/attachmentCapabilityRouter.tssrc/main/ocr/imagePreprocessor.tssrc/main/ocr/imageTextExtractionService.tssrc/main/ocr/lightOcrHelper.tssrc/main/ocr/lightOcrProcessHost.tssrc/main/ocr/lightOcrProtocol.tssrc/main/ocr/ocrArtifactStore.tssrc/main/ocr/ocrCacheKeyProvider.tssrc/main/ocr/ocrExtractionScheduler.tssrc/main/ocr/ocrRuntimeAssetResolver.tssrc/main/ocr/ocrRuntimeService.tssrc/main/ocr/ocrSettings.tssrc/main/ocr/routes.tssrc/main/remote/conversation/runner.tssrc/main/session/chatService.tssrc/main/session/contracts.tssrc/main/session/data/contracts.tssrc/main/session/data/pendingInputStore.tssrc/main/session/data/pendingInputs.tssrc/main/session/data/tables/deepchatPendingInputs.tssrc/main/session/data/transcript.tssrc/main/session/data/userMessageContent.tssrc/main/session/lifecycle.tssrc/main/session/routes.tssrc/main/session/sessionService.tssrc/main/session/submissionCancellationRegistry.tssrc/main/session/transcriptMutations.tssrc/main/session/turn.tssrc/main/tape/application/recallProjection.tssrc/main/tape/application/recallService.tssrc/main/tape/infrastructure/sqlite/tapeSearchProjectionStore.tssrc/renderer/api/ChatClient.tssrc/renderer/api/OcrClient.tssrc/renderer/api/SessionClient.tssrc/renderer/settings/components/OcrSettings.vuesrc/renderer/settings/settingsRouteComponents.tssrc/renderer/src/components/chat/AttachmentPreparationDialog.vuesrc/renderer/src/components/chat/ChatAttachmentItem.vuesrc/renderer/src/components/chat/ChatInputBox.vuesrc/renderer/src/components/chat/ChatInputToolbar.vuesrc/renderer/src/components/chat/ChatStatusBar.vuesrc/renderer/src/components/chat/PendingInputLane.vuesrc/renderer/src/components/chat/composables/useChatInputFiles.tssrc/renderer/src/components/chat/nodes/FileAttachmentView.vuesrc/renderer/src/components/chat/nodes/fileAttachment.tssrc/renderer/src/components/chat/nodes/symbols.tssrc/renderer/src/components/message/MessageContent.vuesrc/renderer/src/components/message/MessageItemUser.vuesrc/renderer/src/features/chat-page/ChatPage.vuesrc/renderer/src/features/chat-page/composables/useComposerSubmit.tssrc/renderer/src/features/chat-page/composables/useMessageActions.tssrc/renderer/src/features/chat-page/composables/usePendingInputActions.tssrc/renderer/src/features/chat-page/model/composerDraftState.tssrc/renderer/src/features/chat-page/model/displayMessage.tssrc/renderer/src/i18n/da-DK/chat.jsonsrc/renderer/src/i18n/da-DK/routes.jsonsrc/renderer/src/i18n/da-DK/settings.jsonsrc/renderer/src/i18n/de-DE/chat.jsonsrc/renderer/src/i18n/de-DE/routes.jsonsrc/renderer/src/i18n/de-DE/settings.jsonsrc/renderer/src/i18n/en-US/chat.jsonsrc/renderer/src/i18n/en-US/routes.jsonsrc/renderer/src/i18n/en-US/settings.jsonsrc/renderer/src/i18n/es-ES/chat.jsonsrc/renderer/src/i18n/es-ES/routes.jsonsrc/renderer/src/i18n/es-ES/settings.jsonsrc/renderer/src/i18n/fa-IR/chat.jsonsrc/renderer/src/i18n/fa-IR/routes.jsonsrc/renderer/src/i18n/fa-IR/settings.jsonsrc/renderer/src/i18n/fr-FR/chat.jsonsrc/renderer/src/i18n/fr-FR/routes.jsonsrc/renderer/src/i18n/fr-FR/settings.jsonsrc/renderer/src/i18n/he-IL/chat.jsonsrc/renderer/src/i18n/he-IL/routes.jsonsrc/renderer/src/i18n/he-IL/settings.jsonsrc/renderer/src/i18n/id-ID/chat.jsonsrc/renderer/src/i18n/id-ID/routes.jsonsrc/renderer/src/i18n/id-ID/settings.jsonsrc/renderer/src/i18n/it-IT/chat.jsonsrc/renderer/src/i18n/it-IT/routes.jsonsrc/renderer/src/i18n/it-IT/settings.jsonsrc/renderer/src/i18n/ja-JP/chat.jsonsrc/renderer/src/i18n/ja-JP/routes.jsonsrc/renderer/src/i18n/ja-JP/settings.jsonsrc/renderer/src/i18n/ko-KR/chat.jsonsrc/renderer/src/i18n/ko-KR/routes.jsonsrc/renderer/src/i18n/ko-KR/settings.jsonsrc/renderer/src/i18n/ms-MY/chat.jsonsrc/renderer/src/i18n/ms-MY/routes.jsonsrc/renderer/src/i18n/ms-MY/settings.jsonsrc/renderer/src/i18n/pl-PL/chat.jsonsrc/renderer/src/i18n/pl-PL/routes.jsonsrc/renderer/src/i18n/pl-PL/settings.jsonsrc/renderer/src/i18n/pt-BR/chat.jsonsrc/renderer/src/i18n/pt-BR/routes.jsonsrc/renderer/src/i18n/pt-BR/settings.jsonsrc/renderer/src/i18n/ru-RU/chat.jsonsrc/renderer/src/i18n/ru-RU/routes.jsonsrc/renderer/src/i18n/ru-RU/settings.jsonsrc/renderer/src/i18n/tr-TR/chat.jsonsrc/renderer/src/i18n/tr-TR/routes.jsonsrc/renderer/src/i18n/tr-TR/settings.jsonsrc/renderer/src/i18n/vi-VN/chat.jsonsrc/renderer/src/i18n/vi-VN/routes.jsonsrc/renderer/src/i18n/vi-VN/settings.jsonsrc/renderer/src/i18n/zh-CN/chat.jsonsrc/renderer/src/i18n/zh-CN/routes.jsonsrc/renderer/src/i18n/zh-CN/settings.jsonsrc/renderer/src/i18n/zh-HK/chat.jsonsrc/renderer/src/i18n/zh-HK/routes.jsonsrc/renderer/src/i18n/zh-HK/settings.jsonsrc/renderer/src/i18n/zh-TW/chat.jsonsrc/renderer/src/i18n/zh-TW/routes.jsonsrc/renderer/src/i18n/zh-TW/settings.jsonsrc/renderer/src/lib/errors.tssrc/renderer/src/pages/NewThreadPage.vuesrc/renderer/src/stores/ui/attachmentPreparation.tssrc/renderer/src/stores/ui/pendingInput.tssrc/renderer/src/stores/ui/session.tssrc/shadcn/components/ui/dropdown-menu/DropdownMenuContent.vuesrc/shared/chat.d.tssrc/shared/contracts/common.tssrc/shared/contracts/domainSchemas.tssrc/shared/contracts/events/settings.events.tssrc/shared/contracts/routes.tssrc/shared/contracts/routes/chat.routes.tssrc/shared/contracts/routes/ocr.routes.tssrc/shared/contracts/routes/sessions.routes.tssrc/shared/contracts/routes/settings.routes.tssrc/shared/contracts/routes/system.routes.tssrc/shared/settingsNavigation.tssrc/shared/types/agent-interface.d.tssrc/shared/types/attachment.tssrc/shared/types/core/chat.tssrc/shared/utils/attachmentRepresentation.tstest/fixtures/light-ocr/fake-helper.mjstest/main/agent/deepchat/runtime/contextBuilder.test.tstest/main/agent/deepchat/runtime/deepChatRuntimeCoordinator.test.tstest/main/agent/manager/deepChatAgentBackend.test.tstest/main/agent/manager/directAcpAgentBackend.test.tstest/main/data/databaseConnection.test.tstest/main/exporter/agentSessionExporter.test.tstest/main/memory/memoryNativeMigration.test.tstest/main/ocr/attachmentCapabilityRouter.test.tstest/main/ocr/imagePreprocessor.test.tstest/main/ocr/imageTextExtractionService.test.tstest/main/ocr/lightOcrHelper.test.tstest/main/ocr/lightOcrProcessHost.test.tstest/main/ocr/ocrArtifactStore.test.tstest/main/ocr/ocrCacheKeyProvider.test.tstest/main/ocr/ocrExtractionScheduler.test.tstest/main/ocr/ocrRuntimeAssetResolver.test.tstest/main/ocr/ocrRuntimeService.test.tstest/main/ocr/ocrSettings.test.tstest/main/ocr/routes.test.tstest/main/remote/remoteConversationRunner.test.tstest/main/routes/contracts.test.tstest/main/routes/dispatcher.test.tstest/main/scripts/afterPack.test.tstest/main/scripts/installRuntime.test.tstest/main/scripts/lightOcrPackageSize.test.tstest/main/scripts/smokeLightOcr.test.tstest/main/session/assignmentPolicy.test.tstest/main/session/chatService.test.tstest/main/session/data/pendingInputStore.test.tstest/main/session/data/pendingInputs.test.tstest/main/session/data/tables/deepchatPendingInputsTable.test.tstest/main/session/data/tapeRecall.test.tstest/main/session/data/transcript.test.tstest/main/session/lifecycle.test.tstest/main/session/runtimeIntegration.test.tstest/main/session/session.integration.test.tstest/main/session/sessionFixture.tstest/main/session/submissionCancellationRegistry.test.tstest/main/session/transcriptMutations.test.tstest/main/session/turn.test.tstest/main/shared/attachmentRepresentation.test.tstest/main/shared/settingsNavigation.test.tstest/renderer/api/clients.test.tstest/renderer/components/AttachmentPreparationDialog.test.tstest/renderer/components/ChatAttachmentItem.test.tstest/renderer/components/ChatInputBox.test.tstest/renderer/components/ChatInputToolbar.test.tstest/renderer/components/ChatPage.test.tstest/renderer/components/DropdownMenuContent.test.tstest/renderer/components/NewThreadPage.onboarding.test.tstest/renderer/components/NewThreadPage.test.tstest/renderer/components/OcrSettings.test.tstest/renderer/components/PendingInputLane.test.tstest/renderer/components/useChatInputFiles.test.tstest/renderer/features/chat-page/composables/useComposerSubmit.test.tstest/renderer/features/chat-page/composables/useMessageActions.test.tstest/renderer/features/chat-page/composables/usePendingInputActions.test.tstest/renderer/features/chat-page/model/composerDraftState.test.tstest/renderer/lib/errors.test.tstest/renderer/pages/NewThreadPage.test.tstest/renderer/stores/attachmentPreparationStore.test.tstest/renderer/stores/sessionStore.test.tstsconfig.node.json
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
resources/model-db/providers.json (1)
236574-236580: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick winClamp Gemini 3.6 Flash output to 65536
resources/model-db/providers.json:236576-236578advertises"output": 1048576, but this model’s published max output is 65,536 tokens. That value should be lowered to match the actual limit.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@resources/model-db/providers.json` around lines 236574 - 236580, Update the Gemini 3.6 Flash model entry’s limit.output value from 1048576 to 65536, while leaving its context and tool_call settings unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Outside diff comments:
In `@resources/model-db/providers.json`:
- Around line 236574-236580: Update the Gemini 3.6 Flash model entry’s
limit.output value from 1048576 to 65536, while leaving its context and
tool_call settings unchanged.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 19abf7c0-bc5f-4a74-8284-a134be85d1f8
📒 Files selected for processing (15)
resources/acp-registry/registry.jsonresources/model-db/providers.jsonscripts/afterPack.jsscripts/smoke-light-ocr.jssrc/main/ocr/lightOcrNativePayload.tssrc/main/ocr/lightOcrProcessHost.tssrc/main/ocr/ocrRuntimeAssetResolver.tssrc/main/ocr/ocrRuntimeService.tstest/main/ocr/attachmentCapabilityRouter.test.tstest/main/ocr/lightOcrNativePayload.test.tstest/main/ocr/lightOcrProcessHost.test.tstest/main/ocr/ocrRuntimeAssetResolver.test.tstest/main/ocr/routes.test.tstest/main/scripts/afterPack.test.tstest/main/scripts/smokeLightOcr.test.ts
🚧 Files skipped from review as they are similar to previous changes (8)
- test/main/ocr/routes.test.ts
- test/main/ocr/ocrRuntimeAssetResolver.test.ts
- src/main/ocr/ocrRuntimeService.ts
- src/main/ocr/ocrRuntimeAssetResolver.ts
- src/main/ocr/lightOcrProcessHost.ts
- test/main/scripts/afterPack.test.ts
- resources/acp-registry/registry.json
- test/main/ocr/attachmentCapabilityRouter.test.ts
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@test/main/scripts/lightOcrPackageSize.test.ts`:
- Around line 94-107: Extend the assertions in the test covering applicationStep
and feishuStep so both unsigned steps are verified not to contain CSC_LINK or
CSC_KEY_PASSWORD. Keep the existing signed cuaStep assertions unchanged.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 83b44083-fcc9-4fdc-818c-9c660367df64
📒 Files selected for processing (2)
.github/actions/light-ocr-package-size/action.ymltest/main/scripts/lightOcrPackageSize.test.ts
🚧 Files skipped from review as they are similar to previous changes (1)
- .github/actions/light-ocr-package-size/action.yml
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
resources/model-db/providers.json (1)
260548-260614: 🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick winFix the Gemma model types in
resources/model-db/providers.jsongoogle/gemma-4-26b-a4b-it,google/gemma-4-26b-a4b-it:free,google/gemma-4-31b-it, andgoogle/gemma-4-31b-it:freeare text-only, sotype: "imageGeneration"is incorrect here.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@resources/model-db/providers.json` around lines 260548 - 260614, Update the provider entries for google/gemma-4-26b-a4b-it, google/gemma-4-26b-a4b-it:free, google/gemma-4-31b-it, and google/gemma-4-31b-it:free to use the appropriate text-model type instead of type: "imageGeneration"; preserve their existing text output and capability metadata.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Outside diff comments:
In `@resources/model-db/providers.json`:
- Around line 260548-260614: Update the provider entries for
google/gemma-4-26b-a4b-it, google/gemma-4-26b-a4b-it:free,
google/gemma-4-31b-it, and google/gemma-4-31b-it:free to use the appropriate
text-model type instead of type: "imageGeneration"; preserve their existing text
output and capability metadata.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: f2f92920-45c6-4610-81cd-5e0feb466c71
📒 Files selected for processing (10)
docs/features/light-ocr-integration/plan.mddocs/features/light-ocr-integration/spec.mddocs/features/light-ocr-integration/tasks.mdelectron-builder.ymlresources/acp-registry/registry.jsonresources/model-db/providers.jsonscripts/apple-notarization.jsscripts/notarize-dmg.jsscripts/notarize.jstest/main/scripts/notarizeDmg.test.ts
🚧 Files skipped from review as they are similar to previous changes (3)
- docs/features/light-ocr-integration/spec.md
- docs/features/light-ocr-integration/plan.md
- resources/acp-registry/registry.json
Summary
Integrate
@arcships/light-ocrinto DeepChat to provide fully offline OCR for image attachments, especially when the selected model does not support vision.What changed
Runtime and packaging
@arcships/light-ocr@0.3.4.ppocrv6-small-native-20260719.1.24.14.1.Safety and reliability
Scope
Included:
Not included:
Validation
App.startup.test.tsmock failures outside this diff.Summary by CodeRabbit