Skip to Content
デベロッパーガイドDaemonクイックスタートと運用

クイックスタートと運用

本ページでは、qwen serve の起動方法、動作確認方法、および qwen serve からリスニングサーバーまでの内部呼び出しチェーン について重点的に解説します。アーキテクチャ、コンポーネント、ワイヤープロトコルの詳細については、デーモンの詳細解説ページを参照してください。

1. 最短パス

qwen serve

Output:

qwen serve listening on http://127.0.0.1:4170 (mode=http-bridge, workspace=/your/cwd) qwen serve: bound to workspace "/your/cwd" qwen serve: bearer auth disabled (loopback default). Set QWEN_SERVER_TOKEN to enable.

ブラウザで http://127.0.0.1:4170/ を開くと、Web Shell UI(チャット、セッションリスト、ワークスペース検査)を確認できます。createServeApp() はバンドルされた Web Shell アセット(packages/cli/src/serve/web-shell-static.ts)を bearerAuth にマウントするため、シェル自体はトークンなしでロードされます。シェル自身の API 呼び出しは、トークンが設定されている場合はベアラートークンを付与します。認証が有効な場合は、デーモンを --open(URL フラグメントにトークンを配置し、サーバーには送信されない)で起動するか、#token=… を手動で追加してください。--no-web でオプトアウトし、デーモンを API のみにします。

2. 起動レシピ

# 1. ローカル開発のデフォルト(ループバック、トークンなし) qwen serve # 2. 明示的なワークスペース + エフェメラルポート qwen serve --workspace /path/to/repo --port 0 # 3. 強化されたループバック開発(ループバックでもベアラ認証を強制) QWEN_SERVER_TOKEN=$(openssl rand -hex 32) qwen serve --require-auth # 4. LAN に公開(非ループバックにはトークンが必要) QWEN_SERVER_TOKEN=$(openssl rand -hex 32) \ qwen serve --hostname 0.0.0.0 --port 4170 # 5. 多数のセッションとより大きなリプレイリング用にチューニング qwen serve --max-sessions 0 --event-ring-size 32000 # 6. マルチクライアント連携 + 厳格な MCP バジェット QWEN_SERVER_TOKEN=secret \ qwen serve --require-auth \ --mcp-client-budget 10 \ --mcp-budget-mode enforce # 7. settings.json で設定されたコンセンサスポリシーで起動 # settings.json: { "policy": { "permissionStrategy": "consensus", "consensusQuorum": 2 } } qwen serve # 8. デバッグログ QWEN_SERVE_DEBUG=1 qwen serve # 9. F2 プールを無効化(セッションごとの MCP クライアントにフォールバック) QWEN_SERVE_NO_MCP_POOL=1 qwen serve # 10. ブラウザ Web UI のクロスオリジンアクセスを許可 QWEN_SERVER_TOKEN=secret \ qwen serve --allow-origin 'http://localhost:3000' # 11. プロンプトデッドライン + SSE アイドルタイムアウト qwen serve --prompt-deadline-ms 300000 --writer-idle-timeout-ms 600000 # 12. 最後のセッションが閉じた後も ACP 子プロセスをウォームに保つ qwen serve --channel-idle-timeout-ms 60000 # 13. HTTP レート制限を有効化 QWEN_SERVE_RATE_LIMIT=1 qwen serve

強化されたループバックのレシピ (3) では、/healthbearerAuth の後に登録されるため、プローブは他の API ルートと同様にトークンを運ぶ必要があります(Web Shell の静的サーフェスは設計上プレ認証のままです。API のみのデーモンにするには --no-web を渡してください)。

3. 完全な起動フラグ

CLI は packages/cli/src/commands/serve.ts で定義されています:

