Files
deepseek-harness/packages/ui/app-boot
imccyu 6dde9f70f0 fix: satisfy doc gates after the examples/ relocation
Repair cross-group README links whose targets changed groups
(ui/jsonrpc, ui/app-boot -> examples; examples/* -> ui seams),
re-record the bilingual-pair consistency hashes for the docs the
rename touched on both language sides, and condense the AGENTS.md and
packages/README.md group entries. The packages/README ceiling rises
710 -> 760 for the mandated new examples/ hierarchy row (5% headroom).
2026-07-15 16:46:05 +08:00
..
2026-07-15 11:28:45 +08:00

@deepseek-ai/dsh-app-boot

Shared boot glue for the app bins (dsh-stdio-demo, dsh-acp-demo): each bin is a thin self-executing composition over these helpers, parameterized by its diagnostic prefix, so the loader-failure lore lives once — under the per-file coverage gate — instead of drifting between two published artifacts.

Export Role
resolveConfigPath(path, snapshotMode, cwd?) Absolute config path; snapshotMode === 'replay' swaps a cordis.yml/.yaml basename for its sibling cordis.snapshot.yml
loadEnv(binName, dir?, warn?) Load the gitignored .env (Node process.loadEnvFile); absent file is fine, an unloadable one warns a single labelled line (default: stderr)
installFailLoud(binName, proc?) Turn a post-boot() unhandled Loader rejection into one labelled stderr line + exit(1); returns the uninstaller (for tests)
assertEntriesLoaded(ctx, binName) Throw when a settled tree holds an enabled entry with no fiber (a plugin module that failed to import)
boot(binName, absoluteConfigPath) Mount the Loader, mount the statically imported include plugin as the cordis:include builtin (so the config may live outside node_modules reach), include the config by absolute file:// URL, await the whole tree, assert entries loaded, return the root context

Two failure classes the guards handle: loader.await() swallows init rejections (Promise.allSettled) — Node still exits non-zero on the resulting unhandled rejection, and installFailLoud replaces the noisy dump with one labelled line and a guaranteed exit(1); a failed plugin IMPORT is only logged by the Loader (the process would otherwise exit 0 on a usable config typo), leaving a fiber-less entry that assertEntriesLoaded turns into a boot() rejection.

Bare plugin specifiers in a config (@deepseek-ai/dsh-*) resolve through the cordis Loader's internal module loader, using node --expose-internals or the optional node-addon-require-builtin fallback. the bins' subprocess smokes exercise that path, while this package's unit suite drives boot() in-process against configs with relative specifiers.

Model Experience

Indirectly, through the plugin tree it loads, which determines the prompts, schemas, messages, and model adapter in the resulting application.

Known Limitations and Deferred Work

  • Bare package specifiers depend on Loader internals — production bins need node --expose-internals or the Loader's optional native fallback; an in-process caller without either must use resolvable relative/file specifiers or tsx path mapping.
  • Snapshot replay swapping is basename-specific — only a config ending in cordis.yml or cordis.yaml maps to the sibling cordis.snapshot.yml; custom config names require caller-managed selection.
  • Environment loading is cwd-scoped and optional — the helper loads one .env file and warns on failure; it does not search parents, merge profiles, or validate required variables.