Commit Graph

4888 Commits

Author SHA1 Message Date
creatixchu
a2c5f7dc0a Merge remote-tracking branch 'origin/master' into worktree/composer-scroll-sync 2026-07-31 14:32:14 +08:00
Chinesezjc
538488506f Merge pull request #973 from deepseek-harness/feat/read-presenter
feat(fs): add a read render-intent card for the read tool result
2026-07-31 14:30:31 +08:00
creatixchu
22d6b1ed81 Merge remote-tracking branch 'origin/master' into worktree/composer-scroll-sync 2026-07-31 14:26:51 +08:00
imccyu
f5680ffabe fix: ci 2026-07-31 14:08:13 +08:00
imccyu
b8b5403f0a fix: ci 2026-07-31 14:08:13 +08:00
imccyu
d2dff40560 feat(ui-workspace): blank New Session rows render no menu and no time
A blank row is a provisional placeholder: nothing has happened in it,
so the row verbs (rename/fork/archive) and a 'now' stamp would act on
content that does not exist. The trailing cells and the hover card's
time line stay off until the first prompt lands.
2026-07-31 14:08:13 +08:00
imccyu
9ed87a6dba refactor(client): archivedSessionIds public face becomes a plain array
Public snapshot state stays in the store engine's plain-data vocabulary
(immer drafts reject Sets without the MapSet plugin, which stays off):
manager/service/contract carry readonly SessionId[] in Host order, and
the tree derivations build their own transient Set — the
expandedProjects pattern. Membership-unchanged installs still keep the
array reference for Object.is short-circuits.
2026-07-31 14:08:13 +08:00
imccyu
d3e8f17a54 fix: review follow-ups for the session archive set
- WorkspaceRegistry.archiveSession no longer wraps persistence-listing
  failures as WorkspaceUnknownSessionError: only a definite miss (live
  lookup, header index, then a fresh list) maps to session-not-found;
  storage faults propagate as internal errors, with a negative test.
- The archived-current sweep moves from the unary path into the
  projection: any install path (local echo, another tab's frame, a
  reconnect baseline) clears a selection that landed in the archive set.
- An archive set installed while workspace.list is in flight supersedes
  the stale baseline's set instead of being rolled back by it.
- The workspace-management e2e anchors the archived row by its session
  actions button and asserts the single-stray fixture assumption loudly.
- Drop the stale touchSession rows from the workspace READMEs (the
  method was removed with its Agent Note).
