Summary
@qwen-code/web-shell is now published by the release pipeline (#12178 adds publish_package 'packages/web-shell'). Three defects in the package's own build/packaging therefore now reach npm consumers. They are out of scope for #12178 (which only wires the release step) and are filed here instead.
Source review threads (all on .github/scripts/run-release-step.sh:191):
1. Published .d.ts files import via the repo-only @/ path alias (highest impact)
Verified against the actually published artifact, not by inference. Downloaded https://registry.npmjs.org/@qwen-code/web-shell/-/web-shell-0.24.1-preview.1.tgz — exactly 3 declaration files carry unresolvable specifiers:
dist/types/components/ui/field.d.ts:2 → import { Label } from '@/components/ui/label';
dist/types/components/ui/alert-dialog.d.ts
dist/types/components/ui/toggle-group.d.ts
No consumer can resolve @/…, so any host importing these components gets a TS error.
Cause: packages/web-shell/tsconfig.lib.json sets declaration: true, emitDeclarationOnly: true, declarationDir: "dist/types" and extends tsconfig.json, which declares "paths": { "@/*": ["./client/*"] }. The build script emits declarations with plain tsc -p tsconfig.lib.json, and tsc never rewrites path aliases in emitted declarations. There is no tsc-alias / vite-plugin-dts step. 36 from '@/…' imports exist under client/.
No lane catches this: @/ resolves fine in-repo, so typecheck and test stay green.
Fix direction: rewrite aliases on emit (tsc-alias after tsc, or vite-plugin-dts), or convert those 3 files to relative imports. A guard should assert no '@/ remains in dist/types/**/*.d.ts.
2. Six declared runtime dependencies are inlined instead of external
packages/web-shell/vite.lib.config.ts → rollupOptions.external lists react, react-dom, radix-ui, lucide-react, class-variance-authority, clsx, tailwind-merge, vaul, @qwen-code/sdk, @datafe-open/markdown-chart*, echarts, react-markdown, remark-*, rehype-katex, shiki, katex, mermaid, codemirror, … but omits these six, all of which are declared in dependencies:
| dependency |
in external? |
@xterm/xterm |
no — inlined |
@xterm/addon-fit |
no — inlined |
@tanstack/react-table |
no — inlined |
@tanstack/react-virtual |
no — inlined |
fzf |
no — inlined |
@modelcontextprotocol/ext-apps |
no — inlined |
Consequence: the published tarball is unpackedSize: 12185806 bytes (~11.6 MB, fileCount: 413), and a consumer that also depends on any of these gets a second, differently-versioned copy — for @xterm/* and @modelcontextprotocol/ext-apps that means duplicate singleton state, not just bytes.
Fix direction: derive external from Object.keys(pkg.dependencies) (the file already imports pkg from './package.json') so the list cannot drift from the manifest again.
3. Nothing asserts the exports targets exist before npm publish
package.json declares three exports targets (., ./transcript, ./daemon-react-sdk), each with a types and an import path, and files: ["dist/*.js", "dist/types"]. No step verifies those six files exist, so a lib-build regression publishes a broken version that npm will never let anyone re-issue (an npm version is immutable once published).
Lower severity than it first looks — two things already mitigate it: the build script runs the SPA vite build (emptyOutDir: true, vite.config.ts:144) before the lib builds (emptyOutDir: false, vite.lib.config.ts:172), so the lib output is not wiped; and dist/*.js is non-recursive, so SPA chunks under dist/assets/ are not swept into the tarball. Still worth a pre-publish assertion.
Scope boundary
All three live in packages/web-shell's build/packaging. #12178's diff only touches .github/scripts/run-release-step.sh, the repository field in packages/web-shell/package.json, and two release test files — fixing bundler externals or declaration aliasing there would balloon a 10-line release-wiring change.
Note: the release-side guard gap that #12178 did introduce (@qwen-code/web-shell missing from PUBLISHED_PACKAGES in scripts/assert-release-version.mjs) is fixed in that PR and is not part of this issue.
Summary
@qwen-code/web-shellis now published by the release pipeline (#12178 addspublish_package 'packages/web-shell'). Three defects in the package's own build/packaging therefore now reach npm consumers. They are out of scope for #12178 (which only wires the release step) and are filed here instead.Source review threads (all on
.github/scripts/run-release-step.sh:191):.d.tsalias)1. Published
.d.tsfiles import via the repo-only@/path alias (highest impact)Verified against the actually published artifact, not by inference. Downloaded
https://registry.npmjs.org/@qwen-code/web-shell/-/web-shell-0.24.1-preview.1.tgz— exactly 3 declaration files carry unresolvable specifiers:dist/types/components/ui/field.d.ts:2→import { Label } from '@/components/ui/label';dist/types/components/ui/alert-dialog.d.tsdist/types/components/ui/toggle-group.d.tsNo consumer can resolve
@/…, so any host importing these components gets a TS error.Cause:
packages/web-shell/tsconfig.lib.jsonsetsdeclaration: true,emitDeclarationOnly: true,declarationDir: "dist/types"and extendstsconfig.json, which declares"paths": { "@/*": ["./client/*"] }. Thebuildscript emits declarations with plaintsc -p tsconfig.lib.json, and tsc never rewrites path aliases in emitted declarations. There is notsc-alias/vite-plugin-dtsstep. 36from '@/…'imports exist underclient/.No lane catches this:
@/resolves fine in-repo, sotypecheckandteststay green.Fix direction: rewrite aliases on emit (
tsc-aliasaftertsc, orvite-plugin-dts), or convert those 3 files to relative imports. A guard should assert no'@/remains indist/types/**/*.d.ts.2. Six declared runtime dependencies are inlined instead of external
packages/web-shell/vite.lib.config.ts→rollupOptions.externallistsreact,react-dom,radix-ui,lucide-react,class-variance-authority,clsx,tailwind-merge,vaul,@qwen-code/sdk,@datafe-open/markdown-chart*,echarts,react-markdown,remark-*,rehype-katex,shiki,katex,mermaid,codemirror, … but omits these six, all of which are declared independencies:external?@xterm/xterm@xterm/addon-fit@tanstack/react-table@tanstack/react-virtualfzf@modelcontextprotocol/ext-appsConsequence: the published tarball is
unpackedSize: 12185806bytes (~11.6 MB,fileCount: 413), and a consumer that also depends on any of these gets a second, differently-versioned copy — for@xterm/*and@modelcontextprotocol/ext-appsthat means duplicate singleton state, not just bytes.Fix direction: derive
externalfromObject.keys(pkg.dependencies)(the file already importspkg from './package.json') so the list cannot drift from the manifest again.3. Nothing asserts the
exportstargets exist beforenpm publishpackage.jsondeclares threeexportstargets (.,./transcript,./daemon-react-sdk), each with atypesand animportpath, andfiles: ["dist/*.js", "dist/types"]. No step verifies those six files exist, so a lib-build regression publishes a broken version that npm will never let anyone re-issue (an npm version is immutable once published).Lower severity than it first looks — two things already mitigate it: the
buildscript runs the SPAvite build(emptyOutDir: true,vite.config.ts:144) before the lib builds (emptyOutDir: false,vite.lib.config.ts:172), so the lib output is not wiped; anddist/*.jsis non-recursive, so SPA chunks underdist/assets/are not swept into the tarball. Still worth a pre-publish assertion.Scope boundary
All three live in
packages/web-shell's build/packaging. #12178's diff only touches.github/scripts/run-release-step.sh, therepositoryfield inpackages/web-shell/package.json, and two release test files — fixing bundler externals or declaration aliasing there would balloon a 10-line release-wiring change.Note: the release-side guard gap that #12178 did introduce (
@qwen-code/web-shellmissing fromPUBLISHED_PACKAGESinscripts/assert-release-version.mjs) is fixed in that PR and is not part of this issue.