Communityライティング&編集github.com

dsh プラグイン開発スキル

DeepSeek Harness (dsh) 向けプラグイン開発のためのAIスキルです。Cordisベースのエージェントフレームワークにおける tool、service、LLM adapter、event listener などの機能を作成・公開する方法を解説します。

dsh プラグイン開発スキル とは?

このスキルは、DeepSeek Harness (dsh) プラグインの開発を支援するために設計されたAIアシスタントスキルです。dsh は Cordis ベースのエージェントフレームワークであり、プラグインは TypeScript モジュールとして `apply(ctx: Context)` をエクスポートし、`cordis.yml` で構成します。スキルでは、プラグインの基本構造(関数形式、オブジェクト形式、クラス形式)、依存関係の注入(`inject`)、自動クリーンアップ(`ctx.effect`)、子プラグインの管理、ファイバー状態(PENDING→LOADING→ACTIVE→UNLOADING→DISPOSED/FAILED)について詳細に説明します。また、ツール定義(`defineTool`)、設定スキーマ(Schemastery)、サービス提供・消費、イベントシステム(emit/parallel/serial/bail/waterfall)、LLMアダプター実装、3層能力設計(定義→プロバイダー→コンシューマー)、`cordis.yml` / バンドルによる配布、HMR(ホットモジュールリロード)など、実践的な開発パターンを網羅しています。プラットフォームは dsh および Cordis エコシステムを対象とし、Reference Docs へのリンクも充実しています。

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

Installed? Explore more ライティング&編集 skills: steipete/notion, langchain-ai/langchain, bytedance/podcast-generation · View all 6 →

お気に入りのAIに質問する

このエージェントスキルを事前に読み込んだ状態で新しいチャットを開きます。

ドキュメント

dsh プラグイン開発

DeepSeek Harness(dsh)向けプラグインを開発します。dsh は Cordis ベースのエージェントフレームワークです。プラグインは apply(ctx: Context) をエクスポートする TypeScript モジュールであり、cordis.yml で構成します。

クイックリファレンス

プラグイン構造

import type { Context } from '@deepseek-ai/cordis'
export const name = 'my-plugin'
export function apply(ctx: Context) { /* 機能を登録 */ }

3つの形式: 関数(デフォルト)、オブジェクト({ name, inject, apply })、クラス(extends Service — 他のプラグインにサービスを提供する場合のみ使用)。

依存関係: export const inject = ['tools', 'llm'] — フレームワークは、注入されたすべてのサービスが準備できるまでプラグインを PENDING 状態に保ちます。

自動クリーンアップ: ctx を通じて登録されたものはすべてエフェクトです — アンロード時に自動的にクリーンアップされます。カスタムリソース(タイマー、接続)の場合は、ctx.effect(() => { ... return () => cleanup }) でラップします。

子プラグイン: const fiber = ctx.plugin(childPlugin) — 子は親コンテキストを継承します。await fiber.dispose() で再帰的にアンロードします。

ファイバー状態

PENDING → LOADING → ACTIVE → UNLOADING → DISPOSED
                 ↘ FAILED

PENDING — サービス依存関係が不足。FAILED — apply が例外をスローしたか、設定の検証に失敗。実行時にサービスが消失すると、依存するプラグインは自動的に破棄されます。

ツール

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 はパラメータを JSON Schema に変換し、引数を検証し、アンロード時に自動登録解除します。詳細は references/basic/tool.md を参照してください。

設定

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) { /* 検証済み設定 */ }

interface Config と const Config: Schema<Config> の両方をエクスポートする必要があります。設定が無効な場合 → 明確なエラーとともに FAILED 状態になります。YAML で動的な値を使用するには !!js を使います: config: { apiKey: !!js process.env.API_KEY }。詳細は references/basic/config.md を参照してください。

サービス

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

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

消費: export const inject = ['name'] → ctx.name.method()。

オプション: ctx.get('name') → 存在しない場合は undefined を返します。

サービスの分離: group: true + isolate: { shell: true } により、各グループに独自のプロバイダーインスタンスが与えられます。詳細は references/framework/service.md を参照してください。

イベント

モード呼び出し用途
emitctx.emit(n, ...args)同期的ブロードキャスト、戻り値を無視
parallelawait ctx.parallel(n, ...args)並行リスナー
serialawait ctx.serial(n, ...args)逐次、最初の非 null が優先
bailctx.bail(n, ...args)同期的シリアル
waterfallctx.waterfall(n, ...args, next)ミドルウェアチェーン

Waterfall リスナーは、意図的にショートサーキットしない限り 必ず next() を呼び出す必要があります。主要なハーネスイベント: agent/step、tools/result、session/event。詳細は references/framework/events.md を参照してください。

LLM アダプター

class MyAdapter extends LlmAdapter {
  async *stream(options: GenerateOptions): AsyncIterable<StreamChunk> {
    // 変換 → プロバイダーAPI → StreamChunk を yield
  }
}
ctx.llm.registerAdapter(['my-provider'], adapter)

ブロックごとの StreamChunk 順序: block-start → text-delta / tool-call-delta → block-end → usage → finish。安定したコードで LlmError をスローします。詳細は references/practice/llm-adapter.md を参照してください。

3層能力設計

定義 (Service 抽象クラス) → プロバイダー (実装) → コンシューマー (ツール)

3つすべてが inject を介して同じサービス名を共有します。各層が独立した進化を必要とする場合にのみ、別々のパッケージに分割します。詳細は references/practice/index.md を参照してください。

cordis.yml / バンドル

ローカル開発: --patch ./cordis.patch.yml

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

配布: dsh.bundle マニフェスト + cordis.patch.yml を含む npm パッケージ。インストール: dsh plugin --profile demo add ./hello-plugin。 層の順序: プロファイルバンドル → プロファイルパッチ → ホームパッチ → --patch オーバーレイ。後方の層が行単位で優先されます(深いマージは行われません)。 詳細は references/basic/publish.md を参照してください。

HMR

@deepseek-ai/cordis-plugin-hmr + @deepseek-ai/cordis-plugin-logger-console + @deepseek-ai/cordis-plugin-timer をロードすると、ファイル保存時に自動リロードが行われます。

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

リファレンスドキュメント

references/ ディレクトリ内の詳細ガイド:

パスカバー内容
references/basic/最初のプラグイン、ツール、設定、公開
references/framework/ライフサイクル、サービス、イベント
references/practice/3層設計、LLM アダプター
references/cordis-tutorial/Cordis フレームワークのステップバイステップチュートリアル

関連スキル