CommunitySchreiben & Editierengithub.com

dsh Plugin-Entwicklung

AI-Skill zur Entwicklung von DeepSeek Harness (dsh) Plugins — einem Cordis-basierten Agenten-Framework. Unterstützt die Erstellung und Veröffentlichung von Tools, Services, LLM-Adaptern, Event-Listenern und mehr.

Was ist dsh Plugin-Entwicklung?

Dieser Skill befähigt KI-Agenten, Plugins für das DeepSeek Harness (dsh) Framework zu entwickeln, das auf Cordis basiert. Er deckt den gesamten Lebenszyklus ab: von der grundlegenden Plugin-Struktur (Funktion, Objekt, Klasse) über die Definition von Dependencies, Tools mit JSON-Schema-Validierung, Konfiguration mit Schemastery, Services mit Isolation, Events mit fünf verschiedenen Modi, LLM-Adapter mit Streaming-Support bis hin zur Veröffentlichung als npm-Paket mit dsh.bundle-Manifest. Besondere Stärken sind das automatische Aufräumen von Ressourcen durch den Effekt-Mechanismus, die klaren Fiber-Zustände (PENDING, LOADING, ACTIVE, FAILED, UNLOADING, DISPOSED) und die Hot Module Replacement (HMR) für schnelle Iterationen. Der Skill unterstützt Entwickler dabei, saubere, wartbare Plugins nach dem Drei-Schichten-Design (Definition → Provider → Consumer) zu bauen und diese über `cordis.yml`-Patches oder Distributionen bereitzustellen.

Funktioniert mit~Claude Code~Codex CLI~Cursor
npx skills add TrueHOOHA/dsh-plugin-dev-skill

Installed? Explore more Schreiben & Editieren skills: steipete/notion, langchain-ai/langchain, bytedance/podcast-generation · View all 6 →

In Ihrer bevorzugten KI fragen

Öffnet einen neuen Chat, in dem dieser Agent-Skill bereits geladen ist.

Dokumentation

Was macht dsh Plugin-Entwicklung?

Entwickeln Sie Plugins für DeepSeek Harness (dsh), ein Cordis-basiertes Agenten-Framework. Plugins sind TypeScript-Module, die apply(ctx: Context) exportieren und über cordis.yml komponiert werden.

Kurzreferenz

Plugin-Struktur

import type { Context } from '@deepseek-ai/cordis'
export const name = 'my-plugin'
export function apply(ctx: Context) { /* Fähigkeiten registrieren */ }

Drei Formen: Funktion (Standard), Objekt ({ name, inject, apply }), Klasse (extends Service — nur verwenden, wenn ein Service für andere Plugins bereitgestellt wird).

Abhängigkeiten: export const inject = ['tools', 'llm'] — das Framework hält das Plugin im Zustand PENDING, bis alle injizierten Services bereit sind.

Automatische Bereinigung: Alles, was über ctx registriert wird, ist ein Effekt — beim Entladen wird automatisch aufgeräumt. Für benutzerdefinierte Ressourcen (Timer, Verbindungen) in ctx.effect(() => { ... return () => cleanup }) kapseln.

Kind-Plugins: const fiber = ctx.plugin(childPlugin) — Kinder erben den Elternkontext; await fiber.dispose() entlädt rekursiv.

Fiber-Zustände

PENDING → LOADING → ACTIVE → UNLOADING → DISPOSED
                 ↘ FAILED

PENDING → fehlende Service-Abhängigkeit. FAILED → apply hat einen Fehler geworfen oder die Konfigurationsvalidierung ist fehlgeschlagen. Wenn ein Service zur Laufzeit verschwindet, werden Abhängige automatisch entsorgt.

Tools

import { defineTool } from '@deepseek-ai/dsh-tools'
export const inject = ['tools']
export function apply(ctx: Context) {
  ctx.tools.register(defineTool({
    name: 'greet', description: '...',
    parameters: { name: { type: 'string', required: true } },
    output: { schema: { type: 'string' }, render: (_args, value) => [{ type: 'text', text: value }] },
    async execute(args) { return `Hello, ${args.name}!` },
  }))
}

defineTool konvertiert Parameter in JSON Schema, validiert Argumente und hebt die Registrierung beim Entladen automatisch auf. Siehe references/basic/tool.md für Details.

