fix: make OCR portable and reliable across AMD64 and ARM64 (#519)

* fix: make OCR portable and reliable

* fix: harden OCR installation portability

* fix: pin OCR partials across downloads

* fix: make OCR execution reliably asynchronous

* fix: harden OCR portability and docs routes

* fix: preserve decoder and docs safeguards
This commit is contained in:
SnapOtter
2026-07-15 03:34:24 +08:00
committed by GitHub
parent 58121f205f
commit 991c981529
409 changed files with 67151 additions and 8076 deletions
+52
View File
@@ -304,6 +304,27 @@ describe("useFeaturesStore", () => {
await promise;
});
it("ignores SSE heartbeats without mutating install progress", async () => {
apiPostMock.mockResolvedValueOnce({ jobId: "job-heartbeat" });
const promise = useFeaturesStore.getState().installBundle("test-bundle");
await vi.waitFor(() => {
expect(FakeEventSource.instances).toHaveLength(1);
});
const es = FakeEventSource.instances[0];
es.onmessage?.({ data: JSON.stringify({ type: "heartbeat" }) });
expect(useFeaturesStore.getState().installing["test-bundle"]).toEqual({
percent: 5,
stage: "Starting...",
});
es.onmessage?.({ data: JSON.stringify({ phase: "complete" }) });
await promise;
});
it("on API failure: sets error and clears installing", async () => {
apiPostMock.mockRejectedValueOnce(new Error("Server error"));
@@ -485,6 +506,37 @@ describe("useFeaturesStore", () => {
expect(useFeaturesStore.getState().queued).toEqual([]);
}, 15000);
it("skips bundles that are incompatible with the current host", async () => {
const bundles = [
makeBundleState({
id: "unsupported-ocr",
status: "error",
compatibility: "incompatible",
compatibilityReason: "unsupported-host",
}),
makeBundleState({
id: "low-memory-ocr",
status: "not_installed",
compatibility: "incompatible",
compatibilityReason: "insufficient-memory",
}),
makeBundleState({ id: "supported-bundle", status: "not_installed" }),
];
useFeaturesStore.setState({ bundles, loaded: true });
apiPostMock.mockResolvedValue({ jobId: "supported-job" });
await useFeaturesStore.getState().installAll();
await vi.waitFor(() => {
expect(apiPostMock).toHaveBeenCalledWith("/v1/admin/features/supported-bundle/install", {});
});
expect(apiPostMock).not.toHaveBeenCalledWith(
"/v1/admin/features/unsupported-ocr/install",
{},
);
expect(apiPostMock).not.toHaveBeenCalledWith("/v1/admin/features/low-memory-ocr/install", {});
});
it("reflects server-queued bundles in the queued pill during Install All", async () => {
const bundles = [
makeBundleState({ id: "bundle-a", status: "not_installed" }),