Community写作与编辑github.com

TrueHOOHA/dsh-plugin-dev-skill

AI Skill for developing DeepSeek Harness (dsh) plugins — Cordis-based agent framework. 辅助开发 dsh 插件的 AI 技能,覆盖 tool、service、LLM adapter、event listener 等能力的创建与发布。

dsh-plugin-dev-skill 是什么?

dsh-plugin-dev-skill is a Claude Code agent skill that aI Skill for developing DeepSeek Harness (dsh) plugins — Cordis-based agent framework. 辅助开发 dsh 插件的 AI 技能,覆盖 tool、service、LLM adapter、event listener 等能力的创建与发布。.

兼容平台~Claude Code~Codex CLI~Cursor
npx skills add TrueHOOHA/dsh-plugin-dev-skill

Installed? Explore more 写作与编辑 skills: steipete/notion, affaan-m/seo, affaan-m/brand-voice · View all 6 →

在你喜欢的 AI 中提问

打开一个已预加载此 Agent Skill 的新对话。

文档

dsh Plugin Development

Develop plugins for DeepSeek Harness (dsh), a Cordis-based agent framework. Plugins are TypeScript modules exporting apply(ctx: Context), composed via cordis.yml.

Quick Reference

Plugin Structure

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

Three forms: function (default), object ({ name, inject, apply }), class (extends Service — use only when providing a service to other plugins).

Dependencies: export const inject = ['tools', 'llm'] — framework keeps plugin PENDING until all injected services are ready.

Auto-cleanup: Everything registered through ctx is an effect — unload automatically cleans up. For custom resources (timers, connections), wrap in ctx.effect(() => { ... return () => cleanup }).

Child plugins: const fiber = ctx.plugin(childPlugin) — children inherit parent context; await fiber.dispose() unloads recursively.

Fiber States

PENDING → LOADING → ACTIVE → UNLOADING → DISPOSED
                 ↘ FAILED

PENDING → missing service dependency. FAILEDapply threw or config validation failed. Service disappearing at runtime auto-disposes dependents.

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 converts parameters to JSON Schema, validates args, and auto-unregisters on unload. See references/basic/tool.md for details.

Configuration

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) { /* validated config */ }

Must export BOTH interface Config AND const Config: Schema<Config>. Invalid config → FAILED state with clear error. Use !!js in YAML for dynamic values: config: { apiKey: !!js process.env.API_KEY }. See references/basic/config.md.

Services

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

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

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

Optional: ctx.get('name') → returns undefined when absent.

Service isolation: group: true + isolate: { shell: true } gives each group its own provider instance. See references/framework/service.md.

Events

ModeCallUse
emitctx.emit(n, ...args)Sync broadcast, ignore returns
parallelawait ctx.parallel(n, ...args)Concurrent listeners
serialawait ctx.serial(n, ...args)Sequential, first non-null wins
bailctx.bail(n, ...args)Sync serial
waterfallctx.waterfall(n, ...args, next)Middleware chain

Waterfall listeners must call next() unless intentionally short-circuiting. Key harness events: agent/step, tools/result, session/event. See references/framework/events.md.

LLM Adapters

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

StreamChunk order per block: block-starttext-delta/tool-call-deltablock-endusagefinish. Throw LlmError with stable codes. See references/practice/llm-adapter.md.

Three-Layer Capability Design

Definition (Service abstract class) → Provider (implements) → Consumer (tool)

All three share the same service name via inject. Only split into separate packages when roles need independent evolution. See references/practice/index.md.

cordis.yml / Bundles

Local dev: --patch ./cordis.patch.yml

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

Distribution: npm package with dsh.bundle manifest + cordis.patch.yml. Install: dsh plugin --profile demo add ./hello-plugin. Layer order: profile bundles → profile patch → home patch → --patch overlays. Later layers win by row (no deep merge). See references/basic/publish.md.

HMR

Load @deepseek-ai/cordis-plugin-hmr + @deepseek-ai/cordis-plugin-logger-console

  • @deepseek-ai/cordis-plugin-timer to auto-reload on file save.

Diagnosing 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`)

Reference Docs

Detailed guides in the references/ directory:

PathCovers
references/basic/First plugin, tools, config, publishing
references/framework/Lifecycle, services, events
references/practice/Three-layer design, LLM adapters
references/cordis-tutorial/Step-by-step Cordis framework tutorial

相关技能

steipete/notion

Notion CLI/API for pages, Markdown content, data sources, files, comments, search, Workers, and raw API calls.

community

affaan-m/seo

Audit, plan, and implement SEO improvements across technical SEO, on-page optimization, structured data, Core Web Vitals, and content strategy. Use when the user wants better search visibility, SEO remediation, schema markup, sitemap/robots work, or keyword mapping.

community

affaan-m/brand-voice

Build a source-derived writing style profile from real posts, essays, launch notes, docs, or site copy, then reuse that profile across content, outreach, and social workflows. Use when the user wants voice consistency without generic AI writing tropes.

community

affaan-m/crosspost

Multi-platform content distribution across X, LinkedIn, Threads, and Bluesky. Adapts content per platform using content-engine patterns. Never posts identical content cross-platform. Use when the user wants to distribute content across social platforms.

community

affaan-m/x-api

X/Twitter API integration for posting tweets, threads, reading timelines, search, and analytics. Covers OAuth auth patterns, rate limits, and platform-native content posting. Use when the user wants to interact with X programmatically.

community

affaan-m/content-engine

Create platform-native content systems for X, LinkedIn, TikTok, YouTube, newsletters, and repurposed multi-platform campaigns. Use when the user wants social posts, threads, scripts, content calendars, or one source asset adapted cleanly across platforms.

community