`package-target.ts` imported `macos-notarization-proxy.ts`, whose top-level
import of `@deepseek-ai/node-addon-system/flock` resolves through the package
`exports` to the unbuilt `lib/flock.js` on a clean checkout. The step that
emits that file runs inside the same packaging script, so `check:package`,
`package:*`, and the `restore:mac-proxy` recovery command all failed with
`ERR_MODULE_NOT_FOUND` before reaching it; running `pnpm run typecheck` first
left the host addon binary missing instead, which failed at lock time.
The proxy lock now loads the entry at first use through `flock-entry.ts`. When
the import is unresolvable or the host platform package lacks a binary listed
in its `prebuilds.json`, the loader runs `pnpm run build:native-system` and
`pnpm --dir native/system run build:ts` before importing again; other errors
and build failures propagate, and a failed load is retried by the next call.
`check:package` no longer touches the entry at all.
Tests cover the loader steps and load the proxy module from a directory where
the addon package cannot be resolved. The Desktop README records the
behavior in both languages.
(cherry picked from commit 2d74cf50310d4efbbccbbe79a105fcc3a468b19d)
The packaged-imports plugin moves from generateBundle to moduleParsed so
external dynamic import() and require() targets, which chunk metadata
omits, fail the bundle too. Each bundle now carries an import policy:
the main process allows Node builtins, sandboxed preloads only the
modules Electron's require polyfill resolves, and the failure names the
importing module and the allowed set. The wine Windows gate bundles
apps/desktop after the Host tsdown pass like build:lib:host, the
ts-build-config note lists that step, and the tsdown docs name the
workspace match exactly.
Fixes#4993
The root tsdown workspace pass builds every member concurrently, so the
Desktop main bundle could resolve its inlined workspace devDependencies
(dsh-home-paths, dsh-app-boot, dsh-deepseek-account) before their lib/
output existed. rolldown then kept them as external imports, which the
asar does not ship, and the packaged application failed at launch with
ERR_MODULE_NOT_FOUND on a clean checkout; stale lib/ output on long-lived
checkouts hid the defect.
apps/desktop leaves the root workspace list and build:lib:host bundles it
after the Host pass. Every Desktop bundle now runs a rolldown plugin that
fails the build when a chunk imports a bare specifier the packaged
application cannot resolve: electron and the manifest dependencies for
the main bundle, electron alone for sandboxed preloads.
- Agent Notes: cross-link the new decision with the native fatal recovery
and fail-loud release notes both ways, rewrite the older note's
console-retention and dialog-detail facts in place, and state the report's
actual bounds.
- crash-report: cut the rendered error section at 256 KiB and prune only
files matching the generated crash-<time>-<source>.log syntax.
- main: backendReady follows the backend state except during shutdown, so a
failure while tearing down a ready backend still reads as running.
- subprocess-local: the temporary-file-cleaner hint is appended only for
ENOENT; other codes rely on the appended error.
- client-modules: describeError is module-private; BootModuleRow.url's
JSDoc names its fallback role.
The ui-chat README described the visibility rule as "while the built-in browser
is available", a phrase that now reads like an option label. Both languages name
the Sidebar Browser, matching the sentence that follows.
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.
apps/desktop imports @deepseek-ai/dsh-api-gateway/stream-protocol, whose
import chain reaches @deepseek-ai/dsh-typert-protocol and then
@deepseek-ai/cordis. Both intermediate packages declare cordis as a
peerDependency and nothing satisfied it for the application closure, so
electron-builder omitted cordis from app.asar and the packaged main process
died before opening a window with ERR_MODULE_NOT_FOUND. A workspace checkout
resolves the peer through pnpm's own links, so development runs and the unit
lanes stayed green while every packaged build since efbc8e26b6 (2026-09-20)
failed to launch.
The lockfile additionally drops a stale duplicate [email protected] in favour of the
7.2.3 it already carries; any real pnpm install removes it.
Verified with a signed win-x64 installer built from this tree: app.asar now
ships cordis and @standard-schema/spec, and the installed application opens
its main window.
The Settings → General row for Chat link destinations now reads
网页链接默认打开方式 with the description 对话中网页链接的打开位置 and the option
labels 应用内侧边栏 and 默认浏览器. English keeps the title "Open chat links in" and
now reads "Choose where to open web links", "In-App Sidebar", and "Default
Browser".
The `ui-chat.linkOpening` setting, its values, persistence, visibility rule, and
open behavior are unchanged. The row spec, the clickable-link gallery scenario,
and the two package READMEs name the new copy; the bilingual pairing records were
re-confirmed for the README pairs.
Carry the user-scoped agent-experience guidance into the repository unchanged so
project sessions discover it beside the other repository skills. The file,
including its frontmatter, is byte-identical to the personal copy.
Skip the per-owner wake ledger entirely when no cap is configured.
Rewrite the 2026-08-11 Agent Note in place for the opt-in cap and add
a note recording why the default was removed. Keep `subagent`
untranslated in Chinese prose and drop change narration from the test.
Refs #4944
The Contact us action already stopped prefilling the signed-in UID, but a
configured contact form URL could still carry its own prefill_uid or hide_uid.
contactUrl now drops both query parameters unconditionally, with regression
coverage that starts from a form URL containing them.
The contact URL test also pins the shipped default form path, and the injected
contactUs documentation and the AccountProfile summary no longer describe a
support UID that is no longer sent.
* fix(web): resolve XLSX part relationships and namespace aliases
* fix(web): keep Excel browser scenario in the host test program
* fix(excel): preserve XML encodings and relocated workbook parts
* fix(excel): exclude installed launchers from dependency patch
* fix(excel): restore Strict and case-equivalent workbook previews
The account menu entry that opens the questionnaire is now labeled Feedback in
English and 意见反馈 in Chinese. The menu action, contact form URL and its
configuration options keep their existing names.
Expected menu snapshots and the bilingual README record the new copy.
`maxConsecutiveWakes` no longer defaults to 3. Unset, every background
job completion wakes its idle owner; the cap is opt-in.
With the default cap, a session chaining background commands and
one-shot subagents exhausted the budget after three wakes. The fourth
notice was injected into the next-step inbox without waking the owner,
the client showed nothing, and the session stalled until the user
typed something (dsh-external/issues#641).
Closesdsh-external/issues#641
The recorded-session scenario edited with a single-line value, so the ARIA
golden could not catch a return to a newline-stripping editor. Edit with a
two-line value and assert the model-bound user message keeps the line break;
with the previous input element the scenario fails on that assertion. Also
refresh the stale input cast and pin that Shift+Enter is not consumed.