Files
deepseek-harness/packages/subprocess/win32-process
Turtle 38c7a9fbf4 feat(release): publish package source, declaration maps, and documentation (#5884)
* feat(release): publish package source, declaration maps, and documentation

Every release member publishes its TypeScript source and the declaration
maps that resolve into it, and @deepseek-ai/dsh publishes the repository
Markdown documentation staged from docs/ at prepack time.

The ./src/* export most members already declared now resolves for an
installed consumer, and a consumer editor follows a declaration to the
implementation. Bundled JavaScript maps stay unpublished; the vendored
family and the Desktop runtime file policy are unchanged.

Rationale: .agents/notes/implemented/process/2026-10-08-published-source-and-docs.md

* feat(release): publish JavaScript maps and compress bundles

Every emitted JavaScript map ships beside the bundle it describes, and the
workspace build and the client preset compress bundles without mangling
identifiers.

The documentation payload now mirrors the website publication manifest and
is removed again by `postpack`; Desktop and the Python executable exclude
the published source, documentation, and maps; `clean` removes a staged
copy. Typert's publication contract gains the Remote declaration map.

* fix(release): keep node bundles readable for the worker image

The browser worker image lowers `yield*` only as a whole statement and
rewrites `for await` loops by their source layout, so compressed node-side
entries either fail that lowering or lower to unparseable code. Only the
browser bundles keep compression, which removes about a third of their text.

The bundle-purity assertion now matches the module-loader call regardless of
the quote style compression picks, and the release-pack fixture exercises
the installed package's new documentation requirement.

* feat(release): publish the whole documentation tree

`@deepseek-ai/dsh` copies `docs/` in full instead of the website's page
set: the maintainer documents, the generated migration records, the
translation guidelines, and the `*.i18n.yaml` consistency records ship
with the installed package, so the documentation's own links resolve
without a checkout.

* feat(release): publish the upgrade guides with the documentation

The staged documentation keeps the website's page set and adds every
`docs/upgrade-guide/` document, which is what an installed reader consults
when a released change breaks something. The rest of the maintainer tree
stays out.

* test(release): expect source and maps in master's new payload cases

* feat(release): keep installed docs and source readable in Desktop

Desktop keeps the published src/ and docs/ trees inside app.asar, and
every model shell call receives DSH_INSTALL_DIR and DSH_NODE_EXECUTABLE
so an agent can read them through Electron's Node mode. Staging also
generates docs/upgrade-guide/README.md, an index of the upgrade guides
grouped by the release they upgrade from.

Minified client bundles print string literals with backticks: the
worker image packer now recognizes those chunk requests, client license
banners are prepended after minification so their text survives, and
the affected artifact tests accept either quote.

* test(desktop): read archived docs through the Windows PowerShell form

Regenerate the config catalog for the shifted shell-env source line.

* test(desktop): wait for the GUI-subsystem Electron process from PowerShell

* build(release): publish source and maps from the message-quotes package

* build(release): publish source and maps from packages new on master

* build(release): publish source and maps from the tool-office package
2026-11-05 00:22:36 +08:00
..

description, kind
description kind
Low-level Win32 process primitives for maintainers implementing or debugging the Windows ACL sandbox and ordinary subprocess Job runner. package-library

@deepseek-ai/dsh-win32-process

English | 中文

Summary

This low-level Win32 process library is consumed by the Windows ACL sandbox and the ordinary subprocess Job runner. It owns the repository's one Koffi binding table for reusable process, stdio, and Job Object operations; it is not a Cordis service and does not choose sandbox policy or public child behavior. Read this page when maintaining either native process path or checking its handle-lifetime limits.

Table of Contents


Behavior

  • One reusable ABI owner — abi.ts owns the Win32 constants and x64 layout values consumed by both process paths. ffi.ts lazily loads kernel32.dll and advapi32.dll, verifies STARTUPINFOW and PROCESS_INFORMATION, exposes typed operations and error formatting, and lets sandbox policy bind its remaining APIs through the same loaded libraries.
  • Restricted-token creation — RestrictedProcessSpawnOptions requires the sandbox's primary token and uses CreateProcessAsUserW. Piped and inherited-stdio paths share command-line quoting, cwd, the restricted-token null-environment policy, checked return values, and handle cleanup.
  • Piped process primitive — spawnPipedProcess() creates anonymous stdin/stdout/stderr pipes, closes stdin immediately, returns the two read ends, and leaves process waiting and pipe draining to the caller. Every partial failure closes the handles already owned by the operation, and every Koffi out-parameter or struct allocation is freed after its Win32 lifetime.
  • Inherited-stdio Job primitive — spawnInheritedJobProcess() creates one kill-on-close Job, temporarily marks the current stdio handles inheritable, creates the restricted child suspended, assigns it to the Job, and then resumes its initial thread. Target code cannot run before Job assignment; controlled assignment or resume failures terminate the suspended child or close the assigned Job before releasing every owned handle.
  • Ordinary Job runner primitive — CurrentTokenProcessSpawnOptions requires a resolved applicationName, the complete target environment, and three runner CRT descriptors dedicated to target stdin, stdout, and stderr. spawnCurrentTokenJobProcess() maps those descriptors to OS handles through Node's exported uv_get_osfhandle(), rejects invalid results, temporarily marks the handles inheritable, and passes them through STARTF_USESTDHANDLES. It sends a sorted UTF-16LE environment block with CREATE_UNICODE_ENVIRONMENT, creates the target suspended through CreateProcessW, assigns it to an unnamed kill-on-close Job, and resumes it only after assignment. The original command-line argv entry remains unchanged, and the runner can close its carrier descriptors without touching Node's own standard streams.
  • Ordinary settlement operations — pollProcessExit() publishes direct exit separately, while isJobEmpty() reads QueryInformationJobObject(JobObjectBasicAccountingInformation) until ActiveProcesses reaches zero. Checked Job termination and handle closure keep the runner as the only native owner.
  • Explicit settlement ownership — waitForProcessExit() waits and closes a sandbox process handle; ordinary runner process polling, Job accounting, and checked Job termination/closure remain separate operations. drainPipe() reuses one native count slot while draining, frees it, and closes the pipe read handle. Each caller owns its result composition and returned handles.

Process creation sets STARTF_USESHOWWINDOW with SW_HIDE before target code runs. It preserves console inheritance and does not add CREATE_NO_WINDOW or CREATE_NEW_CONSOLE, which can fail DLL initialization under the restricted token. Existing parent console windows are not hidden.

The Windows ACL sandbox adds SID, DACL, grant, workspace, and public child policy above these primitives.

  • Inherited control descriptor — Job creation accepts an optional fd-7 pipe. STARTUPINFO.cbReserved2/lpReserved2 carries an eight-slot CRT descriptor table with standard handles, closed slots 3–6, and the control pipe at slot 7. The table is allocated until CreateProcess returns; temporary handle inheritance is reset on success and failure. Initializing the slot before Node starts avoids overwriting descriptors Node has already allocated.

Header verification

The process, stdio, and Job constants plus selected structure sizes and offsets are checked against the MinGW Windows headers by verify/abi-probe.cpp:

g++ -std=c++20 -municode -O2 -o abi-probe.exe verify/abi-probe.cpp && ./abi-probe.exe

The Koffi STARTUPINFOW and PROCESS_INFORMATION definitions also assert their 64-bit sizes at module load. The probe additionally fixes pointer and handle widths, the Unicode-environment flag, and the basic Job accounting record size and ActiveProcesses offset used to determine quiescence; it remains the evidence for the other recorded offsets and constants.

Model Experience

Process primitives

What the model sees

Nothing directly. The package exposes Win32ProcessBindings, CurrentTokenProcessBindings, and process primitives to the sandbox and ordinary runner, which own all model-visible tools, output, and diagnostics; this package contributes no prompt text or tool schema.

Token effect

None directly. Consumers decide whether process output enters a tool result or later model request.

KV Cache effect

The package contributes no stable request prefix, so it does not invalidate model KV caches.

Known Limitations and Deferred Work

  • Windows-only native loading — importing the generic types is portable, but resolving the binding table loads Windows DLLs and fails on other hosts. Cross-platform tests inject a binding table instead of loading native APIs.
  • No public process service — the package intentionally does not wrap its primitives in Cordis or Node streams. A consumer must own its policy, async scheduling, output limits, cancellation, and final handle closure.
  • Restricted-token null environment — the CreateProcessAsUserW sandbox primitives pass a null environment block and establish changes through SetEnvironmentVariableW first because an explicit block through Koffi fails with ERROR_INVALID_PARAMETER. The ordinary CreateProcessW runner instead requires a complete target environment and passes a sorted, double-NUL-terminated UTF-16LE block, including =X: drive entries, without mutating its own environment.
  • No standalone process API — the package exposes the operations current sandbox and ordinary-runner consumers need, but it does not own Node streams, public handles, output policy, cancellation, or durable state.
  • Create-to-assignment interruption — the target starts suspended and cannot execute before Job assignment, but an external termination of the runner in the narrow interval between process creation and assignment can leave the suspended target behind. The package does not claim atomic Job attachment.
  • Header evidence is architecture-specific — the committed ABI probe and layout constants cover the repository's current 64-bit Windows targets. A new pointer width or incompatible Windows ABI requires updating the probe before support is claimed.

Dev Note

Working context for maintainers — click to expand

None.