プラグインの作り方
プラグインとは、以下を行う任意のプロセスです:
- RabbitMQに接続し、
datacore.resource-lifecycleトピックエクスチェンジ上のルーティングキーpipeline.step.dispatched.<your-plugin-id>にキューをバインドする。 - 各メッセージを受け取るたびに処理を行い、コールバックする:
POST {CORE_API_URL}/api/v1/internal/artifacts/{resource_id}。 - それ以外は何もしません。この1つのコールバックを除いてコアを同期的に呼び出すことはなく、他の プラグインと直接やり取りすることもありません (プラグインの分離)。
同梱されている4つのサンプル (plugins/markdown-summarizer、plugins/vector-embedder、 plugins/qdrant-register、plugins/github-profile-scanner) はそれぞれ約100〜150行のTypeScriptで、 最良のリファレンスです — 作ろうとしているものに最も近いものをコピーしてください。
受け取るディスパッチメッセージ
{
"event": "PIPELINE_STEP_DISPATCHED",
"resource_id": "uuid",
"occurred_at": "ISO-8601",
"payload": {
"pipeline_id": "uuid",
"step_position": 0,
"plugin_id": "your-plugin-id",
"attempt_count": 0,
"source_uri": "s3://bucket/key or https://...",
"upstream_artifacts": [{ "type": "SUMMARY", "external_ref": "...", "producing_plugin_id": "..." }]
}
}upstream_artifacts は、パイプライン内の前段のステップが生成したものを提供します。ステップが それらを入力として必要とする場合に使えます (例えば Vector Embedder プラグインは、生のソースを再取得 するのではなく Markdown Summarizer の出力を埋め込みます。Qdrant Register は Vector Embedder が 計算したばかりのベクトルを読み取ります)。
送信すべきコールバック
// success
{ "plugin_id": "your-plugin-id", "step_position": 0, "outcome": "SUCCESS", "artifact": { "type": "SUMMARY", "external_ref": "s3://bucket/key" } }
// failure (Core will retry per that step's configured policy, or mark the resource FAILED once exhausted)
{ "plugin_id": "your-plugin-id", "step_position": 0, "outcome": "FAILURE", "error": "a specific, human-readable reason" }artifact.type は組み込み型 (VECTOR、GRAPH、SUMMARY) のいずれか、またはプラグインが定義する 新しい型にできます — 新しい成果物タイプの追加は、コアウェアハウス側でのPrismaスキーマの1行変更と マイグレーションだけで済みます (実例として github-profile-scanner の REPO_ANALYSIS 型を参照)。
external_ref は実際の内容を保存した場所への参照です — コアがコールバック経由で生の成果物バイト列を 送るよう求めることは決してありません。出力は自分のバケット/コレクションに保存するか (コアと同居させて デプロイする場合はコアのMinIO/Qdrantを再利用しても構いません)、単にロケーター文字列を報告してください。
成果物の内容が表示される仕組み
成果物をWeb UIで表示可能にし (成果物チップ→「結果を表示」モーダル経由)、削除時にクリーンアップ されるようにしたい場合、コアは external_ref からその内容を取得・削除する方法を知る必要があります。 標準では、これは s3:// プレフィックス (MinIOから取得/削除) か qdrant:// プレフィックス (Qdrantから 取得/削除) のいずれかを意味します — backend/src/routes/resources.ts を参照してください。この いずれかの形式で external_ref を報告すれば、追加のコードなしで表示とクリーンアップがそのまま 機能します。
プラグインとしてのストレージ
別のストレージバックエンド (Pinecone、Weaviate、別のQdrant/S3互換インスタンスなど何でも) は、 処理用プラグインに後付けされる特別なモードではなく、単なる別のプラグインを通常のパイプライン ステップとして連結したものです。qdrant-register が実例です:
vector-embedderが埋め込みを計算し、生のベクトルを共有オブジェクトストア内の一時的な場所 (s3://bucket/vectors-pending/{resource_id}.json) に書き込み、それを中間的なVECTOR成果物 として報告します。- 次のステップである
qdrant-registerがupstream_artifacts経由でその上流成果物を読み取り、 ベクトルをQdrantに登録し、一時オブジェクトを削除して、external_ref: qdrant://collection/point-idを持つ最終的なVECTOR成果物を報告します — 中間のものを上書きします (Artifactは(resource_id, type)ごとに一意なので、これは特別な処理ではなく通常のアップサートです)。
コア側に新しいコードは一切必要ありません — 最終的な成果物は完全に通常の qdrant:// 参照であり、 他のものとまったく同じ組み込みロジックで表示・クリーンアップされます。別のバックエンド向けに自分 自身のストレージプラグインを書くということは、同じ2段階の形 — 中間成果物を引き渡す計算/生成ステップ と、実際にあなたのバックエンドへの書き込み (と削除) を担当する登録ステップ — に従うということです。
設定可能にする: プラグインの config
接続URLをハードコードすると、変更のたびに再デプロイが必要になります。代わりに、プラグインは 自身の config — Pluginレコードに保存された任意のJSONオブジェクトで、PUT /plugins/{id}/config または Web UI上のカードの設定ボタンから設定されます — を読み取ることができます (REST APIリファレンス を参照):
// qdrant-register は自身のQdrant URLを次のように解決します:
const res = await fetch(`${CORE_API_URL}/api/v1/plugins/${PLUGIN_ID}`);
const plugin = await res.json();
const qdrantUrl = plugin.config?.qdrant_url || process.env.QDRANT_URL || 'http://localhost:6333';config の形を定義し解釈するのは完全にプラグイン次第です — コアはあなたが PUT した任意のJSON オブジェクトを保存して返すだけです。将来の「Pinecone Register」プラグインは代わりに config.api_key/config.index_name を参照するかもしれません — コアはその違いを知る必要も 気にする必要もありません。
パッケージ化とデプロイ
各プラグインは独自のDockerfile + docker-compose.yml サービスであり、独自の環境変数 (RABBITMQ_URL、CORE_API_URL、PLUGIN_ID、および必要なストレージ認証情報) を持ちます。この リポジトリに存在する必要はありません — プラグインは、RabbitMQブローカーとコアAPIに到達できる 限り、完全に独立してビルド・ホスト・デプロイできます。
他の人と共有する
プラグインが動作するようになったら、コミュニティプラグインレジストリ に 掲載して、他のDataCore運用者が発見できるようにできます。これはメタデータとリポジトリへのリンクを 投稿するものであり、コード自体ではありません — 興味を持った人は自分でリポジトリをクローンし、 レビューし、自分でデプロイします。