mirror of
https://github.com/QwenLM/qwen-code.git
synced 2026-07-10 01:29:17 +00:00
* feat(cli,core): /compress accepts custom focus instructions Extends /compress to take a trailing instruction string (max 2000 chars) that is passed through tryCompressChat → tryCompress → CompressOptions and appended to the compression side-query system prompt as an "Additional Instructions:" block. Mirrors claude-code /compact <text>. Empty / whitespace-only args fall back to the prior behaviour. * test(core): cover /compress customInstructions + PreCompact hook merge * feat(core): restore plan-mode + subagent snapshot after compaction Adds two optional ComposePostCompactOptions: - planModeActive: when true, emits a <plan-mode-active> reminder so the post-compact agent does not forget destructive tools remain gated. - runningSubagents: when non-empty, emits a <background-tasks> block listing each running/paused task by id, status, and description. Both blocks are spliced into the merged user attachment Content before file/image restorations. XML-significant characters in descriptions are escaped to prevent an adversarial subagent description from closing the wrapper tag. Wiring at the call site arrives in the next commit. * feat(core): wire plan-mode + subagent snapshot into post-compact attachments ChatCompressionService.compress now passes: - planModeActive: derived from config.getApprovalMode() === ApprovalMode.PLAN - runningSubagents: filtered from BackgroundTaskRegistry to agent-kind tasks in 'running' or 'paused' state into composePostCompactHistory. Adds collectActiveSubagents() helper that returns [] when the registry is absent so older SDK consumers without it keep working. * fix(core,test): use HookSystem.getAdditionalContext accessor; smoke-test /compress - chatCompressionService: read PreCompact hook output via result.getAdditionalContext() — the wrapper returns DefaultHookOutput (not the raw AggregatedHookResult), and the accessor sanitises < / > consistently with every other call-site in the repo. - Test mocks now return a DefaultHookOutput-shaped stub via a tiny makeHookOutput() helper rather than the aggregator shape. - New integration smoke test for `/compress focus on the scientist mentioned` exercising the args plumbing end-to-end. * test(core): update client.test.ts to match new tryCompressChat signature * feat(core): cap subagent snapshot at 30 entries with overflow notice Code-review follow-up. Pathological sessions with hundreds of backgrounded agents could otherwise produce a multi-KB block. Newest 30 rows are kept (highest startTime); older ones are summarised on a trailing line so the model knows the snapshot is partial. * fix(core,test): flatten subagent description newlines; type-safe ApprovalMode in tests Second code-review pass found two real issues: 1. Subagent descriptions containing `\n`/`\r`/`\t` would split across multiple lines inside the `<background-tasks>` bullet list, letting the second line read as a sibling row (or worse, an orphan paragraph between two `- [..]` entries). Flatten whitespace before the slice so each task stays on one line. 2. The plan-mode wiring tests passed `'plan'` / `'auto-edit'` as plain strings instead of `ApprovalMode.PLAN` / `ApprovalMode.AUTO_EDIT`. Source code compares against the enum; a future enum value change would have silently passed the tests. Import and use the enum. * fix(core): move PreCompact hook fire after length-guard; align plan-mode tool names Round 3 code review surfaced two issues: 1. PreCompact hook fired BEFORE the curatedHistory.length < 2 guard, so a single-message session would trigger any hook side effects (transcript dump, external notification, etc.) and then NOOP. Move the hook fire below the guard so hooks only run when compression is actually possible. New regression test asserts the contract. 2. PLAN_MODE_REMINDER_TEXT said "shell mutations" but the real qwen-code tool is `run_shell_command` (tool-names.ts:26). Use the verbatim tool names so a future rename is grep-discoverable. * refactor(core): share escapeXml, drive plan-mode names from ToolNames, extract reminder builder Code-review follow-ups on post-compact attachments: - Replace the local 3-char escapeForXmlText with the shared 5-char escapeXml from utils/xml.ts, and apply it to the subagent id and status as well as the description. Subagent ids derive from a user-configurable subagentConfig.name, so an unescaped `<`/`&` there could close the <background-tasks> wrapper or forge sibling markup. - PLAN_MODE_REMINDER_TEXT now interpolates ToolNames.WRITE_FILE / .EDIT / .SHELL instead of retyping the names, so a future rename stays in sync. - Extract buildStateReminderParts() as the single source of truth for the plan-mode + subagent reminder blocks, used by both composePostCompactHistory and (next commit) its catch-fallback so the two paths can't drift. * fix(core): scope subagent snapshot to backgrounded tasks; restore reminders on fallback; cap hook context Three code-review fixes in the compaction service: - collectActiveSubagents now also requires isBackgrounded — foreground agents are the parent's synchronously-awaited tool call and don't belong in a <background-tasks> roster. Mirrors getRunningBackgroundCount. - The composePostCompactHistory catch-fallback re-applies the plan-mode + subagent reminders via the shared buildStateReminderParts (pure, no I/O), so a restoration failure no longer silently drops plan-mode enforcement and the subagent roster. - The PreCompact hook's additionalContext is capped at MAX_HOOK_INSTRUCTIONS_CHARS before entering the side-query prompt, closing the unbounded-input hole the user-text cap was meant to prevent. The fallback and hook-cap fixes have RED-verified regression tests. * feat(cli): warn on /compress instruction truncation; fix integration-test pty typing - /compress now emits an INFO notice (interactive), a stream message (acp), and a prefixed return message (non-interactive) when the instruction string exceeds MAX_COMPRESS_INSTRUCTIONS_CHARS, so the silent 2000-char clip is no longer invisible to the user. - Annotate the three `ptyProcess.onData((data: string) => ...)` callbacks in the compress integration test to clear the TS7006 implicit-any the reviewer's typecheck flagged (fixed all three occurrences, not only the one inside this PR's diff). |
||
|---|---|---|
| .. | ||
| baselines | ||
| cli | ||
| concurrent-runner | ||
| fixtures | ||
| hook-integration | ||
| interactive | ||
| sdk-typescript | ||
| terminal-bench | ||
| terminal-capture | ||
| channel-plugin.test.ts | ||
| globalSetup.ts | ||
| test-helper.ts | ||
| test-mcp-server.ts | ||
| tsconfig.json | ||
| vitest.config.ts | ||
| vitest.terminal-bench.config.ts | ||