Merge branch 'worktree/ci-native-windows-coverage-20260808' into worktree/ci-native-windows-multicore-20260809

# Conflicts:
#	.agents/notes/implemented/process/2026-08-08-native-windows-pull-request-ci.i18n.yaml
This commit is contained in:
Tianyi Cui
2026-08-09 21:56:52 +08:00
791 changed files with 1930 additions and 1829 deletions

View File

@@ -2,5 +2,5 @@
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write packages/client/ui-primitives/README.md
README.md: 098a202a4ac9ee263ce1beaaee7a8624ebf26b80
README.zh.md: def1907f81d06b5afdf19af5f19ba17a269ed3c1
README.md: a9c802c1e43cf06aa0492b39d5052e882a72d9e6
README.zh.md: 9e67488ccc1d70263bd0b91d167c4c251ee95926

View File

@@ -2,7 +2,7 @@
English | [中文](README.zh.md)
Pure React atoms (zero cordis): StateDot, DisclosureRow, ic_ds_* icons, Button/Pill/Menu/Modal/Input, the OnboardingSurface first-run takeover (body-portaled mask + opaque stage that holds `#root` inert for exactly its own lifetime), the markdown family (MessageText/MarkdownText/JsonBlock), the read-only JsonTree inspector, the `useAnchoredMaxHeight` hook that clamps a bottom-anchored overlay to the viewport space above its anchor (re-measured on resize, scroll, and a caller-supplied dependency), TerminalBlock, DiffBlock, ReadBlock, SearchBlock, and WebBlock. Contract: api-contracts v3 §8.
Pure React atoms (zero cordis): StateDot, DisclosureRow, ic_ds_* icons, Button/Pill/Menu/Modal/Input, the OnboardingSurface first-run takeover (body-portaled mask + opaque stage that holds `#root` inert for exactly its own lifetime), the markdown family (MessageText/MarkdownText/JsonBlock), the read-only JsonTree inspector, the `useAnchoredMaxHeight` hook that clamps a bottom-anchored overlay to the viewport space above its anchor (re-measured on resize, scroll, and a caller-supplied dependency), TerminalBlock, DiffBlock, ReadBlock, SearchBlock, and WebBlock.
## Hover cards
@@ -46,5 +46,5 @@ None; this package neither assembles nor sends a provider request.
- **Glyph-level icons are redrawn approximations** — the fish logo (and the sparkle held by ui-conversation) come from font glyphs whose vector geometry is not exportable from the local design data; hand-authored recreations stand in until an exact export path exists.
- **Pill and Input have no design source** — both atoms are self-defined; the sidebar search field and view-tab strip that resemble them are consumer-owned compositions, not these atoms.
- **No `Active` StateDot variant** — the supported states are done, warning, ongoing, and error.
- **User-facing copy localizes through label props, defaulting to the original Chinese literals** — the atoms are zero-cordis and cannot reach `ctx.locale`, so `HoverCard` (`copyLabel`/`copiedLabel`), `TerminalBlock` (`labels`), `JsonTree` (`labels`), `CodeBlock` (`copyLabel`/`copiedLabel`), `MarkdownText` (`codeLabels`), `JsonBlock` (`truncatedLabel`), `ConnectionBanner` (`label`), and `Modal` (`closeLabel`) take their copy as optional props with the previous hardcoded strings as defaults. Localized plugins pass dictionary-driven labels from their own `t` seat; a consumer that passes nothing renders exactly the pre-localization output. `WebBlock` does not yet follow this pattern: its source-list and fetch truncation notes and its empty-search note stay inline Chinese, pending the same label-prop treatment.
- **User-facing copy localizes through label props, defaulting to the original Chinese literals** — the atoms are zero-cordis and cannot reach `ctx.locale`, so `HoverCard` (`copyLabel`/`copiedLabel`), `TerminalBlock` (`labels`), `JsonTree` (`labels`), `CodeBlock` (`copyLabel`/`copiedLabel`), `MarkdownText` (`codeLabels`), `JsonBlock` (`truncatedLabel`), `ConnectionBanner` (`label`), and `Modal` (`closeLabel`) take their copy as optional props. Localized plugins pass dictionary-driven labels from their own `t` seat; a consumer that passes nothing gets those defaults. `WebBlock` does not yet follow this pattern: its source-list and fetch truncation notes and its empty-search note stay inline Chinese, pending the same label-prop treatment.
- **`TerminalBlock` is not a terminal emulator** — it renders settled or still-running command output, not an interactive session: SGR color and attributes are honored, and so are the in-line cursor movements a progress line uses — carriage return, backspace, erase-in-line, tab stops and character width. Absolute cursor positioning, screen clearing, and alternate-screen sequences are stripped. Basic-16 magenta and cyan have no token equivalent and stay literal rgb.

