型付きプラグイン設定への移行
型付きインスタンス設定は、オペレーター設定を読み取る 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 階層まで、ルートプロパティは 256 個まで、$id は使用不可、$ref の参照先はローカルの JSON Pointers である必要があります。リモート参照は拒否されるため、スキーマがネットワークフェッチを引き起こすことはありません。いずれかの制限を超えるスキーマは、バリデータのコンパイル前に、パッケージのインストール/アドミッション時にフェイルクローズ動作で拒否されます。
動的キーキーワードはこの方言には含まれません。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#10146 で導入されました。デーモンは明示的に宣言されたチャネルインスタンスを構築し、実際に設定されたエイリアスをキーとして、zpi1(package, channel, alias) から型付きの設定を解決します。
Binding the alias derives, prints, and seeds that key. To put a channel instance’s values on it:
Wait, I need to translate this into Japanese. Here is the translation:
エイリアスをバインドすると、そのキーが導出、出力、およびシードされます。チャネルインスタンスの値をそこに設定するには:
zeroclaw plugin bind <package> --channel-alias <alias>を実行します。マニフェストで送信先が宣言されており、パッケージがそれらに到達可能なトランスポート(http_client、websocket_client、socket_clientのいずれか)を保持しており、かつインスタンスにまだ行がない場合は、--egress declaredを追加するとそれらへのアクセスを許可し、--egress noneを追加するとネットワーク到達性なしでバインドします。どちらも指定しない場合、コマンドは実行を拒否し、該当する送信先を一覧表示します。[channels.plugin.<alias>]バインディングを作成します。既に記述済みのバインディングがあればそれを維持します。また、インスタンスの[[plugins.entries]]行を初期化します。zeroclaw plugin install <source> --channel-alias <alias>も、インストール中に同じ処理を行います。zeroclaw config set plugins.entries.<instance-key>.config.<key>で値を設定します。バインドの準備状況レポートには、各requiredキーが設定済みか未設定かが一覧表示され、未設定のキーについては正確なコマンドも表示されます。zeroclaw plugin info <package>は、インスタンスキーと同じレポートを後から再度出力します。値は保存時に暗号化されたままになります。
インスタンスキーの下に既に存在する行は、そのまま変更されません。そのため、手動で書き込んだ値はバインド後も保持されます。チャネルインスタンスについては、レガシー名は参照されません。チャネルの構築はフルインスタンスキーより後に追加されたため、どのランタイムもパッケージ名やエイリアス名の行からチャネルの設定を読み込むことはありませんでした。
拒否の診断
| メッセージ | 原因 |
|---|---|
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 を宣言していなかったため、すべてに手順1と手順5が必要です。パッケージはホストとは独立してバージョンを付けているため、移行作業はこのリポジトリではなく、そのリポジトリで追跡されています。どちらの種類のパッケージも、オペレーターキーの手順は今すぐ完了できます。ツールパッケージは plugin info を含むインストールを通じて、チャネル専用パッケージは上記のとおり zeroclaw plugin bind を通じて完了できます。
メモリプラグイン
メモリプラグインにはまだ設定のエクスポートがなく、その ABI が存在するまで config_read を要求してはいけません。