DeepSeek Harness の依存関係の宣言:inject と組み込みサービス
前回までに単独で動作するプラグインを学びましたが、ほとんどのプラグインは他のプラグインの能力(ツールレジストリ、LLM、Agent)を利用する必要があります。
この章では、依存関係の宣言方法と、フレームワークが依存関係の準備が整ってから apply を実行することを保証する仕組みについて説明します。
サービスとは
サービスとは、プラグインが他のプラグインに公開する名前付きの能力です。
Harness では、tools、llm、agents はすべてサービスであり、ctx にマウントされています:ctx.tools、ctx.llm、ctx.agents。
| 組み込みサービス | 内容 | 典型的な用途 |
|---|---|---|
| ctx.tools | ツールランタイム(ToolRuntime) | ツールの登録・呼び出し |
| ctx.llm | 大規模言語モデルサービス(LLM) | アダプターの登録、モデルリクエストの送信 |
| ctx.agents | エージェントサービス(Agent) | サブエージェントの管理 |
inject で依存関係を宣言する
プラグインがあるサービスを必要とする場合は、そのサービスを inject 配列に記述します。
フレームワークは、これらのサービスの準備が整ってからプラグインをロードすることを保証します。
例
import type { Context } from '@deepseek-ai/cordis'
export const name = 'my-tool-plugin'
// 依存関係の宣言:tools サービスが必要
export const inject = ['tools']
export function apply(ctx: Context) {
// ここに到達した時点で、ctx.tools は必ず準備完了
ctx.tools.register(/* ... */)
}
apply が実行される時点で、inject で宣言されたサービスはすべて準備完了です。
これはフレームワークの保証であり、コード内で待機処理を行う必要はありません。
依存関係が未準備:プラグインは待機
サービスがまだ準備できていない場合、プラグインは実行されません。
その Fiber は PENDING 状態で停止し、サービスが現れるのを待ちます。
ライフサイクルにおいて、PENDING は「宣言済みだが、必要な依存関係が未準備」を意味します。
サービスが現れない場合、プラグインは待ち続け、エラーにはならず、apply も実行されません。
必須依存関係とオプション依存関係
inject で宣言するのは必須依存関係です:サービスが存在しない場合、プラグインはロードされません。
サービスが必須でない場合は、オプション依存関係を使用します:inject を書かず、使用箇所で ctx.get() を使って問い合わせます。
例
import type { Context } from '@deepseek-ai/cordis'
export function apply(ctx: Context) {
// metrics サービスは存在する場合も存在しない場合もある
const metrics = ctx.get('metrics')
// オプショナルチェーン:存在しなければスキップし、エラーにしない
metrics?.record('plugin_loaded', 1)
}
サービスが消えた場合の動作
実行中に必須サービスが消えた場合(例えば提供元がアンロードされた場合)、2つのことが発生します。
第一に、それに依存するプラグインは自動的に dispose(リソース解放)されます。
第二に、サービスが再び現れた場合、プラグインは自動的に再ロードされます。
これにより、プラグインが存在しなくなったサービスを呼び出すことを防ぎます。
ヒント:このルールは自動クリーンアップと連携します——アンロードは第8篇で説明した disposer をトリガーします。
まとめと自己テスト
inject で必須サービスを宣言し、フレームワークはサービスの準備が整ってから apply を実行することを保証します;オプションサービスは ctx.get() で問い合わせます。
その他の拡張1. inject 配列は何を宣言するものですか?
2. サービスが未準備の場合、プラグインはどのような状態ですか?
3. オプション依存関係はどのように宣言すればよいですか?