フラグデフォルト必須条件動作
--port <n>number4170-TCP ポート。0 は OS によって割り当てられるエフェメラルポートを意味します。
--hostname <host>string127.0.0.1非ループバックにはトークンが必要バインドアドレス。ループバックの値: 127.0.0.1localhost::1[::1][::1] のブラケットは自動的に削除されます。host:port 形式の入力は拒否され、--port を使用するようガイダンスが表示されます。
--token <s>stringenv / none非ループバックおよび --require-authベアラートークン。1回だけトリミングされます。/proc/<pid>/cmdline に表示されるため、QWEN_SERVER_TOKEN の使用を推奨します。起動時の stderr でもこれについて警告されます。
--max-sessions <n>number32-ワークスペースごとのアクティブセッション上限。超過した spawn は 503 を返します。0 は無制限を意味します。NaN / 負の値は例外をスローします。
--max-total-sessions <n>number複数のワークスペース起動用に導出される値-デーモン全体のアクティブセッション上限。省略時は、ワークスペースごとの上限と起動/復元ワークスペース数から有限のデフォルト値が 1 回だけ導出されます。動的な登録では再計算されません。0 は無制限を意味します。
--memory-budget-mb <n>[1024, 1048576] の整数cgroup/ホストメモリの 50%-デーモンプロセスツリーの合計メモリバジェット。解決された利用可能メモリで上限が設定されます。子プロセスのサイズはこれから決定されません。現在の唯一のコンシューマーはアダプティブな live-journal 成長プールです(--max-journal-bytes を参照)。limits.memory の下に報告され、モデル化された子プロセスごとのパーティションが含まれます。
--max-journal-events <n>正の安全な整数10000-セッションごとの飛行中の liveJournal リプレイエントリのベースライン上限。アダプティブ成長によって引き上げられることがあります(--max-journal-bytes を参照)。どちらかのジャーナルフラグを固定すると成長が無効になります。
--max-journal-bytes <n>正の安全な整数8388608-飛行中の liveJournal のセッションごとのベースラインバイト上限。閾値を超えると、ターンごとにキャップがオンデマンドで成長します(Effective --memory-budget-mb の 5% のデーモン全体プール内で、残りプールのヘッドルームに応じて倍増方向。Effective バジェットが 1024 MB 最小値を下回る場合は 0 — 成長無効)。256 MiB のセッションごとのハードキャップを超えることはありません。どちらかのジャーナルフラグを固定すると成長が無効になります。
--memory-pressure-mode <mode>off | observeobserve観察のみ両モードで runtime.memory.pressure を報告します。observe のみ daemon_memory_pressure issue を発生させます。ルートプロセスのみ。
--child-heap-mode <mode>off | observeobserve観察のみobserve の下では、モデル化されたパーティションを limits.memory.childHeap の下に報告します。何も適用せず、何も拒否しません。off の下では、そのブロックの 2 つの数値は null になります。
--max-pending-prompts-per-session <n>number5-セッションごとに受け入れられたが pending/running 状態のプロンプトの上限。超過したプロンプトは 503 を返します。0 / Infinity は無制限を意味します。負の値または非整数値は例外をスローします。
--workspace <dir>string / 繰り返し可能process.cwd()-起動ワークスペースランタイム。繰り返して追加の分離されたランタイムを登録できます。最初がプライマリです。各値は絶対パスであり、存在し、かつディレクトリでなければなりません。起動時に canonicalizeWorkspace を介してすべての値を正規化します。cwd が一致しない POST /session400 workspace_mismatch を返します。
--max-connections <n>number256-リスナーレベルの server.maxConnections0 / Infinity は無制限を意味します。NaN / 負の値は、fail-open 動作を避けるために起動を失敗させます。
--require-authbooleanfalseトークンが必要ベアラ認証をループバック および /health に拡張します。トークンがない場合、起動は拒否されます。
--enable-session-shellbooleanfalseトークンが必要直接の POST /session/:id/shell 実行を有効にします。呼び出し元はセッションにバインドされた X-Qwen-Client-Id も送信する必要があります。
--event-ring-size <n>number8000-セッションごとの SSE リプレイリングの深さ。ソフトキャップは MAX_EVENT_RING_SIZE = 1_000_000 です。範囲外の値はブリッジ構築中に例外をスローします。
--http-bridgebooleantrue-ブリッジモード: 本番環境ではプライマリの qwen --acp 子のプリヒートを試行し、失敗時は初回使用時にリトライします。信頼されたセカンダリはオンデマンドで 1 つを開始しますが、信頼されていないセカンダリは ACP を開始できません。ステージ 2 の in-process モードはまだ実装されていません。--no-http-bridge はフォールバックし、stderr に出力します。
--mcp-client-budget <n>numbernonemcp-budget-mode=enforce に必要ワークスペース MCP クライアントの上限。正の整数である必要があります。
--mcp-budget-mode <m>'enforce' | 'warn' | 'off'バジェットが設定されている場合は warn、それ以外の場合は offenforce には --mcp-client-budget が必要enforce は拒否し、warn は 75% で警告のみを出し、off は監視のみを行います。
--allow-origin <pattern>repeatable stringnone-デフォルトの Origin 拒否を置き換える CORS 許可リスト。* にはトークンが必要です。
--allow-private-auth-base-urlbooleanfalse-localhost / プライベートネットワークの認証プロバイダーの baseUrl インストールを許可します。信頼できるローカル開発でのみ使用してください。
--prompt-deadline-ms <n>numbernone-サーバー側のプロンプトの壁時計制限(ミリ秒)。タイムアウトするとプロンプトが中止されます。
--writer-idle-timeout-ms <n>numbernone-SSE 接続ごとのアイドルタイムアウト(ミリ秒)。
--channel-idle-timeout-ms <n>number0-最後のセッションが閉じた後も ACP 子プロセスを存続させます。0 は即座に回収することを意味します。
--initialize-timeout-ms <n>number10000-ACP 子プロセスのリクエストタイムアウト。initialize ハンドシェイクを含む(ミリ秒)。
--session-reap-interval-ms <n>number60000-セッションリーパーのスキャン間隔。0 は無効にします。
--session-idle-timeout-ms <n>number1800000-切断されたセッションのアイドルタイムアウト。0 は無効にします。
--rate-limit / --no-rate-limitbooleanenv / off-階層ごとの HTTP レート制限を有効または無効にします。
--rate-limit-prompt <n>number10--rate-limitウィンドウごとのプロンプトリクエスト数。
--rate-limit-mutation <n>number30--rate-limitウィンドウごとのミューテーションリクエスト数。
--rate-limit-read <n>number120--rate-limitウィンドウごとのリードリクエスト数。
--rate-limit-window-ms <n>number60000--rate-limitレート制限ウィンドウの長さ。>= 1000 である必要があります。

