fix(cli): prevent silent VP-mode crash by adding uncaughtException handler and error visibility - #8085
fix(cli): prevent silent VP-mode crash by adding uncaughtException handler and error visibility#8085chiga0 wants to merge 267 commits into
Conversation
…d settings persistence
…nto feat/add-verbose-mode-switcher
Title: feat: dataworks tips Link: https://code.alibaba-inc.com/alishu/qwen-code/codereview/26668570
Title: feat: dataworks tips Link: https://code.alibaba-inc.com/alishu/qwen-code/codereview/26668680
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add beta version notice to Tips component - Internationalize beta notice across all 6 locales (en/zh/ja/de/ru/pt) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…nto feat/fold-all-tool-output
Title: refactor: compact tool group display Link: https://code.alibaba-inc.com/alishu/qwen-code/codereview/26669574
Link: https://code.alibaba-inc.com/alishu/qwen-code/codereview/26675235 * refactor: update tips message
## 问题 NPM Publish CI run [QwenLM#174](https://code.alibaba-inc.com/alishu/qwen-code/ci/jobs?pipelineId=132250&pipelineRunId=44196709&createType=yaml) 在 `npm ci` 步骤失败: ``` npm error `npm ci` can only install packages when your package.json and package-lock.json are in sync. npm error Missing: @alife/dataworks-qwen-code-acp-bridge@0.17.0 from lock file ``` ## 根因 上一个 MR [!129](https://code.alibaba-inc.com/alishu/qwen-code/codereview/27745054) 把 `packages/acp-bridge/package.json` 的 name 从 `@qwen-code/acp-bridge` 改成 `@alife/dataworks-qwen-code-acp-bridge`,但漏了重新生成 `package-lock.json`,导致 lockfile 里仍只有旧名字 `@qwen-code/acp-bridge` 的 link 条目,`npm ci` 严格校验直接报错。 正常 sync 流程里 `.aoneci/upstream-sync-merge.yml` Step 2.5 会自动跑 `npm install --package-lock-only --ignore-scripts`,但 !129 是手动改 manifest,不走 sync 流程,所以漏了这一步。 ## 修复 ```bash npm install --package-lock-only --ignore-scripts ``` 只在 `package-lock.json` 里追加了 `node_modules/@alife/dataworks-qwen-code-acp-bridge` 的 link 条目,并把 `packages/acp-bridge.name` 字段同步成新名(5 行 diff)。 ## 验证 本地 `npm ci --ignore-scripts` exit 0,且产出 `node_modules/@alife/dataworks-qwen-code-acp-bridge` 软链。 ## Test plan - [ ] CI 上重新触发 NPM Publish pipeline,确认 `npm ci` 通过 - [ ] 后续 step(build / test / publish)正常进行 Link: https://code.alibaba-inc.com/alishu/qwen-code/codereview/27752512 * fix(release): sync package-lock.json with renamed acp-bridge package CI run #44196709 failed with: npm error `npm ci` can only install packages when your package.json and package-lock.json are in sync. npm error Missing: @alife/dataworks-qwen-code-acp-bridge@0.17.0 from lock file Previous MR (!129) renamed packages/acp-bridge/package.json from @qwen-code/acp-bridge to @alife/dataworks-qwen-code-acp-bridge but did not regenerate package-lock.json, so CI's npm ci hard-fails. This commit runs `npm install --package-lock-only --ignore-scripts` to add the new name's link entry. Verified: `npm ci --ignore-scripts` now succeeds.
## 问题 NPM Publish 报错: ``` 403 Forbidden - PUT https://registry.anpm.alibaba-inc.com/@qwen-code%2fsdk "buc:jinjing.zzj" not authorized to modify @qwen-code/sdk ``` ## 原因 `packages/sdk-typescript` 是 upstream 最近新增的包(`@qwen-code/sdk`),但 fork 的 `.fork/manifest.json` 没有这个映射,`rewrite-package-identity.js` 跳过了它,发布时尝试推到 `@qwen-code/sdk` 被 anpm 权限拦截。 ## 修复 - `.fork/manifest.json`: 新增映射 `packages/sdk-typescript/package.json → @alife/dataworks-qwen-code-sdk` - `packages/sdk-typescript/package.json`: 包名改为 `@alife/dataworks-qwen-code-sdk` + 加 `publishConfig.registry`(由 rewrite 脚本生成) ## 顺手检查的其他遗漏 跑了一遍 audit,所有非 private workspace 包的 `name` 字段都已正确改为 fork 名(manifest 已覆盖): - ✅ acp-bridge, cli, core, sdk, web-templates, webui, channels/* 全部 OK - ✅ vscode-ide-companion 保持 `qwen-code-vscode-ide-companion`(不在 @qwen-code scope,anpm 不拦) ## 一个独立的潜在问题(不在本 MR 范围) 15 个 workspace 内部 dep 引用还指向 `@qwen-code/*`,例如: ```json // packages/cli/package.json "@qwen-code/qwen-code-core": "file:../core", "@qwen-code/acp-bridge": "file:../acp-bridge", ``` - 本地构建没问题(`file:` 协议靠 dep-key 走 symlink,和目标 package 的 `name` 字段无关) - npm publish 本身不会失败 - 但下游用户从 anpm 安装 fork 包时,npm 会尝试解析这些 dep-key,去 anpm 找 `@qwen-code/qwen-code-core`,**找不到会失败** - 需要单独写一个 dep-key rewrite 脚本,或者更新源码 import + dep key 历史上 fork 一直能发布说明这个问题之前要么没暴露,要么有别的兜底(比如 cli 单文件打包时清空了 dependencies)。建议后续单独排查。 Link: https://code.alibaba-inc.com/alishu/qwen-code/codereview/27757910 * fix(publish): add sdk-typescript to identity rewrite mappings @qwen-code/sdk is a new upstream package. Without an entry in manifest.json.packageIdentity.mappings, rewrite-package-identity.js leaves it under the @qwen-code scope and npm publish hits a 403 on the anpm registry (no permission to publish under @qwen-code). Note: 15 cross-workspace dependency keys still reference @qwen-code/* (e.g. cli depends on "@qwen-code/qwen-code-core": "file:../core"). Local builds work because file: links resolve by dep-key, not by the target package's name field. Downstream installs from anpm will fail to resolve these, but that's a separate problem from this publish failure and needs a dedicated dep-key rewrite pass. * fix: sync package-lock.json after sdk rename * fix(publish): expand glob workspaces when bumping versions The auto-version loop was iterating workspaces with literal path.join, so "packages/*" produced a non-existent path and got skipped — only the explicitly-listed channels got their version bumped. cli, core, sdk, acp-bridge, web-templates, webui kept the raw 0.17.0 and collided with previously-published versions on anpm (E403 "Can't modify pre-existing version"). Add expandWorkspacePaths() that walks glob entries the way npm does, then drive both the bump loop and the post-publish report off it. * fix(test): bump anthropic claude-cli identity test timeout to 30s (CI slow) * fix(publish): rename sdk to @alife/dataworks-qwen-code-sdk-typescript @alife/dataworks-qwen-code-sdk was already taken on anpm (owner: gary.gq). Switch to a fork-name that matches the source directory and is still free. * fix(publish): mark vscode-ide-companion as private This is a VSCode extension (publisher: qwenlm) — it ships through the VSCode marketplace, not anpm. The name qwen-code-vscode-ide-companion is already owned on anpm by another team (npm:usgupta), and publishing there hits E403 every release. Setting private: true makes publish-packages.js skip it without touching the existing anpm record. * fix(publish): restore private:true on sdk-typescript Both sdk-typescript and vscode-ide-companion were private:true on the fork's main before the upstream sync. The sync replaced their package.json with upstream's version which lacks the private field. This is the root cause of the publish 403 errors — these packages were never meant to be published to anpm. * fix(ci): produce both tarball naming formats for backward compat Downstream consumers depend on the old format: qwen-code-{version}-linux-amd64.tar.gz Upstream switched to: qwen-code-standalone-{version}.tar.gz Build both: build-standalone-ci.sh copies the tarball to the old name, prepare-artifact.sh carries both into the artifact dir, and upload-oss.sh uploads both to OSS so existing download URLs keep working. * fix(test): extend waitFor timeout for paste mode test (CI slow) * fix(ci): add --testTimeout=30000 to Aone CI test runs Aone CI limits threads to 1-4 (vs config's 8-16) but kept the default 5s testTimeout. Timing-sensitive waitFor assertions fail intermittently under the reduced concurrency. Align testTimeout with hookTimeout at 30s. * fix(ci): raise vitest thread pool to 4-16 (machine has 32 cores) * revert(ci): remove thread/timeout overrides, use vitest config defaults * feat(ci): add release rollback pipeline Manual-trigger pipeline for rolling back a bad release: 1. Repoints OSS channel metadata.json (beta/dataworks/latest) to an older version's metadata.json 2. Optionally runs npm deprecate on all non-private workspace packages for the bad version Both steps support dry-run mode (default on). Example usage: rollback beta channel to 0.15.11-dataworks.2 and deprecate 0.17.0-beta.3. * revert(test): remove unnecessary timeout overrides from test files These timeout bumps were added to work around one-off CI flakes, not real test-duration issues. Both tests pass reliably without them. * refactor(publish): align with upstream — publish CLI from dist/ and channel-base only Upstream release.yml publishes exactly two npm packages: 1. CLI bundle from dist/ (after prepare:package) 2. @qwen-code/channel-base from packages/channels/base The fork was using `npm publish --workspaces` which publishes ALL non-private workspace packages — causing 403 errors when sdk-typescript and vscode-ide-companion (published via separate pipelines upstream) got swept up. Replace the blanket --workspaces publish with explicit per-package publishes matching upstream. This eliminates the need for workarounds (private:true, fork-renaming) on packages the fork doesn't publish. Reverts: sdk-typescript/vscode-ide-companion package.json changes, manifest.json sdk-typescript mapping, and related lockfile changes. * fix: sync package-lock.json with sdk-typescript fork name npm ci failed because package-lock.json still referenced the upstream name @qwen-code/sdk while the workspace package.json (rewritten by rewrite-package-identity.js) uses @alife/dataworks-qwen-code-sdk. Run npm install --package-lock-only to bring them in sync. * fix: restore sdk-typescript to upstream package name sdk-typescript is not published by the fork's npm pipeline (it has its own release pipeline upstream), so its package.json should keep the upstream name @qwen-code/sdk — not the fork-rewritten name.
The 2026-06-03 sync replaced several fork customizations with upstream
versions. This commit restores them from main:
1. packages/core/src/mcp/constants.ts + oauth-provider.ts
— getOAuthRedirectUri() with BFF_ENDPOINT/dsw_baseUrl proxy logic
(patch 0004 exists but did not apply during sync)
2. .aoneci/release-rollback.yml
— fork-only rollback pipeline (added to main after sync ran)
3. .aoneci/scripts/build-standalone-ci.sh, prepare-artifact.sh, upload-oss.sh
— compat tarball format for downstream consumers
4. scripts/publish-packages.js
— targeted publish (CLI bundle + channel-base only) instead of
blanket --workspaces
Root cause: sync/upstream-20260603 was missing patches 0002-0011 (including DSW OAuth redirect patch 0004) due to three bugs: 1. Fork-only file restoration ran BEFORE apply.sh, causing patch 0001's "new file" entry (ConfigInitDisplay.tsx) to hit "already exists in working directory" error. 2. apply.sh ran without --continue, so the first patch failure aborted all remaining patches. 3. Post-LLM-repair check only counted .rej files, but "already exists" errors don't produce .rej files — pipeline falsely declared success. Fixes: - Exclude patch-touched files from fork-only restoration - Use --continue so individual failures don't block other patches - Replace .rej-only check with full apply.sh --check validation
grep without -h prefixes each match with the source filename when searching multiple files, so the sed extraction produced paths like ".fork/patches/0001.patch:packages/..." instead of "packages/...". comm -23 couldn't match these against git ls-tree output, so no files were actually excluded — 0001 and 0009 still hit "already exists" errors.
Upstream reverted the swarm tool (QwenLM#3468) and removed SWARM from ToolNames/ToolDisplayNames. The fork still keeps swarm.ts as a fork-only file, so the constants must remain for compilation.
workspaceAgents, workspaceMemory, and AuthDialog tests had fork- specific adaptations on main that were overwritten by upstream content during sync. Restore from main.
CI runs as root where chmod 0o500 cannot prevent deletion, causing the test to fail with ENOENT in the finally block. Skip the test on root, and guard chmodSync with existsSync.
- Add --testTimeout=30000 to core test run in npm-publish pipeline (Config sessionEnvClaimed tests use vi.isolateModules which is slow in CI, hitting the default 5s timeout) - Add --testTimeout=30000 to cli test run alongside existing hookTimeout - Restore skill-activation.test.ts fork adaptations from main
DingTalk interactive card streaming is no longer in use. All content in this patch is obsolete: - cancelCurrentPrompt() in ChannelBase: no callers remain - Card streaming in DingtalkAdapter: feature deprecated - markdown.ts convertTables removal: upstream version is correct The sync branch now follows upstream's simplified DingTalk adapter (markdown-only, no card).
Title: chore: upstream sync 2026-06-03 (244 commits) ## Upstream Sync 2026-06-03 ### 概要 - 合并了 **244** 个 upstream 提交 - 源: QwenLM/qwen-code main - Sync 分支: `sync/upstream-20260603` ### 验证 - ⏳ 验证将在 MR 创建后异步执行 ### 🎯 高风险文件(fork patch 触动过且本次 sync 也修改) **reviewer 重点 review 这 89 个文件**(与 `.fork/patches.md` 中 fork 类 commit 触动过的文件交集): - `.gitignore` - `docs-site/package.json` - `docs/users/configuration/settings.md` - `docs/users/reference/keyboard-shortcuts.md` - `esbuild.config.js` - `integration-tests/interactive/context-compress-interactive.test.ts` - `package-lock.json` - `package.json` - `packages/acp-bridge/package.json` - `packages/channels/base/package.json` - `packages/channels/base/src/ChannelBase.ts` - `packages/channels/dingtalk/package.json` - `packages/channels/dingtalk/src/DingtalkAdapter.ts` - `packages/channels/dingtalk/src/markdown.ts` - `packages/channels/feishu/package.json` - `packages/channels/plugin-example/package.json` - `packages/channels/telegram/package.json` - `packages/channels/weixin/package.json` - `packages/cli/package.json` - `packages/cli/src/acp-integration/session/Session.test.ts` - `packages/cli/src/acp-integration/session/Session.ts` - `packages/cli/src/commands/channel/channel-registry.ts` - `packages/cli/src/config/keyBindings.ts` - `packages/cli/src/config/settingsSchema.ts` - `packages/cli/src/gemini.test.tsx` - `packages/cli/src/gemini.tsx` - `packages/cli/src/i18n/locales/de.js` - `packages/cli/src/i18n/locales/en.js` - `packages/cli/src/i18n/locales/fr.js` - `packages/cli/src/i18n/locales/ja.js` - `packages/cli/src/i18n/locales/pt.js` - `packages/cli/src/i18n/locales/ru.js` - `packages/cli/src/i18n/locales/zh.js` - `packages/cli/src/serve/workspaceAgents.test.ts` - `packages/cli/src/serve/workspaceMemory.test.ts` - `packages/cli/src/services/tips/tipRegistry.ts` - `packages/cli/src/ui/AppContainer.tsx` - `packages/cli/src/ui/auth/AuthDialog.test.tsx` - `packages/cli/src/ui/components/Footer.test.tsx` - `packages/cli/src/ui/components/Footer.tsx` - `packages/cli/src/ui/components/InputPrompt.test.tsx` - `packages/cli/src/ui/components/InputPrompt.tsx` - `packages/cli/src/ui/components/MainContent.tsx` - `packages/cli/src/ui/components/ModelDialog.tsx` - `packages/cli/src/ui/components/Tips.test.ts` - `packages/cli/src/ui/components/Tips.tsx` - `packages/cli/src/ui/components/agent-view/AgentComposer.tsx` - `packages/cli/src/ui/components/hooks/HooksManagementDialog.test.tsx` - `packages/cli/src/ui/components/hooks/HooksManagementDialog.tsx` - `packages/cli/src/ui/components/hooks/constants.ts` > 共 89 个文件,仅展示前 50 个;完整清单见 CI artifact 或重跑流水线。 ### Review 要点 请查看每日 Upstream Sync 分析 CI 了解完整差异状态。 Link: https://code.alibaba-inc.com/alishu/qwen-code/codereview/27796570
## 问题 2026-06-03 的 upstream sync 静默丢失了多个 fork patches(0002, 0003, 0005, 0007, 0010, 0011)。 根因: 1. CI sync 流程的 reuse 逻辑只检查 `upstream/main` 是否是 sync 分支的 ancestor,不验证 fork patches 是否已 apply。前一次失败运行 push 了 patch 未打上的分支后,后续重试直接复用了这个不完整的分支。 2. sync 分支合入 main 后没有任何 CI 步骤验证 fork patch 内容完整性。 ## 修复 ### Commit 1: 恢复丢失的 patches 重新 apply 了 6 个丢失的 fork patches: - **0002** branding-tips — DataWorks usage tips - **0003** i18n-dataworks — zh/en DSW 环境翻译 - **0005** osc8-internal — `OPENCODE_TERMINAL` / `BFF_TOKEN` / `TERM=xterm-256color` 检测,修复内部 web terminal 中长链接换行后点击断开的问题 - **0007** feishu-channel — 飞书频道注册 - **0010** build-single-bundle — 单包构建配置 - **0011** test-fork-adaptations — doctorChecks Node v22 版本守卫 ### Commit 2: CI 防护 - **新增 `.fork/verify-patches.sh`** — 直接检查每个 patch 的 added content 是否存在于工作树中(与 `apply.sh --check` 互补:后者检查 patch 能否被 apply,即内容不在;本脚本检查内容是否已在) - **修复 reuse 逻辑** — 复用 sync 分支前先跑 `verify-patches.sh`,不完整则 fall through 到完整重建流程 - **新增 post-sync gate** — 提交 sync 结果后、创建 MR 前验证 patch 内容,失败则标记冲突并发送钉钉告警 ## 测试 - `bash .fork/verify-patches.sh --verbose` 在当前分支上全部 PASS(9/9, 100%) - 模拟回退 0005 patch 后 verify-patches.sh 正确报告 FAIL(37%) Link: https://code.alibaba-inc.com/alishu/qwen-code/codereview/27900189 * fix(fork): restore fork patches lost during upstream sync 2026-06-03 Patches 0002, 0003, 0005, 0007, 0010, 0011 were dropped when the sync/upstream-20260603 branch was built — apply.sh either failed or its results were discarded by the reuse-sync-branch shortcut. Restored: - 0002 branding-tips: DataWorks usage tips in tipRegistry - 0003 i18n-dataworks: zh/en locale strings for DSW environment - 0005 osc8-internal: OPENCODE_TERMINAL / BFF_TOKEN / TERM=xterm detection in supportsHyperlinks() — fixes broken link clicks in internal web terminal - 0007 feishu-channel: Feishu (Lark) channel registration - 0010 build-single-bundle: single-bundle esbuild config - 0011 test-fork-adaptations: Node v22 guard in doctorChecks test * fix(ci): add fork patch content verification to upstream sync pipeline The 2026-06-03 upstream sync silently lost fork patches because: 1. The reuse-sync-branch shortcut skipped patch verification — if a previous run pushed a branch with failed patches, subsequent retries reused it without checking. 2. No post-sync step verified that patch content survived in the final tree. Changes: - Add .fork/verify-patches.sh: checks whether each patch's added content is present in the working tree (complements apply.sh --check which tests the opposite — whether patches CAN be applied). - Fix reuse logic: run verify-patches.sh before reusing a sync branch; fall through to full rebuild if patches are incomplete. - Add post-sync gate: run verify-patches.sh after committing the sync result; block MR creation and alert via DingTalk if patches are lost. * fix(fork): restore 0009 patch — remove WebSearch:None mapping Patch 0009-claude-websearch-compat removed the `WebSearch: 'None'` line from claude-converter.ts to enable WebSearch in Claude compat mode. This deletion was missed in the initial restore because the patch file failed to apply cleanly (already-exists conflict on the test file), and the deletion in claude-converter.ts was overlooked. * fix(fork): align claude-converter.ts blank line with patch 0009 Keep the blank line where `WebSearch: 'None'` was removed, matching the exact output of 0009-claude-websearch-compat.patch.
## 背景 6/10 定时任务 Upstream Sync 失败(pipeline run 45917108),钉钉告警列出 9 个 patch 失败,实际只有 1 个真实冲突。 ## 问题与修复 **1. patch 0001 上下文过期(真实冲突)** 上游 6d083fa (PR QwenLM#4741) 把 AppHeader.test.tsx 的断言从 'gemini-pro' 改为 'Gemini Pro',导致 0001-branding-header.patch 第一个 hunk 的上下文行失配被 reject。 修复:刷新 patch 上下文行。已在 upstream/main (debd874) 的 worktree 上验证 9 个 patch 全部干净 apply(Applied: 9, Failed: 0)。 **2. LLM 修复后的成功判定逻辑 bug** 流水线在 LLM 修复后用 apply.sh --check(正向 dry-run)判定是否成功,但此时多数 patch 已打上,正向 check 必然全部 FAIL——即使 LLM 修好了也会被判失败,且钉钉告警因此把 9 个 patch 全列为冲突(误报)。 修复:apply.sh 新增 --check-applied 模式(git apply --reverse --check 验证已应用状态),流水线的修复后判定和失败列表改用该模式。已实测三种场景(未应用/全应用/部分应用)行为正确,YAML lint 通过。 ## 备注 本次 401(CI_QWEN_API_KEY 过期)已另行更换。 Link: https://code.alibaba-inc.com/alishu/qwen-code/codereview/27956413 * fix(fork): refresh patch 0001 context for upstream model display name change Upstream 6d083fa (PR QwenLM#4741) changed the AppHeader test assertion from 'gemini-pro' to 'Gemini Pro', breaking the context line of patch 0001's first hunk. Verified all 9 patches apply cleanly on upstream/main debd874. * fix(ci): use reverse-apply check to verify patches after LLM repair The post-repair success gate ran 'apply.sh --check' (forward dry-run) on a tree where patches were already applied, so every patch reported FAIL and the LLM repair path could never be marked successful — even with a valid API key. The same forward check also produced the misleading DingTalk alert listing all 9 patches as conflicting when only one actually was. Add 'apply.sh --check-applied' (git apply --reverse --check) to verify the applied state, and use it for both the post-repair gate and the failed- patch list.
## What this PR does Refreshes the fork upstream-sync patch stack so it applies cleanly on the latest upstream main while preserving the DataWorks package-name, Claude WebSearch, and single-bundle build customizations. ## Why it's needed The scheduled upstream sync failed because three fork patches no longer matched upstream's current channel registry, Claude tool mapping, and build configuration shapes. Refreshing the patch contexts lets the sync pipeline replay the fork customizations without manual reject-file repair. ## Reviewer Test Plan ### How to verify Run the upstream sync patch replay against the latest upstream main and confirm all patches report OK or APPLIED with zero failed patches. Confirm the final patch content verification reports PASS for all patches. ### Evidence (Before & After) Before: CI run 47649001 failed during patch replay with 0007-feishu-channel.patch, 0009-claude-websearch-compat.patch, and 0010-build-single-bundle.patch not fully applied. After: On upstream/main 3d6b6f7, .fork/apply.sh --check reported Check complete: 0 failed; full replay reported Applied: 9 Failed: 0; .fork/apply.sh --check-applied reported Check complete: 0 failed; .fork/verify-patches.sh --verbose reported PASS: 9 | WARN: 0 | FAIL: 0 | SKIP: 0. ### Tested on | OS | Status | | :--------: | :----: | | 🍏 macOS | ✅ tested | | 🪟 Windows | N/A | | 🐧 Linux | N/A | ### Environment (optional) Local git worktree using upstream/main 3d6b6f7 and the current fork patch metadata. ## Risk & Scope - Main risk or tradeoff: This changes only patch metadata; the next scheduled sync still needs CI confirmation in the Aone environment. - Not validated / out of scope: Full npm build and full test suite were not run. - Breaking changes / migration notes: None expected. ## Linked Issues N/A <details> <summary>中文说明</summary> ## 这个 PR 做了什么 刷新 fork 的 upstream-sync patch 栈,使其可以干净应用到最新 upstream main,同时保留 DataWorks 包名、Claude WebSearch 兼容和单文件 bundle 构建定制。 ## 为什么需要 定时 upstream sync 失败是因为三个 fork patch 不再匹配 upstream 当前的 channel registry、Claude tool mapping 和构建配置结构。刷新 patch 上下文后,同步流水线可以重新回放 fork 定制,不再需要人工处理 reject 文件。 ## Reviewer Test Plan ### How to verify 基于最新 upstream main 运行 upstream sync patch replay,确认所有 patch 都是 OK 或 APPLIED,且 failed 为 0。确认最终 patch 内容验证全部 PASS。 ### Evidence (Before & After) Before: CI run 47649001 在 patch replay 阶段失败,0007-feishu-channel.patch、0009-claude-websearch-compat.patch 和 0010-build-single-bundle.patch 没有完全应用成功。 After: 在 upstream/main 3d6b6f7 上,.fork/apply.sh --check 输出 Check complete: 0 failed;完整 replay 输出 Applied: 9 Failed: 0;.fork/apply.sh --check-applied 输出 Check complete: 0 failed;.fork/verify-patches.sh --verbose 输出 PASS: 9 | WARN: 0 | FAIL: 0 | SKIP: 0。 ### Tested on | OS | Status | | :--------: | :----: | | 🍏 macOS | ✅ tested | | 🪟 Windows | N/A | | 🐧 Linux | N/A | ### Environment (optional) 使用本地 git worktree,基于 upstream/main 3d6b6f7 和当前 fork patch metadata。 ## Risk & Scope - Main risk or tradeoff: 本次只修改 patch metadata;下一次定时同步仍需要在 Aone CI 环境中确认。 - Not validated / out of scope: 没有运行完整 npm build 和完整测试套件。 - Breaking changes / migration notes: 预期无。 ## Linked Issues N/A </details> Link: https://code.alibaba-inc.com/alishu/qwen-code/codereview/28102374 * fix(ci): refresh upstream sync patches
Link: https://code.alibaba-inc.com/alishu/qwen-code/codereview/28129648 * fix(mcp): 统一 OAuth redirect_uri 拼接并支持 ACS_SANDBOX 代理段 - registerClient/exchangeCodeForToken 改用 getOAuthRedirectUri(),与授权阶段 统一,避免 DSW/BFF 代理环境下 token 交换因 redirect_uri_mismatch 失败 - authenticate() 注册前一次性冻结 config.redirectUri,防止流程中途 env 变化 导致注册/授权/换 token 三处 redirect_uri 发散 - getOAuthRedirectUri(): DA_RUNTIME_TYPE=ACS_SANDBOX 时代理段用 bxkxuth(新版 Data Agent 实例),否则保持 kxuth;BFF_ENDPOINT 去尾斜杠 - 新增 constants.test.ts 及 oauth-provider.test.ts 集成测试,覆盖各分支与 三处 redirect_uri 一致性 - 重生成 patch 0004 纳入测试文件,manifest 补充 paths 与 tests 条目
Link: https://code.alibaba-inc.com/alishu/qwen-code/codereview/28414754 * ci: use zero-trust OSS dual-cloud upload
…ndler and error visibility VP (alternate-screen) mode swallows all error output: uncaught exceptions write their stack trace to stderr which lands on the alternate screen buffer, then gets discarded when teardown switches back to the primary buffer. The user sees a silent exit with no error message and nothing in the debug log. Root cause: no `uncaughtException` handler existed anywhere in the CLI. PR QwenLM#7406's ErrorBoundary and unhandledRejection handler only cover React render errors and promise rejections — synchronous exceptions bypass both. Changes: - Add `setupUncaughtExceptionHandler()` with sync debug-log write, alternate-screen exit before stderr output, and clean process.exit(1) - Port QwenLM#7406's ErrorBoundary (normalizeError, fallback, onError, reset) for the internal repo which hasn't synced upstream yet - Wrap AppWrapper with ErrorBoundary + [FATAL_RENDER_ERROR] logging + 5s auto-exit (matching QwenLM#7406's startInteractiveUI.tsx pattern) - Echo last render error to stderr after unmount leaves the alternate screen (consumeLastRenderError) - Fix Kitty protocol teardown ordering: disableKittyProtocol() now runs after instance.unmount() so the pop lands on the correct screen buffer - Remove SIGTERM/SIGINT handlers from kittyProtocolDetector.ts that raced with the main signal handlers (QwenLM#7779) - Add SIGHUP handler alongside SIGTERM/SIGINT (QwenLM#7781) - Guard ThinkMessage/ThinkMessageContent with per-item ErrorBoundary so partial markdown during thought streaming degrades to plain text
|
Closing — branch was based on internal main, not upstream. Re-opening with a clean branch. |
|
Thanks for the PR, and for the detailed investigation into the silent VP-mode crashes — the crash session analysis ( Template: mostly there, but missing the Problem: real and observed. Users are hitting silent exits during model streaming in VP mode with no error trace — the linked issues and the debug log analysis confirm this. The silence mechanism (stderr → alternate screen → discarded on Direction: aligned. Error visibility for silent crashes is squarely within scope. Approach — this is the big one. This PR carries 250 commits and 1,149 changed files (+237K / −26K lines) from what appears to be an internal DataWorks fork that has diverged substantially from upstream More importantly, upstream
The fork's The genuinely new ideas that upstream doesn't have yet:
These are worth upstreaming — but as a focused PR rebased on current Size: 253 production core-module files touched. The vast majority is fork divergence, not the fix. The 1000+ production-line advisory applies many times over. Risk: 22 high-risk paths matched (geminiChat, openaiContentGenerator, shellExecutionService, mcp-client, LspServerManager, relaunch, acp-integration, shell.ts) — all from the fork divergence, not the fix itself. These paths have the strongest correlation with post-merge reverts in this repo. CI: no build/test/lint checks have run on this commit — only bot orchestration. Without CI, there's no evidence the diff compiles against upstream. I'd suggest closing this PR and opening a new one with just the five incremental improvements listed above, rebased on current Flagging for @wenshao's attention given the scope and the core-module breadth. 中文说明感谢这个 PR,也感谢对 VP 模式静默崩溃的详细调查——crash session 分析( 模板: 基本完整,缺少 问题: 真实且已观测到。用户在 VP 模式下模型流式输出时遇到静默退出,无任何错误痕迹——关联的 issues 和 debug log 分析证实了这一点。 方向: 对齐。崩溃错误可见性完全在项目范围内。 方案——这是核心问题。 这个 PR 包含 250 个 commit、1149 个变更文件(+237K / −26K 行),来自一个与上游 更关键的是,上游
fork 的 真正新的、上游还没有的改进:
这些值得合入上游——但应该作为一个聚焦的 PR,基于当前 规模: 触及 253 个核心模块生产文件,绝大部分是 fork 分叉。 风险: 匹配 22 条高风险路径(均来自 fork 分叉)。 CI: 无构建/测试/lint 检查运行。 建议关闭此 PR,基于当前 — Qwen Code · qwen3.8-max-preview Reviewed at |
Code reviewIndependent proposal: given the problem (silent VP-mode exits, no error trace), I'd make five small changes to upstream's existing code: (1) add a sync Comparison with the PR: the PR's fix logic matches this proposal closely — the Findings on the fix code itself:
The remaining ~1,145 files are fork divergence (DataWorks features, Testing
No build, lint, typecheck, or unit-test CI has run on this commit — only bot orchestration checks. The Sandboxed verification would settle the fix's behavioural claim: 中文说明独立方案: 针对 VP 模式静默退出问题,我会对上游现有代码做五处小改动:在 与 PR 的对比: PR 的修复逻辑与这个方案高度吻合——思路都是对的。但实现在 fork 的 修复代码本身的发现:
测试: 无构建/lint/类型检查/单元测试 CI 运行。无证据表明此 diff 能针对上游 — Qwen Code · qwen3.8-max-preview Reviewed at |
|
Confidence: 2/5 — the investigation is thorough and the fix ideas are sound, but the PR as structured cannot merge: it's a 250-commit fork divergence that would overwrite upstream code with a less secure version and target architectural entry points that don't exist upstream. Stepping back: the crash analysis here is genuinely good work. The stderr-to-alternate-screen silence mechanism, the sync-vs-async debug log insight, the kitty signal-handler race — these are real findings from real debugging, not theoretical hardening. The five incremental improvements I called out in Stage 1 are worth upstreaming. But this PR is not the vehicle for that. Three blocking issues:
The path forward is straightforward: close this PR, rebase on current Requesting changes — not because the ideas are wrong, but because the PR needs restructuring before it can be reviewed and merged meaningfully. 中文说明信心:2/5 — 调查很深入,修复思路也很好,但 PR 的结构决定了它无法合入:这是一个 250 commit 的 fork 分叉,会用安全性更低的版本覆盖上游代码,并且针对上游不存在的架构入口。 三个阻塞问题:
建议路径: 关闭此 PR,基于当前 请求修改——不是因为思路错误,而是 PR 需要重构才能被有意义地审查和合入。 — Qwen Code · qwen3.8-max-preview Reviewed at |
qwen-code-ci-bot
left a comment
There was a problem hiding this comment.
Needs restructuring — see my notes above. The fix ideas are solid, but the PR is a 250-commit fork divergence that would overwrite upstream's ErrorBoundary (losing sanitizeTerminalText) and target the wrong architectural entry points. A focused PR on current main with the five incremental improvements would be very welcome. 🙏
What this PR does
Adds a
process.on('uncaughtException')handler and strengthens error visibility in VP (alternate-screen) mode. Related to #7971 #7972 #7779 #7781.This PR does not claim to fix the crashes reported in those issues — it ensures that the next time a crash occurs, the error is captured in the debug log and visible on the terminal, so the actual root cause can be identified and fixed.
Why it's needed
Users report the CLI exiting silently during model streaming with VP mode enabled (
ui.useTerminalBuffer: true) — no error message, no debug log entry, empty stderr.Investigation of a real crash session (
9b4af1de) confirmed:[ERROR],[FATAL], or exception entry in the debug loguncaughtExceptionhandler exists anywhere inpackages/cli/srcunhandledRejectionhandler are present in 0.21.1 but only cover React render errors and promise rejections — synchronous exceptions bypass bothThe silence mechanism: in VP mode, Node's default uncaught-exception stack trace goes to stderr → alternate screen buffer → discarded when teardown writes
?1049l. The user sees their shell prompt with no trace of what happened.Changes
Core fix:
uncaughtExceptionhandlersetupUncaughtExceptionHandler(sessionId)ingemini.tsxfs.appendFileSyncto the debug log (asyncdebugLogger.error()would be abandoned byprocess.exit)?1049l) before writing to stderr, so the error is visible on the main screenErrorBoundary (port of #7406 for internal sync)
ErrorBoundary.tsxwithnormalizeError,fallbackprop,onErrorcallback,resetrecoveryAppWrapperwith[FATAL_RENDER_ERROR]debug logging + 5s auto-exitconsumeLastRenderError()echoes the error to stderr after unmount leaves the alternate screenVP teardown fixes
disableKittyProtocol()moved afterinstance.unmount()so the Kitty pop lands on the main screen buffer, not the alternate screen (bug(cli): VP teardown can leave Kitty keyboard flags enabled on the main screen #7779)SIGTERM/SIGINThandlers fromkittyProtocolDetector.tsthat raced with the main signal handlersSIGHUPhandler alongsideSIGTERM/SIGINT(bug(cli): SIGTERM and SIGHUP can leave VP terminal modes active #7781)MarkdownDisplay defense
ThinkMessage/ThinkMessageContentwrapped with per-itemErrorBoundary— partial markdown during thought streaming degrades to plain text instead of crashing the VP treeHow to verify the fix works
After this PR, any crash will leave a trace:
[UNCAUGHT_EXCEPTION][FATAL_RENDER_ERROR]Unhandled Promise RejectionNo
--debugflag needed — the debug log file is written by default.Reviewer Test Plan
cd packages/cli && bun run typecheck— passesnpx vitest run src/ui/components/shared/ErrorBoundary.test.tsx— 7 tests passnpx vitest run src/ui/components/shared/VirtualizedList.test.tsx src/ui/components/shared/ScrollableList.test.tsx— 29 tests pass (no regression)Risk & Scope
uncaughtExceptionhandler callsprocess.exit(1)— this is intentional. Without it, Node.js would keep the process alive in an undefined state after a synchronous exception.AppWrapperintercepts errors before Ink's internal boundary. In non-VP mode this changes the error display from Ink'sErrorOverviewto our fallback (same information, slightly different UI).