Skip to content

[Bug] Pre-install guard invents an entry file for skill-only bundles: valid plugins are blocked on the git channel and reported to their authors #183

Closed

Description

@SU-AN-coder

DeepSeek Harness version

0.2.0-rc.2 (dsh --version)

Plugin Hub version

1.6.6 (source at main @ f9a5a20)

Node.js version

v24.13.1

Profile

web, clean DSH_HOME

Affected plugin

QingYunA/answer-me-with-html — and every plugin whose manifest declares dsh.bundle.patch and no main / exports

Steps to reproduce

  1. In the market, install qingyuna/answer-me-with-html. It has no npm package (npm search repository:qingyuna/answer-me-with-html finds none), so the install falls back to the git channel.
  2. /install answers 400 before installing:
[packaging] github:QingYunA/answer-me-with-html: plugin distribution is incomplete —
the entry file index.js declared in package.json is not present in the git distribution
(build output not committed). Report to the author.
  1. The failure dialog files that on the author's repository: [dsh-plugin.org | dsh-plugin-hub] plugin distribution incomplete: qingyuna/answer-me-with-html QingYunA/answer-me-with-html#209.

Expected behavior

The install proceeds and the plugin's skill mounts. The package is complete: it is a skill-only bundle, and the file the guard asks for is one its manifest never declares.

Actual behavior

A valid distribution is blocked, with a report filed on the author's repo. Ran the guard's own steps (resolvePackageEntry + rootPackageEntryOfTarList) on the real codeload tarball of 90c8d49d (the live path cannot run from my network — git ls-remote hits PREFLIGHT_TIMEOUT_MS, and that path returns ok: true by design):

what the guard checks result
resolvePackageEntry(manifest) for { dsh: { bundle: { patch: './cordis.patch.yml' } } } (no main, no exports) index.js
root index.js in that tarball absent
the cordis.patch.yml the manifest declares present

The same happens to wjvalue/dsh-answer-me-with-html, which has the same manifest shape.

Why the guard, not the package

  • dsh loads a bundle from its manifest and the patch that manifest names, and never imports the package: bundleManifest in @deepseek-ai/dsh-plugin-manager is documented as "Read bundle metadata without loading its JavaScript", and bundlePatchPaths(...) is what gets applied to the profile.
  • The npm channel never runs this check (the registry is trusted), so the same shape installs there and is blocked here — the two channels disagree about one package.
  • End to end on DSH 0.2.0-rc.2, clean DSH_HOME, pnpm 10.34.7:
$ dsh plugin --profile web add github:QingYunA/answer-me-with-html
+ answer-me-with-html github:QingYunA/answer-me-with-html   Packages: +5   Done in 20.3s
$ ls $DSH_HOME/profiles/web/node_modules/answer-me-with-html
bin  cordis.patch.yml  docs  examples  locale  package.json  README.md  README.zh-CN.md  skills  src
                                                               (no index.js — as the manifest says)
$ dsh --profile web --dump-config | grep -A8 'answer-me-with-html'
# == answer-me-with-html
- id: answer-me-with-html-skill
  name: '@deepseek-ai/dsh-skill-filesystem'
  config:
    providerName: answer-me-with-html
    includeDefaultRoots: false
    bundledSkillDir: !!js >-
      process.getBuiltinModule('node:path').join(…, 'skills')

exit 0, no stderr: the bundle is registered in dsh.profile.bundles, its patch composes into the plugin tree, and nothing imports the package.

Fix

#182 — a manifest that declares no entry is no longer treated as missing one; a distribution is judged on what its manifest declares (the entry, when there is one, plus the dsh.bundle.patch files it names), and that the declared patch is present is now checked too. Both channels use the same rule. Open, CI awaiting approval.

Until it lands, affected users can install with dsh plugin --profile <profile> add github:<owner>/<repo>, which the plugin's README documents.

Checklist

  • I have searched existing issues and this is not a duplicate.

Activity

  1. SU-AN-coder commented on Oct 13, 2026

    @SU-AN-coder
    ContributorAuthor

    Scope check, so this can be judged against how far the bug reaches. I walked the catalogue (api.dsh-plugin.org/plugins.zh.json, 13,810 entries) and audited the top 80 by stars. 32 of those have a readable root package.json (the rest are monorepos or carry no root manifest, where the pre-flight has nothing to inspect at all); of the 32:

    • 31 declare dsh.bundle.patch — bundles are the norm, not a corner.
    • 4 declare no entry at all, i.e. the shape this report is about: QingYunA/answer-me-with-html, mnemon-dev/mnemon, thebiggavin/marketingdashboard, zuorn/tydora. None of them resolves to an npm package whose metadata points back to its repository — three of the names are not on npm at all (answer-me-with-html, @mnemon-dev/dsh-mnemon, tydora → 404 from the registry), and the market only uses the npm channel when that reverse check passes. So for those four the git channel is the only channel, and the pre-install guard blocks all four today.
    • 4 declare an entry their git distribution does not contain — yjh051108/dsh-routing-suite → injector/lib/index.js, sandbaseai/sandbase-harness → dist/index.js, hust-open-atom-club/oh-dsh → dist/plugin.js, toolclub/dsh-agent-team-gui → lib/index.js. These are the guard's true positives, and every one of them is built by a prepare/build script that a git install cannot run. oh-dsh is also a live case for the second half of the rule: it declares dsh.bundle.patch: ./dist/cordis.patch.yml, and the repository has no dist/.
    • 21 of the 31 mount themselves by name (the - insert: - name: <package> pattern the packaging guide shows), which is why the fix keeps the entry requirement for that shape and drops it only for the bundles that mount a provider instead.

    The audit is a small script (catalogue → root manifest → declared files → patch row names → npm reverse lookup); say the word and I will paste it here or turn it into a fixture.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions