mirror of
https://github.com/QwenLM/qwen-code.git
synced 2026-10-29 02:36:20 +00:00
39 commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
c9197a2dce
|
fix(release): extend standalone runtime download retries (#15673)
* fix(release): extend standalone runtime download retries (#15672) Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * docs(release): state retry-budget evidence without claiming the failing leg (#15672) The v0.26.2-preview.0 archive step aborted and passed on an unchanged re-run, but its job log was never retrievable, so raising the download retry budget from three to five attempts is defence-in-depth, not a confirmed fix for the download leg. Record that in the source comment and drop the same unconfirmed attribution from the retry test. * fix(release): correct retry-budget comment with attempt-1 log evidence The comment claimed the v0.26.2-preview.0 archive-step log was not retrievable and the failing leg unpinned. The job log is available via the Actions API and shows three consecutive 504s from the GitHub Releases CDN downloading the bun darwin-x64 runtime, so state the pinned leg directly. --------- Co-authored-by: Qwen Autofix <qwen-autofix@users.noreply.github.com> Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> Co-authored-by: 易良 <1204183885@qq.com> |
||
|
|
0539160f35
|
fix(cli): preserve previews and verify installed OpenTUI distribution (#15655)
Some checks failed
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 / Lint & Static (ubuntu-latest, Node 22.x) (push) Blocked by required conditions
Qwen Code CI / web-shell E2E Smoke (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 / Integration Tests (no-AK, No Sandbox) (push) Blocked by required conditions
Qwen Code CI / Integration Tests (CLI, No Sandbox) (push) Blocked by required conditions
E2E Tests / Build for E2E (push) Waiting to run
E2E Tests / E2E Test (Linux) - sandbox:docker - shard 1/1 (push) Blocked by required conditions
E2E Tests / E2E Test (Linux) - sandbox:none - shard 1/1 (push) Blocked by required conditions
E2E Tests / E2E Test - macOS - shard 1/2 (push) Blocked by required conditions
E2E Tests / E2E Test - macOS - shard 2/2 (push) Blocked by required conditions
E2E Tests / E2E Interactive - OpenTUI renderer (bun) (push) Blocked by required conditions
E2E Tests / channel-plugin E2E (nightly) (push) Blocked by required conditions
E2E Tests / cron-interactive E2E (nightly) (push) Blocked by required conditions
E2E Tests / web-shell Browser Regression (push) Waiting to run
Managed Agent gate / Select the Managed Agent tier (push) Waiting to run
Managed Agent gate / SDK Java () (push) Blocked by required conditions
Managed Agent gate / Managed Agent gate (push) Blocked by required conditions
Verify Landlock helper / Native Linux CLI boundary (push) Waiting to run
Verify Landlock helper / Native Windows settings and streams (push) Waiting to run
Verify Landlock helper / arm64 (push) Waiting to run
Verify Landlock helper / x64 (push) Waiting to run
pnpm Worktree Smoke / Install (macos-latest) (push) Has been cancelled
pnpm Worktree Smoke / Install (ubuntu-latest) (push) Has been cancelled
pnpm Worktree Smoke / Install (windows-latest) (push) Has been cancelled
SDK Java Contract Open PRs / Re-check open PRs against main (push) Has been cancelled
* fix(cli): preserve previews and verify installed OpenTUI distribution * fix(ci): record installed distribution workflow growth * fix(ci): record installed distribution matrix budget |
||
|
|
32b4234b84
|
feat(cli): ship private Bun and preserve interpreter boundaries (#14959)
* fix(cli): restore bounded OpenTUI dialogs and add migration gates
* fix(cli): preserve runtime boundaries during standalone updates
Preserve Node/Bun archive flavor and validate actual CLI loading, package
identity, version and prepared installation identity before activation.
Keep Node npm transport and restrict Bun registry lookup to trusted config.
Integrates chiga0's update stack through
|
||
|
|
97567d5dd7
|
feat(core): add a real PTY backend for the Bun runtime (#14046)
* feat(core): separate app launcher and JS interpreter runtime boundary
Establishes the runtime boundary the Bun migration (MYWO-8 S1) needs
before workers, hooks, sandbox helpers and the code-mode host spawn
JavaScript children under a future compiled-app flavor: arbitrary-JS
child processes resolve their interpreter through one accessor (package
manifest first, process.execPath fallback) instead of reading
process.execPath directly, Bun detection has a single seam, and the
app-launcher contract is documented alongside the full call-site
inventory in a bilingual design doc. Adds the same-fixture Node/Bun
regression matrix (stdio framing, exit codes, SIGTERM, IPC channel,
--expose-gc, --input-type=commonjs --eval).
* fix(core): anchor interpreter resolution to the trusted install root
Arbitrary-JS child resolution no longer walks upward looking for a
manifest: the only trusted location is the standalone package root —
the parent of the caller's bundle directory, which must hold both a
manifest.json and the standalone entry marker lib/cli-entry.js — so an
unrelated ancestor manifest in npm, source or SDK layouts can never be
read. Declarations are validated before use: runtime must be exactly
'bun' or 'node', and the interpreter must be an existing executable
regular file; any invalid or missing declaration falls back to
process.execPath without throwing (non-string interpreter, directory,
non-executable file, unknown runtime, absent binary, missing marker).
Adds the regression matrix for unrelated ancestor manifests (npm
bundle and deep SDK layouts), object/number/directory interpreters,
unknown runtime, missing and non-executable interpreters, and the
trust anchor; syncs both design-doc language versions with the
validated contract.
* docs(design): complete the migration inventory handoff
Adds the three interpreter-identity call sites the re-review found
missing from the call-site inventory (hook-command-cgroup launcher,
bwrap-execution and landlock-execution allowlist staging), marks the
unwired rows as owned by the S3 migration sweep, and notes platform
applicability: the cgroup/bwrap/landlock rows are Linux-only
mechanisms validated against the Linux targets of the platform
matrix, while the mem0 and pem rows apply on every platform. Both
design-doc language versions are updated; no product or test code
changes.
* feat(core): add a real PTY backend for the Bun runtime
Under Bun, @lydell/node-pty's wrapper pumps the PTY master fd through a
tty.ReadStream, and Bun surfaces the nonblocking fd's EAGAIN as an error
event instead of "no data yet", destroying the stream and closing the
master: onData never fires, resize fails with EBADF, and the shell tool
and web terminal hang. Reproduced on Bun 1.3.14 and 1.4.0.
getPty() now loads a qwen-bun-pty backend under Bun (non-Windows) that
drives the same native addon directly with a main-thread async fs.read
pump: EAGAIN retries on a short timer instead of erroring, EIO/EBADF end
the pump and close the fd, writes queue through an async fs.write with
EAGAIN retries, and exit waits briefly for the drained fd so data is
never truncated behind onExit. The wrapper's observable contract (env
sanitizing, flow-control bytes, encoding, resize validation, IPty
lifecycle) is mirrored, and the pump starts in the constructor so an
unpumped fd can never hold the event loop open.
Packaging stages the node-pty addon for both runtime flavors, since Bun
installs now load it through this backend. The Windows-under-Bun gate
stays honest (explicit load error), and the runtime-boundary design docs
point at the new backend doc for the mechanism and evidence.
Tests: unit coverage for the backend lifecycle (output, write, resize,
kill, pause/resume, flow control, raw encoding), getPty selection under
Bun/Windows, and a cross-runtime regression that runs the same fixture
through the real getPty() seam under both Node and Bun when a bun binary
is present.
* fix(core): keep PTY exit detection alive while paused
The pinned node-pty addon fires its native exit callback only around
master-fd read activity (isolated-probe evidence, identical on Node and
Bun), so the old pause() that stopped the pump lost onExit entirely:
pause then child exit left the master fd open and the host unable to
drain — the same mechanism behind the XOFF-then-cancel FD residue under
handleFlowControl.
pause() now buffers output into a bounded hold (1 MiB) that resume()
flushes, while reads continue so exit detection rides on the pump.
On end of life the hold is discarded for wrapper parity: onExit arrives
exactly once and the fd is released, but resume-after-exit replays
nothing, matching the wrapper's destroyed paused socket. Docs are
synced to the actual main-thread async fs.read pump (the earlier
worker-threads/blocking-read sketch is documented as abandoned), and
regressions cover pause-at-exit, hold overflow, and XOFF-cancel on both
runtimes.
* fix(core): make the Bun PTY pause hold lossless and exits leak-free
Serializes master-fd reads behind an in-flight guard (a resume chaining
into a read that is still outstanding would cross-observe the shared
64 KiB buffer), holds paused output without a cap so nothing is ever
silently dropped, and routes every end-of-life path through one cleanup
that flushes the decoder, stops the retry timer, closes the master fd
and fires onExit exactly once — including the 500 ms fallback, which is
now ref'd so exit delivery cannot depend on a droppable timer. Pins all
of it with byte/line-exact regressions: no-gap pause/resume storms and
a ~1.9 MB flood resumed byte-for-byte, cross-runtime.
* fix(core): cap the Bun PTY pause hold and terminate on overflow
The lossless pause hold could grow without bound while a consumer
stays paused. The hold now copies chunks into fixed 64 KiB blocks
under a per-pty byte ledger (4 MiB default) inside a process-wide
budget (32 MiB total hold, 8 active ptys, 1 MiB write queue), so the
bound holds for any producer chunk pattern.
Reaching a cap terminates that pty (SIGTERM then SIGKILL) and emits
one structured PtyLimitError — never a success result and never a
fabricated native exit; the real signal death lands only in
stats.nativeExitRecord. Shell executions converge the error into
{error, exitCode: null, signal: null}; web terminals mark the session
failed and the /terminal route sends an error control frame followed
by close 4001. Node behavior is unchanged.
Design docs corrected per review: the drip "kernel corruption" claim
is withdrawn, and exit detection wording no longer overstates when
exits are observed.
* fix(core): harden post-termination pty edges per review
Dual-review follow-ups on the bounded hold: resize() joins write() in
treating a terminated/closed pty as a no-op instead of throwing EBADF
from the addon; a read that was in flight when the limit termination
closed the fd no longer delivers or re-charges its late bytes; and a
resume() replay stops at the first data listener that terminates the
pty, so no held bytes flow after the structured error.
* fix(core): detach pty error subscriptions by observed shape, not assumed Disposable
node-pty's Terminal.prototype.on proxies the listener to its master socket
and returns undefined, while an EventEmitter-based pty (the Bun backend)
returns the emitter itself. The registry stored that return value as a
Disposable and called dispose() on release, so every Bun release, natural
exit, or backend failure path threw TypeError from the route/registry and
could take the whole serve process down (server exit 1, client saw 1006
instead of the explicit close).
Store the subscription return as unknown and detach by observed shape: a
real { dispose } is used as-is, otherwise off/removeListener removes the
listener, and undefined (node-pty's actual return) keeps the previous
no-dispose behavior unchanged.
Covered by two registry unit tests on the mocked shapes plus a real-serve
lifecycle probe (release 4004 / exit 4000 / backend over-limit 4001 with
failed-session reconnect replay, server alive throughout) run under Bun
1.3.14, Bun 1.4.0, and Node.
* fix(core): close Bun PTY fds only after in-flight ops settle
Review round on #14046:
- bun-pty closeFd() ran closeSync() while libuv fs.read/fs.write ops could
still own the master fd, so the recycled descriptor number could take a
queued write into an unrelated session. fdClosed now flips and the
process-wide admission slot is released immediately, but the real close
is deferred until the last outstanding op settles, with witnesses for
both the read-held and write-held arms.
- A write-side EIO/EBADF (child already gone) is the expected teardown
race and is no longer reported, matching the wrapper's swallowed EIO;
other write errors keep their errno code so the entry classifier and
getPtyLimitMessage can recognize them instead of escaping as an
uncaught exception. The pump's emit dispatch runs under try/finally so
a throwing error listener can never strand the pump.
- The web-terminal registry's pty error subscription no longer re-throws:
a throw there leaves the backend's fs callback as an uncaught exception
and kills the serve daemon. EIO/EAGAIN races are swallowed and other
non-limit errors go to the diagnostic sink.
- Failed sessions no longer count against the web-terminal admission cap,
and release() no longer fabricates a 143/15 exit frame for them.
- processPtyBudget.maxActivePtys is 64 (headroom over the eight-slot
web-terminal cap so a full house cannot starve the shell tool), with
the per-pty vs process-wide cap relationship documented.
- ShellExecutionResult.executionMethod declares 'qwen-bun-pty', its
error-field contract documents resource-limit termination, and the two
casts that hid the Bun backend name are dropped.
- getPty tests that assert the Bun arm loads now pin a POSIX platform so
they pass on Windows hosts; docs and the packaging help text are
aligned (correct smoke-runtime.js path, boundary-doc PTY row now cites
the bun-pty fixture, node-pty staging applies to both runtimes).
* chore: re-verify S1 boundary test-file merge resolution with recorded evidence
Empty commit: no code change is warranted by the deterministic gate's
test-weakening rejection. The merge
|
||
|
|
5f638ae436
|
feat(generated-ui): bundle Generated UI behind an experimental flag (#14888)
* feat(generated-ui): bundle behind an experimental flag * fix(generated-ui): preserve runtime admission and settings aliases * fix(generated-ui): invalidate owning cards after MCP refresh --------- Co-authored-by: 衍星 <qiuyusheng.qys@alibaba-inc.com> |
||
|
|
9763580b84
|
feat(mods): run experimental headless Mod commands (#13843)
Some checks are pending
Qwen Code CI / web-shell E2E Smoke (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 / Integration Tests (no-AK, No Sandbox) (push) Blocked by required conditions
Qwen Code CI / Integration Tests (CLI, No Sandbox) (push) Blocked by required conditions
Qwen Code CI / Desktop Shell (ubuntu-22.04) (push) Blocked by required conditions
Qwen Code CI / Desktop Shell (windows-2022) (push) Blocked by required conditions
E2E Tests / Build for E2E (push) Waiting to run
E2E Tests / E2E Test (Linux) - sandbox:docker - shard 1/1 (push) Blocked by required conditions
E2E Tests / E2E Test (Linux) - sandbox:none - shard 1/1 (push) Blocked by required conditions
E2E Tests / E2E Test - macOS - shard 1/2 (push) Blocked by required conditions
E2E Tests / E2E Test - macOS - shard 2/2 (push) Blocked by required conditions
E2E Tests / E2E Interactive - OpenTUI renderer (bun) (push) Blocked by required conditions
E2E Tests / channel-plugin E2E (nightly) (push) Blocked by required conditions
E2E Tests / cron-interactive E2E (nightly) (push) Blocked by required conditions
E2E Tests / web-shell Browser Regression (push) Waiting to run
SDK Java Flyway Open PRs / Re-check open PRs against main (push) Waiting to run
SDK Java / ubuntu-latest / Java 11 (push) Waiting to run
SDK Java / ubuntu-latest / Java 17 (push) Waiting to run
SDK Java / macos-latest / Java 21 (push) Waiting to run
SDK Java / ubuntu-latest / Java 21 (push) Waiting to run
SDK Java / Flyway migration version uniqueness (push) Waiting to run
SDK Java / windows-latest / Java 21 (push) Waiting to run
SDK Java / Real daemon E2E / Java 11 (push) Waiting to run
SDK Java / Runtime Broker and Managed Agent MariaDB / Java 21 (push) Waiting to run
SDK Java / Hosted process fault gates / MySQL 8.4 / Java 21 (push) Waiting to run
Verify Landlock helper / Native Linux CLI boundary (push) Waiting to run
Verify Landlock helper / Native Windows settings and streams (push) Waiting to run
Verify Landlock helper / arm64 (push) Waiting to run
Verify Landlock helper / x64 (push) Waiting to run
* feat(mods): run experimental headless Mod commands * fix(mods): preserve marketplace hooks and packaging fixtures * fix(mods): skip ignored Claude hook paths --------- Co-authored-by: qqqys <266654365+qqqys@users.noreply.github.com> |
||
|
|
abcf23a3d9
|
feat(memory): bundle Mem0 with the main CLI (#12891)
* feat(memory): bundle Mem0 with the main CLI Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * feat(memory): support settings-defined Mem0 credentials Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * fix(memory): preserve bundled Mem0 trust and configuration boundaries Ignore repository-scoped MCP conflicts, require the genuine bundled runtime for confirmation hooks, and use native artifact paths in packaging assertions. Improve field diagnostics and document existing precedence, scope, and verification limits. Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * fix(mem0): close three review Criticals on the bundled Mem0 binding R1-1 (scripts/tests/package-assets.test.js): the two new multi-segment `missingArtifact` entries are compared against a message built with `path.join`, so `mem0/main.js` never matches the `\`-joined Windows path. Normalise the separator in the assertion; single-segment entries and POSIX behaviour are unchanged. R1-2 (packages/cli/src/config/config.ts): the mem0/external-context conflict guard read the merged all-scopes map, so a `external-context` entry that a trusted repository contributes through its own `.qwen/settings.json` (`scope: 'workspace'`) aborted `loadCliConfig` for every operator who configured `memory.mem0` — before `assembleMcpServers` applied the approval gate that would have held that server pending anyway. Limit the settings leg to operator scopes via `isGatedMcpScope`; a gated-scope entry is now overridden by the built-in binding (topTierMcpServers spreads last), exactly as a `.mcp.json` entry of the same name always has been, matching the design doc this PR adds. R1-28 (packages/cli/src/config/mem0-settings.ts): `bundledMem0Hooks` identified the bundled server by duck-typing an env-var name plus `includeTools`, so a repository-authored `external-context` entry reaching the `/hooks` reload path through `getMcpServers()` was filed under `systemHooks` — the one hook source folder trust does not gate — rendered as `[System]` configuration and pointed at a different script than the one the MCP approval dialog showed. Require identity instead: every file-sourced entry carries a provenance `scope`, the bundled one never does. Tests: workspace-scoped override + operator-scoped conflict still throws (config.test.ts), three scoped-entry rejection rows + an unscoped positive control (mem0-settings.test.ts), and a control/negative pair on the real reload path (hooksCommand.test.ts). Each fix was mutation-proved red. Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> Patrol-Run: qwen-pr-closeout/jmultfgjtdh * test(mem0): pin the spawn interpreter, timeout slack and both bound copies R1-23: nothing in the repo observed `server.command` or `server.timeout`, and the `memory.mem0.timeoutMs` bounds are declared independently in mem0-settings.ts (zod, the runtime contract) and settingsSchema.ts (the settings-dialog copy). Replacing `command: process.execPath` with `'node'`, or dropping the `+ 5000` slack, left every suite green — a packaged or GUI-launched install routinely has no `node` on PATH, and the same value gates `bundledMem0Hooks` and is interpolated as the hook interpreter. Adds, in mem0-settings.test.ts: `command === process.execPath`, `config.timeoutMs === 5000` / `server.timeout === 10_000` for the default, an accept row at the documented ceiling asserting `35_000`, and reject rows for `0` / `30001` / `1.5`. Adds, in settingsSchema.test.ts, the bound test mirroring the existing `tools.webSearch.timeoutMs` precedent so the JSON-schema copy is pinned to the same documented numbers (docs/users/features/mem0.md: "defaults to 5000, between 1 and 30000"). Mutation-proved individually: `process.execPath` -> `'node'` red, `+ 5000` removed red, `maximum: 30000` -> `60000` red; intact tree green (27 + 61). Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> Patrol-Run: qwen-pr-closeout/jmultfgjtdh * fix(mem0): restore PolarDB direct-import text on retrieval Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * test(mem0): use the real bundled binding in hook reload control Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * fix(memory): Preserve Mem0 operator and legacy preset semantics Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * test(memory): Pin Windows Mem0 package artifact errors Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * fix(memory): Retain Mem0 safeguards across reloads --------- Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> |
||
|
|
1a5a74bc35
|
feat(core): Add Landlock execution fallback (#12278)
* feat(core): Add Landlock execution fallback Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * fix(ci): Track Landlock helper workflow size Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * docs(sandbox): Clarify Landlock compatibility limits Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * fix(sandbox): Repair installed Landlock helpers and prompt guidance Restore missing execute bits only for the bundled helper, anchor asset lookup to the actual source layout, and describe the effective Landlock boundary in the model prompt. Keep portable asset checks on Windows. Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> --------- Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> |
||
|
|
010941d202
|
fix(standalone): pin @lydell/node-pty-linux-arm64 and fail release on missing prebuilds (#12649)
* fix(standalone): pin @lydell/node-pty-linux-arm64 and make missing prebuilds fatal at release The wrapper publishes a linux-arm64 prebuild at the same 1.2.0-beta.10 pin, but the root and core manifests never declared it, so the linux-arm64 standalone archive and the linux-arm64 Desktop runtime both degraded to "PTY not available" while every other target shipped a working web terminal. With the pin in place every shipped target resolves a prebuild package, so the release archive build can stop degrading silently: release.yml now exports QWEN_STANDALONE_REQUIRE_NODE_PTY_PREBUILD=1 next to the existing audio-capture gate, turning a missing prebuild into a hard failure instead of another #11872. Fixes #11872 * fix(standalone): update pnpm lockfile for the linux-arm64 node-pty pin The two package.json manifests gained @lydell/node-pty-linux-arm64 but pnpm-lock.yaml was not regenerated, so every CI job failed at the frozen-lockfile install with ERR_PNPM_OUTDATED_LOCKFILE. * docs(standalone): align the linux-arm64 PTY guide and tripwire with the pin Pinning @lydell/node-pty-linux-arm64 makes linux-arm64 a supported PTY target, but INSTALLATION_GUIDE.md still told users that archive ships without PTY and reports "PTY not available". CI could not catch the drift because install-script.test.js pinned that exact sentence as its tripwire, so the guide and the assertion have to move together. List all five shipped targets in the guide, retarget the tripwire at the new sentence, and refresh the matching stale comment in desktop-shell's test-release.js degrade fixture - that arm now only fires for a target the map does not know. Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * fix(standalone): complete the node-pty linux-arm64 pin in esbuild externals `create-standalone-package.js` documents that "esbuild.config.js keeps every node-pty specifier external" so the bundled CLI resolves the platform prebuild from `lib/node_modules` at runtime. The external list carried five of the six pinned platform packages and omitted `@lydell/node-pty-linux-arm64` — the exact platform this PR pins. Nothing imports that specifier statically today, so the bundle is unaffected; the gap is that the invariant the archive's PTY support rests on was one entry short of complete. Probe (esbuild, `--platform=node --format=esm`, entry importing both specifiers): - without the entry: `Could not resolve "@lydell/node-pty-linux-arm64"` - with the entry: builds clean and emits the import left external, matching the other five platforms Also corrects two comments this PR rewrote in the previous round. Both claimed the desktop degrade arm "fires only for a target the map does not know (a future platform)". That trigger is unreachable: `desktopTarget()` throws `Unsupported desktop target` for anything outside its five-entry allowlist and `NODE_PTY_PREBUILD_PACKAGE` maps exactly those five, so `prebuildPackage` is always a real name. Verified by running the script: $ QWEN_DESKTOP_SKIP_BUILD=1 QWEN_DESKTOP_TARGET=freebsd-x64 \ node packages/desktop-shell/scripts/prepare-runtime.js Error: Unsupported desktop target: freebsd-x64 at desktopTarget (prepare-runtime.js:351:11) The reachable trigger is the one the warn string already names and the one `test-release.js` reproduces four lines below its own comment: a known target whose prebuild package is unpinned in the source root manifest. Comment-only apart from the single external entry. prettier --check and eslint --max-warnings 0 clean on all three files; node --check passes. Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * test(standalone): pin the node-pty release gate and its target map Closes out three review findings on the node-pty pin. Test- and comment-only apart from one new export; no production behavior changes. R1-1 prepare-runtime.js: the nodePtyPackageSpecs() docstring still claimed its null return "is how an unsupported target degrades". desktopTarget() throws for anything outside its five-entry allowlist, and test-release.js:testRuntimeNodePtyTargetMapping() asserts NODE_PTY_PREBUILD_PACKAGE's keys equal exactly that allowlist, so an unknown target can never reach it. A null here is a dropped pin. Verified by re-running that tripwire's extraction against the edited file: both literals still match and keys == allowlist == the same five targets. R1-2 create-standalone-package.js: export TARGET_PREBUILD_DIR and assert every release target maps to a package the manifests actually pin. The guide sentence this PR adds states that invariant while release.yml:707 makes violating it abort the whole archive step, yet the map had zero test references. The expectation is derived from readNodePtyPackageSpecs() so the version list stays single-sourced, and is one-directional because @lydell/node-pty-win32-arm64 is pinned while no target maps to it. R1-3 install-script.test.js: the release.yml assertion matched only the variable name, which also appears in the packager's usage text, so nothing connected producer to consumer and no test executed the fail() branch at create-standalone-package.js:578. Tightened to the full wiring line and added the behavioral twin of the audio-capture pair: gate on with the addon removed must throw, gate off must still build a PTY-less archive. packageFakeStandalone() gained an env option for this; spreading process.env leaves its 15 existing callers unchanged. Mutation-checked, each mutant applied alone then restored and md5 verified: win-x64 mapped to an unpinned name, gate reader renamed to '2', gate polarity flipped to !==, and release.yml no longer evaluating to '1' are each caught by a new or tightened assertion. The polarity flip was previously undetectable on the PR lane, where the linux-x64 prebuild is present so the gate is never reached. Focused: install-script.test.js 130 passed / 11 skipped (141). prettier --check and eslint --max-warnings 0 clean on all three files. Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> Patrol-Run: qwen-pr-closeout/jmufv3et42h * docs(standalone): state the real node-pty degrade conditions in comments prepare-runtime.js said the degrade arm fires only "where the repo pins nothing", but nodePtyPackageSpecs returns null at the first unpinned name of the pair, so it also fires when the wrapper pin is the one that went missing while the warning names the prebuild package. Say "either name in the pair" and note which package the warning names. create-standalone-package.js justified the non-fatal default with "a developer archive stays usable on an unmapped future target", which cannot happen: main() calls copyNativeAddon first and it reads the same TARGET_PREBUILD_DIR in an unconditional path.join(), so an unmapped target dies with a TypeError in the audio step before copyNodePtyAddon runs. Replace the rationale with the case that does reach the warn arm (a target whose prebuild the host install does not have). Comment-only; no behaviour change. Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> Patrol-Run: qwen-pr-closeout/jmug1iw422v * test(standalone): make the node-pty gate assertions discriminate Pin the `Required ` prefix on the fatal-gate regex. copyNodePtyAddon builds one message and emits it on both paths, so the prefix-less regex was also satisfied by the degrade warning folded into the child's stderr — the suite would have reported the gate as covered after the prefix was dropped from fail(). The sibling clipboard gate assertion already spells the prefix. Assert QWEN_STANDALONE_REQUIRE_NODE_PTY_PREBUILD structurally on the `Build Standalone Archives` step env instead of as a whole-file substring, so commenting the line out or moving it into a neighbouring step's env goes red. build-standalone-release.js spawns the packager with no env override, so that step's env is the only route to the gate. The comment defending the substring pin named a collision with create-standalone-package.js's usage text, which cannot occur: the searched string is release.yml alone. Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> Patrol-Run: qwen-pr-closeout/jmug1iw422v * test(standalone): cover the node-pty target map and the win-x64 dir name Two coverage gaps left by the previous round of gate tests: - The map test looped over TARGET_PREBUILD_DIR itself, so a release target with no map entry was never visited, deleting a whole entry merely removed an iteration, and an emptied map passed vacuously. Drive the loop from TARGETS and assert the lookup before the pin. Still one-directional: @lydell/node-pty-win32-arm64 is pinned while no target maps to it. - Both gate tests reached the packager through packageFakeStandalone, which hardcoded --target linux-x64, the one dialect where the prebuild dir name equals the target name. Add a win-x64 arm so the 'win-x64' -> 'win32-x64' translation in copyNodePtyAddon is covered on every lane rather than only on test_windows. Parameterise the staged-modules fixture and the packaging helper to make that reachable without a Windows host. Test-only change; no production code is modified. Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> Patrol-Run: qwen-pr-closeout/jmug5t7mp33 --------- Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> |
||
|
|
0371b40fbd
|
fix(release): retry transient standalone runtime downloads (#11870) (#11879)
* fix(release): retry transient standalone runtime downloads (#11870) The v0.23.4 publish died in Build Standalone Archives while the identical re-run — same commit, same prebuild artifact — passed, so the failure was a transient external call, not a code defect. That leg downloads SHASUMS256.txt plus one Node.js archive per target with no timeout and no retry, so a single nodejs.org blip aborted the whole release. Bound each download with a 120s fetch timeout and retry up to 3 times with exponential backoff, verifying the archive checksum inside the loop so a corrupted download is re-fetched rather than reported once and abandoned. Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * fix(release): harden runtime download retries and pin their wiring (#11870) Address review findings on the retry change. Verify each flavor's checksum list inside the retry, so a corrupt or truncated SHASUMS256.txt is re-downloaded instead of poisoning every archive check against a stale in-memory map; the expected names come from the same runtimeArchiveName helper the archive leg uses, so the two cannot drift. Drop the timeoutMs/maxAttempts knobs no caller could set and read the module constants directly, matching uploadWithRetry. Include error.cause in retry warnings, since a real undici failure reads only "fetch failed", and separate the retry notice from the error text. Pin the retry call sites, backoff schedule, and constant values in tests, and drop the nodejs.org host attribution from the rationale comment: the v0.23.4 abort was a transient download failure and the retry is host-agnostic. Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * fix(release): aggregate missing runtime checksums under the display label (#11870) * test(release): pin bun checksum label and observe retry wiring behaviourally (#11870) Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * test(release): pin archive-leg call site and tolerate comments in wiring pin (#11870) Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> --------- Co-authored-by: qwen-code-dev-bot <qwen-code-dev-bot@users.noreply.github.com> Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> |
||
|
|
64dd058c9c
|
ci(pnpm): install with pnpm everywhere and retire package-lock.json (#11859)
* ci(pnpm): install dependencies with pnpm in CI and release CI tests the graph release ships only if both install it the same way, so this moves both, keeping every `npm run` script and `npm publish` as they are. - ci.yml (7), release.yml (3) and release-vscode-companion.yml (2) install with `corepack pnpm install --frozen-lockfile`; release keeps --ignore-scripts plus its explicit postinstall and generate steps. - setup-node drops the npm cache and sets package-manager-cache: false, which setup-node v5+ needs once package.json declares a pnpm packageManager. - A composite action caches the pnpm store on the three always-hosted jobs; the ECS pool keeps its store on local disk. - version.js no longer lets npm reify node_modules: --no-workspaces-update on both `npm version` calls, and a package-lock-only refresh in step 9. - The notices generator, prepare-package's sharp pin and the standalone release's native package specs read the installed tree or pnpm-lock.yaml instead of package-lock.json keys. - New size baselines for the three workflows, which were already over them. * chore(vscode): regenerate NOTICES from the pnpm-installed tree Generated in CI (pnpm Worktree Smoke on ubuntu-latest) by the ported generator. Same entry set as before except the five packages npm and pnpm resolve differently: fdir 6.5.0, picomatch 4.0.5, mdurl 2.1.0, @types/node 22.20.1 and mime-db 1.52.0 (form-data's pinned copy). No entry lacks a license text or repository. * fix(pnpm): resolve undeclared zod peers to the repo's zod, as npm does The first CI run on this branch failed the export renderer's size budget: 1,930,015 bytes against 1,930,000, where the same commit built on npm's tree comes to 1,858,186. Comparing both trees' esbuild metafiles and prebuilt bundles put the whole difference in web-shell's transcript.js (+100,903 bytes pre-minify), and the added code is zod 4 plus the @modelcontextprotocol/ext-apps schemas; the sdk daemon bundle is identical. web-shell bundles ext-apps, whose zod and MCP SDK are peers, and declares no zod itself, so pnpm filled the peer with the highest locked zod (4.4.3) while npm serves the hoisted 3.25.76. Declaring zod 3.25.76 as a root devDependency makes pnpm resolve every such peer to it (resolve-peers-from-workspace-root is on by default), which is npm's hoisting behaviour. mobile-mcp keeps its own zod 4.4.3, as under npm; the npm tree does not change. * fix(pnpm): keep npm's root @types/node so root-level typechecks match The no-AK integration gate typechecks integration-tests/, which takes Node's types from the root node_modules. npm hoists @types/node 20.19.1 there, because acp-bridge and core pin it; pnpm, with no root declaration, hoisted 22.20.1, whose spawnSync overloads type process-registry.ts's stdout as string | NonSharedBuffer and fail TS2322. The same code passes on every npm-installed PR. Declaring 20.19.1 as a root devDependency puts npm's copy back where a root-level tsconfig looks. The npm tree does not change. * ci(pnpm): install with pnpm in the remaining workflows The follow-up to switching CI and release: every other workflow that installs the root workspace now uses the pinned pnpm with --frozen-lockfile, so no job tests a graph that release does not ship. - e2e, tui-parity, repo-hygiene, web-shell-visuals, serve-ab, sdk-java, windows-runner-smoke, qwen-autofix, the SDK releases, finalize-release, sync-release-to-oss, the root install in desktop-release and cd-cua-driver, and the sandbox Dockerfile. - setup-node drops the root npm cache (package-manager-cache: false); hosted jobs restore the pnpm store through the shared composite action, and qwen-autofix keeps af-012's rule that the persistent pool restores no remote cache. - serve-ab and web-shell-visuals install a separate base checkout that can predate pnpm-lock.yaml, so those installs fall back to npm ci there. - Out of scope, unchanged: packages with their own lockfile (cua-driver's TypeScript SDK, desktop-shell, live-host, mobile-mcp), and the triage lanes with npm-cache.yml and the npm audit gate, which move with the package-lock.json retirement. - New size baselines for the touched workflows; qwen-autofix stays under the 470000-byte gate. * fix(pnpm): link the workspace packages that root-level code imports npm links every workspace package into the root node_modules, so integration-tests/ and scripts/, which are not workspace packages themselves, can import @qwen-code/* by name. pnpm links a workspace package only where it is a declared dependency, and the root declared none, so the no-AK integration gate could not find @qwen-code/qwen-code-core. The root now declares the seven packages that root-level code imports at runtime as file: devDependencies: acp-bridge, channel-base, the CLI, core, sdk, web-shell and web-templates. npm already links them, so its tree does not change (letting npm re-resolve the lock reproduces the same root entry); .pnpmfile.mjs rewrites them to workspace:*, which pnpm links at the root. * ci(pnpm): move triage, the store producer and the root audit to pnpm - qwen-triage's verify and tmux-testing lanes install the PR with `corepack pnpm install --frozen-lockfile` from a restored pnpm store. The one retry clears node_modules first, because pnpm install, unlike npm ci, keeps it. - npm-cache.yml becomes pnpm-store.yml, keyed on pnpm-lock.yaml. - security-checks audits the root workspace with `pnpm audit`, which reads the lockfile, so the root install step goes. The vendored lockfiles keep npm, and the retry recognises pnpm's endpoint error too. - qwen-autofix drops the hosted-only store cache: its heavy jobs forbid local `uses: './...'` actions, and the file sits at the size gate. - cd-cua-driver: setup-node@v4 has no package-manager-cache input. - package-assets fixtures install sharp rather than listing it in package-lock.json, matching how prepare-package now resolves it. - AGENTS.md, CONTRIBUTING.md and the npm workspace guide install with pnpm. * feat(review): install pnpm repos in qwen review's build/test qwen review installed dependencies only for a repo with package-lock.json and reported a pnpm repo as unsupported, so reviews of qwen-code would lose their build and test once its npm lockfile goes. - lockfileInstaller() picks npm or pnpm from the committed lockfile. With both, `packageManager: pnpm@...` chooses pnpm; anything else keeps npm. - A pnpm repo installs with `corepack pnpm install --frozen-lockfile` through the same disk, budget and sandbox path as `npm ci`, and counts as installed once node_modules/.modules.yaml exists. - Scripts still run through `npm run`, and the npm path is unchanged. * ci(pnpm): retire the root package-lock.json pnpm-lock.yaml is now the only root lockfile. - check-lockfile keeps the pnpm integrity check and Playwright parity, which now reads pnpm importers and snapshots. The npm-vs-pnpm agreement and build-approval checks go: pnpm 11's strictDepBuilds and every CI install's --frozen-lockfile enforce what they covered. - pnpm-lock-freshness.yml goes; it regenerated pnpm-lock.yaml from package-lock.json. - Release: version.js drops its package-lock refresh, the release commit stages pnpm-lock.yaml and the SDK release stages no lockfile, so neither `git add` fails on the missing file. `npm version` in the SDK and mobile-mcp releases passes --no-workspaces-update so it cannot reinstall the root with npm. - cd-mobile-mcp installs from the root pnpm lockfile. setup-node in cd-mobile-mcp, qwen-code-pr-review and desktop-release no longer keys an npm cache on the root lockfile. - check-desktop-isolation reads pnpm importers; build.js, build_sandbox.js and preflight install with pnpm. - pnpm-lock.yaml, pnpm-workspace.yaml and .pnpmfile.mjs join the autofix supply-chain class and repo-hygiene's deny list; pnpm-lock.yaml joins autofix's generated-diff exclusions, sdk-java's path filter and the platform-sensitivity manifests. - .gitignore lists /package-lock.json so an npm install cannot commit it back. Tests and docs follow. * fix(standalone): read the node-pty versions from the pnpm lockfile * chore(vscode-ide-companion): regenerate NOTICES.txt after the lockfile swap * chore(vscode-ide-companion): regenerate NOTICES.txt from the pnpm dependency tree The committed NOTICES.txt was generated from an npm install and does not match the tree produced by the pnpm install the release pipeline now uses (659 resolved dependencies, differing @types/node and mime-db versions). Regenerating with the pinned pnpm install makes the freshness check reproducible. * fix(ci): drop the npm cache from the daily dependency audit actions/setup-node's npm cache keys off the root package-lock.json, which this branch retires, so the scheduled job would fail at Set up Node before the audit ran. No pull_request run reaches this workflow to catch it. The root tree is never installed here either: pnpm audit reads pnpm-lock.yaml directly. Matches the sibling workflows that already set package-manager-cache: false; scripts/tests/security-workflows.test.js now pins it. * chore(ci): stop banking main-side drift in the workflow size ratchet The ratchet exists to turn a workflow's growth into one reviewed line. This branch re-recorded entries for 17 workflows it never touches, several upward by 0.4-2.8 KB - drift that happened on main, banked into the manifest without review. Restore those to their merge-base values, so .size-baseline changes only for the 22 workflows this branch actually edits. The entries were not needed to go green: ci.yml passes the PR's base commit, so a file that drifted on main and is otherwise untouched earns a warning, not a failure. * fix(release): initialize standalone state before main * test(browser-use): read Playwright pin from pnpm lock * fix(ci): address pnpm migration review blockers * fix(desktop): stop reading the retired root lockfile --------- Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> |
||
|
|
3486cd8f86
|
feat(core): Add the bwrap execution foundation (#12067)
* feat(core): add bwrap execution foundation Extract the internal structured launch, confined worker and trusted completion boundary from the tool sandbox work. Keep runtime policy and CLI activation for subsequent changes, and include worker packaging and standalone Linux acceptance. Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * fix(core): bound streamStdout post-exit settle and harden sandbox plumbing Address PR #12067 review findings: - settle streaming pipe executions on 'close' or a bounded 1s post-exit drain, whichever comes first: settling on 'close' alone wedged the result promise whenever an exited shell left a grandchild holding the pipes (background shells, ACP channel) — @chiga0 F1, ci-bot R1-2 - keep transport-level stdin EPIPE out of the spawn-error slot unless the process left no exit information, so a receipt-confirmed run finalizes confirmed and an interrupted run cleans up (ci-bot R1-26); re-key sandbox evidence retention on the finalized status (R1-24) and prefer the specific transport/spawn error over the generic status error (R1-22) - allowlist the two new sandbox dist assets for standalone packaging and require them at archive build time, with a drift test covering every npm files entry (ci-bot R1-1) - default the payload TERM under --clearenv (R1-4), gate the streaming decoder flush on text mode (R1-7), log post-promote settle chain failures (R1-25), and pin the caller-signal/pipe-transport contract (R1-15), the caller-owned stdin snapshot (R1-31) and both settle-timing directions (R1-30) in tests * fix(core): scope sandbox evidence retention to post-exec uncertainty Address @wenshao's blocking verification finding on PR #12067: keying retention on status.state === 'unconfirmed' retained the control/scratch dir pair for failures that never reached exec — a missing bubblewrap or payload binary — leaking one pair per invocation and breaking the PR's own verifier (33/34 on tip vs 34/34 on the reviewed candidate). - parseBwrapStatus now reports payloadExitObserved when the status wire carries a well-formed bwrap exit-code record (bwrap only emits it once the payload is past exec), and the relay attests payloadExitObserved: false on spawn/transport failure - the finalizer retains only when the payload may genuinely have run: the receipt attests an exit record, or the receipt file exists but is unreadable (relay died mid-payload); a missing receipt means the relay died before the spawn call, and an attested no-exec receipt means setup failed before exec — both clean up - sandboxStatusError distinguishes the attested no-exec case with a "did not run (setup failed before execution)" message (N4) - design docs record the retention scoping and the drain-window abort nuance (N2); PR body now states the bounded-drain trade-off (N1) Verified: core 204/204, tsc/eslint clean, and the relay probed against real processes — missing bwrap and exec failure now produce no-exec receipts (cleanup), an uncorrelated exit record retains, and the confirmed path is byte-identical. * fix(core): keep unknown sandbox receipts from attesting non-execution Address @wenshao's round-2 findings on PR #12067: - the no-exec attestation was being manufactured from absence of evidence at two sites: the finalizer coerced a receipt without payloadExitObserved into an explicit false, and the relay attested false for every `failed` cause although only a bwrap spawn error proves the payload never ran (a status-stream transport error or a 16KiB wire overflow can happen after the payload executed). Both now keep undefined as unknown: only a genuine spawn error or a wire with no bwrap exit-code record attests no-exec. - retention follows: clean up only on a positive no-exec attestation or a missing receipt file (the relay creates it O_EXCL before spawning bwrap, so absence proves pre-spawn death); unknown retains. The fail-safe direction for a retry-deciding caller is restored — an oversized or empty wire with the payload having run now retains and reads "may have run" instead of "did not run". - the no-exec message no longer points only at bubblewrap; it also covers a missing payload binary. - verify.mjs: the mount-setup-failure receipt assertion now expects the payloadExitObserved attestation (the one shipped deepEqual on the receipt object). - bwrap-status tests now discriminate all three attestation states strictly (absent vs false vs true) instead of applying the same coercion the code did. Verified: core 204/204, tsc/eslint clean, relay probed against real processes for six receipt shapes — spawn failure and child-pid-only wire attest false, mismatched exit record attests true, empty and oversized wires stay unattested, success control confirmed. * fix(core): harden bwrap execution foundation Address the remaining execution-foundation review findings with deterministic file-worker framing, separate worker diagnostics, scratch-root admission, CI unit coverage, and stronger Linux acceptance evidence. Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * test(core): Make bwrap verifier portable Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> --------- Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> |
||
|
|
907667bbd6
|
feat(core): add container execution for subagents (#11711)
* feat(core): add container execution for subagents * fix: address container execution review and CI failures * test(cli): account for relaunch environment provenance * test: include execution worker in package asset fixtures * fix(core): harden container execution boundaries and lifecycle * fix(core): isolate container cancellation and bound cleanup * fix(core): protect container roots and cache recovery * fix(core): report container startup failures and waits * fix(core): reject unsupported teams and arena before setup * fix(core): keep root git metadata masked across worker startup * fix(core): reclaim owned git mount points after worker cleanup * fix: preserve container policy and retry failed cleanup * ci: refresh PR head and rerun checks * fix(core): retain cleanup ownership after container startup failure * fix: fail closed on container policy refusals * fix(agent): close container execution review gaps |
||
|
|
77f1f93d23
|
fix(core): carry the PTY load reason on the call, not in module state (#11923)
Six follow-ups left on main by #11881, tracked in #11898. The reason a PTY load failed lived in a module-global that every getPty() call cleared on entry and only wrote after two `await import()` suspensions, so a second call in flight could drop it or report its own cause for someone else's failure. WebTerminalRegistry.create reads it after awaiting getPty(), and ShellExecutionService.execute calls the same function for every PTY-backed shell command - its abort path leaves a call in flight. Measured with the real registry and the real getPty, both backends made unresolvable: 50/50 kept the cause with no other caller, and 6/50, 9/50 and 5/50 lost it across three runs of a competing two-call chain, leaving the browser with the prefix-only message. loadPty() now returns { impl, loadError } so the reason travels on its own call; getPty() stays `(await loadPty()).impl`, still resolving null and still typed PtyImplementation for ShellExecutionService. The Bun arm recorded "the Bun runtime has no PTY backend", which the registry then prefixed with an independent claim that no backend was loadable. Bun can load @lydell/node-pty and is deliberately not asked to, so the reason now names the runtime switch instead of a backend the user would go and install. That arm still returns rather than throwing, which create-standalone-package.js relies on when it skips copyNodePtyAddon for --runtime bun. getPty.test.ts now pins the mechanism: per-call delivery across an interleaving call, the two-failure join, no reuse of an earlier reason, and the Bun reason. Before this, each of the three reason-recording statements could be deleted with getPty.test.ts, web-terminal-registry and shellExecutionService all green (3 files / 197 tests, measured). copyNodePtyAddon gains a filter that drops .pdb files. The win32-x64 prebuild package ships 10,780,672 B of them: 86% of its 12,485,696 B prebuild payload and ~2.05 MiB of the compressed win-x64 archive, and nothing reads them at runtime. install-script.test.js stages a fake prebuild holding a .pdb beside the .node, runs the real packaging script and asserts on the extracted archive. INSTALLATION_GUIDE.md said no @lydell/node-pty-linux-arm64 package is published. It is, at 1.2.0-beta.10 - the version this repo pins for its five siblings - and package-lock.json already resolves it; the gap is the missing pin, so the sentence now says that. The assertion beside it (`toContain('linux-arm64')`) also matched the release-artifact list and so could not fail; it now pins the reworded sentence. Patrol-Run: qwen-issue-patrol/jmu29p3id5x Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> |
||
|
|
10dafaf796
|
fix(standalone): bundle @lydell/node-pty prebuilds so the web terminal works (#11881)
* fix(standalone): bundle @lydell/node-pty prebuilds so the web terminal works The standalone archive declares six @lydell/node-pty* optionalDependencies but never ships them: esbuild keeps every node-pty specifier external, and create-standalone-package.js rebuilt lib/node_modules with only the audio-capture and clipboard addons. Every web terminal creation in a standalone install therefore failed with a bare "PTY not available". - create-standalone-package.js: add copyNodePtyAddon, copying the @lydell/node-pty wrapper plus the target's own platform prebuild package (derived from TARGET_PREBUILD_DIR) into lib/node_modules. Node runtime only (getPty() returns null under Bun), warn-and-degrade locally, with QWEN_STANDALONE_REQUIRE_NODE_PTY_PREBUILD=1 as the opt-in fatal gate. - build-standalone-release.js: stage the pinned @lydell/node-pty* packages alongside the clipboard ones in --native-modules-dir, since release packaging cross-builds all targets from a single host. The spec list derives from the root manifest so a future linux-arm64 pin is picked up automatically. - web-terminal-registry: split the two identical "PTY not available" arms into messages that say which failure occurred and on which platform/arch. Refs #11872 Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> Patrol-Run: qwen-issue-patrol/jmu1djouw4l * fix(core,standalone): name the real PTY load failure instead of claiming no module was found R1-1: the copyNodePtyAddon comment claimed release packaging sets QWEN_STANDALONE_REQUIRE_NODE_PTY_PREBUILD=1. Nothing does - release.yml exports only QWEN_STANDALONE_REQUIRE_AUDIO_CAPTURE_PREBUILD for the archive build - so the comment now says the gate is opt-in, that nothing sets it, and why it cannot be wired unconditionally while linux-arm64 has no pinned platform package. R1-2: getPty() collapses "absent" and "present but failed to load" into null, so the reachable arm asserted a cause that is false whenever the wrapper is installed but its prebuild cannot be dlopen'd (#11872's own signature-refused case). getPty() keeps RESOLVING null, because ShellExecutionService turns a rejection into a thrown error and loses the graceful childProcessFallback, but it now records the reasons and the registry reports them instead of claiming no backend module exists. R1-3: the installation guide still sent PTY users to --method npm; it now names the bundled @lydell/node-pty packages for the four targets that have a published prebuild, and the surviving linux-arm64 gap. The guide test pins both directions. R1-5: the --native-modules-dir help text now documents its second consumer and its different failure polarity. Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> Patrol-Run: qwen-pr-closeout/jmu1r4dew54 --------- Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> |
||
|
|
4ec9f63d0a
|
feat(core): add CodeModeOnly tool execution (#10607)
* feat(core): add CodeModeOnly tool execution * fix(core): preserve CodeModeOnly execution semantics * fix(core): drop the tool_search reminder in CodeModeOnly CodeModeOnly hides `tool_search` and binds every deferred tool — schema included — into the `exec` description, so progressive discovery has nothing left to do. The session prelude still announced those tools as "reachable via `tool_search`", pointing the model at a tool that is never declared and re-billing the text on every cached prefix. Worse, tools already callable as `tools.web_fetch(...)` looked gated behind a lookup step that does not exist. The subagent and fork-resume callers already opted out, but the main-session prelude sites did not, so the gate now lives where the prelude is built rather than in each caller. * chore: refresh settings schema * chore: refresh companion notices * fix: register exec tool metadata * fix(cli): localize exec tool display name * fix(core): stop offering ToolSearch lookups in CodeModeOnly CodeModeOnly hides tool_search and binds every deferred schema into the exec description, so text that tells the model to look a tool up describes a surface it cannot reach. Return an empty deferred summary from the registry itself - this also covers the fork-resume reminder that bypassed the earlier call-site gate - and point the image zoom hint at tools.zoom_image. * feat(core): teach the system prompt CodeModeOnly's tool surface In CodeModeOnly the model can only call exec, so the tool guidance and the worked examples described a surface it does not have: bare tool names it cannot call, an instruction to issue several tool calls in one response, and examples in a direct tool-call syntax that does not exist there. Give "Using Your Tools" a code-mode branch that routes every tool through tools.<name>, states which tools are direct controls instead, and replaces multi-call parallelism with batching inside one exec program. Swap the four model-family example sets for one shared exec set, since the syntax differences they exist for do not apply. The mechanics of exec itself stay in its tool description; the prompt carries only policy. * test: include code mode host in standalone fixture * fix(core): return code mode media as multimodal output * feat(core): support image tool results in code mode * fix(core): carry deferred tool schemas in the exec description CodeModeOnly hides tool_search and never surfaces a nested call as a history functionCall, so a signature collapsed to Record<string, unknown> could never be filled in later: parameter names were reachable only by guessing, or by reading them off validation errors one at a time. Deferred tools keep their registry state; only the generated signature gains the schema. * fix(node-repl): restore the bin exec bit after rebuild npm chmods dist/index.js when it links the bin at install time, but the build deletes that exact file and tsc re-emits it as 0644. After any rebuild node_modules/.bin/node-repl-mcp therefore points at a non-executable target and spawning it fails with EACCES (exit 126) before the shebang is ever read. OR the exec bits into the emitted mode instead of setting 0o755, so a restrictive umask is preserved rather than widened. * fix(cli): pin patched Ink version * feat(cli): add collapsible tool call details * fix(dev): use CLI tsconfig outside repository * fix(cli): preserve expanded tool details after completion * fix(cli): fail headless runs on model API errors * fix(core): expose shell timeout bounds in code mode * feat(core): add code mode timeout helpers * feat(cli): expose code mode in settings * fix(mcp): preserve structured results for model and exec consumers * fix(core): preserve code mode output and truncate inline * feat(core): port scoped context tools to code mode * fix(build): synchronize pnpm lockfile and capability docs * fix(core): recover from rejected Responses encrypted reasoning |
||
|
|
11e629b3a1
|
perf(export): split the transcript renderer's embedded CSS into a versioned asset (#11485)
* perf(export): split the transcript renderer's embedded CSS into a versioned asset The export renderer carried the web-shell component stylesheet as a ~2.3 MB string literal, so every reader parsed and compiled 4.1 MB of JS (56% of it dead CSS) before a transcript could render. Lift that literal out at export build time into a version-pinned, SRI-protected export-transcript-document.css served from unpkg and loaded via a nonce-bearing <link>, dropping the renderer JS to ~1.83 MB. The transform is an esbuild onLoad plugin in the web-templates export build that strips the injected CSS constant from web-shell's dist/transcript.js; web-shell source and runtime behavior are untouched. The document's fail-closed load-error path is extended to the stylesheet so a missing CSS asset fails the same way as a missing renderer. * fix(export): match the transcript CSS entry on Windows paths too esbuild hands plugin callbacks the platform-native absolute path, so the extract-transcript-css `onLoad` filter never matched on Windows: the callback did not run, `extractedTranscriptCss.css` stayed undefined, and the mandatory extraction guard below aborted the build. That build is not platform-gated — `scripts/prepare.js` runs it from `prepare`, so `npm ci` itself would fail on every Windows contributor and on the windows-latest legs of test_windows and desktop-release. Widen the separator to `[\\/]`, keeping the `transcript\.js$` tail so the barred `web-shell/dist/index.js` package root still does not match. The filter moves to transcript-css-entry.mjs because build.mjs is a top-level-await script with no harness — the same reason scripts/sdk-node-exporter-stub.js exists — so scripts/tests/transcript-css-entry-filter.test.js can pin both separators. Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> Patrol-Run: qwen-pr-closeout/jmtufhms2u4 * fix(export): latch a stylesheet failure ahead of the parser block The `<link id="transcript-stylesheet">` sits in `<head>` while the `window` error listener that catches its failure is registered by an inline script in `<body>`. Chromium parser-blocks that script on the pending stylesheet, so when the CSS failure settles first the error event is dispatched with no listener to receive it: nothing marks the render as failed, both renderComplete guards in document-main.tsx pass, React mounts the transcript without any of the component CSS, and the requestAnimationFrame stamps `data-render-complete="true"`. The reviewer measured this fail-open above roughly 2.1 MB of document HTML (272 of the 1,000 permitted blocks) for a 404, an SRI rejection, a truncated body and a destroyed socket alike, and fail-closed for a *late* failure — so size, not failure kind, decides it. Latch the failure in `<head>` before the `<link>` is parsed and act on the latch from the existing body IIFE. The head script only records: `showLoadError()` writes `document.body.dataset` and `#app`, neither of which exists while the parser is still in `<head>`. It carries `nonce="__EXPORT_NONCE__"` because the document CSP allows no inline script, which is safe — `formatters/html.ts:53` replaces every occurrence. The listener is capture-phase because resource error events do not bubble. Not the `link.sheet === null` variant: the reviewer measured `sheet` non-null for a 404, a truncated body and a destroyed socket, so it only detects SRI rejection. scripts/tests/export-transcript-document-template.test.js pins the position, the nonce, the capture phase and the record-only shape; all five cases go red against the unpatched template. The behavioural witness (real Chromium, large document, instant CSS abort) belongs to the playwright transcript gate, which is out of budget on this host. Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> Patrol-Run: qwen-pr-closeout/jmtufhms2u4 * fix(scripts): name the missing export renderer assets, pin the CSS gate The bundle copy became all-or-nothing over two artifacts but its `else` warning still named only the renderer, so the one new way to reach that branch — a tree built before the split, then `npm run bundle`d without rebuilding web-templates, which has the JS and no CSS — told the operator to go looking for a `export-transcript-document.js` that was sitting right there, and silently discarded it. List the paths that are actually absent, matching the sibling Web Shell warning twenty lines above. Stays warn-and-skip: prepare-package.js is the release gate. Also pin that release gate. Every fixture that reached `preparePackage` staged `dist/export-transcript-document.css` unconditionally, so deleting the new required-path entry left the whole test:scripts lane green; a release built with `npm ci --ignore-scripts` would then publish documents whose stylesheet 404s on unpkg for that version. `verifyBundleArtifacts` reports through console.error + process.exit(1) rather than a throw, so the new case stubs exit instead of copying the audio-capture sibling's `toThrow` idiom. Both cases were flip-checked: restoring the old warning text, and deleting the CSS line from prepare-package.js, each turn their case red. Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> Patrol-Run: qwen-pr-closeout/jmtufhms2u4 * fix(export): pin the stylesheet-failure id contract and sync the design docs The <head> latch, the body listener and the <link> each spell 'transcript-stylesheet' independently and nothing compared them, so renaming either listener's id left the whole suite green while the latch recorded nothing - reinstating the fail-open the latch was added to close. Derive the id from the <link> and assert both listeners compare against it. Verified red under both mutations: latch id -> 'transcript-renderer' (1 failed | 5 passed), and the mirror with the body listener's id wrong and the latch intact (same). Both design docs still specified the two shapes the previous round replaced: the forward-slash-only onLoad filter that never matches on Windows, and the body-listener-only fail-closed extension. Section 1 now quotes the shipped TRANSCRIPT_CSS_ENTRY_FILTER and names transcript-css-entry.mjs, section 2 describes the <head> latch (position, nonce, capture phase, record-only), section 3 names the module-level render guard, and "Files affected" lists the three omitted files. EN and zh-CN are updated in the same commit. Also correct the shape-guard comment in build.mjs: the document nonces every <style> created through document.createElement, so the CSP would not block an un-stripped duplicate, and a 367-byte regrowth stays inside both byte budgets. That throw is the only guard on the duplicate-injection path. Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> Patrol-Run: qwen-pr-closeout/jmtuo29vduf * fix(export): close out transcript CSS review comments * fix(export): tighten transcript CSS closeout Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> --------- Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> |
||
|
|
e09c461a92
|
fix(cli): restore OpenTUI banner, footer, and loading states; fix the OSS mirror flavor (#11437)
Some checks failed
Qwen Code CI / Integration Tests (no-AK, No Sandbox) (push) Blocked by required conditions
Qwen Code CI / Integration Tests (CLI, No Sandbox) (push) Blocked by required conditions
Qwen Code CI / Desktop Shell (ubuntu-22.04) (push) Blocked by required conditions
Qwen Code CI / Desktop Shell (windows-2022) (push) Blocked by required conditions
E2E Tests / E2E Test - macOS - shard 1/2 (push) Blocked by required conditions
E2E Tests / E2E Test - macOS - shard 2/2 (push) Blocked by required conditions
E2E Tests / Build for E2E (push) Waiting to run
E2E Tests / E2E Test (Linux) - sandbox:none - shard 1/1 (push) Blocked by required conditions
E2E Tests / E2E Interactive - OpenTUI renderer (bun) (push) Blocked by required conditions
E2E Tests / channel-plugin E2E (nightly) (push) Blocked by required conditions
pnpm Worktree Smoke / Install (macos-latest) (push) Waiting to run
pnpm Worktree Smoke / Install (ubuntu-latest) (push) Waiting to run
E2E Tests / E2E Test (Linux) - sandbox:docker - shard 1/1 (push) Blocked by required conditions
E2E Tests / cron-interactive E2E (nightly) (push) Blocked by required conditions
E2E Tests / web-shell Browser Regression (push) Waiting to run
npm cache producer / Save npm cache (push) Waiting to run
pnpm Worktree Smoke / Install (windows-latest) (push) Waiting to run
SDK Java / ubuntu-latest / Java 11 (push) Waiting to run
SDK Java / ubuntu-latest / Java 17 (push) Waiting to run
SDK Java / macos-latest / Java 21 (push) Waiting to run
SDK Java / ubuntu-latest / Java 21 (push) Waiting to run
SDK Java / windows-latest / Java 21 (push) Waiting to run
SDK Java / Real daemon E2E / Java 11 (push) Waiting to run
Update ECS Runner Qwen / Resolve version (push) Has been cancelled
Update ECS Runner Qwen / Update Qwen on ecs-update-hk-1 (push) Has been cancelled
Update ECS Runner Qwen / Update Qwen on ecs-update-hk-2 (push) Has been cancelled
Update ECS Runner Qwen / Update Qwen on ecs-update-hk-3 (push) Has been cancelled
Update ECS Runner Qwen / Update Qwen on ecs-update-hk-4 (push) Has been cancelled
Update ECS Runner Qwen / Update Qwen on ecs-update-hk-5 (push) Has been cancelled
Update ECS Runner Qwen / Report a stale fleet (push) Has been cancelled
* fix(cli): restore banner, footer, and loading states in the OpenTUI shell The batched OpenTUI migration restructured the original single-file backend into modules and dropped three user-visible pieces of the chrome along the way: the startup banner, the bottom status line, and the responding spinner. The OpenTUI renderer therefore booted into a screen that looked nothing like the ink one it was meant to replace. Rebuild all three as their own modules and mount them in the app shell, following the ink layout: banner at the top, loading indicator above the composer, status line at the bottom. Two defects carried over from the original implementation are fixed rather than copied. The context-usage label was missing its percent sign, and the approval-mode colour check compared against a label that never matched, so the auto-edit mode fell through to the default colour. The context-file count is intentionally not restored: the shell no longer tracks it and the current ink footer dropped it too. * fix(cli): tick the OpenTUI spinner at the rate ink uses The restored spinner ran at 120ms, carried over from the pre-batch implementation, while the ink responding spinner it mirrors runs the same frame set at 80ms and the existing OpenTUI compaction spinner does too. The same animation therefore looked visibly slower under one renderer. Name the interval and set it to the shared rate. The frame set itself is unchanged. * fix(release): sync the OSS mirror by what the tag shipped, not by a variable The workflow that mirrors a release to Aliyun OSS decided whether to expect the bun/OpenTUI preview archives from a repository variable. A repository variable describes the default branch, while the checkout and the downloaded assets come from the tag being synced, and the workflow can be re-dispatched for any tag. Re-syncing a tag cut before the preview flavor existed therefore asked that tag's own verify script for archives the release never shipped: v0.22.3 fails because its script does not know the flag at all, and v0.23.0 fails on a missing checksum entry. Derive the flag once from the archives actually downloaded and let all three consumers read it, so the mirror follows the release instead of the branch. Two related gaps in the same gate are closed here. The test covering it asserted only the variable name, so inverting the comparison and silently changing the flavor's default polarity stayed green; it now pins the operator. And the variable appeared in no documentation, so an operator had no way to learn that leaving it unset is what keeps the flavor off. * fix(cli): source the OpenTUI chrome from main's shared helpers The restored banner, footer, and responding indicator had grown private copies of mappings main already owns, so the two renderers could drift. Route the approval-mode label through formatApprovalModeName, extract the context-usage format and version-label rules into ink-free helpers both trees consume, and take the spinner frames and loading phrases from the shared constants and cycler. Also truncate the footer rows and the indicator phrase to the terminal width so a long branch, path, or phrase cannot wrap the chrome mid-turn, and read typed Config accessors in the banner instead of structural casts and a manual package.json read. |
||
|
|
078b924989
|
refactor(ci): extract release workflow scripts (#11165)
* refactor(ci): extract release workflow scripts
* test(ci): pin release-note labeling to the extracted step script
release.yml no longer inlines the auto-labeling body: the publish step now
just dispatches to run-release-step.sh, which owns the git rev-list
enumeration and the classify-release-notes.mjs call. The wiring test kept
asserting those four strings against the step's run block, so it failed on
the dispatcher path alone.
Read run-release-step.sh and assert the labeling body there, and assert the
dispatch from release.yml. The workflow-level guarantees (step name,
continue-on-error, GITHUB_TOKEN env, issues/pull-requests write permissions)
and the .github/release.yml exclusion entry are unchanged.
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
Patrol-Run: qwen-pr-conflict/jmtpmlcodmz
* test(ci): repoint release assertions at the extracted step script
The extraction moved the GitHub Release notes, standalone archive, and
release-failure autofix label logic out of .github/workflows/release.yml
into .github/scripts/run-release-step.sh, but three consumer suites still
pinned the moved text in the YAML, so `npm run test:scripts` was red and
the release workflow's fail-closed `quality` gate would refuse to publish.
Read the step script in ai-release-notes-workflow, install-script, and
qwen-autofix-workflow and assert the moved strings there with their new
lowercase locals (`notes_args`/`notes_file`), keeping on release.yml only
what genuinely stayed in it. Restore the "Safe to auto-apply approval"
rationale above both AUTOFIX_APPROVED_LABEL writes in the notify-failure
arm; it is the only recorded justification for the workflow granting
itself autonomous autofix approval.
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
Patrol-Run: qwen-pr-closeout/jmtq0vr74ni
* test(ci): derive the ECS wipe subject set from the runner, not the wipe
Selecting checkout jobs by "has a Restore workspace ownership step" made
the subject set a function of the property under test, so a job added to
the ecs-qwen-hk4-host pool with an actions/checkout and no wipe was
filtered out before any assertion ran. Key the exemption on the pool
marker instead, and pin that every pool-routed job carries the wipe
whether or not it checks out.
The hosted label cannot be the discriminator: every pool-routed runs-on
expression names 'ubuntu-latest' as its fallback branch.
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
Patrol-Run: qwen-pr-closeout/jmtq0vr74ni
* test(ci): re-scope the release-creation token pin to its own step
The workflow-wide toContain was satisfied by the second CI_BOT_PAT
occurrence on "Trigger ECS runner qwen update", so flipping the token on
"Create GitHub Release and Tag" to github.token left every lane green.
Restore the step scoping and the deleted rationale comment in release.yml.
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
Patrol-Run: qwen-pr-closeout/jmtqfvvmto2
* fix(ci): fail the release step runner closed on pipeline legs
run-release-step.sh set bare `set -e` while both sibling runners set
pipefail. In notify-failure a connection-level gh failure inside
`gh issue list ... | jq -c ...` leaves jq exiting 0 on empty input, so the
empty result took the create-a-new-issue branch and filed a duplicate
autofix/approved release-failure issue past all three reuse guards.
Pin the flag next to the existing sibling pin and add a behavioural row for
the notify-failure arm with an unreachable gh.
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
Patrol-Run: qwen-pr-closeout/jmtqfvvmto2
* test(ci): relocate the release timeout value-format contract
This PR condensed the nine-line release.yml lane comment to "values are
minutes" and relocated the format half nowhere: grep for the deleted claims
(expression error / free text / truthy / leading number) found no copy under
.github/, scripts/tests/ or docs/. Put the contract beside the assertions that
already pin the three tunable lanes' expressions, since release.yml is
size-pinned twice.
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
Patrol-Run: qwen-pr-closeout/jmtqfvvmto2
* docs(ci): scope the workflow_sha claim to the extracted helpers
The design doc said the trusted checkout "prevents an operator-selected
release ref from supplying code that receives release credentials". Two paths
at HEAD contradict that reading: resolve-version executes the ref's
scripts/get-release-version.js under the job token (run-release-step.sh:84),
and push-release-branch commits with core.hooksPath .husky (:116, :130) in a
step whose env carries CI_BOT_PAT (release.yml:659). Both predate this
extraction, so name them as residual paths rather than as prevented ones.
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
Patrol-Run: qwen-pr-closeout/jmtqfvvmto2
* fix(ci): format the release-version test to satisfy the Prettier gate
`Lint & Static` failed at the `Run Prettier` step: a continuation line in
the `assert-unreleased` format-gate test carried four extra spaces.
* fix(ci): exclude nested .git dirs from the docker build context
The extraction added a `.release-workflow/` checkout to `integration_docker`
between the sandbox build's reset and the build itself, and `.dockerignore`
listed `.git` only in its root-anchored form. A depth-1 sparse checkout of
the pinned ref is 1.1M of worktree over 51M of git objects, so every
uncached sandbox image baked those objects into a discarded builder layer on
the shared pool this job is routed to. `node_modules` and `dist` already
carry both forms.
* fix(release): close four gaps the script extraction left behind
R1-15: the push-time guard returned exit 2 for a malformed version, and
run-release-step.sh treats 2 as a transient probe failure — so a refusal
that can never succeed was retried three times over ~45s and logged as a
connectivity problem. Malformed versions now exit 4, which the retry loop
breaks on immediately and which is not the exit-3 version_refusal marker.
R1-16: the extraction moved the guard behind `.release-workflow/` so the
decision comes from the workflow-pinned SHA, but left a working
`--assert-unreleased` dispatch in the ref-supplied get-release-version.js.
A future step using that spelling would load the selected ref's guard.
Removed it, and re-pointed its five tests at the real entry point.
R1-13: assert-release-version.mjs ships alone under release.yml's
sparse-checkout set, so it cannot import release-helpers.js — the
duplicated isExpectedMissingGitHubRelease is deliberate. Documented that
at both sites and pinned the two bodies identical, so widening only the
guard's copy (which would read a rate-limited probe as "release absent")
goes red.
R1-6: restored the notify-failure arm's rationale, matching the condensed
comments the other five arms kept: the exact-title re-check that stops a
v0.18.1 failure reusing a v0.18.10 issue, the bot-author preference, and
the re-query that keeps autofix off a maintainer-owned issue.
* fix(release): re-pin the trusted runner before every step that runs it
R1-10: `Build Bundle and Prepare Package`, `Build Standalone Archives` and
`Verify Standalone Archives` executed `.release-workflow/.../run-release-step.sh`
from a tree that selected-ref npm code had already run over — `build-package`
for the first two, and `npm publish`'s own lifecycle scripts for the third,
inside the job that holds `id-token: 'write'`. At the merge base these were
inline `run:` bodies sourced from the workflow file, immune to anything
written into the working tree, so the exposure is introduced by the
extraction. Each now gets the reset-and-re-checkout pair the design doc
already promises for credential-bearing steps.
The guarding test hand-listed six protected step names, so it could not fail
for the three it omitted. It now sweeps every step whose `run` mentions
`.release-workflow/` (17 today) and separately pins that each re-checkout is
preceded by a reset.
R1-5: nothing tied the publish allowlist to the guard's `PUBLISHED_PACKAGES`
except a comment pointing at publish steps this PR deleted from release.yml.
A channel added to the loop but not the array would ship unprobed, so a retry
of a partial release reports "unreleased" and force-pushes over the tip the
shipped package anchors to. The two sets are now pinned against each other,
and the stale comment points at the real pin.
The three inserted step pairs grow release.yml by 294 bytes (well inside the
4096-byte allowance); the ratchet baseline and the PR description move with
it rather than letting the recorded number drift.
* test(release): pin the flags, arms and modes the extraction left unwitnessed
R1-19: the arm's only executable probe stubbed npm with a script that
recorded `$PWD` and discarded every argument, so deleting `--tag=${NPM_TAG}`
stayed green while `npm publish` would fall back to the `latest` dist-tag —
handing the 21:00 UTC nightly to every end-user install and to the ECS fleet
updater. The stub now records the argv and each publish is checked for
`--access public` and the dist-tag.
R2-3: `resolve-version` was the one arm no test executed or text-pinned;
flipping `--type=preview` to `--type=stable` survived all 2233 scripts tests,
while at runtime the stable path ignores `preview_version_override` and would
publish an operator's manual preview as a stable release. Two execution tests
now cover the preview mapping and the malformed-version rejection; both were
run against the real arm before pushing.
R1-18: release.yml invokes these scripts by bare path, so the executable bit
is load-bearing, but every test invokes them as `bash <script>`, which
ignores the mode — and the workflow triggers only on schedule/dispatch, so no
pull-request lane runs the bare-path form. A mode-normalizing commit would
keep the suite green and kill `set-flags` with exit 126. The recorded git
mode is now pinned for all three scripts.
* test(release): pin the trusted prefix, the fork gate and the real version formats
R1-3: every arm pin elsewhere is a substring match that a bare
`.github/scripts/run-release-step.sh` invocation would satisfy just as well,
so nothing pinned the mechanism the extraction exists for. All 17 step
invocations are now required to carry the `.release-workflow/` prefix and
forbidden from naming the release-ref copy.
R1-9: `PUBLISH_AUDIO_CAPTURE` replaced a deleted step-level
`if: github.repository == 'QwenLM/qwen-code'` gate and, unlike its
`PUBLISH_EXTERNAL_CONTEXT_MEM0` sibling, had neither its gate expression nor
its true branch pinned — a fork running this workflow would publish
@qwen-code/audio-capture. Both halves are pinned now.
R1-14: the format gate is the guard's only genuinely new behaviour and its
accept path was exercised solely with '1.2.3', while the two scheduled
releases produce nightly and preview strings. Both formats are now asserted,
so tightening the pattern fails here rather than at 21:00 UTC.
* fix(release): keep failure reporting alive when the trusted runner is not
R1-11: `notify_failure` gained a checkout of `github.workflow_sha` as its
first step, and its whole body now lives in a shell script. At base the job
had no checkout at all and the notifier was inline, so the job whose only
purpose is reporting every other job's failure acquired two ways to fail
silently: a degraded git backend takes out the checkout, and a syntax error
or dropped exec bit in run-release-step.sh takes out every arm including
notify-failure. In both cases `Create Issue on Failure` carried the default
`if: success()` and was skipped — no issue, no autofix label, no dispatch,
and the scheduled autofix fallback scans issues, so nothing recovered it.
Rather than moving 105 lines of notifier back into the workflow — which the
orchestration guard in this PR forbids at 12 run-lines per step — the primary
path keeps the extraction and stops being load-bearing: it runs under
`always()`, absorbs its own failure, and a five-line inline fallback files a
plain issue whenever it did not succeed. The fallback depends on neither the
checkout nor the script, does no reuse, labelling or dispatch, and accepts a
duplicate issue as the cost of never going silent.
The workflow's line ceiling moves 800 -> 830 for those lines, with the reason
recorded at the assertion; the per-step run cap that keeps logic out of the
YAML is unchanged and still holds. Ratchet baseline and the PR description
move with the file.
* style(release): apply the pinned Prettier to the fallback notifier
Prettier 3.6.1 normalizes the quoting on the new `if:` and drops a
trailing space; the ratchet baseline follows the two-byte change.
* docs(release): name exit 4 where the guard's exit codes are described
Adding the malformed-version code left two descriptions behind: the retry
loop had no statement of the contract at all, and the test comment beside it
still said exit 0 and exit 3 were the only decisive outcomes.
* fix(release): avoid duplicate fallback failure issues
---------
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
Co-authored-by: yiliang114 <jinjing.zzj@gmail.com>
|
||
|
|
aab0258857
|
fix(test): put the scripts suite's quiet-host budgets on its own knob (#11098) (#11106)
Release run 33957952281 lost Quality Checks (Scripts) to two budgets that were measured on a quiet machine and met a contended one: - install-script.test.js capped itself at 30s with vi.setConfig, overriding the 90s floor scripts/tests/vitest.config.ts sets for exactly this reason (#10870). A standalone-packaging case that costs 3s idle timed out at exactly 30000ms. The file's two per-test 30s arguments and its 15s/60s describe ceilings were the same quiet-host figure, so they go too. - qwen-autofix-workflow.test.js bounded its deferred-findings subprocess at 30s. That case costs 0.9s idle; killed mid-run, the stub `gh` recording truncates, so the timeout reported itself as a content mismatch on the first recorded call. The file's four hung-runner bounds now ride QWEN_SCRIPTS_TEST_TIMEOUT_MS. Its 3s/2s bounds pair with a stubbed QWEN_TIMEOUT_MS and are fast-fail guards, so they stay. Both signatures were reproduced locally by shrinking each budget, then reverted. A witness in unit-vitest-configs.test.ts fails if a file in the suite caps the floor again; mutation-probed both ways. The same run also lost Quality Checks (Static) to its 30-minute job timeout, and the re-run on current main lost Static and Build the same way. That is release-workflow capacity rather than test code, so it is escalated on the issue instead of changed here. Co-authored-by: qwen-code-dev-bot <qwen-code-dev-bot@users.noreply.github.com> |
||
|
|
077c57d200
|
refactor!: retire @qwen-code/webui (#9812)
* feat(transcript): add cross-host document export pipeline Establish a shared transcript model and document-mode projection so Web Shell, VS Code, and HTML export can consume the same stable conversation semantics without changing interactive rendering. - Preserve daemon and ACP segment identity across replay and normalization - Add export-safe previews and a versioned transcript document builder - Add document-mode Web Shell rendering with bounded Mermaid processing - Lock direct-daemon and ACP behavior with contract fixtures - Cover render and export equivalence in integration tests * feat(transcript): wire real VS Code and HTML export consumers Move transcript prevalidation onto real product paths while preserving the legacy VS Code timeline as the default fallback. - Add version-bound document HTML with strict CSP and schema checks - Add opt-in ACP projection with stable source identity - Reuse product export code across hosts and the integration runner - Remove test-only production probes and consolidate shared validation Note: Browser, host-action, VSIX, and packaging gates remain pending. * build(deps): sync transcript workspace dependencies Keep the npm lockfile aligned with the VS Code and HTML export package manifests added by the transcript consumer migration. - Lock the VS Code Web Shell workspace dependency - Lock Web Templates SDK, Web Shell, and React build dependencies * feat(vscode-ide-companion): reuse WebShell transcript UI behind experimental flag Bridge ACP session/update notifications into the shared SDK daemon transcript reducer and render the result with the WebShell transcript component, gated on qwen-code.experimental.webShellTranscript (default off). The WebShell renderer and its heavy transitive dependencies (echarts, mermaid, shiki, codemirror, katex) are lazily loaded via esbuild code splitting, so the default configuration keeps the ~700KB webview bundle unchanged. * fix(vscode-ide-companion): grant wasm-unsafe-eval for shiki WASM when WebShell transcript enabled * fix(transcript): harden export and identity paths Resolve review findings across document export and the VS Code ACP timeline while preserving default interactive and readonly semantics. - Preserve stable text and non-text identity across live and replay - Harden export projection, budgets, URL handling, CSP, and nonces - Make document rendering complete, inert, and browser-validated - Keep VS Code transcript scope, theme, copy, and flags reactive - Restore fixture, schema, hash, and compatibility contract locks Note: The overall gate remains failed pending VSIX, host-action, and packaged-artifact evidence. * feat(vscode-ide-companion): adopt WebShell transcript as default timeline Drop the experimental flag and the legacy MessageList renderer. The companion timeline now always renders through the shared WebShell transcript component, fed by ACP session/update notifications via the SDK daemon transcript reducer (lazy loaded through esbuild code splitting). The flag-gated wiring is removed: the qwen-code.experimental.webShellTranscript setting, the conditional CSP/body attribute in WebViewContent, and the legacy MessageList path in App.tsx (~850 lines). The webview CSP now grants wasm-unsafe-eval unconditionally for Shiki's Oniguruma WASM. * fix(vscode-ide-companion): reset WebShell transcript state on session switch The experimental useAcpTranscript hook only consumed transcriptUpdate messages, so its reducer state survived session boundaries. When the extension switched sessions it kept the webview mounted and replayed the newly-selected session through ACP, causing the previous session's blocks to merge with the new replay (e.g. user text "alpha" from session A leaked into session B as "alphabeta"). Reset both the reducer state and the rendered blocks on the same boundaries the legacy message flow uses: qwenSessionSwitched (sent before the ACP replay of the selected session) and conversationCleared (new session). Adds a regression test that replays two sessions with a switch between them. * fix(vscode-ide-companion): harden WebShell transcript session boundaries - reset the transcript on `conversationLoaded` too, closing the same cross-session leak the previous commit fixed for `qwenSessionSwitched` and `conversationCleared` (agent reconnect posts only this boundary) - track the active session id and drop late `transcriptUpdate` frames whose `sessionId` no longer matches, so a previous session's trailing frames cannot contaminate the next session's timeline - seed the transcript from cached messages carried by `qwenSessionSwitched` so offline restores and load-failure fallbacks render their history instead of a blank timeline - dispatch `assistant.done` on `streamEnd`/`sessionLoadComplete` so the final assistant/thought block of a turn (or history replay) does not stay `streaming: true` forever * fix(transcript): harden identity and document export Close the latest review findings across transcript identity, VS Code rehydration, and the HTML export security boundary. - Terminate discrete ACP segments and bind automatic turn provenance - Reset VS Code transcript scopes across replay and reconnect lifecycles - Align Markdown sanitization and envelope budgets with document rendering - Run browser gates with Chromium and complete third-party notices * fix(vscode-ide-companion): adopt live ACP session id after load-failure fallback * fix(vscode-ide-companion): echo user prompt into WebShell transcript * fix(vscode-ide-companion): keep WebShell transcript expanded and clear of the composer * fix(vscode-ide-companion): surface local error and interrupt notices in the transcript area * fix(vscode-ide-companion): restore file-link opening from the WebShell transcript * fix(vscode-ide-companion): restore contributed copy commands for the WebShell transcript * fix(vscode-ide-companion): add localOnly marker to TextMessage state type * fix(vscode-ide-companion): restore /insight progress card and report link in the transcript UI * fix(vscode-ide-companion): finalize in-flight tools on timeout and pin session-switch seeding guard Map streamEnd reasons timeout/session_expired onto the reducer's error reason so abandoned mid-tool turns no longer spin forever (ceuI). Add qwenSessionSwitched cases with no messages field and an empty cache array; the no-messages case fails when the seeding guard is forced true, pinning its false side (ceuN). * fix(vscode-ide-companion): remove unreachable editMessage backend and dead submit options The user-message edit/rewind UI was dropped in the WebShell-transcript migration, leaving editTargetTurnIndex/onSubmitted options in useMessageSubmit and the full editMessage/rewind flow in SessionMessageHandler unreachable. Remove the dead options, the editMessage dispatch case, the rewind/snapshot flow with its recovery branches, and their tests (R1-8 direction b). * fix(vscode-ide-companion): drop write-only loadingMessage bookkeeping The waiting-message renderer was removed with the WebShell transcript migration and the user prompt is echoed into the timeline at send time ( |
||
|
|
d7fbf305cc
|
feat(release): add gated bun/OpenTUI preview flavor to standalone releases (#10814)
* feat(release): add gated bun/OpenTUI preview flavor to standalone releases Phase 2 validation needs a real archive that boots the OpenTUI renderer, so the standalone pipeline gains an opt-in second flavor instead of replacing the classic Node.js one: - create-standalone-package.js derives archive names from a shared standaloneArchiveName() helper; bun archives carry the -opentui-preview suffix, and bun shims default QWEN_TUI_RENDERER to opentui (explicit user overrides still win). - build-standalone-release.js accepts --include-opentui-preview to package both flavors in one run, with per-flavor publisher checksums and a flavor-aware output assertion. - verify-installation-release.js accepts the same flag so a gated release directory/URL and the OSS upload list both expect the preview archives. - release.yml and sync-release-to-oss.yml thread the flag behind a vars.OPENTUI_PREVIEW_RELEASE_ENABLED gate (off by default, byte-identical behavior when unset); .size-baseline re-pinned in the same PR. - Also fix a latent crash in copyOpenTuiAddon's warn-only degradation path, which asserted against a lib/node_modules directory it never created. * feat(release): add a thin installer for the gated opentui-preview archives The preview flavor is not reachable through the hosted installer chain, which only packages assets for stable releases, so testers had to download and unpack the archive by hand. This adds a scratch-directory installer pair that resolves the platform target, verifies the release SHA256SUMS, and unpacks into ~/.qwen-preview without touching PATH or an existing classic installation. A local archive can be installed directly so the path is testable before a gated release exists. |
||
|
|
60c338f144
|
fix(install): avoid Get-FileHash for Windows checksums (#9112)
* fix(install): avoid Get-FileHash for Windows checksums * refactor(install): simplify Windows checksum verification * test(install): require checksum resource disposal |
||
|
|
c73b5ed887
|
ci: run Windows merge queue tests on ECS (#8386)
* ci: run Windows merge queue tests on ECS
* test(channels): skip POSIX mode assertion on Windows
* ci: expose Git Bash on Windows ECS runner
* ci: scope Windows ECS tuning to self-hosted and restore full test:ci
Review feedback on the Windows ECS routing: dropping test:scripts removed the only Windows execution of 9 Windows-only install-script tests, and the job-wide PowerShell default plus narrowed test command changed the kill-switch fallback away from the known-good hosted configuration.
Restore the full npm run test:ci on both paths (bash is available: pre-installed on hosted runners, exposed via the Git Bash PATH entry on ECS) and gate every ECS-specific adjustment on runner.environment: the PowerShell setup step (now also skip_ci-guarded), TEMP/TMP/LC_ALL env writes, and the Linux-style Node setup split that fails with an actionable error naming MAINTAINER_ECS_RUNNER_DISABLED. The windows-2022 fallback is byte-for-byte the pre-ECS job again.
* test: make Windows CI suites platform-aware
* ci: add stale-checkout guard to Windows ECS test job
* test(core): compare canonical directory identity
* ci: add fork guard and review follow-ups to Windows ECS job
* test(core): exercise real directory identity change
* test(core): wait for killed lease process exit
* test(scripts): avoid cmd echo trailing spaces
* test(scripts): use unambiguous cmd echo syntax
* test(cli): avoid sidecar I/O in truncation test
* test: fix Windows script-suite gaps and unify platform gating
- Fix missed trailing-space cmd stub in package-scripts.test.js so the
'runs prepare steps in order' assertion passes on Windows.
- Add qwen-pr-review-workflow.test.js and pr-self-report-label.test.js to
the win32 exclude list (both test Linux-only workflows and are not
portable to Windows).
- Replace local itPosix/describeOnNonWindows consts with vitest's built-in
it.skipIf/it.runIf/describe.skipIf, matching the codebase idiom.
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
* test(scripts): restore Windows workflow coverage
* test(scripts): re-exclude Windows-incompatible workflow tests on win32
Re-add pr-self-report-label.test.js and qwen-pr-review-workflow.test.js to
the win32 exclude list. Both fail on a Windows runner for reasons the code
still carries: qwen-pr-review-workflow.test.js calls execFileSync('mkdir'),
which has no executable to resolve there, and pr-self-report-label.test.js
joins PATH with ':', corrupting the ';'-separated Windows PATH so its gh
stub never resolves. Excluding them restores a green Windows gate; Linux CI
remains their authoritative coverage. Document the criterion inline.
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
* ci: extract checkout-head guard into composite action, pin Windows gate (#8386)
Address review round 2: move the stale-checkout guard shared by the four CI gates into .github/actions/verify-checkout-head so the copies cannot drift, pin the Windows gate kill-switch routing and guard wiring in the script tests, re-enable lint.test.js on Windows via separator normalization and a lazy linter setup in scripts/lint.js, unify the platform skips on it.skipIf(process.platform === 'win32'), and document the queued-run behavior of the ECS kill switch.
* ci: fail fast in Windows gate environment setup (#8386)
* ci: dedupe self-hosted runner steps into actions, pin gate mutations (#8386)
* fix(ci): checkout before repository-local actions in Windows gates (#8386)
* fix(ci): configure Windows runner before bash guard
* test(ci): pin remaining shared-action wiring in script tests (#8386)
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
* fix(ci): skip zip-dependent packaging tests when zip is missing (#8386)
* fix(ci): validate full Windows smoke path
* fix(ci): match Windows smoke shell to gate and drop dead runs-on guard (#8386)
* fix(ci): make SIGTERM escalation test Windows-aware and tighten pins (#8386)
The CDP acceptance test asserted a POSIX-only SIGKILL escalation, which
fails deterministically on Windows where kill('SIGTERM') terminates the
child directly — blocking the Windows merge-queue gate. Assert the
platform-appropriate signal instead.
Also address review suggestions: probe `unzip` alongside `zip`, pin the
integration_cli guard's missing step-level `if:`, stop getWorkflowStep
at unnamed steps, pin install-script.test.js out of the win32 excludes,
add the stale-checkout guard to windows-runner-smoke.yml, pin the
Node preflight warning branch and the guard reject path contiguously,
and extend the smoke shell-parity loop to the npm cache step.
* docs(ci): clarify Windows runner trust boundary
---------
Co-authored-by: qwen-code-dev-bot <qwen-code-dev@service.alibaba.com>
Co-authored-by: qwen-code-ci-bot <qwen-code-ci-bot@users.noreply.github.com>
Co-authored-by: qwen-code-dev-bot <qwen-code-dev-bot@users.noreply.github.com>
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: qwen-code-ci-bot <qwen-code-ci@service.alibaba.com>
|
||
|
|
d7e2892a7c
|
fix(cli): avoid updating active CLI processes (#6874)
* fix(cli): avoid updating active processes * fix(cli): close update relaunch gaps * test(cli): fix standalone update source path * fix(cli): reset deferred update per relaunch |
||
|
|
b19ebd8fc6
|
fix(packaging): bundle clipboard addon in standalone builds (#6708) | ||
|
|
c90e6e7ba4
|
feat(channels): Add channel agent bridge abstraction (#5978)
* feat(channels): add channel agent bridge abstraction Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * fix(channels): handle bridge session lifecycle cleanup Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * fix(channels): close bridge lifecycle review gaps Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * codex: address PR review feedback (#5978) Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * codex: address PR review feedback (#5978) Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * fix: address channel bridge review feedback Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * codex: address PR review feedback (#5978) Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * codex: address PR review feedback (#5978) Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> --------- Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> |
||
|
|
aa8f9bb993
|
fix(standalone): Route serve shim through cli-entry (#5977)
* fix(standalone): route serve shim through cli-entry Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * codex: address PR review feedback (#5977) Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> --------- Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> |
||
|
|
7696d9a7d9
|
ci: route in-repo PRs' Linux test to self-hosted runner (#5620)
* ci: route in-repo PRs' Linux test to self-hosted runner Send the required Linux Test job to the self-hosted ECS runner for PRs whose head branch lives in this repo (which implies the author had write access), while forks and push/merge_group runs stay on GitHub-hosted runners. This lets maintainer changes skip the shared hosted Linux queue without ever running untrusted fork code on self-hosted infrastructure. The MAINTAINER_ECS_RUNNER_DISABLED repo variable forces everything back to hosted if the ECS runner is unavailable. * ci: reuse pre-installed Node on self-hosted runners, route Lint to ECS The self-hosted ECS runners cannot reliably download the Node tarball from nodejs.org through the egress proxy (actions/setup-node aborts mid-download), which failed the Test job routed there. On self-hosted runners, reuse the machine's pre-installed Node instead of re-downloading it every run; hosted runners keep using actions/setup-node. Also route the Lint job to ECS for in-repo PRs — scripts/lint.js already skips installing actionlint/shellcheck/yamllint when they are on PATH, so no lint.js change is needed. * ci: trim verbose runner-routing comments * ci: run classify_pr gate on ECS for in-repo PRs * ci: quote classify_pr/lint runs-on expressions * ci: keep Lint on hosted runners (ECS proxy truncates linter downloads) * ci: route Lint and review/triage gate jobs to self-hosted runner Lint goes back to ECS (linters are now pre-installed on the runners, so scripts/lint.js skips downloading them). The pr-review gate jobs (authorize, review-config, delay-automatic-review, ack-review-request) and the triage authorize gate also move to ECS so the ECS heavy jobs (review-pr, tmux-testing) are no longer bottlenecked by the shared hosted queue. All respect the MAINTAINER_ECS_RUNNER_DISABLED kill-switch. |
||
|
|
8809c16b57
|
fix(voice): bundle native audio addon into standalone archives (#5628)
Standalone archives shipped only curated dist/ entries, so the esbuild-external @qwen-code/audio-capture addon couldn't be resolved at runtime — streaming voice was unavailable in standalone installs (batch only, and only with SoX on PATH). create-standalone-package.js now bundles the addon into lib/node_modules (where the bundled lib/cli.js resolves bare specifiers): the trimmed package.json (install hook removed; type/exports kept for ESM resolution) + dist + only this target's prebuild (win-x64 -> win32-x64) + its zero-dep runtime dependency node-gyp-build. Targets without a matching prebuild (e.g. local builds) ship without it and degrade to SoX/arecord as before (warns, doesn't fail). The release pipeline already downloads prebuilds before packaging. Refs: #5502, #5590. Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> |
||
|
|
e88356c6b7
|
ci(release): auto-publish VSCode companion after releases (#5572) | ||
|
|
ac4d100e1a
|
fix(installer): print shell reload hint when new qwen is not picked up (#4960)
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
* fix(installer): print shell reload hint when new qwen is not picked up The installer updates the shell rc file, but the invoking shell keeps its original PATH, so right after install `qwen` can still resolve to an older install (e.g. a previous npm global version) with no indication of why. Capture the PATH inherited from the invoking shell and, when the new install is not reachable from it (install dir missing from PATH, or another qwen executable shadows it), print the exact reload command in the start steps and warn about the shadowing executables. * fix(installer): derive reload hint from the rc file actually written maybe_update_shell_path can fall back to ~/.bash_profile (or create ~/.bashrc), but the summary re-derived the rc name from $SHELL alone and always claimed ~/.bashrc for bash. Record the file the PATH block was written to in PATH_UPDATE_RC_FILE and build both the success message and the source hint from it, so the two can no longer drift apart. Also drop the non-hermetic shadow-warning assertion from the reload-hint test: PRE_INSTALL_QWENS scans well-known absolute paths regardless of PATH, so the warning may legitimately fire on hosts with qwen installed. Add a regression test for the macOS-style .bash_profile-only setup. |
||
|
|
968a0d1f03
|
fix(installer): auto-detect SYSTEM account and default PATH scope to machine (#4903)
* fix(installer): auto-detect SYSTEM account and default PATH scope to machine When the Windows standalone installer runs as the SYSTEM account (SID S-1-5-18), which is common for ECS Workbench SSM, WinRM, and scheduled tasks, the default --path-scope is now 'machine' instead of 'user'. Previously, persisting PATH to the SYSTEM user's HKCU hive had no effect on new sessions spawned by the SSM agent service, because the agent inherits its environment at service start time and never re-reads HKCU. Writing to the Machine PATH (HKLM) ensures new sessions pick up the qwen shim immediately. Also adds: - --repair-path flag to fix PATH for an existing install without reinstalling - --path-scope user|machine CLI option and QWEN_INSTALL_PATH_SCOPE env var - Uninstaller now cleans both User and Machine PATH entries - CI validation step for hosted installation assets Resolves #4901 * test(installer): add Windows self-hosted qwen smoke * fix(installer): address Windows PATH review feedback * refactor(installer): remove redundant YAML validation, deduplicate test fixtures - Remove windows-self-hosted-qwen-smoke.yml (operational tool, not part of fix) - Revert sync-release-to-oss.yml validate step (redundant with JS behavior guards) - Extract duplicated test fixture strings into shared constants - Pass normalized path to Remove-PathEntry to avoid double Get-NormalizedPath - Fix stale comment referencing "user PATH" when scope is now configurable * chore: drop unrelated dev.test.js changes from installer PR |
||
|
|
0def5f77ff
|
fix(installer): correct 'for more info' URL to GitHub repo instead of docs site (#4916)
Co-authored-by: tanzhenxin <tanzhenxing1987@gmail.com> |
||
|
|
aef3e704b4
|
feat(installer): verify release assets + switch public docs to standalone entrypoint (#3855)
* fix(installer): tighten verifier base-url + clarify test helper
Three small refinements from the second review pass:
- normalizeHttpsBaseUrl rejects everything except https, since real release
URLs are always HTTPS. Accepting http previously would let an operator
silently target a stale or attacker-controlled mirror.
- Drop EXPECTED_RELEASE_ASSET_NAMES from the public exports; it was only
used internally for the verification log line.
- Rename the test helper standaloneChecksumContent to
placeholderChecksumContent and document that the hashes in its output are
placeholders — the remote verifier does not download archives or compare
hashes, it only validates that SHA256SUMS lists the expected names and
that each archive URL is reachable.
The non-https rejection test now also covers `http://` in addition to the
existing `file://` case.
* style(installer): align installer completion output
* revert(installer): keep hosted installer output unchanged
* fix(installer): address release validation review feedback
* docs: switch public install commands to standalone hosted entrypoint
Update README, quickstart, and overview to point at the new
install-qwen-standalone.sh / install-qwen-standalone.ps1 hosted URLs.
Add standalone uninstall instructions to Uninstall.md. Remove the
staged-rollout note from INSTALLATION_GUIDE.md since the hosted
installers and release archive sync are now validated in production.
* docs: clarify pull request size guidance
* fix(installation): harden standalone release validation
* fix(installation): redact release verifier credentials
* feat(installer): add visual branding to Linux/macOS install script
Add brand-colored ASCII art logo, custom download progress bar with
Unicode block characters, and step indicators [1/3] [2/3] [3/3] to
match the quality of competing CLI installers.
* fix(test): update stale assertion after guide text was removed
The text "Public installation documentation" was removed in
|
||
|
|
5493888c15
|
ci: split Aliyun OSS sync into a separate post-release workflow (#4492)
* ci: split Aliyun OSS sync into a separate post-release workflow The OSS upload and verification steps were adding significant time to the release workflow's critical path. Move them into a new `sync-release-to-oss.yml` workflow that triggers on `release: published`, running asynchronously after the release completes. Key changes: - Extract all OSS steps (ossutil install, credential config, asset upload, verification, hosted installation sync, latest VERSION pointer) into `sync-release-to-oss.yml` - Switch `gh release create` to use CI_BOT_PAT so the release event can trigger the new downstream workflow (GITHUB_TOKEN events don't trigger other workflows) - Add `workflow_dispatch` input for manual re-runs on failure - New workflow downloads release assets from GitHub Release instead of rebuilding them This decouples publishing from CDN distribution: the release finishes as soon as npm publish + GitHub Release are done, and China CDN sync happens in parallel without blocking. * fix(test): update install-script test to check sync-release-to-oss.yml The test asserts OSS sync steps exist in the workflow. Now that these steps live in sync-release-to-oss.yml instead of release.yml, update the test to read from the correct file and add assertions that release.yml no longer contains OSS logic. * fix(ci): address review feedback for OSS sync split - Add 'Verify Standalone Archives' step before gh release create in release.yml as a pre-publish safety gate (wenshao) - Add concurrency group to sync-release-to-oss.yml to prevent race conditions when multiple releases publish close together (wenshao) - Update test to assert verify step exists in release.yml * chore: add comment explaining CI_BOT_PAT requirement [skip ci] |
||
|
|
d59c9e7b77
|
feat(installer): add standalone hosted install and uninstall flow (#3828)
* feat(installer): add standalone archive installation * fix(installer): harden standalone archive installs * fix(installer): address standalone review findings * chore(installer): clarify review followups * fix(installer): stabilize standalone script checks * chore(installer): remove internal planning docs * chore(installer): simplify standalone release review fixes * test(installer): add Windows batch install smoke * test(installer): fix Windows batch smoke quoting * test(installer): preserve Windows cmd quotes * fix(installer): use robust Windows checksum hashing * ci: narrow installer debug matrix * fix(installer): address standalone review hardening * fix(installer): avoid Windows validation parse errors * fix(installer): simplify Windows option validation * fix(installer): harden standalone review fixes * feat(installer): publish release installer assets * fix(installer): address release asset review feedback * fix(installer): avoid prerelease installer asset links * test(installer): isolate standalone dist fixture * feat(installer): add hosted install release alias * chore: no changes - code review requested Agent-Logs-Url: https://github.com/QwenLM/qwen-code/sessions/38467aec-15b9-4b76-9139-0b2cfe40477a * fix(installer): pin versioned installer assets * fix: parallelize Node.js binary downloads in standalone release build Use Promise.all instead of sequential for...of+await for the 5 independent Node.js runtime downloads, reducing CI release build time by ~4-5x. Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * fix(installer): address release asset review followups * refactor(installer): share release CLI parsing * fix(installer): address release asset review followups - sh: reject CR/LF in archive entry names before the literal `..` glob so a `..\r` entry cannot bypass path validation. - bat: prefer Tls12+Tls13 in PowerShell helpers, fall back to Tls12 alone on older .NET Framework where the Tls13 enum is missing. - bat: document the implicit `:ValidateOptions` dependency next to the qwen.cmd wrapper writer so loosening the validator stays a conscious choice. - build-standalone-release: surface the `xz-utils` host requirement for Linux Node downloads in `--help`. - release-script-utils: support `--key=value` form in `parseCliArgs`. - tests: cover the new CRLF message, TLS string, and `--key=value` parsing; register process-level signal/exit handlers in `ensureMinimalDist` so a crashed test still restores `dist/`. * fix(installer): unblock Windows CI for standalone install path Three CI failures and a few review followups in one pass. - ensureMinimalDist places its dist/ backup beside dist/ instead of under os.tmpdir(). On Windows GitHub runners the workspace lives on D: while os.tmpdir() is on C:, so renameSync raised EXDEV for every test that needed to swap dist/ in. - create-standalone-package.js and the matching test fixture build win-x64 zips with [IO.Compression.ZipFile]::CreateFromDirectory. Compress-Archive emits backslash entry names that the .bat installer's path-traversal guard then rejected, so every freshly built archive failed the standalone install path on Windows. - :ValidateArchiveContents normalizes entry separators to '/' before checking for '..', absolute paths, and drive prefixes - archives from any Windows zip tool still install while real traversal entries remain rejected. - createWindowsTraversalStandaloneArchive runs PowerShell via -File instead of a single -Command line; the joined-with-'; ' form had a function definition the runner's PowerShell refused to parse. Drive-by review followups: - replaceRequired uses replaceAll so a future duplicate placeholder cannot silently keep the trailing copy as 'latest'. - :ValidateOptions runs the unsafe-character check on SOURCE alongside the other variables. - build-installation-assets.js drops a dead INSTALLATION_ASSETS re-export; consumers already import from release-asset-config.js. - .gitignore covers the new sibling .qwen-dist-backup-* directory. * fix(installer): address release asset review findings * fix(installer): keep installer entrypoint hosted * fix(installer): reject stale hosted assets * fix(installer): refine hosted asset staging * fix(installer): tighten hosted default-version check, flag legacy URL - Replace the loose `latest` fragment check with per-format regex patterns in HOSTED_INSTALLER_DEFAULT_VERSION_PATTERNS so an unrelated occurrence of `latest` (comment, help text) cannot satisfy the staging guard. The patterns still tolerate whitespace variation, only the default-version assignment itself must be intact. - Add a "Hosted endpoint status" callout in INSTALLATION_GUIDE.md before the curl examples. The documented `--version` flow does not work against the OSS URL today because it currently serves the legacy NVM-based installer; the callout points users at a local checkout until the next release sync. - Tests: drop `latest` from the fragments equality assertion, add positive and negative regex coverage, add a failure-path case for sources whose default version is not `latest`, and pin the new guide markers so the callout cannot silently disappear. * feat(installer): verify installation release assets Adds `npm run verify:installation-release` and wires it into the release workflow after `Build Standalone Archives`, so a broken release directory fails CI before publishing. Local mode (`--dir PATH`) checks: - All five `qwen-code-{platform}.{ext}` standalone archives exist. - `SHA256SUMS` covers exactly those five — missing or unexpected entries fail. - Each archive's actual SHA256 matches its `SHA256SUMS` entry. Remote mode (`--base-url URL`) checks: - `SHA256SUMS` is downloadable, parseable, and contains exactly the expected archive entries. - Each archive URL is reachable via HEAD, with a 1-byte ranged GET fallback for hosts that disable HEAD. Hosted installer scripts (`install-qwen.sh` / `install-qwen.bat`) are intentionally out of scope here — they are served from the hosted endpoint prepared by `package:hosted-installation` (PR #3853), not from the GitHub Release surface this verifier targets. * fix(installer): tighten verifier base-url + clarify test helper Three small refinements from the second review pass: - normalizeHttpsBaseUrl rejects everything except https, since real release URLs are always HTTPS. Accepting http previously would let an operator silently target a stale or attacker-controlled mirror. - Drop EXPECTED_RELEASE_ASSET_NAMES from the public exports; it was only used internally for the verification log line. - Rename the test helper standaloneChecksumContent to placeholderChecksumContent and document that the hashes in its output are placeholders — the remote verifier does not download archives or compare hashes, it only validates that SHA256SUMS lists the expected names and that each archive URL is reachable. The non-https rejection test now also covers `http://` in addition to the existing `file://` case. * fix(installer): address standalone review follow-ups * fix(installer): repair Windows installer tests * fix(release): tighten standalone asset checks * fix(installer): stabilize Windows managed install checks * test(installer): relax Windows installer timeout * fix(test): escape release asset regex * test(cli): avoid POSIX node path in relaunch test * fix(installer): align npm fallback node gate with engines * test(installer): allow Windows archive validation more time * fix(installer): remove stale node 20 installer references * docs(installer): clarify hosted endpoint sync requirement * refactor(installer): reuse standaloneArchiveName in release verifier The verify-installation-release script was duplicating the archive name derivation logic with a hardcoded ternary instead of reusing the standaloneArchiveName helper from build-standalone-release. Export the helper and import it so the extension mapping lives in one place. * fix(scripts): address release verifier review feedback * feat(installer): add standalone archive installer with multi-platform release workflow - Add standalone archive installer (bat/sh) that downloads platform binaries from GitHub/Aliyun without requiring Node.js or npm on the target machine - Add fork-friendly release-test workflow for manual GitHub Release creation covering all 5 platforms (darwin-arm64/x64, linux-arm64/x64, win-x64) - Add OSS upload/mirror tools for staging and release distribution - Update .gitignore to exclude generated build artifacts (release-staging/, hosted-staging/) - Fix Windows PowerShell test command in copy-release-to-latest tool * feat(installer): support QWEN_INSTALL_GITHUB_REPO env var for custom repo * chore(installer): exclude local-only staging tools from PR The tools/ directory contained personal staging-OSS upload helpers (upload-staging, upload-release-mirror, copy-release-to-latest, test-upload-one) that should not ship in the public PR. They reference a personal staging bucket and only exist to validate the installer end-to-end before production release. Removes them from git tracking via `git rm --cached` (files stay on disk for the author's local use) and adds /tools/ to root .gitignore so they cannot be re-added accidentally. No runtime / installer code change. Production CI on ubuntu-latest is unaffected. * fix(installer): enforce CRLF line endings for .bat files via gitattributes cmd.exe requires CRLF in batch scripts; the global eol=lf was causing every line to be misparsed on Windows, producing errors like 'QWEN_VALIDATE_METHOD=detect is not recognized as a command'. * fix(installer): store .bat files with CRLF in git blob for raw GitHub downloads GitHub raw file serving bypasses gitattributes eol conversion and serves blob bytes directly, so eol=crlf alone was not enough. Use -text to disable normalization and commit with actual CRLF so raw downloads work on Windows. * fix(installer): follow HTTP redirects in UrlExists and RaceMirrorHead probes GitHub release asset URLs return HTTP 302 to objects.githubusercontent.com. [Net.WebRequest] with HEAD does not auto-redirect by default, so the existence check and mirror-race probe both incorrectly reported the file as missing. Set AllowAutoRedirect=true on HttpWebRequest instances. * fix(installer): surface download errors and add MaximumRedirection 10 * feat(installer): add hosted install-qwen.ps1 shim for irm|iex one-liner The previous Windows quick-install one-liner used `Invoke-WebRequest -OutFile (Join-Path $env:TEMP 'install-qwen.bat'); & (Join-Path …)`. When pasted into a narrow terminal, line wrap could land on `-OutFile`, orphaning the parameter from its value and producing the "missing argument for OutFile" failure followed by a "file not found" when the second `&` ran. PowerShell's line continuation rules cannot resolve this for parameter-name-at-EOL. Add `install-qwen.ps1` as a thin hosted entrypoint that downloads `install-qwen.bat` into TEMP, runs it, and cleans up. Documented one-liner becomes the standard pattern used by bun, uv, scoop, deno, pnpm: powershell -ExecutionPolicy Bypass -c "irm <url>/install-qwen.ps1 | iex" The `.bat` remains the source of truth for installer behavior; `.ps1` is just the modern hosted entrypoint. Version pinning via `$env:QWEN_INSTALL_VERSION` flows through unchanged. Stored with `*.ps1 -text` so CRLF survives both GitHub raw and OSS uploads, matching the existing `.bat` handling. * fix(installer): stage direct hosted install scripts * chore(installer): trim hosted release diff scope * chore(installer): narrow hosted release diff * feat(installer): restore hosted PowerShell entrypoint * chore(installer): stage standalone hosted entrypoints * fix(installer): address hosted installer review followups * fix(installer): stabilize Windows installer tests * fix(installer): make Windows option validation readable * feat(installer): wire Aliyun OSS sync, address review followups - Add Aliyun OSS sync steps to release workflow: package hosted assets, install pinned ossutil, configure credentials, upload versioned and latest paths, and verify upload via verify:installation-release plus curl probes against the hosted installer endpoint. - Document required production-release environment secrets and bucket variables in INSTALLATION_GUIDE.md. - Restructure hosted endpoint guidance to lead with the pre-sync warning, splitting "Run today" (local checkout) from "After the OSS sync" (hosted one-liners) so users no longer copy a one-liner that silently installs latest. - Distinguish mirror auto-selection timeout from successful selection in install-qwen-standalone.sh and install-qwen-standalone.bat: emit a "timed out; defaulting to github" log instead of pretending the HEAD probe picked github. - Support QWEN_INSTALLER_BAT_URL override (https only) in the PowerShell shim so staging mirrors can be exercised without forking the file. - Strip a leading UTF-8 BOM in verify-installation-release.js parseSha256Sums so BOM-prefixed SHA256SUMS reports a useful "Missing checksum entry" error instead of "Malformed SHA256SUMS line 1". - Add tests for verifier HEAD→Range fallback, partial-failure formatting, all-failure wording, and BOM tolerance. * ci(installer): add temporary OSS smoke test * fix(installer): make OSS release assets public-readable * chore(installer): remove temporary OSS smoke workflow * fix(installer): address hosted installer review gaps * feat(installer): refactor argument parsing and utility functions for release scripts * fix(installer): harden hosted release script checks * fix(installer): suppress PowerShell progress bar in hosted entrypoint shim Add $ProgressPreference = 'SilentlyContinue' to the .ps1 wrapper so Invoke-WebRequest downloads don't render a progress bar when invoked via the irm | iex one-liner. * fix(installer): suppress PowerShell progress bar in bat installer downloads Add $ProgressPreference = 'SilentlyContinue' to DownloadFile so the full-screen progress UI does not appear during archive downloads in interactive PowerShell sessions, consistent with the .ps1 shim. * fix(installer): use curl.exe -# progress bar in Windows downloads Prefer curl.exe with -# (hash-mark progress bar) for archive and installer downloads on Windows 10+. Falls back to Invoke-WebRequest (which shows its own progress bar) when curl.exe is unavailable. Matches the approach used by code-server (curl -#fL) and bun.sh (curl.exe -#SfLo). * fix(installer): suppress progress bars for small downloads and Expand-Archive - .ps1: replace curl.exe -# with silent mode, suppress Invoke-WebRequest progress bar; save/restore $global:ProgressPreference - .bat: add $ProgressPreference = 'SilentlyContinue' before Expand-Archive to prevent full-screen extraction progress UI - .sh: remove --progress-bar / --show-progress from download_file, always use silent curl/wget * fix(installer): auto-backup non-qwen directories and simplify output - ensure_managed_install_dir / :EnsureManagedInstallDir now back up non-qwen directories instead of refusing to install, so users upgrading from npm or old installers don't hit a hard error - Simplify header/footer output: remove banner bars, verbose INFO lines, and redundant "Installation completed!" message - Match bun.sh / code-server style: minimal, to the point * fix(installer): revert Expand-Archive progress suppression in bat The inline $ProgressPreference = 'SilentlyContinue' caused a cmd.exe parsing error ("此时不应有 >") on Chinese Windows. Revert to the original Expand-Archive invocation. * fix(installer): fix cmd.exe parsing error in backup fallback code The %s in the for /f fallback command string was interpreted as a variable reference by cmd.exe, causing "此时不应有 >" on Chinese Windows. Replace with a safe fallback and re-enable Expand-Archive progress suppression. * fix(installer): always persist install bin to user PATH Previously MaybeUpdateUserPath was only called when shadow qwen executables were detected. When no shadow was found, the PATH update was skipped entirely, leaving the user without qwen on PATH after restarting their terminal. Now always persist the bin directory to PATH (unless --no-modify-path is set), regardless of whether other qwen installations exist. * fix(installer): persist PATH to current terminal session on Windows Use the `endlocal & set` trick (same as bun/Rust installers) to export the install bin directory from the setlocal scope to the current cmd session. qwen is now usable immediately without restarting the terminal. * docs(installer): document cmd.exe one-liner for immediate PATH availability Add curl-based one-liner for cmd.exe users. Running the .bat directly in the current cmd session makes `qwen` available immediately via the `endlocal & set` trick. The `powershell -c "irm | iex"` path creates a child process so PATH changes cannot propagate to the parent. * feat(installer): make qwen usable immediately from PowerShell after install - .ps1: detect parent process, update current session PATH, and for cmd.exe parents emit a `set PATH=...` command - .bat: skip final instructions when called from PowerShell to avoid duplicate "Run: qwen" output * fix(installer): remove non-functional doskey approach for cmd parent doskey /exename from a child PowerShell process cannot modify the parent cmd.exe session. Replace with a simple set PATH=... command that the user can copy-paste. * fix(installer): make Windows standalone shim available in cmd * feat(installer): add standalone uninstall scripts * fix(uninstall): match shell-quoted paths when removing the wrapper The installer's write_unix_wrapper shell-quotes the binary path, so paths containing single quotes (or other shell metacharacters) appear as shell-quoted strings in the generated wrapper file. The uninstall script's literal grep -qF missed these, leaving the wrapper orphaned. Add shell_quote to the uninstall script and match against both the raw and shell-quoted forms before removing the wrapper. * fix(installer): update download commands to use progress indicators for curl and wget * fix(installer): resolve Aliyun latest via version pointer * fix(installer): cleanup mirror probe temp dirs * fix(installer): harden standalone release fallback * fix(installer): address standalone review feedback * style(installer): align standalone install output * fix(installer): print standalone uninstall commands * fix(installer): address release review follow-ups * fix(installer): harden Windows target detection * test(installer): stabilize Windows fake tool path * fix(installer): allow explicit Windows curl path * test(installer): use cmd fake curl on Windows * test(installer): cover Windows fake curl helper * test(installer): inject Windows arch overrides in cmd * test(cli): wait for prompt suggestion render * test(cli): revert prompt suggestion wait tweak * fix(installer): harden hosted release publishing * fix(installer): harden Windows latest pointer parsing * fix(installer): bound Windows download timeouts * fix(installer): bound hosted installer probes * fix(release): make ossutil download configurable * fix(installer): address hosted release review feedback * test(installer): keep dist backup on same filesystem * fix(installer): address remaining review feedback on PR #3828 - Remove REQUIRE_CHECKSUM dead code, always hard-fail on checksum issues - Add JSDoc to HOSTED_INSTALLER_BEHAVIOR_PATTERNS explaining its purpose - Add credential cleanup trap for ossutilconfig in release workflow - Add 3-attempt retry with exponential backoff for OSS uploads - Tighten findstr SOURCE regex to require leading letter * fix(release): correct OSS credentials lifetime and mirror probe fallback - release.yml: remove `trap EXIT` inside the Configure step; it deleted ${RUNNER_TEMP}/.ossutilconfig as soon as the configure shell exited, so every subsequent step (publish/sync/verify) lost the credentials. Move credential cleanup to a final `if: always()` step at the job tail. - install-qwen-standalone.sh: drop the predictable PID-based mktemp -d fallback in race_mirror_head; if mktemp fails, return "github" instead of using /tmp/qwen-mirror.$$ which a local attacker could pre-create to bias mirror selection. * fix(installer): address review feedback round 2 Workflow: - Move 'Publish Aliyun OSS Latest VERSION' to run after the hosted installer assets are uploaded and verified, so the latest/VERSION pointer only flips once every release artifact is in place. Previously a hosted-sync failure could leave the pointer ahead of the actual installer scripts. upload-aliyun-oss-assets.js: - Replace `spawnSync('sleep', ...)` retry backoff with an Atomics.wait-based cross-platform sleep so retries also work on Windows runners. install-qwen-standalone.bat: - :DetectTarget no longer emits TARGET=win-arm64 because RELEASE_TARGETS has no win-arm64 archive; ARM64 hosts now fall through to the unsupported-arch branch and (in detect mode) get the npm fallback instead of a 404. - Add QWEN_INSTALL_CURL_EXE to :ValidateRawEnvironmentOptions so this curl override is checked for shell metacharacters like every other knob. - Replace `call echo %%i>>...` with plain `echo %%i>>...` when capturing pre-install qwen.cmd paths; `call` triggered an extra parse pass that could interpret &/|/<,>/etc. inside a directory name as command separators. - Add `--retry 2` to curl.exe downloads (`:DownloadFile` / `:DownloadFileQuiet`) to match the shell installer. - Include expected vs actual hash in the checksum-mismatch error message. install-qwen-standalone.ps1: - Stage the downloaded installer at a cryptographically random temp path (`qwen-installer-<random>.bat`) so a same-user attacker cannot pre-stage a malicious .bat at a predictable path and race the verify/execute window. - Atomically install the current-session cmd shim by writing to a sibling `.new` temp file then renaming, so a partial write cannot leave a half-written shim on PATH. - Add `--retry 2` to the curl.exe download path. - Include expected vs actual hash in the checksum-mismatch error message. install-qwen-standalone.sh: - Include expected vs actual hash in the checksum-mismatch error message. uninstall-qwen-standalone.ps1: - Accept `-Purge` and `-Help` parameters; previously every CLI flag was silently dropped, so users running with `-Purge` got no purge and no error. `-Purge` maps to `QWEN_UNINSTALL_PURGE=1`. uninstall-qwen-standalone.sh: - `remove_install_wrapper` additionally requires the wrapper file to start with a `#!` shebang before it deletes it; a user-authored script that just happens to mention the install path now stays untouched. verify-installation-release.js, build-hosted-installation-assets.js: - Include expected vs actual hash in the checksum-mismatch error messages. scripts/tests/install-script.test.js: - Update assertions for the new error wording, the curl `--retry 2` flag, the dropped ARM64 detection, and the new release-step ordering. * fix(installer): address review feedback round 3 Workflow: - Configure Aliyun OSS Credentials: write the ossutil config file directly with restricted umask instead of invoking `ossutil config -k <secret>`. Passing the access-key secret via argv made it visible in /proc/<pid>/cmdline for the lifetime of that step; writing the INI file in-process keeps the secret out of the process table. upload-aliyun-oss-assets.js: - Upload assets in parallel with `Promise.all` + async `spawn` instead of a sequential `spawnSync` loop. Each asset keeps its own retry budget; failures are aggregated so one flaky upload does not mask a separate failure. - Replace the bespoke `Atomics.wait` retry sleep with `timers/promises#setTimeout` now that the loop is async. INSTALLATION_GUIDE.md: - Drop the misleading "instead of overwriting the global installation/ entrypoint objects" sentence; the workflow has always also refreshed the global versionless objects so curl|bash links keep resolving without a version segment. Document the rollback story instead. * test(installer): add parseUploadArgs unit tests and align verify derivation - scripts/tests/upload-aliyun-oss-assets.test.js: cover --help short-circuit, required-option validation (--bucket/--config/--prefix/empty assets), unknown options, missing option values, and trailing-slash prefix normalization. - scripts/verify-installation-release.js: switch the win-only zip branch from `startsWith('win-')` to the strict `=== 'win-x64'` check used by build-standalone-release.js, and add a comment recording that the two derivations must stay aligned. Without this the helpers would diverge the moment a non-x64 win target gets added. * test(installer): add uploadAssets integration tests with fake ossutil Add two integration tests that route a temp-directory ossutil shim onto PATH so uploadAssets actually spawns the real binary with the real cp argv: - happy-path test asserts the destination URI, `-c <config>`, `--acl public-read`, and per-asset cp invocations land for both inputs. - failure-path test asserts non-zero ossutil exits surface as an aggregate `asset uploads failed` error after the retry budget runs out. * revert(installer): drop over-engineered ossutil/upload changes Roll back two changes from a1ef8697b/0a5d308c9 that were not justified by the actual threat model or release-pipeline needs: - .github/workflows/release.yml: restore the supported `ossutil config -k` invocation. The earlier switch to writing the .ossutilconfig INI file in-process was meant to keep the access-key out of /proc/<pid>/cmdline, but GitHub-hosted runners are single-tenant ephemeral VMs where no other user can read that namespace. The benefit was theoretical; the cost was taking on a brittle dependency on ossutil's undocumented config format. - scripts/upload-aliyun-oss-assets.js: revert the uploadAssets parallel rewrite (Promise.all + spawn + setTimeout) back to the original sync spawnSync loop with retry. Release-time uploads of ~6 small files do not need parallelism, and the async refactor changed the public contract (sync→async) for no real wall-clock win. Kept from those commits: - The cleanup `if: always()` step that removes RUNNER_TEMP/.ossutilconfig at the end of the publish job. - The cross-platform sleepSync(ms) helper, since `spawnSync('sleep', ...)` still does not work on Windows runners. - The INSTALLATION_GUIDE.md doc fix. - All other round-2 fixes. Test assertions updated for the restored sync uploadAssets contract. * test(installer): cover Windows release script regressions * test(release): avoid Windows shim lookup in oss upload tests * test(installer): use stable fake Aliyun version on Windows * fix(installer): parse Aliyun latest version in batch * fix(installer): validate Aliyun latest version without findstr * fix(installer): normalize Aliyun latest version via PowerShell * fix(installer): avoid captured PowerShell output in batch latest parsing * fix(installer): normalize Aliyun latest pointer from file * test(installer): fix fake Windows curl output parsing * fix(installer): print checksum path on miss, gate hardcoded version pin in ps1 [skip ci] Address two narrow follow-ups from PR #3828 review: - build-hosted-installation-assets.js: add a HOSTED_INSTALLER_FORBIDDEN_PATTERNS guard for install-qwen-standalone.ps1. The ps1 shim has no VERSION variable of its own (it forwards @args to the .bat), so the existing default-version positive-match patterns don't apply. The new guard fails the build if a $env:QWEN_INSTALL_VERSION assignment or a --version flag prepended to the forwarded argument list ever lands in the shim. Patterns are line-anchored with /m so the documented usage examples in the header docstring stay valid. Two vitest cases cover the reject and allow paths. - install-qwen-standalone.sh / .bat: include the searched checksum-file path in the "SHA256SUMS not found" error. Operators triaging --archive failures could not tell from the prior message whether the fallback path (next to the archive) or the remote URL was being looked up. Existing test assertions updated to match the new wording. Local validation: npm run test:scripts -> 160 passed | 9 skipped (was 158 | 9). * fix: stamp release version in hosted installers and add Zip Slip protection [skip ci] 1. The hosted installation asset build now accepts --version and stamps it into the copied .sh/.bat installers so they default to the tagged release version instead of 'latest'. The release workflow passes the version. 2. install-qwen-with-source.bat now validates archive entries before calling Expand-Archive, rejecting paths with '..', leading '/', drive-rooted paths, empty names, or control characters — matching the protection already present in install-qwen-standalone.bat and the .sh installer. * fix(installer): add SOURCE to PowerShell unsafe-character validation [skip ci] The SOURCE variable is user-provided and used in path operations but was not included in the :ValidateOptions unsafe-character check. Add it alongside the other validated variables. * fix: correct copyright year 2025 -> 2026 in new files [skip ci] --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: Shaojin Wen <shaojin.wensj@alibaba-inc.com> Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> Co-authored-by: yiliang114 <effortyiliang@gmail.com> |
||
|
|
16f0fde19a
|
fix(test): raise timeout for Windows installer end-to-end tests (#4352)
* fix(test): raise timeout for Windows installer end-to-end tests The Windows-only end-to-end installer tests spawn cmd.exe to run the .bat installer and then qwen.cmd --version, which boots a Node process. On GitHub's windows-latest runners that chain regularly takes >5s, so the default 5s vitest timeout makes them flaky (recently observed at 5804ms on CI). Bump the describe-block timeout to 30s, which leaves headroom without masking real regressions. * fix(test): raise timeout for Linux/macOS installer end-to-end tests Match the timeout already applied to the Windows e2e block: the Linux/macOS installer tests also spawn child processes via execFileSync, so they share the same flake risk near the default 5s vitest timeout. 15s leaves ample headroom without Windows' cmd.exe overhead. Addresses review feedback on #4352. |
||
|
|
cb7059f54d
|
feat(installer): add standalone archive installation (#3776)
* feat(installer): add standalone archive installation * fix(installer): harden standalone archive installs * fix(installer): address standalone review findings * chore(installer): clarify review followups * fix(installer): stabilize standalone script checks * chore(installer): remove internal planning docs * chore(installer): simplify standalone release review fixes * test(installer): add Windows batch install smoke * test(installer): fix Windows batch smoke quoting * test(installer): preserve Windows cmd quotes * fix(installer): use robust Windows checksum hashing * ci: narrow installer debug matrix * fix(installer): address standalone review hardening * fix(installer): avoid Windows validation parse errors * fix(installer): simplify Windows option validation * fix(installer): harden standalone review fixes |