Commit Graph

1933 Commits

Author SHA1 Message Date
Yichen Jiang
a4f3aa073f test(ui-agent-preset): cover the paths the extraction left uncovered
The shared picker's id fallback on both trust levels, the chip refusing an
unrelated settings namespace, a refused `settings.describe`, and a blank
draft that names no source. Drops the picker's `title`, which this layer's
one caller never passes.
2026-08-07 16:06:01 +08:00
Yichen Jiang
93ad74cab5 refactor(ui-agent-preset): keep the row's picker shared, the hero chip its own
The chip renders name and description on two lines with its own icon and
alignment, so it is not the same control as the settings row — the shared
picker carries the row, and the chip keeps its shape.
2026-08-07 16:01:43 +08:00
Yichen Jiang
b4213fac6f Merge branch 'stack/agent-profiles-5-web-ui' into stack/agent-profiles-8-authoring
# Conflicts:
#	packages/client/ui-agent-preset/src/client/AgentPresetRow.tsx
#	packages/client/ui-agent-preset/src/client/AgentPresetSeat.tsx
2026-08-07 15:59:59 +08:00
Yichen Jiang
e9648bdeee refactor(ui-agent-preset): one preset picker behind both surfaces
The settings row and the composer seat differ in where they sit, what they
call the current value, and when they refuse a pick — not in how the picker
behaves. Extracting it also stops the row from reading like the permission
row it has nothing to do with.
2026-08-07 15:59:23 +08:00
Yichen Jiang
82ae1a8a37 refactor(ui-agent-preset): one home for the roster read every surface starts from
The row and the management section opened `load` the same way — refuse a
concurrent read, mark the store loading, read, fold both refusal shapes into
the store's error. What differs between them starts after that.
2026-08-07 15:52:02 +08:00
Yichen Jiang
0f27a505c4 refactor(ui-agent-preset): one home for turning a roster into options
The chip and the settings row both spread the same three fields, and
`exactOptionalPropertyTypes` makes the absent-vs-undefined dance verbose
enough that the duplication gate flagged it.
2026-08-07 15:46:46 +08:00
Yichen Jiang
53bd0a90a6 Merge pull request #1754 from deepseek-harness/worktree/web-skill-tool-row
feat(web): add dedicated skill tool row
2026-08-07 15:45:24 +08:00
Yichen Jiang
d03d3ab70b Merge remote-tracking branch 'origin/master' into worktree/default-model-persistence
Carries two edits beyond conflict resolution, both forced by what master
brought in:

- `CustomProviderCard`: master added front-end key validation and a
  component-level `keyValue` (already trimmed) while still writing
  `apiKeyEnv` unconditionally. Kept this branch's blank-key rule and its
  committed-profile retry gate, and adopted master's single `keyValue` so
  the component has one spelling of the key rather than two.
- `docs/user/guide/providers`: master merged #1810, whose default-model
  section still taught overriding the `api-gateway` row in
  `$DSH_HOME/config.yaml` — the behavior this branch replaced. Rewritten
  for the settings section the picker now writes, plus the review fix from
  #1810 replacing the colloquial 挂着 in the opener.
2026-08-07 15:44:57 +08:00
Yichen Jiang
5ec13a23b3 Merge branch 'stack/agent-profiles-5-web-ui' into stack/agent-profiles-8-authoring
# Conflicts:
#	packages/host/apiproxy/README.i18n.yaml
2026-08-07 15:41:18 +08:00
Yichen Jiang
df2d2adbb8 Merge branch 'stack/agent-profiles-3-wire' into stack/agent-profiles-5-web-ui
# Conflicts:
#	packages/host/apiproxy/README.i18n.yaml
2026-08-07 15:41:14 +08:00
Yichen Jiang
6093c266c6 Merge branch 'stack/agent-profiles-1-seam' into stack/agent-profiles-3-wire 2026-08-07 15:41:09 +08:00
Turtle
d9a3ae4c3a Merge remote-tracking branch 'origin/master' into task/command-feedback-master 2026-08-07 15:28:07 +08:00
Yichen Jiang
bb43ff4f37 feat(ui): make a session that cannot send refuse to accept one
A default naming a route the Models page has since removed left the
composer saying 选择模型 while the input still accepted a message, which
then failed inside the adapter mid-turn.

`session.prompt` now refuses with `model-unavailable` before opening a
turn. That is the enforcement boundary: the method stays callable no
matter what a client disables. `session.models` reports the same fact as
`routable`, and ui-model pushes a block through the new
`ctx.conversation.blocks` registry so the bar renders the disabled
textarea it already renders without a workspace, carrying the blocker's
own reason. The push direction is forced — ui-model already depends on
ui-conversation, so ui-conversation cannot read it back.

