feat(sdk): add dsh-plugin-fetch source + fetcher seam

Greenfield #2 "建插件" modules for the forthcoming `dsh-sdk create <source>`
command, in a new foundation-independent package so it touches none of the
dsh-scripts / dsh-helper / create-sdk hotspots the foundation refactor edits.

- `resolvePluginSource(spec)` parses `owner/repo[/subdir]#ref` (github) or
  `pkg@version` (npm) into a `PluginSource` discriminated union, failing loud on
  an ambiguous or malformed spec.
- `PluginFetcher<S>` seam + `fetchPlugin` tag dispatch returning a common
  `FetchedPlugin` (temp dir + immutable provenance).
- `GigetFetcher` (github) over @bluwy/giget-core: resolve `#ref` to a commit SHA
  first, download that SHA; provenance pins the SHA. Chosen over unjs/giget for
  its single runtime dep and absent install/action surface.
- `PacoteFetcher` (npm) over pacote: resolve the manifest, then extract the
  tarball verified against its registry integrity. Registry-only is enforced by
  the source resolver; extract runs no lifecycle scripts.
- Branded `CommitSha`/`Integrity`; network + temp-dir boundaries are injected so
  the logic is unit-tested at 100% per-file coverage without network.

Wiring (package.json pin, cordis.yml via ProjectEditSession with a confirmed
diff, install --ignore-scripts) and the launcher command registration land
later with the foundation.
This commit is contained in:
imccyu
2026-07-17 13:20:34 +08:00
parent dcd886798f
commit 825a63ab01
22 changed files with 1974 additions and 3 deletions

View File

@@ -138,6 +138,7 @@ flowchart TD
end
subgraph group_sdk["packages/sdk"]
pkg_helper["helper"]
pkg_plugin_fetch["plugin-fetch"]
pkg_scripts["scripts"]
end
subgraph group_tasks["packages/tasks"]
@@ -152,6 +153,7 @@ flowchart TD
pkg_llm --> pkg_brand
pkg_code_runtime_worker --> pkg_code_runtime
pkg_helper --> pkg_brand
pkg_plugin_fetch --> pkg_brand
pkg_scripts --> pkg_app_boot
pkg_llm_deepseek --> pkg_llm
pkg_llm_pi_ai --> pkg_llm
@@ -442,6 +444,7 @@ flowchart TD
| [`llm`](../packages/llm/llm) | `llm` | [`brand`](../packages/util/brand) |
| [`code-runtime-worker`](../packages/code-runtime/code-runtime-worker) | `code-runtime` | [`code-runtime`](../packages/code-runtime/code-runtime) |
| [`helper`](../packages/sdk/helper) | `sdk` | [`brand`](../packages/util/brand) |
| [`plugin-fetch`](../packages/sdk/plugin-fetch) | `sdk` | [`brand`](../packages/util/brand) |
| [`scripts`](../packages/sdk/scripts) | `sdk` | [`app-boot`](../packages/ui/app-boot) |
| [`llm-deepseek`](../packages/llm/llm-deepseek) | `llm` | [`llm`](../packages/llm/llm) |
| [`llm-pi-ai`](../packages/llm/llm-pi-ai) | `llm` | [`llm`](../packages/llm/llm) |