refactor(cli): rename serve files to kebab-case (#5592)

Rename the PR1 serve and daemon adapter files from issue #5576 to kebab-case and update current imports, tests, comments, and developer docs to match.

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
Co-authored-by: Shaojin Wen <shaojin.wensj@alibaba-inc.com>
This commit is contained in:
jinye 2026-06-22 13:13:07 +08:00 committed by GitHub
parent ec99a7f2db
commit b4705b2534
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
81 changed files with 186 additions and 186 deletions

View file

@ -1142,7 +1142,7 @@ packages/core/src/config/config.ts # setMcpTransportPool / getMcpT
packages/cli/src/acp-integration/acpAgent.ts # QwenAgent.mcpPool construction; broadcastBudgetEvent;
# newSessionConfig wires pool into Config;
# killSession calls pool.releaseSession
packages/cli/src/serve/runQwenServe.ts # pass --mcp-pool-transports + budget env to ACP child
packages/cli/src/serve/run-qwen-serve.ts # pass --mcp-pool-transports + budget env to ACP child
packages/cli/src/serve/httpAcpBridge.ts # buildWorkspaceMcpStatus reads pool;
# restartMcpServer extMethod returns RestartResult[]
packages/cli/src/serve/capabilities.ts # advertise mcp_workspace_pool
@ -1160,7 +1160,7 @@ Per maintainer's feature-cohesive batch guidance (#4175 branching strategy 2026-
| 1 | `refactor(core): split McpClient.discover into pure tool/prompt list and unify connect paths` | Add `discoverAndReturn()`; extract shared `establishConnection()` used by both `McpClient.connect()` and `connectToMcpServer()` factory; legacy `discover()` becomes thin wrapper that registers (preserves standalone qwen behavior). Zero observable behavior change. | `mcp-client.ts`, `mcp-client.test.ts` |
| 2 | `feat(core): McpTransportPool + SessionMcpView` | Pool core: `fingerprint`, refcount, `spawnInFlight` dedupe, `sessionToEntries` reverse index, drain state machine, snapshot replay on attach, generation guard, tool+prompt dual fan-out, per-session trust copy. Mock McpClient for unit tests. No production wiring. | new `mcp-transport-pool.ts`, `mcp-pool-key.ts`, `mcp-pool-entry.ts`, `session-mcp-view.ts`, `mcp-pool-events.ts` + tests |
| 3 | `feat(core): cross-platform descendant pid sweep + pool health monitor` | `listDescendantPids` (Unix `pgrep -P` recursive, Windows PowerShell CIM); unified health monitor inside `PoolEntry` (interval check + failure count + reconnect backoff per §6.6); subprocess-spawn integration tests gated on `QWEN_INTEGRATION === '1'`. | new `pid-descendants.ts` + tests; `mcp-pool-entry.ts` |
| 4 | `feat(serve): wire McpTransportPool into QwenAgent daemon mode` | `Config.setMcpTransportPool` + `getMcpTransportPool`; `ToolRegistry` threads pool into `McpClientManager`; `McpClientManager` optional `pool?` ctor param; `acpAgent.QwenAgent` constructs pool at init; `newSessionConfig` injection; `killSession` calls `pool.releaseSession`; SDK MCP + HTTP/SSE bypass via `createUnpooledConnection`; CLI flags `--mcp-pool-transports`, `--mcp-pool-drain-ms`, `--no-mcp-pool`. | `config.ts`, `tool-registry.ts`, `mcp-client-manager.ts`, `acpAgent.ts`, `runQwenServe.ts` |
| 4 | `feat(serve): wire McpTransportPool into QwenAgent daemon mode` | `Config.setMcpTransportPool` + `getMcpTransportPool`; `ToolRegistry` threads pool into `McpClientManager`; `McpClientManager` optional `pool?` ctor param; `acpAgent.QwenAgent` constructs pool at init; `newSessionConfig` injection; `killSession` calls `pool.releaseSession`; SDK MCP + HTTP/SSE bypass via `createUnpooledConnection`; CLI flags `--mcp-pool-transports`, `--mcp-pool-drain-ms`, `--no-mcp-pool`. | `config.ts`, `tool-registry.ts`, `mcp-client-manager.ts`, `acpAgent.ts`, `run-qwen-serve.ts` |
| 5 | `feat(serve): pool-aware status + restart routes` | `QwenAgent.getMcpPoolAccounting` extMethod; `httpAcpBridge.buildWorkspaceMcpStatus` pool-first + bootstrap-session fallback; `restartMcpServer` accepts `?entryIndex=` and returns `RestartResult[]`; `entryCount` + `entrySummary[].entryIndex` on cell; capability tags `mcp_workspace_pool` + `mcp_pool_restart`. | `httpAcpBridge.ts`, `capabilities.ts`, SDK types |
| 6 | `feat(serve): graduate MCP budget guardrails to workspace scope` | Move `tryReserveSlot`/`releaseSlotName`/hysteresis state machine from `McpClientManager` to pool; remove per-session `setMcpBudgetEventCallback` wiring in `acpAgent.newSessionConfig`; `QwenAgent.broadcastBudgetEvent` fan-out; snapshot cell `scope: 'workspace'`; SDK `scope?` additive field; `isWorkspaceScopedBudgetEvent` helper; inline doc updates. | `mcp-transport-pool.ts`, `mcp-client-manager.ts`, `acpAgent.ts`, `httpAcpBridge.ts`, SDK |

View file

@ -85,7 +85,7 @@ Use these anchors when moving from the docs into the latest `main` code:
| Surface | Implementation anchors | Primary docs |
| ----------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------- |
| Bootstrap and HTTP assembly | `packages/cli/src/serve/runQwenServe.ts`, `server.ts`, `/demo` | [`02`](./02-serve-runtime.md), [`20`](./20-quickstart-operations.md) |
| Bootstrap and HTTP assembly | `packages/cli/src/serve/run-qwen-serve.ts`, `server.ts`, `/demo` | [`02`](./02-serve-runtime.md), [`20`](./20-quickstart-operations.md) |
| ACP bridge and session multiplexing | `packages/acp-bridge/src/bridge.ts`, `packages/acp-bridge/src/bridgeTypes.ts`, `@qwen-code/acp-bridge` | [`03`](./03-acp-bridge.md), [`08`](./08-session-lifecycle.md) |
| Permission mediation | `packages/acp-bridge/src/permissionMediator.ts`, `fromLoopback: boolean`, `policy.*` | [`04`](./04-permission-mediation.md), [`12`](./12-auth-security.md) |
| MCP transport pool | `packages/core/src/tools/mcp-transport-pool.ts`, `mcp-pool-key.ts`, `pid-descendants.ts`, `session-mcp-view.ts`, `/mcp refresh`, `MCPCallInterruptedError` | [`05`](./05-mcp-transport-pool.md), [`06`](./06-mcp-budget-guardrails.md) |
@ -94,7 +94,7 @@ Use these anchors when moving from the docs into the latest `main` code:
| Event schema and SSE writer | `packages/sdk-typescript/src/daemon/events.ts`, `packages/cli/src/serve/server.ts`, `formatSseFrame`, `packages/cli/src/acp-integration/session/emitters/ToolCallEmitter.ts`, `ToolCallEmitter.resolveToolProvenance`, `tool_call.provenance`, `serverId` | [`09`](./09-event-schema.md), [`10`](./10-event-bus.md) |
| Event resync | `state_resync_required`, `awaitingResync`, `RESYNC_PASSTHROUGH_TYPES`, `asKnownDaemonEvent`, `unrecognizedKnownEventCount` | [`09`](./09-event-schema.md), [`10`](./10-event-bus.md) |
| Capabilities | `packages/cli/src/serve/capabilities.ts`, `mcp_server_restart_refused.reason`, `MCP_RESTART_REFUSED_REASONS.has` | [`11`](./11-capabilities-versioning.md) |
| Auth and device flow | `packages/cli/src/serve/auth.ts`, `packages/cli/src/serve/auth/deviceFlow.ts` | [`12`](./12-auth-security.md) |
| Auth and device flow | `packages/cli/src/serve/auth.ts`, `packages/cli/src/serve/auth/device-flow.ts` | [`12`](./12-auth-security.md) |
| TypeScript SDK daemon client | `packages/sdk-typescript/src/daemon/{DaemonClient,DaemonSessionClient,DaemonAuthFlow,sse,events,types}.ts`, `MCP_RESTART_DEFAULT_TIMEOUT_MS` | [`13`](./13-sdk-daemon-client.md) |
| Shared UI transcript layer | `DaemonUiEventType`, `DaemonSessionProvider`, `packages/webui/src/daemon/` | [`13`](./13-sdk-daemon-client.md), [`14`](./14-cli-tui-adapter.md), [`../daemon-ui/README.md`](../daemon-ui/README.md) |
| Channels and IDE adapters | `packages/channels/`, `packages/vscode-ide-companion/src/services/daemonIdeConnection.ts` | [`15`](./15-channel-adapters.md), [`16`](./16-vscode-ide-adapter.md) |
@ -152,7 +152,7 @@ Use these anchors when moving from the docs into the latest `main` code:
| Surface | Status |
| ------------------------------------------------ | -------------------------------------------------------------------------------------------------------------- |
| `docs/developers/daemon-client-adapters/tui.md` | Historical draft for the old `DaemonTuiAdapter` spike; current shared UI transcript architecture is in doc 14. |
| `packages/cli/src/ui/daemon/DaemonTuiAdapter.ts` | Legacy experimental adapter still in-tree. New shared UI work should prefer SDK `daemon/ui/*`. |
| `packages/cli/src/ui/daemon/daemon-tui-adapter.ts` | Legacy experimental adapter still in-tree. New shared UI work should prefer SDK `daemon/ui/*`. |
| `--no-http-bridge` | Accepted for compatibility but falls back to http-bridge and prints stderr. |
### Forward compatibility

View file

@ -64,12 +64,12 @@ The daemon process and the ACP child are connected by an `AcpChannel` (default:
```mermaid
flowchart TB
subgraph serve["packages/cli/src/serve"]
RQS["runQwenServe.ts<br/>(bootstrap)"]
RQS["run-qwen-serve.ts<br/>(bootstrap)"]
SRV["server.ts (Express)"]
CAP["capabilities.ts"]
AUTH["auth.ts"]
FSM["fs/ (sandbox)"]
DSP["daemonStatusProvider.ts"]
DSP["daemon-status-provider.ts"]
end
subgraph br["packages/acp-bridge"]
@ -99,7 +99,7 @@ flowchart TB
subgraph adapters["Adapters"]
WUIP["webui/src/daemon/<br/>DaemonSessionProvider.tsx"]
TUIA["cli/src/ui/daemon/<br/>DaemonTuiAdapter.ts"]
TUIA["cli/src/ui/daemon/<br/>daemon-tui-adapter.ts"]
CHB["channels/base/<br/>DaemonChannelBridge.ts"]
DT["channels/dingtalk"]
WX["channels/weixin"]
@ -327,7 +327,7 @@ The two-phase shutdown matters because in-flight HTTP requests, in-flight SSE su
| Concern | File |
| -------------------- | ----------------------------------------------------------- |
| Bootstrap | `packages/cli/src/serve/runQwenServe.ts` |
| Bootstrap | `packages/cli/src/serve/run-qwen-serve.ts` |
| Express app | `packages/cli/src/serve/server.ts` |
| Capability registry | `packages/cli/src/serve/capabilities.ts` |
| Auth middleware | `packages/cli/src/serve/auth.ts` |

View file

@ -16,7 +16,7 @@
## Architecture
**Entry**: `runQwenServe(opts, deps)` in `packages/cli/src/serve/runQwenServe.ts`. Returns a `RunHandle` (`{ url, port, close, ... }`).
**Entry**: `runQwenServe(opts, deps)` in `packages/cli/src/serve/run-qwen-serve.ts`. Returns a `RunHandle` (`{ url, port, close, ... }`).
**App factory**: `createServeApp(opts, getPort, deps)` in `packages/cli/src/serve/server.ts`. Builds the Express `Application`. Direct embedders and tests call it without the bootstrap wrapper.
@ -40,20 +40,20 @@
| Path | Role |
| ------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `serve/fs/` | `WorkspaceFileSystem` factory plus `policy.ts` (size/trust/binary checks), `paths.ts` (canonicalize, resolveWithin, symlink rejection), `audit.ts`, and typed `FsError` values. |
| `serve/routes/workspaceFileRead.ts`, `workspaceFileWrite.ts` | HTTP handlers for `GET /file`, `GET /file/bytes`, `POST /file/write`, and `POST /file/edit`. |
| `serve/workspaceMemory.ts` | `GET/POST /workspace/memory` (QWEN.md CRUD). |
| `serve/workspaceAgents.ts` | `GET/POST/DELETE /workspace/agents` (subagent CRUD). |
| `serve/daemonStatusProvider.ts` | Env snapshot plus daemon-host preflight cells: Node version, CLI entry, workspace stat, ripgrep, git, npm. |
| `serve/permissionAudit.ts` | `PermissionAuditRing` (512-entry FIFO) and `createPermissionAuditPublisher`. |
| `serve/auth/deviceFlow.ts`, `qwenDeviceFlowProvider.ts` | Device-flow OAuth routes. See [`12-auth-security.md`](./12-auth-security.md). |
| `serve/routes/workspace-file-read.ts`, `workspace-file-write.ts` | HTTP handlers for `GET /file`, `GET /file/bytes`, `POST /file/write`, and `POST /file/edit`. |
| `serve/workspace-memory.ts` | `GET/POST /workspace/memory` (QWEN.md CRUD). |
| `serve/workspace-agents.ts` | `GET/POST/DELETE /workspace/agents` (subagent CRUD). |
| `serve/daemon-status-provider.ts` | Env snapshot plus daemon-host preflight cells: Node version, CLI entry, workspace stat, ripgrep, git, npm. |
| `serve/permission-audit.ts` | `PermissionAuditRing` (512-entry FIFO) and `createPermissionAuditPublisher`. |
| `serve/auth/device-flow.ts`, `qwen-device-flow-provider.ts` | Device-flow OAuth routes. See [`12-auth-security.md`](./12-auth-security.md). |
| `serve/daemonLogger.ts` | `DaemonLogger` structured file logs. See [`19-observability.md`](./19-observability.md). |
| `serve/debugMode.ts` | Shared `isServeDebugMode()` predicate controlling verbose error context in HTTP responses. |
| `serve/debug-mode.ts` | Shared `isServeDebugMode()` predicate controlling verbose error context in HTTP responses. |
| `serve/acpHttp/` | ACP Streamable HTTP transport (RFD #721), mounted at `/acp`. Seven files implement JSON-RPC POST, SSE GET, DELETE teardown, and shared bridge usage in parallel with the REST surface. |
| `serve/demo.ts` | Self-contained inline HTML for `GET /demo`: browser debug console with chat UI, event log, and workspace inspector. On loopback without `--require-auth`, it is registered **before** `bearerAuth`; on non-loopback or with `--require-auth`, it is registered **after** `bearerAuth`. Served with CSP `default-src 'none'; script-src 'unsafe-inline'; style-src 'unsafe-inline'; connect-src 'self'; frame-ancestors 'none'` plus `X-Frame-Options: DENY`. |
**Re-export shims** for compatibility with pre-F1 import paths:
- `serve/eventBus.ts` -> `@qwen-code/acp-bridge/eventBus`
- `serve/event-bus.ts` -> `@qwen-code/acp-bridge/eventBus`
- `serve/status.ts` -> `@qwen-code/acp-bridge/status`
- `serve/httpAcpBridge.ts` -> `@qwen-code/acp-bridge`
@ -144,12 +144,12 @@ See [`17-configuration.md`](./17-configuration.md) for the merged reference.
## References
- `packages/cli/src/serve/runQwenServe.ts` (bootstrap, boot validation, graceful shutdown)
- `packages/cli/src/serve/run-qwen-serve.ts` (bootstrap, boot validation, graceful shutdown)
- `packages/cli/src/serve/server.ts` (`createServeApp()`, middleware and route assembly)
- `packages/cli/src/serve/auth.ts` (CORS, Host allowlist, bearer auth, mutation gate)
- `packages/cli/src/serve/rateLimit.ts` (per-tier HTTP rate limit)
- `packages/cli/src/serve/rate-limit.ts` (per-tier HTTP rate limit)
- `packages/cli/src/serve/capabilities.ts` (capability registry and conditional advertisement)
- `packages/cli/src/serve/types.ts` (`ServeOptions`, `CapabilitiesEnvelope`)
- `packages/cli/src/serve/daemonStatusProvider.ts`
- `packages/cli/src/serve/permissionAudit.ts`
- `packages/cli/src/serve/daemon-status-provider.ts`
- `packages/cli/src/serve/permission-audit.ts`
- Issues: [#3803](https://github.com/QwenLM/qwen-code/issues/3803), [#4175](https://github.com/QwenLM/qwen-code/issues/4175)

View file

@ -251,7 +251,7 @@ context threaded through bridge calls; it carries `clientId`,
- `MCP_RESTART_TIMEOUT_MS = 300_000` (5 min) — the bridge timeout for `/workspace/mcp/:server/restart` is intentionally large because `McpClientManager.MAX_DISCOVERY_TIMEOUT_MS` can be up to 5 min for stdio servers. A shorter deadline would produce false timeouts while the ACP child kept reconnecting in the background.
- `BridgeOptions.eventRingSize > 1_000_000` throws at construction.
- `connection.unstable_resumeSession` is exposed through the stable `session_resume` daemon capability; `unstable_session_resume` remains advertised as a deprecated compatibility alias for older SDKs. Clients should feature-detect `session_resume`.
- The bridge package is `@qwen-code/acp-bridge` and is consumed through re-export shims in `serve/eventBus.ts`, `serve/status.ts`, `serve/httpAcpBridge.ts` for backward compatibility with pre-F1 import paths. New code should import directly.
- The bridge package is `@qwen-code/acp-bridge` and is consumed through re-export shims in `serve/event-bus.ts`, `serve/status.ts`, `serve/httpAcpBridge.ts` for backward compatibility with pre-F1 import paths. New code should import directly.
## References

View file

@ -215,7 +215,7 @@ unanimity for M = 4, use the same field.
## Boot-time policy validation
`runQwenServe.validatePolicyConfig(policyConfig)`
(`packages/cli/src/serve/runQwenServe.ts`) validates merged `settings.json`
(`packages/cli/src/serve/run-qwen-serve.ts`) validates merged `settings.json`
`policy.*` at boot and throws `InvalidPolicyConfigError` for operator mistakes:
- `policy.permissionStrategy` is set but not in the four supported modes. The
@ -270,5 +270,5 @@ mechanism does not exist in v1.
- `packages/acp-bridge/src/permissionMediator.ts` (F3 mediator implementation)
- `packages/acp-bridge/src/bridgeClient.ts` (uses structural sub-typing on `PermissionMediator`)
- `packages/acp-bridge/src/bridgeErrors.ts` (`CancelSentinelCollisionError`, `InvalidPermissionOptionError`, `PermissionForbiddenError`)
- `packages/cli/src/serve/permissionAudit.ts` (audit ring + publisher)
- `packages/cli/src/serve/permission-audit.ts` (audit ring + publisher)
- Issue: [#4175](https://github.com/QwenLM/qwen-code/issues/4175) F3 series.

View file

@ -34,7 +34,7 @@ The HTTP file routes (`GET /file`, `GET /file/bytes`, `POST /file/write`, `POST
| `policy.ts` | `MAX_READ_BYTES`, `MAX_WRITE_BYTES`, `BINARY_PROBE_BYTES`, `assertTrustedForIntent`, `detectBinary`, `enforceReadBytesSize`, `enforceReadSize`, `enforceWriteSize`, `shouldIgnore`. |
| `audit.ts` | `FS_ACCESS_EVENT_TYPE`, `FS_DENIED_EVENT_TYPE`, `createAuditPublisher`, audit payload types. |
| `errors.ts` | `FsError` class, `isFsError`, `FsErrorKind` union (14 kinds), `FsErrorStatus` union (`400 / 403 / 404 / 409 / 413 / 422 / 500 / 503`). |
| `workspaceFileSystem.ts` | `createWorkspaceFileSystemFactory`, `WorkspaceFileSystem` (the orchestrator that reads/writes/lists), `WriteMode`, `ContentHash`, `FsEntry`, `FsStat`, `ListOptions`, `GlobOptions`, `ReadTextOptions`, `ReadBytesOptions`, `WriteTextAtomicOptions`. |
| `workspace-file-system.ts` | `createWorkspaceFileSystemFactory`, `WorkspaceFileSystem` (the orchestrator that reads/writes/lists), `WriteMode`, `ContentHash`, `FsEntry`, `FsStat`, `ListOptions`, `GlobOptions`, `ReadTextOptions`, `ReadBytesOptions`, `WriteTextAtomicOptions`. |
### `FsErrorKind` taxonomy
@ -66,7 +66,7 @@ interface BridgeFileSystem {
}
```
This is the injection point for ACP `readTextFile` / `writeTextFile`. Bridge tests and Mode A embedded callers can omit it on `BridgeOptions`; `BridgeClient` falls back to its inline `fs.readFile` / `fs.writeFile` proxy (preserves pre-F1 behavior). Production `qwen serve` wires `BridgeFileSystem` through `createBridgeFileSystemAdapter(fsFactory)` (`packages/cli/src/serve/bridgeFileSystemAdapter.ts`) so agent-side ACP writes pick up the same TOCTOU, symlink, trust-gate, and audit gates the HTTP routes use.
This is the injection point for ACP `readTextFile` / `writeTextFile`. Bridge tests and Mode A embedded callers can omit it on `BridgeOptions`; `BridgeClient` falls back to its inline `fs.readFile` / `fs.writeFile` proxy (preserves pre-F1 behavior). Production `qwen serve` wires `BridgeFileSystem` through `createBridgeFileSystemAdapter(fsFactory)` (`packages/cli/src/serve/bridge-file-system-adapter.ts`) so agent-side ACP writes pick up the same TOCTOU, symlink, trust-gate, and audit gates the HTTP routes use.
Two defensive gates the adapter MUST replicate (because the inline proxy is fully bypassed when the adapter is injected):
@ -210,7 +210,7 @@ flowchart LR
- `@qwen-code/qwen-code-core``Ignore`, `isBinaryFile`, `Config.isTrustedFolder()`.
- `node:fs`, `node:path`, `node:crypto`.
- `@qwen-code/acp-bridge``BridgeFileSystem` contract on the ACP side.
- HTTP routes: `packages/cli/src/serve/routes/workspaceFileRead.ts`, `workspaceFileWrite.ts`.
- HTTP routes: `packages/cli/src/serve/routes/workspace-file-read.ts`, `workspace-file-write.ts`.
## Configuration
@ -239,7 +239,7 @@ flowchart LR
- `packages/cli/src/serve/fs/policy.ts`
- `packages/cli/src/serve/fs/errors.ts`
- `packages/cli/src/serve/fs/audit.ts`
- `packages/cli/src/serve/fs/workspaceFileSystem.ts`
- `packages/cli/src/serve/bridgeFileSystemAdapter.ts`
- `packages/cli/src/serve/fs/workspace-file-system.ts`
- `packages/cli/src/serve/bridge-file-system-adapter.ts`
- `packages/acp-bridge/src/bridgeFileSystem.ts`
- HTTP route reference: [`../qwen-serve-protocol.md`](../qwen-serve-protocol.md).

View file

@ -183,7 +183,7 @@ Already-aborted signals at subscribe time call `onAbort()` synchronously before
- Consumed by `packages/acp-bridge/src/bridge.ts` (`BridgeClient.sessionUpdate` / `BridgeClient.extNotification``events.publish(...)`).
- Consumed by `packages/cli/src/serve/server.ts` (SSE route handler → `events.subscribe(...)` then formats `BridgeEvent` to SSE wire frames).
- Re-export shim: `packages/cli/src/serve/eventBus.ts` → `@qwen-code/acp-bridge/eventBus`.
- Re-export shim: `packages/cli/src/serve/event-bus.ts` → `@qwen-code/acp-bridge/eventBus`.
- SDK consumer: `packages/sdk-typescript/src/daemon/sse.ts` (`parseSseStream`), then `asKnownDaemonEvent` (see [`09-event-schema.md`](./09-event-schema.md), [`13-sdk-daemon-client.md`](./13-sdk-daemon-client.md)).
## Configuration

View file

@ -24,7 +24,7 @@ This doc walks through each layer and the explicit invariants the boot path enfo
### Boot-time refuse rules
In `runQwenServe.ts`:
In `run-qwen-serve.ts`:
```ts
if (!isLoopbackBind(opts.hostname) && !token) {
@ -180,10 +180,10 @@ Separate OAuth surface for provider authentication (Qwen OAuth, etc.):
SSE events `auth_device_flow_{started, throttled, authorized, failed, cancelled}` fan-out flow state to all subscribers so multi-client UIs stay in sync. See [`09-event-schema.md`](./09-event-schema.md).
Implementation: `packages/cli/src/serve/auth/deviceFlow.ts` + `qwenDeviceFlowProvider.ts`.
Implementation: `packages/cli/src/serve/auth/device-flow.ts` + `qwen-device-flow-provider.ts`.
**Log injection / Trojan Source defense**: `sanitizeForStderr(value)`
(`deviceFlow.ts`) replaces ASCII control characters and Unicode control
(`device-flow.ts`) replaces ASCII control characters and Unicode control
characters with `?`. A malicious IdP could otherwise forge log lines or hide
payloads:
@ -269,8 +269,8 @@ sequenceDiagram
## Dependencies
- `node:crypto``createHash`, `timingSafeEqual`.
- `packages/cli/src/serve/loopbackBinds.ts` — `isLoopbackBind`.
- `packages/cli/src/serve/auth/deviceFlow.ts` — device-flow state machine.
- `packages/cli/src/serve/loopback-binds.ts` — `isLoopbackBind`.
- `packages/cli/src/serve/auth/device-flow.ts` — device-flow state machine.
- `@qwen-code/acp-bridge` — surfaces device-flow events on the per-session SSE bus.
## Configuration
@ -295,9 +295,9 @@ sequenceDiagram
## References
- `packages/cli/src/serve/auth.ts` (entire file)
- `packages/cli/src/serve/runQwenServe.ts` (refuse rules)
- `packages/cli/src/serve/loopbackBinds.ts`
- `packages/cli/src/serve/auth/deviceFlow.ts`
- `packages/cli/src/serve/auth/qwenDeviceFlowProvider.ts`
- `packages/cli/src/serve/run-qwen-serve.ts` (refuse rules)
- `packages/cli/src/serve/loopback-binds.ts`
- `packages/cli/src/serve/auth/device-flow.ts`
- `packages/cli/src/serve/auth/qwen-device-flow-provider.ts`
- User-facing threat model: [`../../users/qwen-serve.md`](../../users/qwen-serve.md).
- Wire reference: [`../qwen-serve-protocol.md`](../qwen-serve-protocol.md).

View file

@ -1,6 +1,6 @@
# Shared UI Transcript Layer
> **Current status**: `packages/cli/src/ui/daemon/DaemonTuiAdapter.ts` is still present on `main` as a legacy experimental CLI-side adapter. This document describes the newer SDK-side shared UI transcript layer: reusable daemon event normalization and transcript primitives that any UI host can consume, including Web, TUI, IDE, and IM channels. CLI TUI, channel, and VS Code IDE migrations are follow-up work.
> **Current status**: `packages/cli/src/ui/daemon/daemon-tui-adapter.ts` is still present on `main` as a legacy experimental CLI-side adapter. This document describes the newer SDK-side shared UI transcript layer: reusable daemon event normalization and transcript primitives that any UI host can consume, including Web, TUI, IDE, and IM channels. CLI TUI, channel, and VS Code IDE migrations are follow-up work.
## Overview
@ -148,7 +148,7 @@ The web UI can now connect directly to daemon HTTP+SSE and render a transcript.
[`../daemon-ui/MIGRATION.md`](../daemon-ui/MIGRATION.md) provides a v2 incremental guide for web chat and web terminal adapters. It explicitly calls out that **CLI TUI, channel base, and VS Code IDE are not migrated by that PR**; each will move in follow-up PRs and use the conformance suite to preserve rendering parity.
## Relationship to legacy `DaemonTuiAdapter.ts`
## Relationship to legacy `daemon-tui-adapter.ts`
| Dimension | Legacy CLI `DaemonTuiAdapter` | New shared transcript layer |
| ----------------- | --------------------------------------------------------------- | -------------------------------------------------------------- |
@ -175,7 +175,7 @@ The web UI can now connect directly to daemon HTTP+SSE and render a transcript.
## Caveats and known limits
- **`DaemonTuiAdapter.ts` still exists**. It is the CLI package's legacy experimental adapter. New code should prefer SDK `ui/*`: `normalizeDaemonEvent`, `reduceDaemonTranscriptEvents`, and `DaemonTranscriptBlock`.
- **`daemon-tui-adapter.ts` still exists**. It is the CLI package's legacy experimental adapter. New code should prefer SDK `ui/*`: `normalizeDaemonEvent`, `reduceDaemonTranscriptEvents`, and `DaemonTranscriptBlock`.
- **CLI TUI, channel base, and VS Code IDE are not migrated yet**. They still maintain their own rendering logic. The `docs/developers/daemon-client-adapters/` directory still has `ide.md`, `channel-web.md`, and the historical `tui.md` draft; the newer `web-ui.md` covers the web UI adapter design.
- **`eventId` is the primary ordering key**. `createdAt` remains as a deprecated alias (`clientReceivedAt`). New code should use `selectTranscriptBlocksOrderedByEventId(state)`. `MIGRATION.md` shows the code diff for switching from `createdAt` ordering to `eventId` ordering.
- **Unknown wire types normalize to `debug`**. They are no longer dropped as in the old adapter. Renderers do not show `debug` by default; hosts must opt in to display it.

View file

@ -137,7 +137,7 @@ The daemon reads settings once at boot through `loadSettings(boundWorkspace)` in
| `DEFAULT_MAX_PENDING_PER_SESSION` | `bridge.ts` | `64` | Aligned with `DEFAULT_MAX_SUBSCRIBERS`. |
| `MAX_RESOLVED_PERMISSION_RECORDS` | `permissionMediator.ts` | `512` | FIFO for recently resolved permissions. |
| `KILL_HARD_DEADLINE_MS` | `spawnChannel.ts` | `10_000` | Per-channel graceful shutdown window. |
| `SHUTDOWN_FORCE_CLOSE_MS` | `runQwenServe.ts` | `5_000` | HTTP server force-close timer. |
| `SHUTDOWN_FORCE_CLOSE_MS` | `run-qwen-serve.ts` | `5_000` | HTTP server force-close timer. |
| `MAX_READ_BYTES` | `fs/policy.ts` | `256 * 1024` | Read cap. |
| `MAX_WRITE_BYTES` | `fs/policy.ts` | `5 * 1024 * 1024` | Write cap. |
| `MAX_DISPLAY_NAME_LENGTH` | `bridge.ts` | `256` | Session `displayName` cap. |

View file

@ -60,13 +60,13 @@ Typed classes thrown by the bridge / mediator. Most carry an HTTP status via the
| `BridgeTimeoutError` | 504 | Bridge-level wallclock exceeded. | Retry; investigate underlying slowness. |
| `MissingCliEntryError` | 500 | The `qwen` CLI entry file is missing (defined in `status.ts`, not `bridgeErrors.ts`). | Confirm the CLI install is complete; check that `packages/cli/index.ts` exists. |
## Boot-time configuration errors (`packages/cli/src/serve/runQwenServe.ts`)
## Boot-time configuration errors (`packages/cli/src/serve/run-qwen-serve.ts`)
| Class | When | Remediation |
| -------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `InvalidPolicyConfigError` | `validatePolicyConfig()` rejects merged settings: unknown `policy.permissionStrategy` (validated against `SERVE_CAPABILITY_REGISTRY.permission_mediation.modes`) or non-positive-integer `policy.consensusQuorum`. Boot fails explicitly. | Fix the offending field in `settings.json`. The class supports `instanceof`; `runQwenServe` uses it to distinguish policy mismatch from settings read I/O failures, which fall back to defaults. |
## Device Flow auth (`packages/cli/src/serve/auth/deviceFlow.ts`)
## Device Flow auth (`packages/cli/src/serve/auth/device-flow.ts`)
| Class | When | Notes |
| ---------------------------- | ---------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

View file

@ -20,7 +20,7 @@
| `/workspace/skills`, `/workspace/providers` | Routes | ACP-side live snapshots; return empty idle data when no session exists. |
| Per-session SSE | `GET /session/:id/events` | Real-time event stream. |
| `/demo` debug console | `GET /demo` (`packages/cli/src/serve/demo.ts`) | Browser-accessible single-page console: chat, event log, workspace inspector, and permission UX. On loopback, `http://127.0.0.1:4170/demo` is the quickest end-to-end validation path without writing SDK code. Registration rules are in [`02-serve-runtime.md`](./02-serve-runtime.md). |
| `PermissionAuditRing` | `permissionAudit.ts` | In-memory FIFO of 512 permission decisions. |
| `PermissionAuditRing` | `permission-audit.ts` | In-memory FIFO of 512 permission decisions. |
| Mediator `decisionReason` audit | `permissionMediator.ts` | Internal structured record explaining why a permission request resolved the way it did. |
## What does not exist today
@ -110,7 +110,7 @@ flowchart TD
## State and lifecycle
- `QWEN_SERVE_DEBUG` is read on every check through `isServeDebugMode()` from `debugMode.ts`; toggling it does not require restart. Boot logs are not available unless the env was set at boot.
- `QWEN_SERVE_DEBUG` is read on every check through `isServeDebugMode()` from `debug-mode.ts`; toggling it does not require restart. Boot logs are not available unless the env was set at boot.
- `PermissionAuditRing` is bounded at 512 FIFO entries; older records are silently dropped.
- `DaemonStatusProvider` rebuilds cells per request and does not cache; avoid unnecessary high-frequency polling.
@ -142,9 +142,9 @@ flowchart TD
## References
- `packages/cli/src/serve/daemonStatusProvider.ts`
- `packages/cli/src/serve/daemon-status-provider.ts`
- `packages/cli/src/serve/daemonLogger.ts` (`DaemonLogger`, `buildDaemonLogLine`)
- `packages/cli/src/serve/debugMode.ts` (`isServeDebugMode`)
- `packages/cli/src/serve/debug-mode.ts` (`isServeDebugMode`)
- `packages/acp-bridge/src/permissionMediator.ts` (`PermissionDecisionReason`)
- `packages/cli/src/serve/server.ts` (`daemonTelemetryMiddleware`, access-log middleware)
- Configuration: [`17-configuration.md`](./17-configuration.md)

View file

@ -139,7 +139,7 @@ Settings I/O failure, such as malformed JSON, falls back to defaults. `InvalidPo
## 6. Boot refusal scenarios (explicit failures)
`runQwenServe.ts` intentionally throws instead of falling back in these cases:
`run-qwen-serve.ts` intentionally throws instead of falling back in these cases:
| Scenario | Error prefix |
| ----------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------- |
@ -232,7 +232,7 @@ commands/serve.ts const { runQwenServe } = await import('../ser
commands/serve.ts await runQwenServe({...})
|
v
serve/runQwenServe.ts runQwenServe(opts, deps)
serve/run-qwen-serve.ts runQwenServe(opts, deps)
| |- trim token
| |- hostname mismatch fallback
| |- auth preflight
@ -244,7 +244,7 @@ serve/runQwenServe.ts runQwenServe(opts, deps)
| `- createHttpAcpBridge({...})
|
v
serve/runQwenServe.ts const app = createServeApp(opts, () => actualPort, {...})
serve/run-qwen-serve.ts const app = createServeApp(opts, () => actualPort, {...})
|
v
serve/server.ts createServeApp() - builds Express app (**does not listen**)
@ -253,7 +253,7 @@ serve/server.ts createServeApp() - builds Express app (**does
| `- return app
|
v
serve/runQwenServe.ts server = app.listen(port, hostname, cb)
serve/run-qwen-serve.ts server = app.listen(port, hostname, cb)
| |- server.maxConnections = cap
| |- actualPort = server.address().port
| |- write "qwen serve listening on ..."
@ -277,10 +277,10 @@ The main assembly happens in `createServeApp()` in `server.ts`, which mounts fou
| Routes | File | Mounting entry |
| ------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------- | --------------------------------------------- |
| `/health`, `/demo`, `/capabilities`, all session routes, device flow, permission vote, SSE, and single-server MCP restart | `packages/cli/src/serve/server.ts` | Registered directly inside `createServeApp()` |
| `/workspace/memory` (GET/POST) | `packages/cli/src/serve/workspaceMemory.ts` | `mountWorkspaceMemoryRoutes()` |
| All `/workspace/agents` CRUD routes | `packages/cli/src/serve/workspaceAgents.ts` | `mountWorkspaceAgentsRoutes()` |
| `GET /file`, `/file/bytes`, `/list`, `/glob`, `/stat` | `packages/cli/src/serve/routes/workspaceFileRead.ts` | `registerWorkspaceFileReadRoutes()` |
| `POST /file/write`, `/file/edit` | `packages/cli/src/serve/routes/workspaceFileWrite.ts` | `registerWorkspaceFileWriteRoutes()` |
| `/workspace/memory` (GET/POST) | `packages/cli/src/serve/workspace-memory.ts` | `mountWorkspaceMemoryRoutes()` |
| All `/workspace/agents` CRUD routes | `packages/cli/src/serve/workspace-agents.ts` | `mountWorkspaceAgentsRoutes()` |
| `GET /file`, `/file/bytes`, `/list`, `/glob`, `/stat` | `packages/cli/src/serve/routes/workspace-file-read.ts` | `registerWorkspaceFileReadRoutes()` |
| `POST /file/write`, `/file/edit` | `packages/cli/src/serve/routes/workspace-file-write.ts` | `registerWorkspaceFileWriteRoutes()` |
For the complete route and wire protocol reference, see [`../qwen-serve-protocol.md`](../qwen-serve-protocol.md). For architecture, see [`01-architecture.md`](./01-architecture.md).
@ -361,7 +361,7 @@ QWEN_SERVE_DEBUG=1 qwen serve
## References
- CLI entry: `packages/cli/src/commands/serve.ts`
- Bootstrap: `packages/cli/src/serve/runQwenServe.ts`
- Bootstrap: `packages/cli/src/serve/run-qwen-serve.ts`
- Express factory: `packages/cli/src/serve/server.ts`
- Middleware: `packages/cli/src/serve/auth.ts`
- Bridge factory: `packages/acp-bridge/src/bridge.ts`

View file

@ -1673,13 +1673,13 @@ The connection then closes.
| Path | Purpose |
| ---------------------------------------------------- | ---------------------------------------------------------------------------------------------------------- |
| `packages/cli/src/commands/serve.ts` | yargs command + flag schema |
| `packages/cli/src/serve/runQwenServe.ts` | listener lifecycle + signal handling |
| `packages/cli/src/serve/run-qwen-serve.ts` | listener lifecycle + signal handling |
| `packages/cli/src/serve/server.ts` | Express routes + middleware |
| `packages/cli/src/serve/auth.ts` | bearer + Host allowlist + CORS deny |
| `packages/cli/src/serve/httpAcpBridge.ts` | spawn-or-attach + per-session FIFO + permission registry |
| `packages/cli/src/serve/status.ts` | read-only daemon status wire types + `ServeErrorKind` + `BridgeTimeoutError` + `mapDomainErrorToErrorKind` |
| `packages/cli/src/serve/envSnapshot.ts` | pure helper that builds `/workspace/env` payloads from `process.*` state, including credential redaction |
| `packages/cli/src/serve/eventBus.ts` | bounded async queue + replay ring |
| `packages/cli/src/serve/env-snapshot.ts` | pure helper that builds `/workspace/env` payloads from `process.*` state, including credential redaction |
| `packages/acp-bridge/src/eventBus.ts` | bounded async queue + replay ring |
| `packages/sdk-typescript/src/daemon/DaemonClient.ts` | TS client |
| `packages/sdk-typescript/src/daemon/sse.ts` | EventSource frame parser |
| `integration-tests/cli/qwen-serve-routes.test.ts` | 18 cases, no LLM |

View file

@ -39,7 +39,7 @@ import { fileURLToPath } from 'node:url';
import { afterAll, describe, expect, it } from 'vitest';
const __dirname = path.dirname(fileURLToPath(import.meta.url));
import { EventBus } from '../../packages/cli/src/serve/eventBus.js';
import { EventBus } from '../../packages/cli/src/serve/event-bus.js';
import {
spawnDaemon,
startRssPolling,
@ -528,7 +528,7 @@ async function measureRssAtSessionCount(sessionCount: number): Promise<{
// doesn't take a sessionId in publish/subscribe — the bus instance
// itself is per-session, owned upstream. We use it directly here for
// deterministic backpressure invariants without needing a live HTTP
// round-trip; pattern matches `packages/cli/src/serve/eventBus.test.ts`.
// round-trip; pattern matches `packages/acp-bridge/src/eventBus.test.ts`.
it('overflow at maxQueued boundary fires client_evicted', async () => {
const bus = new EventBus();
const ac = new AbortController();

View file

@ -60,7 +60,7 @@ Lift history (#4175 Mode B daemon roadmap):
`maxSessions`, `eventRingSize`, `permissionResponseTimeoutMs`,
persistence callbacks, etc.) plus the `DaemonStatusProvider`
injection seam for daemon-host env / preflight cells (production
impl in `cli/src/serve/daemonStatusProvider.ts`) and the F1
impl in `cli/src/serve/daemon-status-provider.ts`) and the F1
`BridgeFileSystem` injection seam for the ACP fs proxy.
- `spawnChannel` (F1) — `defaultSpawnChannelFactory` + `killChild` +
`SCRUBBED_CHILD_ENV_KEYS` denylist + `scrubChildEnv` pure env-policy
@ -113,8 +113,8 @@ Both variants are stable across the F1 lift.
## Backward compatibility
`packages/cli/src/serve/eventBus.ts` and
`packages/cli/src/serve/inMemoryChannel.ts` remain as one-line
`packages/cli/src/serve/event-bus.ts` and
`packages/cli/src/serve/in-memory-channel.ts` remain as one-line
re-export wrappers, so every existing relative import inside
`serve/` and the one external import in `cli/src/commands/serve.ts`
keeps resolving without churn.
@ -124,8 +124,8 @@ After F1, `packages/cli/src/serve/httpAcpBridge.ts` shrinks to a
symbol (`createHttpAcpBridge`, `defaultSpawnChannelFactory`,
`BridgeClient`, all the typed errors, all the type aliases) from
the lifted subpaths. Every relative `./httpAcpBridge.js` import in
`server.ts` / `runQwenServe.ts` / `workspaceAgents.ts` /
`workspaceMemory.ts` / `index.ts` / the bridge test suite keeps
`server.ts` / `run-qwen-serve.ts` / `workspace-agents.ts` /
`workspace-memory.ts` / `index.ts` / the bridge test suite keeps
resolving without any call-site changes.
## See also

View file

@ -1033,7 +1033,7 @@ export function createAcpSessionBridge(opts: BridgeOptions): AcpSessionBridge {
// Build the mediator before the BridgeClient so the agent's
// `requestPermission` callback can hand the record straight in.
// Audit publisher fallback: when the host doesn't supply one
// (cli/serve/runQwenServe.ts wraps a real `PermissionAuditRing`
// (cli/serve/run-qwen-serve.ts wraps a real `PermissionAuditRing`
// backed publisher in production), we use the canonical no-op
// fallback so the mediator can still run for embedded callers /
// tests without an audit consumer.

View file

@ -18,8 +18,8 @@
*
*
* The bridge package owns the error contract directly. The
* 7 error classes server.ts imports + 1 each from workspaceAgents.ts
* and workspaceMemory.ts continue to resolve through the
* 7 error classes server.ts imports + 1 each from workspace-agents.ts
* and workspace-memory.ts continue to resolve through the
* httpAcpBridge.ts re-export shim.
*/

View file

@ -40,7 +40,7 @@ export type DiagnosticLineSink = (
*
* The bridge is intentionally agnostic about how its host computes
* these cells; production `qwen serve` provides
* `cli/src/serve/daemonStatusProvider.ts` which wraps
* `cli/src/serve/daemon-status-provider.ts` which wraps
* `buildEnvStatusFromProcess` + `buildDaemonPreflightCells`. Future
* Mode A / in-process consumers may omit the provider entirely; the
* bridge falls back to idle placeholders so `getWorkspaceEnvStatus`
@ -254,7 +254,7 @@ export interface BridgeOptions {
* status cells (env snapshot, daemon preflight). Production
* `qwen serve` provides
* `createDaemonStatusProvider()` from
* `cli/src/serve/daemonStatusProvider.ts`.
* `cli/src/serve/daemon-status-provider.ts`.
*
* **When omitted**: the bridge returns idle placeholders for
* `getWorkspaceEnvStatus` (full envelope with empty `cells: []`
@ -326,7 +326,7 @@ export interface BridgeOptions {
* the bridge unit-test suite) can run the mediator without an
* audit consumer.
*
* **In production** (`qwen serve`), `runQwenServe.ts` allocates a
* **In production** (`qwen serve`), `run-qwen-serve.ts` allocates a
* `PermissionAuditRing` (default capacity 512), wraps it with
* `createPermissionAuditPublisher`, and passes the result here.
* The ring stays alive for the lifetime of the daemon so a future

View file

@ -108,7 +108,7 @@ const WARN_RESET_RATIO = 0.375;
* session from being opened thousands of times by an attacker to amplify
* each `publish()` (which is O(N) over subscribers) into a CPU/memory
* DoS. Daemon's HTTP listener also wants `server.maxConnections`
* configured at the listener level see `runQwenServe.ts`.
* configured at the listener level see `run-qwen-serve.ts`.
*/
const DEFAULT_MAX_SUBSCRIBERS = 64;

View file

@ -8,7 +8,7 @@
* @internal
*
* Shared bridge test fixtures used by `bridge.test.ts` (acp-bridge
* package) and `daemonStatusProvider.test.ts` (cli package). Extracted
* package) and `daemon-status-provider.test.ts` (cli package). Extracted
* so both suites can exercise the same
* `FakeAgent` / `makeChannel` / `makeBridge` helpers without
* cross-package duplication.
@ -86,7 +86,7 @@ export const SESS_A = `sess:${WS_A}`;
* Unlike the pre-split cli-side helper, this version does NOT default
* `statusProvider` that's a daemon-host-specific seam and
* the acp-bridge tests exercise the no-provider fallback paths. The
* cli-side `daemonStatusProvider.test.ts` defines its own wrapper that
* cli-side `daemon-status-provider.test.ts` defines its own wrapper that
* wires `createDaemonStatusProvider()` for the 4 daemon-host
* integration tests.
*/

View file

@ -136,7 +136,7 @@ export type PermissionDecisionReason =
/**
* Audit sink the mediator writes to. Implementation lives in
* `packages/cli/src/serve/permissionAudit.ts` and writes into an
* `packages/cli/src/serve/permission-audit.ts` and writes into an
* in-memory bounded ring on the bridge NOT onto the SSE bus
* (audit records and SSE wire events are intentionally separate
* channels by design).

View file

@ -27,7 +27,7 @@
* but the denylist still wins).
* - An `overrides` map with `undefined` value silently failing to
* delete a stale inherited var (PR 14 fix #4247 wenshao R5
* the `runQwenServe.ts:216` use case).
* the `run-qwen-serve.ts:216` use case).
*
* Each branch listed below is now regression-guarded by an assertion.
*/

View file

@ -1018,7 +1018,7 @@ export function createIdleWorkspaceProvidersStatus(
* tests, embedded callers that don't need daemon-host cells). Single
* construction site so future optional-field additions to
* `ServeWorkspaceEnvStatus` only need updating in one place the
* production builder in `cli/src/serve/envSnapshot.ts buildEnvStatusFromProcess`
* production builder in `cli/src/serve/env-snapshot.ts buildEnvStatusFromProcess`
* and this helper would otherwise diverge silently (TS won't flag a
* missing optional field).
*

View file

@ -2599,7 +2599,7 @@ class QwenAgent implements Agent {
private connection: AgentSideConnection,
) {
// Pool kill switch via env var so operators can A/B compare or
// roll back without rebuilding. `runQwenServe.ts` sets this when
// roll back without rebuilding. `run-qwen-serve.ts` sets this when
// `--no-mcp-pool` is passed at daemon startup.
if (process.env['QWEN_SERVE_NO_MCP_POOL'] === '1') {
this.mcpPool = undefined;

View file

@ -11,7 +11,7 @@ import type { Argv, CommandModule } from 'yargs';
// with ~50ms of cold ESM resolution. The runtime import is deferred to the
// handler below so it only loads when the user actually runs `qwen serve`.
import { writeStderrLine } from '../utils/stdioHelpers.js';
import { DEFAULT_RING_SIZE } from '../serve/eventBus.js';
import { DEFAULT_RING_SIZE } from '../serve/event-bus.js';
import {
ApprovalMode,
MCP_BUDGET_WARN_FRACTION,

View file

@ -2155,7 +2155,7 @@ const SETTINGS_SCHEMA = {
'unreachable quorum. Unset = floor(M/2)+1. ' +
'Requires daemon restart — read once at boot.',
showInDialog: false,
// runQwenServe.ts validates `Number.isInteger(n) && n >= 1` and
// run-qwen-serve.ts validates `Number.isInteger(n) && n >= 1` and
// refuses to boot otherwise. Override the generated schema so IDE
// (VSCode, JetBrains via JSON Schema) flags `0`, `-1`, `1.5`
// BEFORE the user restarts the daemon. The bare `type:'number'`

View file

@ -22,7 +22,7 @@ import {
TooManyActiveDeviceFlowsError,
UnsupportedDeviceFlowProviderError,
UpstreamDeviceFlowError,
} from '../auth/deviceFlow.js';
} from '../auth/device-flow.js';
import type { HttpAcpBridge } from '@qwen-code/acp-bridge/bridgeTypes';
import type { BridgeEvent } from '@qwen-code/acp-bridge/eventBus';
import {
@ -35,13 +35,13 @@ import {
MAX_READ_BYTES,
type WorkspaceFileSystemFactory,
} from '../fs/index.js';
import type { DeviceFlowRegistry } from '../auth/deviceFlow.js';
import { collectWorkspaceMemoryStatus } from '../workspaceMemory.js';
import type { DeviceFlowRegistry } from '../auth/device-flow.js';
import { collectWorkspaceMemoryStatus } from '../workspace-memory.js';
import {
createDaemonSubagentManager,
toSummary as agentToSummary,
toDetail as agentToDetail,
} from '../workspaceAgents.js';
} from '../workspace-agents.js';
import {
InvalidCursorError,
listWorkspaceSessionsForResponse,
@ -1853,7 +1853,7 @@ export class AcpDispatcher {
}
const startResult = await this.deviceFlowRegistry.start({
providerId:
providerId as import('../auth/deviceFlow.js').DeviceFlowProviderId,
providerId as import('../auth/device-flow.js').DeviceFlowProviderId,
initiatorClientId: conn.clientId,
});
const { view, attached } = startResult;

View file

@ -13,7 +13,7 @@ import type { HttpAcpBridge } from '@qwen-code/acp-bridge/bridgeTypes';
import { writeStderrLine } from '../../utils/stdioHelpers.js';
import type { DaemonWorkspaceService } from '../workspace-service/types.js';
import type { WorkspaceFileSystemFactory } from '../fs/index.js';
import type { DeviceFlowRegistry } from '../auth/deviceFlow.js';
import type { DeviceFlowRegistry } from '../auth/device-flow.js';
import { AcpDispatcher } from './dispatch.js';
import {
ConnectionRegistry,
@ -21,7 +21,7 @@ import {
} from './connectionRegistry.js';
import { SseStream } from './sseStream.js';
import { WsStream } from './wsStream.js';
import type { RateLimitTier } from '../rateLimit.js';
import type { RateLimitTier } from '../rate-limit.js';
import { RPC, error as rpcError, isRequest, parseInbound } from './jsonRpc.js';
export const ACP_CONNECTION_HEADER = 'acp-connection-id';

View file

@ -11,8 +11,8 @@
* `defaultSpawnChannelFactory`, `createAcpSessionBridge` factory closure,
* plus the supporting types/errors/options/status) to
* `@qwen-code/acp-bridge`. This shim preserves every existing relative
* import path (`./acpSessionBridge.js`) so `server.ts`, `runQwenServe.ts`,
* `workspaceAgents.ts`, `workspaceMemory.ts`, `index.ts`, plus the
* import path (`./acpSessionBridge.js`) so `server.ts`, `run-qwen-serve.ts`,
* `workspace-agents.ts`, `workspace-memory.ts`, `index.ts`, plus the
* bridge test suite, keep resolving without any call-site changes.
*
* The implementation now lives at:

View file

@ -123,7 +123,7 @@ describe('createMutationGate (#4175 PR 15)', () => {
expect(body.error).toMatch(/--token/);
// `--require-auth` is intentionally NOT named here as a remediation:
// setting it without a token is itself a boot-error path (see
// `runQwenServe.ts`). The error must point operators at fixes that
// `run-qwen-serve.ts`). The error must point operators at fixes that
// work standalone.
expect(body.error).not.toMatch(/--require-auth/);
});

View file

@ -6,7 +6,7 @@
import { createHash, timingSafeEqual } from 'node:crypto';
import type { Request, Response, NextFunction, RequestHandler } from 'express';
import { isLoopbackBind } from './loopbackBinds.js';
import { isLoopbackBind } from './loopback-binds.js';
/**
* Reject any request that carries an `Origin` header. CLI/SDK clients never
@ -428,7 +428,7 @@ export function createMutationGate(
// cache is visible.
const strictDenier: RequestHandler = (_req: Request, res: Response) => {
// Only list remediations that work standalone. `--require-auth` is
// paired-required-with-a-token at boot (`runQwenServe.ts` refuses
// paired-required-with-a-token at boot (`run-qwen-serve.ts` refuses
// to start with the flag set but no token), so naming it as a
// third standalone option here would loop the operator into a
// different boot error. Configuring a token via `QWEN_SERVER_TOKEN`

View file

@ -29,7 +29,7 @@ import {
type DeviceFlowPollResult,
type DeviceFlowProvider,
type DeviceFlowProviderId,
} from './deviceFlow.js';
} from './device-flow.js';
interface FakeClock {
now: number;
@ -630,8 +630,8 @@ describe('DeviceFlowRegistry — polling state machine', () => {
// here loudly.
const dir = path.dirname(fileURLToPath(import.meta.url));
const sources = [
fs.readFileSync(path.join(dir, 'deviceFlow.ts'), 'utf8'),
fs.readFileSync(path.join(dir, 'qwenDeviceFlowProvider.ts'), 'utf8'),
fs.readFileSync(path.join(dir, 'device-flow.ts'), 'utf8'),
fs.readFileSync(path.join(dir, 'qwen-device-flow-provider.ts'), 'utf8'),
];
const forbiddenPatterns = [
// Static imports

View file

@ -30,8 +30,8 @@ import {
QwenOAuthPollError,
type IQwenOAuth2Client,
} from '@qwen-code/qwen-code-core';
import { QwenOAuthDeviceFlowProvider } from './qwenDeviceFlowProvider.js';
import { brandSecret } from './deviceFlow.js';
import { QwenOAuthDeviceFlowProvider } from './qwen-device-flow-provider.js';
import { brandSecret } from './device-flow.js';
function fakeClient(
overrides: Partial<IQwenOAuth2Client> = {},

View file

@ -28,7 +28,7 @@ import {
type DeviceFlowProvider,
type DeviceFlowProviderId,
type DeviceFlowStartResult,
} from './deviceFlow.js';
} from './device-flow.js';
const QWEN_OAUTH_SCOPE = 'openid profile email model.completion';

View file

@ -33,11 +33,11 @@ import type {
ReadTextFileRequest,
WriteTextFileRequest,
} from '@agentclientprotocol/sdk';
import { createBridgeFileSystemAdapter } from './bridgeFileSystemAdapter.js';
import { createBridgeFileSystemAdapter } from './bridge-file-system-adapter.js';
import {
createWorkspaceFileSystemFactory,
type WorkspaceFileSystemFactory,
} from './fs/workspaceFileSystem.js';
} from './fs/workspace-file-system.js';
describe('createBridgeFileSystemAdapter', () => {
let tmpDir: string;
@ -136,7 +136,7 @@ describe('createBridgeFileSystemAdapter', () => {
// Symlink-rejection posture (BridgeFileSystem contract divergence
// from the pre-F1 inline proxy) is enforced by `writeTextOverwrite`
// and verified at the lower layer in
// `workspaceFileSystem.test.ts > writeTextOverwrite rejects symlink
// `workspace-file-system.test.ts > writeTextOverwrite rejects symlink
// targets planted post-resolve (symlink_escape)`. Re-testing at the
// adapter layer would only re-exercise the same code path; the
// adapter contract is "delegate to writeTextOverwrite", and the

View file

@ -59,7 +59,7 @@ import type { BridgeFileSystem } from '@qwen-code/acp-bridge';
import type {
WorkspaceFileSystemFactory,
RequestContext,
} from './fs/workspaceFileSystem.js';
} from './fs/workspace-file-system.js';
/** Route label used in audit events for ACP-triggered fs operations. */
const ACP_WRITE_ROUTE = 'ACP writeTextFile';

View file

@ -15,7 +15,7 @@
*/
import { describe, it, expect } from 'vitest';
import { createDaemonStatusProvider } from './daemonStatusProvider.js';
import { createDaemonStatusProvider } from './daemon-status-provider.js';
import { createDaemonWorkspaceService } from './workspace-service/index.js';
import type {
DaemonWorkspaceServiceDeps,

View file

@ -13,7 +13,7 @@
*
* Lift origin (#4175 PR 22b/2): the inline `buildDaemonPreflightCells`
* function moved here from `httpAcpBridge.ts`; `buildEnvStatusFromProcess`
* stays in `envSnapshot.ts` and is wrapped here. Mode A consumers can
* stays in `env-snapshot.ts` and is wrapped here. Mode A consumers can
* omit this provider entirely the bridge falls back to idle placeholders.
*/
@ -27,7 +27,7 @@ import {
type ServeWorkspaceEnvStatus,
} from '@qwen-code/acp-bridge';
import { getGitVersion, getNpmVersion } from '../utils/systemInfo.js';
import { buildEnvStatusFromProcess } from './envSnapshot.js';
import { buildEnvStatusFromProcess } from './env-snapshot.js';
const REQUIRED_NODE_MAJOR = 22;

View file

@ -11,12 +11,12 @@ import type {
AcpSessionBridge,
BridgeDaemonStatusSnapshot,
} from './acpSessionBridge.js';
import { DeviceFlowRegistry } from './auth/deviceFlow.js';
import { DeviceFlowRegistry } from './auth/device-flow.js';
import {
buildDaemonStatusResponse,
type BuildDaemonStatusOptions,
} from './daemonStatus.js';
import type { RateLimiterInstance, RateLimitTier } from './rateLimit.js';
import type { RateLimiterInstance, RateLimitTier } from './rate-limit.js';
import type { DaemonWorkspaceService } from './workspace-service/index.js';
const BASE_WORKSPACE = '/work/status';

View file

@ -6,14 +6,14 @@
import type { ServeProtocolVersions } from './capabilities.js';
import type { AcpHttpHandle } from './acpHttp/index.js';
import type { DeviceFlowRegistry } from './auth/deviceFlow.js';
import type { DeviceFlowRegistry } from './auth/device-flow.js';
import type { DaemonLogger } from './daemonLogger.js';
import type {
AcpSessionBridge,
BridgeDaemonStatusSnapshot,
} from './acpSessionBridge.js';
import { isLoopbackBind } from './loopbackBinds.js';
import type { RateLimiterInstance, RateLimitTier } from './rateLimit.js';
import { isLoopbackBind } from './loopback-binds.js';
import type { RateLimiterInstance, RateLimitTier } from './rate-limit.js';
import type { ServeOptions } from './types.js';
import type {
DaemonWorkspaceService,

View file

@ -10,7 +10,7 @@
* `httpAcpBridge.ts` (which gates stderr-side debug log output).
*
* Extracted into its own module in fold-in 2i so route files
* (`workspaceMemory.ts`, `workspaceAgents.ts`, future Wave 4 mutation
* (`workspace-memory.ts`, `workspace-agents.ts`, future Wave 4 mutation
* routes) can share one canonical predicate when deciding whether to
* include `errorMessage` / `filePath` in their response bodies.
* Without the toggle, error responses carry only structured fields

View file

@ -12,7 +12,7 @@ import {
ENV_SECRET_VARS,
buildEnvStatusFromProcess,
readProxyVar,
} from './envSnapshot.js';
} from './env-snapshot.js';
const TRACKED_ENV = [
...ENV_SECRET_VARS,

View file

@ -5,7 +5,7 @@
*/
// Re-export wrapper. The implementation lives in `@qwen-code/acp-bridge`
// (lifted in #4175 PR 22a). Existing `import { ... } from './eventBus.js'`
// (lifted in #4175 PR 22a). Existing `import { ... } from './event-bus.js'`
// callers inside `serve/` and the one external import in
// `cli/src/commands/serve.ts:14` keep resolving without churn.
//

View file

@ -14,7 +14,7 @@ import {
createAuditPublisher,
} from './audit.js';
import type { ResolvedPath } from './paths.js';
import type { BridgeEvent } from '../eventBus.js';
import type { BridgeEvent } from '../event-bus.js';
function expectedHash(p: string): string {
return createHash('sha256').update(p).digest('hex').slice(0, 16);

View file

@ -6,7 +6,7 @@
import { createHash } from 'node:crypto';
import * as path from 'node:path';
import { EVENT_SCHEMA_VERSION, type BridgeEvent } from '../eventBus.js';
import { EVENT_SCHEMA_VERSION, type BridgeEvent } from '../event-bus.js';
import type { FsErrorKind } from './errors.js';
import type { Intent, ResolvedPath } from './paths.js';

View file

@ -13,7 +13,7 @@ import { WorkspaceContext } from '@qwen-code/qwen-code-core';
import { canonicalizeWorkspace, resolveWithinWorkspace } from './paths.js';
// `isFsError` is a runtime guard called below — must stay a value
// import. `FsError` is type-only here (typed `catch` variable); same
// for `FsErrorKind`. The eslint-disable mirrors the workspaceFileSystem.ts
// for `FsErrorKind`. The eslint-disable mirrors the workspace-file-system.ts
// fix and exists because the auto-fix at commit 7b0db4c3a promoted the
// whole line to `import type`, erasing `isFsError` at runtime and
// failing 11 tests in this file alone.

View file

@ -60,4 +60,4 @@ export {
type WriteOutcome,
type WriteTextAtomicOptions,
type WriteTextAtomicOutcome,
} from './workspaceFileSystem.js';
} from './workspace-file-system.js';

View file

@ -167,7 +167,7 @@ export interface ReadSizeOutcome {
* when `opts.maxBytes < fileSize <= MAX_READ_BYTES`. It runs only
* AFTER `readText`'s pre-stat hard-cap check has rejected files
* above `MAX_READ_BYTES` with `file_too_large` (see
* `workspaceFileSystem.ts:readText`). Within the hard cap the
* `workspace-file-system.ts:readText`). Within the hard cap the
* caller can opt into a tighter byte ceiling via `opts.maxBytes`,
* and we surface that truncation via `truncated: true` rather
* than throwing operators want to see a partial config file

View file

@ -18,7 +18,7 @@ import {
type WorkspaceFileSystem,
type WorkspaceFileSystemFactory,
} from './index.js';
import type { BridgeEvent } from '../eventBus.js';
import type { BridgeEvent } from '../event-bus.js';
import { canonicalizeWorkspace } from './paths.js';
import { isFsError } from './errors.js';

View file

@ -27,7 +27,7 @@ import {
type Ignore,
type WriteTextFileOptions,
} from '@qwen-code/qwen-code-core';
import type { BridgeEvent } from '../eventBus.js';
import type { BridgeEvent } from '../event-bus.js';
import {
type AuditContext,
type AuditPublisher,

View file

@ -6,7 +6,7 @@
// Re-export wrapper. The implementation lives in `@qwen-code/acp-bridge`
// (lifted in #4175 PR 22a). Existing `import { createInMemoryChannel }
// from './inMemoryChannel.js'` callers inside `serve/` and the SDK
// from './in-memory-channel.js'` callers inside `serve/` and the SDK
// in-process bridge tests keep resolving without churn.
//
// @see ../../../acp-bridge/src/inMemoryChannel.ts for the implementation

View file

@ -9,7 +9,7 @@ export {
runQwenServe,
type RunHandle,
type RunQwenServeDeps,
} from './runQwenServe.js';
} from './run-qwen-serve.js';
export {
CAPABILITIES_SCHEMA_VERSION,
STAGE1_FEATURES,
@ -98,7 +98,7 @@ export {
ENV_PROXY_VARS,
ENV_SECRET_VARS,
buildEnvStatusFromProcess,
} from './envSnapshot.js';
} from './env-snapshot.js';
export {
bearerAuth,
createMutationGate,
@ -139,5 +139,5 @@ export {
EVENT_SCHEMA_VERSION,
type BridgeEvent,
type SubscribeOptions,
} from './eventBus.js';
export { createInMemoryChannel } from './inMemoryChannel.js';
} from './event-bus.js';
export { createInMemoryChannel } from './in-memory-channel.js';

View file

@ -9,7 +9,7 @@ import {
createPermissionAuditPublisher,
DEFAULT_PERMISSION_AUDIT_RING_SIZE,
PermissionAuditRing,
} from './permissionAudit.js';
} from './permission-audit.js';
import type {
PermissionRequestRecord,
PermissionVote,

View file

@ -5,7 +5,7 @@
*/
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
import { createRateLimiter, createKeyExtractor } from './rateLimit.js';
import { createRateLimiter, createKeyExtractor } from './rate-limit.js';
import type { Request, Response } from 'express';
function mockReq(overrides: Record<string, unknown> = {}): Request {

View file

@ -5,7 +5,7 @@
*/
import type { Request, Response, NextFunction, RequestHandler } from 'express';
import { isLoopbackBind } from './loopbackBinds.js';
import { isLoopbackBind } from './loopback-binds.js';
// ---------------------------------------------------------------------------
// Types

View file

@ -16,7 +16,7 @@ import {
canonicalizeWorkspace,
createWorkspaceFileSystemFactory,
} from '../fs/index.js';
import type { BridgeEvent } from '../eventBus.js';
import type { BridgeEvent } from '../event-bus.js';
import type { ServeOptions } from '../types.js';
const baseOpts: ServeOptions = {

View file

@ -15,7 +15,7 @@ import {
canonicalizeWorkspace,
createWorkspaceFileSystemFactory,
} from '../fs/index.js';
import type { BridgeEvent } from '../eventBus.js';
import type { BridgeEvent } from '../event-bus.js';
import type { ServeOptions } from '../types.js';
const baseOpts: ServeOptions = {

View file

@ -16,7 +16,7 @@ import {
applyReadHeaders,
sendFsError,
workspaceRelative,
} from './workspaceFileRead.js';
} from './workspace-file-read.js';
interface RegisterDeps {
bridge: AcpSessionBridge;

View file

@ -13,7 +13,7 @@ import {
InvalidPolicyConfigError,
runQwenServe,
validatePolicyConfig,
} from './runQwenServe.js';
} from './run-qwen-serve.js';
import type { HttpAcpBridge } from './acpSessionBridge.js';
/**

View file

@ -8,8 +8,8 @@ import * as fs from 'node:fs';
import { type Server } from 'node:http';
import * as path from 'node:path';
import { writeStderrLine, writeStdoutLine } from '../utils/stdioHelpers.js';
import type { BridgeEvent } from './eventBus.js';
import { getDeviceFlowRegistry } from './auth/deviceFlow.js';
import type { BridgeEvent } from './event-bus.js';
import { getDeviceFlowRegistry } from './auth/device-flow.js';
import {
loadSettings,
reloadEnvironment,
@ -48,15 +48,15 @@ import {
type TelemetryRuntimeConfig,
type TelemetrySettings,
} from '@qwen-code/qwen-code-core';
import { createBridgeFileSystemAdapter } from './bridgeFileSystemAdapter.js';
import { createDaemonStatusProvider } from './daemonStatusProvider.js';
import { isLoopbackBind } from './loopbackBinds.js';
import { createBridgeFileSystemAdapter } from './bridge-file-system-adapter.js';
import { createDaemonStatusProvider } from './daemon-status-provider.js';
import { isLoopbackBind } from './loopback-binds.js';
import { resolveWebShellDir } from './webShellStatic.js';
import { parseAllowOriginPatterns } from './auth.js';
import {
createPermissionAuditPublisher,
PermissionAuditRing,
} from './permissionAudit.js';
} from './permission-audit.js';
import {
createServeApp,
getActiveSseCount,
@ -74,7 +74,7 @@ import type {
import type { WorkspaceFileSystemFactory } from './fs/index.js';
import type { PermissionPolicy } from '@qwen-code/acp-bridge';
import { getCliVersion } from '../utils/version.js';
import { getRateLimiter } from './rateLimit.js';
import { getRateLimiter } from './rate-limit.js';
import type { AcpHttpHandle } from './acpHttp/index.js';
const QWEN_SERVER_TOKEN_ENV = 'QWEN_SERVER_TOKEN';
@ -862,7 +862,7 @@ export async function runQwenServe(
// Construct `fsFactory` BEFORE the bridge so the bridge can wire it
// through `BridgeFileSystem` for ACP-side writeTextFile / readTextFile
// calls. See `bridgeFileSystemAdapter.ts` for the translation layer.
// calls. See `bridge-file-system-adapter.ts` for the translation layer.
const trustedWorkspace = deps.trustedWorkspace ?? true;
const fsFactory = resolveBridgeFsFactory({
boundWorkspace,

View file

@ -19,7 +19,7 @@ import {
PromptDeadlineExceededError,
resolvePromptDeadlineMs,
} from './server.js';
import { runQwenServe, type RunHandle } from './runQwenServe.js';
import { runQwenServe, type RunHandle } from './run-qwen-serve.js';
import { resolveWebShellDir, isDocumentNavigation } from './webShellStatic.js';
import {
CONDITIONAL_SERVE_FEATURES,
@ -77,7 +77,7 @@ import {
type AcpSessionBridge,
type SessionMetadataUpdate,
} from './acpSessionBridge.js';
import type { BridgeEvent, SubscribeOptions } from './eventBus.js';
import type { BridgeEvent, SubscribeOptions } from './event-bus.js';
import type {
ServeSessionContextStatus,
ServeSessionContextUsageStatus,
@ -1273,8 +1273,8 @@ function fakeBridge(opts: FakeBridgeOpts = {}): FakeBridge {
publishWorkspaceEvent(_event) {
// Issue #4175 PR 16 — fakeBridge default is a no-op. Tests that
// assert on workspace fan-out override this through the dedicated
// route-level test files (workspaceMemory.test.ts /
// workspaceAgents.test.ts) where the real fan-out behavior is
// route-level test files (workspace-memory.test.ts /
// workspace-agents.test.ts) where the real fan-out behavior is
// exercised against a live bridge.
},
knownClientIds() {
@ -1935,7 +1935,7 @@ describe('createServeApp', () => {
});
it('omits mcp_workspace_pool / mcp_pool_restart when mcpPoolActive=false (F2 #4175 commit 5)', async () => {
// Mirrors the env-var kill switch path: `runQwenServe.ts` infers
// Mirrors the env-var kill switch path: `run-qwen-serve.ts` infers
// `mcpPoolActive: false` when the parent process has
// `QWEN_SERVE_NO_MCP_POOL=1`. Verify the capability envelope
// tracks the toggle so SDK clients pre-flighting on the tags
@ -10436,7 +10436,7 @@ describe('auth device-flow routes', () => {
// whose `poll` is scripted per-test. Lives at the top of the suite so
// every `it()` can compose it with the registry.
function makeFakeProvider(): {
provider: import('./auth/deviceFlow.js').DeviceFlowProvider;
provider: import('./auth/device-flow.js').DeviceFlowProvider;
startCount: () => number;
} {
let starts = 0;
@ -10449,10 +10449,10 @@ describe('auth device-flow routes', () => {
deviceCode:
// Use the brandSecret helper so the secret follows the same
// redaction shape the production provider produces.
(await import('./auth/deviceFlow.js')).brandSecret(
(await import('./auth/device-flow.js')).brandSecret(
`device-${starts}`,
),
pkceVerifier: (await import('./auth/deviceFlow.js')).brandSecret(
pkceVerifier: (await import('./auth/device-flow.js')).brandSecret(
`pkce-${starts}`,
),
userCode: `USER-${starts}`,
@ -10935,8 +10935,8 @@ describe('auth device-flow routes', () => {
// must surface as 502 with code:'upstream_error' instead of falling
// through `sendBridgeError`'s generic 500 path. Build a fake
// provider whose start always throws.
const { UpstreamDeviceFlowError } = await import('./auth/deviceFlow.js');
const failingProvider: import('./auth/deviceFlow.js').DeviceFlowProvider = {
const { UpstreamDeviceFlowError } = await import('./auth/device-flow.js');
const failingProvider: import('./auth/device-flow.js').DeviceFlowProvider = {
providerId: 'qwen-oauth',
async start() {
throw new UpstreamDeviceFlowError('mocked upstream outage');
@ -10964,9 +10964,9 @@ describe('auth device-flow routes', () => {
// PR 21 fold-in 0 P1-13: cover the time-based expiry path via an
// injected registry with a controlled clock + manual sweeper trigger.
const { DeviceFlowRegistry, brandSecret } = await import(
'./auth/deviceFlow.js'
'./auth/device-flow.js'
);
const fakeProvider: import('./auth/deviceFlow.js').DeviceFlowProvider = {
const fakeProvider: import('./auth/device-flow.js').DeviceFlowProvider = {
providerId: 'qwen-oauth',
async start() {
return {
@ -11067,7 +11067,7 @@ describe('auth device-flow routes', () => {
it('POST returns 409 too_many_active_flows when registry cap is reached', async () => {
// Inject a fake registry whose `start` always throws the cap error.
const { TooManyActiveDeviceFlowsError } = await import(
'./auth/deviceFlow.js'
'./auth/device-flow.js'
);
const fakeRegistry = {
start: async () => {
@ -11077,7 +11077,7 @@ describe('auth device-flow routes', () => {
cancel: () => undefined,
listPending: () => [],
dispose: () => {},
} as unknown as import('./auth/deviceFlow.js').DeviceFlowRegistry;
} as unknown as import('./auth/device-flow.js').DeviceFlowRegistry;
const bridge = fakeBridge();
const app = createServeApp({ ...baseOpts, token: 'tkn' }, undefined, {

View file

@ -55,16 +55,16 @@ import {
type DeviceFlowProvider,
type DeviceFlowProviderId,
type DeviceFlowPublicView,
} from './auth/deviceFlow.js';
} from './auth/device-flow.js';
import { mapDomainErrorToErrorKind } from '@qwen-code/acp-bridge';
import { QwenOAuthDeviceFlowProvider } from './auth/qwenDeviceFlowProvider.js';
import { createBridgeFileSystemAdapter } from './bridgeFileSystemAdapter.js';
import { createDaemonStatusProvider } from './daemonStatusProvider.js';
import { isServeDebugMode } from './debugMode.js';
import { QwenOAuthDeviceFlowProvider } from './auth/qwen-device-flow-provider.js';
import { createBridgeFileSystemAdapter } from './bridge-file-system-adapter.js';
import { createDaemonStatusProvider } from './daemon-status-provider.js';
import { isServeDebugMode } from './debug-mode.js';
import { SUPPORTED_LANGUAGES } from '../i18n/index.js';
import { loadSettings } from '../config/settings.js';
import { isWorkspaceTrusted } from '../config/trustedFolders.js';
import { isLoopbackBind } from './loopbackBinds.js';
import { isLoopbackBind } from './loopback-binds.js';
import { mountAcpHttp, type AcpHttpHandle } from './acpHttp/index.js';
import {
buildDaemonStatusResponse,
@ -104,7 +104,7 @@ import {
getAdvertisedServeFeatures,
getServeProtocolVersions,
} from './capabilities.js';
import { SubscriberLimitExceededError, type BridgeEvent } from './eventBus.js';
import { SubscriberLimitExceededError, type BridgeEvent } from './event-bus.js';
import {
CAPABILITIES_SCHEMA_VERSION,
type CapabilitiesEnvelope,
@ -119,26 +119,26 @@ import {
mountWebShellAssets,
mountWebShellSpaFallback,
} from './webShellStatic.js';
import { mountWorkspaceMemoryRoutes } from './workspaceMemory.js';
import { mountWorkspaceAgentsRoutes } from './workspaceAgents.js';
import { mountWorkspaceMemoryRoutes } from './workspace-memory.js';
import { mountWorkspaceAgentsRoutes } from './workspace-agents.js';
import {
createWorkspaceFileSystemFactory,
type WorkspaceFileSystemFactory,
} from './fs/index.js';
import { registerWorkspaceFileReadRoutes } from './routes/workspaceFileRead.js';
import { registerWorkspaceFileWriteRoutes } from './routes/workspaceFileWrite.js';
import { registerWorkspaceFileReadRoutes } from './routes/workspace-file-read.js';
import { registerWorkspaceFileWriteRoutes } from './routes/workspace-file-write.js';
import {
createDaemonWorkspaceService,
type DaemonWorkspaceService,
type WorkspaceRequestContext,
} from './workspace-service/index.js';
import { registerWorkspaceSettingsRoutes } from './routes/workspaceSettings.js';
import { registerWorkspaceSettingsRoutes } from './routes/workspace-settings.js';
import { registerA2uiActionRoutes } from './routes/a2uiAction.js';
import {
createRateLimiter,
setRateLimiter,
type RateLimiterInstance,
} from './rateLimit.js';
} from './rate-limit.js';
import {
STATUS_SCHEMA_VERSION,
type ServeExtensionCapabilities,
@ -1596,7 +1596,7 @@ export function createServeApp(
// both halves of the policy (matched → CORS headers + pass-through or
// 204 preflight; unmatched → 403 with the same error envelope as the
// wall). When `--allow-origin` is empty/undefined, the deny-wall stays
// installed. Pattern parsing happens in `runQwenServe.ts` for validation;
// installed. Pattern parsing happens in `run-qwen-serve.ts` for validation;
// here we still keep the wildcard/no-token invariant for embedded
// callers that construct the app directly.
if (opts.allowOrigins && opts.allowOrigins.length > 0) {
@ -4521,7 +4521,7 @@ export function createServeApp(
const idleForMs = Date.now() - lastWriteAt;
if (idleForMs < writerIdleTimeoutMs) return;
// Reuse the existing `client_evicted` taxonomy from
// `eventBus.ts` so SDK reducers branch on the same frame type
// `event-bus.ts` so SDK reducers branch on the same frame type
// they already handle for queue-overflow eviction; the new
// `reason` slot is the differentiator. Write DIRECTLY here
// (bypassing `writeWithBackpressure`) because the chain may

View file

@ -11,7 +11,7 @@ import express from 'express';
import type { Application, NextFunction, Request, Response } from 'express';
import { resolveBundleDir } from '@qwen-code/qwen-code-core';
import { writeStderrLine } from '../utils/stdioHelpers.js';
import { isServeDebugMode } from './debugMode.js';
import { isServeDebugMode } from './debug-mode.js';
/**
* Content-Security-Policy for the Web Shell HTML shell.

View file

@ -21,8 +21,8 @@ import {
import { Storage, QWEN_DIR } from '@qwen-code/qwen-code-core';
import { createMutationGate } from './auth.js';
import type { AcpSessionBridge } from './acpSessionBridge.js';
import type { BridgeEvent } from './eventBus.js';
import { mountWorkspaceAgentsRoutes } from './workspaceAgents.js';
import type { BridgeEvent } from './event-bus.js';
import { mountWorkspaceAgentsRoutes } from './workspace-agents.js';
type RecordedEvent = Omit<BridgeEvent, 'id' | 'v'>;

View file

@ -17,7 +17,7 @@ import {
type SubagentLevel,
} from '@qwen-code/qwen-code-core';
import { writeStderrLine } from '../utils/stdioHelpers.js';
import { isServeDebugMode } from './debugMode.js';
import { isServeDebugMode } from './debug-mode.js';
import {
InvalidClientIdError,
type AcpSessionBridge,

View file

@ -24,8 +24,8 @@ import {
InvalidClientIdError,
type AcpSessionBridge,
} from './acpSessionBridge.js';
import type { BridgeEvent } from './eventBus.js';
import { mountWorkspaceMemoryRoutes } from './workspaceMemory.js';
import type { BridgeEvent } from './event-bus.js';
import { mountWorkspaceMemoryRoutes } from './workspace-memory.js';
type RecordedEvent = Omit<BridgeEvent, 'id' | 'v'>;

View file

@ -15,7 +15,7 @@ import {
writeWorkspaceContextFile,
} from '@qwen-code/qwen-code-core';
import { writeStderrLine } from '../utils/stdioHelpers.js';
import { isServeDebugMode } from './debugMode.js';
import { isServeDebugMode } from './debug-mode.js';
import type { AcpSessionBridge } from './acpSessionBridge.js';
import {
createIdleWorkspaceMemoryStatus,
@ -159,7 +159,7 @@ export function mountWorkspaceMemoryRoutes(
if (clientId === null) return;
let originatorClientId: string | undefined;
if (clientId !== undefined) {
// Mirror the workspaceAgents.ts `resolveOriginatorClientId`
// Mirror the workspace-agents.ts `resolveOriginatorClientId`
// posture: validate against `bridge.knownClientIds()`, send
// 400 directly, return `null` so the caller short-circuits.
// Previously this branch threw `InvalidClientIdError` and

View file

@ -15,7 +15,7 @@ import {
reduceDaemonEventToTuiUpdates,
type DaemonTuiEvent,
type DaemonTuiSessionClient,
} from './DaemonTuiAdapter.js';
} from './daemon-tui-adapter.js';
import { ToolCallStatus } from '../types.js';
class EventQueue implements AsyncGenerator<DaemonTuiEvent> {

View file

@ -12,7 +12,7 @@ export default defineConfig({
resolve: {
alias: {
'@qwen-code/qwen-code-core': path.resolve(__dirname, '../core/index.ts'),
// cli's daemonStatusProvider.test.ts imports `FakeAgent` /
// cli's daemon-status-provider.test.ts imports `FakeAgent` /
// `makeChannel` from acp-bridge's package-private
// `internal/testUtils` module. This alias overrides the runtime
// resolution so vitest reads the .ts source directly instead of

View file

@ -231,7 +231,7 @@ function resolveContextFilePath(
// appending to a stale `QWEN.md` — clients then observed "I just
// wrote content but it's missing from /workspace/memory". Mirrors the
// discovery path's `getAllGeminiMdFilenames()` usage in
// `workspaceMemory.ts:collectWorkspaceMemoryStatus`.
// `workspace-memory.ts:collectWorkspaceMemoryStatus`.
const filename = getCurrentGeminiMdFilename();
if (scope === 'workspace') {
return path.join(projectRoot, filename);

View file

@ -285,7 +285,7 @@ function readBudgetFromEnv(): McpBudgetConfig {
// operator typos
// like `QWEN_SERVE_MCP_CLIENT_BUDGET=abc` previously fell
// through silently to "no budget" with zero indication. The
// CLI parent (`commands/serve.ts` + `runQwenServe.ts`)
// CLI parent (`commands/serve.ts` + `run-qwen-serve.ts`)
// validates and throws, but the ACP child process — where
// this function runs — has no such validation. Surface a
// boot breadcrumb so operators see the misconfiguration in

View file

@ -85,7 +85,7 @@ function isRecord(value: unknown): value is Record<string, unknown> {
function isLoopbackHostname(hostname: string): boolean {
// Keep this client-side policy aligned with
// packages/cli/src/serve/loopbackBinds.ts when daemon bind rules change.
// packages/cli/src/serve/loopback-binds.ts when daemon bind rules change.
const normalized = hostname.toLowerCase().replace(/^\[|\]$/g, '');
if (normalized === 'localhost' || normalized === '::1') {
return true;