The gate is `routable`, not "matches no advertised group": catalog
membership is advisory, so a route serving a model it stopped advertising
is missing from the groups yet perfectly usable, and `null` before the
first load never blocks so a slow Host cannot lock a working composer.

The scaffold gains a route-only adapter for fixture-less keyless
scenarios. Registering zero providers is a test artifact — every product
composition mounts one — and the goldens that froze the seat's fallback
label now show the model those scenarios actually route to.
2026-08-07 15:26:42 +08:00
Yichen Jiang
a45beb1292 Merge branch 'master' into worktree/web-skill-tool-row 2026-08-07 15:06:42 +08:00
Yichen Jiang
c96b480bc4 test(ui-agent-preset): cover the surface where it is introduced
The package landed here with one store spec; the rest of its tests were written
three layers up, so this layer and the two above it failed the per-file
coverage gate on 191 locations while every test passed.

Adds the node half's invariant companion, the two components, the registration
apply, and the stores' failure paths. `currentValue` drops a `?? ''` that an
empty roster already returned before reaching — the same shape the later layer
arrived at, so the two converge instead of conflicting.
2026-08-07 14:58:03 +08:00
creatixchu
40ee7f5e27 docs,test: settle review follow-ups for the create-by-name deletion
Rewrite the three sibling Agent Note pairs that still described create-by-name
as current (workspace-ui-product-flow, session-list-browsing-and-manual-order,
same-basename-workspace-adoption) and the one-route note's own alternative and
section title; delete scripts/hero-composer-dom-continuity.mjs, which drove the
name dialog removed by the one-route change; mark WorkspaceRegistry.create's
now test-only title parameter with a deletion TODO; pin the retired { name }
spelling as a schema rejection; align the workspace spec on stageDir and the
fixture spec title on path creates.
2026-08-07 14:48:26 +08:00
Turtle
5e5664e668 Merge remote-tracking branch 'origin/master' into task/command-feedback-master
# Conflicts:
#	.agents/notes/proposed/architecture/2026-07-27-session-projection-and-command-log.i18n.yaml
#	apps/cli/config/base.cordis.yml
#	apps/cli/package.json
#	packages/README.i18n.yaml
#	pnpm-lock.yaml
2026-08-07 14:40:42 +08:00
creatixchu
fbd3a6272b Merge remote-tracking branch 'origin/master' into worktree/drop-create-by-name
# Conflicts:
#	packages/host/apiproxy/README.i18n.yaml
2026-08-07 14:40:25 +08:00
Yichen Jiang
23a4c0a51e Merge pull request #1827 from deepseek-harness/worktree/charming-swartz-83bf33
fix(llm,web): validate API key format before it reaches an HTTP header
2026-08-07 14:36:04 +08:00
creatixchu
a7e43d4346 refactor: drop the create-by-name workspace route
The Web picker collapsed onto the directory flow (see the one-route-to-add-a-workspace
Agent Note), leaving workspace.create({ name }) with no product consumer. Delete the
whole feed line: the wire schema's name member and WorkspaceApi spelling, the gateway's
workspaceRoot config/default and the mkdir branch, the client seam that carried the name
(WorkspaceCreateInput, WorkspacesService.create, intentName), the dsh web
--workspace-root flag, and the fixture's name handling. workspace-name-conflict stays as
workspace.rename's duplicate-title error.
2026-08-07 14:26:50 +08:00
_Kerman
4ede2798fe fix(web): address review — placeholder key family, menu-open gate, plan precedence, note wording 2026-08-07 14:20:14 +08:00
Yichen Jiang
d5c5e7f2e9 Merge remote-tracking branch 'origin/master' into worktree/charming-swartz-83bf33
# Conflicts:
#	apps/web/tests/models-settings.e2e.ts
#	docs/config-catalog.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/ProviderEditor.tsx
#	packages/client/ui-models/tests/provider-form.spec.tsx
#	packages/llm/llm-deepseek/README.i18n.yaml
#	packages/llm/llm-deepseek/README.md
#	packages/llm/llm-deepseek/README.zh.md
#	packages/llm/llm-deepseek/src/index.ts
2026-08-07 14:12:17 +08:00
Yichen Jiang
63724ed5f9 Merge pull request #1856 from deepseek-harness/worktree/fix-wsl-open-config
fix(apiproxy): open config files through Windows on WSL
2026-08-07 14:11:30 +08:00
_Kerman
f79db87d8d Merge remote-tracking branch 'github/feat/web-queue-steer-all' into feat/web-queue-steer-tooltip
# Conflicts:
#	packages/client/ui-conversation/README.i18n.yaml
2026-08-07 14:05:27 +08:00
Yichen Jiang
0823a3484a fix(web): report a wrapped paste as the same API key format failure 2026-08-07 14:03:11 +08:00
Yichen Jiang
72618f29b5 fix(ui-models): stop the create card pinning a reference on a blank key
Master's credential-lifecycle work taught the editor card that a pi-ai
profile names `apiKeyEnv` only when a key is actually stored, so a route
left blank keeps its provider-native auth path. The create card kept
writing the derived reference unconditionally, so a route declared for a
credential chain or ADC was born pointing at a reference nothing sets —
and now rendered a red missing-key dot for it.

