Commit Graph

4925 Commits

Author SHA1 Message Date
Yichen Jiang
02cd5bf733 Merge remote-tracking branch 'origin/master' into worktree/custom-deepseek-models
# Conflicts:
#	apps/web/tests/onboarding-deepseek-config.e2e.ts
#	packages/client/ui-models/README.i18n.yaml
#	packages/host/apiproxy/README.i18n.yaml
2026-07-31 15:12:41 +08:00
Yichen Jiang
f12d4f698e doc(web): own the Web/TUI split on an unlisted current model
The TUI still renders the unlisted current model as its own row and marks it
current; Web shows the unset trigger label and asks for a replacement. The
note recorded the Host decision but not that the two surfaces present it
differently, which reads as a missed migration rather than a choice.

Also records why `trigger.selectAria` and `trigger.fallback` hold identical
strings, so a future coalescing cleanup does not merge them.
2026-07-31 15:11:11 +08:00
Yichen Jiang
d6af60f5ec testing(web): pin the row card against the editor it expands into
The previous assertion pinned the literal `bg-layer-3` fill that was just
reverted. What matters is the relationship it broke: `bg-layer-3` and
`bg-module-platform` both resolve to neutral-bluish-800 under the dark
theme, so filling the row with either erases the nested editor's boundary.
2026-07-31 15:11:02 +08:00
Yichen Jiang
e42e1c3ed7 fix(web): keep every row's unreadable context-window text
The typed text was held in one active buffer, so editing a second row
displaced the first — which then fell back to rendering its stored NaN as
the literal `NaN`, losing the text the row was supposed to let the user
correct. Reset dropped the override but kept the buffer, leaving typed text
over an inherited row that no settings layer stores, and an unreadable
buffer never settles, so it stayed there.

There is now one entry per row. `remove` re-keys around the dropped row so
text travels with its own row, and reset clears them all because the rows
they annotated are gone.

Model ids are compared trimmed as well: `"   "` passed the required check,
and `"model "` slipped past the duplicate check against its own twin before
silently failing to match at the adapter. A pasted id settles on blur rather
than being trimmed per keystroke, which would stop an interior space.
2026-07-31 15:10:59 +08:00
Yichen Jiang
6056062f8f Revert "fix(web): fill the provider row card"
This reverts commit 5f96d085f46bcb712beab248bab6c1f5cd030689.
2026-07-31 14:57:15 +08:00
imccyu
95c238a74f Merge remote-tracking branch 'origin/master' into mergebot/pr1016 2026-07-31 14:51:15 +08:00
imccyu
ef01e2e9af Merge pull request #1046 from deepseek-harness/worktree-infdev01
Shared anonymous user id from $DSH_HOME/.userid, reported as OTel Resource user.id
2026-07-31 14:49:00 +08:00
Yichen Jiang
267fbdbf7f Merge remote-tracking branch 'origin/master' into worktree/custom-deepseek-models
# Conflicts:
#	packages/host/apiproxy/README.i18n.yaml
2026-07-31 14:48:50 +08:00
imccyu
06fc3c68a6 Merge pull request #1039 from deepseek-harness/worktree/composer-scroll-sync
fix(web): scroll the composer's glyph layer with its textarea
2026-07-31 14:48:41 +08:00
imccyu
5dcb096015 Merge pull request #997 from deepseek-harness/worktree/chat-ui-polish
fix(web): polish chat activity and queue states
2026-07-31 14:45:23 +08:00
Yichen Jiang
ef996473a7 fix(web): restore the default model catalog without a reload
Restore defaults dropped the user's `models` override from the draft but the
rows kept showing it, so the catalog only looked restored after closing and
reopening the card.

The inherited rows were read from the namespace's effective value, which
still carries the stored override until the unset is applied — so dropping
the override echoed it straight back. They now come from the layer beneath
the user's: what the composition entry pinned, or else the schema default
that resolution would supply.
2026-07-31 14:44:15 +08:00
imccyu
4c01550833 Merge remote-tracking branch 'origin/master' into mergebot/pr1016 2026-07-31 14:43:03 +08:00
Yichen Jiang
1dbf70cb8a fix(web): fill the provider row card
Raises a configured provider's row onto layer 3 so it reads as a surface
rather than an outline. No-op under the light theme, where layer 3 and the
panel are both white.
2026-07-31 14:36:23 +08:00
Yichen Jiang
935578ed98 feat(web): accept K and M suffixes in the context window field
The catalog's context window is now a text field that reads a decimal K or M
suffix — 1M is 1000K, matching how model capacities are quoted — and stores
the plain token count, so settings.yaml and the adapter are unchanged.