View File

@@ -2,7 +2,7 @@
[English](README.md) | 中文
纯 React 原子组件(零 cordisStateDot、DisclosureRow、ic_ds_* 图标、Button/Pill/Menu/Modal/Input、OnboardingSurface 首次使用接管层portal 到 body 的遮罩加不透明展示层,在且仅在自身生命周期内保持 `#root``inert`、markdown 家族MessageText/MarkdownText/JsonBlock、只读 JsonTree 检查器、`useAnchoredMaxHeight` 钩子(把底部锚定的浮层高度收敛到锚点上方的视口空间,并在 resize、scroll 与调用方提供的依赖变化时重新测量、TerminalBlock、DiffBlock、ReadBlock、SearchBlock以及 WebBlock。约定api-contracts v3 §8。
纯 React 原子组件(零 cordisStateDot、DisclosureRow、ic_ds_* 图标、Button/Pill/Menu/Modal/Input、OnboardingSurface 首次使用接管层portal 到 body 的遮罩加不透明展示层,在且仅在自身生命周期内保持 `#root``inert`、markdown 家族MessageText/MarkdownText/JsonBlock、只读 JsonTree 检查器、`useAnchoredMaxHeight` 钩子(把底部锚定的浮层高度收敛到锚点上方的视口空间,并在 resize、scroll 与调用方提供的依赖变化时重新测量、TerminalBlock、DiffBlock、ReadBlock、SearchBlock以及 WebBlock。
## 悬浮卡片
@@ -46,5 +46,5 @@
- **字形级图标是重新绘制的近似版本**:鱼形标志(以及 ui-conversation 持有的闪光图标)来自字体字形,而本地设计数据无法导出其矢量几何;在获得精确导出路径前,使用手工重建版本代替。
- **Pill 与 Input 没有设计来源**:两个原子组件均自行定义;与其相似的侧边栏搜索字段和视图标签条由消费方组合,不是这些原子组件。
- **StateDot 没有 `Active` 变体**:支持的状态为 done、warning、ongoing 和 error。
- **面向用户的文案经 label props 本地化,默认值为原中文字面量**:这些原子组件是 zero-cordis 的,拿不到 `ctx.locale`,因此 `HoverCard``copyLabel`/`copiedLabel`)、`TerminalBlock``labels`)、`JsonTree``labels`)、`CodeBlock``copyLabel`/`copiedLabel`)、`MarkdownText``codeLabels`)、`JsonBlock``truncatedLabel`)、`ConnectionBanner``label`)和 `Modal``closeLabel`)都把文案作为可选 props 接收,默认值即此前的硬编码字符串。已本地化的插件用自己的 `t` 席位传入字典驱动的 label什么都不传的消费者渲染与本地化之前逐字节一致`WebBlock` 尚未跟进这一模式:它的来源列表截断提示与 fetch 截断提示、以及空搜索提示仍是内联中文,待同样的 label-prop 处理。
- **面向用户的文案经 label props 本地化,默认值为原中文字面量**:这些原子组件是 zero-cordis 的,拿不到 `ctx.locale`,因此 `HoverCard``copyLabel`/`copiedLabel`)、`TerminalBlock``labels`)、`JsonTree``labels`)、`CodeBlock``copyLabel`/`copiedLabel`)、`MarkdownText``codeLabels`)、`JsonBlock``truncatedLabel`)、`ConnectionBanner``label`)和 `Modal``closeLabel`)都把文案作为可选 props 接收。已本地化的插件用自己的 `t` 席位传入字典驱动的 label什么都不传的消费方得到的就是这些默认值`WebBlock` 尚未跟进这一模式:它的来源列表截断提示与 fetch 截断提示、以及空搜索提示仍是内联中文,待同样的 label-prop 处理。
- **`TerminalBlock` 不是终端模拟器**它渲染已结束或仍在运行的命令输出而不是交互式会话SGR 颜色与属性会被遵循,进度行所用的行内光标移动同样被遵循——回车、退格、行内擦除、制表位与字符宽度。绝对光标定位、清屏与备用屏幕序列会被剥离。基础 16 色中的洋红与青色没有对应 token保持字面 rgb。