Both cards apply one rule. The obsolete assertion moves with the behavior
(the with-key case is covered by the neighbouring test), and the merged
Models e2e golden shows the declared route unmarked rather than flagged.
2026-08-07 13:57:52 +08:00
Yichen Jiang
768e2e866f fix(web): keep skill row pairing client-local 2026-08-07 13:56:42 +08:00
Yichen Jiang
d63c70bcf1 Merge remote-tracking branch 'origin/master' into worktree/default-model-persistence
# Conflicts:
#	apps/web/tests/models-settings.e2e.ts
#	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
2026-08-07 13:54:15 +08:00
Yichen Jiang
9679597204 feat(ui-models): tag the provider rows this deployment declared
A row's stored profile could not tell a hand-declared gateway from a
shipped provider whose models someone narrowed — both look identical from
outside the adapter — so the Models page had no way to mark the routes a
deployment added itself.

The directory entry now carries `declared`, answered by the owning adapter
against its own installed catalog, and the page renders a Custom tag from
it. Absence stays "this adapter draws no such distinction" rather than
"shipped", so a route no adapter claims is labelled neither way.

Also records the default-route work's Agent Note and the e2e evidence for
all three changes: the composer switch writing the section, and the Models
page declaring a route with its own reasoning effort.
2026-08-07 13:49:47 +08:00
_Kerman
1e759608f6 test(web): refresh steer-all goldens against merged master UI 2026-08-07 13:48:33 +08:00
fz
1f853d85cd Attribute reader scroll input through the observed-top ledger
ChatView's bottom-follow recognized only wheel gestures as reader input,
so touch panning, scrollbar dragging, and keyboard paging could not leave
the bottom of a streaming transcript. Replace the wheel listener with
device-agnostic attribution: a scroll position deviating from the
observed-top ledger of the last delivered or written scrollTop is reader
input. Adds keyboard-paging and touch-style fling e2e scenarios (red under
the old implementation) and the bilingual Agent Note triplet.
2026-08-07 13:44:49 +08:00
_Kerman
07854f017e Merge remote-tracking branch 'github/master' into feat/web-queue-steer-all
# Conflicts:
#	packages/client/ui-conversation/README.i18n.yaml
2026-08-07 13:40:06 +08:00
Yichen Jiang
90734c188e Merge branch 'stack/agent-profiles-7-docs' into stack/agent-profiles-8-authoring 2026-08-07 13:39:41 +08:00
Yichen Jiang
a184d9efde Merge branch 'stack/agent-profiles-4-settings' into stack/agent-profiles-5-web-ui 2026-08-07 13:39:40 +08:00
Yichen Jiang
f3f2129154 Merge branch 'stack/agent-profiles-2-configs' into stack/agent-profiles-3-wire
# Conflicts:
#	packages/host/apiproxy/src/api-proxy.ts
#	packages/host/apiproxy/tests/api-proxy-subagents.spec.ts
2026-08-07 13:39:29 +08:00
Yichen Jiang
0cb922199d fix(apiproxy): open config files through Windows on WSL 2026-08-07 13:30:05 +08:00
Yichen Jiang
ddacc8de45 Merge pull request #1735 from deepseek-harness/worktree/provider-credential-lifecycle
fix(web): recover provider credential lifecycle
2026-08-07 13:27:18 +08:00
Yif
7a76365585 feat(web): restyle hero preview badge and grow wide-sidebar settings icon
The hero Preview tag becomes a superscript mono pill riding the title's
top-right (r24, bordered, business-tertiary fill), colored by the new
--dsw-alias-label-primary-bluish alias over --dsw-static-blue-900 — the
first design-owner-approved addition under the token-sheet authority
exception recorded in the ui-theme README. The expanded sidebar trigger
now uses the native 16px settings icon instead of the 14px asset.
2026-08-07 13:27:15 +08:00
Yichen Jiang
e0f9f7a6e6 fix(ui-models): let a hand-declared route set its reasoning effort
The create card omitted the provider-level effort the editor card offers
for the same namespace, so a route declared through 添加自定义提供方 gained
a setting the moment it was reopened for editing — one the creating user
was never shown.

