mirror of
https://github.com/QwenLM/qwen-code.git
synced 2026-08-27 01:23:52 +00:00
2 commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
3a46420d59
|
fix: repair the Windows test lane's standing failures (#10064)
* fix: repair the Windows test lane's standing failures
Fixes the eight failure clusters that keep Test (windows-latest) red on
the ECS nightly lane — three product bugs and five test bugs.
Product:
- extension-git-client: GIT_CONFIG_GLOBAL was os.devNull, whose win32
spelling ('\\.\nul') Git for Windows rejects with "Invalid argument",
failing every restricted-env git command on Windows. Use the literal
'/dev/null', which git's compat layer maps on every platform.
- sessionArtifacts: the pre-open/post-open identity check compared
numeric dev/ino. NTFS file ids are 64-bit and lose precision above
2^53 as Numbers, so two files created close together can round to the
same ino and defeat the swap (TOCTOU) detection. Compare bigint stats.
- dws-event-stream: clearing a stale stderr error on a healthy stdout
line was gated on the child still being alive, but on Windows the pipe
routinely drains only after exitCode is set, so the final healthy line
never cleared it and close reported the stale error. A clean (code 0)
exit now certifies recorded errors as stale at close.
Tests:
- daemon-git-worktree-guard: fixtures pasted native Windows paths into
command strings unquoted; on the bash lane the tokenizer consumes the
backslashes (C:\t\repo -> C:trepo), so resolvable targets tested as
unresolvable ones and cd shifts silently failed in place. Interpolate
through cmdPath(), which spells them with forward slashes on win32 —
what bash preserves and Windows resolves. Assertions keep the native
spelling; the guard canonicalizes targets through realpath.
- review/lib/worktree: git marks a linked worktree's .git gitfile hidden
on Windows and CREATE_ALWAYS on a hidden file fails with EPERM;
rewrite gitfiles via unlink-then-write.
- config: compare getCwd() against path.resolve(targetDir) — the
constructor resolves it, so the POSIX fixture comes back
drive-qualified on win32.
- SessionMessageHandler: complete the pathToFileURL shim's mirror case —
parse POSIX-spelled fixture paths with { windows: false } on win32 so
expected file:// URLs read the same on every host.
- node-repl.semantics: dispose the kernel before removing its cwd (a
process's cwd cannot be removed on Windows) and retry the removal
across the child's asynchronous teardown.
* fix: witness the Windows-lane fixes per review feedback (#10064)
- Document why the workspace-status identity fstat cannot be folded into
the Number stat (bigint stats truncate mtimeMs and return BigInt fields).
- Add a clean-exit fixture + test proving the dws consumer reports the
code-0 process error instead of a stale stderr error.
- Add an injected-stats test detecting swaps whose file ids differ only
above 2^53, so a numeric identity revert cannot ship green.
- Route the remaining unquoted/eval'd env-var assignment payloads in the
worktree guard tests through cmdPath so they stay resolvable on the
win32+bash lane.
* test(acp-bridge): consolidate the duplicated forwarding lstat spy (#10064)
---------
Co-authored-by: qwen-code-ci-bot <qwen-code-ci-bot@users.noreply.github.com>
|
||
|
|
be891657f7
|
refactor(node-repl)!: deliver the persistent Node REPL as a standalone MCP server (#9499)
* feat(core): add persistent Node REPL runtime * fix(core): align Node REPL phase-one contract * fix(core): align Node REPL module compatibility * fix(core): remove unused Node REPL host broker * refactor(node-repl)!: deliver as a standalone MCP server, revert core tools Replaces the three built-in `packages/core` node_repl tools with a self-contained MCP server package, `@qwen-code/node-repl-mcp`. Why --- Issue #9333 triage accepted the runtime only "for exploration" and gated it on an open maintainer decision: built-in core tool vs MCP-server-first. Reversing OpenAI Codex 0.149.0 settled the shape — it ships code mode as a standalone host with an in-process fallback, and its real-Node `js_repl` (not the restricted V8 `exec`) is the analogue this roadmap needs, because stage 3 (#9335) imports cua-driver's N-API addons, which only real Node can load. Delivering out-of-core also keeps a security-relevant subsystem out of the maintainer-gated `packages/core` until its value is proven. What changed ------------ - New `packages/node-repl`: the kernel, module loader, cell transform, protocol and kernel manager, ported and now dependency-free (local `debug-log`/`win-path`/`tokenizer` replace core utils; `output-adapter` emits MCP content blocks in place of `result-converter`). - Reverted every `packages/core` change, the ~11 packaging files that existed only to ship the runtime assets into six distribution layouts, and the two design/plan docs describing the core delivery. - Deleted the trusted-package/sha256 layer: it was empty and unreachable in production (`module-loader.mjs` 882 -> 483 lines). - Wired the package into `scripts/build.js` and the root `vitest.config.ts`. Net effect: `packages/core` is untouched relative to main; the tool is opt-in via `mcpServers` instead of registered unconditionally for every user. Correctness fixes made while porting ------------------------------------ - Stack line numbers were wrong and drifted with binding count (source line 4 reported as 87). The prelude is now one physical line and the cell compiles with `lineOffset: -1`. - Top-level `var` nested in blocks/try/switch/loops was silently dropped; collection now walks the statement subtree, pruning at function boundaries. Verified against real Node for 16 constructs. - A binding named `nodeRepl` permanently broke the output channel; such cells are now rejected. Ordinary globals stay shadowable, matching plain Node. - Errors thrown by imported modules lost their class, `code` and stack. - A throwing frame handler could discard buffered protocol frames. - A hoisted `var` assigned before a throw is now kept, as Node does. - Unhandled rejections settling after a cell no longer vanish. - Live sandbox timers are capped, so one runaway loop cannot saturate the session's event loop. - Image MIME types are matched case-insensitively on both input paths. - Binding sort no longer depends on host locale collation. - The published bin lacked a shebang and mis-detected its entry point, and the server plus its kernel leaked on every host disconnect. Tests: 146 across 14 files, including a compiled N-API addon fixture, 100 consecutive cells, 10 concurrent isolated kernels, stack-line fidelity, and hoisting semantics. Three smoke scripts cover the adapter, the MCP wire and process lifecycle; the packed tarball was installed into a clean project and driven end to end. Refs #9333 * fix(node-repl): pin zod to the hoisted 3.x so the workspace build type-checks `packages/node-repl` declared `zod ^4.1.13`, so `npm ci` installed a nested zod 4.4.3 for it while `@modelcontextprotocol/sdk` resolved the hoisted zod 3.25.76. Two zod type identities in one compilation made every `registerTool` input schema unassignable (`Type 'ZodString' is not assignable to type 'AnySchema'`), failing `npm run build` for this workspace — and with it the install step of every CI job that builds workspaces. The SDK accepts `^3.25 || ^4.0`, so pin the hoisted 3.x line and drop the now-stale nested lockfile entry. One deduped zod, no behaviour change. This only reproduced with a lockfile-driven install; the local tree had no nested copy, which is why the build passed locally and failed in CI. * fix(lint): lint package .mjs node scripts with the node env The eslint "scripts we run with node" override matched `packages/*/scripts/**/*.js` but not `.mjs`, nor a package-root `build.mjs`. `packages/node-repl` is `type: module`, so its `build.mjs` and `scripts/*.mjs` were linted as browser code and `eslint .` failed with `'process' is not defined` / `'console' is not defined` / `'setTimeout' is not defined`. The pre-commit hook only lints `*.{js,jsx,ts,tsx}`, so `.mjs` files are not checked locally — this only surfaced in the root CI lint step. Add `packages/*/scripts/**/*.mjs` and `packages/*/build.mjs` to the override, matching the existing `.js` entries. Generic, additive, no behaviour change. * fix(node-repl): address round-3 review findings (resolution, error identity, image bound) Triaged the bot's round-3 critical findings against the ported code and fixed the three that were genuine defects here; each has a regression test. - R3-5 (resolution): a symlinked `<cwd>/node_modules` — the norm under pnpm, monorepo hoisting and shared CI caches — was silently dropped, so the documented zero-config `await import('pkg')` failed with "cannot resolve from 0 module roots" while plain Node resolved it. The implicit cwd root was applying a re-link self-comparison that only makes sense for registered roots (which carry a registration-time canonical baseline). Follow the symlink for the implicit root, but skip it entirely when the cwd node_modules is itself a registered root, so the registered root's revocation guard is not undermined. - R3-3 (error identity): an error thrown by a host builtin inside imported code (e.g. `fs.readFileSync` → ENOENT) was rewrapped message-only, dropping `code`/`errno`/`syscall`/`cause`/`stack` — so `catch (e) { if (e.code === 'ENOENT') }`, a ubiquitous Node idiom, silently took the wrong branch. Carry those fields onto the realm-wrapped error. - R3-6 (image bound): image-frame `mimeType` was unbounded — only `data.length` counted against the raw image budget — so a malformed/forged frame could retain a huge string that also got interpolated into a notice and tokenized. Bound the MIME at frame ingestion (a real image MIME is a few dozen chars). - R3-4 is by design (the runtime is not a security boundary), but the tool description recommended `createRequire` without noting it is not subject to the process denial or module-root containment the import path enforces; the description now says so. - R3-1 / R3-2 (the `.mjs` lint failure) were already fixed in an earlier commit. Suite: 148 tests (added symlinked-cwd resolution and host-builtin error-code regressions). The symlink fix initially defeated the registered-root revocation test; the registered-root deferral above resolves both. * docs(node-repl): note top-level function/class re-declaration needs a fresh name Round-3 review R3-12/R3-33: re-declaring an existing top-level function or class in a later cell is a link-time SyntaxError (they persist as `let`, which the prelude re-declares), whereas a plain Node REPL accepts it. A correct fix needs declaration-kind tracking the manager does not carry today; until then the tool description's rerun guidance ('prefer var') is corrected, since a function cannot be made rerunnable via var. --------- Co-authored-by: Claude <noreply@anthropic.com> |