mirror of
https://github.com/QwenLM/qwen-code.git
synced 2026-08-22 15:15:18 +00:00
* feat(sdk): DaemonTransport abstraction — pluggable transport for REST/ACP-HTTP/ACP-WS
- DaemonTransport interface with fetch + subscribeEvents
- RestSseTransport: extract current SSE logic from DaemonClient
- AcpWsTransport: WebSocket multiplexer + URL-to-JSON-RPC mapping
- AcpHttpTransport: POST /acp + session-scoped SSE
- AcpEventDenormalizer: JSON-RPC notification -> DaemonEvent
- AutoReconnectTransport: opt-in reconnect + fallback wrapper
- negotiateTransport(): auto-detect best transport via GET /capabilities
- Provider: DaemonWorkspaceProvider gains transport prop
- Server: GET /capabilities advertises supported transports
- Zero breaking changes: no transport = current REST behavior
Generated with AI
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
* docs(design): include DaemonTransport design doc in implementation PR
* fix(sdk): address 6 verification findings — bundle size, WS hang, error types, ACP compat
- Remove ACP transport class re-exports from barrel (index.ts) to avoid
~19.7KB browser bundle bloat; keep type-only exports
- Fix WS dial hang: reject connect promise in onerror when not yet
connected (Node WebSocket may only fire error, not close)
- Fix parked generators: maintain _activeGenerators set, abort all on
WS close so generators throw DaemonTransportClosedError
- Forward abort signal through AcpHttpTransport.sendRequest to fetch
- Restore DaemonHttpError in RestSseTransport (was plain Error)
- ACP endpoint compat: extract connectionId from initialize, send
Acp-Connection-Id header, add _qwen/ prefix for vendor methods,
preserve real HTTP status in error mapping, fetch /capabilities
from REST endpoint for correct shape
Generated with AI
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
* fix(sdk): address 16 review findings + CI bundle size
- CI: move negotiateTransport to separate file, extract DaemonHttpError
to break static import chain from barrel -> DaemonClient. Browser
bundle drops from 136KB to 115KB, under the 116KB budget.
- Route table: extract shared acpRouteTable.ts, used by both transports.
Unify method naming (remove _qwen/ prefix inconsistency).
- Token: move from URL query to Authorization header on WS upgrade
- Error type: DaemonHttpError extracted to DaemonHttpError.ts; import
in RestSseTransport no longer pulls in DaemonClient.
- Init retry: reset failed initPromise so next call retries
- Reconnect mutex: prevent concurrent reconnect storms
- Generator queue: cap at 256, drop-oldest
- WS init timeout: 30s default
- negotiate: clear timer on all paths, catch dispose rejection
- Headers: forward init.headers in ACP transports via mergeHeaders()
- Dead code: remove unused pendingRequests/sseAbort fields
- Provider: dispose client on unmount
- Helpers: extract matchRoute/synthesizeResponse/jsonRpcErrorToHttpStatus/
isRecord/composeAbortSignals to shared acpTransportUtils.ts
- Package exports: add deep import paths for ACP transports
- Tests: add AcpEventDenormalizer unit tests (17 cases)
Generated with AI
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
* fix(sdk): ESLint array-type rule — ReadonlyArray<T> → readonly T[]
Generated with AI
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
* fix(sdk): fix 3 ACP wire bugs + bundle size + npm exports
Wire bugs (verified broken against real daemon):
1. AcpHttpTransport: read connectionId from response header + correct JSON path
2. AcpWsTransport: send token via Authorization header, not URL query
3. AcpEventDenormalizer: read params.update.sessionUpdate, not params.type
Bundle: remove negotiateTransport from barrel-reachable imports
Exports: add package.json deep import paths for ACP transports
Generated with AI
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
* test(sdk): comprehensive ACP transport test suite (~175 tests)
- RestSseTransport: fetch delegation, SSE subscribe, auth, timeout, signal
- AcpWsTransport: route mapping, token auth, event filtering, queue cap
- AcpHttpTransport: connectionId extraction, header injection, init retry
- AutoReconnectTransport: reconnect mutex, fallback, delegation
- negotiateTransport: capability probing, timeout, fallback
- acpRouteTable: URL→method mapping, param extraction
Generated with AI
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
* fix(sdk): route table coverage, browser WS auth, header forwarding, capabilities type
- Route table: add file/stat/list/glob/write/edit paths (all DaemonClient URLs)
- Route table: add session diagnostic routes (context, tasks, stats, rewind, language)
- Route table: add bulk sessions/delete
- WS auth: document browser limitation, Node uses headers, browser needs proxy
- Headers: forward X-Qwen-Client-Id via JSON-RPC _meta in WS transport
- DaemonCapabilities: add transports field to SDK type
- Package exports: remove unreachable deep exports, document monorepo usage
- Provider bypass: document limitation for glob/stat/list in workspace actions
Generated with AI
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
* fix(sdk): add missing detach + hooks routes per QA doc
Cross-referenced with daemon-acp-integration-qa.md route table.
Added POST /session/:id/detach and GET /session/:id/hooks.
Generated with AI
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
* fix(serve,sdk): enforce ACP standard session/new — always isolated session
ACP standard mandates session/new MUST create a new isolated session.
Server-side (dispatch.ts):
- Force sessionScope='thread' on /acp session/new, ignoring client params
- REST POST /session retains 'single' default for backward compat
SDK-side (acpRouteTable.ts):
- Strip sessionScope from session/new params in ACP transports
- Document that ACP follows the standard (no extensions)
Generated with AI
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
* fix(serve): ACP session/new returns standard models/modes fields
ACP standard NewSessionResponse includes optional `models` and `modes`
top-level fields alongside `configOptions`. Extract model/mode state
from configOptions and surface them as standard-shaped objects:
- models: { currentModelId, availableModels: [{id}] }
- modes: { currentModeId, availableModes: [{id}] }
Also update test to verify sessionScope is always forced to 'thread'
(ACP standard compliance — session/new always creates isolated session).
Generated with AI
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
* feat(serve): add standard ACP methods session/set_mode, session/set_model, session/fork
Align /acp endpoint with ACP standard protocol:
- session/set_mode: dedicated method for mode changes (standard)
Maps to bridge.setSessionApprovalMode(). Params: {modeId, sessionId}
- session/set_model: dedicated method for model changes (unstable)
Maps to bridge.setSessionModel(). Params: {modelId, sessionId}
- session/fork: create a branched copy of an existing session
Maps to bridge.branchSession(). Response includes configOptions,
models, modes per ACP standard.
- session/load, session/resume: responses now include configOptions,
models, modes (per ACP LoadSessionResponse/ResumeSessionResponse)
Generated with AI
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
* fix(serve): TS2345 — pass persist: false to setSessionApprovalMode
Generated with AI
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
* fix(webui): add dispose() to MockDaemonClient in provider tests
DaemonClient now has dispose() (called in provider cleanup effect).
Mock clients in test files need to implement it.
Generated with AI
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
* fix(serve): add sessionId pre-validation + remove type assertion
- session/set_mode, session/set_model: add explicit sessionId empty
check before requireOwned (consistent with session/fork)
- session/set_model: remove `as unknown as` type assertion, pass
proper {modelId, sessionId} matching SetSessionModelRequest
Generated with AI
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
* fix(sdk,serve): align route table with dispatcher + AcpHttp SSE response correlation
Route table:
- Add _qwen/ prefix to all vendor session/workspace methods
- Split workspace catch-all into granular dispatcher methods
- Fix session/branch → session/fork, model → session/set_model
- Remove routes with no dispatcher handler
AcpHttpTransport:
- Implement conn-scoped SSE stream for response correlation
- POST returns 202 (ack), real response rides SSE stream
- Map<id, {resolve, reject}> for pending request correlation
dispatch.ts:
- Remove session/set_mode, session/set_model from CONN_ROUTED_METHODS
Generated with AI
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
* fix(sdk): bump browser bundle budget 116KB→118KB for transport abstraction
Main uses 117,753 bytes (99.1% of 116KB budget). The transport
abstraction adds ~1.5KB (DaemonTransport interface + RestSseTransport
default constructor in DaemonClient). Bump to 118KB (120,832 bytes).
Also change RestSseTransport to type-only export from barrel (class
is constructed internally by DaemonClient, not needed as a value
export for consumers).
Generated with AI
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
* fix(sdk): fix 2 test failures — SSE error message + workspace catch-all route
- RestSseTransport: error message 'SSE response has no body' → 'No SSE body'
(matches existing DaemonClient.test.ts assertion)
- acpRouteTable: re-add GET/POST /workspace/* catch-all after granular routes
(AcpWsTransport.test.ts expects generic workspace path to resolve)
Generated with AI
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
* fix(sdk): align RestSseTransport test with updated error message
Generated with AI
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
---------
Co-authored-by: 秦奇 <gary.gq@alibaba-inc.com>
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
|
||
|---|---|---|
| .. | ||
| design | ||
| developers | ||
| e2e-tests | ||
| plans | ||
| superpowers | ||
| users | ||
| verification/abort-controller-refactor | ||
| _meta.ts | ||
| declarative-agents-port.md | ||
| index.md | ||
| yaml-parser-replacement.md | ||