Both cards now render one shared control. The field, its vocabulary, and
the inherit-means-absent rule live with the control rather than in the
editor, which is what stops the two from drifting apart again.
2026-08-07 13:25:46 +08:00
Yichen Jiang
9264f383e6 Merge remote-tracking branch 'origin/master' into worktree/web-skill-tool-row
# Conflicts:
#	apps/web/tsconfig.json
#	tsconfig.host.json
2026-08-07 12:48:08 +08:00
NI0317
9597ff9bf7 feat(web): advertise whole-queue steering shortcut 2026-08-07 12:18:30 +08:00
_Kerman
156c284239 Merge remote-tracking branch 'github/master' into feat/web-queue-steer-all
# Conflicts:
#	packages/client/ui-conversation/README.i18n.yaml
2026-08-07 12:03:44 +08:00
creatixchu
aa831f4f5e Merge remote-tracking branch 'origin/master' into worktree/turn-tail-actions
# Conflicts:
#	packages/client/ui-conversation/README.i18n.yaml
2026-08-07 11:55:53 +08:00
_Kerman
653e22bc50 test(web): cover empty-draft queue flush with a keyless replay scenario
Also pin the queue-item-not-found convergence arm through the hub and
document the repeated-trigger contract on steerQueue.
2026-08-07 11:55:46 +08:00
Yichen Jiang
05756950a8 Merge branch 'stack/agent-profiles-7-docs' into stack/agent-profiles-8-authoring
# Conflicts:
#	packages/client/ui-agent-preset/src/client/settings-store.ts
#	packages/client/ui-agent-preset/tests/settings-store.spec.ts
#	packages/host/apiproxy/src/api-proxy.ts
#	packages/host/apiproxy/tests/api-proxy-agent-preset.spec.ts
2026-08-07 11:52:05 +08:00
Yichen Jiang
d099a24cb1 fix(web): resume the preset the log records, and serialize the switch
Six review findings on the select surface, all reachable from the wire:

**Resume read the header, not the log.** The switch was recorded as
`agent-preset/selected` and every projection resolved from it, but `agentFor`
still composed from `inspected.meta.agentPreset` — the value written once at
creation. A blank session that switched and then ran turns came back after a
restart under the ORIGINAL preset, restoring that history under the tool set it
was not produced with, which is the mismatch this feature exists to prevent.
`inspected` already carries the events.

**Cold summaries dropped the preset entirely.** `summarizeCold` hand-copied
three header fields and omitted the fourth, so a restored session reported no
preset and the picker showed the deployment default. It now uses the same
projection the attached path does.

**`select` had no gate.** Two concurrent selects both passed the blank check;
the second `unmountPresetFor` then found no record, because the first had
already removed it, and both mounts installed into one agent layer. Selects on
one session now queue, and the blank check is re-read inside the queue. This is
not turn admission — a `session.prompt` racing a switch is the agent loop's to
reserve — but it closes the select-versus-select tear-down.

**A same-id restore was skipped.** The roster is a live directory, so "the same
inputs that worked a moment ago" does not hold: a changed file is exactly how a
same-id reselect fails, and skipping the restore left the agent with no
composition at all.

**`writable` was dead state**, initialized true and never set, so the row could
never disable. It now carries `settings.describe`'s bit — a browser that may
not write settings sees the current default and no control, rather than one
whose write answers `settings-not-exposed`.

**`list` was documented as id-ordered.** It is root-precedence order with each
root's own presets sorted, first root to supply an id winning.
2026-08-07 11:45:10 +08:00
Yichen Jiang
545080105f Merge branch 'master' into worktree/charming-swartz-83bf33 2026-08-07 11:37:57 +08:00
Yichen Jiang
abd2e2973b Merge branch 'master' into worktree/provider-credential-lifecycle 2026-08-07 11:37:41 +08:00
Yichen Jiang
3aa3212fd7 Merge branch 'master' into worktree/web-skill-tool-row 2026-08-07 11:37:34 +08:00
Yichen Jiang
fcc3148cc9 Merge remote-tracking branch 'origin/master' into worktree/persist-web-theme-settings 2026-08-07 11:37:13 +08:00