4. 環境変数

環境変数同等のフラグ / 効果
QWEN_SERVER_TOKEN--token と同等。--token が優先されます。cat token.txt からの末尾の改行を避けるため、起動時に 1 回だけトリミングされます。
QWEN_SERVE_DEBUG1 / true / on / yes(大文字小文字を区別しない)で詳細な stderr ログが有効になります。
QWEN_SERVE_NO_MCP_POOL1 でワークスペース MCP プールを完全に無効化し、セッションごとの McpClientManager にフォールバックします。Capabilities は mcp_workspace_pool / mcp_pool_restart の広告を停止します。
QWEN_SERVE_MCP_CLIENT_BUDGETACP 子プロセスの内部バジェット入力。CLI は childEnvOverrides を介して --mcp-client-budget からこれを生成します。親プロセスの環境変数フォールバックではありません。
QWEN_SERVE_MCP_BUDGET_MODEACP 子プロセスの内部バジェットモード。CLI は childEnvOverrides を介して --mcp-budget-mode からこれを生成します。親プロセスの環境変数フォールバックではありません。
QWEN_SERVE_PROMPT_DEADLINE_MS--prompt-deadline-ms の環境変数フォールバック。
QWEN_SERVE_WRITER_IDLE_TIMEOUT_MS--writer-idle-timeout-ms の環境変数フォールバック。
QWEN_SERVE_MCP_POOL_TRANSPORTSACP 子プロセスによって読み取られます。カンマ区切りのプールされたトランスポート許可リスト。デフォルトは stdio,websocket です。
QWEN_SERVE_MCP_POOL_DRAIN_MSACP 子プロセスによって読み取られます。プールエントリのアイドルドレイン遅延。デフォルトは 30000 で、1000..600000 ms にクランプされます。
QWEN_SERVE_RATE_LIMIT1 / true でレート制限が有効になります。CLI フラグが優先されます。
QWEN_SERVE_RATE_LIMIT_PROMPT--rate-limit-prompt の環境変数フォールバック。
QWEN_SERVE_RATE_LIMIT_MUTATION--rate-limit-mutation の環境変数フォールバック。
QWEN_SERVE_RATE_LIMIT_READ--rate-limit-read の環境変数フォールバック。
QWEN_SERVE_RATE_LIMIT_WINDOW_MS--rate-limit-window-ms の環境変数フォールバック。

