mirror of
https://github.com/QwenLM/qwen-code.git
synced 2026-07-10 01:29:17 +00:00
19 commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
07beac1ddb
|
feat(telemetry): Make sensitive span attribute limit configurable (#5804)
* feat(telemetry): Make sensitive span attribute limit configurable Default sensitive native OTel span attribute payload truncation to 1 MiB and allow users to override the limit via settings or environment. Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * codex: fix CI failure on PR #5804 Add the new sensitive span attribute default export to telemetry/core mocks used by the full Windows test suite. Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * codex: address PR review feedback (#5804) Include invalid telemetry max-length values in errors, make the telemetry parser stricter, include the configured truncation limit in markers, and cover the exact truncation boundary. Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * codex: address PR review feedback (#5804) Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * codex: address PR review feedback (#5804) Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * codex: address PR review feedback (#5804) Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * test(cli): fix ACP worktree mock for telemetry limit Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * fix(core): honor telemetry limit for model output spans Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * test(core): cover telemetry span limit edge cases Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * codex: address PR review feedback (#5804) Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * codex: address PR review feedback (#5804) Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * codex: address PR review feedback (#5804) Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * codex: address PR review feedback (#5804) Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * codex: address PR review feedback (#5804) Keep sensitive span truncation results within the configured max length, make response-text extraction require an explicit cap, and cover whitespace-only sensitive span max length env values. Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * codex: address PR review feedback (#5804) Keep model-output span attribute writes best-effort and share visible response text extraction between log and sensitive span paths. Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * fix(core): address telemetry review feedback Bound prefixed tool span payloads, share sensitive max-length validation, and cover multi-part sensitive model output. Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * fix(cli): update workspace facade core mock Add telemetry sensitive span length constants to the qwen-code-core mock used by the workspace service facade test so settings schema imports can load. Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * codex: address PR review feedback (#5804) Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * codex: address PR review feedback (#5804) Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * codex: address PR review feedback (#5804) Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> --------- Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> Co-authored-by: Shaojin Wen <shaojin.wensj@alibaba-inc.com> Co-authored-by: 易良 <1204183885@qq.com> |
||
|
|
a234860a4a
|
fix(core): Align MCP OAuth guidance and docs (#5589)
Some checks are pending
Qwen Code CI / Classify PR (push) Waiting to run
Qwen Code CI / Test (ubuntu-latest, Node 22.x) (push) Blocked by required conditions
Qwen Code CI / Test (macos-latest, Node 22.x) (push) Blocked by required conditions
Qwen Code CI / Test (windows-latest, Node 22.x) (push) Blocked by required conditions
Qwen Code CI / Post Coverage Comment (push) Blocked by required conditions
Qwen Code CI / CodeQL (push) Blocked by required conditions
Qwen Code CI / Integration Tests (CLI, No Sandbox) (push) Waiting to run
E2E Tests / E2E Test (Linux) - sandbox:docker (push) Waiting to run
E2E Tests / E2E Test (Linux) - sandbox:none (push) Waiting to run
E2E Tests / E2E Test - macOS (push) Waiting to run
* docs: Align docs with current CLI behavior Update stale documentation and user-facing MCP OAuth guidance to match the current dialog-based flows, SDK permission semantics, current links, and Qwen OAuth status. Also replace Ink internal imports with public Ink APIs for the shared text input so the workspace builds against Ink 7. Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * codex: address PR review feedback (#5589) Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * codex: address PR review feedback (#5589) Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * codex: address PR review feedback (#5589) Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * codex: address PR review feedback (#5589) Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * codex: address PR review feedback (#5589) Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * codex: address PR review feedback (#5589) Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * codex: address PR review feedback (#5589) Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * codex: address PR review feedback (#5589) Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * codex: address PR review feedback (#5589) Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * codex: address PR review feedback (#5589) Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * codex: fix BaseTextInput Ink import (#5589) Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * codex: address PR review feedback (#5589) Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * fix(core): surface MCP OAuth credential read failures Fix SSE OAuth credential pre-check failures by reporting token storage read errors before connecting. Update SDK coreTools docs and extension release link text from the follow-up review. Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * fix(core): harden MCP OAuth error handling Handle stderr warning failures as best-effort and keep SSE 401 OAuth guidance when credential re-read fails. Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * fix(core): keep SSE OAuth pre-read best effort Avoid blocking SSE MCP connections when the diagnostic credential pre-read fails, and cover BaseTextInput absolute-position edge cases. Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * fix(core): handle SSE OAuth validation errors Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * fix(core): surface MCP OAuth recovery guidance Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * fix(core): cover MCP OAuth retry paths Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * fix(core): address OAuth guidance review Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> --------- Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> |
||
|
|
7cb95bebbd
|
fix(docs): update Coding Plan model list and fix stale references in developer docs (#5054)
* fix(docs): update Coding Plan model list and fix stale references in developer docs - model-providers.md: expand Coding Plan model table from 3 to 9 models (add qwen3.6-plus, glm-5, kimi-k2.5, MiniMax-M2.5, qwen3-coder-next, glm-4.7) to match the provider registry - auth.md: update Coding Plan model list to match all 9 models and use the correct date-stamped model ID (qwen3-max-2026-01-23) - contributing.md: fix Node.js version requirement from 18+ to 22+ to match package.json engines - sdk-typescript.md: fix nonexistent tool name run_terminal_cmd → run_shell_command - integration-tests.md: fix file extension from .test.js to .test.ts to match actual test files - qwen-serve-protocol.md: fix legacy tool name search_file_content → grep_search and remove nonexistent ripgrep tool reference * fix(docs): add missing qwen3.7-plus to Coding Plan model docs MODELSTUDIO_MODELS in alibaba-coding-plan.ts defines 10 models, but the inline list in auth.md and the table in model-providers.md only listed 9, omitting qwen3.7-plus (1M context, thinking enabled). Add it after qwen3.6-plus in both, matching the source order. |
||
|
|
62ed44e1f3
|
feat(telemetry): client-side HTTP span + opt-in W3C traceparent propagation (#4384) (#4390)
Some checks are pending
Qwen Code CI / Classify PR (push) Waiting to run
Qwen Code CI / Lint (push) Blocked by required conditions
Qwen Code CI / Test (macos-latest, Node 22.x) (push) Blocked by required conditions
Qwen Code CI / Test (ubuntu-latest, Node 22.x) (push) Blocked by required conditions
Qwen Code CI / Test (windows-latest, Node 22.x) (push) Blocked by required conditions
Qwen Code CI / Post Coverage Comment (push) Blocked by required conditions
Qwen Code CI / CodeQL (push) Blocked by required conditions
E2E Tests / E2E Test (Linux) - sandbox:docker (push) Waiting to run
E2E Tests / E2E Test (Linux) - sandbox:none (push) Waiting to run
E2E Tests / E2E Test - macOS (push) Waiting to run
* feat(telemetry): propagate W3C traceparent on outbound LLM requests Part 1 of #4384 (sub-issue of #3731 P3 deeper observability). Today qwen-code's only OTel instrumentation is `HttpInstrumentation`, which only patches Node's `http`/`https` modules. The `openai` and `@google/genai` SDKs use `globalThis.fetch` (undici), so outbound LLM requests carry no `traceparent` header and trace context dies at the qwen-code process boundary. Adds `@opentelemetry/instrumentation-undici@0.14.0` (peer-compatible with the installed `@opentelemetry/instrumentation@0.203.0`) and wires it into `initializeTelemetry()` next to the existing `HttpInstrumentation`. Default propagator (W3C tracecontext + baggage) remains unchanged — no explicit `textMapPropagator` needed. `ignoreRequestHook` skips OTLP exporter endpoints to avoid the classic feedback loop (OTel SDK uses fetch to upload OTLP data; without the hook each upload would create a span that gets uploaded, infinitely). Configured `otlpEndpoint` / per-signal endpoints are stripped of trailing slash and query string for robust prefix matching against undici's `request.origin + request.path`. Outbound LLM calls now also produce a client-side HTTP span (separating network TTFB / transfer time from the existing `api.generateContent` total-duration span). Design doc: docs/design/telemetry-outbound-propagation-design.md (Part A — traceparent; Part B — session id header — lands in a follow-up PR per the design's split rationale.) 🤖 Generated with [Qwen Code](https://github.com/QwenLM/qwen-code) * fix(telemetry): harden OTLP feedback-loop guard + slim lockfile diff Review feedback on #4390: 1. CI was failing on npm ci because the lockfile was generated with npm 11 locally (it sprinkles `peer: true` annotations npm 10 reads differently and rejects). Regenerated with npm 10 (matching CI's Node 22.x default), so the diff vs main is now 18 lines (the actual instrumentation-undici entry) instead of 105 lines of npm-version drift noise. 2. (Copilot inline at sdk.ts:330) `otlpUrlPrefixes` was derived from raw Config strings, so a settings.json `"otlpEndpoint": "\"http://...\""` (quoted) or trailing `#fragment` would silently miss the prefix match and reintroduce the feedback loop the hook exists to prevent. Replaced the regex-based suffix trim with a WHATWG URL parser: - strips ?query, #fragment, trailing slash - trims symmetric ASCII quotes a user may have placed in settings.json - falls back to safe suffix trimming if URL parsing fails (misconfigured endpoint still gets SOME protection) 3. (CodeQL inline) Replaced the `/\?.*$/` regex in ignoreRequestHook with `indexOf('?')`/`indexOf('#')` slicing for ReDoS hygiene. The regex was linear in practice but flagged as polynomial — using indexOf removes the ambiguity and is arguably simpler. Added 3 tests in sdk.test.ts covering the new normalizations (#fragment on incoming path, quoted endpoint, #fragment on configured endpoint). 🤖 Generated with [Qwen Code](https://github.com/QwenLM/qwen-code) * feat(telemetry): propagate X-Qwen-Code-Session-Id on outbound LLM requests Part 2 of #4384. Stacks on top of PR #4390 (traceparent via undici). Adds a product-namespaced HTTP header X-Qwen-Code-Session-Id to every outbound LLM request when telemetry is enabled, so server-side ingestion can correlate observed requests with qwen-code session metric/log records. Pattern matched from claude-code (X-Claude-Code-Session-Id, verified at src/services/api/client.ts:108 in their open-source repo). Critical design decision (design doc section 4.3): the OpenAI / Anthropic providers use a per-request fetch wrapper rather than the SDK defaultHeaders option, because content-generator SDK clients are constructed once and NOT recreated on /clear-triggered session resets (Config.resetSession updates this.sessionId but the contentGenerator keeps using the stale header value). Reading config.getSessionId() from inside the wrapper at request time gives the live value. Gemini provider uses static httpOptions.headers — @google/genai HttpOptions interface does not expose a fetch hook (only headers, baseUrl, apiVersion, timeout, extraParams). This is a known limitation: after session reset, Gemini X-Qwen-Code-Session-Id stays stale until the contentGenerator is recreated. Documented in telemetry.md and the design doc section 8.6; spans/logs continue to carry the live session id for trace/log correlation. Lazy-invalidate fix is a follow-up sub-issue. Header is omitted when telemetry is disabled OR when getSessionId returns an empty string (some HTTP middleware rejects empty header values). Integration sites: - packages/core/src/core/openaiContentGenerator/provider/default.ts (base class — automatically covered by deepseek/minimax/mistral/ modelscope/openrouter subclasses; openrouter calls super.buildHeaders) - packages/core/src/core/openaiContentGenerator/provider/dashscope.ts (overrides buildClient — must be touched separately; QwenContentGenerator inherits via this provider) - packages/core/src/core/anthropicContentGenerator/anthropicContentGenerator.ts - packages/core/src/core/geminiContentGenerator/index.ts (factory function, not the GeminiContentGenerator class — no signature change) End-to-end verification (local HTTP server in tmux): PASS: traceparent + X-Qwen-Code-Session-Id on every LLM request PASS: session id refreshes after simulated /clear (staleness regression guarded by llm-correlation-fetch.test.ts) PASS: OTLP upload traffic not traced (no feedback loop — PR A ignoreRequestHook working) Robot generated with Qwen Code https://github.com/QwenLM/qwen-code * fix(telemetry): R2 review fixes — critical correctness + tsc + boundary safety Adopts 7 review findings from wenshao on #4390 (+ duplicates from now-closed #4393). Critical bugs first, polish second. CRITICAL: 1. tsc TS2322 — wrapper return type incompatible with Anthropic SDK Fetch. `typeof fetch` (Node WHATWG, 2 overloads) is not structurally assignable to Anthropic's narrower `Fetch = (input: RequestInfo, init?) => ...`, even though they're call-compatible at runtime. Make wrapper generic `<TFetch extends FetchLikeLoose>` so callers preserve their exact fetch signature; cast the Anthropic call site through `unknown` with a comment explaining why. 2. tsc TS2352 / TS2493 — `baseFetch.mock.calls[0]![1] as RequestInit` was out-of-bounds when wrapped was called with no init arg. Replaced with a `makeFetchMock()` helper returning typed accessors. 3. normalizeOtlpPrefix catch fallback was DANGEROUS — a config of `"http"` produced prefix `"http"` which `startsWith`-matched every outbound HTTP request → silently disabled ALL instrumentation (no client spans, no correlation header — defeats the entire feature). Fixed: catch returns undefined + diag.warn. Misconfigured endpoint loses its feedback-loop guard (acceptable) instead of disabling all guards (catastrophic). 4. `url.startsWith(prefix)` matching was NOT boundary-safe — port collision (`:4318` matches `:43180`), hostname suffix collision (`otlp.example.com` matches `otlp.example.com.evil.net`), path-segment collision (`/v1` matches `/v1foo/x`). Replaced with origin-equality + path-prefix + boundary-char check (next char must be `/`, `?`, `#`, or end-of-string). 5. HttpInstrumentation also lacked the OTLP feedback-loop guard. The OTLP HTTP exporter (`@opentelemetry/exporter-trace-otlp-http`) uses node:http (patched by HttpInstrumentation, NOT undici). Without this, every OTLP upload batch creates a parasitic client span → feedback loop. Added `ignoreOutgoingRequestHook` that reuses the same `matchesOtlpPrefix` / `stripPathSuffix` helpers as the undici instrumentation. SAFETY: 6. Request input + undefined init dropped the Request's own headers (Authorization etc.) because `new Headers(undefined)` → `{...init, headers}` replaced them with just our session header. Fix: when input is a Request and init.headers is unset, seed from input.headers before adding ours. 7. Wrapped fetch had no try/catch — a throwing Config getter or Headers constructor would propagate as TypeError and break the LLM request path. Wrapped header construction in try/catch; on failure, fall through to baseFetch with original init (no header) + diag.warn. Telemetry must never break the model call. COVERAGE: - 3 new sdk.test.ts boundary tests (port/host/path) - 1 new sdk.test.ts normalizeOtlpPrefix catch-branch coverage - 1 new sdk.test.ts HttpInstrumentation OTLP guard test - 1 new sdk.test.ts proxy-mode wrapped-fetch test (default.test.ts) - 1 new anthropic test asserting wrapped fetch installed on Anthropic SDK - 2 new llm-correlation-fetch.test.ts (Request-headers preservation + try/catch fall-through) All 668 tests pass (1 pre-existing Anthropic User-Agent failure on main is unrelated). tsc clean. Declined: #10 DRY-refactor of baseFetch extraction across 3 sites — the duplication was pre-existing (default/dashscope buildClient was already near-identical), refactoring is a separate cleanup PR not gated by this feature. Will reply on the thread. 🤖 Generated with [Qwen Code](https://github.com/QwenLM/qwen-code) * chore(deps): allow patch updates for @opentelemetry/instrumentation-undici Switch from exact pin `0.14.0` to `^0.14.0` for consistency with the rest of the `@opentelemetry/*` deps in this block (all carated). For 0.x semver, npm treats `^0.14.0` as `>=0.14.0 <0.15.0`, so patch updates within the 0.14.x line — which are tied to the same `@opentelemetry/instrumentation@0.203.x` peer — flow in via `npm update` without requiring a manual package.json edit. A bump across the 0.x minor (e.g. 0.15.x) would shift the instrumentation peer compatibility and still requires explicit attention, which the caret correctly blocks. Per review feedback on #4390 (wenshao). 🤖 Generated with [Qwen Code](https://github.com/QwenLM/qwen-code) * test(telemetry): stub getTelemetryEnabled + getSessionId in Gemini factory tests The X-Qwen-Code-Session-Id commit added a `staticCorrelationHeaders(gcConfig)` call inside the Gemini content generator factory. That helper reads `gcConfig.getTelemetryEnabled()` and `gcConfig.getSessionId()` per request. Both pre-existing Gemini tests in `contentGenerator.test.ts` build a minimal partial Config stub via `as unknown as Config` and only stub the methods the factory used to need. The new call path now hits the unstubbed methods at runtime, surfacing as `TypeError: config.getTelemetryEnabled is not a function` on all three CI platforms. Add the two missing stubs to both test cases. The Gemini factory continues to ignore the values when telemetry is off — these stubs only have to exist, not return anything in particular. Local check ran the full test suite for the four directories `/loop` covers plus `src/core/contentGenerator.test.ts` itself; all green. Also re-ran the other test files that build partial Config mocks via the same idiom (`client.test.ts`, `config.test.ts`, `nextSpeakerChecker.test.ts`, `content-generator-config.test.ts`) — none exercise the new code path. 🤖 Generated with [Qwen Code](https://github.com/QwenLM/qwen-code) * fix(telemetry): R3 review fixes — port + protocol + quote + safety Four issues found by wenshao reviewing the R2 boundary-safety pass on PR #4390. All four close gaps where the OTLP feedback-loop guard or the correlation-header path could fail silently. 1. **Port normalization mismatch** (sdk.ts ignoreOutgoingRequestHook): `normalizeOtlpPrefix` builds prefixes via `URL.origin`, which strips default ports (`:80` for http, `:443` for https). The hook reconstructed request origin manually as `${proto}://${host}${portPart}`, keeping the port. Result: prefix `http://collector` (no explicit port) didn't match a request to `http://collector:80/v1/traces` because their `.origin` differed → guard bypassed → feedback loop. Now the reconstructed origin is also routed through `URL` so both sides apply the same default-port stripping. 2. **HTTPS proto silent fallback** (sdk.ts ignoreOutgoingRequestHook): The `(req.protocol && ...) || 'http'` fallback would silently mis-bucket HTTPS requests as HTTP when `req.protocol` was unset, so HTTPS OTLP endpoints couldn't match their prefix. Changed to fail open: when proto can't be determined, return false (request gets instrumented). Worst case is a parasitic client span — observable, recoverable — versus the previous unbounded silent feedback loop. Picked fail-open over the bot's port-based heuristic because non-standard HTTPS ports break the heuristic but not fail-open. 3. **Quote-stripping divergence** (sdk.ts normalizeOtlpPrefix): `parseOtlpEndpoint` (line 109) uses `/^["']|["']$/g` which strips asymmetric leading/trailing quotes; `normalizeOtlpPrefix` previously only stripped symmetric pairs. A settings.json typo like `"value'` would let the exporter connect (parseOtlpEndpoint trims) but leave the guard returning `undefined` (normalizeOtlpPrefix rejected) → parasitic loop. Aligned `normalizeOtlpPrefix` to the same lenient regex. 4. **`staticCorrelationHeaders` missing try/catch** (llm-correlation-fetch.ts): `wrapFetchWithCorrelation` already catches all internal exceptions and falls through to baseFetch — same "telemetry must never break LLM path" contract was missing on the static-headers helper. A throw here would propagate up to the Gemini content-generator factory and crash content-generator init for the whole session. Wrapped the body in try/catch with `diag.warn` fall-through to `{}`. Tests: added 4 regression tests covering each scenario: - default-port HTTP request matched against portless prefix (1) - hook returns false when req.protocol missing on https endpoint (2) - asymmetric-quoted endpoint normalizes for guard parity (3) - staticCorrelationHeaders returns {} when config getter throws (4) 🤖 Generated with [Qwen Code](https://github.com/QwenLM/qwen-code) * docs(telemetry): fix misleading "BOTH" wording in wrapFetchWithCorrelation The comment described the header-seeding logic as merging "BOTH the init.headers AND the Request's own headers", but the two branches are mutually exclusive — `new Headers(init?.headers)` runs unconditionally (empty Headers when init.headers is undefined), and the Request-headers copy only runs when init.headers is undefined. So in practice it's either-or, not BOTH. Reworded to match the actual logic per #4390 review feedback (wenshao). Behavior unchanged. 🤖 Generated with [Qwen Code](https://github.com/QwenLM/qwen-code) * fix(telemetry): strip port from req.host fallback + document undici scope Two issues found by wenshao reviewing the R3 boundary-safety fixes on PR #4390. 1. **`req.host` may already include `:port`** (sdk.ts ignoreOutgoingRequestHook): When `req.hostname` is absent and `req.host` is the fallback, the value may already be `"collector:4318"`. Naively appending `:${req.port}` produced `"http://collector:4318:4318"` → `new URL()` rejects → catch returns false → silent guard bypass for that request. Currently unreachable because `@opentelemetry/otlp-exporter-base` always sets `hostname` from WHATWG URL parsing, but the fallback exists in the code and must be correct — a future OTLP transport that emits `host` without `hostname` would silently trigger the feedback loop. Strip the port when falling back; bracketed IPv6 literals like `"[::1]:443"` keep their bracketed host intact. 2. **Undici scope honesty** (telemetry.md): Previous docs framed the propagation as "outbound LLM requests", but `UndiciInstrumentation` actually patches `globalThis.fetch` for the whole process — `WebFetch`, MCP clients, IDE extension calls all get spans + `traceparent` injection too. Added a "Scope: all fetch() calls, not just LLM" subsection covering: (a) trace ID leakage to third-party URLs (the user-supplied destinations of `WebFetch` see our trace ID; not secret per W3C but worth knowing); (b) non-LLM span volume inflating OTLP batches with a workaround tip. Per-destination scoping toggle deferred as a follow-up — out of scope for this PR. Added regression test for the host:port-fallback path. Test exercises the previously broken combination (hostname absent, host carries port) through the existing test harness. 🤖 Generated with [Qwen Code](https://github.com/QwenLM/qwen-code) * feat(telemetry): scope X-Qwen-Code-Session-Id to first-party hosts by default Address LaZzyMan's REQUEST_CHANGES review of PR #4390. The original design injected `X-Qwen-Code-Session-Id` on every outbound LLM request gated only by `telemetry.enabled`. Review caught that this broadcasts a stable cross-request client identifier to every configured third-party provider (OpenAI, Anthropic, OpenRouter, MiniMax, ModelScope, Mistral, vanilla Gemini, ...), which the claude-code precedent does NOT justify — claude-code is a first-party Anthropic→Anthropic flow; qwen-code is an open-source CLI connecting to many providers. Fix: add a host allowlist with a deliberately narrow default. The header is now only attached to destinations whose hostname matches: dashscope.aliyuncs.com dashscope-intl.aliyuncs.com *.dashscope.aliyuncs.com *.dashscope-intl.aliyuncs.com *.alibaba-inc.com *.aliyun-inc.com This is exactly the set where the LLM provider, the upstream telemetry backend (ARMS Tracing), and qwen-code itself are the same legal entity — mirroring the first-party claude-code pattern and preserving the real product value (server-side trace stitching against DashScope) without exposing the session id to third parties. Operators with broader correlation requirements override via: "telemetry": { "sessionIdHeaderHosts": ["*"] // restore broadcast "sessionIdHeaderHosts": [] // fully disable "sessionIdHeaderHosts": ["api.example.com", "*.foo"] // custom allowlist } Implementation: - NEW `telemetry/trusted-llm-hosts.ts`: `DEFAULT_SESSION_ID_HEADER_HOSTS` + `matchesTrustedHost(hostname, patterns)` + `extractRequestHost(input)`. Pattern syntax is intentionally tiny (bare hostname OR `*.suffix`, dot-anchored to reject `evil-alibaba-inc.com` style attacks). Unit-tested in dedicated test file including TLD/sub-domain attack vectors. - `wrapFetchWithCorrelation` (openai + anthropic providers): resolves the allowlist at wrap time (Config snapshot), inspects each request's destination URL inside `correlationFetch`, falls through to baseFetch for non-trusted destinations. Wildcard escape hatch via `["*"]`. - `staticCorrelationHeaders` (Gemini factory): now takes an optional `destinationUrl` and applies the same host gate. The Gemini SDK default endpoint `generativelanguage.googleapis.com` is NOT on the default allowlist, so vanilla Gemini calls receive no header — matching the "first-party only" scope. Operators who put the Gemini SDK on a DashScope-compatible endpoint via `baseUrl` get the header naturally. - `Config.getTelemetrySessionIdHeaderHosts()` getter + `TelemetrySettings.sessionIdHeaderHosts` interface field + JSON schema entry in `settingsSchema.ts`. Wired through `resolveTelemetrySettings`. - Defensive optional-chaining + try/catch on the Config getter call at wrap time so partial test mocks (or pre-getter Config implementations) fall back to the default allowlist rather than crashing buildClient. Tests: 12 new cases covering host match/skip on default allowlist, sub-domain handling, TLD-suffix attack rejection, `["*"]` broadcast override, `[]` full-disable, custom operator allowlist, unparseable destination (fail closed), and the three Gemini factory paths (googleapis.com default → omit; DashScope `baseUrl` → inject; custom allowlist → inject). Docs updated in `docs/developers/development/telemetry.md` Session correlation header section, including override examples and the new Gemini host-gate semantics. Closes the LaZzyMan REQUEST_CHANGES blocker. The cross-vendor fingerprint-broadcast failure mode is now opt-in rather than default, restoring the first-party-only semantics that make the claude-code precedent applicable. 🤖 Generated with [Qwen Code](https://github.com/QwenLM/qwen-code) * fix(telemetry): R5 review fixups — Vertex destination + ["*"] trim + docs Self-review pass on commit |
||
|
|
64401e1d17
|
feat(telemetry): support custom resource attributes and add metric cardinality controls (#4367)
* feat(telemetry): support custom resource attributes and add metric cardinality controls Resolves #4365. Adds two coupled OpenTelemetry capabilities to make qwen-code's telemetry production-ready in multi-team / multi-tenant deployments: 1. Custom resource attributes via standard `OTEL_RESOURCE_ATTRIBUTES` and `OTEL_SERVICE_NAME` env vars and a new `telemetry.resourceAttributes` setting. Operators can now tag every span / log / metric with `team`, `env`, `cost_center`, or anything else their backend needs. 2. Metric cardinality controls. `session.id` is moved off the OpenTelemetry Resource (where it auto-attached to every metric data point and caused unbounded time-series fan-out on Prometheus / ARMS Metric / etc.) and gated behind a new opt-in `telemetry.metrics.includeSessionId` toggle. Spans and logs still carry `session.id` for trace and log correlation. Reserved keys (`service.version`, `session.id`) are stripped from both env and settings sources with a `diag.warn`. `OTEL_SERVICE_NAME` follows the OTel spec precedence (highest priority for `service.name`). Settings JSON values are runtime-coerced to strings as defense against hand-edited non-conforming JSON. Breaking change: metrics no longer carry `session.id` by default. Operators who need it can restore the previous behavior with `QWEN_TELEMETRY_METRICS_INCLUDE_SESSION_ID=true` or `telemetry.metrics.includeSessionId: true` in settings.json; recommended only for short-term debugging since it re-introduces the cardinality problem. For long-term session-level analysis, prefer trace and log backends which handle per-event data without cardinality pressure. Design doc: docs/design/telemetry-resource-attributes-design.md 🤖 Generated with [Qwen Code](https://github.com/QwenLM/qwen-code) * docs(telemetry): align reserved-key descriptions with implementation Round 1 review fixes (#4367). After session.id was added to RESERVED_RESOURCE_ATTRIBUTE_KEYS in Codex review, four user-facing descriptions still claimed only service.version was reserved: - packages/core/src/telemetry/config.ts (merge comment) - packages/core/src/config/config.ts (TelemetrySettings JSDoc) - packages/cli/src/config/settingsSchema.ts (schema description) - packages/vscode-ide-companion/schemas/settings.schema.json (regenerated) Also corrects scope claim: resource attributes apply to every signal the SDK exports (OTLP and file outfile share the same Resource), not just OTLP. 🤖 Generated with [Qwen Code](https://github.com/QwenLM/qwen-code) * docs(telemetry): clarify warning destination and surface percent-encoding hint Round 2 self-review fixes (#4367). Two small but real UX gaps: 1. Reserved-key / malformed-pair / coerce warnings route to the debug log (per #3986), not the console — so a user who types `OTEL_RESOURCE_ATTRIBUTES=service.version=2.0` sees no feedback that the value was silently dropped. Adds a "Troubleshooting" section in telemetry.md telling users where to look, and a note in the parser docstring documenting where warns go. 2. A literal (unencoded) comma in an env var value is a common foot-gun: the parser splits on it, producing a malformed second half that is silently dropped. Updates the warn text to include a "hint: percent-encode literal commas as %2C" callout, and adds the same guidance to the docs. Deferred to a follow-up: startup-time stderr summary of dropped attributes. Stderr during TUI render could break Ink rendering, so the right surface needs separate design. 🤖 Generated with [Qwen Code](https://github.com/QwenLM/qwen-code) * test(telemetry): cover first-`=` split contract in OTEL_RESOURCE_ATTRIBUTES parser Per review feedback on #4367. The parser uses `indexOf('=')` so the first `=` separates key and value while subsequent `=` stay in the value. The behavior was correct but untested; a future refactor to `split('=')` would silently break base64-padded, JWT, or connection-string values. 🤖 Generated with [Qwen Code](https://github.com/QwenLM/qwen-code) * feat(telemetry): tighten resource-attribute input validation + startup summary Adopts review feedback from #4367 (wenshao via Qwen Code /review). Five accepted suggestions, bundled because they all touch the same parse/coerce/strip pipeline: 1. Key percent-decoding (CRITICAL). `parseOtelResourceAttributes` now percent-decodes both keys and values per the OTel / W3C Baggage spec. Without this, `OTEL_RESOURCE_ATTRIBUTES=service%2Eversion=99` lands on Resource as the literal key `service%2Eversion`, bypassing the reserved-key filter; a collector that decodes keys downstream could then resurrect `service.version` and spoof the version label. 2. Startup summary of dropped attributes. Every `diag.warn` in resource-attributes.ts routes only to the OTel debug log (per #3986), giving operators zero feedback when their attributes are silently dropped. Helpers now optionally accumulate diagnostics into a `ResourceAttributeWarnings` array; the resolver collects them and the SDK emits a one-time console summary at init (before Ink renders, so no TUI conflict). 3. `||` instead of `??` for service.name fallback. Settings can put an empty string through `??`, producing a blank `service.name` that some backends reject. `||` falls through to the default. 4. `coerceStringResourceAttributes` now trims keys and skips empty/whitespace-only keys, matching `parseOtelResourceAttributes`. Previously `{" ": "x"}` or `{"team ": "y"}` from settings.json would land as malformed Resource attributes. 5. `OTEL_SERVICE_NAME` is trimmed before the truthy check, so values like `' '` or `'\t'` are treated as unset rather than producing a whitespace-only service name on Resource. One suggestion declined (in-thread reply on PR): - "Redundant `?? {}` in sdk.ts:160" — intentional defense-in-depth for `vi.mock('../config/config.js')` callers in `telemetry.test.ts` where auto-stub returns undefined. The reviewer is right that production code paths never hit it, but tests do. 🤖 Generated with [Qwen Code](https://github.com/QwenLM/qwen-code) * fix(telemetry): trim whitespace-only service.name + add invalid-key-encoding test Adopts two review suggestions on #4367 (wenshao via Qwen Code /review): 1. `service.name` fallback uses `.trim() || SERVICE_NAME` instead of plain `||`. Plain `||` lets whitespace-only values (`" "`, `"\t"`) through as truthy, producing a blank service name on Resource that some backends reject. Both settings (no value trimming) and env (`%20` decodes to `" "`) can deliver such values. Test added. 2. Adds `key%ZZ=val` to the parameterized parser test to cover the invalid-percent-encoding-on-key catch branch. Previously only the value-side catch was tested. 🤖 Generated with [Qwen Code](https://github.com/QwenLM/qwen-code) |
||
|
|
54fd5c50f0
|
feat(telemetry): add detailed sensitive span attributes (#4097)
Layer detailed content attributes onto the existing hierarchical spans (qwen-code.interaction / qwen-code.llm_request / qwen-code.tool) gated by includeSensitiveSpanAttributes: - Interaction span: user prompt (new_context) - LLM request span: system prompt + hash + preview + length (full text deduped per session via SHA-256), tool schemas (per-tool tool_schema events, also hash-deduped), model output - Tool span: tool input, tool result on every exit path (success + pre-hook block + post-hook stop + tool error + try-block cancel + catch-block cancel + execution exception) All large content truncated at 60KB with *_truncated and *_original_length metadata. Heavy serialization (safeJsonStringify on tool I/O, partToString on user prompt) is guarded by the sensitive flag at the call site so it doesn't run when telemetry is off. Also adds: - getActiveInteractionSpan() helper for client.ts to attach prompt attributes to the interaction span. - Updated config schema description and docs (telemetry.md + settings.md) to reflect expanded scope and add security/cost notes. - 28 unit tests for detailed-span-attributes, 4 tests for getActiveInteractionSpan, integration mocks updated. |
||
|
|
aecea70114
|
docs(telemetry): align config and docs semantics for target, outfile, and CLI flags (#4066)
* docs(telemetry): align config and docs semantics for target, outfile, and CLI flags - Remove stale warning note "This feature requires corresponding code changes" — the OTLP implementation is now complete (#3779, #4061) - Clarify that `target` is an informational destination label and does not control exporter routing; `otlpEndpoint` or `outfile` must be set to configure where data is sent - Mark `--telemetry-target` CLI flag as deprecated in the configuration table to match the deprecateOption() call in cli/src/config/config.ts - Fix `outfile` / `QWEN_TELEMETRY_OUTFILE` descriptions: remove the incorrect "when target is local" qualifier — outfile overrides OTLP export regardless of the target value - Simplify the file-based output example by removing the now-redundant `"target": "local"` and `"otlpEndpoint": ""` fields Closes the "Align telemetry config and docs semantics for target, useCollector, otlpEndpoint, otlpProtocol, and outfile" checklist item in #3731. 🤖 Generated with [Qwen Code](https://github.com/QwenLM/qwen-code) * docs(telemetry): address Copilot review comments on outfile and target descriptions - Fix outfile table row in telemetry.md: "overrides `otlpEndpoint`" → "overrides OTLP export" (outfile disables all OTLP exporting, not just the base endpoint) - Use fully-qualified setting names (`telemetry.otlpEndpoint`, `telemetry.outfile`) in the target description in settings.md for consistency with the rest of the table 🤖 Generated with [Qwen Code](https://github.com/QwenLM/qwen-code) * docs(telemetry): update QWEN_TELEMETRY_TARGET env var description and add outfile note - Align QWEN_TELEMETRY_TARGET env var description with the updated telemetry.target setting semantics (informational label, not routing) - Add a note after the file-based output example clarifying that outfile automatically disables OTLP export 🤖 Generated with [Qwen Code](https://github.com/QwenLM/qwen-code) |
||
|
|
32a49b4ddb
|
refactor(telemetry): remove dead useCollector setting and unreachable TelemetryTarget.QWEN (#4061)
Some checks are pending
Qwen Code CI / Classify PR (push) Waiting to run
Qwen Code CI / Lint (push) Blocked by required conditions
Qwen Code CI / Test (macos-latest, Node 22.x) (push) Blocked by required conditions
Qwen Code CI / Test (ubuntu-latest, Node 22.x) (push) Blocked by required conditions
Qwen Code CI / Test (windows-latest, Node 22.x) (push) Blocked by required conditions
Qwen Code CI / Post Coverage Comment (push) Blocked by required conditions
Qwen Code CI / CodeQL (push) Blocked by required conditions
E2E Tests / E2E Test (Linux) - sandbox:docker (push) Waiting to run
E2E Tests / E2E Test (Linux) - sandbox:none (push) Waiting to run
E2E Tests / E2E Test - macOS (push) Waiting to run
useCollector was plumbed through config (interface, constructor, getter, env var resolution) but never consumed by the telemetry SDK — the setting had no runtime effect. TelemetryTarget.QWEN existed in the enum but parseTelemetryTargetValue() only accepted 'local' and 'gcp', making 'qwen' unreachable (it would throw FatalConfigError). Remove both dead code paths along with their tests and documentation. Part of #3731 |
||
|
|
df90da6f03
|
feat(telemetry): add sensitive span attribute opt-in (#3893)
* feat(telemetry): add sensitive span attribute opt-in Add a telemetry setting and environment override for including sensitive attributes in spans created by the log-to-span bridge. Keep the default filtering behavior for prompt, function_args, and response_text unless explicitly enabled. Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * fix(telemetry): clarify span bridge options Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * feat(telemetry): populate api response text Populate response_text on API response telemetry events for non-internal prompts so opted-in bridge spans can include model response bodies. Exclude thought text from the recorded response text and keep internal prompt responses omitted. Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * docs(telemetry): clarify sensitive span attribute scope Clarify that the sensitive span attribute setting only controls log-to-span bridge spans, while response text may still reach other telemetry sinks from API response events. Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * fix(telemetry): cap recorded response text Limit response_text captured for API response telemetry to a bounded length and mark truncated values to avoid oversized OTLP attributes. Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> --------- Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> |
||
|
|
5d1052a358
|
feat(telemetry): define HTTP OTLP endpoint behavior and signal routing (#3779)
Some checks are pending
Qwen Code CI / Lint (push) Waiting to run
Qwen Code CI / Test (push) Blocked by required conditions
Qwen Code CI / Test-1 (push) Blocked by required conditions
Qwen Code CI / Test-2 (push) Blocked by required conditions
Qwen Code CI / Test-3 (push) Blocked by required conditions
Qwen Code CI / Test-4 (push) Blocked by required conditions
Qwen Code CI / Test-5 (push) Blocked by required conditions
Qwen Code CI / Test-6 (push) Blocked by required conditions
Qwen Code CI / Test-7 (push) Blocked by required conditions
Qwen Code CI / Test-8 (push) Blocked by required conditions
Qwen Code CI / Post Coverage Comment (push) Blocked by required conditions
Qwen Code CI / CodeQL (push) Waiting to run
E2E Tests / E2E Test (Linux) - sandbox:docker (push) Waiting to run
E2E Tests / E2E Test (Linux) - sandbox:none (push) Waiting to run
E2E Tests / E2E Test - macOS (push) Waiting to run
* feat(telemetry): define HTTP OTLP endpoint behavior and signal routing - Add resolveHttpOtlpUrl() that appends /v1/traces, /v1/logs, /v1/metrics to base HTTP OTLP endpoints per the OpenTelemetry specification - Add per-signal endpoint overrides (otlpTracesEndpoint, otlpLogsEndpoint, otlpMetricsEndpoint) for backends with non-standard paths (e.g. Alibaba Cloud) - Add LogToSpanProcessor that bridges OTel log records to spans for traces-only backends, with session-based traceId correlation and error status propagation - Auto-wire LogToSpanProcessor when traces URL exists but logs URL doesn't - Validate per-signal URLs gracefully (log error + skip, don't crash) - Preserve query strings when appending signal paths to URLs - Guard gRPC branch against missing base endpoint with per-signal config - Update telemetry documentation with signal routing semantics and Alibaba Cloud HTTP per-signal endpoint examples Closes #3734 Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * fix(telemetry): fix TS noPropertyAccessFromIndexSignature errors in tests Use typed ExportedSpan interface and bracket notation for index signature properties to satisfy strict TypeScript checks in CI. Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * fix(telemetry): replace MD5 with SHA-256 for traceId derivation CodeQL flagged MD5 as a weak cryptographic algorithm when used with session.id (considered sensitive data). Switch to SHA-256 truncated to 32 hex chars to satisfy CodeQL while maintaining the same traceId format required by the OTel specification. Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * fix(telemetry): address review feedback for LogToSpanProcessor robustness - Wrap JSON.stringify in try/catch to handle circular refs and BigInt - Add export timeout (30s) and try/catch to prevent hung shutdown - Track in-flight exports to avoid interval-vs-shutdown race condition - Fix deriveSpanStatus: use truthy checks (!!), drop success===false heuristic since declined tool calls are normal, not errors - Enforce http(s) scheme in validateUrl to reject file:/javascript: URLs - Change DiagLogLevel from ERROR to WARN to preserve operational diagnostics - Preserve logRecord.instrumentationScope instead of hardcoding - Forward severityNumber/severityText as span attributes - Add tests for circular refs, error status edge cases, severity Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * fix(telemetry): flush sdk shutdown through cleanup Remove async process exit handlers from telemetry initialization and route SDK shutdown through Config cleanup so normal CLI exit paths await pending telemetry exports. Keep shutdown idempotent while an SDK shutdown is in flight. Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * fix(telemetry): harden bridged log shutdown Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * fix(telemetry): address review follow-ups Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> --------- Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> |
||
|
|
6c71b6b09c
|
chore(core): drop tool token usage tracking (#3727)
The `tool_token_count` field was sourced from `toolUsePromptTokenCount` on the GenAI usage metadata, but none of the providers we adapt (OpenAI/DashScope, Anthropic) populate it, and Google's Gemini API only emits it for built-in server-side tools that qwen-code does not use. The metric was therefore always zero in practice, so the dedicated counter, telemetry field, UI row, and supporting plumbing are removed end-to-end (telemetry types, OTEL counter type, UI aggregation, model stats display, qwen-logger payload, VS Code session schema, and docs). |
||
|
|
4be0234d10
|
docs(telemetry): clarify Alibaba Cloud console entry (#3498)
Some checks are pending
Qwen Code CI / Lint (push) Waiting to run
Qwen Code CI / Test (push) Blocked by required conditions
Qwen Code CI / Test-1 (push) Blocked by required conditions
Qwen Code CI / Test-2 (push) Blocked by required conditions
Qwen Code CI / Test-3 (push) Blocked by required conditions
Qwen Code CI / Test-4 (push) Blocked by required conditions
Qwen Code CI / Test-5 (push) Blocked by required conditions
Qwen Code CI / Test-6 (push) Blocked by required conditions
Qwen Code CI / Test-7 (push) Blocked by required conditions
Qwen Code CI / Test-8 (push) Blocked by required conditions
Qwen Code CI / Post Coverage Comment (push) Blocked by required conditions
Qwen Code CI / CodeQL (push) Waiting to run
E2E Tests / E2E Test (Linux) - sandbox:docker (push) Waiting to run
E2E Tests / E2E Test (Linux) - sandbox:none (push) Waiting to run
E2E Tests / E2E Test - macOS (push) Waiting to run
* docs(telemetry): clarify Alibaba Cloud console entry Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * docs(telemetry): fix unreachable intl console URL and split new/legacy console guidance - Replace unreachable tracing-sgnew.console.alibabacloud.com with the verified arms.console.alibabacloud.com for international users - Separate OTLP endpoint retrieval steps by console version: new console uses Integration Center, legacy console uses Cluster Configurations → Access point information 🤖 Generated with [Qwen Code](https://github.com/QwenLM/qwen-code) * docs(telemetry): align target example with current implementation Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * docs(telemetry): clarify Alibaba Cloud OTLP setup Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * docs(telemetry): remove stale TOC entry Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> --------- Co-authored-by: jinye.djy <jinye.djy@alibaba-inc.com> Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> |
||
|
|
6e0cf6541d |
refactor(telemetry): update session event fields to match current config
- Remove deprecated fields: embedding_model, api_key_enabled, vertex_ai_enabled, log_prompts_enabled - Add new fields: truncate_tool_output_threshold, truncate_tool_output_lines, hooks, ide_enabled, interactive_shell_enabled This aligns telemetry data with the current CLI configuration options. Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> |
||
|
|
35c865968f | chore: remove tiktoken dependency and replace with character-based token estimation | ||
|
|
5742a69d8a | feat: update docs | ||
|
|
60211b8180 | feat: update docs | ||
|
|
e12a80b24e | feat: update docs | ||
|
|
bfe8133ea3 | feat: refactor docs | ||
|
|
17785c418d | feat: restructure docs |