2026-07-31 14:08:13 +08:00
imccyu
c00f0dccda test(test-runtime): cover the archiveSession double's default and stub arms
The default arm builds the next Set outside the immer draft: reading a
Set through a draft requires the MapSet plugin, assigning a fresh Set
does not.
2026-07-31 14:08:13 +08:00
imccyu
fc0042e47e fix(client-runtime): never reuse an archived blank session in connectWorkspace
Reusing one would open a session no grouping surface can show; the New
Session flow mints a fresh blank instead.
2026-07-31 14:08:13 +08:00
imccyu
3b86c288d6 docs: catalogs and Agent Note for the session archive set 2026-07-31 14:08:13 +08:00
imccyu
e235be2bac feat(ui-workspace): archive session from the row menu
The visual-only Delete session placeholder becomes a wired Archive
session action: no confirmation dialog (non-destructive), failures stay
console diagnostics. tree.ts hides archived sessions in every
derivation (workspace groups, Ungrouped, search, flat list) through the
sessionVisible predicate. The workspace-management e2e pins the archive
round trip across reload.
2026-07-31 14:08:13 +08:00
imccyu
c764ed7e64 feat(client-runtime): project the archive set and the archiveSession action
WorkspaceListState gains archivedSessionIds (ReadonlySet, replaced only
on membership change), installed as full snapshots from the list
baseline, the unary echo, and the changed frame. Archiving the current
session clears the selection into the New Session view state. Test
doubles (test-runtime, fake APIs, fixture client) follow the widened
IWorkspaces/IApiClient faces.
2026-07-31 14:08:13 +08:00
imccyu
53ceab53b8 feat(apiproxy): workspace.archiveSession RPC and archived-sessions frame
workspace.archiveSession answers the full updated archive set;
workspace.list carries the set as the reconnect baseline; the host
stream pushes host/archived-sessions-changed full snapshots from the
domain/changed global-put branch (same posture as workspace-changed).
Unknown sessions map to the existing session-not-found code.
2026-07-31 14:08:11 +08:00
imccyu
b00cd0cd8c feat(workspace): add registry-global archivedSessionIds set
The workspace domain global singleton gains archivedSessionIds (schema
default [], version unchanged): a display-layer archive set layered over
workspace accounting. archiveSession() rides the registry operation
chain, validates the session against live/persisted headers, and is
idempotent; archived sessions keep their sessionIds slot so a future
unarchive restores position.
2026-07-31 14:07:51 +08:00
creatixchu
dec1950b6a Merge remote-tracking branch 'origin/master' into worktree/composer-scroll-sync 2026-07-31 14:07:04 +08:00
Yichen Jiang
6acdb6631d Merge pull request #1036 from deepseek-harness/worktree/permission-default-settings
feat(permission): configure new-session defaults in Web settings
2026-07-31 14:05:00 +08:00
Chinesezjc
fe7ae124b7 Merge remote-tracking branch 'origin/master' into feat/read-presenter 2026-07-31 13:55:00 +08:00
creatixchu
676fee485a Merge remote-tracking branch 'origin/master' into worktree/composer-scroll-sync 2026-07-31 13:46:05 +08:00
Yichen Jiang
8ab6473660 test(permission): cover settings confirmation paths 2026-07-31 13:45:22 +08:00
Yichen Jiang
75f2489ba1 Merge pull request #1031 from deepseek-harness/worktree/fix-models-settings
fix(web): improve Models settings presentation and safety
2026-07-31 13:44:11 +08:00
Yichen Jiang
7aa126e0d5 test(session): expect empty fork seed marker 2026-07-31 13:36:40 +08:00
Yichen Jiang
cb60e1759a Merge remote-tracking branch 'origin/master' into worktree/permission-default-settings
# Conflicts:
#	packages/host/apiproxy/README.i18n.yaml
2026-07-31 13:27:43 +08:00
Yichen Jiang
48152a7a1d merge master and address permission settings review 2026-07-31 13:24:30 +08:00
creatixchu
52d6c487b7 Merge remote-tracking branch 'origin/master' into worktree/composer-scroll-sync 2026-07-31 13:22:52 +08:00
imccyu
9aa867b6ea Merge branch 'master' into fix/command-execute-transport-timeout 2026-07-31 13:18:12 +08:00
creatixchu
23c4745560 fix(web): assert the wrap-width premise instead of reserving a gutter
Review flagged that "equal by construction" rested on an engine behaviour I
had not measured: `scrollbar-gutter: stable` only equalizes the layers if the
engine applies it to `overflow: hidden` the way it does to `overflow-y: auto`.
Measured it on the running app across the three engines Playwright ships,
and the property does not hold up.

  engine    .input / .backdrop / .mirror wrap width
  chromium  776 / 776 / 776   (768 / 768 / 768 with the declaration)
  firefox   776 / 776 / 776   (unchanged by it — overlay scrollbar)
  WebKit    768 / 776 / 776   (unchanged by it)

WebKit reserves for `overflow-y: auto` and not for `overflow: hidden`, so the
declaration left .input at 768 against 776 — exactly the gap it was meant to
close — on the one engine where that gap is observable at all, while costing
every chromium user 8px of text column unconditionally. Reverted: the
composer's metrics are now the same as before this PR.

The WebKit gap predates this change and is not closed here. It is recorded in
the Agent Note with the numbers, and the browser scenario asserts the equality
on the lane's engine so a regression into that state fails loudly. The mirror
is unaffected on WebKit for the drafts measured — the extents still agree — but
a draft whose wrapping turns on those 8px would clamp it.

The review's monotonicity concern resolves the same way: the declaration was
never worse than master, because WebKit already measured 768 against 776
without it. It simply was not better.

