チャンネルおよびウェブバックエンドデーモンアダプターのドラフト
目標
チャンネルアダプターとウェブチャットバックエンドが、DaemonSessionClient を介して qwen serve を利用できるようにする。ただし、既存のチャンネル ACP サブプロセス動作はデフォルトのままとする。
本ドラフトはサーバー側のクライアントのみを対象とする:
- チャンネルボットバックエンド ->
qwen serve - ウェブブラウザ -> ウェブバックエンド / BFF ->
qwen serve
ブラウザ JavaScript がデーモンに直接呼び出すことは明示的に許可しない。現在デーモンは設計上、ブラウザの Origin リクエストを拒否している。
提案するエントリーポイント
チャンネルバックエンド:
QWEN_CHANNEL_DAEMON_URL=http://127.0.0.1:4170 qwen channel start telegramウェブバックエンド:
QWEN_WEB_DAEMON_URL=http://127.0.0.1:4170 qwen web-chat-backend共通のオプション変数:
QWEN_DAEMON_TOKEN=...
QWEN_DAEMON_WORKSPACE=/repo最小限のチャンネルフロー
この PR では、チャンネルアダプターとウェブバックエンドアダプター向けに、ローカルで検証可能なサーバー側ブリッジ DaemonChannelBridge を追加する。既存の ACP ブリッジはデフォルトのまま維持し、デーモンのセッション状態はバックエンドプロセス内で管理する。
- チャンネルの送信者/スレッドをチャンネルセッションキーに解決する。
DaemonClient+DaemonSessionClient.createOrAttach()を使用する。- 受信したユーザーテキストを
session.prompt()で送信する。 session.events()を購読し、アシスタントのテキストチャンクを収集する。- 最終テキストをプラットフォームアダプター経由で返信する。
session.respondToPermission()で権限投票をキャストする。session.cancel()でアクティブな処理をキャンセルする。
最小限のウェブバックエンドフロー
- ブラウザがウェブバックエンドへの websocket または HTTP ストリームを開く。
- バックエンドが
DaemonSessionClientを所有する。 - バックエンドがブラウザメッセージをデーモンプロンプトに変換する。
- バックエンドがデーモンの SSE イベントをブラウザセーフなアプリイベントに変換する。
- バックエンドがデーモンの
sessionIdと最後に確認したイベント ID をサーバー側に保存する。
ブラウザクライアントはデーモンのベアラートークンを受信してはならない。
セッション分離の制約
現在のデーモン Stage 1 の動作は、実質的にデーモン設定レベルで sessionScope: single となっている。リクエスト単位の sessionScope が導入されるまでは、マルチユーザーのチャンネルまたはウェブデプロイメントでは、以下のいずれかの安全な形態を選択する必要がある:
- チャンネルスレッド / ウェブルームごとに 1 つのデーモン
- ユーザーワークスペースごとに 1 つのデーモン
- シングルユーザーデモのみ
無関係なチャンネルスレッドを 1 つのデーモンセッションに黙って多重化してはならない。
イベントマッピング契約
| デーモンイベント | チャンネル/ウェブバックエンドの処理 |
|---|---|
session_update / agent_message_chunk | アシスタントテキストを追記 |
session_update / agent_thought_chunk | オプションの非表示/デバッグストリーム |
session_update / tool_call | ツールステータスカード/メッセージを出力 |
permission_request | プラットフォーム固有の承認インタラクション |
permission_resolved | 承認インタラクションをクローズ/更新 |
model_switched | バックエンドセッションメタデータを更新 |
session_died | ユーザーに通知しストリームを停止 |
未知のデーモンイベントは無視するか、致命的エラーではなくデバッグメタデータとして転送する必要がある。
ブリッジはまだ qwen channel start に組み込まれていない。既存の Telegram、Weixin、Dingtalk、プラグインチャンネル、ブラウザの動作は変更されない。
明示的な非目標
- ブラウザからデーモンへの直接 fetch または EventSource は不可。
- このアダプター PR での CORS 緩和は行わない。
- Telegram、Weixin、Dingtalk、プラグインチャンネルのデフォルト移行は行わない。
- ファイル CRUD、メモリ CRUD、MCP 再起動、プロバイダー変更は行わない。
- デーモン側でサポートがない場合、クライアント側での sessionScope エミュレーションは行わない。
マージの安全性
- デフォルトでオフ。
- 既存の ACP チャンネルブリッジはデフォルトのまま。
- ウェブバックエンドは明示的な BFF レイヤーであり、デーモンのセキュリティ変更ではない。
- どのチャンネルアダプターも、デーモントークンをフロントエンド/ブラウザコードに取り込んではならない。
検証計画
- チャンネルセッションキーからデーモンセッションへのバインディングのユニットテスト。
- デーモンイベントからチャンネル/ウェブメッセージへのマッピングのユニットテスト。
- prompt、cancel、model switch、permission response の転送のユニットテスト。
- シングルユーザーチャンネルバックエンドとローカルの
qwen serveとのスモークテスト。 - ブラウザ -> BFF -> デーモン(デーモントークンを公開しない)のスモークテスト。
デフォルト移行前のブロッカー
- リクエスト単位の
sessionScope。 - セッションメタデータ + close/delete のライフサイクル。
- デーモンが付与するクライアント ID。
- セッションスコープの権限ルート。
- MCP、スキル、プロバイダー、環境に関する読み取り専用の診断情報。