dsh-app-packager
DeepSeek Harness bundle for AppPackager: list your uni-app x projects, check the local toolchain, and build iOS IPA / Android APK / HarmonyOS HAP without leaving a Harness session — from the agent (four tools) or from a panel in the web GUI.
Install
Search for AppPackager in the Harness plugin market, or:
dsh plugin --profile desktop add dsh-app-packager
Restart the profile afterwards. The plugin depends on app-packager (the CLI
and the packaging engine), which is installed with it.
Panel in the web GUI
The bundle ships a client half (./src/client.ts), so the web GUI gains an
App packaging entry in the sidebar's own panel list, with its page in the
centre column:
- Engine — engine directory, engine version, whether it is materialized,
and which bash bridge was found (macOS/Linux
bash, Windows Git Bash or WSL). Init engine materializes a missing engine in one click. - Environment check (Node) — the same report as
app_packager_doctor, for one platform or all of them, with hints for every failed item. It runs by itself as soon as the panel has the engine state (you never sit on Loading…), re-runs when you switch the platform in that card, and a failure is written into the card so Run check can retry. - Folding — every section (Engine / Environment check / SDK / Projects / Build options & scope / Upload / Job) starts collapsed; click its title to open. The fold state lives with the component, so refreshing state or polling a job never loses where the user left it.
- Projects — every
config/projects/*.env, its source directory (flagging a missing one), the platforms it enables, and per-project Env check / Build buttons; the whole list folds under the Project list header, and each row keeps its own Remove button. The Choose folder… button opens the host's own folder dialog and Add project registers the picked directory through the engine'sregistersubcommand, so a project anywhere on disk gets the sameconfig/projects/<id>.envthe wizard would write. The field is the folder that holds your projects (e.g./Users/you/work/projects) — the engine scans one level below it and registers every uni-app x project it finds, so picking projects one by one is unnecessary (several picked folders are joined into that one field). - Build options & scope — one card for both halves of "how to build" and
"what to build": the version override, the Upload after build row, the
Advanced fold, and underneath the boxed scope block — any set of platforms
(tick All for the three) and any subset of projects (none ticked = every
project that platform enables), with the one Env check / Build pair. The
engine CLI takes a single platform and a single project per run, so a
selection becomes several engine runs executed back to back inside one job,
each marked
▶ i/nin the log; the job succeeds only if every run did, keeping the first failing exit code. A build can still upload what it just produced: the Upload after build row ticks the distribution platforms (the same selection the Upload card's Distribution row edits, sent as one comma separated--upload), and ticking none sendsnoUpload, so uploading without a rebuild stays the Upload card's job. HarmonyOS debug HAP and Keep work dir live in that Advanced fold, each with a one-line explanation. - Upload — the installers the engine has already archived, straight from
state.artifacts(listArtifactsreadspackages/iOS|Android|HarmonyOS/ <项目ID>-latest.json): display name, version, file size (or a no installer archived tag when the JSON outlived the file) and build time, each with an Upload button that starts akind: 'upload'job for that one artifact — the engine'supload <platform> <project> --to <平台>action, which never rebuilds and fails the job when the engine skipped rather than uploaded. The card also holds the distribution targets (the usable uploaders fromconfig/upload.env, ticked ones sent as one comma separated--to) and the credential rows: an uploader that declaresUPLOAD_PLATFORM_<id>_API_KEY_VAR(pgyer declaresPGYER_API_KEY) or_USER_KEY_VAR(PGYER_USER_KEY, pgyer's optional API 1.0uKey) gets a masked row each, with aConfigured/Not setchip next to its Save button. Save writes only the field you typed into, so storing one never clears the other:POST /api/app-packager/upload/credentialupdatesconfig/upload.local.env(mode 600, the filelib/init.shsources), and the key only ever travels engine-ward —GET statecarries the booleanscredentialConfigured/userKeyConfigured, never a secret. The card also reports whether the official CLI is installed (with its package and version once it is). - SDK — the detected HBuilderX app/CLI and its version series, and each
platform's SDK directory with its state (
ready/mismatch/missing). One-click setup asks the engine to download and unpack the matching SDK for the ticked platforms, Process downloaded SDKs imports archives already insdk/, and each row links to DCloud's official download page — plus the direct iOS archive URL, which follows from the version series alone. - Upgrade plugin — reinstalls
dsh-app-packager@latestinto the current profile. The engine directory is renamed out of the way for the duration, so an upgrade can never delete your downloaded SDKs, certificates or registered projects; the button is hidden when the plugin does not run from a profile'snode_modules. Once the upgrade job succeeds the card tells you to restart DeepSeek Harness and deliberately offers no Reload page button: the browser asks for client modules by the revision from its boot-time manifest, and after an upgrade that revision no longer exists on the server (plugins/??<id>/src/client.ts&rev=<old>answers 404), so a reload takes the sidebar entry away instead of bringing it back. Restarting DSH rebuilds the manifest. - Job — the running check/build/upload with its live engine log, its verdict
(
[FAIL]or a non-zero exit code counts as failed) and a Stop button. Engine[FAIL] …/[WARN] …lines are also lifted into their own box above the log together with the totals, so a missing profile, p12 or SDK is readable without scrolling the raw output. The job lives in the host process, not in the browser tab: switching to another DeepSeek Harness tab (or reloading the panel) re-adopts the newest job fromGET state, so a build that is still running comes back with its log, verdict and Stop button, and a finished one stays on screen until you start another build or press Clear (settled jobs only — a running one is never dropped, or there would be nothing left to stop).
The panel only calls same-origin routes registered by this plugin
(/api/app-packager/state|init|doctor|pick|project|project/remove|job|job/log|job/kill|job/clear|upload/credential) — no
build logic runs in the browser. It needs a profile that ships the web app
(@deepseek-ai/dsh-web-app, as the desktop and web profiles do); in a headless
profile the panel is simply absent and the four tools keep working.
Tools
app_packager_list
Lists the projects configured in the engine directory (config/projects/*.env):
project id, app name, whether the source directory exists, enabled platforms.
AppPackager 引擎目录:<plugin>/home
引擎版本:0.6.2
项目(1):
- shop(商城)
平台: iOS (IPA), Android (APK)
源码: /Users/me/work/shop
Pure Node, so it also works on Windows. The first call materializes the engine.
app_packager_doctor
Reports whether this machine can build: Node version, the bash bridge, Xcode /
signing tools, HBuilderX CLI, JDK, Android SDK, DevEco Studio, the HarmonyOS
signing directory and the project config. platform: ios / android /
harmony / all (default all). Also pure Node.
app_packager_check
Runs the engine's check subcommand for one platform (certificates, SDK
directories, HBuilderX CLI) and returns the tail of its output plus a verdict.
Parameters: platform (default all), project (project id, omit for all),
home.
app_packager_build
Runs a real build; minutes per platform (iOS especially), timeout 90 minutes.
| Parameter | Description |
|---|---|
platform |
required, ios / android / harmony / all |
project |
project id; optional with platform=all (means every project) |
upload |
upload after building, e.g. pgyer |
noUpload |
skip the upload stage |
version |
override the artifact version |
harmonyDebug |
emit a HarmonyOS debug side-load HAP |
keepWork |
keep the intermediate work directory |
home |
engine directory (usually omitted, see below) |
When unsure, run app_packager_check first.
Configuration
The bundle patch provides the config; override it in your own profile
cordis.patch.yml by re-inserting id: app-packager:
- insert:
- id: app-packager
name: 'dsh-app-packager'
config:
home: '' # engine dir; empty = <plugin>/home or APP_PACKAGER_HOME
searchRoots: [] # extra project scan roots (outside the engine's parent)
checkTimeoutMs: 600000 # check timeout (ms)
buildTimeoutMs: 5400000 # build timeout (ms)
outputLimit: 12000 # engine output kept in a tool result (tail)
The same values are editable in Harness under Settings → Plugins → Plugin config.
Engine directory and first use
The engine directory lives inside the plugin (<plugin>/home), so it travels
with the plugin; APP_PACKAGER_HOME or the home config key points it
somewhere else. An existing ~/AppPackager from an earlier version is renamed
into place on first use — a rename, never a copy, so multi-GB SDKs and
registered projects move instantly.
The first tool call (or the panel's Init engine) releases the bundled engine
there; later upgrades refresh the engine files (when the .engine-version in the
directory differs from the package version, the next tool call or panel button
refreshes it in place, and until then that panel row reads "the directory holds
X — needs a refresh") but never overwrite your own
config, certificates, SDKs or artifacts. Upgrade plugin in the panel goes one
step further and reinstalls the npm package, keeping the engine directory
stashed until the install finishes.
Do not reinstall this package around the panel.
<plugin>/homesits inside the package directory, so any pnpm command that really reinstalls it —pnpm install --force, adding another version, changing thefile:spec — deletes the engine directory along with it, SDKs, certificates and registered projects included. Use Upgrade plugin in the panel, ornode <plugin>/upgrade.ts, which stashes the engine directory first; both also refuse to move you onto an older release than the one installed.When the sidebar entry disappears. The host composes the plugin list once at startup and silently skips a plugin whose package directory is missing. Check in order: (1)
ls <plugin>(i.e.<profile>/node_modules/dsh-app-packager); (2) if it is gone, read<profile>/.plugin-manager/logs/*/pnpm.log— a failed install leavesCommand failed with exit code 1, and pnpm removes the old package directory first, taking the SDKs, certificates and projects inhomewith it; (3) install it back (plugin market, ordsh plugin --profile <profile> add dsh-app-packager) and restart DSH — the list is composed at startup only.
For the interactive wizard (register uni-app x projects found next to the engine, pick platforms, configure signing), use the CLI:
npx app-packager init
npx app-packager register ~/work/shop # or register a directory directly
Platform support
list / doctor work anywhere. check / build need bash: built in on
macOS/Linux, and on Windows through Git for Windows (recommended) or WSL. iOS
packaging is macOS only — elsewhere doctor reports iOS as failed rather than
pretending otherwise.
Licence
MIT
No comments yet. Be the first to write one.