PerryLink/dsh-plugin-kit

dsh-plugin-kit

编写 DeepSeek Harness 插件的共享工具包,发布为 @perrylink/dsh-plugin-kit:可插拔的 Provider 注册表接缝、失败即拒绝的审批与会话事件门、共享的脱敏/计价/裁决模块,以及新插件骨架。

미분류approvalcordisdeepseek

@perrylink/dsh-plugin-kit

dsh plugin --profile <name> add @perrylink/dsh-plugin-kit

Shared zero-runtime-dependency toolkit for the PerryLink DSH plugin repositories. The per-project audit found 20+ plugins hand-rolling the same Provider seam and duplicating the same sanitize/pricing/verdict shapes, so this package extracts all of it — the pluggable Provider seam, the fail-closed approval and adaptive session-event gates, the mechanical verify scripts, and the shared sanitize/pricing/judge pure modules — into one ESM + TypeScript package.

Package name. This project publishes to npm as `@perrylink/dsh-plugin-kit`. The bare npm name dsh-plugin-kit belongs to a different, unrelated project — installing it does not install this package.
  • 1024 store channel: npm i -g dsh1024 once, then dsh1024 plugin --profile web add @perrylink/dsh-plugin-kit (counts toward the deepseek1024.com install ranking).

English | 简体中文 | Español | Português | हिन्दी

Shared zero-runtime-dependency toolkit for the PerryLink DSH plugin repositories. The per-project audit found 20+ plugins hand-rolling the same Provider seam and duplicating the same sanitize/pricing/verdict shapes, so this package extracts all of it — the pluggable Provider seam, the fail-closed approval and adaptive session-event gates, the mechanical verify scripts, and the shared sanitize/pricing/judge pure modules — into one ESM + TypeScript package.

Install & uninstall

As a library, install is pnpm add (see Quick start). The package also ships an intentionally empty dsh.bundle.patch layer (cordis.patch.yml), so it flows through the harness bundle channel when a profile wants the kit mounted as a package:

# npm channel (published releases)
dsh plugin --profile web add @perrylink/dsh-plugin-kit

# git channel (latest master)
dsh plugin --profile web add github:PerryLink/dsh-plugin-kit

Remove with:

pnpm remove @perrylink/dsh-plugin-kit

Nothing registers global state: uninstall is exactly the reverse of install.

What is dsh-plugin-kit?

Shared zero-runtime-dependency toolkit for the PerryLink DSH plugin repositories. The per-project audit found 20+ plugins hand-rolling the same Provider seam and duplicating the same sanitize/pricing/verdict shapes, so this package extracts all of it — the pluggable Provider seam, the fail-closed approval and adaptive session-event gates, the mechanical verify scripts, and the shared sanitize/pricing/judge pure modules — into one ESM + TypeScript package.

*Workflow overview: call → plugin → result. The examples below use the real command surface.*