Also from this round: the wrap-width assertion now covers .mirror as well as
the two glyph layers — it is the height authority, so a mirror alone wrapping
wider would measure the box short and clip content below the 14-line cap with
every other assertion green. Plus `renderGeometry`'s missing `@param
trailingNewline`, and both e2e tsconfig lists restored to alphabetical order.
2026-07-31 13:13:50 +08:00
imccyu
eacd24d66a Merge branch 'master' into feat/web-diff-card 2026-07-31 13:07:51 +08:00
Chinesezjc
a2fa8ccbcf Merge remote-tracking branch 'origin/master' into feat/read-presenter 2026-07-31 13:03:05 +08:00
Chinesezjc
64c855737d Merge remote-tracking branch 'origin/master' into feat/web-diff-card
# Conflicts:
#	packages/client/ui-conversation/README.i18n.yaml
#	packages/client/ui-conversation/README.md
#	packages/client/ui-conversation/README.zh.md
2026-07-31 12:50:58 +08:00
Yichen Jiang
f45b6f76a5 fix(web): remove tool-call settings placeholder 2026-07-31 12:48:39 +08:00
Yichen Jiang
ee74b5b07a feat(permission): add new-session default setting 2026-07-31 12:48:19 +08:00
imccyu
68a99cf75c Merge branch 'master' into codex/responsive-queue-panel 2026-07-31 12:44:53 +08:00
creatixchu
2143361195 fix(web): reserve one scrollbar gutter across the composer's text layers
Second review round escalated the wrap-width divergence from a separate
concern to a defect in this fix's own premise, and it is right.

Only .input scrolls, so only .input loses content width to a scrollbar that
consumes layout space — what Windows and Firefox draw, and what the theme's
global `::-webkit-scrollbar` width makes chromium treat as occupying space.
A narrower .input wraps a long soft-wrapped draft onto more lines, so it
grows taller, its scroll maximum exceeds the backdrop's, and the mirrored
offset clamps below the caret. That is the same failure the trailing-line
sentinel fixes, in the same direction, so deferring it would have shipped a
fix that does not hold where users run a classic scrollbar.

My first attempt to reproduce it found nothing and was wrong: the probe
content was not wrap-sensitive. With varied-length words the effect is
plain — the same draft laid out at 8px-apart widths differs by 2 to 5
lines, while at equal widths a textarea and a div agree exactly.

The three layers now reserve the gutter together, in the shared metrics
block that already exists to keep them symmetric. `overflow: hidden` is
still a scroll container, so the non-scrolling layers honour it: 8px is
reserved on each, measured. The cost is a text column 8px narrower on every
platform, which is the price of one geometry rather than a per-platform one.

The browser scenario asserts the premise directly — equal wrap widths, and a
reserved band greater than zero on each layer. The band is what stops the
assertion being vacuous: the widths would also match with no reservation at
all on this engine's overlay scrollbar, and it is the reservation, not the
match, that carries the guarantee to a platform whose scrollbar takes real
width. Removing the declaration fails it with `expected 0 to be greater
than 0`, and fails the golden with it.

Also from the same round, three comment corrections: the e2e file header no
longer describes the deleted layout effect, the measurement guard no longer
claims the backdrop holds exactly one text node (the sentinel makes a
second), and the sentinel comment now carries the one-sidedness argument
that also settles the ghost hint — the mirror only fails when the backdrop
is SHORTER, and the hint can only add content, never remove a line box.
2026-07-31 12:39:52 +08:00
Wenlu Wang
4e345c38a9 Merge branch 'master' into codex/responsive-queue-panel 2026-07-31 12:34:57 +08:00
imccyu
5afdb5c235 Merge remote-tracking branch 'origin/master' into mergebot/pr998
# Conflicts:
#	packages/client/ui-conversation/README.i18n.yaml
2026-07-31 12:23:03 +08:00
creatixchu
f8ef2cf36b fix(web): give the backdrop the trailing-line sentinel so the layers share one extent
Review caught a real divergence the earlier measurements missed: mirroring
an offset is only correct while both layers can reach it, and for a draft
ending in a newline the backdrop could not.

A textarea reserves a line box for the caret after a final newline.
`white-space: pre-wrap` collapses a text node's trailing newline and
generates none. So a draft ending in a newline made the backdrop exactly one
line shorter than the textarea — measured 628 against 652 — and the mirrored
assignment clamped, leaving the glyphs one line behind the caret at the very
bottom of the draft.

The backdrop now carries the same trailing-line sentinel the mirror div has
carried all along: its content is the decoration walk plus one newline. The
same pre-wrap collapse absorbs it when the draft does not end in a newline,
so it costs no height in the ordinary case, and it supplies the missing line
box when it does. Verified in isolation first: a bare pre-wrap div measures
180/180/198 against a textarea's 180/198/216 for zero, one and two trailing
newlines, and 180/198/216 with the sentinel.

Coverage for the shape that exposed it: the browser scenario asserts the two
extents are equal before asserting the glyphs reach the end, observing each
layer's maximum by asking for an impossible offset and reading back the
clamp rather than computing it from scrollHeight, and the golden records the
relation. The unit spec pins the backdrop's text as the draft plus exactly
one newline. Removing the sentinel fails both, the e2e with the same 628
against 652.

The scrollbar-gutter half of the same review point does not reproduce here:
both layers measure clientWidth 776 against a border box of 776 while the
draft overflows, so this engine's textarea scrollbar is an overlay and takes
no width out of the wrap.
2026-07-31 12:12:54 +08:00
creatixchu
07448093c5 fix(web): drop the redundant second mirror
The first version coupled the layers from two places: a `scroll` listener
and a layout effect keyed on the committed draft. Mutation-testing each
hook alone against the built client shows the effect never fires the only
assignment that matters — with just the layout effect disabled the browser
scenario stays green, while disabling just the listener fails it.

Both premises behind the effect were wrong. Typing scrolls the caret into
view, which is an ordinary `scroll`. A draft that shrinks past the current
offset clamps both layers to the same maximum, because their extents are
equal — measured in chromium at 964/964, 1012/1012, 844/844 and 820/820 for
plain, soft-wrapped, unbreakable-run and highlighted drafts — and the
textarea's clamp fires `scroll` too.

The hazard the effect was imagined to cover does not exist either: React
replacing every child of the backdrop when the decoration set changes shape
preserves `scrollTop` (measured: 300 stays 300 through a full child
replacement), and the only replacement that zeroes it shrinks the content
below the offset, which is the clamp case already covered.

The e2e's edit case survives, retitled to say what it actually pins: that
typing is not a separate case needing its own mirror. The unit spec now
asserts the backdrop tracks a second move back to the top, which a one-shot
mirror would fail.
2026-07-31 12:02:38 +08:00
Chinesezjc
4bcec15edd Merge remote-tracking branch 'origin/master' into feat/web-diff-card
# Conflicts:
#	apps/web/tests/built-boot.snapshot.ts
#	packages/client/connection/src/client/fixture.ts
#	packages/client/ui-conversation/README.i18n.yaml
#	packages/client/ui-conversation/src/client/apply.ts
#	packages/client/ui-conversation/src/client/chat/GenericToolCard.tsx
#	packages/client/ui-conversation/src/client/skeleton/DetailsPanel.tsx
#	packages/client/ui-conversation/tests/chat-apply.spec.tsx
#	packages/client/ui-primitives/README.i18n.yaml
#	packages/client/ui-primitives/README.md
#	packages/client/ui-primitives/README.zh.md
#	packages/client/ui-primitives/src/index.ts
2026-07-31 11:56:28 +08:00
creatixchu
a7b7066267 fix(web): scroll the composer's glyph layer with its textarea
A composer draft past the 14-line cap could not be scrolled: the caret and
the selection moved, but the words stayed frozen at line 1, so the tail of
anything longer than the cap was unreachable while writing it.

The composer paints its text in two stacked layers. The textarea owns the
value, the selection and the caret but renders its own glyphs transparent;
every visible character is painted by the decoration backdrop beneath it,
which also carries the claim-token highlight, the chips and the ghost hint.
The backdrop is `inset: 0; overflow: hidden` — clipped, not scrolled — and
nothing linked its offset to the textarea's. Below the cap both layers rest
at 0, which is why the defect hid behind every short-draft screenshot and
fixture.

InputBar now mirrors the textarea's scrollTop onto the backdrop, from a
`scroll` listener (every gesture and every caret-driven scroll) and from a
layout effect keyed on the committed draft (an edit reflows both layers
without necessarily firing a scroll event).

Scrolling is layout, so jsdom cannot show this: the unit spec stubs both
offsets and proves the mirroring paths run, while a new browser scenario
measures the user-visible fact against the built client with a DOM Range
over the backdrop's own text — after a wheel gesture over a 40-line draft
the last line is on screen and the first has scrolled out. Confirmed both
directions: with the mirroring reverted and the packages rebuilt, the
golden reads `last draft line is on screen: false` while `textarea moved:
true`.
2026-07-31 11:53:04 +08:00
ZiyaZhang
45e5317ecd fix(ci): stabilize merged coverage gates 2026-07-30 20:52:35 -07:00
Hypatia May
322950487e fix(apiproxy): let commands outlive unary deadline 2026-07-31 11:51:49 +08:00
Yichen Jiang
8763491a9d Merge remote-tracking branch 'origin/master' into worktree/web-model-request-retry
# Conflicts:
#	packages/client/ui-conversation/README.i18n.yaml
2026-07-31 11:49:02 +08:00
Ziya
ade8358e67 Merge branch 'master' into feat/gui-full-access-confirmation 2026-07-30 23:45:31 -04:00
Chinesezjc
3248955f44 Merge pull request #987 from deepseek-harness/feat/web-web-card
feat(web): render web_search/web_fetch output as a web card
2026-07-31 11:44:57 +08:00
Yichen Jiang
2e07da19e5 Merge remote-tracking branch 'origin/master' into worktree/web-model-request-retry
# Conflicts:
#	apps/cli/README.i18n.yaml
#	apps/cli/README.md
#	apps/cli/README.zh.md
#	packages/client/runtime/README.i18n.yaml
#	packages/client/ui-conversation/README.i18n.yaml
2026-07-31 11:39:58 +08:00
Ziya
25fd90a561 Merge branch 'master' into feat/gui-full-access-confirmation 2026-07-30 23:32:55 -04:00
Yichen Jiang
049e64b002 Merge remote-tracking branch 'origin/master' into worktree/fix-models-settings 2026-07-31 11:32:17 +08:00
Yichen Jiang
788b9eb986 fix(web): hide provider liveness badges 2026-07-31 11:32:10 +08:00
Chinesezjc
6f0405ed84 docs: re-record ui-conversation README pairing after master merge 2026-07-31 11:27:13 +08:00