型付きプラグイン設定への移行
型付きインスタンス設定は、オペレーター設定を読み取る 1.0 未満のすべてのプラグインにとって、破壊的変更です。このページは、プラグイン作成者とオペレーター向けの移行資料です。何が壊れるのか、その理由、パッケージを修正するための正確な手順を説明します。
ここで説明する動作は、crates/zeroclaw-plugins/src/config.rs、crates/zeroclaw-plugins/src/instance.rs、およびcrates/zeroclaw-plugins/src/host.rsにある受け入れ経路を基に確認されています。
リリース判定
この機能には強制適用が組み込まれています。互換性シムも猶予期間もオプトアウトフラグもありません。プラグインは 1.0 前の実験的なインターフェースであるため、プロジェクトは恒久的に弱い設定経路を維持するのではなく、この破壊的変更を受け入れています。型なしフォールバックでは、ホストが型付け、名前付け、または上限設定できない値をゲストに渡すことになり、これはまさにこの機能が塞ぐ抜け穴です。
移行されないパッケージは検出されなくなります。暗黙的にダウングレードされることはなく、部分的な設定がゲストコードに渡ることもありません。
何が壊れるか
独立した 3 つの項目:
config_schemaなしでconfig_readを要求するマニフェストは、検出もインストールもされなくなりました。 この2つは必要十分条件の関係にあり、権限なしのスキーマも同様に無効です。- パッケージ名またはバインディング名をキーとする設定エントリは、参照されなくなりました。 オペレーター値は、パッケージ、ケイパビリティ、バインディングから導出される完全なインスタンスキーの下に格納されるようになりました。
- ゲストには文字列のマップではなく、型付き JSON が渡されます。 これまで文字列を自分で解析していたゲストは、実際のブール値、数値、配列、オブジェクトを取得するようになりました。
ホストにスキーマが必要な理由
オペレーターの値はシークレットとしてマークされた文字列マップに保存され、保存時に暗号化されます。また、ゲストは信頼されていないサードパーティコードです。宣言されたコントラクトがなければ、ホストはゲストの起動前に答える必要がある2つの問いに答えられません。このパッケージが受け取ることを許可されているキーはどれか、そして各値の型は何か、という問いです。WIT ワールドは固定されており、すべてのプラグインで共有されるため、パッケージごとの設定型を ABI に含めることはできません。コントラクトを宣言できる場所はマニフェストだけであり、additionalProperties = false と明示的な properties マップによって、config_read グラントが列挙可能な対象を持つものになります。
作成手順
1. スキーマを宣言する
プラグインが読み取るキーだけを過不足なく含む、閉じた Draft 2020-12 オブジェクトを追加します。トップレベルの各プロパティは、string、boolean、integer、number、array、object のいずれか1つの明示的な型に解決される必要があります。
name = "my-plugin"
version = "0.2.0"
wasm_path = "my_plugin.wasm"
capabilities = ["channel"]
permissions = ["config_read"]
[config_schema]
"$schema" = "https://json-schema.org/draft/2020-12/schema"
type = "object"
required = ["bot_token"]
additionalProperties = false
[config_schema.properties.bot_token]
type = "string"
minLength = 1
[config_schema.properties.poll_interval_secs]
type = "integer"
minimum = 1
[config_schema.properties.allowed_chats]
type = "array"
ホストはスキーマ自体に次の制限を適用します。シリアライズ後のサイズは64 KiB、ネストは最大32レベル、$idは使用できず、$refの対象はローカルJSON Pointerである必要があります。リモート参照は拒否されるため、スキーマによってネットワークフェッチが発生することはありません。
動的キーキーワードはこの方言には含まれません。patternProperties、propertyNames、unevaluatedProperties はルートで拒否されます。ホストはルートの properties マップで指定されたキーに対してのみ値を生成するため、パターンで許可されたキーがプラグインに届くことはないからです。入れ子になったプロパティスキーマには影響ありません。
pattern は線形時間の正規表現方言を使用します
ホストは呼び出しごとにスキーマを再コンパイルして再検証することで設定を解決し、その処理はコンポーネントの燃料予算内ではなくホスト上で実行されます。そのため、pattern には、ホストがコストを予測できる正規表現のみを指定できます:
- 後方参照とルックアラウンドは拒否されます。
(\w+)\s\1、(?=...)、(?<=...)などにはバックトラッキングマッチャーが必要です。代わりに、パターンの記述方法にかかわらず値の長さに比例する時間でマッチする、線形時間のregex方言を使ってパターンがコンパイルされます。 - 単一のパターンをコンパイルして生成されるプログラムは、256 KiBを超えられません。 繰り返し回数が大きいとこの制限に引っかかります。
^[\s\S]{0,200}$は問題ありませんが、^[\s\S]{0,1000}$は使えません。長さの上限にはmaxLengthを使ってください。チェックのコストがかからず、意図も明確になります。
いずれの拒否も、スキーマ名を示す InvalidManifest エラーとともにインストール時に発生するため、ホストが上限を設定できない pattern を持つプラグインは一切実行されません。構造的なパターンは期待どおりに動作します。スラッグ、UUID、メールアドレス、URL、長さに上限のある短い自由テキストは、いずれもコンパイルできます。
2. 値のエンコーディングを一致させる
Operator のストレージは文字列マップのままです。スキーマは、保存されている各文字列の読み取り方法をホストに伝えます:
| 宣言された型 | オペレーターが保存するもの | ゲストが受け取るもの |
|---|---|---|
string | secret-value | "secret-value" |
boolean | true | true |
integer | 4 | 4 |
number | 0.5 | 0.5 |
array | ["a","b"] | ["a","b"] |
object | {"k":"v"} | {"k":"v"} |
宣言された型としてパースできないものは、コードが実行される前に拒否されます。
3. キーごとに必須か任意かを決定する
実効権限は、マニフェストの要求とは別に確認されます。config_read が要求されているものの許可されていない場合、ホストは空のオブジェクトをスキーマに照らして検証します:
- すべてのフィールドがオプションのスキーマは
{}を受け取るため、各フィールドにゲスト側のデフォルト値を指定します。 requiredフィールドはフェイルクローズします。認証情報では、これが望ましい動作です。認証できないチャネルは、不完全な設定のまま実行するのではなく、起動を拒否すべきです。
4. ゲストで型付き JSON をデシリアライズする
文字列解析を、注入されたオブジェクトの 1 回のデシリアライズに置き換えます。ツールプラグインは予約済みの __config キーを読み取り、ホストはその名前のモデル提供値を削除した後、その値を呼び出し引数にマージします。
5. 再ビルドして再署名する
config_schema はマニフェスト署名の対象となるため、これを追加した後は署名済みパッケージに再署名する必要があります。署名の流れについては、プラグインの配布を参照してください。
オペレーターの手順
パッケージまたはバインディングの名前が付けられた既存の [[plugins.entries]] ブロックは読み込まれません。利用可能な移行方法は、プラグインの機能によって異なります。
ツールインスタンス
install コマンドと info コマンドでは、パッケージのデフォルトのツールバインディングからツールインスタンスを導出できます。ツールの値を新しいキーに移動するには:
- 完全なインスタンスキーを出力するには、
zeroclaw plugin info <package>を実行します。これはzpi1_...のような形式です。 - 既存のエントリの
nameをそのキーに変更するか、プラグインを再インストールしてエントリを作成し、その後zeroclaw config set plugins.entries.<instance-key>.config.<key>で値を設定します。 - 設定を保存します。値は保存時も暗号化されたままです。
キーは、パッケージ、ケイパビリティ、バインディングをバージョン付きで可逆的にエンコードしたものです。そのため、2つのパッケージがどちらも main という名前のバインディングを使用していても、認証情報を共有せずに済みます。新規インストールでは、このツールキーが自動的にシードされ、表示されます。
チャネルインスタンス
チャネルキーには、設定されたチャネルエイリアスが含まれます。zeroclaw plugin install と zeroclaw plugin info はパッケージを把握していますが、そのエイリアスを所有していないため、チャネルキーを導出、表示、またはシードすることはできず、パッケージレベルの代替値を作成してはなりません。エイリアスを認識したチャネル構築と実行時設定の解決は zeroclaw#10146 で導入されました。デーモンは明示的に宣言されたチャネルインスタンスを構築し、実際に設定されたエイリアスをキーとして、zpi1(package, channel, alias) から型付き設定を解決します。
チャンネルインスタンスの自動的な plugin info キー表示とインストール時のシード処理は、zeroclaw#9584 の grant セレモニーが完了するまで手動のままです。そのセレモニーが実施されるまでは、オペレーターは install や info に表示・シードさせるのではなく、zeroclaw config set を使ってチャンネルキーを手動でシードします。そのため、自動的な install と info のキー処理に依存するチャンネル専用パッケージは、まだ完成していません。
拒否の診断
| メッセージ | 原因 |
|---|---|
config_read を要求していますが、config_schema を宣言していません | ステップ 1 は未完了です |
config_read を要求せずに config_schema を宣言する | スキーマを削除するか、権限を追加してください |
config_schema で additionalProperties = false を設定する必要があります | ルート オブジェクトが開いています |
config_schema はルートに <keyword> を宣言してはなりません | ルートでは動的キーのキーワードが使用されます。代わりに、properties 内のすべてのキーに名前を付けてください。 |
| プロパティでサポートされていない型が使用されています | プロパティに明示的にサポートされている型がないか、解決できないローカルの $refがある |
config に config_schema に存在しないプロパティが含まれています | 演算子キーが宣言されていません。多くの場合、タイプミスです |
| config プロパティは JSON の整数である必要があります | 保存された文字列を宣言された型として解析できません |
config は <path> で config_schema に違反しています | minimum や required などの制約を満たしていません |
ファーストパーティパッケージ
zeroclaw-labs/zeroclaw-plugins で公開されているすべてのパッケージは config_read を要求しており、この変更が入った時点では config_schema を宣言しているものはなかったため、すべて step 1 と step 5 が必要です。移行はパッケージがホストとは独立してバージョン管理されるため、ここではなくそのリポジトリで追跡されます。ツールパッケージは、今すぐオペレーターキーのステップを完了できます。チャネル専用パッケージは、上記のエイリアス対応キー経路が整うまで待つ必要があり、この契約についてトラッカーがそれらを移行済みとしてマークまたは公開するのはその後になります。
メモリプラグイン
メモリプラグインにはまだ設定のエクスポートがなく、その ABI が存在するまで config_read を要求してはいけません。