Commit Graph

12341 Commits

Author SHA1 Message Date
Pine 8e79ec4942 feat: enhance desktop packaging process with self-contained harness verification
- Updated README and README.zh to clarify packaging commands and added verification step.
- Improved packaging scripts to automatically build the self-contained runtime and verify its integrity.
- Introduced new scripts for verifying harness self-containment and booting the web profile.
- Added comprehensive tests for relinking harness symlinks and ensuring self-containment.
- Updated package.json scripts to reflect new build and verification processes.
2026-08-16 00:31:19 +08:00
Pine 82814ad7d3 docs: redesign the bilingual README, merge the desktop app, add static visuals
- Rewrite README.md / README.zh.md around the skill's story order: hero, proof
  screenshots, what it is, why different, features (desktop app, plugin marketplace,
  image recognition, skill manager), how it works, then all commands (desktop download,
  npm/CLI, from source, desktop dev, packaging, quality gates).
- Merge deepseek-harness-desktop into the root README as a first-class feature.
- Add static visual assets under assets/readme/: a project-native hero SVG, a
  how-it-works architecture SVG, and real product screenshots.
- Keep the community-fork notice and links to MODIFICATIONS.md / .zh.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-15 18:10:15 +08:00
Pine 3dacd6e399 docs: document the community fork, bilingual README + license + modification notes
- README.md / README.zh.md: add a bilingual "community fork" banner noting this is a
  derivative of deepseek-ai/deepseek-harness with a desktop app, plugin marketplace,
  image recognition, and a release channel; link to the modification notes.
- MODIFICATIONS.md / MODIFICATIONS.zh.md: standard, bilingual list of changes vs upstream.
- LICENSE: keep MIT, add PineSound as derivative copyright holder while preserving the
  original DeepSeek copyright, and point to MODIFICATIONS.md.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-15 18:05:42 +08:00
Pine d64ff6e3d4 fix(settings): expose third-party settings namespaces to the web config client
The web configuration surface (apiproxy) served only model-provider plus
explicit allowlist namespaces, so a third-party plugin's settings card (e.g.
the web-ui image-understanding plugin's describe-image) showed "namespace not
exposed" and was uneditable. Let a plugin opt its namespace in via
`settings.register(..., { configurable: true })`, and let a deployment expose
any shipped third-party namespace via the gateway's new `exposeSettings`
config (the web-app bundle lists describe-image). Default stays not-exposed.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-15 17:04:36 +08:00
Pine 604a817546 refactor(desktop): shell polish — register the dsh launcher, use vendored pnpm, docs
Register the dsh CLI launcher from the desktop shell, prefer the vendored
pnpm in the CLI plugin command, and update the desktop and CLI reference docs.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-15 17:04:36 +08:00
Pine a53769955b feat(plugin): plugin marketplace, durable install persistence, skill manager
Add an in-app plugin marketplace fed by a remote web catalog: the host
plugin-inventory gateway gains marketplaceList/Install/Uninstall remotes,
a durable per-user install table reconciled against the actual profile, and
git/npm/tarball/bundle install paths with non-interactive git and vendored
pnpm. The Web Settings surface gains a sibling 插件市场 tab that lists the
catalog with recommended badges, repository links, and a combined sort
(recommended first, then catalog priority, then id).

