mirror of
https://github.com/QwenLM/qwen-code.git
synced 2026-11-11 17:43:43 -10:00
feat/btw-qodercli-alignment
8
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
6ec1b83044 |
feat(web-shell): delete selected message groups from session history (#14297)
* feat(web-shell): add grouped message deletion with durable history updates * fix(web-shell): repair message deletion CI contracts * docs(serve): index message deletion protocol routes * fix(web-shell): harden grouped deletion recovery and export build * fix(web-shell): allow selecting all message groups for deletion * test(cli): observe hook cancellation rejection before waiting --------- Co-authored-by: 钉萁 <[email protected]> Co-authored-by: qwen-code-dev-bot <[email protected]> |
||
|
|
0a42064649 |
fix(web-shell): move the hover timestamp off the message text (#11380)
* fix(web-shell): stop the hover timestamp from garbling message text
`MessageTimestamp`'s hover chip is absolutely positioned at the row's
top-right with a 92%-opaque background, so it paints over the first line of
the message underneath and lets the glyphs bleed through it. The first line of
a wrapped message runs the full column width, so it is almost always the one
that gets hit: in the web-shell visual preview for #11267 the turn-error copy
"...before the answer finished." renders as "finisheu." beneath an 09:18:16
tip, which reads as a corrupted error message rather than as an overlay.
Anchor the chip at the bottom-right instead and make its background opaque.
The last line of a wrapped block is a ragged remainder, and rows that carry an
action bar - the turn-error Copy button is one - leave that corner empty
outright, so the common case no longer overlaps text at all; where it still
does, an opaque chip with a border reads as an overlay instead of as broken
characters. `.chatTip` and `.copyButton` share the same translucent
background over content that `.chatActions` pulls up by -24px, so they get the
same treatment.
This makes overlap rare, not impossible - a message ending in a full-width
code block or table still gets the chip in its corner. Reserving space in flow
was rejected on purpose: adding padding on hover reflows the transcript, and a
permanent float notch shrinks every code block that establishes its own
formatting context.
* test(web-shell): freeze the wall clock for visual captures
The visuals job renders the PR head, then reinstalls dependencies and renders
the merge-base, so the two passes photograph the same view minutes apart. Any
view showing a wall-clock time therefore differed on every run for no reason
other than when it was taken. On #11267 that was the entire preview: the only
view the compose step reported as CHANGED was
`terminal-turn-error-copy-narrow-dark` at exactly the 0.02% threshold, and the
whole diff was a 09:09:28 timestamp against a 09:18:16 one. The narrow
viewport is half the pixels of the wide one, which is why the same ~100
timestamp pixels cleared the threshold there and were skipped at 0.01%
everywhere else - so the noise also crowded out any real change the PR made.
Pin `Date.now()` / `new Date()` with `page.clock.setFixedTime` from
`gotoSession` and `gotoNewSession`, which every visuals spec navigates
through, including the Pixel 7 touch page. `setFixedTime` fakes only clock
readings and keeps timers running, so replay, streaming and
`freezeLoopingAnimations` are unaffected; elapsed-duration UI settles on a
constant instead of drifting, which is the point. This is the same class of
fix as `freezeLoopingAnimations`, and `harness.spec.ts` pins its contract the
same way.
`formatTimestamp` renders local time, so pin `timezoneId: 'UTC'` alongside
it. CI runners are already UTC, so this changes no baseline there; it is what
makes a local capture match them. Contexts created directly from the browser
do not inherit `use` from the config, so the flow-recording context and the
touch context repeat it.
* fix(web-shell): future-date the frozen capture clock
The first pass froze captures at 2026-01-01, which is BEFORE dates the
fixtures hardcode. `formatRelativeTime` measures `Date.now() - value`, so the
channel editor's pairing requests, dated 2026-07-28, came out negative and
collapsed to "just now" where the real clock rendered "7/28/2026" -- visible
as the only unexplained CHANGED pair in this PR's own preview
(`channel-editor-existing-{dark,light}`).
Move the constant to 2027-01-01. Future-dating is the safe direction: every
fixture then reads as older than now, which is what all of them mean, and the
relative formatter lands in the same branch the live clock did.
`git-branch-picker` seeded `computedAt` from `Date.now()`, which in a spec is
Node's real clock rather than the page's frozen one. The status therefore
looked newer than the branch listing and armed a reconcile re-fetch that no
real session performs; it now derives from the same constant. Both rules are
written into the constant's docstring for the next fixture.
* test(web-shell): make the turn-error fixture identify itself
The visual harness injects a fake `turn_error` so the error row's Copy button
can be photographed, but its copy was written to read like a real incident --
"The model provider closed the response stream before the answer finished.
Retry the request or copy these details when reporting the failure." One test
produces four screenshots (two themes x two viewports), so every web-shell
preview shows that sentence four times, and readers keep taking the preview
for a live failure rather than for mock data. It is the top question this
preview generates.
Nothing about the scenario needs realistic copy; it needs an error row. Say
what the row is instead, and follow the string in the two locators that filter
on it.
* revert(web-shell): drop the fixture recopy, the timezone pin and the tip move
Three of the changes on this branch were not root-caused before being made,
and this reverts them to what the reported symptom actually justifies.
The tip no longer moves to the bottom-right. The symptom -- "finished."
reading as "finisheu." -- comes entirely from the chip's 92%-opaque
background letting the glyph beneath bleed through it, so the fix is the one
word that makes it opaque. Repositioning was a second, bundled change: more
correct in that it stops covering a word at all, but not what was reported,
and it is what churned six screenshots. `.chatTip` and `.copyButton` carry the
identical translucent background over content, so they change with it.
The turn-error fixture keeps its original copy. Rewording it fixed no bug and
measurably backfired: the touch pair started differing BECAUSE of the edit, so
the preview went from four red screenshots to six, and the replacement text
was a line longer. The red rows are the subject of the only visual test that
hovers a message row -- the Copy affordance shipped in #10001 -- not evidence
of a failure, and no wording makes them look otherwise.
The `timezoneId: 'UTC'` pins go too. CI runners are already UTC, so they
changed no baseline and only served a local reproduction nobody had asked for.
The `harness.spec.ts` clock case goes with them: `freezeWallClock` is a
one-line wrapper, so the case asserted that Playwright's own `setFixedTime`
works. `freezeLoopingAnimations` keeps its case because that function has real
logic to pin.
What survives is what measurement supports: the opaque background, the frozen
clock with its future-dated constant, and the `git-branch-picker` fixture that
the freeze would otherwise desynchronise.
* test(web-shell): drop the touch turn-error captures, keep their assertions
The touch variant renders under `hover: none`, so `.row:hover > .tip` never
fires and the hover timestamp is absent from those two screenshots entirely.
A run that moved the chip and repainted its background scored both of them at
0% diff, which is direct evidence they carry no coverage of it -- they only
contributed two full-height red error images to every web-shell preview.
The behaviour they were meant to protect is the one #10001 shipped: on a touch
device the row actions stay visible with no hover to reveal them. That is
asserted directly (`toHaveCSS('opacity', '1')` plus a visible Copy button) and
those assertions stay. Only the captures go.
The four remaining turn-error captures stay for now: they are the only views
in the suite where the hover timestamp lands on real text, so they are the
sole visual evidence for the opacity fix on this branch.
* fix(web-shell): move the hover timestamp off the first line of the message
Reverting the chip to the top-right was wrong, and zooming into the captured
pixels is what showed it. The chip's lower edge cuts horizontally through the
first line of the message; it does not cover the last word so much as
decapitate it, removing a letter's ascender while the bowl stays visible
underneath. That is the whole of the reported symptom: "finished." reads as
"finisheu." because only the bowl of the d survives.
An opaque background therefore cannot fix it. The faint remnant of the
ascender currently showing through the 92% chip is the only hint the letter is
a d at all -- painting the chip solid erases that hint and leaves a cleaner
"u". The previous commit would have made the reported symptom slightly worse.
Anchoring at the bottom-right is what removes the overlap: the last line of a
wrapped block is a ragged remainder, and rows carrying an action bar leave
that corner empty outright. Opacity is kept for its own reason -- a glyph
bleeding through any overlay reads as broken text -- and the border makes the
chip legible as an overlay where it does still land on content.
* test(web-shell): stop capturing the turn-error scenario
This scenario is the only visual test that hovers a message row, which it must
do to reveal the Copy affordance shipped in #10001. The hover timestamp is
`opacity: 0` until `.row:hover`, so those captures were the only place in the
whole suite where a hover-timestamp change could appear -- and the six
screenshots they produced meant every web-shell preview led with full-height
red error images, whatever the PR had actually touched. Readers repeatedly
took the preview for a live failure.
They have now done the one job that justified keeping them: run 34231051803
proved the overlap fix at pixel level, with the d in "finished." regaining its
ascender at full h-height while the base panel still shows "finisheu.". That
evidence is recorded in the PR description, where it does not have to be
re-rendered on every unrelated push.
The behaviour stays pinned by assertion, not by image: seven opacity checks
across the default viewport, the 720px viewport and the Pixel 7 touch context
cover reveal on hover, reveal on focus, hide on blur, and always-visible
actions under `hover: none`. A capture never verified any of that; Playwright
does not diff these images, the preview bot does, and the preview is a review
aid rather than a test.
The scenario, the fixture and every assertion remain. Only the captures go.
* test(web-shell): fail when a fixture date outlives the frozen capture clock
Captures render at a fixed instant, so a fixture dated after it silently reads
as "just now": `formatRelativeTime` measures `Date.now() - value`, a future
value yields a negative age, and that lands in the `mins < 1` branch. This
already happened on this branch. The first frozen constant sat at 2026-01-01,
before the channel editor's 2026-07-28 pairing requests, and turned "7/28/2026"
into "just now" across four views. Nothing failed -- no assertion covers that
label -- and it was caught only by reading a preview diff by eye.
Scan the visuals specs for ISO date literals and require each to precede
FIXED_CAPTURE_TIME. The docstring already asked for this; a comment does not
fail a build. `harness.ts` is skipped because it is where the constant itself
is written, so its literal is the boundary rather than a fixture.
The scan reaches further than the fixture that caused the incident: it covers
eleven literals across the suite, eight of them a 2026-07-03 pair I had not
been aware of. Verified in both directions -- silent against the tree as it
stands, and flagging a planted 2027-06-01 literal.
Not a general date linter. It catches ISO strings in fixtures, which is the
shape the regression actually took; an epoch number is already opaque enough
that nobody reads it as a date.
* test(web-shell): fail when a fixture date outlives the frozen capture clock
Captures render at a fixed instant, so a fixture dated after it silently reads
as "just now": `formatRelativeTime` measures `Date.now() - value`, a future
value yields a negative age, and that lands in the `mins < 1` branch. This
already happened here. The first frozen constant sat at 2026-01-01, before the
channel editor's 2026-07-28 pairing requests, and turned "7/28/2026" into
"just now" across four views. Nothing failed -- no assertion covers that label
-- and it surfaced only by reading a preview diff by eye.
Scan the visuals specs for ISO date literals and require each to precede
FIXED_CAPTURE_TIME. The constant's docstring already asked for this, and a
docstring does not fail a build. `harness.ts` is skipped because it is where
the constant itself is written, so its literal is the boundary, not a fixture.
The scan reaches further than the fixture that caused the incident: eleven
literals across the suite, eight of them a 2026-07-03 group that was not on my
radar. Checked in both directions before committing -- silent against the tree
as it stands, and flagging a planted 2027-06-01 literal.
Not a general date linter. It catches ISO strings in fixtures, which is the
shape this regression actually took; an epoch number is already opaque enough
that nobody reads it as a date.
|
||
|
|
f2de42dec4 |
feat(web-shell): improve compact tool activity (#8973)
* feat(web-shell): improve compact tool activity * fix(web-shell): preserve tool timing metadata * fix(web-shell): address compact activity review * fix(web-shell): preserve customized tool metadata * test(web-shell): cover completed agent tokens --------- Co-authored-by: 钉萁 <[email protected]> |
||
|
|
4fd72b3ce3 |
feat(web-shell): polish chat UI and table rendering (#6099)
* feat(web-shell): polish chat UI and table rendering * fix(web-shell): address review follow-ups --------- Co-authored-by: ytahdn <[email protected]> |
||
|
|
a384c4a21a |
feat(web-shell): polish chat UI (#5893)
* style(web-shell): polish chat UI * fix(web-shell): address chat polish review feedback --------- Co-authored-by: ytahdn <[email protected]> |
||
|
|
83e09f2b5b |
refactor(web-shell): restructure chat UI (#5775)
Co-authored-by: ytahdn <[email protected]> |
||
|
|
9641532a10 |
Polish web-shell execution display (#5190)
* fix(web-shell): correct prompt turn metrics * feat(web-shell): clarify turn execution traces * fix(web-shell): stabilize thinking trace display * style(web-shell): polish execution display * style(web-shell): refine command and tool displays * fix(web-shell): address review feedback on execution display polish - Remove unused trace field and withTrace() helper from DisplayItem - Simplify getRowClassName to a single ternary, drop unused index param - Restore !content guard on thinking preview tail-scroll - Add CSS comment documenting margin-left cross-file coupling - Rename isNonAssistantStep to isExecutionWorkStep for clarity - Replace APL glyphs (⌄/⌃) with Geometric Shapes (▼/▲) - Add keyboard accessibility tests for tool row expand (Enter/Space) * fix(web-shell): address execution display review --------- Co-authored-by: ytahdn <[email protected]> |
||
|
|
84d01e7070 |
feat(web-shell): show message time on hover (#5079)
* fix(acp-bridge): preserve original timestamp when replaying session history History replay re-emits each persisted record with its original epoch-ms time nested in update._meta, but BridgeClient.sessionUpdate published the frame without lifting it to the envelope. EventBus.publish then stamped envelope _meta.serverTimestamp with publish-time Date.now(), which the client's extractServerTimestamp picks up at higher priority than the nested original — so a resumed session rendered every historical message at the resume moment instead of when it was sent. Lift update._meta.timestamp (or serverTimestamp) to the envelope serverTimestamp so EventBus preserves it. Live updates without such a timestamp keep the Date.now() fallback unchanged. * feat(web-shell): show each history message's time on hover Carry each transcript block's wall-clock time (serverTimestamp ?? clientReceivedAt) onto every message and reveal it as a CSS-only hover tooltip in the message list. Same-day messages show HH:mm:ss; older ones show yyyy-MM-dd HH:mm:ss (local time, zero-padded). |