ハンドルごとの環境変数オーバーライドは意図的なものです。同じプロセスで実行される 2 つのデーモンは process.env で競合しません。defaultSpawnChannelFactory は spawn 時に環境変数のスナップショットを取得します。

5. settings.json も読み込まれます

起動時に loadSettings(boundWorkspace) が 1 回呼び出されます:

キー動作
policy.permissionStrategy'first-responder' | 'designated' | 'consensus' | 'local-only'BridgeOptions.permissionPolicy を設定します。起動時に validatePolicyConfig で検証されます。不明な値はサイレントにフォールバックするのではなく、InvalidPolicyConfigError をスローします。
policy.consensusQuorumpositive integerconsensus ポリシーの N。デフォルトは floor(M/2)+1 です。非コンセンサスポリシーの下で設定された場合、無視され、起動時に stderr に警告がログ出力されます。
context.fileNamestringgetCurrentGeminiMdFilename() をオーバーライドし、POST /workspace/init がどのファイルを書き込むかを制御します。
tools.disabledstring[]次の ACP 子プロセスの spawn に影響を与える前に、normalizeDisabledToolList() を介して正規化されます(トリム、空のエントリ削除、重複排除)。
tools.approvalModestringデフォルトのセッション承認モード。
telemetryobjectOTel 設定: enabledotlpEndpointotlpProtocol、シグナルごとのエンドポイントなど。詳細は 17-configuration.md を参照してください。

不正な JSON などの設定 I/O 失敗はデフォルトにフォールバックします。InvalidPolicyConfigError は例外です。ポリシーの誤設定は起動を明示的に失敗させます。

6. 起動拒否シナリオ(明示的な失敗)

run-qwen-serve.ts は、以下のケースでフォールバックする代わりに意図的に例外をスローします:

シナリオエラープレフィックス
トークンなしの非ループバックバインドRefusing to bind ... without a bearer token
トークンなしの --require-authRefusing to start with --require-auth set but no bearer token
--workspace が存在しない、ディレクトリではない、または絶対パスではないInvalid --workspace ...
--workspace の stat 権限が拒否されたInvalid --workspace ...: permission denied
--mcp-client-budget が正の整数ではないMust be a positive integer
バジェットなしの --mcp-budget-mode=enforcerequires a positive mcpClientBudget
--hostnamelocalhost:4170 と記述されているlooks like a "host:port" combination. Use --port
--hostname [::1]:8080Invalid --hostname ... brackets indicate an IPv6 literal but the value is not a clean [addr] form
--max-connectionsNaN または負の値Must be >= 0
--event-ring-size > 1_000_000Thrown during bridge construction
トークンなしの --allow-origin '*'Refusing to start with --allow-origin '*' but no bearer token configured
--prompt-deadline-ms / --writer-idle-timeout-ms が正の整数ではないMust be a positive integer
--initialize-timeout-ms が正の整数ではないか 2^31-1 を超えるMust be a positive integer / Exceeds maximum JS timer delay
不明な policy.permissionStrategy または正でない policy.consensusQuorumInvalidPolicyConfigError

7. Curl 検証チェックリスト

