* fix(external-context): read the response body with a reader, not for-await
Async-iterating a ReadableStream needs [Symbol.asyncIterator] on the
TYPE, and whether it is there depends on which lib set the program
resolves — @types/node's stream has it, the DOM lib's needs
lib.dom.asynciterable. That resolution flipped underneath this file on
2026-08-08: #8693 installed @types/jsdom at the root, vitest's types
pull the jsdom types in wherever they exist, and jsdom's carry
/// <reference lib="dom" />. #8693 shipped the tsconfig `types` guard in
the same commit, so main stayed green — but the guard travels with the
BRANCH while node_modules travel with the TRUSTED BASE in the autofix
verification build, so every managed branch behind #8693 failed that
build with TS2504 on this line. Two legs measured on run 31276008548:
63 minutes of accepted agent work discarded per round, 18 more minutes
burned by a repair step that cannot fix a failure outside the PR's diff
(#8614 reached attempt 13 that way; #8616 died identically).
Reproduced locally in both directions before changing anything:
@types/jsdom installed + guard removed = the gate's exact error,
character for character; with the reader loop the same poisoned setup
builds clean. The guard stays — belt and suspenders — but the build no
longer depends on it, or on which lib set any future environment
resolves.
Behavior is unchanged and now pinned by tests the file never had:
multi-chunk assembly, the exact MAX_RESPONSE_BYTES boundary (bound is
strictly-greater), invalid-UTF-8 rejection, and the easy one to drop in
this rewrite — cancelling the stream on early exit, which `for await`
did implicitly via iterator return(). Mutation-tested: removing the
cancel fails exactly that test against an endless producer.
The package's other for-awaits iterate process.stdin (a Node stream,
async-iterable in every lib set) and are untouched.
* fix(external-context): await stream cancellation before rejecting the request
On early exit from the reader loop (the oversize throw) cancellation was
started fire-and-forget, so postJson() rejected while the stream's
teardown was still settling — `for await` had awaited its implicit
iterator return() before propagating. An immediate retry could overlap
the previous response transport's unfinished cancellation. Await
reader.cancel() before releaseLock(), and pin the sequencing with a
deferred-cancel regression test that fails against the fire-and-forget
form.
Also cover read() rejecting after a partial chunk was received: the
error maps to the request-did-not-complete transport error rather than
EOF-then-parse of the partial JSON, and the reader lock is still
released.
* fix(external-context): drop the types guard the reader rewrite made obsolete
The `"types": ["node"]` override existed solely to keep @types/jsdom's
lib.dom out of this program while http-client.ts read the response body
with `for await` — the DOM lib's ReadableStream is not async-iterable,
and the flip broke the build with TS2504 (#8693). The reader loop that
replaced the `for await` types identically in every lib set, so the
guard is no longer load-bearing: with it removed, lib.dom re-enters the
program and the package still builds cleanly. Drop it with its stale
comment instead of leaving maintainers two contradicting stories about
whether it is needed.
Also export MAX_RESPONSE_BYTES and import it in the boundary tests
instead of re-declaring it locally, so the tests pin the real constant
rather than a copy that can silently drift.
* test(external-context): make the invalid-UTF-8 test pin fatal decoding
---------
Co-authored-by: verify <verify@local>
Co-authored-by: qwen-code-dev-bot <qwen-code-dev@service.alibaba.com>
* fix(integration-tests): make the project typecheckable and fix what that found
`tsc -p integration-tests/tsconfig.json` could not run at all. The config
carried a `"//"` documentation key inside `compilerOptions.paths`, and every
value there must be an array, so tsc aborted with TS5063 before checking a
single file. Nothing in CI runs it either, so the directory has been
unchecked for its whole life -- which is how PR #8620 shipped an
`integration-tests/cli/qwen-serve-streaming.test.ts` that referenced an
undeclared `REPO_ROOT`, swallowed the ReferenceError in a bare catch, and
reported a green skip for a security regression test.
Moving that note out of `paths` exposed 404 errors. Three more config
defects accounted for 353 of them:
- `composite: true` is inherited from the root config for the packages that
are actually referenced. Composite requires every file in the program to
appear in `include`, and these tests import package sources by relative
path, so it produced 324 TS6307. Nothing references this project and it
emits nothing, so it is now `composite: false`.
- The root `lib` is ES2023 only. The suite drives browser-side code in
`terminal-capture/` and pulls SDK sources that name `WebSocket` and
`HeadersInit`, so 21 identifiers resolved to nothing. Now DOM +
DOM.Iterable + ES2023, matching packages/cli.
- Workspace packages resolved through `packages/core/dist` via a project
reference, so with core unbuilt the checker reported a dozen members as
missing from `Storage` that are right there in the source. They now
resolve from source through `paths`, mirroring packages/cli, and the
reference is gone.
node-pty declares `types` at the top level but its `exports` map is a bare
string with no `types` condition, so nodenext never reached the
declarations and every pty handle degraded to `any` -- which is what
silently untyped the `data` and `exitCode` callbacks in test-helper.ts. It
now resolves through `paths` as well. `@types/jsdom` is added for the one
file that uses it; DefinitelyTyped has no release matching jsdom 26 (it
jumps 21 -> 27), so this pins the current 28.x.
Two real defects fell out of the remaining 51:
- write_file.test.ts built a detailed tool-call failure message and passed
it to `toBeTruthy()`, which takes no arguments. It was discarded on every
failure, leaving only a bare literal.
- Two terminal-capture scenarios set `gif: true` inside `streaming`, where
the runner never reads it. It is a scenario-level switch.
The rest was making an existing `undefined` visible. `readToolLogs()`
promised `name: string` for fields copied straight out of telemetry
attributes that nothing validates; the stdout fallback can promise them,
the telemetry branch cannot, and claiming otherwise just moved the
`undefined` past the type checker into the assertions.
This is type resolution only. `integration-tests/vitest.config.ts` keeps
its own hardcoded aliases onto the built SDK bundle, so the suite still
exercises the published-bundle shape at runtime.
Not wired into CI here, but not for cost reasons: a cold run of
`tsc -p integration-tests/tsconfig.json` takes about 106s on an idle
developer box. The program is 2679 files, of which 103 are integration
tests and roughly 1100 are package sources their own projects already
check, so there is duplicated work available to reclaim by resolving the
packages from their built declarations -- but at ~106s it is already cheap
enough to gate on as-is.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* fix(integration-tests): isolate jsdom types and complete source-resolution paths
Address review round 1:
- external-context: override `types` to ["node"]. The root @types/jsdom
entered its program through vitest's optional jsdom types and injected
lib dom, flipping @types/node's fetch globals to DOM variants whose
ReadableStream is not async-iterable (TS2504 in http-client.ts), which
failed every CI job during the npm ci prepare build.
- integration-tests tsconfig: explicit nodenext paths entries for every
workspace subpath the program imports (sdk/daemon, 19 acp-bridge
subpaths, core goalWire/memoryScopes/userPromptSubmitContext, webui
daemon-react-sdk, channel-base); drop the dead `*` wildcards; include
**/*.tsx. Typechecks green with the source packages' dists removed.
- Relax noPropertyAccessFromIndexSignature in integration-tests and
revert the six bracket-access rewrites it forced in SDK sources.
- channel-plugin: import channels/base from src and map
@qwen-code/channel-base to source so both declarations agree.
- qwen-serve-streaming: asAccepted delegates to the SDK's exported
isNonBlockingAccepted type predicate instead of a drifted copy.
- sleep-interception: tighten blocked predicates to success === false
and fix the comment describing them.
- Declare jsdom at the root next to @types/jsdom.
* fix(integration-tests): complete source-resolution paths and restore single channel-base instance
Address review round 2:
- Map the eight builtin channel adapters and web-templates to source.
channel-registry.ts and html.ts still resolved them through their
exports maps to dist, so the typecheck's build-independence was
incomplete: on a tree without built dists it failed with the exact
9 x TS2307 the maintainer verification measured.
- channel-plugin.test.ts: import @qwen-code/channel-base by bare
specifier instead of a relative src path. At runtime the test and
plugin-example now resolve the same dist/index.js through the
exports map, restoring the single ChannelBase / SessionRouter
instance the relative src import silently split; type resolution
still maps to source through paths, and vitest.config.ts keeps
pointing e2e runs at the built bundles.
---------
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Co-authored-by: Shaojin Wen <shaojin.wensj@alibaba-inc.com>
Co-authored-by: qwen-code-dev-bot <qwen-code-dev@service.alibaba.com>
Co-authored-by: qwen-code-dev-bot <qwen-code-dev-bot@users.noreply.github.com>
* fix(external-context): harden MCP dependencies
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
* fix(external-context): drop no-op MCP override, raise SDK floors (#8206)
Remove the `@modelcontextprotocol/sdk@^1.30.0` -> `@hono/node-server`
override: resolution with and without it is byte-identical because the
SDK's own `^1.19.9 || ^2.0.5` range already selects 2.0.12, and
mobile-mcp's exact SDK pin (not this entry) keeps its nested Hono 1.
Raise the `@modelcontextprotocol/sdk` floor to `^1.30.0` on the packages
that actually instantiate the Hono-backed transport (cli, core,
sdk-typescript, vscode-ide-companion) so the hardened constraint lives in
the manifests where the code runs, matching the PR's stated intent.
---------
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
* feat(external-context): add submitted-prompt auto recall
Add an opt-in Hook-only profile that derives bounded retrieval queries from submitted prompt provenance while preserving the existing on-demand MCP contract.
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
* fix(external-context): harden auto recall query sanitization (#7877)
Address review feedback on the submitted-prompt auto recall Hook:
- Bound the sanitizer input before the redaction regexes run so a
worst-case prompt cannot drive the assignment regex into quadratic
backtracking that blocks the event loop past the wall-clock budget.
- Test the whole assignment for secret names so a leading label such as
"Deploy failed:" can no longer claim the match and leak an api_key=.
- Skip the interactive E2E under container sandboxes (docker/podman),
matching the cron-interactive precedent.
- Restore real undici coverage for a malformed proxy environment value.
- Make the wall-clock-budget test exercise the internal timer rather than
the provider timeout, and give the backtracking regression test a shape
that actually backtracks.
- Clarify that the v2 top-level timeoutMs applies only to the on-demand
MCP path, and note session-lifetime context accumulation in the design
doc.
* fix(external-context): complete secret redaction, guard MCP config version (#7877)
Anchor the secret keyword to the name that owns the separator so a leading
prose label can no longer claim the match. This redacts spaced separators
(api_key = sk-...) and inline JSON ({"api_key": "..."}), and stops
over-redacting ordinary prose such as "readme: token refresh flow".
Also reject non-version-1 configs in runMcp with a clear startup error so an
auto-recall (v2) config cannot silently expose a second retrieval surface.
---------
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
Co-authored-by: Qwen Code Autofix <qwen-code-autofix@users.noreply.github.com>
Co-authored-by: qwen-code-dev-bot <qwen-code-dev@service.alibaba.com>