Add a host + client skill manager: list local skills by direct filesystem
discovery, and install/uninstall/toggle/edit their SKILL.md from git/npm/
tarball/local sources in the writable user root.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-15 17:04:36 +08:00
Pine 5f348f9b1c fix(desktop): bundle the preload to CommonJS so the dshApp bridge loads under sandbox
The renderer opens with sandbox:true, and Electron sandboxed preload scripts
only support CommonJS. The preload was emitted as ESM (package.json is
"type": "module"), so it failed to load silently and window.dshApp was never
injected. The About section then fell back to plain-web mode: current version
stayed on the '—' fallback and check-for-updates reported up-to-date without
querying. Build the preload with esbuild into lib/types/preload.cjs and point
the main process at it.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-14 23:25:54 +08:00
Pine ebe2d43bee chore(ui-conversation): clarify the preview badge copy
Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-14 23:02:06 +08:00
Pine c90beb5289 style(plugin-inventory): align install/toggle controls with the design system
The install input matched the catalog search field, and the install button plus
the enable/disable toggles now use the shared Button primitive (primary /
outline sm), replacing unstyled native buttons. The install hint clarifies that
registry installs require a published npm package.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-14 23:01:57 +08:00
Pine aaa434afbd feat(desktop): dynamic About version, update manifest date, and a unified publish flow
The About section hardcoded its version; the main process now exposes
get-app-info so it reads app.getVersion() dynamically, and the update result
carries the manifest release date. The manifest generator orders versions
numerically (0.10.0 outranks 0.9.0). A new stage-release script copies
releases.json plus installers into the deepseek-harness-web site root's
updates/, which deploy.py publishes to OSS alongside the download page, so the
app and web share one update channel. The About section also gains links to the
release site and official site.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-14 23:01:36 +08:00
Pine 768bcd4356 fix(image-recognition): keep the vision key on its own ref; add clear-key
Image recognition and the chat model shared DEEPSEEK_API_KEY: the
image-recognition bundle defaulted apiKeyEnv to the model key, so saving one
overwrote the other. Point the bundle at IMAGE_RECOGNITION_API_KEY and guard
both the provider and the settings card against a stale model ref, so vision
never reads or writes the chat key. Also add a clear-key button, default the
model to qwen3-vl-flash on the DashScope compatible-mode endpoint, and send
file images as base64 with a normalized base URL.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-14 23:01:15 +08:00
Pine 6890e87021 feat(image-recognition): independent key/url/model defaults
Make the HTTP vision provider's configuration independent of the main chat
model: the API key default moves from DEEPSEEK_API_KEY to IMAGE_RECOGNITION_API_KEY,
and the URL and model get image-recognition-specific defaults (Aliyun DashScope
compatible-mode and qwen3-vl-flash) instead of the chat model's deepseek-v4-flash.
The provider fails loud when no model is configured.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-14 20:45:35 +08:00
Pine e87a3084ea feat(desktop): manual-download update check and OSS release manifest
Adds an unsigned, manual-download update flow. The main process fetches the OSS
updates/releases.json manifest (DSH_UPDATE_URL overrides), compares the latest
version, and on startup and hourly prompts to open the per-platform installer
URL; a preload bridge exposes the same check to the SPA's About "check for
updates" button, which renders the version, notes, and a download link.
scripts/generate-release-json.mjs builds the manifest from the packaged
.dmg/.exe. Windows nsis packaging is configured.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-14 20:45:21 +08:00
Pine e18cfbfb93 feat(plugin-inventory): live plugin activation, mirror install, and toggle lists
Installing a plugin now activates it without a restart: the CLI boot provides a
dshReloadProfile handle that re-runs the profile composition and applies it to
the running root Include, and the install/uninstall Remotes recompose live when
the handle is present (restartRequired: false). Registry installs try the
ordered INSTALL_REGISTRIES mirrors with the official npm registry as the final
fallback, erroring only when every source is unreachable. The enable/disable
guard splits into a REQUIRED_PLUGINS blacklist and a USER_TOGGLEABLE_PLUGINS
whitelist (default toggleable) generated from the running plugin list, and the
offline optional-bundle catalog is emptied (default bundles are not
installable/uninstallable). The plugin-list tab becomes a registry install form
and shows immediate-activation instead of a restart notice.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-14 20:45:00 +08:00
Pine a0efe02c04 fix(plugin-inventory): rename install Remote to installPlugin
The RemoteNamespaceService reserves `install` as its private registration
method, so a Remote method also named `install` collided at client-api boot
(`pluginInventory/install conflicts with its namespace service`). Rename the
plugin-install Remote to `installPlugin` across host, client, and tests.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-14 18:57:08 +08:00
Pine 6cd7c5a590 feat(plugin-inventory): offline bundle and pnpm plugin install for the desktop
Adds an install surface to the plugin-inventory gateway: availableBundles lists
the curated offline-installable optional bundles (AVAILABLE_BUNDLES); install
composes an offline bundle into the profile's dsh.profile.bundles, or for a
registry spec runs pnpm against the writable profile via the bundled Node and a
vendored pnpm (gated behind the dshAllowPluginInstall context flag, set only by
the desktop boot); uninstall removes a bundle layer. The reconcile logic from
`dsh plugin add` moves into app-boot as shared helpers. The desktop vendored
pnpm into the harness and sets the allow-install env; the plugin-list SPA gains
an installable-bundles section. Tests cover the guard, install helpers, and the
SPA section at 100% host coverage.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-14 18:46:39 +08:00
Pine 8f1c764614 feat(plugin-inventory): blacklist/whitelist toggle guard with a default-open default
Splits the enable/disable guard into two code-editable lists: REQUIRED_PLUGINS
(the blacklist of load-bearing core that must never be disabled) and
USER_TOGGLEABLE_PLUGINS (the whitelist, which overrides the blacklist for an
explicitly toggleable plugin). A plugin on neither list is toggleable by
default. isRequiredPlugin and isUserToggleable derive from the two lists.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-14 18:44:56 +08:00
Pine e90650c164 docs(plugin-system): reference for install, injection, and required/optional split
Adds a bilingual reference explaining how plugins are installed and composed
(bundles, patches, profiles, the Loader), how they are injected and activated
(Cordis inject/provide, fiber PENDING), and a dependency-derived split of the
shipped base bundle into system-required and freely optional plugins. Links the
plugin-inventory README to it and excludes the desktop build output from the
translation-pairing corpus scan.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-14 18:44:41 +08:00
Pine 7f4a87b992 i18n(ui): clarify preview build and extended image-recognition copy
Notes the preview build as unofficial in the conversation hero and describes the
image-recognition plugin as an extension beyond the official DeepSeek surface.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-14 17:39:47 +08:00
Pine 79ae82fa48 feat(desktop): Chinese menu, branded icon, and a self-contained harness bundle
Localizes the Electron application menu (文件/编辑/视图/窗口/帮助 plus the
macOS app menu), adds a branded 1024px app icon (window + per-target icns/ico),
and makes the packaged app fully self-contained. Because the harness's pnpm
workspace does not cleanly materialize via pnpm deploy or electron-builder's
dependency resolution (per-package symlinks to vendored sources, native addons,
a separate frontend dist), scripts/build-harness.mjs assembles the repository's
working runtime — node_modules, vendor, packages, native, apps/cli, apps/web,
and a bundled Node binary — into build/harness. electron-builder ships it as an
extraResource at Resources/harness, and the main process spawns that bundled
node + dsh entry when packaged (keeping the system-Node child during dev). Adds
a comprehensive README and ignores the multi-GB harness/dist from git.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-14 17:39:26 +08:00
Pine 1031b63100 feat(ui-settings): add an About section with company copy and version check
Registers a new `settings.section` (id `about`) in ui-settings-general that
introduces PineSound, names the product build, shows the current version, and
offers a check-updates control (a client-side placeholder comparing against a
known-latest constant pending a real update channel). Adds a 16px info icon to
ui-primitives and wires the section into the settings nav. Tests cover the
registration and the About component; READMEs and translation-pairing hashes
are updated.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-14 17:39:02 +08:00
Pine a8ec40ad34 feat(plugin-inventory): flat plugin list with a default-open toggle guard
The plugin-list tab rendered one flat list of every Loader entry — no separate
"system plugins" section — with each card showing its real enabled state and an
enable/disable button (a required plugin shows only a read-only note). The
enable/disable guard flipped from default-protect to default-open: only the
small REQUIRED_PLUGINS core (entry tree, Remote RPC spine, session/agent spines)
is protected from being disabled, so the shipped plugins are actually
toggleable. Tests, host READMEs, and the enable-disable agent note track the new
grouping and guard.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-14 17:38:38 +08:00
Pine cbec8cd6a9 feat(plugin-inventory): group by enabled state and allow re-enabling disabled plugins
The plugin-list tab now splits by current state: disabled plugins sit in the
main list with an enable button (so a bundle-default-disabled plugin can be
re-enabled), while enabled plugins sit in the collapsible system section —
a user-added enabled plugin keeps a disable toggle, a required one shows
none. setEnabled refuses to disable a required plugin but allows re-enabling
a disabled one, verifying the fiber activates and reverting a
dependency-missing enable.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-14 14:30:13 +08:00
Pine d385b7cf05 feat(ui): group the plugin list into toggleable and system sections
User-added (toggleable) plugins carry an enable/disable button in the main
list; required system plugins sit in a separate collapsible 'system plugins'
section with no controls. The system section starts expanded so the existing
web e2e/snapshot (which targets a system plugin row) still passes.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-14 14:23:42 +08:00
Pine df085ac6f8 feat(plugin-inventory): guard critical plugins from enable/disable
Every entry now carries a protected flag. The guard is default-protect:
disabling a plugin another plugin injects breaks the dependent, and enabling
one whose service is unavailable fails the boot (dsh-tool-ralph: pending on
workflowEngine). setEnabled refuses and the UI hides the toggle for every
shipped plugin; only opt-in-bundle plugins (USER_TOGGLEABLE_PLUGINS in
required.ts) are toggleable.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-14 14:10:38 +08:00
Pine 842483164d docs(plugin-inventory): document setEnabled, persistence, and the in-page toggle decision
Update the plugin-inventory READMEs from read-only to toggleable and record
the in-page enable/disable capability as an Agent Note.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-14 13:53:46 +08:00
Pine f01795ea97 feat(ui): add enable/disable toggle to the plugin-list tab
Each expanded plugin card gains an enable/disable button wired to
pluginInventory.setEnabled; the tab re-lists after toggling. Adds zh/en
copy for the toggle states.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-14 13:53:36 +08:00
Pine 3e0eca752c feat(plugin-inventory): add setEnabled Remote that toggles and persists a plugin
pluginInventory/setEnabled calls ctx.loader.update({disabled}) for a live
effect and writes an explicit disabled override into the profile's user
patch layer so the choice survives a restart. The patch row id is the bare
entry options.id, not the group-prefixed tree id.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-14 13:53:24 +08:00
Pine 18457f57b9 test(ui): render the image-recognition card's endpoint, key, and model controls
Unit-render the card after expanding its disclosure header, asserting the
three configurable controls appear (getByLabelText throws when absent).

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-14 13:36:28 +08:00
Pine 79c0d49a08 fix(web): expose the image-recognition-http settings namespace to config clients
The RPC settings.describe only serves namespaces on the WEB_SETTINGS_NAMESPACES
and PRODUCT_SETTINGS_NAMESPACES allowlists; a namespace absent from both answers
settings-not-exposed even when its owner registered it. image-recognition-http
was missing, so the plugin-config card's scope stayed unavailable and the card
rendered nothing. Add it to the web allowlist beside web-search-deepseek.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-14 13:32:59 +08:00
Pine f0500eea3d test(ui): update ui-settings-plugins assertions for the image-recognition card
The apply test now expects four plugin.item cards (bash, agent-loop,
web-search, image-recognition), a cardCount of 4, and two credential
re-reads (web-search and image-recognition both watch the reference).

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-14 13:17:34 +08:00
Pine d8b2b684e2 build(desktop): add desktop:dev:fast preview that skips the host rebuild
tsdown re-bundles all host packages every build:lib:host (~35s), which
desktop:dev runs each time. desktop:dev:fast skips it for web/client/
desktop-only changes (vite compiles from source), leaving the full path for
host-package changes.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-14 12:27:07 +08:00
Pine 6c2b292a58 fix(desktop): restore a valid package name so the workspace filter resolves
The package name must be a valid npm/pnpm workspace name; the display name
belongs in electron-builder productName. The invalid rename broke
pnpm --filter @deepseek-ai/dsh-desktop in desktop:dev.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-14 12:12:45 +08:00
Pine 08ac7c3da5 feat(vision): gate recognition on a configured provider
Expose ImageRecognitionRuntime.available() and gate the image-task pre-step
injection on it, so the capability is dormant until an endpoint is
configured instead of guiding the model to a call that can only fail.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-14 12:08:30 +08:00
Pine 2b81e38263 build(cli): depend on the image-recognition bundle so it resolves from the anchor
The web profile template mounts the bundle; apps/cli must declare it so the
harness resolves it from the installation anchor for both fresh and existing
web profiles.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-14 11:51:04 +08:00
Pine b12262e8c9 feat(app-boot): mount image recognition by default for the web profile
Add the image-recognition bundle to the web profile template so the
capability is on by default for new web profiles.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-14 11:48:17 +08:00
Pine c73b9eb403 feat(ui): add model field to the image-recognition settings card
The card now configures the provider endpoint, API key, and model, mirroring
the provider Config.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-14 11:33:13 +08:00
Pine f5f114dfb8 docs(vision): package READMEs, Model Experience, and the capability Agent Note
Document the four image-recognition packages and the vision group, register
the vision domain in the package index, add the capability decision as an
Agent Note, declare the invariants peer dep, and drop the unused agents
injection from the consumer.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-14 11:15:59 +08:00
Pine 19b39bc2e0 build(catalog): catalogue recognize_image and allowlist model-agnostic vision packages
Register the tool-image-recognition package in the tool-catalog generator so
its schema is catalogued, and add the model-agnostic vision seam/provider/
bundle to the README Model Experience omission allowlist.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-14 11:15:39 +08:00
Pine b6b982dc87 feat(ui): add the image-recognition settings card
An image-recognition card in the Plugins settings page (endpoint + key),
cloned from the web-search card: baseURL via the settings section, the key
through the credentials domain.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-14 11:15:26 +08:00
Pine 381c6510e9 build(vision): register the vision domain and packages in the build graph
Add the vision path domain to the tsconfig base paths catch-all, reference
the four new packages in the host TypeScript program, and record their
workspace deps in the lockfile.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-14 10:58:40 +08:00
Pine 5e962b8a8d feat(vision): add the opt-in image-recognition bundle
Mounts the capability seam, the configurable HTTP provider, and the
model-facing recognition consumer. Not in any default profile's bundles
list — a user opts in per profile.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-14 10:58:29 +08:00
Pine 457304e619 feat(vision): add the model-facing recognition consumer
Registers the recognize_image tool and a bundled image-recognition skill,
and hooks agent/pre-step to deterministically inject the skill body when a
step input carries an image (content block or image path/URL), so the model
recognizes the image before continuing the task.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-14 10:57:38 +08:00
Pine 6409636afb feat(vision): add the configurable HTTP vision provider
Registers an OpenAI-compatible chat-completions provider into
ctx.imageRecognition with a user-editable baseURL + API key via a settings
section and the credential plane. Logs the secret-free vision request body
as the image-recognition/llm-request session event.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-14 10:56:10 +08:00
Pine fc180997c6 feat(vision): add the image-recognition capability seam
Service Definition for ctx.imageRecognition: a provider registry and
provider-selecting execution, mirrored on the web seam (duplicate ids
rejected, order-independent selection, ImageRecognitionError taxonomy).

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-14 10:55:57 +08:00
Pine 1c27680bb9 docs(desktop): record the Electron desktop shell decision as an Agent Note
Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-14 10:23:56 +08:00
Pine 10a4f4a8f5 build(desktop): wire the Electron app into the workspace and build graph
Add desktop:dev/build/pack scripts, approve the electron build script in
pnpm-workspace.yaml allowBuilds, and reference apps/desktop (plus its
tests) in the host TypeScript program. Records the electron and
electron-builder deps in the lockfile.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-14 10:23:39 +08:00
Pine 0cdbbfbf1a feat(desktop): add Electron desktop shell over the web profile
Spawn the real dsh CLI running the web profile on loopback (OS-assigned
port), parse the printed readiness URL, and open a native window at it.
The harness and its native addons stay on the system Node ABI; the main
imports only electron and node builtins.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-14 10:23:22 +08:00
imccyu 47f943859b Merge pull request #2519 from deepseek-harness/feat/npm-public
release: dsh@0.1.0-rc.5 & publish the dsh family publicly
2026-08-13 19:38:46 +08:00
imccyu abe560f81e release(dsh): 0.1.0-rc.5 2026-08-13 18:49:33 +08:00