# 1. 生存確認 curl http://127.0.0.1:4170/health # -> {"status":"ok"} # 1.1 ディープヘルスチェック curl -s 'http://127.0.0.1:4170/health?deep=1' | jq # 2. ケーパビリティ curl -s http://127.0.0.1:4170/capabilities | jq # 3. プリフライト準備状況 curl -s http://127.0.0.1:4170/workspace/preflight | jq # 4. 環境スナップショット (シークレットは存在のみ報告) curl -s http://127.0.0.1:4170/workspace/env | jq # 5. MCP プール / バジェットスナップショット curl -s http://127.0.0.1:4170/workspace/mcp | jq # 6. セッションの作成 curl -s -X POST http://127.0.0.1:4170/session \ -H 'Content-Type: application/json' \ -H 'X-Qwen-Client-Id: curl-debug' \ -d '{}' | jq # 7. SSE のテール (<sid> を置換) curl -N \ -H 'Accept: text/event-stream' \ -H 'X-Qwen-Client-Id: curl-debug' \ -H 'Last-Event-ID: 0' \ 'http://127.0.0.1:4170/session/<sid>/events' # 8. Web Shell UI open http://127.0.0.1:4170/

Bearer 認証が有効な場合、すべてのリクエストに -H "Authorization: Bearer $QWEN_SERVER_TOKEN" を追加します。

8. ブラウザ UI はあるか?

はい — Web Shell です。 resolveWebShellDir() がビルド済みアセットを見つけ(リリースでは CLI バンドルの隣、チェックアウトでは packages/web-shell/dist)、mountWebShellAssets()//assets、および /session/:id のドキュメントナビゲーション(ブラウザのディープリンク — 通常の curl /session/<id> ではシェルの代わりに API の 401/404 が返されます)にそれらを提供します。アセットが存在しない場合、デーモンはクラッシュせずに API のみにフォールバックします。--no-web で明示的にオプトアウトできます。

静的シェルはすべての起動モードで bearerAuth にマウントされます。ブラウザはアドレスバーのナビゲーションや <script src> サブリソースに Authorization ヘッダーを付与できないため、ゲートすると UI が壊れるだけです。シェルが呼び出すすべての API ルートはトークン保護されたままであり、フロントエンド自身がベアラートークンを付与します。非ループバックのバインドでは、--allow-origin <origin> が渡されない限りシェルは読み取り専用です。同一オリジンの POST は Origin ヘッダーを運び、CORS ウォールが拒否(403)します。ループバック以外のバインドには --allow-origin を渡してください。

