Files
deepseek-harness/packages/skill/skill

@deepseek-ai/dsh-skill

English | 中文

Pure agent skill provider registry.

This package owns the ctx.skills interface. It does not know whether skills come from local files, embedded plugin data, HTTP, or another backend; providers register those sources with ctx.skills.registerProvider(...). The shipped local implementation is @deepseek-ai/dsh-skill-local.

Service: SkillService (ctx key: skills)

Public API

  • ctx.skills.registerProvider(provider): () => void Registers a readonly provider by unique provider.name. Duplicate provider names throw, and runtime is reserved for ctx.skills.register(...). The registry borrows the provider object and invokes its methods directly. The registration is effect-scoped and HMR-safe, and the exact Cordis disposer supports ordered composite teardown.
  • ctx.skills.invalidateProvider(provider): void Marks one exact live provider dirty and clears completed catalog caches. Calls from a disposed or replaced provider instance are no-ops, so late watcher callbacks cannot invalidate its replacement.
  • ctx.skills.snapshot({ cwd?, signal? }) Returns { skills, complete }. complete is false when any provider failed transiently; incomplete observations are never cached, so a model-facing consumer can retain its last-good catalog and retry at the next request boundary.
  • ctx.skills.list({ cwd?, signal? }) Borrows the readonly lookup options, then returns model-invocable summaries for the current workspace, merged across providers and sorted by name.
  • ctx.skills.get(name, { cwd?, signal? }) Uses the same readonly options and winning candidate for discovery and loading, rechecks cancellation after discovery or a cache hit, races provider loading against the signal, validates the loaded definition, then returns it, including disabled-for-model skills.
  • ctx.skills.register(skill): () => void Registers a readonly runtime embedded skill, adding provider: "runtime" when omitted. Same-name runtime registrations are first-wins: a duplicate logs a warning and gets a no-op disposer. Successful registrations return the exact Cordis disposer for ordered composite teardown.

Events

  • skills/change is an unfiltered invalidation notification emitted after a provider or runtime contribution is registered or disposed and after invalidateProvider() accepts an exact live provider. It carries no catalog or diff: each consumer refetches snapshot() with its own lookup options. Listener throws and rejected promises are logged and cannot veto the registry mutation or starve later listeners.

Config

Field Default Meaning
collectCacheMaxEntries 128 Maximum completed cwd/provider catalogs kept in memory.

Provider Contract

A provider registers synchronously and performs remote setup, authentication, and discovery in its awaited list(options) call. Provider objects, lookup options, candidates, and definitions are borrowed readonly rather than cloned or rebound. Providers should honor options.signal; the registry also stops awaiting uncooperative discovery or loading after cancellation.

The registry validates candidates before caching and definitions before returning them. The winning provider receives the same candidate and opaque locator it returned from list(), allowing backend-specific file, URL, id, or version handles. Callers and providers must preserve the readonly contract.

Contract violations fail fast. A rejected provider list() is treated as a transient source failure: its entries are omitted from that observation, complete is false, and the result is not cached. A provider or runtime revision change discards an in-flight result and retries before returning. Duplicate names resolve by rank, provider registration order, then provider-local order. Summaries are sorted by skill name.

Definitions remain progressively loaded. get() asks the winning provider for the body on every call rather than caching it in this registry. If the returned definition has a different name from the selected candidate, the stale selection is rejected and that exact provider is invalidated so the next snapshot rediscovers its catalog.

Runtime Skills

ctx.skills.register(...) is a convenience for embedded runtime skills. Runtime skills use rank 250: project providers can override them, while they override the shipped local provider's custom and user roots. Runtime definitions and nested resource metadata are borrowed readonly; the service only materializes the top-level definition needed to supply the default provider. Registration is first-wins within runtime contributions, so a duplicate contribution cannot remove the active one through its disposer.

Consumer boundary

The registry does not render model guidance or register model-facing tools. @deepseek-ai/dsh-tool-skill consumes ctx.skills to provide the session-prefix catalog and skill tool, so providers remain independent of the model surface.

Model Experience

Indirectly, through dsh-tool-skill, which renders provider summaries into the initial session prefix or durable replacement catalog messages and loaded instructions into retained tool results.

KV Cache effect

No direct prompt effect. The named consumer owns initial prefix composition and append-only catalog replacements after invalidation.

Known Limitations and Deferred Work

  • Invalidation is provider-driven — the registry has no TTL and cannot infer that an arbitrary remote source changed; each mutable provider must call invalidateProvider() from its own observation mechanism.
  • Providers are queried sequentially — one slow cooperative provider delays every provider registered after it; cancellation stops the caller's wait but cannot terminate work an uncooperative provider keeps running.
  • An incomplete snapshot omits the failing provider in that observation — the registry reports complete: false, but it does not own a last-good catalog or a per-provider diagnostic; consumers choose whether to retain earlier state.
  • Duplicate resolution is first-wins — later lower-priority candidates are logged and hidden; there is no API to inspect all shadowed definitions.