A stored count reads back in the shortest form that round-trips: 1000000 as
1M, 256000 as 256K, and 131072 written out, because it is not a whole number
of thousands. The field holds the typed text while its row has focus, since
re-deriving it from the parsed count on every keystroke would rewrite 1000
to 1K mid-word; text that does not parse stays on screen so the save-time
rejection names a row the user can still see and correct.
2026-07-31 14:36:16 +08:00
Yichen Jiang
2701862bf1 Merge remote-tracking branch 'origin/master' into worktree/custom-deepseek-models
# Conflicts:
#	.agents/notes/implemented/architecture/2026-07-30-web-config-plane.i18n.yaml
#	.agents/notes/implemented/architecture/2026-07-30-web-config-plane.md
#	.agents/notes/implemented/architecture/2026-07-30-web-config-plane.zh.md
#	apps/web/tests/snapshots/message-actions/ui.expected.md
#	apps/web/tests/snapshots/seeded-history/ui.expected.md
#	packages/client/ui-models/README.i18n.yaml
#	packages/client/ui-models/README.md
#	packages/client/ui-models/README.zh.md
#	packages/client/ui-models/src/client/ModelsSection.module.css
#	packages/client/ui-models/src/client/ModelsSection.tsx
#	packages/client/ui-models/tests/components.spec.tsx
#	packages/host/apiproxy/README.i18n.yaml
2026-07-31 14:36:00 +08:00
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
imccyu
bff581ffb3 feat(telemetry): anonymous user id from $DSH_HOME/.userid, reported as OTel Resource user.id
session-telemetry-otel owns the identity as its own module (src/user-id.ts):
getOrCreateAnonymousUserId() returns the bare UUID line in $DSH_HOME/.userid,
minting a random UUID v4 on first use — synchronous IO with a process-lifetime
memo keyed by resolved path, an exclusive-create (wx) settle for concurrent
first launches, best-effort on read-only homes, and deletion resetting the
identity on the next launch by design.

The backend carries the id as the Resource's user.id (the OTel semconv user
attribute), once per export batch alongside service.name/service.version.
The identity belongs to the OTel feed alone; the dsh-sdk launcher telemetry
keeps its own separate store.
2026-07-31 14:28:03 +08:00
creatixchu
22d6b1ed81 Merge remote-tracking branch 'origin/master' into worktree/composer-scroll-sync 2026-07-31 14:26:51 +08:00
Yichen Jiang
a2a79ada82 test(web): scope retry status assertion 2026-07-31 14:18:47 +08:00
Yichen Jiang
e0e48bfc10 Merge remote-tracking branch 'origin/master' into worktree/chat-ui-polish
# Conflicts:
#	apps/web/tests/snapshots/live-interactions/retry.expected.md
#	packages/client/ui-conversation/README.i18n.yaml
2026-07-31 14:16:51 +08:00
Yichen Jiang
a332f2f333 feat(web): configure custom DeepSeek models 2026-07-31 14:08:59 +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
NI0317
cf4027afe8 Merge remote-tracking branch 'origin/master' into feature/gui-first-run-welcome
# Conflicts:
#	packages/host/apiproxy/README.i18n.yaml
2026-07-31 13:41:17 +08:00
Yichen Jiang
7aa126e0d5 test(session): expect empty fork seed marker 2026-07-31 13:36:40 +08:00
NI0317
139464f3e7 docs(onboarding): refine internal testing notice 2026-07-31 13:34:13 +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
NI0317
c171ce2944 Merge remote-tracking branch 'origin/master' into feature/gui-first-run-welcome 2026-07-31 13:10:06 +08:00
NI0317
1962d71b70 fix(web): balance credential step vertically 2026-07-31 13:09:41 +08:00