メインコンテンツまでスキップ

チャンネルプラグインのパッケージング(official / steam)

チャンネルプラグイン(Discord、Feishu、Telegram、Slack、WhatsApp など)は事前ビルド済みアーティファクトとしてインストーラーと共に配布されます。このドキュメントでは、ソースコードから実行時までの完全なパス、ビルドチャンネル(official / steam)間のパッケージングの違い、そして steam チャンネルでかつてプラグインが欠落していた理由と現在の監査による防止策を説明します。

2 つの検出ディレクトリ

実行時に ChannelPluginLoader2 つのディレクトリからチャンネルプラグインを検出します。pluginsDirbundledDir より優先度が高くなります(type が同じ場合は上書き):

ディレクトリパス読み書きソース
ユーザーインストール(pluginsDir<userData>/channel-plugins/読み書きMarketplace ダウンロード / ローカルインストール
組み込み(bundledDir<resources>/bundled-channel-plugins/読み取り専用インストーラーと共に配布

関連コード:packages/desktop/app/main/services/capabilities/integrations/channel/ChannelPluginLoader.tspackages/desktop/app/main/bootstrap/capabilities-channel.ts

bundledDir の解決は bootstrap/index.ts にあります:

const channelBundledDir = isDev
? path.join(__dirname, '..', '..', '..', 'elftia-channels', 'dist-plugins') // Dev mode: workspace source directory
: path.join(process.resourcesPath, 'bundled-channel-plugins'); // Packaged mode: copy under resources

ChannelPluginLoader は構築時に bundledDir の存在確認を行います:

this.bundledDir = bundledDir && existsSync(bundledDir) ? bundledDir : null;

重要な意味:パッケージ済みの <resources>/bundled-channel-plugins/ が存在しない場合、bundledDirnull に設定され、discover()<userData>/channel-plugins/ ディレクトリのみを対象とします。新規インストールの場合、このディレクトリは空のため → チャンネルプラグインが 0 件発見される → チャンネルページに利用可能なプラグインが存在しない

ソースコードからインストーラーへ

チャンネルプラグインのソースコードビルドアーティファクトはワークスペースディレクトリに格納されます:

packages/elftia-channels/dist-plugins/
├── discord/
├── feishu/
├── telegram/
├── slack/
├── whatsapp/
└── … (total ~26)

packages/elftia-channels/dist-plugins事前ビルド済みアーティファクトディレクトリであり、build:official / build:steam のインラインビルドチェーンには含まれません。パッケージング前に既に存在している必要があります。

パッケージング時に、electron-builder の extraResources がそれを resources/bundled-channel-plugins にコピーします。両方のビルドチャンネルでこれを宣言する必要があります

# Both electron/electron-builder.official.yml and electron/electron-builder.steam.yml need:
extraResources:
- from: packages/elftia-channels/dist-plugins
to: bundled-channel-plugins
filter:
- "**/*"

official と steam のパッケージングの違い

項目officialsteam
設定ファイルelectron/electron-builder.official.ymlelectron/electron-builder.steam.yml
renderer-extension/byo-providers含まれる(BYO は official の核心的な約束)除外(Steam コンプライアンスの分離、明示的な負のフィルターマッチ)
bundled-channel-plugins含まれる同様に含める必要がある

チャンネルプラグインは BYO コンプライアンスの分離とは無関係:チャンネルプラグインはユーザー自身のボットトークン(Discord ボットトークン、Telegram ボットトークンなど)を使用しており、Steam が拒否する「BYO LLM プロバイダーキー / サイト外決済」カテゴリーには属しません。Steam チャンネルのコンプライアンス上の唯一の除外は renderer-extension/byo-providers であり、チャンネルプラグインは除外リストに含まれていません。

過去のバグ:steam.yml の設定漏れ

electron-builder.steam.ymlextraResources には、かつて bundled-channel-plugins完全に欠落していました(git の全履歴に一度も現れていません)。影響:

  1. Steam パッケージに resources/bundled-channel-plugins/ ディレクトリがない;
  2. 実行時に channelBundledDir が存在しないパスを指す → ChannelPluginLoader.bundledDir = null
  3. discover() は空のユーザーディレクトリのみをスキャン → チャンネルプラグインが 0 件発見される;
  4. ユーザー体験:Steam 版はチャンネルプラグインを使用できないが、official 版は正常に動作する

この漏れは意図的なコンプライアンス上の分離ではありませんでした(意図的な除外はすべてコメント付きの負の filter マッチを持っています)。steam.ymlofficial.yml からフォークされた際に見落とされた extraResources の追記漏れでした。

監査のフォールバック:verify:steam-package

scripts/verify-steam-packaging.mtsnpm run verify:steam-package、現在は build:steam チェーンの末尾に統合)は4 つの不変条件を検証します:

不変条件意味
byo-providers ABSENTSteam パッケージは renderer-extension/byo-providers含まない(コンプライアンス)
design-studio PRESENTSteam パッケージは renderer-extension/design-studio含む
channel === 'steam'チャンネルメタデータが steam である
bundled-channel-plugins PRESENTSteam パッケージに少なくとも 1 つのチャンネルプラグインが含まれる ← 今回新規追加

終了コードの契約:0 は全て合格;2 は少なくとも 1 つの違反;1 は入力が利用不可。

監査には 2 つのモードがあります(優先度順):

  • MODE 1(パッケージング済み、権威)release/steam/<platform>-unpacked/…/resources/plugins/renderer-extension/ が存在する場合、実際のアーティファクトを直接監査します。チャンネルプラグイン数 = 同じ階層の resources/bundled-channel-plugins/ のサブディレクトリ数。
  • MODE 2(ステージング ドライラン、フォールバック)electron-builder.steam.ymlextraResources エントリを解析して bundled-channel-plugins にマップし、from: のソースディレクトリのサブディレクトリを数えます。エントリがない → 0 と見なす → 不変条件失敗(これがまさに今回防ぎたい設定漏れです)。

歴史的な教訓:以前の監査は renderer-extension のみを対象とし、チャンネルプラグインはスコープ外でした。そのため、パッケージにチャンネルプラグインが 0 件でも監査はパスしていました。新しい bundled-channel-plugins PRESENT 不変条件がこの盲点を塞ぎます。

変更 / 検証チェックリスト

チャンネルプラグインのパッケージングを追加または調整する際:

  • electron-builder.steam.ymlofficial.yml両方packages/elftia-channels/dist-plugins → bundled-channel-plugins を宣言している;
  • パッケージング前に packages/elftia-channels/dist-plugins/ がビルド済みで空でない;
  • 再ビルド:npm run build:steam:win(古い release/steam/win-unpacked/ は前回のビルドのため、MODE 1 監査はそれを使用します。再ビルド後に監査すること);
  • アーティファクトの確認:release/steam/win-unpacked/resources/bundled-channel-plugins/ にすべてのプラグインディレクトリが含まれている;
  • 監査合格:npm run verify:steam-package の終了コードが 0[PASS] bundled-channel-plugins PRESENT
  • 実行時確認:メインプロセスのログに Channel plugin directories … bundledExists: trueChannel plugin discover: found N plugin(s)(N > 0)が表示される。