Files
deepseek-harness/packages/client/ui-command
Yif 92dd231ce4 polish(web): 打磨 Web 会话界面的布局、自适应与组件一致性
1. 统一会话列宽度轴:新增 --dsh-chat-content-width(748px),输入框、todo、goal、queue、approval、plan review、ask question 等容器的宽度与边距全部由该变量推导,消除各面板之间的像素漂移,窄视口下的边缘留白也保持一致。
2. 输入框自适应与细节:控制行改为容器查询(460px 阈值以下权限选择器只显示图标+下拉,隐藏文字);卡片圆角 20→22、行内边距调整并整体下移 2px(发送按钮除外);permission/model 触发器统一 24px 圆角;Plan 与 Read Only 间距 +8。
3. 修复浮层菜单溢出:slash 菜单与命令弹层钳制到输入卡片宽度,超长行以省略号截断;Tooltip 增加 12px 视口边缘安全距离。
4. 增加与替换图标:Add provider 改用输入框同款加号图标(IconPlusOutline16),统一图标尺寸与字号。
5. 统一 Settings → Models 组件:补齐按钮 hover 态、select 下拉箭头不再贴边、标题区与 provider 卡片间距 +12。
6. 侧边栏交互:add workspace / group by / create session / 收起侧边栏四个图标按钮增加 500ms 延迟 tooltip(前两个向下弹出);展开态的 New Session 不再重复显示 tooltip;侧边栏窄屏自适应收起逻辑微调。
7. 其他:hero 区 workspace 徽章右移对齐;附带 Agent Note(中英双语)记录共享宽度轴与容器查询的设计取舍。
2026-08-04 14:14:12 +08:00
..
wip
2026-07-31 02:13:53 +08:00
wip
2026-07-31 02:13:53 +08:00

@deepseek-ai/dsh-client-ui-command

English | 中文

Client command surface (ctx.command): the session-keyed command-directory cache, the / command source with matchSpace/matchEnter adjudication hooks, three-kind dispatch (execute / popupSelect / leadingInput), and the popupSelect registration face for business packages. Contract: the web command surfaces Agent Note.

src/client/contract.ts is the frozen business face: CommandServiceContract.register(name, spec) and decorate(name, spec) are everything a business package consumes; CommandUiSpec{options, onSelect} keeps popup data self-served — the shell component is this package's and business never sees it. A contribution is a client-owned command (a host-name collision fails loud); a decoration hangs a bare-invocation popup on an EXISTING host command — the host keeps its catalog row, argument claim (space / argued enter), and lifecycle logging, and a decorated name with no host row in the session's directory simply never fires. Command kinds derive per dispatch, never per registration: a host descriptor with input is leadingInput, a registered CommandUiSpec is popupSelect, everything else is execute.

CommandDirectory (src/client/directory.ts) is the one wire-derived cache, keyed by session. Ordinary sessions fetch through command.list({sessionId}), and the source's scope-birth warm hook prewarms the session's entry. Catalog-addressed continuable children resolve an empty command directory locally: command.list is Agent-bound, so prewarming it would activate a child merely to view persisted history. Entries are soft-invalidated by the commands/changed typed event (old snapshot serves while the repull flies), hard-invalidated by connection/reset, epoch-guarded so a superseded pull can never overwrite a newer one. matchSpace answers synchronously from this cache only; matchEnter strong-waits it on the SubmitAttempt signal and rejects on warmup failure — a / line is never silently downgraded to a plain prompt.

PopupSelectController (src/client/popup.ts) is the headless shell state: PopupSelectView self-registers into conversation.input.overlay (the SlotMap key is ui-conversation's; this package pulls the declaration in with a type-only import — no runtime edge). The shell is a transient layer holding focus while open; token-segment consumption after onSelect runs both branches through consumeTokenSegment (menu-path span CAS, enter-path bare-token equality) against the draft face the wiring layer binds via bindDraft.

The /client export surface is the plugin body (apply/inject), CommandService, the directory and popup classes with their state types, and the frozen contract types; the shell component itself is internal to the overlay registration.

Model Experience

Indirectly, through the host command.execute RPC this package's dispatch and claim.submit paths trigger: a matched command's handler mutates host domain state that other packages project into the next request (the /plan handler flips plan mode, whose owning package injects its plan:policy system-prompt section), while the command line itself, the detached result, and every menu/notice rendering stay client-side and never enter the session log.

KV Cache effect

None directly; this package neither assembles nor sends a provider request. Command handlers it triggers may change what the owning host packages contribute to the next request's system prompt (a section appearing or disappearing replaces earlier request tokens and invalidates the provider prefix from that point), but that effect is owned and documented by each command's host package.

Known Limitations and Deferred Work

  • The popupSelect shell has no shipped business consumer — model selection (host selectModel) is the design's reference case and lands with its own feature work; until then the shell is exercised by package tests only.
  • Detached-result notices fall back to the console off-session — the fire-and-forget paths route results to the triggering session's composer via SessionInput.notify; after session teardown the console line is the only remaining surface.