View File

@@ -221,8 +221,8 @@ export function TerminalBlock({
// Read from the parsed lines the card actually renders, not from the raw text:
// output that is only escapes or control bytes (a lone reset, an OSC title, an
// erase) survives `text.trim()` yet parses to nothing visible. Judging it on
// the raw text drew an output box of blank rows plus a copy control for
// invisible bytes, and hid the placeholder that belongs there.
// the raw text would draw an output box of blank rows plus a copy control
// for invisible bytes, and hide the placeholder that belongs there.
const empty = lines.every(line => line.every(span => span.text.trim() === ''))
const { hidden, capped, headLines, tailLines } = headTailCap(lines.length, maxLines, expanded)

View File

@@ -1,6 +1,6 @@
/* Visual spec mirrors deepsuite @deepseek/ui Tooltip.css (size m, no arrow),
except padding tightened 6/12 -> 3/7, type 14/22 -> 13/20, and radius
10 -> 8 by product ruling: tooltip-bg plate,
except padding tightened 6/12 -> 3/7, type 14/22 -> 13/20, radius
10 -> 8, a tooltip-bg plate,
one text color across both themes (the plate stays dark in light and dark
mode). Behavior (fixed positioning off the anchor rect) is local — the
upstream Floating stack is intentionally not vendored. */

View File

@@ -84,8 +84,7 @@ const LAZY_GRAMMARS = new Map<string, () => Promise<LangModule>>([
* the markdown-fence aliases `CodeBlock` uses and the file-extension hint ids
* the read tool's `langFromPath` emits, so both callers resolve the same
* grammars. The JS family maps to the TypeScript grammar (see {@link LANGS} for
* the JSX/TSX approximation), unchanged from when this was the only
* non-shell/JSON grammar. A value not in {@link LANGS} names a
* the JSX/TSX approximation). A value not in {@link LANGS} names a
* {@link LAZY_GRAMMARS} entry loaded on first use.
*/
const LANG_ALIASES = new Map<string, string>([

View File

@@ -359,10 +359,10 @@ describe('parseAnsiLines: line-end state and column widths', () => {
describe('parseAnsiLines: bounded state and true widths', () => {
it('emits one canonical sequence per boundary however the state was reached', () => {
// Colors that never fully reset used to accumulate raw sequence history per
// cell, so every boundary re-emitted the whole chain: 3200 such cells
// produced 25 MB and eventually a RangeError. The state is normalized now,
// so the emitted text stays linear in the number of cells.
// Colors that never fully reset would, under a raw per-cell sequence
// history, re-emit the whole chain at every boundary: 3200 such cells
// produce 25 MB and eventually a RangeError. Normalized state keeps
// the emitted text linear in the number of cells.
let input = ''
for (let index = 0; index < 2000; index += 1) input += `${ESC}[3${index % 6 + 1}mx`
const emitted = parseAnsiLines(`${input}\rz`)[0] ?? []

View File

@@ -91,8 +91,8 @@ describe('HoverCard', () => {
it('reaching the card inside the grace keeps it open without restarting the dwell', () => {
// The portaled card is a React child of the wrapper, so the pointer
// arriving on it re-enters the wrapper — the gesture the 8px anchor gap
// used to make impossible.
// arriving on it re-enters the wrapper — the gesture an anchor gap
// would make impossible.
const { wrapper } = mount()
fireEvent.pointerEnter(wrapper)
act(() => { vi.advanceTimersByTime(500) })

View File

@@ -16,7 +16,7 @@ const icons = Object.fromEntries(
const iconNames = Object.keys(icons)
describe('ic_ds_ icon set', () => {
it('exports the full P-I set (46 deepsuite + 17 figma extracts + three product glyphs outside those sets)', () => {
it('exports the full icon set (46 deepsuite + 17 figma extracts + three product glyphs outside those sets)', () => {
expect(iconNames.length).toBe(66)
})

View File

@@ -2,7 +2,7 @@ import { clientOnly } from '../tsdown.client.ts'
/**
* ui-primitives is browser-only, but its lib bundle IS imported under plain
* Node now that the web shell is a lib (dsh-client-web's lib chain reaches
* Node because the web shell is a lib (dsh-client-web's lib chain reaches
* this package). CSS imports are therefore stubbed to empty modules instead
* of externalized — the hashed class maps only matter in bundler contexts
* (loader module table / vite source paths), which compile src directly and