Konfiguration

import Schema from '@deepseek-ai/schemastery'
export interface Config { greeting: string; maxRetries: number }
export const Config: Schema<Config> = Schema.object({
  greeting: Schema.string().default('Hello'),
  maxRetries: Schema.number().default(3),
})
export function apply(ctx: Context, config: Config) { /* validierte Konfiguration */ }

Es MÜSSEN sowohl interface Config als auch const Config: Schema<Config> exportiert werden. Ungültige Konfiguration → Zustand FAILED mit klarem Fehler. Verwenden Sie !!js in YAML für dynamische Werte: config: { apiKey: !!js process.env.API_KEY }. Siehe references/basic/config.md.

Services

Bereitstellen: class extends Service { constructor(ctx) { super(ctx, 'name') } }

  • declare module '@deepseek-ai/cordis' { interface Context { name: NameService } }

Konsumieren: export const inject = ['name'] → ctx.name.method().

Optional: ctx.get('name') → gibt undefined zurück, wenn nicht vorhanden.

Service-Isolation: group: true + isolate: { shell: true } gibt jeder Gruppe eine eigene Anbieterinstanz. Siehe references/framework/service.md.

Events

ModusAufrufVerwendung
emitctx.emit(n, ...args)Synchrone Broadcast, Rückgabewerte ignorieren
parallelawait ctx.parallel(n, ...args)Parallele Listener
serialawait ctx.serial(n, ...args)Sequentiell, erster nicht-null gewinnt
bailctx.bail(n, ...args)Synchron seriell
waterfallctx.waterfall(n, ...args, next)Middleware-Kette

Waterfall-Listener müssen next() aufrufen, es sei denn, sie beenden die Kette absichtlich vorzeitig. Wichtige Harness-Events: agent/step, tools/result, session/event. Siehe references/framework/events.md.

LLM-Adapter

class MyAdapter extends LlmAdapter {
  async *stream(options: GenerateOptions): AsyncIterable<StreamChunk> {
    // Konvertieren → Provider-API → yield StreamChunk
  }
}
ctx.llm.registerAdapter(['my-provider'], adapter)

StreamChunk-Reihenfolge pro Block: block-start → text-delta/tool-call-delta → block-end → usage → finish. Werfen Sie LlmError mit stabilen Codes. Siehe references/practice/llm-adapter.md.

Drei-Schichten-Fähigkeitsdesign

Definition (Service-Abstract-Klasse) → Anbieter (implementiert) → Konsument (Werkzeug)

Alle drei teilen denselben Servicenamen über inject. Nur in separate Pakete aufteilen, wenn die Rollen unabhängig voneinander weiterentwickelt werden müssen. Siehe references/practice/index.md.

cordis.yml / Bundles

Lokale Entwicklung: --patch ./cordis.patch.yml

- insert:
    - id: my-plugin
      name: '/absolute/path/to/src/my-plugin.ts'
      config: { greeting: 'Hi' }

Verteilung: npm-Paket mit dsh.bundle-Manifest + cordis.patch.yml. Installation: dsh plugin --profile demo add ./hello-plugin. Ebenen-Reihenfolge: Profil-Bundles → Profil-Patch → Home-Patch → --patch-Overlays. Spätere Ebenen gewinnen zeilenweise (kein Deep Merge). Siehe references/basic/publish.md.

HMR

Laden Sie @deepseek-ai/cordis-plugin-hmr + @deepseek-ai/cordis-plugin-logger-console

  • @deepseek-ai/cordis-plugin-timer, um bei Dateiänderungen automatisch neu zu laden.

Diagnose von PENDING

import { FiberState, type Context } from '@deepseek-ai/cordis'
for (const fiber of ctx.registry.values().flatMap(r => r.fibers))
  if (fiber.state === FiberState.PENDING)
    console.log(`${fiber.name} is PENDING`)

Referenzdokumente

Ausführliche Anleitungen im Verzeichnis references/:

PfadAbgedeckt
references/basic/Erstes Plugin, Werkzeuge, Konfiguration, Veröffentlichung
references/framework/Lebenszyklus, Services, Events
references/practice/Drei-Schichten-Design, LLM-Adapter
references/cordis-tutorial/Schrittweises Cordis-Framework-Tutorial

Verwandte Skills