Compatibility

  • DSH harness: the kit imports nothing from @deepseek-ai/* at runtime.

@deepseek-ai/cordis (^4.0.5-alpha.1), @deepseek-ai/schemastery (^3.18.5-alpha.1), and the @deepseek-ai/dsh-* packages are optional peer dependencies in the >=0.1.2-rc.1 =0.1.5-alpha.1 =0.1.6-0 =0.1.7-0 =0.2.0-0 =0.2.1-0 <0.3.0 band the PerryLink plugin repos share; they exist only for type interop. Verified 2026-09-11 against the dsh-v0.1.7-alpha.1 master checkout (full gate chain + profile install smoke), and re-verified 2026-10-05 against the dsh-v0.2.1-alpha.1 checkout (full gate chain + profile install smoke).

  • Node: ^22.19.0 || >=24.0.0, ESM only.
  • Wire compatibility: names and shapes mirror dsh-mask (sanitize),

dsh-budget (pricing), and dsh-auto-review (judge and the fallbackPolicy vocabulary), so migration is mechanical.

What you get

  • Zero runtime dependencies — the pure core (seam, gates, shared)

is browser-safe.

  • ESM + strict TypeScript — JSDoc contracts on every module; strict,

noUncheckedIndexedAccess, exactOptionalPropertyTypes.

  • Fail-closed and adaptive gates — approval never defaults to a grant;

session-event appends degrade gracefully on hosts that reject unknown event types.

  • A new-plugin skeleton — template/ with cordis.yml, a three-role

src/index.ts (Service Definition / Provider / Consumer), a test, and the shared Renovate preset.

Quick start

dsh plugin --profile web add github:PerryLink/dsh-plugin-kit

From npm:

pnpm add @perrylink/dsh-plugin-kit

From git (the prepare script builds lib/ using only production dependencies):

pnpm add github:PerryLink/dsh-plugin-kit

Replace a hand-rolled registry in one step:

import { ProviderRegistry } from '@perrylink/dsh-plugin-kit/seam'

const registry = new ProviderRegistry<Detector>({
  default: { name: 'regex', impl: new RegexDetector() },
})
ctx.effect(() => registry.register('ner', new NerDetector()))
const active = registry.use('ner') ?? registry.use()

Examples

These are the plugin's real entry points; install once, then call one.

Detailed example

Command

~~~sh import { createStripper } from '@perrylink/dsh-plugin-kit/shared' createStripper().strip('call 13800138000 or email a@b.com') ~~~

Output

~~~text call or email ~~~

*Observed from README.md:153 (shared sanitize); src/shared/sanitize.ts:268; test/sanitize.test.ts:8-19*

Failure branch

Input

~~~text const r = new ProviderRegistry(); r.register('openai', impl); r.register('openai', impl) // second call ~~~

Output

~~~text Error: Provider "openai" is already registered ~~~

*Observed from plugins/dsh-plugin-kit/lib/seam/provider.js:55-58; plugins/dsh-plugin-kit/test/seam.test.ts:27-30; plugins/dsh-plugin-kit/README.md:164*

Brief examples

  • applyFailClosed
  • parseVerdict

Configuration

No runtime configuration: the gates and helpers are pure functions. The only configuration surface is cordis.patch.yml, the bundle-patch layer shipped for harness profile composition; it mounts no plugin row (the kit is a library) and documents how consuming plugins add their own rows.

Tools & surfaces

Subpath · Purpose seam · ProviderRegistry — reversible, fail-loud named provider registry. gates · applyFailClosed; makeEventGate / maybeAppendSessionEvent / probeIgnorableAppend. shared · sanitize (Stripper, redactText, redactMapping, sanitizeText, sanitizeUrl), pricing (BUILTIN_PRICES, estimateUsageCost, tokenCarbon, latencyStats, formatMoney, formatTokens), judge (parseVerdict, VERDICT_SCHEMA, riskExceeds). verify · Mechanical CI gates (verify-license, verify-readme-languages, verify-seam) with a VerifyReport and a non-zero-exit CLI: node lib/verify/cli.js all . template/ · New-plugin skeleton (cordis.yml, three-role plugin, test, README, renovate.json5). root barrel · Re-exports all of the above.

Permissions & data

The kit performs no I/O, no network access, and no subprocess spawns on its own. Stripper keeps placeholder→original mappings in memory only, and stats()/redactMapping() never emit plaintext; a consumer that persists a mapping owns that decision and its storage permissions.

Security boundaries

  • sanitize/redact* are display hygiene, not a security boundary: they

reduce leakage into logs and results, they do not authenticate or authorize.

  • Approval gates are fail closed by default (rejected); the only grant path

is an explicit allow-once opt-in.

  • Session-event appends the host refuses are skipped, never retried in a way

that could break session resume.

  • Report vulnerabilities via GitHub Security Advisories — see SECURITY.md.

Known limitations

  • Hosts whose Session.append third argument is a SurfaceIntent

(0.1.2-rc.1) throw validateNext on the ignorable-envelope probe; the gate degrades to skip-unknown, so audit events are dropped (fail closed) rather than logged on those hosts.

  • 0.1.2-rc.1 (adapted 2026-09-02): the session envelope keeps its ignorable field for stored-log read compatibility only - Session.append still cannot stamp it, so audit-gate behavior is unchanged.
  • The kit ships no browser UI half; it is a library consumed by the Host (and

optionally Client) halves of other plugins.

Development

pnpm install
pnpm run typecheck        # tsc --noEmit
pnpm run typecheck:ci     # CI face: tsc -p tsconfig.ci.json --noEmit
pnpm test                 # vitest unit tests
pnpm run build            # emit lib/ + declarations (also run by prepare)
pnpm run verify:self-contained
pnpm run verify:artifacts

Topics

This repository is also the maintenance hub for the ecosystem: scripts/sync-peer-range.mjs re-pins the shared peer band across every repo in the target directory in one command, renovate/default.json5 is the shared Renovate preset every repo extends, .github/workflows/npm-publish.yml is a reusable tag-triggered publish workflow (needs only an NPM_TOKEN secret), and data/repos.json is the ecosystem registry consumed by the portal. Read that file for the roster; the per-plugin READMEs carry the collapsed list. See docs/ecosystem-tooling.md.

Keywords: dsh, dsh-plugin, deepseek-harness, deepseek, cordis, perrylink, provider, seam, approval, sanitize, pricing, judge.

Contributors

Maintained by PerryLink with contributions from the DSH plugin ecosystem.