- office-render: report inspection results in text and never link or embed
removed previews. Desktop and Web replies otherwise embed deleted preview
images, because their file-reference guidance encourages inline images.
- office-export-pdf: validate with the command result, nonempty output, and
%PDF- signature; do not search for PDF readers unless the user requests
deeper checks. The bundled runtime has none, so the old conditional made
the model probe system Python and command-line tools.
- Assert that the PDF export e2e does not probe PDF reader tools.
- Replace stale "structural checks" wording in the Desktop Office plugin
JSDoc and the skill package description.
The fixed 19387 listener fails when Windows (Hyper-V/WinNAT) reserves a dynamic
port range covering it, even though no process uses the port. Electron already
reads the bound port from the Host's ready message.
loadProfileDirectory printed each skipped bundle on every call, and startup,
runtime resolution, the config editor, the plugin manager, and HMR all load
the profile, so one incompatible bundle printed the same warning six times at
startup and again on each Web page load. Loading now returns the skips in
Profile.skippedBundles, and the CLI and Desktop launchers print them once per
start with reportSkippedBundles.
Closing the main window hides it on macOS and Windows; the page and the
Host keep running and the next show resumes the same document. Windows
gets a permanent tray icon (open / quit) and a one-time notification the
first time the window is hidden after installation.
Every ordinary quit entry asks the Host over a new quit-inspection IPC
request for active tasks (same rule as the update restart check) and
armed scheduled reminders (schedule family of workspace/session-activity
for loaded sessions). Nothing to interrupt quits silently; otherwise a
native message box explains what stops, with Quit as the default and
Cancel on Esc. Inspection failure or a missed two-second deadline counts
as running tasks. The installer restart, fatal recovery, the development
restart command, and OS session end skip the confirmation.
Also: defer the downloaded-update confirmation while the window is hidden,
render the tray ICO from the vector icon, and point the installer's
running-application message at the tray.
Closes#4013
A Host startup failure reached the crash report as a fresh Error built from
a message string three hops away from the original: the Host sent only
error.message over the fatal IPC event, DesktopHostProcess wrapped it in a
new Error, desktopErrorState flattened it to text, and main.ts wrapped that
text again. Stack, cause, code, and path were gone, and the Host's stderr
tail arriving with the later exit was blocked by the first-failure latch.
The Host now sends its complete inspected error alongside the message
(bounded to 64 KiB; carried over IPC rather than stderr because the two
race and the shell reports the first failure it sees). DesktopHostProcess
keeps it on DesktopHostFatalError.diagnostic, the backend error state
carries the original failure object, main.ts reports that object, and the
crash report prints the Host diagnostic verbatim in its own section.
Move `load_workspace_dependencies` and the primary-runtime payload logic out
of `apps/desktop-host` into `@deepseek-ai/dsh-tool-workspace-dependencies`
so profiles other than Desktop can mount the same tool. Desktop keeps its
behavior through the package.
Two additions for carriers that are not Electron applications:
- `root` is optional: without it the payload is validated and used in place
(no copy under the Harness home), which suits read-only container layers.
- `runtime.json` accepts `linux`, and the `node` / `pnpm` components are
optional; the returned paths and the tool output omit what the payload
does not ship.
The `sdk` profile mounts the tool and `@deepseek-ai/dsh-skill-office` when
`DSH_PRIMARY_RUNTIME` names a payload directory (its sibling `office-skills/`
carries the skill resources); both rows stay disabled otherwise. Both
packages join the Python runtime closure.