qwen-code/packages/core
易良 796de4dfef
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(core): merge IDE context into user prompt (#3980)
* fix(core): merge IDE context into user prompt

IDE mode now wraps editor context in a <system-reminder> block and
prepends it to the current user request instead of inserting a separate
user history entry via addHistory(). This preserves the API history
turn shape and avoids extra user turns in IDE mode.

Key changes:
- IDE context merged into user request via prependToFirstTextPart()
- State update deferred until after arena cancellation check
- escapeClosingSystemReminderTags() hardens against tag injection
  including zero-width/control character variants
- forceFullIdeContext reset on stream errors for correct resend
- Context prompt updated to encourage active use of editor context

Refs #3712

* fix(core): restore BaseLlmClient per-model cache clear on session reset

resetChat only cleared GeminiClient's new perModelGeneratorCache but
dropped the BaseLlmClient.clearPerModelGeneratorCache() call that was
present before the refactoring. sideQuery.ts and sessionTitle.ts still
route through BaseLlmClient with the fast model, so stale generators
survived session reset.

* refactor(core): remove duplicated per-model generator code from GeminiClient

The per-model ContentGenerator resolution logic (resolveModelAcrossAuthTypes,
createRetryAuthTypeForModel, createContentGeneratorForModel, perModelGeneratorCache)
was inadvertently duplicated from BaseLlmClient into GeminiClient. This restores
the original one-line delegation to BaseLlmClient.resolveForModel() and removes
~130 lines of redundant code to keep the PR focused on IDE context merging only.

* fix(core): harden IDE context reminder escaping

* fix(core): defer IDE context baseline update

* fix(core): use shared escapeSystemReminderTags in tool scheduler

Aligns the rule-activation envelope scrub with the IDE-context path —
both now route through `escapeSystemReminderTags`, which neutralizes
whitespace, zero-width, and control-character variants of
`<system-reminder>` tag boundaries. The previous narrow regex only
matched the literal `</system-reminder>` sequence, so a rule body
containing `</system-reminder >`, `</ system-reminder>`, or
`<​/system-reminder>` could still close the envelope mid-content.

* docs(core): clarify request assembly order in IDE merge path

Two adjacent comments described the pre-merge model: one called
the system-reminder block "append" while the code prepends, and the
tryCompressChat note still talked about "the previous context turn"
which no longer exists once IDE context is merged into the user
prompt. Rewrite both to match what the code actually does so future
readers do not get a misleading mental model of prompt assembly or
post-compression resend behavior.

* docs(core): align scheduler scrub comment with shared helper

The block-level comment still labeled the sanitization step as
"closing-tag scrub", which described the old narrow regex. The
shared escapeSystemReminderTags helper now neutralizes opening /
self-closing / obfuscated variants too, so name the helper directly
to keep the rationale and the call site in agreement.

* test(core): cover escapeSystemReminderTags variants in scheduler

The end-to-end scheduler scrub test only exercised a literal
</system-reminder> body. Now that the rule-activation envelope routes
through escapeSystemReminderTags, extend the integration coverage to
the obfuscated closing-tag variants the helper was introduced to
catch (whitespace before/after the slash, ZWSP / WJ / VS-16 inside
the name) and to opening-tag injection. Each case asserts that the
envelope still has exactly one </system-reminder> closer and that the
raw obfuscated form (or unescaped opening tag) does not survive into
the model-facing payload.

Refactor the existing test's mock setup into a shared
runSchedulerWithRule helper so the new it.each variants stay
focused on the assertion shape.

* fix(core): address remaining review feedback

- Add debug log when IDE context parts are empty for diagnosability
- Add safety comment in xml.ts explaining why no fast-path pre-check
  is used in getSystemReminderTagKind (zero-width obfuscation bypass)
2026-05-14 11:33:00 +08:00
..
scripts Fix: Improve ripgrep binary detection and cross-platform compatibility (#1060) 2025-11-18 19:38:30 +08:00
src fix(core): merge IDE context into user prompt (#3980) 2026-05-14 11:33:00 +08:00
vendor feat test tool permissions 2026-03-10 16:30:22 +08:00
index.ts fix: Remove remaining ClearcutLogger export from packages/core/index.ts 2026-02-01 14:52:14 +08:00
package.json chore(release): v0.15.11 [skip ci] 2026-05-14 09:51:46 +08:00
test-setup.ts feat(memory): managed auto-memory and auto-dream system (#3087) 2026-04-16 20:05:45 +08:00
tsconfig.json fix: upgrade @lydell/node-pty to 1.2.0-beta.10 to fix PTY FD leak 2026-04-01 07:55:56 +08:00
vitest.config.ts