CSP は buildWebShellCsp() によって構築され、静的ページのそれよりも意図的に緩くなっています(インラインの performance.measure パッチ用の 'unsafe-inline'、shiki と mermaid 用の eval/wasm/blob ワーカー、katex フォント用の data:、SSE 用の connect-src 'self')。frame-ancestors 'none'X-Frame-Options: DENY でクリックジャッキングをブロックしますが、--allow-origin で拡張オリジンが明示的に許可されている場合は例外です(UI を Chrome サイドパネルにホストできるようにするため、#5626)。

生のプロトコル検査には、SSE ストリームを直接購読してください(routes/sse-events.ts)— セクション 7 の curl レシピを参照してください。

9. qwen serve からリスニングサーバーまでのコールチェーン

qwen serve | v (process) packages/cli/index.ts main() | v gemini.tsx main() - parseArguments() | v (yargs assembly) config/config.ts import { serveCommand } ... config/config.ts .command(serveCommand) config/config.ts await yargsInstance.parse() | v (handler) commands/serve.ts handler(argv) - boot pre-checks commands/serve.ts const { runQwenServe } = await import('../serve/index.js') # 遅延ロード commands/serve.ts await runQwenServe({...}) | v serve/run-qwen-serve.ts runQwenServe(opts, deps) | |- trim token | |- hostname mismatch fallback | |- auth preflight | |- workspace validation + canonicalization | |- MCP budget validation + childEnvOverrides | |- loadSettings + validatePolicyConfig | |- PermissionAuditRing + publisher | |- resolveBridgeFsFactory | `- createHttpAcpBridge({...}) | v serve/run-qwen-serve.ts const app = createServeApp(opts, () => actualPort, {...}) | v serve/server.ts createServeApp() - builds Express app (**does not listen**) | |- middleware chain (Host allowlist / CORS / bearerAuth / mutation gate / rate limit) | |- route mounting (health / web-shell static / capabilities / workspace / session / SSE / ACP HTTP) | `- return app | v serve/run-qwen-serve.ts server = createServer(app) / https.createServer(..., app) | |- lifecycle.bindServer(server, { startupReady, drainHost }) | |- server.listen(port, hostname) | |- server.maxConnections = cap | |- actualPort = server.address().port | |- write "qwen serve listening on ..." | |- register SIGINT / SIGTERM (onSignal) | `- resolve(handle: RunHandle) | v commands/serve.ts await blockForever() // block forever until signal

重要な事実:

  • createServeApp はビルドのみを行い、リスニングは行いません。 ミドルウェアとルートがマウントされた express() インスタンスを返します。Ordinary-only の組み込み側は app.listen() を所有し続けることができます。Live/Conversations を使用する組み込み側は、リスニング前に実際の Node サーバーをエクスポートされたアプリライフサイクルにバインドし、シャットダウン時にそのライフサイクルを待機する必要があります。
  • () => actualPort は遅延クロージャです。 actualPortserver.listen のコールバック内で代入されます。hostAllowlist ミドルウェアはオンデマンドでそれを読み取るため、エフェメラルポート(--port 0)でも Host ヘッダーを正しくゲートします。
  • await blockForever() は意図的なものです。 yargs.parse() が解決すると、CLI のトップレベルは対話型 TUI のエントリポイント(gemini.tsx)にフォールスルーします。SIGINT / SIGTERM は runQwenServeonSignal パスを通じて終了します。

10. HTTP ルートファイルの分割

主要なアセンブリは server.ts 内の createServeApp() で行われ、ミドルウェアを接続し、焦点を絞ったルートモジュールをマウントします。

ルートファイルマウントエントリ
/healthpackages/cli/src/serve/routes/health.tshealthRoutes.register()
/daemon/statuspackages/cli/src/serve/routes/daemon-status.tsregisterDaemonStatusRoutes()
/capabilities、ワークスペースの初期化/ツール/MCP 変更ルート、ACP HTTP ブリッジpackages/cli/src/serve/server.tscreateServeApp() 内で直接登録
ワークスペースのステータス、環境、プリフライト、MCP/ツール/プロバイダー/スキルのサマリーpackages/cli/src/serve/routes/workspace-status.tsregisterWorkspaceStatusRoutes(), registerWorkspaceDiagnosticStatusRoutes()
ワークスペース拡張機能と拡張機能の操作packages/cli/src/serve/routes/workspace-extensions.tsregisterWorkspaceExtensionRoutes()
/workspace/memory (GET/POST)packages/cli/src/serve/workspace-memory.tsmountWorkspaceMemoryRoutes()
すべての /workspace/agents CRUD ルートpackages/cli/src/serve/workspace-agents.tsmountWorkspaceAgentsRoutes()
GET /file, /file/bytes, /list, /glob, /statpackages/cli/src/serve/routes/workspace-file-read.tsregisterWorkspaceFileReadRoutes()
POST /file/write, /file/editpackages/cli/src/serve/routes/workspace-file-write.tsregisterWorkspaceFileWriteRoutes()
ワークスペースのセットアップ、信頼、設定、権限、および音声ルートpackages/cli/src/serve/routes/workspace-*.tsregisterWorkspaceSetupGithubRoutes(), registerWorkspaceTrustRoutes() など
ワークスペースの認証プロバイダーとデバイスフローのルートpackages/cli/src/serve/routes/workspace-auth.tsregisterWorkspaceAuthRoutes()
セッションのライフサイクル、プロンプト、メタデータ、言語、シェル、リキャップ、リワインド、ブランチ、およびリストルートpackages/cli/src/serve/routes/session.tsregisterSessionRoutes()
GET /session/:id/events SSE ストリームpackages/cli/src/serve/routes/sse-events.tsregisterSseEventsRoutes()
権限レスポンスルートpackages/cli/src/serve/routes/permission.tsregisterPermissionRoutes()

完全なルートおよびワイヤープロトコルのリファレンスについては、../qwen-serve-protocol.md を参照してください。アーキテクチャについては、01-architecture.md を参照してください。

11. グレースフルシャットダウンとハードシャットダウン

  • 最初の SIGINT / SIGTERM -> runQwenServeonSignal -> 2段階のグレースフルシャットダウン:
    1. bridge.shutdown(): 各チャネルに KILL_HARD_DEADLINE_MS(10秒)が与えられ、その後 channel.kill() が実行されます。
    2. server.close(): 処理中のリクエストがドレインされ、SHUTDOWN_FORCE_CLOSE_MS(5秒)で closeAllConnections() がトリガーされ、その後 2 番目の 2 秒のデッドラインが適用されます。
  • すでに終了処理中の 2 回目の SIGINT / SIGTERM -> bridge.killAllSync() がすべての ACP 子プロセスを同期的に SIGKILL し、オーファンプロセスを回避するために process.exit(1) を呼び出します。

runQwenServe によって返される RunHandle.close() は、エンベッダーやテスト用のプログラムによる同等のシャットダウン手段です。

12. 組み込み呼び出し(CLI をバイパス)

import { runQwenServe } from '@qwen-code/qwen-code/serve'; const handle = await runQwenServe({ port: 0, // ephemeral hostname: '127.0.0.1', mode: 'http-bridge', maxSessions: 20, workspace: '/abs/path/to/repo', }); console.log(`Daemon at ${handle.url}`); // ... call handle.bridge directly or access handle.server await handle.close(); // programmatic shutdown

または、Express アプリを直接取得し、リスナーのライフサイクルを自分でバインドします。この形式は Live/Conversations を使用する組み込みに必要です。

import { createServer } from 'node:http'; import type { AddressInfo } from 'node:net'; import { createServeApp, getServeAppLifecycle, } from '@qwen-code/qwen-code/serve'; let actualPort = 0; const app = createServeApp( { port: 0, hostname: '127.0.0.1', mode: 'http-bridge', maxSessions: 20, }, () => actualPort, { /* deps: bridge, fsFactory, ... */ }, ); const lifecycle = getServeAppLifecycle(app); const server = createServer(app); lifecycle.bindServer(server); await new Promise<void>((resolve, reject) => { server.once('error', reject); server.listen(0, '127.0.0.1', () => resolve()); }); actualPort = (server.address() as AddressInfo).port; console.log('listening on', server.address()); // 受け入れを停止し、アプリの作業を drain し、リスナーをクローズし、所有権を解放します。 await lifecycle.close();

生の server.close() を呼び出すと、同じイベント駆動のクリーンアップが開始されますが、プロセスが存続しない限りベストエフォートに過ぎません。シャットダウンエラーを受け取るには常に lifecycle.close() を待機してください。サーバーがバインドされていない場合、Live/Conversations のリクエストは fail closed になりますが、Ordinary-only のアプリの動作は変わりません。

注: createServeApp を直接呼び出す場合、デフォルトでは fsFactory.trusted = false となります。エージェント側の ACP writeTextFileuntrusted_workspace として拒否され、stderr に警告が一度出力されます。明示的な信頼を持つ deps.fsFactory を注入するか、deps.bridge を注入するか、信頼ゲートされたデフォルトの動作を受け入れてください。

13. デバッグのレシピ

19-observability.md のデバッグセクションを参照してください。一般的なコマンドは次のとおりです。

# デーモンは生存しているか? curl http://127.0.0.1:4170/health # どのケーパビリティが公開されているか? curl -s http://127.0.0.1:4170/capabilities | jq # デーモンホストの準備状況 curl -s http://127.0.0.1:4170/workspace/preflight | jq # ライブ SSE のテール curl -N -H 'Accept: text/event-stream' \ -H 'Last-Event-ID: 0' \ 'http://127.0.0.1:4170/session/<sid>/events' # 詳細ログ QWEN_SERVE_DEBUG=1 qwen serve

リファレンス

  • CLI エントリ: packages/cli/src/commands/serve.ts
  • ブートストラップ: packages/cli/src/serve/run-qwen-serve.ts
  • Express ファクトリ: packages/cli/src/serve/server.ts
  • ミドルウェア: packages/cli/src/serve/auth.ts
  • ブリッジファクトリ: packages/acp-bridge/src/bridge.ts
  • Web Shell 静的マウント: packages/cli/src/serve/web-shell-static.ts
  • ユーザードキュメント: ../../users/qwen-serve.md
  • ワイヤープロトコル: ../qwen-serve-protocol.md
Last updated on