mirror of
https://github.com/QwenLM/qwen-code.git
synced 2026-08-25 08:33:55 +00:00
7794 commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
5bb53eb645
|
fix(core): stringify const-derived enums in toOpenAPI30 (#7547)
toOpenAPI30 maps const to a single-value enum, then separately stringifies
enums because — per its own comment — Gemini strictly requires enums to be
strings. The two never met: the stringification keys off source['enum'],
which a const-only schema never sets, so the const value went through raw.
{ const: 5 } -> { enum: [5] } // number, breaks the rule
{ const: true } -> { enum: [true] } // boolean, likewise
{ enum: [1, 2] } -> { enum: ['1', '2'] } // the intended behavior
Build the const-derived enum with String() so both paths produce the same
kind of value.
Co-authored-by: Shaojin Wen <shaojin.wensj@alibaba-inc.com>
|
||
|
|
3a85d48e77
|
fix(desktop): scale formatBytes past GB so terabyte sizes don't render as "undefined" (#7623)
formatBytes only had B/KB/MB/GB units and indexed the array with an unclamped log-based exponent, so any value >= 1 TB overflowed to "1.0 undefined". This is reachable in api-tools: the "Response too large" guard formats an untrusted remote Content-Length, which a server can report in the terabytes. Extend the unit table through EB, clamp the exponent to the last unit, and guard non-finite / sub-1 inputs so the function never emits "undefined" or "NaN". Add formatBytes coverage to the existing binary-detection test (range/limit guards plus the TB/PB/EB and non-finite cases that fail on the old code). |
||
|
|
dbadf49c6c
|
feat(stats): show generation timing metrics (#7677)
Co-authored-by: destire-mio <248462155+destire-mio@users.noreply.github.com> |
||
|
|
16ead53675
|
refactor(core): assemble the system prompt through one layered builder (#7707)
* perf(core): keep the volatile auto-memory section last in the system prompt The managed auto-memory section (instructions + MEMORY.md indexes) is rewritten in-session on every memory save, but it was pre-concatenated into the middle of the userMemory blob — ahead of appendSystemPrompt and git status, which are stable for the whole session. Every save therefore invalidated the prompt-cache prefix from the middle of the system prompt, and the stable/context/volatile layers were indistinguishable in code. Store the auto-memory section separately on Config (getAutoMemoryPrompt) and have every assembly site append it after all stable and context content, yielding a stable -> context -> volatile layout: base prompt, QWEN.md hierarchy + rules, append prompt, git status, auto-memory. Also count the section in /context (previously dropped by the marker parser) and keep /memory show and the context-size warning covering both layers. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * refactor(core): reuse buildSystemPromptSuffix for subagent auto-memory + add regression tests - agent-core.ts: replace the inline auto-memory separator with buildSystemPromptSuffix so the '---' separator and trimming stay in sync with the other assembly sites (client.ts x2, ArenaManager.ts). - client.test.ts: add coverage that a non-empty getAutoMemoryPrompt is appended as the last block of the main-session system instruction. - contextCommand.test.ts: add coverage that a non-empty getAutoMemoryPrompt surfaces an 'auto memory' row in the /context memory breakdown. * refactor(core): assemble the system prompt through one layered builder Follow-up to the auto-memory reordering: the stable -> context -> volatile order existed only as a convention spread across four call sites (client, subagents, Arena, custom-instruction path), so a new segment could silently be appended in the wrong position. Introduce assembleSystemPrompt with one named slot per segment (base, contextFiles, appendPrompt, gitStatus, autoMemory); it is now the single place that knows the order, and getCoreSystemPrompt / getCustomSystemPrompt delegate to it so there is one join implementation. buildSystemPromptSuffix returns to module-private. Pure refactor: every assembly site produces byte-identical output, so no prompt caches are invalidated by this change. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(core): stop duplicating the auto-memory section in Arena workers ArenaManager pre-appended buildSystemPromptSuffix(getAutoMemoryPrompt()) onto the in-process worker's systemPrompt, but AgentCore.buildChatSystemPrompt already appends the auto-memory section itself when the worker builds its system instruction (and the per-agent Config inherits a non-empty getAutoMemoryPrompt() from the base via Object.create). The section therefore appeared twice in the worker's prompt. Drop the ArenaManager append so the volatile auto-memory layer is added exactly once, by AgentCore, keeping it last. Add regression tests: ArenaManager no longer embeds the auto-memory marker, and generateContent's per-call systemInstruction branch still appends it. * refactor(core): make buildSystemPromptSuffix module-private It has no external importers after routing every assembly site through assembleSystemPrompt, so dropping the export prevents a future caller from bypassing the enforced layer order — matching the PR's stated intent. * chore: drop unrelated lightningcss lockfile churn Restore the "peer": true entries on the lightningcss optional deps that an incidental npm install had removed; keeps this refactor's lockfile diff empty so it does not mislead bisects on lightningcss resolution. --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
0b5116a1bb
|
feat(core): configure stream rate-limit retry delays (#7674) | ||
|
|
c4859627a7
|
feat(serve): Hot-reload workspace trust changes (#7268)
Some checks are pending
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
E2E Tests / cron-interactive E2E (nightly) (push) Waiting to run
E2E Tests / web-shell Browser Regression (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
* feat(serve): hot-reload workspace trust changes Rebuild workspace runtime generations when trust policy changes, fail closed across daemon routes, and expose reconciliation status to SDK and Web Shell clients. Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * codex: address PR review feedback (#7268) Document the trust hot-reload capability and reuse the daemon environment fallback so the serve process environment guard remains satisfied. Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * fix(cli): cache workspace trust status snapshots Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * fix: address trust reload race regressions Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * fix(serve): avoid repeated runtime containment Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * fix(serve): harden workspace generation boundaries Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * fix(serve): restore stale session owner fallback Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * fix(serve): preserve workspace metadata across trust reloads Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * fix(serve): align hot-reload trust semantics Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * fix(serve): stop git-state watcher on dispose only, fix git chip test (#7268) beginDrain stopped the git-state watcher but cancelDrain had no way to restart it, leaving the watcher disposed until the next lazy poll. disposeRuntime already stops git-state when the drain is committed, so the beginDrain stop was redundant — remove it. Also fix the WorkspaceSection git chip test that broke when the trigger changed from <button> to <span role="button"> inside DropdownMenuTrigger: use closest('[role="button"]') and interact with the dropdown menu item. * fix(serve): address review feedback on trust polling and setValue assertion (#7268) * fix(cli): correct daemon trust policy settings precedence and drain continuation (#7268) * fix(serve): address review feedback on fork cleanup, persist simplification, sync guard, and a11y (#7268) * fix(serve): assert before mutate in setValue, add pre-mutation guard, trust-before-generation ordering (#7268) * fix(serve): honor system defaults in trust policy Apply the documented settings precedence to daemon folder trust evaluation and keep workspaces outside configured trust rules fail-closed. Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * fix(serve): preserve managed scratch trust during reloads Keep daemon-created scratch workspaces trusted across policy reloads while retaining controlled-root validation, and reject trust mutations that cannot apply to these fixed-trust runtimes. Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * fix(serve): guard auth provider persistence by generation Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * refactor(serve): remove Web Shell trust UI Keep this PR focused on daemon and SDK trust reconciliation; the Web Shell integration can follow separately. Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * fix(sdk): restore workspace trust bundle budget Preserve the merge-only browser bundle allowance required by the additive workspace trust v2 SDK surface after rebasing. Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * fix(cli): handle trusted folder write failures Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * fix(cli): keep capabilities available during trust reload Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * fix(cli): address review feedback for workspace trust hot reload (#7268) Drop the closed generation guard before retrying dynamic workspace runtime creation so the retried runtime starts with a fresh, open guard instead of inheriting the one closed during the abandoned attempt. Make the /workspace/reload trust reconcile fire-and-forget with a swallowed rejection (failures are reported separately), reuse sendGenerationClosedError for the memory write error path, and assert the subagent deletion commit boundary once before unlinking so a closed generation fails atomically. Add coverage for the blocked-entry deep health probe and the /session/:id/cd generation-close-during-flight path. * fix(serve): close trust reload cleanup gaps Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * fix(serve): use fire-and-forget for trust reconcile in workspace-qualified reload (#7268) * fix(serve): address review feedback on generation guard and trust reconciler (#7268) * fix(serve): use shared helpers for untrusted/generation-closed responses (#7268) * fix(serve): continue cleanup after drain commit errors Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * fix(cli): retry transient trust policy disappearance Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * fix(serve): align status provider trust default with route-level check (#7268) * fix(serve): clean up worktree on generation guard abort (#7268) * fix(cli): guard tool and skill settings commits Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * test(cli): add discriminating persistent-ENOENT test for trust policy read (#7268) * fix(serve): close runtime generation gaps Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * fix(serve): preserve scheduled task cap errors Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * fix(serve): address review feedback on trust reconciler, settings guard, and route simplification (#7268) * fix(serve): preserve containment retry semantics Restore the last verified trust-reconciliation and generation-guard behavior after the automated review fix marked an unconfirmed disposal as contained and removed per-scope commit checks. Defer the remaining late-round suggestions to avoid expanding the PR. Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> --------- Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> Co-authored-by: qwen-code-ci-bot <qwen-code-ci-bot@users.noreply.github.com> Co-authored-by: Qwen Code Bot <qwen-code-bot@users.noreply.github.com> Co-authored-by: Qwen Autofix <qwen-autofix@alibaba-inc.com> Co-authored-by: Qwen Code Autofix <qwen-code-autofix@users.noreply.github.com> |
||
|
|
cb36659e39
|
fix(cli): align inline math recognition (#7701)
* fix(cli): align inline math recognition * fix(cli): tighten inline code span handling * test(cli): cover escaped inline math closer |
||
|
|
b9db14cb13
|
feat(review): enforce the submit-only write contract with a cleanup tripwire (#7691)
* feat(review): enforce the submit-only write contract with a cleanup tripwire
The /review skill's posting ban named one API route — `gh api
.../pulls/<n>/reviews` — and a run that had lost the surrounding prose to
four context compressions walked around it: it decided its findings were
all duplicates, never called submit, and hand-posted a consolidated
summary with `gh pr comment`. No authorisation gate, no downgrade
semantics, no `posted` fact, no completion line; nothing downstream could
tell it had happened.
Three layers close this:
- SKILL.md Step 7 now bans every write path to the PR (`gh pr comment`,
`gh pr review`, `gh issue comment`, mutating `gh api` calls, comment
edits/deletes) and routes prose wrap-ups into the review body via
compose-review; the overlap-drop branch and Step 9 restate it at the
two decision points where runs improvised.
- fetch-pr stamps `fetchedAt` (and `host`) into the fetch report — the
review window's opening time, on the carrier that exists on every PR
run.
- cleanup audits that window before sweeping: issue comments by the
reviewing account are flagged with warning lines the skill must relay
(submit posts reviews, never issue comments, so the overlap with
sanctioned output is zero). Best-effort by design — offline or
unauthenticated runs skip it silently, and an audit failure never
fails the cleanup.
Validated against the real bypass: with a window opening at the original
run's fetch time, the audit names the exact hand-posted comment.
* fix(review): bypass-audit review follow-ups — shared-account filter, edit class, named skips
Addresses the review on the tripwire design:
- Medium: in CI the reviewing account is the bot that precheck/triage
also post from, so their marker-stamped comments (<!-- qwen-… -->) are
filtered out and the warning prose gains the third reading (another
workflow under the same account). Without this, every mid-review push
produced a false accusation the skill is told to relay verbatim.
- Low-Medium: producer contract tests — fetch-pr's report is now pinned
to carry fetchedAt (a real timestamp) and --host, since dropping either
silently turns the audit off with output identical to a clean window.
- Low: every skip path names itself on stderr (note: bypass audit
skipped (…)), so the tripwire's off state is distinguishable from its
all-clear state.
- Low: pre-window comments edited inside the window are flagged as an
edit class of their own — ?since= filters on updated_at, so the rows
were already fetched. Verified empirically that reactions do not bump
an issue comment's updated_at before adding this.
- Low: the empty-window early return skips the currentUser() round trip;
report-derived prNumber is cross-checked against the cleanup target and
ownerRepo is shape-checked before either reaches a gh api path.
- Nits: use the tmpFile helper instead of re-deriving its path; SKILL.md's
fetch-pr snippet now shows --host (the report records it and the audit
queries it — a dropped host silently audits github.com).
* test(review): cover the github.com (host: null) path of the bypass audit
* fix(review): harden the bypass audit — review channel, boundary integrity, provenance
Addresses the second review round on the tripwire:
- Review-channel coverage: submit now records a receipt (the one review
id it was authorised to create, parsed from the POST response), and
cleanup flags any in-window review by the reviewing account the
receipt does not vouch for — `gh pr review` and direct POSTs to
pulls/<n>/reviews were bannable but invisible before. No receipt
vouches for nothing (fail-safe).
- Boundary integrity across restarts: fetch-pr preserves the earliest
window opening as auditSince when it overwrites its own report (the
head-drift rule reruns it), so writes made during an abandoned attempt
stay inside the audit window. A window from a different PR left at the
same path is not inherited.
- Clock skew: the audit boundary backs off two minutes from the recorded
opening — fetchedAt is local time compared against GitHub's server
timestamps, and a fast local clock could otherwise hide the first
moments of the review. Errs toward over-flagging.
- Marker provenance: the automation filter is anchored to the body
START, so a hand-posted summary that merely quotes a marked bot
comment (or hides the marker mid-body) stays visible to the tripwire.
- Named skip fidelity: ENOENT alone means "no fetch report" (any other
read failure names its code); gh failures surface the first non-empty
stderr line instead of the generic Command-failed wrapper.
- Tests: rogue-review flag + receipt exclusion, skew boundary, auditSince
window, edited-warning rendering through runCleanup, malformed-report
table, EACCES vs ENOENT, stderr extraction, marker-quoting visibility,
and producer tests for auditSince preservation.
* fix(review): distinguish a corrupt prior fetch report from an absent one
The auditSince-preservation block swallowed every read/parse error as "no
previous report". A crash mid-write leaves truncated JSON: on the next
drift restart JSON.parse threw, the catch reset auditSince to the new
fetch, and a bypass write from the abandoned attempt escaped the audit
window silently. ENOENT is still the silent first-attempt path; a
non-ENOENT read failure and an unparseable existing report each warn on
stderr that the window may not reach an earlier attempt. Tests cover
corrupt-JSON, ENOENT-silent, and EACCES-named.
* fix(review): accumulate submit-receipt ids across a window, and test the producer
Two gaps in the review-channel bypass audit's receipt contract:
- The receipt was overwritten on every submit, but the audit window spans
drift restarts (fetch-pr preserves auditSince), so two sanctioned
submits could fall in one window — the single-id receipt then vouched
only for the last, and cleanup flagged the earlier legitimate review as
a bypass (a false positive for a write submit itself made). The receipt
now accumulates ids (read prior, append, dedupe); cleanup reads the set
and excludes all of them. Both sides migrate a legacy single `reviewId`.
- The producer half had no test: submit.test.ts's ghMock returns '', so
JSON.parse(response) threw and the receipt write always hit its catch —
the happy path never ran. Added producer tests (id/event/timestamp
written, accumulation across two submits, legacy migration) driven from
inside the fixture dir, plus a cleanup test that spares every id in a
multi-id receipt.
* fix(review): correct SKILL.md prose-wrap-up guidance; de-fragilize fetch-pr mock reset
- SKILL.md told the orchestrator to route a free-form prose wrap-up
through compose-review's input, but ComposeReviewInput has no free-text
body field — the body is computed from structured state, by design (the
model does not author PR-facing prose). Following that instruction would
force the model to misuse a structured field or forge a `body` submit
refuses. Both passages now say the recap belongs in the TERMINAL
summary; the PR receives only submit's computed body plus inline
comments. This aligns the guidance with the submit-only principle rather
than contradicting it.
- fetch-pr.test.ts's producer beforeEach re-set git/gh but not
readFileSync, and clearAllMocks does not reset implementations — so a
mockReturnValue from one test could leak into a later test relying on
the default. The beforeEach now re-asserts the ENOENT default, removing
the ordering dependency.
The receipt-overwrite and receipt-untested suggestions from the same
review were already addressed in
|
||
|
|
a470ba626c
|
feat(review): add comment-status helper for existing-thread triage (#7690)
* feat(review): add comment-status helper for existing-thread triage
One deterministic pass over a PR's existing inline comments, replacing
the per-comment `gh api` fetches the orchestrating model used to make
during /review: anchor validity at the live head (outdated detection,
with a file-level exemption), whether the anchored file changed in the
reviewed worktree since each comment's commit and which commits touched
it (the re-check's candidate "fixed by" list), reply participation and
PR-author response, the blocker signal (same carriesBlockerSignal as
pr-context, so the two surfaces agree by construction), and
worktree-vs-live head drift.
Measured on a heavily discussed PR (72+ inline comments), a single
review run burned 20+ model turns re-deriving exactly these fields one
comment id at a time. SKILL.md now runs the subcommand in Step 1 and
routes the Step 6 re-check's status questions at the report; comment
bodies stay in the pr-context file under its untrusted-data preamble,
and a comment-status failure only warns — it is an index, not the
evidence, so it never sets the context-unavailable state.
* test(review): add comment-status to the subcommand registry expectations
* fix(review): comment-status review follow-ups — size warning, --host wiring, scope clauses
Addresses the review at
|
||
|
|
8f667f5bdc
|
feat(integrations): add retrieval-only external context search (#7586)
* feat(integrations): add direct external context provider Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * fix(integrations): harden external context failure handling Preserve provider timeout classification, reject ambiguous Mem0 statuses, release rejected response bodies, and clarify credential and workspace deployment boundaries. Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * refactor(integrations): narrow external context to retrieval Limit Phase 1 to one provider-bound search tool, remove hooks and writes, and document the direct profile's actual permission and isolation boundaries. Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * fix(integrations): harden external context deployment Pin the managed MCP source through an administrator-owned command-line configuration, document the Direct Profile trust boundary, and remove unused logging/runtime abstractions. Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * fix(integrations): preserve external context results Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * fix(integrations): honor provider proxy settings Install an environment-aware dispatcher before the external context MCP server starts so enterprise egress proxy and NO_PROXY settings apply to provider requests. Document the managed launcher environment and cover startup wiring. Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * fix(integrations): diagnose invalid proxy settings Classify proxy dispatcher construction failures as sanitized configuration errors so managed deployments can identify an invalid proxy environment without exposing proxy credentials. Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> --------- Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> |
||
|
|
638dc9a1c3
|
fix(triage): resolve finalize PRs from the open-PR list, not the commit association (#7706)
Live verification of the finalize loop (#7693) on its first real fork PR caught the deferred approval being silently dropped: CI landed green, the approve-on-green marker was in place, but commits/:sha/pulls returned an empty list for the PR's current head — the association endpoint is not reliable for fork-branch commits (workflow_run.pull_requests is likewise empty for forks). The run logged 'No open PR; nothing to finalize' and exited, so the approval never posted. Resolve PRs by filtering the open-PR list on head.sha as the primary source — it cannot miss the PR a current-head firing belongs to — and keep the association endpoint as the second source (when it works it also surfaces PRs whose head moved past the SHA, which powers the stale note). Union both, deduped. |
||
|
|
52f6eaf8f0
|
fix(triage): resolve stage comment ids by marker at patch time, harden model injection (#7703)
* fix(triage): resolve stage comment ids by marker at patch time, harden model injection Two hardenings from shepherding #7693, plus a wording fix: - Re-run comment updates now resolve the target comment id by its stage marker (bot-author-filtered, startswith match) immediately before each PATCH, instead of trusting remembered ids or list positions. Observed on a real re-run: the agent PATCHed the stage=3 comment with stage=1 content mid-run before self-correcting — with four bot comments in the thread, remembered-id bookkeeping is fragile. - The model-name injection step previously no-opped silently if the 'qwen3.7-max' literal ever left the skill (shipping the wrong signature in every comment), and corrupted the skill text on model names carrying sed metacharacters (/ & \). It now fails the job loudly when the target literal is missing and escapes the replacement. Covered by a behavioral test that runs the extracted step script against fixture files. - The finalize status text said 'stage comments above', but the status comment is created first, so the stage comments are below it — now 'in this thread'. * chore(triage): drop unrelated formatting churn from qwen-triage.yml The previous commit let prettier rewrite untouched lines (runs-on quoting, comment spacing) while formatting the edited step. Restore those lines to main's form; the diff now carries only the injection hardening and the status wording fix. * test(triage): pin the stage_comment_id recipe's load-bearing constraints Guards the startswith match and the bot-author filter in the skill's re-run comment-id recipe against silent regression — a contains match or a dropped author filter re-introduces the wrong-comment-overwrite bug this PR fixes. * test(triage): shim BSD sed only on darwin in the injection test The extracted step script uses GNU 'sed -i' (the step only runs on ubuntu runners), but this suite also runs in the macOS merge-queue job where BSD sed needs an extension argument after -i. Rewrite to sed -i '' on darwin only — on GNU sed a separated '' parses as the sed script, so the unconditional rewrite would break the Linux runs that mirror production. |
||
|
|
d61b0ea475
|
perf(web-shell): paint the composer git chip before git status completes (#7680)
* perf(web-shell): paint the composer git chip before git status completes New sessions gated the chip on a full `git status --porcelain` subprocess behind GET /workspaces/:ws/git, so the branch chip appeared hundreds of milliseconds (worst case seconds) after the composer was ready. The daemon now keeps a per-workspace last-known summary with in-flight dedup and a 2s background-refresh throttle: the default GET returns the cached status (branch-only on a cold start) immediately and recomputes in the background, publishing git_status_changed over SSE only on a delta, while ?wait=1 keeps the previous blocking semantics. The composer fetches both paths concurrently — the fresh GET also covers the no-session state, which has no per-session SSE stream — so the branch paints in ~3ms and the counters land when the computation finishes. The sidebar keeps wait:true since it has no SSE fill-in path. * fix(web-shell): add exhaustiveness guard and worktree git-status test (#7680) * fix(web-shell): add exhaustiveness guard and worktree git-status test (#7680) * fix(web-shell): add exhaustiveness guard and worktree git-status test (#7680) * fix(cli): use writeStderrLineSafe in git-status refresh error path (#7680) * fix(web-shell): add debug trail to fresh-path catch and test branch-watcher dispose guard (#7680) * fix(cli): assert writeStderrLineSafe in git-status refresh failure test (#7680) --------- Co-authored-by: Qwen Code Bot <qwen-code-bot@users.noreply.github.com> Co-authored-by: qwen-code-ci-bot <qwen-code-ci-bot@users.noreply.github.com> |
||
|
|
de1c317724
|
perf(core): keep the volatile auto-memory section last in the system prompt (#7651)
* perf(core): keep the volatile auto-memory section last in the system prompt The managed auto-memory section (instructions + MEMORY.md indexes) is rewritten in-session on every memory save, but it was pre-concatenated into the middle of the userMemory blob — ahead of appendSystemPrompt and git status, which are stable for the whole session. Every save therefore invalidated the prompt-cache prefix from the middle of the system prompt, and the stable/context/volatile layers were indistinguishable in code. Store the auto-memory section separately on Config (getAutoMemoryPrompt) and have every assembly site append it after all stable and context content, yielding a stable -> context -> volatile layout: base prompt, QWEN.md hierarchy + rules, append prompt, git status, auto-memory. Also count the section in /context (previously dropped by the marker parser) and keep /memory show and the context-size warning covering both layers. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * refactor(core): reuse buildSystemPromptSuffix for subagent auto-memory + add regression tests - agent-core.ts: replace the inline auto-memory separator with buildSystemPromptSuffix so the '---' separator and trimming stay in sync with the other assembly sites (client.ts x2, ArenaManager.ts). - client.test.ts: add coverage that a non-empty getAutoMemoryPrompt is appended as the last block of the main-session system instruction. - contextCommand.test.ts: add coverage that a non-empty getAutoMemoryPrompt surfaces an 'auto memory' row in the /context memory breakdown. * fix(core): stop duplicating the auto-memory section in Arena workers ArenaManager pre-appended buildSystemPromptSuffix(getAutoMemoryPrompt()) onto the in-process worker's systemPrompt, but AgentCore.buildChatSystemPrompt already appends the auto-memory section itself when the worker builds its system instruction (and the per-agent Config inherits a non-empty getAutoMemoryPrompt() from the base via Object.create). The section therefore appeared twice in the worker's prompt. Drop the ArenaManager append so the volatile auto-memory layer is added exactly once, by AgentCore, keeping it last. Add regression tests: ArenaManager no longer embeds the auto-memory marker, and generateContent's per-call systemInstruction branch still appends it. * test(core,cli): cover auto-memory layering in headless and /memory paths Address review feedback on #7651: - add an agent-headless test asserting a non-empty getAutoMemoryPrompt is appended as the trailing volatile section of the subagent system prompt - add useShowMemoryCommand tests covering the two-layer (context + auto-memory) concatenation: both non-empty (joined by the section separator), each layer alone (no separator), and both empty * fix(cli): narrow getCombinedMemoryMessage return type to fix build The Message union includes the COMPRESSION variant, which has no content field, so getCombinedMemoryMessage(): Message | undefined made combined!.content fail strict type-checking (TS2339), breaking tsc --noEmit and the packages/cli build in CI. Narrow the return type to the content-bearing Message member via Extract<Message, { content: string }> and give find() a type-guard predicate so the narrowed type flows to callers. * fix(core): clarify context-size warning covers auto-memory too The memory context-size warning is fed the combined size of the context files (getUserMemory) and the auto-memory section (autoMemoryPrompt), but its text only named "QWEN.md/context instructions". Broaden the message to "always-on context (QWEN.md context files + auto-memory)" so users know the auto-memory index also counts toward the estimate, and update the assertions. * test(core): assert auto-memory prompt is cleared in safe mode The safe-mode branch of refreshHierarchicalMemory clears this.autoMemoryPrompt, but the safe-mode test only asserted getUserMemory() and getGeminiMdFileCount(). Add an assertion that getAutoMemoryPrompt() is empty so a future refactor dropping that line cannot silently leak the auto-memory section into safe-mode system prompts. * fix(core): stop duplicating the auto-memory section in the remember agent The managed remember agent's system prompt already embeds the full auto-memory protocol and MEMORY.md indexes via buildCleanMemorySystemPrompt (forceFullProtocol). After splitting auto-memory into a separate Config.getAutoMemoryPrompt() field, AgentCore.buildChatSystemPrompt appends it a second time on every managed remember run, duplicating the whole section and, in clean mode, re-injecting parent-session memory into the intended blank-slate agent. Zero out getAutoMemoryPrompt() on the forked-agent config for all context modes so the section is present exactly once (via the remember prompt), and keep clearing getUserMemory() in clean mode. Add regression coverage for both clean and non-clean modes. * test(core): assert managed auto-memory prompt is standalone --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
cf6b8a0e6b
|
perf(cli): cache GitHub PR list in the daemon route with a 60s TTL (#7705)
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> |
||
|
|
efdcb63936
|
fix(web-shell): add :focus-visible outline to GitHub PR list rows (#7704)
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> |
||
|
|
f4e333c580
|
fix(mcp): harden OAuth callback handling (#7510) | ||
|
|
e560f8e41f
|
fix(cli): clear stale retry error when agent auto-recovers mid-turn (#7681)
* fix(cli): clear stale retry error when agent auto-recovers mid-turn When a transient API error (e.g. UND_ERR_SOCKET: other side closed) occurs during a tool-use loop, handleErrorEvent sets a static pendingRetryErrorItem with a "Press Ctrl+Y to retry" hint. If the stream processor auto-retries the failed call and the agent completes the turn successfully, the error message lingers on screen because the turn-completion path only clears countdown-based errors, not static ones. Additionally, lastPromptErroredRef stays true, causing the turn to be reported as failed (onDeliveryFailed) even though it succeeded. Fix: in the turn-completion success path, if a static retry error is still showing (no active countdown timer), clear it and reset the errored flag. This correctly handles the auto-recovery case without affecting the existing behavior where errors that truly end the turn keep their retry hint visible. * fix(cli): gate stale-error clearing on non-terminal turn (#7681) The previous else-if branch cleared pendingRetryErrorItem whenever it was set and no countdown timer was active — including after terminal Error events. Since handleErrorEvent always clears the timer before setting the error item, every fatal API error hit this branch, silently swallowing the error and reporting the turn as delivered. Gate on !lastPromptErroredRef.current so only countdown-originated errors (from successful auto-retry) are cleared; terminal errors remain visible with the Ctrl+Y hint. Add regression tests for both paths. * fix(cli): clear stale countdown item on auto-recovery (#7681) --------- Co-authored-by: qwen-code-dev-bot <qwen-code-dev-bot@users.noreply.github.com> Co-authored-by: Qwen Code Bot <qwen-code-bot@users.noreply.github.com> |
||
|
|
a4f5e50d19
|
feat(web-shell): add read-only GitHub pull requests panel (#7683)
* feat(web-shell): add read-only GitHub pull requests panel Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * fix(web-shell): address review findings for GitHub PRs panel Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * fix(web-shell): clamp GitDialog view when PR capability is withdrawn mid-session Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * fix(web-shell): address review feedback for GitHub PRs panel (#7683) - Add workspace_github_prs to integration test baseline capabilities - Sanitize git root path in error responses to prevent path leakage when workspace is a repo subdirectory - Add NEUTRAL check-run conclusion test case - Add not.toContain path-leak assertion for sanitization test - Add pending checks indicator UI test - Add timeAgo utility unit test * fix(web-shell): address review feedback for GitHub PRs panel (#7683) - Sanitize workspace paths before truncating the error message so a path straddling the 512-char display boundary is redacted, not cut mid-token - Render a badge for the review_required decision instead of leaving it dead - Align PR row icon sizes (12px) with sibling git dialogs --------- Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> 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> |
||
|
|
331d58c652
|
fix(core): allow reading saved plan files without a confirmation prompt (#7678)
The default plans dir (~/.qwen/plans) sits outside the workspace and was in none of ReadFileTool's permission-free roots, so reading a saved plan back landed on an ask confirmation — popped at exactly the moment the user approved the plan and told the agent to start coding, and resolvable as a denial in non-interactive/ACP flows. With the approved-plan pointer (#7197) the saved file is the model's only recovery route for the plan text, so the read must not stall on a prompt. Adds config.getPlansDir() to ReadFileTool.getDefaultPermission's allowedRoots and to AcpAgent.buildAcpLocalReadRoots (per the SYNC comment). The dir holds only session plan files; sibling ~/.qwen files such as settings.json stay confirmation-gated, pinned by a new test. Refs #6237 Co-authored-by: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
a76a0feedb
|
fix(core): give plugins from the same repository distinct extension ids (#7676)
* fix(core): give plugins from the same repository distinct extension ids getExtensionId() hashed only the normalized repo URL, so two plugins installed from one marketplace repo (e.g. dotnet and dotnet-test from github.com/dotnet/skills) collided on the same id and the second install failed with 'Extension id belongs to "dotnet", not "dotnet-test"'. The plugin name is now appended to the hash input when present. Because the formula change would strand existing installs (the store would mint a fresh default policy under the new id, resetting activation state, and the orphaned old policy would trip the name-conflict guard on update/uninstall), ExtensionStore.ensureInitialized now re-keys a stored policy to a loaded identity's id when the id is unknown but the unique name matches and no loaded extension still owns the old entry. Fixes #7568 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * test(core): pin case-insensitive matching in the store re-key migration Seeds a policy under 'DotNet', re-keys it via an identity named 'dotnet', and asserts the policy moves with its activation state and the stored name normalizes — so a future simplification to case-sensitive matching fails a test instead of silently orphaning differently-cased installs. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
a3d78c9594
|
fix(core): tell the model when the user manually exits plan mode (#7682)
* fix(core): tell the model when the user manually exits plan mode While plan mode is active the plan-mode system reminder is re-injected on every model-bound turn, so after a manual exit (Shift+Tab, /approval-mode, /plan, ACP mode switch) the reminder just silently stops appearing — a non-signal models do not reliably notice. The model's most recent context still says plan mode is active, so it keeps calling exit_plan_mode and gets stuck (#7671, problem 1). Config.setApprovalMode now queues a one-shot notice on every PLAN -> non-PLAN transition except the approved exit_plan_mode flow (which passes the new fromApprovedPlanExit option); re-entering plan mode clears a stale notice. GeminiClient's system-reminder assembly consumes the flag on the next turn and injects an explicit "the user has manually switched out of plan mode" reminder naming the new mode. Fixes the first half of #7671; the deny-message half is #7673. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * test(core): pin the leader-approval exit option and the exit-reminder text Adds the two review-suggested pins: a successful leader-approved exit asserts setApprovalMode receives { fromApprovedPlanExit: true } (only the regular approval site was pinned), and getManualPlanExitSystemReminder gets dedicated prompts tests covering the rendered mode name, the exit_plan_mode prohibition, and the reminder envelope. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
2cc7da4cef
|
fix(core): exit_plan_mode returns guidance error from execute() instead of permission deny (#7673)
* fix(core): exit_plan_mode returns guidance error from execute() (#7671) When the model calls exit_plan_mode outside plan mode (e.g. after the user manually switched modes via Shift+Tab), it previously got a generic permission deny error that gave zero guidance. Changed getDefaultPermission() to return 'allow' instead of 'deny' when not in plan mode — this is a state issue, not a security issue, so the permission layer should not block it. The execute() method now checks approvalMode !== PLAN (with no approval snapshot) and returns a context-aware errorResult telling the model what happened and what to do instead. This also fixes the YOLO mode issue where a permission deny error was semantically wrong. * fix(core): cover getConfirmationDetails() outside-Plan guidance path (#7671) The guidance error for outside-Plan exit_plan_mode calls was only reachable through execute(). A PM ask rule or a Plan-to-non-Plan mode switch between permission evaluation and confirmation construction routes through getConfirmationDetails() instead, which still threw a generic error. Extract outsidePlanGuidanceMessage() and reuse it in both getConfirmationDetails() (throw) and execute() (errorResult) so the model receives actionable guidance on every reachable path. Add scheduler-level regression tests for both bypass paths and update the design doc failure-behavior section. * fix(core): use StructuredToolError and ToolErrorType for exit_plan_mode guidance (#7671) --------- Co-authored-by: qwen-code-dev-bot <qwen-code-dev-bot@users.noreply.github.com> Co-authored-by: Qwen Code Bot <qwen-code-bot@users.noreply.github.com> Co-authored-by: Qwen Code Autofix <qwen-code-autofix@users.noreply.github.com> |
||
|
|
451bcad991
|
fix(core): write a status sidecar so models stop misreading quiet background shells (#7669)
* fix(core): write a status sidecar so models stop misreading quiet background shells A background shell whose child block-buffers stdout (typical for Python/ML jobs without a TTY) keeps its output file at 0 bytes for its entire run. The launch message only said "read the output file", so the model's sole liveness heuristic became "empty file = dead process" — and it would relaunch a still-running job, doubling CPU/GPU usage (#7626). The registry now mirrors every entry into a machine-readable JSON sidecar (`shell-<id>.status`, next to `.output`, same ReadFileTool auto-allow rules): written on register and on every terminal transition, including the `abortAll()` batch path so CLI exit settles sidecars too. Contents are a pure projection of the entry (status, pid, command, cwd, ISO timestamps, exitCode/error), written via temp-file + rename so readers never see a torn document; write failures are logged and swallowed, mirroring the output-stream error handling. Written at the registry rather than in the tool because both launch sites (executeBackground and the promoted-foreground path) and all four settle entries converge there, and the single statusChange callback slot is already taken by the UI. Both launch messages now name the status file and teach the correct heuristic: do NOT infer liveness from the output file; block-buffering keeps it empty while the process is alive (use `python -u` / `stdbuf -oL` for live output). Covered by registry unit tests (every transition, atomicity, failure swallowing), launch-message assertions for both paths, and a real-spawn integration suite replicating the reported scenario: quiet child → sidecar `running` with pid while the output file is empty → `completed` on exit, plus `failed` and `cancelled` variants. Fixes #7626 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * refactor(core): share the status-file guidance between both launch paths Review on #7669 caught the two copies already drifting: the promote path omitted the actionable unbuffering hint (`python -u` / `stdbuf -oL`) that executeBackground includes. Extract the guidance into one helper used by both paths so they cannot drift again, and pin the promote path's hint with test assertions. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * refactor(core): use atomicWriteFileSync for status sidecar writes Replaces the hand-rolled tmp+rename with the shared atomicWriteFileSync utility, gaining EPERM/EACCES rename retry with exponential backoff, random temp-file suffixes, and orphan cleanup on failure. * Update packages/core/src/tools/shell.ts Co-authored-by: qwen-code-ci-bot <qwen-code-ci@service.alibaba.com> * fix(core): skip fsync and restrict permissions on status sidecar (#7669) * fix(core): force 0o600 and noFollow on status sidecar writes (#7669) --------- Co-authored-by: ComplexSimply <rudy.arrowsong@gmail.com> Co-authored-by: Claude Fable 5 <noreply@anthropic.com> Co-authored-by: Qwen Code <qwen-code@users.noreply.github.com> Co-authored-by: qwen-code-ci-bot <qwen-code-ci@service.alibaba.com> Co-authored-by: qwen-code-ci-bot <qwen-code-ci-bot@users.noreply.github.com> |
||
|
|
541c80d678
|
feat(serve): expose workspace Channel management API (#7637)
* feat(serve): expose workspace Channel management API * fix(cli): add workspace boundary guards to stop and remove channel methods (#7637) * fix(cli): defer channel management runtime loading * test(serve): cover channel management capability * fix(serve): scope channel ownership to workspace and address review feedback (#7637) * fix(serve): scope assertOwnedRuntime to workspace and add no-store to mutation routes (#7637) * fix(serve): serve channel-types without resolving management service (#7637) * fix(serve): add validateClient to GET /channels and expand invalid-client test coverage (#7637) * fix(serve): prevent double 400 response when both name and body validation fail (#7637) * test(serve): assert workspace reload is blocked * test(serve): assert workspace reload is blocked (#7637) * test(serve): expand route test coverage for review suggestions (#7637) * refactor(cli): compose workspaceCommittedNames from workerFor to remove duplicated predicate (#7637) --------- Co-authored-by: qwen-code-dev-bot <qwen-code-dev@service.alibaba.com> Co-authored-by: Qwen Code Bot <qwen-code-bot@users.noreply.github.com> Co-authored-by: qwen-code-ci-bot <qwen-code-ci-bot@users.noreply.github.com> |
||
|
|
effb59ff73
|
fix(acp): sweep review worktree leases at the end of each prompt turn (#7694)
The ACP prompt path never entered promptIdContext — only the TUI (useGeminiStream) and headless (nonInteractiveCli) entry points do — so shell subprocesses in daemon sessions saw an empty QWEN_CODE_PROMPT_ID and `qwen review fetch-pr` silently skipped recording its worktree lease. A cancelled or errored /review in a Web Shell session therefore left .qwen/tmp/review-pr-<n> and the qwen-review/pr-<n> branch behind until the next review of the same PR happened to clean them up. - Bind promptIdContext in #executePromptInner (enterWith, mirroring the sessionIdContext wrapper in #executePrompt) so lease creation works and shell subprocesses can identify the prompt that spawned them. - Sweep the prompt's leases in the turn-wide finally, unconditionally like the headless path: the ACP loop runs whole turns, so unlike the TUI's per-continuation submitQuery this can never fire mid-review. No-op when the review's own cleanup step already released the lease. |
||
|
|
1f9318f974
|
feat(triage): stop in-agent CI polling, finalize evidence and approval after CI completes (#7693)
* feat(triage): stop in-agent CI polling, finalize evidence and approval after CI completes
The triage agent's Stage 2b polled pending checks for up to 10 minutes, but
this repo's unit suite runs ~30 minutes, so the poll always burned its full
budget, gave up with 'CI still running', and Stage 3 could then approve before
the suite finished (observed on a PR approved 12 minutes before its Test job
completed).
Split the wait out of the agent entirely:
- pr-workflow.md Stage 2b now forbids polling: fetch check-runs once, report
pending checks honestly, and wrap the CI table in qwen-triage-ci region
markers keyed to the reviewed SHA.
- Stage 3 defers a clean-verdict approval when checks are still pending: the
comment carries an approve-on-green marker instead of an immediate APPROVE.
- New qwen-triage-finalize.yml fires on workflow_run completion of 'Qwen Code
CI' / 'E2E Tests' and, with plain bash over the API (no model, no checkout),
rewrites the marked table region with the settled results and posts the
commit-pinned approval only when every check landed green — failing closed
on red checks, a moved head, or a closed/draft PR, and flipping the triage
status comment to say which way it resolved.
Markers are honored only in comments authored by the bot identity itself, and
check names (attacker-influenced on fork PRs) go through the same HTML-escape
chain the skill mandates for file paths.
Stage comments now land ~10 minutes sooner and the approval, when deferred,
lands at CI completion with full evidence instead of before it.
* fix(triage): address finalize review — broken red gate, table truncation, dead trigger
Review findings on the finalize workflow, all reproduced before fixing:
- Blocker 1: the RED jq used the array-first membership form, where | rebinds
. and .conclusion indexes an array — jq exits 5 every run, RED comes back
empty, [ "" -gt 0 ] errors, and control falls through to the approve path:
a red CI auto-approved. The gate now binds the conclusion before the
membership test (IN(...)), and the counters are numeric-validated so any
future jq failure reads as 'cannot attest', never 'approve'.
- Blocker 2: the table rendered raw check-runs — on a real PR (96 runs, 35
names, 68 skipped) alphabetical sort + head -60 truncated away every actual
test job. table_rows now dedups per name (latest run), drops skipped rows,
and sorts running/non-green first so the cap can only cut green rows.
Replayed against the same PR: 96 rows -> 16, unit suite present.
- The approval gate now reads workflow runs filtered to event=pull_request
(deduped per workflow) instead of head-SHA check-runs, which also carry
long-running bot orchestration jobs that would wedge PENDING above zero at
the exact moment the last CI workflow fires — silently dropping the
deferred approval forever. The skill's Stage 3 PENDING count matches.
- E2E Tests had no pull_request trigger (dead entry); the workflows list is
now exactly the six pull_request-triggered workflows, so the last finisher
always re-fires the job.
- Head/state re-check moved before the red/deferred verdicts so a
cancel-in-progress firing on a stale SHA cannot stamp a red status over
the new head's comment; the still-deferred branch now updates the status
comment instead of staying invisible.
- replace_region fails closed when the end-marker text only precedes the
begin marker (awk END guard) — previously that shape truncated the comment
body, eating the signature and reviewed-commit footer.
- Region content is deterministic (no run URL) so the no-op cmp works;
empty run list or unavailable gate skips approval; comment wording fixed
(workflow_run jobs are attributed to the default branch, so the self-check
exclusion is belt-and-braces, not load-bearing).
Tests now execute the decision logic, not just grep for it: gate_counts and
table_rows run against fixtures covering every conclusion class, non-PR
events, re-run dedup, skipped filtering, ordering, and both marker-order
failure shapes. 30/30 passing.
* fix(triage): keep a stale finalize firing from clobbering the newer review's status comment
The status comment is deliberately not SHA-scoped (the triage workflow
creates it unscoped; scoping only the finalize side would orphan the
pairing), so a finalize firing for an old SHA that loses the race against a
newer head's green approval would overwrite the ✅ status with a stale
warning. Guard the stale path: when the current head already carries bot
sha= markers (a re-review owns the status comment), stay silent; when the
head moved with no re-review yet — triage does not auto-rerun on
synchronize — the stale note is accurate and still posts. Closed/draft PRs
now just log instead of flipping the status.
* fix(triage): close the guardrail bypass and align the finalize table with the gate
Second review round, all four findings reproduced or confirmed before fixing:
- The approve-on-green marker was emitted in Step 1 while the fork-refactor
GUARD only ran in Step 2 — a marker that slipped out on a fork refactor
would have been honored by the finalize job on green CI, bypassing the
guardrail entirely. GUARD now computes in Step 1 and gates the marker's
emission, and the finalize job re-asserts it structurally from the PR
state it already fetched (null head.repo = deleted fork = blocked), with
a 'guarded' status message instead of an approval.
- table_rows now restricts check-runs to the suites of the same deduped
event=pull_request workflow runs the gate trusts. Without it, 5 of 8
rendered rows on this PR's own head were bot plumbing presented as CI
evidence; with it, 115 raw check-runs reduce to exactly the 3 CI rows.
- A firing that saw PENDING>0 after the approval landed flipped the status
comment back to 'deferred' with nothing to ever right it; the
already-approved branch now repairs the status.
- Zero surviving table rows (failed runs fetch, missing suite ids) skips
the region rewrite instead of blanking the agent's table, and
replace_region refuses an empty region file (an unchecked getline would
have deleted the region and its markers unrecoverably).
Nits: the house github.repository guard on the job, the table header
matches the skill template, and the run-URL stays out of the region so the
no-op cmp keeps working.
|
||
|
|
3493dab8a0
|
test(web-shell): capture the git-mode new-branch sub-state in the visuals suite (#7672)
* test(web-shell): capture the git-mode new-branch sub-state in the visuals suite The `git mode selector` visuals scenario captured the composer chip and the opened three-mode popover, but stopped there: selecting an option used to dismiss the popover ~100ms later (the click bubbled through the React tree out of the portaled content to the composer surface's onClick → core.focus() → Radix focus-outside close), so the branch-name sub-state couldn't be shot stably. #7668 fixed that dismissal, so it now can. Extend the scenario to click "New branch", fill a valid branch name, and capture the revealed input (validated) with its Create-branch affordance, in both themes. All six git-mode captures are byte-stable across runs (0% pixel diff). Match the option by role — its label is split across a name and a description span, so getByText('New branch') is ambiguous (also fixed in #7668). Beyond covering a state the preview never showed, this doubles as a visual regression guard for #7668: if the popover ever dismisses on option-click again, the input goes missing and the assertion fails here, not only in the screenshot. * test(web-shell): strengthen git-mode branch assertion and trim comment (#7672) * test(web-shell): harden git-mode branch capture into a real #7668 guard Scope the New branch option to the popover locator and settle past the ~100ms dismissal window before re-asserting the popover and input stay visible, so a regression of #7668 hard-fails here instead of only producing a wrong (visually reviewed) screenshot. Mirrors the proven guard in web-shell.git-mode.spec.ts. --------- Co-authored-by: wenshao <wenshao@example.com> Co-authored-by: qwen-code-ci-bot <qwen-code-ci-bot@users.noreply.github.com> |
||
|
|
1183a4c821
|
feat(core): add Goal v3 runtime orchestration (#7664)
Some checks are pending
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
E2E Tests / cron-interactive E2E (nightly) (push) Waiting to run
E2E Tests / web-shell Browser Regression (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
* feat(core): add Goal v3 runtime orchestration * fix(core): remove unused goal runtime paths |
||
|
|
65b4a5a383
|
fix(ci): update qwen in the runner's active npm prefix (#7689)
* fix(ci): update qwen in runner npm prefix * test(ci): cover writable runner prefix install |
||
|
|
055523afab
|
feat(core): Align GenAI content telemetry fields (#7667)
* feat(core): align GenAI content telemetry fields Capture provider-final GenAI messages and tool payloads with the shared ARMS/OpenTelemetry field contract, and retire equivalent private content aliases. Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * fix(telemetry): address content observability review Keep ACP tool telemetry best-effort, improve diagnostics and sensitive-off coverage, and document finish-reason and tool-description behavior. Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * docs(telemetry): clarify optional tool parameters Document that invalid optional parameter schemas are omitted while required tool identities remain ordered and complete. Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * docs(core): clarify telemetry compatibility behavior Document the changed semantics of deprecated helpers and the reason the fallback context shadows key operations. Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> --------- Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> |
||
|
|
2da42099d4
|
fix(ci): don't fail triage cleanup when there is nothing to clean (#7688)
The 'Clean stale agent state' step strips non-allowlisted keys from the persistent workspace's local git config through a `git config --list | grep -ivE <allowlist> | while ...` pipeline. When the config holds only allowlisted keys — the steady state on a reused runner this step already sanitized, since actions/checkout's post step removes its auth extraheader at job end — grep matches nothing and exits 1. Under the default `bash -e` shell combined with the script's `set -o pipefail`, that kills the step exactly when there is nothing to clean, before any output, and every downstream triage step is skipped (seen on run 30095456731, runner ecs-qwen-runner-sg-4). Guard the grep with `|| true` so an empty match feeds an empty loop instead of failing the job. Sanitization behavior is unchanged: non-allowlisted keys (core.pager, include.path, `!`-aliases) are still stripped. The workflow test harness missed this because its allowlist test re-assembles the pipeline without the step's shell flags and always plants non-allowlisted keys first. Add a steady-state regression test that runs the step's actual script under `bash -e` against a config holding only allowlisted keys, plus a negative control that strips the guard and demands the step die — red on the old workflow, green now. Co-authored-by: verify <verify@local> |
||
|
|
b1ce0c2087
|
refactor(autofix): extract review verification runner (#7644)
* refactor(autofix): extract review verification runner * test(ci): follow extracted autofix verifier * docs(autofix): document the review verification runner env contract (#7644) |
||
|
|
2051a41739
|
fix(cli): measure insight days and hours in local time everywhere (#7670)
Some checks are pending
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
E2E Tests / cron-interactive E2E (nightly) (push) Waiting to run
E2E Tests / web-shell Browser Regression (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 / ubuntu-latest / Java 21 (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
The /insight pipeline measured "a day" inconsistently: heatmap keys were UTC (toISOString), the active-hours histogram bucketed by local hour in the same loop, the ASCII renderer looked keys up by local date, and the web renderer mixed a local grid cursor with UTC lookup keys. For non-UTC users the ASCII heatmap lit the wrong cell, the web heatmap hung values under weekday labels off by one day, and a UTC-string parse followed by local normalization shifted days for negative offsets. Per the maintainer decision on #6835, local time is now the single convention, defined in one module — insight/dates.ts (dayKey / parseDayKey / todayKey / hourOfDay) — that every producer and consumer goes through: DataProcessor aggregation, streak calculation, the ASCII renderer, the report filename, and the web renderer (via a same-shaped twin, since web-templates cannot import from the cli package). If the convention is ever revisited, that one file changes. parseDayKey builds local midnight directly, fixing the negative-offset day shift; day diffs round rather than floor so DST-shortened days still count as one day. calculateStreaks also gets the semantics its empty guard block was reaching for: currentStreak now means "the streak ending today or yesterday, else 0" — previously a user inactive for months still showed their last streak as current. Existing tests asserting the trailing- streak behavior are updated, with new relative-date cases pinning today/yesterday/two-days-ago boundaries. No stored data migrates: heatmap, streaks, and active-hours are re-aggregated from raw timezone-aware ChatRecord timestamps on every run. The /stats services already key by local date, so this aligns the repo on one basis. Fixes #6835 Co-authored-by: ComplexSimply <rudy.arrowsong@gmail.com> Co-authored-by: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
9e7acec863
|
chore(release): v0.21.0 (#7675)
* chore(release): v0.21.0 * docs(changelog): sync for v0.21.0 --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> |
||
|
|
1eb1523ad4
|
docs(triage): scale PR verification to the change, add real-run depth (#7648)
* docs(triage): scale PR verification to the change, add real-run depth /triage already drives a real tmux before/after (installed vs dev build). But where it matters most that floor is not enough: a UI change's highlight/caret is invisible in capture-pane text, build/test numbers from a shared or symlinked tree can be environmental TS errors not the PR's, and a perf claim went unmeasured. Strengthen Stage 2b to scale the evidence to the change, pointing at harnesses the repo already ships: the terminal-capture skill (node-pty -> xterm.js -> pixel-accurate PNG) for UI/interaction changes with a named on-screen oracle; a clean build for the numbers cited as evidence (a symlinked node_modules surfaces spurious cross-package TS errors); instrumenting the real built code for a measured before/after on perf changes; and separating merge-blockers from standing follow-ups with a reproducible methodology note. Docs/refactor PRs stay N/A. * docs(triage): align Mandatory and BEFORE POSTING checks with N/A escape hatch (#7648) * docs(triage): add N/A escape hatch to the tmux-output mandate (#7648) * docs(triage): restate CI boundary and fork-sandbox ref in scale-evidence block (#7648) * docs(triage): align tmux summary table and SKILL.md with conditional mandate (#7648) * docs(triage): extend BEFORE POSTING gate to check evidence depth per PR type (#7648) --------- Co-authored-by: wenshao <wenshao@example.com> Co-authored-by: qwen-code-ci-bot <qwen-code-ci-bot@users.noreply.github.com> Co-authored-by: Qwen Code <qwen-code@users.noreply.github.com> |
||
|
|
cc742ca31e
|
fix(web-shell): keep git mode popover open when picking branch/worktree (#7668)
Clicking the "New branch" or "Worktree" option dismissed the popover
instead of revealing the branch-name input / confirm button. The option
click bubbles as a React synthetic event through the portal up to the
composer surface onClick, which calls core.focus() and moves focus
outside the popover — tripping the Radix focus-outside dismissal (the
popover only guarded the pointer path via onInteractOutside).
Stop click propagation on the popover content, matching the composer
ToolbarPopover pattern in ChatEditor. Also fix the e2e selectors
(getByText('New branch') matched both the name and description spans)
and add a delayed still-open assertion so the flash-then-dismiss
regression cannot false-pass.
|
||
|
|
1130865949
|
fix(web-shell): show full session names on hover (#7662)
* fix(web-shell): show full session names on hover Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * test(web-shell): cover archived session tooltip attribute (#7662) --------- Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> Co-authored-by: Qwen Code Autofix <qwen-code-autofix@users.noreply.github.com> |
||
|
|
b30a4c27d9
|
fix(cli): align all TUI icon columns to a uniform 2-col width (#7633)
* fix(cli): align all TUI icon columns to a uniform 2-col width
Remove the extra left padding (paddingX=1) from ToolMessage and
CompactToolGroupDisplay that caused tool status icons (✓, ✗) to be
indented relative to the assistant message prefix (◆).
Reduce STATUS_INDICATOR_WIDTH from 3 to 2 so the tool status indicator
column matches the prefix width used by conversation and status
messages. Add flexShrink={0} to prefix boxes that were missing it.
Unify CompressionMessage, SummaryMessage, and MemorySavedMessage to
use the same fixed-width prefix box pattern (width=2, flexShrink=0)
instead of ad-hoc marginRight or minWidth approaches.
Restructure tool_use_summary in HistoryItemDisplay to use the
standard prefix box pattern instead of inline paddingLeft.
This ensures all icons (◆, ✓, ✗, ●, △, etc.) start at the same
column and all text content begins at a uniform offset, regardless
of whether the icon glyph is 1 or 2 terminal columns wide.
* fix(cli): address review feedback on icon alignment PR
- Remove dead COMPACT_GROUP_HORIZONTAL_PADDING constant (now 0)
and its no-op subtraction from the height estimation formula.
- Reduce TMUX_SPINNER_FRAMES from 3-char to 2-char equivalents
('. ' / '..') so they fit the narrowed 2-col indicator box
without overflowing in tmux sessions.
* fix(cli): force narrow presentation for ambiguous-width TUI icons
Append VS15 (U+FE0E, Variation Selector 15) to all East-Asian-Width
'Ambiguous' icon glyphs (◆ ● △ ○ ◎ ※ ∴ ∵ ★ ◉) via a central ICON
constant map in constants.ts. VS15 forces the terminal to render these
glyphs in their narrow (1-column) text presentation, matching
string-width's default ambiguousIsNarrow=true calculation.
Without this, CJK terminals render ambiguous glyphs as 2 columns while
Ink's layout engine allocates 1, causing a 1-column visual drift that
breaks icon/text alignment in the conversation view.
25 files updated to use ICON.XXX constants instead of raw string
literals for ambiguous icons.
* fix(cli): update test assertions for VS15 icon changes
- Fix 17 inline test assertions across 7 test files to match
VS15-appended icon output
- Fix MarkdownDisplay.tsx: use stringWidth(prefix) instead of
prefix.length to correctly measure display width of icons
that include VS15 (a zero-width code unit that .length counts
but stringWidth ignores)
* fix(cli): update CronPill/SettingsDialog for VS15 icon changes
- Fix CronPill test assertion for ◎ with VS15
- Update SettingsDialog to use ICON.CIRCLE_FILLED instead of raw ●
- Fix 10 SettingsDialog test assertions for ● with VS15
- Update SettingsDialog snapshots
* fix(cli): address maintainer review feedback on PR #7633
- Fix ToolGroupMessage width regression: split innerWidth so
ToolMessage gets full contentWidth (no longer needs -2 since
paddingX was removed) while ToolConfirmationMessage keeps -2
(it still has its own padding={1})
- Fix stale '3-char' comment in GeminiRespondingSpinner → '2-char'
- Add comment explaining minWidth vs width asymmetry in
ToolStatusIndicator (minWidth allows growth for tmux spinner
frames and test mocks)
* fix(cli): add VS15 to ◐ (U+25D0) ambiguous icon in todo components
◐ (CIRCLE WITH LEFT HALF BLACK) is East-Asian-Width Ambiguous.
Added ICON.CIRCLE_LEFT_HALF constant and updated StickyTodoList
and TodoDisplay to use it.
* fix(cli): strengthen test assertion and clarify VS15 comment
- HistoryItemDisplay test: restore spatial assertion to
toContain('◆\uFE0E Hello') instead of split checks
- constants.ts: clarify that VS15 is zero-width in string-width
but forces narrow terminal presentation
* fix(cli): update StickyTodoList test assertion for ◐ VS15
---------
Co-authored-by: 秦奇 <gary.gq@alibaba-inc.com>
|
||
|
|
f8014652a5
|
test(triage): regression-guard the triage workflow, and make the git cleanup an allowlist (#7660)
Guards the security-critical invariants of qwen-triage.yml that broke silently once already — the `settings_json:` input name was wrong, so the action dropped it and the review agent ran with the full default toolset and no deny list. A new `node:test` suite (wired into the shared HELPER_TESTS list both CI paths run) asserts: the `settings:` input name (never `settings_json:`), the tools.core registration whitelist and the deny list, the fork-PR runner routing invariants, and the git exec-vector cleanup. It also flips that cleanup from a best-effort denylist — which kept missing new families (pager, filter.*, includeIf subsections, url.*, credential…) — to a keep-known-safe allowlist: unset every local config key that isn't plumbing actions/checkout needs (repo format, remote, branch, fetch/gc/pack/index, safe.directory, extensions, submodule url/active/branch — not submodule.*.update, which can be `!cmd`). This closes the whole exec-vector class, including knobs not yet enumerated. The harness runs the workflow's actual allowlist pattern against a scratch repo to prove it unsets every exec family and preserves the checkout plumbing. Co-authored-by: verify <verify@local> |
||
|
|
4c2b48115b
|
feat(core): add bounded Goal evidence verification (#7639) | ||
|
|
d550aeabee
|
fix(triage): actually restrict the CI review agent's tools (#7647)
The `settings_json:` input on the Qwen Code action does not exist — the action
reads `settings:`. The block was silently dropped ("Unexpected input(s)
'settings_json'" in the run logs), so the triage agent ran with the full
default toolset and no restrictions in a job that carries a write PAT.
- Rename to `settings:` and express it in the current schema (tools.core +
permissions.deny); verified to load through the real settings pipeline
(11 tools registered, 106 deny rules active).
- Deny interpreters, build tools, shells, network binaries, path execution, and
the git/gh write subcommands that execute configured commands or materialize
PR code. This is defense-in-depth, NOT a boundary: under the action's --yolo a
command denylist cannot be one (`$(...)` is not reliably deny-matchable, and
exec can hide in other commands) — see the in-file note. The real controls are
the skill's no-PR-code rule, ephemeral runners for fork PRs, and the git
exec-vector cleanup added here. Residual token-exfil-under-injection risk is
documented, with token isolation flagged as the structural follow-up.
- Route fork PRs (and comment/dispatch reruns, which may target fork PRs) to
ephemeral hosted runners so a steered agent cannot persist on the shared ECS
pool. Issue triage and same-repo PRs keep the ECS pool.
- Wipe stale git hooks/config/aliases each run before checkout.
Depends on the skill change that switches test evidence to the CI API and the
CHANGELOG fetch to `gh api`; merge that first so the npm/curl denials are
harmless.
Co-authored-by: verify <verify@local>
|
||
|
|
a0b9512003
|
feat(core): add configurable image generation models (#7607)
* feat(core): add configurable image generation models * fix(core): keep undici out of ACP bundle * fix(core): address review feedback for image generation (#7607) - Use loadUndici() instead of direct import('undici') in downloadPng to handle esbuild CJS bundling where named exports are unavailable - Check response.ok before parsing JSON body so non-JSON error pages (e.g. 502 HTML) produce structured HTTP status errors - Use matched.baseUrl instead of matched.registryBaseUrl in the image model handler for consistency with the vision model handler - Add zh-CN and zh-TW translations for ImageGen tool display name, model command description with --image, and all new image model UI strings (fixes i18n test failures) - Add tests: redirect-following path, max redirect limit, non-JSON error body, permission-disabled registration, imageOnly vision guard * fix(cli): add missing English i18n keys for image model feature (#7607) * fix(core): prevent signed-URL leak via error cause chain in image-gen (#7607) * fix(core): add web-shell image_gen display name and fix safe-mode re-read (#7607) --------- Co-authored-by: qwen-code-dev-bot <qwen-code-dev@service.alibaba.com> Co-authored-by: Qwen Code Bot <qwen-code-bot@users.noreply.github.com> Co-authored-by: Qwen Code Autofix <qwen-code-autofix@users.noreply.github.com> Co-authored-by: Shaojin Wen <shaojin.wensj@alibaba-inc.com> Co-authored-by: qwen-code-ci-bot <qwen-code-ci-bot@users.noreply.github.com> |
||
|
|
4c3bf1c13a
|
feat(channels): run loops in daemon workers (#7641)
Some checks are pending
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
E2E Tests / cron-interactive E2E (nightly) (push) Waiting to run
E2E Tests / web-shell Browser Regression (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
* feat(channels): run loops in daemon workers * fix(channels): preserve loop workspace rejection |
||
|
|
2a97c55ac8
|
feat(review): follow the session output language for runtime task names (#7653)
/review's user-facing runtime — the Agent tool description each subagent runs under, the progress narration between steps, the Step 6 terminal report — was English regardless of the session's Output Language, while the posted artifacts already follow the PR's language. Split the two registers: everything that lands on the PR keeps matching the PR (the prDescriptionHasHan machinery is unchanged), and everything the local user watches live now follows the output language preference, falling back to the user's input language under auto. The description parameter is display-only — the delivery and coverage checks compare recorded prompts and role keys, never descriptions — so the CLI-built blocks still travel verbatim, and the Verdict: line and the final 'Review complete:' line stay untranslated. The roster and reverse-audit round preambles restate the rule at the point of action, where an orchestrator actually constructs the Agent calls. Co-authored-by: verify <verify@local> |
||
|
|
713a083aea
|
fix(triage): make unattended PR review static — read CI via API, never run PR code (#7646)
The triage skill instructed the review agent to run the PR's tests (npm/tmux) in the CI worktree. That executes untrusted PR code in a job whose environment carries a write PAT, and the "tests pass" evidence it produced came from self-run commands rather than the PR's own CI. Scope the behavior by trigger: - Unattended CI runs (GITHUB_EVENT_NAME set): never build or run PR-derived code. Stage 2 test evidence comes from the PR's own CI checks via the API (check-runs + the failing job's log excerpt). Real-scenario TUI coverage is left to the isolated `@qwen-code /tmux` job. - Local invocation only (no GITHUB_EVENT_NAME): drive the app in tmux as before. Also: never present the author's self-reported results under a testing heading — attribute them as a claim if referenced at all; and fetch the CHANGELOG via `gh api` instead of `curl`. The companion workflow change that enforces these restrictions with tool/permission settings should merge after this, so its npm/curl denials never surprise the agent. Co-authored-by: verify <verify@local> |
||
|
|
39702ad2f8
|
fix(core): Preserve usage after empty OpenAI stream frames (#7650)
* fix(core): preserve usage after empty stream frames Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> * codex: address PR review feedback (#7650) Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> --------- Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> |
||
|
|
66da87d7ad
|
ci(triage): surface live progress via an early status comment (#7654)
`@qwen-code /triage` runs the agent as one long workflow step, so the PR thread stays silent until the first stage comment lands — the maintainer can't tell it started or how far along it is. The agent's output already streams live to the Actions log; the run link was only surfaced at the end. Post a `stage=status` comment up front carrying that live run link, and finalize the same comment (by marker, so a re-run reuses one comment) to a terminal state at the end. Covers manual, auto (pull_request_target), and dispatch triage. Best-effort — a failed status post never fails triage. Co-authored-by: wenshao <wenshao@example.com> |
||
|
|
5561ba1e92
|
fix(web-shell): honor locked workspace session actions (#7629)
* fix(web-shell): honor locked workspace session actions * fix(web-shell): preserve scoped session actions * test(web-shell): strengthen untrusted action coverage |
||
|
|
7ede46cff2
|
feat(cli): reference prior sessions via @ and add completion tabs (#7302)
* docs: design spec for @ session reference + tabbed completion UI * docs: implementation plan for @ session reference + tabbed completion UI * feat(cli): add @session: mention ref parser * feat(core): add SessionReferenceService for slimmed session injection * feat(cli): inject slimmed prior-session context on @session: mention * feat(cli): surface prior sessions as @ completion suggestions * feat(cli): tabbed category layout for @ completion dropdown * feat(cli): ←/→ tab switching for @ completion categories * docs: mark @ session reference design as implemented * fix(cli): preserve assistant text on tool-call turns, keep newest turn under budget, guard stale session results * docs(core): clarify SessionReferenceService slimming rules * perf(cli): remove @ completion input latency from session listing Dispatch file/MCP suggestions immediately and append prior-session suggestions in a second render once the disk listing resolves, instead of blocking the first render on session I/O. Cache the per-cwd session listing for a short TTL so rapid keystrokes don't re-walk the chats dir. * Revert "perf(cli): remove @ completion input latency from session listing" This reverts commit 08bbbc21386ac0cd6db7a6f480f0fd59f2e6b8d4. * fix(cli): harden session ref resolution and i18n tab labels (#7302) * fix(cli): guard session ref I/O errors to never abort the turn (#7302) * fix(cli): strip session: prefix in completion filter and align tab guard (#7302) * fix(cli): address review feedback on session refs and tab tests (#7302) * fix(cli): use SESSION_MENTION_PREFIX constant in completion filter (#7302) * fix(cli): address review feedback on session refs and tab tests (#7302) * fix(cli): address review feedback on session refs and tab tests (#7302) - Constrain ctrl/command on completion tab-switch bindings so ctrl+left/right (word-jump) is not consumed for tab switching - Derive a friendly title from the first user message in SessionReferenceService.resolve() when no explicit title is given, so UUID-based refs show meaningful context headers - Fix dead conditional in plan doc code snippet * fix(cli): surface real session lookup errors and test left tab switch (#7302) * fix(cli): reset suggestion indices when active category tab disappears (#7302) * fix(cli): address review feedback on session refs docs and tests (#7302) * fix(cli): address review feedback on session refs and completion ordering (#7302) * docs(cli): clarify title matching semantics in session reference design (#7302) * test(cli): assert error card in ambiguous session title test (#7302) * fix(core,cli): address review feedback on session refs (#7302) - Replace O(N²) budget trimming with single-pass backward accumulation (maintainer-measured 6.8s → ~80ms for 8k-record sessions) - Include header/marker overhead in approxTokens - Prefer custom_title system record in deriveTitle over first user message - Move session-ref detection before MCP resource ref to prevent collision with an MCP server literally named "session" - Handle bare @session (no colon) as empty filter in completion - Clamp activeSuggestionIndex when suggestion list shrinks - Strengthen not-found test assertion to check ToolCallStatus.Error - Fix unreachable mock state in InputPrompt tab-guard test - Add tests: custom_title derivation, overhead in approxTokens, bare session filter, index clamping, activeCategory reset * fix(core,cli): address review feedback on session refs (#7302) - Fix approxTokens to exclude omission marker cost when not truncated - Clamp visibleStartIndex when suggestion list shrinks to prevent empty dropdown - Document merge order invariant for session suggestions in @ completion * fix(core,cli): address review feedback on session refs (#7302) * fix(core): address review feedback on session refs (#7302) * fix(core,cli): address review feedback on session refs (#7302) * fix(core): address review feedback on session refs (#7302) * fix(cli): address review feedback on session refs (#7302) * fix(core,cli): address review feedback on session refs (#7302) - Wrap MCP category label in t() for i18n consistency - Fix comment to match > 2 tab guard semantics - Add test for Ctrl+arrow with exactly 2 categories (guard boundary) - Fix budget loop to not reserve marker tokens when session fits --------- Co-authored-by: qwen-code-ci-bot <qwen-code-ci-bot@users.noreply.github.com> Co-authored-by: Qwen Code Bot <qwen-code-bot@users.noreply.github.com> Co-authored-by: Shaojin Wen <shaojin.wensj@alibaba-inc.com> |