mirror of
https://github.com/QwenLM/qwen-code.git
synced 2026-08-26 00:53:48 +00:00
* refactor(goal): render Goal continuation prompts from one core renderer The prompt sent when `runtime.finishTurn` schedules another Goal turn was assembled independently in three hosts: the TUI's inline array in `useGeminiStream`, and a `buildGoalContinuationParts` in each of the ACP session and the non-interactive CLI. Three copies of the same four shared lines have already drifted -- the TUI carries the anti-spoofing guard lines but no objective, while ACP and non-interactive carry the runtime continuation context but no guard lines. Upcoming work adds further variants (an "objective was edited" announcement and a budget wind-down prompt). With the text living in three places, every new variant means three edits, which is precisely how the current drift was produced. This moves assembly into `packages/core/src/goals/goal-continuation-prompt.ts`, where a variant is a case in one function and the shared prefix exists once. The two `buildGoalContinuationParts` helpers keep their names and signatures and simply delegate. This is a pure refactor: no prompt text changes. Each host still emits a byte-identical string to the one it emitted before. The existing drift is preserved deliberately and is left for a separate, behavior-changing follow-up. The new unit test pins the complete rendered string for both variants with and without verifier feedback, so any future edit to a line surfaces as a test diff; the existing host tests pass unmodified. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix(goal): tighten continuation renderer contract * test(goal): cover verifier feedback hosts * refactor(goal): hoist Goal continuation parts builder into core (#9581) * fix(goal): converge the three continuation prompts on one guarded contract Every automatic Goal turn now renders the same prompt in every host: the runtime-supplied goalId, revision and objective as an escaped JSON data block, framed as untrusted task data, under both anti-spoofing guard lines, followed by a line stating the block supersedes any earlier objective in the conversation. Before this change the drift ran the wrong way. ACP and non-interactive interpolated the raw objective into a synthetic user-role turn carrying neither guard line; the TUI carried both guard lines but dropped the objective, so the host that guarded most gave up information and the two that guarded least were the exposed ones. None of the three escaped the objective, so objective text shaped like a tag could break out of the surrounding prompt. The prompt input collapses to a single flat shape, so the variant discriminant and its unreachable-default arm are gone. `<`, `>` and `&` are escaped inside the serialized JSON so an objective cannot close the data block or open one of its own. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5 <noreply@anthropic.com> Co-authored-by: qqqys <266654365+qqqys@users.noreply.github.com> Co-authored-by: qwen-code-dev-bot <qwen-code-dev@service.alibaba.com> |
||
|---|---|---|
| .. | ||
| src | ||
| .gitignore | ||
| index.ts | ||
| package.json | ||
| test-setup.ts | ||
| tsconfig.json | ||
| vitest.config.ts | ||