Skip to content

Ship the LibreOffice engine beside the asar so Office previews work - #705

Merged
Fei2411 merged 4 commits into
Fei2411:devfrom
AdamPlatin123:fix/679-office-preview-asar
Nov 2, 2026
Merged

Fei2411 merged 4 commits into
Fei2411:devfrom
AdamPlatin123:fix/679-office-preview-asar

Conversation

@AdamPlatin123

@AdamPlatin123 AdamPlatin123 commented Oct 30, 2026 •

Copy link
Copy Markdown
Collaborator

Issue

Fixes #679

The bug: in the 0.2.3 desktop app, every preview of a Word, Excel or PowerPoint file fails with 「读取失败:Office 转换失败,未生成可用的 PDF。请检查该文件后重试。」 on Windows (and, by the same code path, on macOS).

What changed / 改了什么

  • Cause. The Host loads DSH from resources/app.asar. @deepseek-ai/libreoffice-kit resolves its engine package (require.resolve('@deepseek-ai/libreoffice-kit-<platform>/package.json')) and starts the program in it, so the engine's executable and program folder are paths inside app.asar. Electron cannot start a program by a path inside an archive, even an unpacked one: spawn … app.asar\node_modules\@deepseek-ai\libreoffice-kit-win32-x64\bin\libreoffice-kit.exe ENOENT. DSH maps this to the generic failed reason the preview shows.
  • Fix. The asar stays. electron-builder.yml leaves only the engine packages (@deepseek-ai/libreoffice-kit-*) out of it and ships them as plain files in resources/node_modules (extraResources). Node's lookup from the kit inside app.asar/node_modules goes up to resources/node_modules and finds the engine at a real path. No change to DSH or the kit (AGENTS.md rule 1). On Linux, where the app is already plain files since dev's plain-Node Host, the engine moves from resources/app/node_modules to resources/node_modules and is found the same way.
  • Packaged check. scripts/check-packed.mjs gains checkOffice, next to checkSharp: it writes a one-paragraph .docx into the throwaway folder and converts it to PDF with the packaged kit and engine, run the way the Host runs (plain Node on Linux, Electron's Node mode elsewhere), with the font cache in the throwaway folder, and checks the PDF header. CI runs it on Windows, macOS and Linux (WASM engine), after the build, after the install and after the update.
  • Test. test/package.test.mjs checks, with electron-builder's own matchers, that the engine packages stay out of the app's files and go to resources/node_modules, and that the kit and other packages stay in.
  • app/README.md says where the engine ships and why, and what check-packed now converts.

Why not asar: false. The first version of this pull request turned the asar off. On CI that made the Windows installer write 23,573 files: a fresh install took about 4 min 20 s instead of about 1 min, and the update step (uninstall, then install) ran past its 4-minute limit, which is the red Windows job on the earlier run. Locally the app also took about 7 s longer to show the Host page. Shipping only the engine as plain files keeps all of that as it is on dev.

Changelog

Office file previews (Word, Excel, PowerPoint) work again in the desktop app on Windows and macOS.

How I checked it / 怎么验证的

  • By hand on Windows, Electron 44.7.0 in Node mode (as the Host): a real app.asar with the kit (unpacked as in asarUnpack) and the engine in resources/node_modules converts a .docx to PDF with the native engine. The same layout with the engine inside the asar fails with the ENOENT above.
  • App tests (app/): test/package.test.mjs passes, and its new test fails against dev's electron-builder.yml. The other failures on this machine are local only: Node 22.14 lacks registerHooks and zstdCompressSync (CI uses Node 24), and one symlink test expects an EPERM that this machine does not raise.
  • oxlint on the changed files.
  • npm test, --check in ds-bot/: this pull request changes nothing there; CI runs them.
  • npm run pack and check-packed locally: not run here (this machine's Node is older than the app needs). CI packs, checks, installs, updates and uninstalls on Windows, macOS and Linux.
  • Smoke test, for changes to index.js or src/host/ / 改了 index.js 或 src/host/ 时跑冒烟测试 — not applicable.
  • Screenshot attached, for interface changes / 界面改动已附截图 — not applicable.
  • Seen on the way, not fixed here: the native engine also failed when its program folder path was 232 characters long, under the kit's 260-character workaround (Cannot open directory …/program/program/services). An install under %LOCALAPPDATA%\Programs\DS Bot is about 110 characters.

Checklist / 检查

  • One issue, one subject. / 只做一件事。
  • src/client/ changed → npm run build ran and client.js is committed. / 改了 src/client/ 就已重新 build 并提交 client.js。 (not changed)
  • No keys, tokens or personal data, also in screenshots. / 没有密钥、token 或个人信息,截图里也没有。
  • No AI tool as author or Co-authored-by. / 没有把 AI 工具写成作者或 Co-authored-by。

🤖 Generated with Claude Code

Every preview of a Word, Excel or PowerPoint file failed in the packaged
app. The Host loads DSH from app.asar, and the LibreOffice kit finds its
engine next to its own files, so the engine's executable and program
folder were paths inside the archive. Electron cannot start a program by
such a path, even when electron-builder unpacked it: spawn fails with
ENOENT, and through the kit's API the engine cannot use its program
folder.

Without an asar archive every package path is a real path, and the
asarUnpack list for pnpm and sharp is no longer needed. This costs Host
start time; an asar-aware kit would let the app go back to asar.

check-packed now converts a small .docx with the packaged kit and
engine, the way the Host does, so CI catches this on every platform.

Fixes Fei2411#679
Fei2411#624 unpacked the LibreOffice Kit and ds-bot's office.js from the asar for
the Office payload's plain Node. Without an asar archive those files are
plain already, so the asarUnpack list goes and check-packed looks for them
in the app's folder; the office.js and Kit CLI path mappings stay, as a
no-op here and for DSH Desktop's asar.
The conflicts in app/README.md and app/scripts/check-packed.mjs, and every
other file of this branch, are resolved to dev: the next commit replaces
the branch's asar: false with an engine beside the asar.
Every Office file preview in the desktop app failed (Fei2411#679): the kit resolves
its engine package and starts the program in it, and from the asar that path
lies inside the archive, where Electron cannot start a program even when it
is unpacked.

This branch first turned the asar off. That made the Windows install write
23,573 files: a fresh install took about 4 minutes on CI instead of 1, the
update step ran past its 4-minute limit, and the app started slower.

Instead, keep the asar and leave only the engine packages out of it. They
ship as plain files in resources/node_modules (extraResources), and Node's
lookup from the kit inside app.asar goes up to resources/node_modules and
finds them. Checked by hand on Windows with Electron 44.7.0 in Node mode: a
.docx converts to PDF with this layout, and the engine inside the asar fails
with the ENOENT of Fei2411#679.

check-packed converts a Word document with the packaged kit and engine, run
the way the Host runs (plain Node on Linux, Electron's Node mode elsewhere).
@AdamPlatin123 AdamPlatin123 changed the title Ship the desktop app as plain files so Office previews work Ship the LibreOffice engine beside the asar so Office previews work Nov 1, 2026
@Fei2411
Fei2411 merged commit f5508a3 into Fei2411:dev Nov 2, 2026
13 checks passed
@Fei2411 Fei2411 mentioned this pull request Nov 3, 2026
6 tasks done
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants