chore(telemetry): rebrand to proto-cli, nuke qwen-logger Alibaba RUM ping#167
Conversation
Aligns telemetry / public-facing identifiers with the actual product name. Verified against the Langfuse instance: new spans land with service.name=proto-cli on scope=proto.openai-pipeline; existing proto.* tracers (proto.llm, proto.turn, proto.tools, proto.harness, etc.) were already correct. Changes: - SERVICE_NAME: qwen-code → proto-cli (resource attribute, the marquee label in Langfuse's service column) - All EVENT_* constants: qwen-code.* → proto.* (matches the existing proto.harness.* convention already in this file) - pipeline.ts tracer: qwen-code.openai-pipeline → proto.openai-pipeline (one straggler vs. the 9 other proto.* tracers in core/) - types.ts event.name literals (PromptSuggestion, Speculation): qwen-code.* → proto.* - acpAgent.ts agentInfo.name: qwen-code → proto-cli (visible to ACP clients like Zed when listing agents) - marketplace.ts User-Agent: qwen-code → proto-cli (extension fetch identifier sent to api.github.com / raw.githubusercontent.com) Out of scope (deliberately): - packages/core/src/telemetry/qwen-logger/* — separate analytics ping to gb4w8c3ygj-default-sea.rum.aliyuncs.com (Alibaba RUM, the upstream Qwen team's endpoint). Should be disabled rather than rebranded; tracking separately. - DEFAULT_SERVICE_NAME='qwen-code-oauth' in mcp/token-storage — renaming would orphan existing keychain entries. - Misc qwen-code-* file paths, tmp dir names, sandbox image tag, test fixtures — not telemetry / not user-visible labels. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
WalkthroughRebranding and telemetry overhaul: identifier strings changed from Changes
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Review rate limit: 1/5 review remaining, refill in 45 minutes and 57 seconds. Comment |
Code Coverage Summary
CLI Package - Full Text ReportCore Package - Full Text ReportFor detailed HTML reports, please see the 'coverage-reports-22.x-ubuntu-latest' artifact from the main CI run. |
…ents on Langfuse
The qwen-logger system shipped usage telemetry to a fixed Alibaba RUM
endpoint (gb4w8c3ygj-default-sea.rum.aliyuncs.com) — the upstream Qwen
Code team's analytics pipeline. We don't operate that endpoint, the
data isn't visible to us, and it labelled traffic as qwen-code-cli /
qwen-code@${version}. Confirmed unused on our deployment; nuking.
What's removed:
- packages/core/src/telemetry/qwen-logger/ (entire directory: logger,
event-types, tests)
- packages/core/src/telemetry/integration.test.circular.ts (was a
qwen-logger-specific circular-reference proxy-agent test, no longer
applicable)
- ~30 QwenLogger.getInstance(config)?.logXxxEvent(event) callsites in
loggers.ts
- QwenLogger exports from telemetry/index.ts and core/index.ts
- QwenLogger spies and assertions in config.test.ts and the
describe('logHookCall', ...) block in loggers.test.ts that was
exclusively QwenLogger-shaped
What's kept and rerouted to OTel/Langfuse:
- HookCallEvent type and the logHookCall function — hook execution
data is genuinely useful telemetry (which hook fired, success,
duration, exit code, captured stdout/stderr, error). Now emits a
proto.hook_call OTel log record via logs.getLogger(SERVICE_NAME)
instead of the Alibaba ping. Existing call site in
hookEventHandler.ts:619 still fires per hook execution.
- LoopDetectionDisabledEvent likewise: was an empty no-op after the
qwen-logger pull; rerouted to a proto.loop_detection_disabled OTel
log record so the signal still reaches Langfuse.
- New tests in loggers.test.ts assert OTel emission shape for
logHookCall (success, error, sdk-not-initialized branches).
Renamed (per "all not used" — no existing keychain entries to
invalidate):
- DEFAULT_SERVICE_NAME 'qwen-code-oauth' → 'proto-cli-oauth'
- FORCE_ENCRYPTED_FILE_ENV_VAR 'QWEN_CODE_…' → 'PROTO_CLI_…'
- file-token-storage encryption salt prefix and scrypt key seed
switched to proto-cli; only invalidates non-existent tokens
Verified live: kimi-k2.6 turn through the rebuilt CLI lands a Langfuse
trace with service=proto-cli, scope=proto.openai-pipeline,
gen_ai.response.thinking present. No outbound traffic to aliyuncs.com.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 4
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@packages/core/src/mcp/token-storage/file-token-storage.ts`:
- Around line 26-27: The change to the scrypt password/salt broke existing AES
keys so decrypt() will fail for legacy token files; implement a fallback
read/migration: in the file-token-storage module (where the key is derived and
decrypt() is invoked, e.g., the derive/crypto.scryptSync usage and
decryptToken/decrypt functions), first attempt decryption with the new key, and
if that fails with a bad padding/invalid auth tag error, attempt derivation with
the previous password and salt values and retry decryption; if the legacy key
succeeds, re-encrypt and overwrite the token file with the new key (so future
reads use the new derivation) and return the token, otherwise surface the
existing "Token file corrupted" error. Ensure you reference the same
key-derivation call sites and decrypt() path for the fallback and migration
save.
In `@packages/core/src/mcp/token-storage/index.ts`:
- Around line 12-14: DEFAULT_SERVICE_NAME was changed to 'proto-cli-oauth' and
the new env var FORCE_ENCRYPTED_FILE_ENV_VAR was added, but old credentials and
the legacy env var (QWEN_CODE_FORCE_FILE_STORAGE) are still in use; restore
compatibility by adding a legacy fallback: keep the old service identifier as a
fallback when reading/storing credentials (use DEFAULT_SERVICE_NAME but if no
creds found, try the legacy name), and update the hybrid-token-storage logic
(the code referencing QWEN_CODE_FORCE_FILE_STORAGE) to accept either env var
(check FORCE_ENCRYPTED_FILE_ENV_VAR first, then QWEN_CODE_FORCE_FILE_STORAGE) so
the old knob is honored until the rename is fully rolled out.
In `@packages/core/src/telemetry/constants.ts`:
- Around line 9-12: Replace hardcoded event name literals in
packages/core/src/telemetry/types.ts with the exported constants from
packages/core/src/telemetry/constants.ts (e.g., use EVENT_USER_PROMPT,
EVENT_USER_RETRY, EVENT_TOOL_CALL, EVENT_API_REQUEST and any arena-related
constant equivalents) so classes that currently set event.name = 'user_prompt' /
'tool_call' / 'api_request' / 'arena_session_started' / 'arena_agent_completed'
/ 'arena_session_ended' instead import and use the corresponding constants;
update import statements at the top of types.ts and assign the constants (not
raw strings) in the relevant event classes and factory functions to ensure all
forwarded events carry the new proto.* namespace consistently.
In `@packages/core/src/telemetry/loggers.ts`:
- Around line 789-814: The telemetry code currently includes raw hook payloads
(hook_input, hook_output, stdout, stderr, and error) in the attributes object;
change this so raw payloads are not sent by default by gating them behind an
explicit opt-in flag (e.g., config.telemetry.includeHookPayloads) or by
replacing them with redacted/truncated metadata. Update the block that sets
attributes (the attributes: LogAttributes creation and subsequent ifs for
event.hook_output, event.stdout, event.stderr, event.error) to only add full
payloads when config.telemetry.includeHookPayloads is true; otherwise add safe
redacted placeholders or use a truncate/redact helper (reusable function)
applied to safeJsonStringify outputs and error messages. Ensure hook_input still
uses the redaction/truncation policy and preserve existing fields like
'event.name' and duration_ms unchanged.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 7fbe3039-5950-4bc9-897a-ff0ae2639f62
📒 Files selected for processing (15)
packages/core/src/config/config.test.tspackages/core/src/core/client.test.tspackages/core/src/hooks/hookEventHandler.tspackages/core/src/index.tspackages/core/src/mcp/token-storage/file-token-storage.tspackages/core/src/mcp/token-storage/index.tspackages/core/src/telemetry/constants.tspackages/core/src/telemetry/index.tspackages/core/src/telemetry/integration.test.circular.tspackages/core/src/telemetry/loggers.test.tspackages/core/src/telemetry/loggers.tspackages/core/src/telemetry/qwen-logger/event-types.tspackages/core/src/telemetry/qwen-logger/qwen-logger.test.tspackages/core/src/telemetry/qwen-logger/qwen-logger.tspackages/core/src/telemetry/types.ts
💤 Files with no reviewable changes (9)
- packages/core/src/core/client.test.ts
- packages/core/src/hooks/hookEventHandler.ts
- packages/core/src/telemetry/index.ts
- packages/core/src/index.ts
- packages/core/src/config/config.test.ts
- packages/core/src/telemetry/integration.test.circular.ts
- packages/core/src/telemetry/qwen-logger/event-types.ts
- packages/core/src/telemetry/qwen-logger/qwen-logger.test.ts
- packages/core/src/telemetry/qwen-logger/qwen-logger.ts
🚧 Files skipped from review as they are similar to previous changes (1)
- packages/core/src/telemetry/types.ts
| const salt = `${os.hostname()}-${os.userInfo().username}-proto-cli`; | ||
| return crypto.scryptSync('proto-cli-oauth', salt, 32); |
There was a problem hiding this comment.
Preserve a legacy decryption path for existing file tokens.
Changing both the scrypt password and salt changes the AES key, but the token file path stays ~/.qwen/mcp-oauth-tokens-v2.json. Existing encrypted files will now fail decrypt() and surface as Token file corrupted until users reauthenticate, so this needs a fallback or an on-read migration strategy.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@packages/core/src/mcp/token-storage/file-token-storage.ts` around lines 26 -
27, The change to the scrypt password/salt broke existing AES keys so decrypt()
will fail for legacy token files; implement a fallback read/migration: in the
file-token-storage module (where the key is derived and decrypt() is invoked,
e.g., the derive/crypto.scryptSync usage and decryptToken/decrypt functions),
first attempt decryption with the new key, and if that fails with a bad
padding/invalid auth tag error, attempt derivation with the previous password
and salt values and retry decryption; if the legacy key succeeds, re-encrypt and
overwrite the token file with the new key (so future reads use the new
derivation) and return the token, otherwise surface the existing "Token file
corrupted" error. Ensure you reference the same key-derivation call sites and
decrypt() path for the fallback and migration save.
| export const DEFAULT_SERVICE_NAME = 'proto-cli-oauth'; | ||
| export const FORCE_ENCRYPTED_FILE_ENV_VAR = | ||
| 'QWEN_CODE_FORCE_ENCRYPTED_FILE_STORAGE'; | ||
| 'PROTO_CLI_FORCE_ENCRYPTED_FILE_STORAGE'; |
There was a problem hiding this comment.
This token-storage rename still breaks existing installs.
DEFAULT_SERVICE_NAME = 'proto-cli-oauth' will strand credentials stored under the old service identifier, and packages/core/src/mcp/token-storage/hybrid-token-storage.ts:12-24 still reads QWEN_CODE_FORCE_FILE_STORAGE, so the new PROTO_CLI_FORCE_ENCRYPTED_FILE_STORAGE knob is ignored there. Please keep a legacy alias/fallback before flipping the default.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@packages/core/src/mcp/token-storage/index.ts` around lines 12 - 14,
DEFAULT_SERVICE_NAME was changed to 'proto-cli-oauth' and the new env var
FORCE_ENCRYPTED_FILE_ENV_VAR was added, but old credentials and the legacy env
var (QWEN_CODE_FORCE_FILE_STORAGE) are still in use; restore compatibility by
adding a legacy fallback: keep the old service identifier as a fallback when
reading/storing credentials (use DEFAULT_SERVICE_NAME but if no creds found, try
the legacy name), and update the hybrid-token-storage logic (the code
referencing QWEN_CODE_FORCE_FILE_STORAGE) to accept either env var (check
FORCE_ENCRYPTED_FILE_ENV_VAR first, then QWEN_CODE_FORCE_FILE_STORAGE) so the
old knob is honored until the rename is fully rolled out.
| export const EVENT_USER_PROMPT = 'proto.user_prompt'; | ||
| export const EVENT_USER_RETRY = 'proto.user_retry'; | ||
| export const EVENT_TOOL_CALL = 'proto.tool_call'; | ||
| export const EVENT_API_REQUEST = 'proto.api_request'; |
There was a problem hiding this comment.
Finish the proto.* rename in types.ts too.
These constants now define the new namespace, but several event classes in packages/core/src/telemetry/types.ts still hardcode stale names ('user_prompt', 'tool_call', 'api_request', 'arena_session_started', 'arena_agent_completed', 'arena_session_ended'). Any path that forwards the event instance before loggers.ts overwrites event.name will still emit the old identifiers, so the telemetry rebrand is only partial. Prefer importing these constants there instead of duplicating string literals.
Also applies to: 47-49
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@packages/core/src/telemetry/constants.ts` around lines 9 - 12, Replace
hardcoded event name literals in packages/core/src/telemetry/types.ts with the
exported constants from packages/core/src/telemetry/constants.ts (e.g., use
EVENT_USER_PROMPT, EVENT_USER_RETRY, EVENT_TOOL_CALL, EVENT_API_REQUEST and any
arena-related constant equivalents) so classes that currently set event.name =
'user_prompt' / 'tool_call' / 'api_request' / 'arena_session_started' /
'arena_agent_completed' / 'arena_session_ended' instead import and use the
corresponding constants; update import statements at the top of types.ts and
assign the constants (not raw strings) in the relevant event classes and factory
functions to ensure all forwarded events carry the new proto.* namespace
consistently.
| const attributes: LogAttributes = { | ||
| ...getCommonAttributes(config), | ||
| 'event.name': EVENT_HOOK_CALL, | ||
| 'event.timestamp': event['event.timestamp'], | ||
| hook_event_name: event.hook_event_name, | ||
| hook_type: event.hook_type, | ||
| hook_name: event.hook_name, | ||
| hook_input: safeJsonStringify(event.hook_input, 2), | ||
| duration_ms: event.duration_ms, | ||
| success: event.success, | ||
| }; | ||
| if (event.hook_output !== undefined) { | ||
| attributes['hook_output'] = safeJsonStringify(event.hook_output, 2); | ||
| } | ||
| if (event.exit_code !== undefined) { | ||
| attributes['exit_code'] = event.exit_code; | ||
| } | ||
| if (event.stdout !== undefined) { | ||
| attributes['stdout'] = event.stdout; | ||
| } | ||
| if (event.stderr !== undefined) { | ||
| attributes['stderr'] = event.stderr; | ||
| } | ||
| if (event.error !== undefined) { | ||
| attributes['error.message'] = event.error; | ||
| } |
There was a problem hiding this comment.
Don’t ship raw hook payloads to telemetry by default.
hook_input, hook_output, stdout, and stderr can easily contain prompts, secrets, or file contents, and this change now forwards all of them into OTel/Langfuse. Please gate these fields behind an explicit opt-in or emit only redacted/truncated metadata.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@packages/core/src/telemetry/loggers.ts` around lines 789 - 814, The telemetry
code currently includes raw hook payloads (hook_input, hook_output, stdout,
stderr, and error) in the attributes object; change this so raw payloads are not
sent by default by gating them behind an explicit opt-in flag (e.g.,
config.telemetry.includeHookPayloads) or by replacing them with
redacted/truncated metadata. Update the block that sets attributes (the
attributes: LogAttributes creation and subsequent ifs for event.hook_output,
event.stdout, event.stderr, event.error) to only add full payloads when
config.telemetry.includeHookPayloads is true; otherwise add safe redacted
placeholders or use a truncate/redact helper (reusable function) applied to
safeJsonStringify outputs and error messages. Ensure hook_input still uses the
redaction/truncation policy and preserve existing fields like 'event.name' and
duration_ms unchanged.
…r nuke) — bumps to v0.28.0 (#169) * fix(core): preserve tool history when building no-tools requests /recap (and any other caller without tools, e.g. /btw) was sending an empty conversation to the model. The no-tools branch in pipeline buildRequest dropped every assistant turn with tool_calls and every tool-role message wholesale, so in tool-heavy sessions the recap saw only bare user prompts and hallucinated context. - generateRecap now passes tools: [] so the strip path doesn't fire, matching cc-2.18's awaySummary pattern. - pipeline.ts no-tools branch now flattens instead of dropping: keeps assistant prose content and removes only the tool_calls field; tool results become [tool result] assistant notes truncated at 2000 chars. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(ci): release.yml now fires on auto-release/v* PRs (#160) auto-release.yml opens version-bump PRs from `auto-release/v*` branches into main, but release.yml's job gate only matched `head.ref == 'dev'`. Result: every auto-release PR was merging cleanly but skipping publish (v0.26.25 had to be dispatched manually). This adds the auto-release/* prefix to the gate and refreshes the stale top-of-file comment. Co-authored-by: Automaker <automaker@localhost> Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * chore: release v0.26.26 (#161) Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> * feat(telemetry,ui): reasoning span attribute + collapsed thought summary (Phase 1 of #162) (#165) * feat(core): preserve task plan state in compaction summaries (#163) * feat(core): preserve task plan state in compaction summaries When context compaction fires, the agent loses awareness of its task plan (completed, in-progress, pending work) and may re-plan already-done tasks. Add extractTaskPlanSummary() that queries the TaskStore and produces a structured <task-plan> XML section with status markers ([x], [~], [ ], [-], [!]), priority labels, and parent-child indentation. Extend compactMessages() to accept an optional taskStore and append the plan to the compaction summary. Wire the TaskStore into agent-core at the compaction call site. Backward compatible: existing callers without taskStore remain unaffected. Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * fix: add error handling and recursive nesting to compaction task plan Address PR feedback from CodeRabbit: - Wrap extractTaskPlanSummary call in try/catch so TaskStore failures don't break compaction - Replace flat 2-level subtask rendering with recursive renderTask() that supports arbitrary nesting depth - Add tests for multi-level nesting and error fallback Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> --------- Co-authored-by: Automaker <automaker@localhost> Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * feat(telemetry,ui): capture reasoning on Langfuse span and collapse thoughts post-stream Phase 1 of the reasoning coordination tracked in #162. Captures delta.reasoning_content / delta.reasoning across stream chunks and surfaces it as gen_ai.response.thinking on the gen_ai chat span (gated on logPrompts, matching the completion event policy). Always emits gen_ai.usage.thinking_tokens when usage exposes it. Non-streaming responses get the same treatment by inspecting {thought:true} parts on the response — and the completion event no longer double-counts thoughts as content. Renders gemini_thought items as a compact "▸ thinking (N chars)" summary once the stream finalizes (live streaming render unchanged). Full text remains in ChatRecord, ACP agent_thought_chunk notifications, and Langfuse for downstream investigation. An in-TUI expand affordance is a follow-up. Once homelab-iac#31 (EMIT_REASONING_CONTENT) flips on, this also covers vLLM-served models that previously lost their <think> blocks at the gateway. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Automaker <automaker@localhost> Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * chore: release v0.26.27 (#166) Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> * chore(telemetry): rebrand to proto-cli, nuke qwen-logger Alibaba RUM ping (#167) * chore(telemetry): rebrand qwen-code identifiers to proto-cli Aligns telemetry / public-facing identifiers with the actual product name. Verified against the Langfuse instance: new spans land with service.name=proto-cli on scope=proto.openai-pipeline; existing proto.* tracers (proto.llm, proto.turn, proto.tools, proto.harness, etc.) were already correct. Changes: - SERVICE_NAME: qwen-code → proto-cli (resource attribute, the marquee label in Langfuse's service column) - All EVENT_* constants: qwen-code.* → proto.* (matches the existing proto.harness.* convention already in this file) - pipeline.ts tracer: qwen-code.openai-pipeline → proto.openai-pipeline (one straggler vs. the 9 other proto.* tracers in core/) - types.ts event.name literals (PromptSuggestion, Speculation): qwen-code.* → proto.* - acpAgent.ts agentInfo.name: qwen-code → proto-cli (visible to ACP clients like Zed when listing agents) - marketplace.ts User-Agent: qwen-code → proto-cli (extension fetch identifier sent to api.github.com / raw.githubusercontent.com) Out of scope (deliberately): - packages/core/src/telemetry/qwen-logger/* — separate analytics ping to gb4w8c3ygj-default-sea.rum.aliyuncs.com (Alibaba RUM, the upstream Qwen team's endpoint). Should be disabled rather than rebranded; tracking separately. - DEFAULT_SERVICE_NAME='qwen-code-oauth' in mcp/token-storage — renaming would orphan existing keychain entries. - Misc qwen-code-* file paths, tmp dir names, sandbox image tag, test fixtures — not telemetry / not user-visible labels. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * chore(telemetry): remove qwen-logger Alibaba RUM ping; keep useful events on Langfuse The qwen-logger system shipped usage telemetry to a fixed Alibaba RUM endpoint (gb4w8c3ygj-default-sea.rum.aliyuncs.com) — the upstream Qwen Code team's analytics pipeline. We don't operate that endpoint, the data isn't visible to us, and it labelled traffic as qwen-code-cli / qwen-code@${version}. Confirmed unused on our deployment; nuking. What's removed: - packages/core/src/telemetry/qwen-logger/ (entire directory: logger, event-types, tests) - packages/core/src/telemetry/integration.test.circular.ts (was a qwen-logger-specific circular-reference proxy-agent test, no longer applicable) - ~30 QwenLogger.getInstance(config)?.logXxxEvent(event) callsites in loggers.ts - QwenLogger exports from telemetry/index.ts and core/index.ts - QwenLogger spies and assertions in config.test.ts and the describe('logHookCall', ...) block in loggers.test.ts that was exclusively QwenLogger-shaped What's kept and rerouted to OTel/Langfuse: - HookCallEvent type and the logHookCall function — hook execution data is genuinely useful telemetry (which hook fired, success, duration, exit code, captured stdout/stderr, error). Now emits a proto.hook_call OTel log record via logs.getLogger(SERVICE_NAME) instead of the Alibaba ping. Existing call site in hookEventHandler.ts:619 still fires per hook execution. - LoopDetectionDisabledEvent likewise: was an empty no-op after the qwen-logger pull; rerouted to a proto.loop_detection_disabled OTel log record so the signal still reaches Langfuse. - New tests in loggers.test.ts assert OTel emission shape for logHookCall (success, error, sdk-not-initialized branches). Renamed (per "all not used" — no existing keychain entries to invalidate): - DEFAULT_SERVICE_NAME 'qwen-code-oauth' → 'proto-cli-oauth' - FORCE_ENCRYPTED_FILE_ENV_VAR 'QWEN_CODE_…' → 'PROTO_CLI_…' - file-token-storage encryption salt prefix and scrypt key seed switched to proto-cli; only invalidates non-existent tokens Verified live: kimi-k2.6 turn through the rebuilt CLI lands a Langfuse trace with service=proto-cli, scope=proto.openai-pipeline, gen_ai.response.thinking present. No outbound traffic to aliyuncs.com. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Automaker <automaker@localhost> Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * chore: release v0.26.28 (#168) Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --------- Co-authored-by: Automaker <automaker@localhost> Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
Summary
Aligns telemetry identifiers with the actual product, and removes the upstream Qwen Code team's analytics ping that was sending our usage data to Alibaba RUM (
gb4w8c3ygj-default-sea.rum.aliyuncs.com).Three concerns in one PR (related, all about cleaning up Qwen-fork legacy in telemetry)
1. Rebrand identifiers
SERVICE_NAME(Langfuse service column)qwen-codeproto-cliEVENT_*constants intelemetry/constants.tsqwen-code.*(~30)proto.*(matches existingproto.harness.*convention in same file)pipeline.tstracer scopeqwen-code.openai-pipelineproto.openai-pipeline(matches the 9 otherproto.*tracers in core/)types.tsevent.name literalsqwen-code.*proto.*acpAgent.tsagentInfo.nameqwen-codeproto-cli(Zed-visible)marketplace.tsHTTPUser-Agentqwen-codeproto-cli2. Nuke qwen-logger
The
qwen-loggersystem shipped usage telemetry to a fixed Alibaba RUM endpoint — the upstream Qwen Code team's analytics pipeline. We don't operate that endpoint, the data isn't visible to us, and traffic was labelledqwen-code-cli/qwen-code@${version}. Confirmed unused on our deployment.Removed:
packages/core/src/telemetry/qwen-logger/(entire directory),integration.test.circular.ts(qwen-logger-specific), ~30QwenLogger.getInstance(config)?.logXxxEvent(event)callsites inloggers.ts, exports fromtelemetry/index.tsandcore/index.ts, related test scaffolding.Kept and rerouted to OTel/Langfuse (genuinely useful telemetry, just don't want it on Alibaba):
HookCallEvent+logHookCall— emitsproto.hook_callOTel log records (which hook fired, success, duration, exit code, captured stdout/stderr, error). Existing call site inhookEventHandler.tsstill fires per hook execution.LoopDetectionDisabledEvent+logLoopDetectionDisabled— emitsproto.loop_detection_disabledOTel log record. Was a no-op shell after the qwen-logger pull; now lands in Langfuse.New tests in
loggers.test.tsassert OTel emission shape forlogHookCall(success / error / sdk-not-initialized branches).3. Rename qwen-code-oauth identifiers
Per "all not used" — no existing keychain entries to invalidate:
DEFAULT_SERVICE_NAME'qwen-code-oauth'→'proto-cli-oauth'FORCE_ENCRYPTED_FILE_ENV_VAR'QWEN_CODE_…'→'PROTO_CLI_…'file-token-storage.tsAES key salt prefix and scrypt seed switched toproto-cli. Only invalidates non-existent tokens.Verified live
Two
kimi-k2.6turns through the rebuilt CLI immediately after each commit. Both lifecycles confirmed in Langfuse:gen_ai.response.thinking(Phase 1 of #162) still lands correctly under the new scope. No outbound traffic toaliyuncs.com.Out of scope (deliberately)
~/.qwen/config directory hard-coded for OAuth token storage — separate migration concern.qwen-code-mcp-clientMCP client identifier (different system).ghcr.io/qwenlm/qwen-code:0.26.27— published under upstream Qwen org.qwen-code-tool-modify-diffs, etc.) — not user-visible.Test plan
npm run typecheckcleannpm run lintcleanpackages/coretest suite: 5310 pass (was 5352 before; difference is removed qwen-logger tests and the deleted circular-ref integration test) / 2 skippackages/clitest suite: 3774 pass / 7 skipkimi-k2.6turn → answer rendered, Langfuse trace showsservice=proto-cli,scope=proto.openai-pipeline,gen_ai.response.thinkingsetqwen-codetraces unchanged (no destructive migration)🤖 Generated with Claude Code
Summary by CodeRabbit
Chores
New Features
Tests