dsh-plugin-bridge 0.3.1 → 0.3.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -9,7 +9,7 @@
9
9
  [![ci](https://github.com/Totoro-qaq/dsh-plugin-bridge/actions/workflows/ci.yml/badge.svg)](https://github.com/Totoro-qaq/dsh-plugin-bridge/actions/workflows/ci.yml)
10
10
  [![license](https://img.shields.io/badge/license-MIT-green)](LICENSE)
11
11
  [![node ≥22](https://img.shields.io/badge/node-%E2%89%A522-339933)](package.json)
12
- [![dsh rc.6 → 0.1.2-alpha.2](https://img.shields.io/badge/dsh-rc.6%20%E2%86%92%200.1.2--alpha.2-4c8dff)](https://github.com/deepseek-ai/deepseek-harness)
12
+ [![dsh 0.1.3-alpha.2](https://img.shields.io/badge/dsh-0.1.3--alpha.2-4c8dff)](https://github.com/deepseek-ai/deepseek-harness)
13
13
  [![Listed in Awesome DSH Plugin](https://img.shields.io/badge/listed_in-Awesome_DSH_Plugin-2ea44f)](https://github.com/awesome-dsh-plugin/awesome-dsh-plugin)
14
14
  [![dshfind](https://dshfind.com/api/badge/Totoro-qaq/dsh-plugin-bridge?lang=en)](https://dshfind.com/en/plugins/Totoro-qaq/dsh-plugin-bridge?ref=badge)
15
15
 
@@ -35,7 +35,7 @@ dsh plugin --profile web add dsh-plugin-bridge
35
35
  Pinned GitHub fallback:
36
36
 
37
37
  ```bash
38
- dsh plugin --profile web add github:Totoro-qaq/dsh-plugin-bridge#v0.3.1
38
+ dsh plugin --profile web add github:Totoro-qaq/dsh-plugin-bridge#v0.3.3
39
39
  ```
40
40
 
41
41
  Then type in the official WebUI:
@@ -48,7 +48,7 @@ Then type in the official WebUI:
48
48
  /bridge code --go --continue restate and start work in the same target request
49
49
  ```
50
50
 
51
- On DSH rc.7 and later, the official WebUI renders `/bridge` as a native card. **Text** exposes the fixed five sections as ordinary fields and list rows; **Markdown** preserves full source freedom; **Preview** renders Markdown or a complete JSON tree. Long content scrolls inside the card while the action bar stays reachable. **Confirm migration** opens the created target session.
51
+ On DSH rc.7 and later, the official WebUI renders `/bridge` as a native card. **Text** exposes the fixed five sections as ordinary fields and flat bullet or ordered-list rows while preserving their Markdown markers; **Markdown** preserves full source freedom; **Preview** renders Markdown or a complete JSON tree. Long content scrolls inside the card while the action bar stays reachable. **Confirm migration** opens the created target session.
52
52
 
53
53
  UIs that implement the official `conversation.chat.commandview` slot receive the same card automatically. Other custom UIs retain the complete server result, summary-file workflow, and target title/session-ID fallback; UI authors can reuse the framework-free `dsh-plugin-bridge/client-contract` export instead of reimplementing the wire. On an older or non-slot client, correct the printed summary file and run:
54
54
 
@@ -84,7 +84,7 @@ The release gate is intentionally small and reproducible; these are regression r
84
84
  | Confirm extra, paired nominal median | **+8.1%** vs `--continue` |
85
85
  | Summary worker share of clean acceptance components | **20.74% nominal** |
86
86
  | Native WebUI repeat gate (preview / target facts) | **3/3 · 3/3**, five facts each |
87
- | DSH 0.1.2-alpha.2 npm install / doctor / target | **clean · 13/13 · PTC paused** |
87
+ | DSH 0.1.2 alpha.2 / alpha.3 / alpha.5 installed WebUI | **13/13 · ordered-list edit · PTC paused · image → text fallback** |
88
88
 
89
89
  The token percentage varies widely with preset, response length, and cache state. The worker share is composition, not causal overhead versus no Bridge; the stable product claim is one additional confirmation request. Read the [design and evidence boundaries](docs/design.md), [full release report](reports/v0.2.3-e2e-report.md), and [vision report](reports/v0.2.6-rc11-vision-report.md).
90
90
 
@@ -117,7 +117,10 @@ The five sections are Goal, Current state, Key decisions and conventions, Key fi
117
117
  | 0.1.0-rc.6 | Yes | No | Narrow RPC contract and text compatibility tests |
118
118
  | 0.1.0-rc.7 / rc.8 | Yes | Contract-checked | Client-module/command-slot contract plus server fallback |
119
119
  | 0.1.1-rc.2 | Yes | Yes | Installed official WebUI: doctor 13/13, edit/confirm/auto-open, three-run repeat gate |
120
- | 0.1.2-alpha.2 | Yes | Yes | Official npm install: typed controllers 13/13, split-client build, edit/confirm/PTC auto-open, clean removal |
120
+ | 0.1.2-alpha.2 / alpha.3 / alpha.5 | Yes | Yes | Official DSH npm hosts: typed controllers 13/13 and PTC auto-open; the alpha.5 gate installed the branch tarball, retained alpha.3 titles, edited ordered lists, fell back from unresolved image to text, and removed cleanly |
121
+ | 0.1.2-rc.1 → 0.1.3-alpha.2 | Yes (Bridge 0.3.3+) | Yes (Bridge 0.3.3+) | Real npm-host upgrade, preserved v2 history/title, exact edited payload, PTC paused goal, image fallback and clean removal; see [acceptance report](reports/dsh-0.1.3-alpha.2-compat-2026-09-08.md) |
122
+
123
+ Use Bridge 0.3.3 or later for DSH 0.1.3-alpha.2; Bridge 0.3.2 does not include these compatibility changes. The typed adapter reads the default 240-message history window with one fresh `inspect` call instead of four; it does not cache running state. `doctor` checks method availability, not end-to-end compatibility.
121
124
 
122
125
  CI covers Node.js 22 and 24. Run `/bridge --doctor` after every Harness upgrade; it names missing required gateway methods instead of failing vaguely.
123
126
 
@@ -148,7 +151,7 @@ npm ci
148
151
  npm run verify
149
152
  ```
150
153
 
151
- `verify` builds and type-checks both plugin halves, runs 167 tests, checks generated `lib/` and datasets, then packs, installs, and imports the actual npm tarball. Tests spend no model tokens. `prepublishOnly` runs the same gate; GitHub releases also require the tag to match `package.json` before trusted npm publishing.
154
+ `verify` builds and type-checks both plugin halves, runs 174 tests, checks generated `lib/` and datasets, then packs, installs, and imports the actual npm tarball. Tests spend no model tokens. `prepublishOnly` runs the same gate; GitHub releases also require the tag to match `package.json` before trusted npm publishing.
152
155
 
153
156
  Community listings: [Awesome DSH Plugin](https://github.com/awesome-dsh-plugin/awesome-dsh-plugin) · [Awesome DeepSeek Harness](https://github.com/Dominic789654/awesome-deepseek-harness)
154
157
 
package/README.zh.md CHANGED
@@ -9,7 +9,7 @@
9
9
  [![ci](https://github.com/Totoro-qaq/dsh-plugin-bridge/actions/workflows/ci.yml/badge.svg)](https://github.com/Totoro-qaq/dsh-plugin-bridge/actions/workflows/ci.yml)
10
10
  [![license](https://img.shields.io/badge/license-MIT-green)](LICENSE)
11
11
  [![node ≥22](https://img.shields.io/badge/node-%E2%89%A522-339933)](package.json)
12
- [![dsh rc.6 → 0.1.2-alpha.2](https://img.shields.io/badge/dsh-rc.6%20%E2%86%92%200.1.2--alpha.2-4c8dff)](https://github.com/deepseek-ai/deepseek-harness)
12
+ [![dsh 0.1.3-alpha.2](https://img.shields.io/badge/dsh-0.1.3--alpha.2-4c8dff)](https://github.com/deepseek-ai/deepseek-harness)
13
13
  [![收录于 Awesome DSH Plugin](https://img.shields.io/badge/%E5%B7%B2%E6%94%B6%E5%BD%95-Awesome_DSH_Plugin-2ea44f)](https://github.com/awesome-dsh-plugin/awesome-dsh-plugin)
14
14
  [![dshfind](https://dshfind.com/api/badge/Totoro-qaq/dsh-plugin-bridge?lang=zh)](https://dshfind.com/zh/plugins/Totoro-qaq/dsh-plugin-bridge?ref=badge)
15
15
 
@@ -35,7 +35,7 @@ dsh plugin --profile web add dsh-plugin-bridge
35
35
  GitHub 固定版本备用路径:
36
36
 
37
37
  ```bash
38
- dsh plugin --profile web add github:Totoro-qaq/dsh-plugin-bridge#v0.3.1
38
+ dsh plugin --profile web add github:Totoro-qaq/dsh-plugin-bridge#v0.3.3
39
39
  ```
40
40
 
41
41
  然后在官方 WebUI 输入:
@@ -48,7 +48,7 @@ dsh plugin --profile web add github:Totoro-qaq/dsh-plugin-bridge#v0.3.1
48
48
  /bridge code --go --continue 在同一次目标请求里复述并开始工作
49
49
  ```
50
50
 
51
- DSH rc.7 及以上会在官方 WebUI 原生卡片中渲染 `/bridge`。「文本编辑」把固定五段变成普通文本框和逐条列表;「Markdown」保留完整源码自由;「预览」渲染 Markdown 或完整 JSON 树。长内容只在卡片正文内滚动,操作按钮保持可达;点「确认迁移」后自动打开目标会话。
51
+ DSH rc.7 及以上会在官方 WebUI 原生卡片中渲染 `/bridge`。「文本编辑」把固定五段变成普通文本框,并无损支持平坦的项目符号或编号列表;「Markdown」保留完整源码自由;「预览」渲染 Markdown 或完整 JSON 树。长内容只在卡片正文内滚动,操作按钮保持可达;点「确认迁移」后自动打开目标会话。
52
52
 
53
53
  实现官方 `conversation.chat.commandview` slot 的第三方 UI 会自动得到同一张卡片。其他自定义 UI 仍保留完整服务端结果、摘要文件流程和目标标题/session ID 回退;UI 作者还可以复用无 React 的 `dsh-plugin-bridge/client-contract` 导出,而无需重写协议。旧客户端可修改输出里打印的摘要文件,再执行:
54
54
 
@@ -84,7 +84,7 @@ DSH rc.7 及以上会在官方 WebUI 原生卡片中渲染 `/bridge`。「文本
84
84
  | Confirm 相对 `--continue` 的 nominal 配对中位额外成本 | **+8.1%** |
85
85
  | 摘要 worker 在干净验收组件中的 nominal 占比 | **20.74%** |
86
86
  | 原生 WebUI 重复门禁(预览 / 目标事实) | **3/3 · 3/3**,每次五项 |
87
- | DSH 0.1.2-alpha.2 npm 安装 / doctor / 目标 | **干净 · 13/13 · PTC 已暂停** |
87
+ | DSH 0.1.2 alpha.2 / alpha.3 / alpha.5 官方 WebUI 实装 | **13/13 · 编号列表编辑 · PTC 已暂停 · 图片转文本降级** |
88
88
 
89
89
  token 百分比会随 preset、回复长度和缓存状态大幅波动;worker 占比是组成,不是相对“无 Bridge”的因果开销。稳定结论是默认确认多一个请求。边界和原始证据见[设计与证据说明](docs/design.md)、[完整 release report](reports/v0.2.3-e2e-report.md)和[视觉迁移报告](reports/v0.2.6-rc11-vision-report.md)。
90
90
 
@@ -117,7 +117,10 @@ token 百分比会随 preset、回复长度和缓存状态大幅波动;worker
117
117
  | 0.1.0-rc.6 | 支持 | 不支持 | 窄 RPC 契约与文本兼容测试 |
118
118
  | 0.1.0-rc.7 / rc.8 | 支持 | 契约核对 | client module / command slot 契约与服务端回退 |
119
119
  | 0.1.1-rc.2 | 支持 | 支持 | 官方 WebUI 实装:doctor 13/13、编辑/确认/自动跳转、三次重复门禁 |
120
- | 0.1.2-alpha.2 | 支持 | 支持 | 官方 npm 实装:typed controllers 13/13、拆分 client 构建、编辑/确认/PTC 自动跳转、干净卸载 |
120
+ | 0.1.2-alpha.2 / alpha.3 / alpha.5 | 支持 | 支持 | 官方 DSH npm 宿主:typed controllers 13/13 PTC 自动跳转;alpha.5 门禁安装分支 tarball,保留 alpha.3 标题,编号列表可编辑,未解析图片降级为文本,卸载干净 |
121
+ | 0.1.2-rc.1 → 0.1.3-alpha.2 | 支持(Bridge 0.3.3+) | 支持(Bridge 0.3.3+) | 官方 npm 宿主真实升级、v2 历史与标题保留、编辑内容逐字交接、PTC goal 暂停、图片回退及卸载;见[验收记录](reports/dsh-0.1.3-alpha.2-compat-2026-09-08.md) |
122
+
123
+ DSH 0.1.3-alpha.2 请使用 Bridge 0.3.3 或更高版本;Bridge 0.3.2 不包含这些兼容改动。typed adapter 只调用一次 `inspect`,就能读取默认 240 条消息的历史窗口,原来需要四次;不会缓存运行状态。`doctor` 检查方法是否存在,不能代替完整迁移验收。
121
124
 
122
125
  CI 覆盖 Node.js 22/24。每次升级 Harness 后先跑 `/bridge --doctor`;缺哪个必要网关方法会被直接点名。
123
126
 
@@ -148,7 +151,7 @@ npm ci
148
151
  npm run verify
149
152
  ```
150
153
 
151
- `verify` 会构建并类型检查插件两端、运行 167 项测试、核对 `lib/` 与数据集,再把真实 npm tarball 打包、安装并导入。测试不消耗模型 token。`prepublishOnly` 使用同一个 gate;GitHub Release 还会先检查 tag 与 `package.json` 版本一致,再走可信 npm 发布。
154
+ `verify` 会构建并类型检查插件两端、运行 174 项测试、核对 `lib/` 与数据集,再把真实 npm tarball 打包、安装并导入。测试不消耗模型 token。`prepublishOnly` 使用同一个 gate;GitHub Release 还会先检查 tag 与 `package.json` 版本一致,再走可信 npm 发布。
152
155
 
153
156
  社区收录:[Awesome DSH Plugin](https://github.com/awesome-dsh-plugin/awesome-dsh-plugin) · [Awesome DeepSeek Harness](https://github.com/Dominic789654/awesome-deepseek-harness)
154
157
 
package/docs/design.md CHANGED
@@ -81,4 +81,6 @@ Bridge's preview, safety, and migration engine depends on the typed `BridgeHost`
81
81
 
82
82
  `/bridge --doctor` checks thirteen required semantic capabilities and names missing capabilities before mutation. Attachment recovery and goal clearing are optional enhancements and do not raise that baseline. Any future adapter must implement `BridgeHost` and pass the same fail-closed fixtures.
83
83
 
84
+ Hosts that already materialize a full snapshot may optionally implement `sessions.historyWindow`. `foldedHistory` requests its complete message budget once through this method; other adapters keep the existing paged `history` path. The typed DSH adapter takes one fresh `inspect` snapshot per window, returns only the bounded tail, and retains no snapshot between calls. Worker polling continues through fresh `history` reads. This reduces repeated Bridge-side reads and allocations; it does not promise bounded disk I/O inside the host. Method probes check availability only; v2 log replay and actual migration are covered by the [installed-host acceptance](../reports/dsh-0.1.3-alpha.2-compat-2026-09-08.md).
85
+
84
86
  The server-side slash command remains the compatibility core. The package also ships an optional WebUI client half that occupies the official per-command slot, reuses `MarkdownText` / `JsonTree`, offers lossless Text/Markdown editing, submits the reviewed summary back to the same host command, and opens the created target through the official Session runtime. The React-free `dsh-plugin-bridge/client-contract` export lets other UIs reuse the same parser and wire while unknown UIs retain the server/file fallback. No folding, attachment, goal, or fail-closed policy is reimplemented in the browser. The version boundary and fallback are documented in [native-webui-feasibility.md](native-webui-feasibility.md).
package/docs/guide.zh.md CHANGED
@@ -13,7 +13,7 @@ dsh plugin --profile web add dsh-plugin-bridge
13
13
  需要固定 GitHub tag 或 npm 暂时不可用时:
14
14
 
15
15
  ```bash
16
- dsh plugin --profile web add github:Totoro-qaq/dsh-plugin-bridge#v0.3.1
16
+ dsh plugin --profile web add github:Totoro-qaq/dsh-plugin-bridge#v0.3.3
17
17
  ```
18
18
 
19
19
  发生了什么(不用手动干预):
@@ -43,15 +43,18 @@ export interface BridgeTextSection {
43
43
  bodyStart: number;
44
44
  bodyEnd: number;
45
45
  items?: BridgeTextListItem[];
46
- listStyle?: 'bullet' | 'plain';
46
+ listStyle?: BridgeListStyle;
47
47
  textStyle?: 'plain' | 'bullets';
48
48
  }
49
+ type BridgeListStyle = 'bullet' | 'ordered' | 'plain';
49
50
  export interface BridgeTextListItem {
50
51
  text: string;
51
52
  contentStart: number;
52
53
  contentEnd: number;
53
54
  itemStart: number;
54
55
  itemEnd: number;
56
+ /** Exact Markdown marker retained when this item is edited. */
57
+ marker?: string;
55
58
  /** Original indentation for wrapped lines, kept when that item is edited. */
56
59
  continuationPrefixes?: string[];
57
60
  }
@@ -75,7 +78,7 @@ export declare function replaceBridgeTextSection(projection: BridgeTextProjectio
75
78
  export declare function replaceBridgeTextListItem(projection: BridgeTextProjection, key: BridgeTextSectionKey, index: number, plainText: string): string;
76
79
  /** Remove exactly one original list-item span. */
77
80
  export declare function removeBridgeTextListItem(projection: BridgeTextProjection, key: BridgeTextSectionKey, index: number): string;
78
- /** Append one item using the section's existing bullet/plain convention. */
81
+ /** Append one item using the section's existing Markdown list convention. */
79
82
  export declare function appendBridgeTextListItem(projection: BridgeTextProjection, key: BridgeTextSectionKey, plainText: string): string;
80
83
  /** Map the official WebUI document language onto Bridge's supported UI copy. */
81
84
  export declare function uiLanguageOf(documentLang: string | undefined): 'zh' | 'en';
@@ -85,3 +88,4 @@ export declare function parseBridgeCard(outcome: BridgeOutcome): BridgeCard;
85
88
  export declare function parseJsonDocument(text: string): object | unknown[] | undefined;
86
89
  /** Build the hidden-input-safe command used by the native editor confirmation. */
87
90
  export declare function buildBridgeMigrationCommand(targetPreset: string, summary: string, lang: 'zh' | 'en', previewId: string): string;
91
+ export {};
@@ -87,6 +87,8 @@ const THEMATIC_OR_SETEXT = /^ {0,3}(?:(?:\*[\t ]*){3,}|(?:-[\t ]*){3,}|(?:_[\t ]
87
87
  const TABLE_DELIMITER = /^ {0,3}\|?[\t ]*:?-{3,}:?[\t ]*(?:\|[\t ]*:?-{3,}:?[\t ]*)+\|?[\t ]*$/u;
88
88
  const LINK_DEFINITION = /^ {0,3}\[[^\]]+\]:[\t ]*\S/u;
89
89
  const HTML_BLOCK_START = /^ {0,3}<[/!?A-Za-z]/u;
90
+ const BULLET_LIST_ITEM = /^(- )(.+)$/u;
91
+ const ORDERED_LIST_ITEM = /^(\d{1,9}[.)] )(.+)$/u;
90
92
  function hasUnsafeBlock(line) {
91
93
  return MARKDOWN_BLOCK_START.test(line)
92
94
  || THEMATIC_OR_SETEXT.test(line)
@@ -104,8 +106,14 @@ function parseListItems(markdownBody, lineEnding, bodyStart, allowPlain) {
104
106
  const lines = sourceLines(markdownBody, lineEnding);
105
107
  if (lines.some((line) => !line.text.trim()))
106
108
  return undefined;
107
- const bullet = /^- (.+)$/u.exec(lines[0]?.text ?? '');
108
- const style = bullet ? 'bullet' : allowPlain ? 'plain' : undefined;
109
+ const firstLine = lines[0]?.text ?? '';
110
+ const style = BULLET_LIST_ITEM.test(firstLine)
111
+ ? 'bullet'
112
+ : ORDERED_LIST_ITEM.test(firstLine)
113
+ ? 'ordered'
114
+ : allowPlain
115
+ ? 'plain'
116
+ : undefined;
109
117
  if (!style)
110
118
  return undefined;
111
119
  const items = [];
@@ -123,9 +131,10 @@ function parseListItems(markdownBody, lineEnding, bodyStart, allowPlain) {
123
131
  }
124
132
  }
125
133
  else {
134
+ const itemPattern = style === 'ordered' ? ORDERED_LIST_ITEM : BULLET_LIST_ITEM;
126
135
  const starts = [];
127
136
  for (const [index, line] of lines.entries()) {
128
- if (/^- (.+)$/u.test(line.text)) {
137
+ if (itemPattern.test(line.text)) {
129
138
  starts.push(index);
130
139
  continue;
131
140
  }
@@ -137,18 +146,21 @@ function parseListItems(markdownBody, lineEnding, bodyStart, allowPlain) {
137
146
  const first = lines[lineIndex];
138
147
  const nextLineIndex = starts[itemIndex + 1] ?? lines.length;
139
148
  const last = lines[nextLineIndex - 1];
140
- const firstText = /^- (.+)$/u.exec(first.text)?.[1];
141
- if (!firstText)
149
+ const itemMatch = itemPattern.exec(first.text);
150
+ const marker = itemMatch?.[1];
151
+ const firstText = itemMatch?.[2];
152
+ if (!marker || !firstText)
142
153
  return undefined;
143
154
  const continuationLines = lines.slice(lineIndex + 1, nextLineIndex);
144
155
  const continuationPrefixes = continuationLines.map((line) => /^[\t ]*/u.exec(line.text)?.[0] ?? '');
145
156
  const continuation = continuationLines.map((line, index) => line.text.slice(continuationPrefixes[index]?.length ?? 0));
146
157
  items.push({
147
158
  text: [firstText, ...continuation].join(lineEnding),
148
- contentStart: bodyStart + first.start + 2,
159
+ contentStart: bodyStart + first.start + marker.length,
149
160
  contentEnd: bodyStart + last.contentEnd,
150
161
  itemStart: bodyStart + first.start,
151
162
  itemEnd: bodyStart + (lines[nextLineIndex]?.start ?? markdownBody.length),
163
+ marker,
152
164
  continuationPrefixes,
153
165
  });
154
166
  }
@@ -269,7 +281,7 @@ export function replaceBridgeTextSection(projection, key, plainText) {
269
281
  }
270
282
  markdownBody = section.listStyle === 'plain'
271
283
  ? values.join(projection.lineEnding)
272
- : values.map((line) => `- ${line}`).join(projection.lineEnding);
284
+ : values.map((line, index) => `${section.items?.[index]?.marker ?? '- '}${line}`).join(projection.lineEnding);
273
285
  }
274
286
  else {
275
287
  markdownBody = section.textStyle === 'bullets'
@@ -296,7 +308,7 @@ function editedListItem(text, style, lineEnding, original) {
296
308
  throw new Error('Bridge list item contains Markdown block structure');
297
309
  if (style === 'plain' && lines.length > 1)
298
310
  throw new Error('Plain path rows must stay on one line');
299
- return style === 'bullet'
311
+ return style !== 'plain'
300
312
  ? [
301
313
  lines[0],
302
314
  ...lines.slice(1).map((line, index) => `${original?.continuationPrefixes?.[index] ?? ' '}${line}`),
@@ -326,12 +338,24 @@ export function removeBridgeTextListItem(projection, key, index) {
326
338
  : item.itemStart;
327
339
  return projection.markdown.slice(0, removeStart) + projection.markdown.slice(item.itemEnd);
328
340
  }
329
- /** Append one item using the section's existing bullet/plain convention. */
341
+ /** Append one item using the section's existing Markdown list convention. */
330
342
  export function appendBridgeTextListItem(projection, key, plainText) {
331
343
  const section = listSection(projection, key);
332
344
  const edited = editedListItem(plainText, section.listStyle, projection.lineEnding);
333
345
  const prefix = section.bodyStart === section.bodyEnd ? '' : projection.lineEnding;
334
- const item = section.listStyle === 'bullet' ? `- ${edited}` : edited;
346
+ let marker = '';
347
+ if (section.listStyle === 'bullet')
348
+ marker = '- ';
349
+ if (section.listStyle === 'ordered') {
350
+ const previous = section.items?.at(-1)?.marker;
351
+ const match = /^(\d{1,9})([.)]) $/u.exec(previous ?? '');
352
+ const next = match ? Number(match[1]) + 1 : (section.items?.length ?? 0) + 1;
353
+ if (!Number.isSafeInteger(next) || next > 999_999_999) {
354
+ throw new Error('Bridge ordered list marker is out of range');
355
+ }
356
+ marker = `${String(next)}${match?.[2] ?? '.'} `;
357
+ }
358
+ const item = `${marker}${edited}`;
335
359
  return projection.markdown.slice(0, section.bodyEnd) + prefix + item + projection.markdown.slice(section.bodyEnd);
336
360
  }
337
361
  function previewHeaderOf(line) {
package/lib/client.js CHANGED
@@ -148,6 +148,8 @@ window.__ModuleLoader__.load({
148
148
  const TABLE_DELIMITER = /^ {0,3}\|?[\t ]*:?-{3,}:?[\t ]*(?:\|[\t ]*:?-{3,}:?[\t ]*)+\|?[\t ]*$/u;
149
149
  const LINK_DEFINITION = /^ {0,3}\[[^\]]+\]:[\t ]*\S/u;
150
150
  const HTML_BLOCK_START = /^ {0,3}<[/!?A-Za-z]/u;
151
+ const BULLET_LIST_ITEM = /^(- )(.+)$/u;
152
+ const ORDERED_LIST_ITEM = /^(\d{1,9}[.)] )(.+)$/u;
151
153
  function hasUnsafeBlock(line) {
152
154
  return MARKDOWN_BLOCK_START.test(line) || THEMATIC_OR_SETEXT.test(line) || TABLE_DELIMITER.test(line) || LINK_DEFINITION.test(line) || /^(?: {4}|\t)/u.test(line) || line.includes("<!--") || line.includes("-->") || line.includes("--!>") || HTML_BLOCK_START.test(line);
153
155
  }
@@ -159,7 +161,8 @@ window.__ModuleLoader__.load({
159
161
  };
160
162
  const lines = sourceLines(markdownBody, lineEnding);
161
163
  if (lines.some((line) => !line.text.trim())) return void 0;
162
- const style = /^- (.+)$/u.exec(lines[0]?.text ?? "") ? "bullet" : allowPlain ? "plain" : void 0;
164
+ const firstLine = lines[0]?.text ?? "";
165
+ const style = BULLET_LIST_ITEM.test(firstLine) ? "bullet" : ORDERED_LIST_ITEM.test(firstLine) ? "ordered" : allowPlain ? "plain" : void 0;
163
166
  if (!style) return void 0;
164
167
  const items = [];
165
168
  if (style === "plain") for (const line of lines) {
@@ -173,9 +176,10 @@ window.__ModuleLoader__.load({
173
176
  });
174
177
  }
175
178
  else {
179
+ const itemPattern = style === "ordered" ? ORDERED_LIST_ITEM : BULLET_LIST_ITEM;
176
180
  const starts = [];
177
181
  for (const [index, line] of lines.entries()) {
178
- if (/^- (.+)$/u.test(line.text)) {
182
+ if (itemPattern.test(line.text)) {
179
183
  starts.push(index);
180
184
  continue;
181
185
  }
@@ -185,17 +189,20 @@ window.__ModuleLoader__.load({
185
189
  const first = lines[lineIndex];
186
190
  const nextLineIndex = starts[itemIndex + 1] ?? lines.length;
187
191
  const last = lines[nextLineIndex - 1];
188
- const firstText = /^- (.+)$/u.exec(first.text)?.[1];
189
- if (!firstText) return void 0;
192
+ const itemMatch = itemPattern.exec(first.text);
193
+ const marker = itemMatch?.[1];
194
+ const firstText = itemMatch?.[2];
195
+ if (!marker || !firstText) return void 0;
190
196
  const continuationLines = lines.slice(lineIndex + 1, nextLineIndex);
191
197
  const continuationPrefixes = continuationLines.map((line) => /^[\t ]*/u.exec(line.text)?.[0] ?? "");
192
198
  const continuation = continuationLines.map((line, index) => line.text.slice(continuationPrefixes[index]?.length ?? 0));
193
199
  items.push({
194
200
  text: [firstText, ...continuation].join(lineEnding),
195
- contentStart: bodyStart + first.start + 2,
201
+ contentStart: bodyStart + first.start + marker.length,
196
202
  contentEnd: bodyStart + last.contentEnd,
197
203
  itemStart: bodyStart + first.start,
198
204
  itemEnd: bodyStart + (lines[nextLineIndex]?.start ?? markdownBody.length),
205
+ marker,
199
206
  continuationPrefixes
200
207
  });
201
208
  }
@@ -295,7 +302,7 @@ window.__ModuleLoader__.load({
295
302
  if (section.kind === "list") {
296
303
  const values = normalized.split(projection.lineEnding);
297
304
  if (!section.items || values.length !== section.items.length || section.items.some((item) => item.text.includes(projection.lineEnding))) throw new Error("Use Bridge list-item helpers for this section");
298
- markdownBody = section.listStyle === "plain" ? values.join(projection.lineEnding) : values.map((line) => `- ${line}`).join(projection.lineEnding);
305
+ markdownBody = section.listStyle === "plain" ? values.join(projection.lineEnding) : values.map((line, index) => `${section.items?.[index]?.marker ?? "- "}${line}`).join(projection.lineEnding);
299
306
  } else markdownBody = section.textStyle === "bullets" ? normalized.split(projection.lineEnding).map((line) => `- ${line}`).join(projection.lineEnding) : markdownSafePlainText(normalized, projection.lineEnding);
300
307
  return projection.markdown.slice(0, section.bodyStart) + markdownBody + projection.markdown.slice(section.bodyEnd);
301
308
  }
@@ -310,7 +317,7 @@ window.__ModuleLoader__.load({
310
317
  const lines = normalized.split(lineEnding);
311
318
  if (lines.some((line) => hasUnsafeBlock(line))) throw new Error("Bridge list item contains Markdown block structure");
312
319
  if (style === "plain" && lines.length > 1) throw new Error("Plain path rows must stay on one line");
313
- return style === "bullet" ? [lines[0], ...lines.slice(1).map((line, index) => `${original?.continuationPrefixes?.[index] ?? " "}${line}`)].join(lineEnding) : normalized;
320
+ return style !== "plain" ? [lines[0], ...lines.slice(1).map((line, index) => `${original?.continuationPrefixes?.[index] ?? " "}${line}`)].join(lineEnding) : normalized;
314
321
  }
315
322
  /** Replace one list item without rewriting siblings and while retaining wrapped-line indentation. */
316
323
  function replaceBridgeTextListItem(projection, key, index, plainText) {
@@ -329,12 +336,21 @@ window.__ModuleLoader__.load({
329
336
  const removeStart = index > 0 && index === items.length - 1 ? item.itemStart - projection.lineEnding.length : item.itemStart;
330
337
  return projection.markdown.slice(0, removeStart) + projection.markdown.slice(item.itemEnd);
331
338
  }
332
- /** Append one item using the section's existing bullet/plain convention. */
339
+ /** Append one item using the section's existing Markdown list convention. */
333
340
  function appendBridgeTextListItem(projection, key, plainText) {
334
341
  const section = listSection(projection, key);
335
342
  const edited = editedListItem(plainText, section.listStyle, projection.lineEnding);
336
343
  const prefix = section.bodyStart === section.bodyEnd ? "" : projection.lineEnding;
337
- const item = section.listStyle === "bullet" ? `- ${edited}` : edited;
344
+ let marker = "";
345
+ if (section.listStyle === "bullet") marker = "- ";
346
+ if (section.listStyle === "ordered") {
347
+ const previous = section.items?.at(-1)?.marker;
348
+ const match = /^(\d{1,9})([.)]) $/u.exec(previous ?? "");
349
+ const next = match ? Number(match[1]) + 1 : (section.items?.length ?? 0) + 1;
350
+ if (!Number.isSafeInteger(next) || next > 999999999) throw new Error("Bridge ordered list marker is out of range");
351
+ marker = `${String(next)}${match?.[2] ?? "."} `;
352
+ }
353
+ const item = `${marker}${edited}`;
338
354
  return projection.markdown.slice(0, section.bodyEnd) + prefix + item + projection.markdown.slice(section.bodyEnd);
339
355
  }
340
356
  function previewHeaderOf(line) {
package/lib/client.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"client.js","names":["useState","useMemo","MarkdownText","JsonTree","useId","useRef","Component"],"sources":["../src/client-contract.ts","../src/client.tsx"],"sourcesContent":["/** Pure wire-to-view helpers shared by the native WebUI card and Node tests. */\n\nexport const MAX_EDITED_SUMMARY_CHARS = 24_000\n\nexport type BridgeOutcome = { kind: 'success' | 'error'; text?: string } | null\n\nexport type BridgeCard =\n | { phase: 'running' }\n | {\n phase: 'preview'\n lang: 'zh' | 'en'\n sourcePreset: string\n targetPreset: string\n previewId?: string\n summary: string\n summaryFile?: string\n stats: string\n warnings: string[]\n }\n | {\n phase: 'migrated'\n lang: 'zh' | 'en'\n targetPreset: string\n title: string\n sessionId: string\n details: string[]\n warnings: string[]\n }\n | { phase: 'error'; text: string }\n | { phase: 'message'; text: string; lang: 'zh' | 'en' }\n\nexport type BridgeTextSectionKey =\n | 'goal'\n | 'currentState'\n | 'keyDecisions'\n | 'keyFiles'\n | 'nextStep'\n\nexport interface BridgeTextSection {\n key: BridgeTextSectionKey\n label: string\n kind: 'text' | 'list'\n /** Plain-text editor value. List markers are intentionally omitted. */\n text: string\n /** Exact source span replaced when this field is edited. */\n bodyStart: number\n bodyEnd: number\n items?: BridgeTextListItem[]\n listStyle?: 'bullet' | 'plain'\n textStyle?: 'plain' | 'bullets'\n}\n\nexport interface BridgeTextListItem {\n text: string\n contentStart: number\n contentEnd: number\n itemStart: number\n itemEnd: number\n /** Original indentation for wrapped lines, kept when that item is edited. */\n continuationPrefixes?: string[]\n}\n\nexport interface BridgeTextProjection {\n lang: 'zh' | 'en'\n /** The untouched Markdown document used to enter text mode. */\n markdown: string\n lineEnding: '\\n' | '\\r\\n'\n sections: BridgeTextSection[]\n /** Known appendices are visible but read-only in plain-text mode. */\n opaqueSuffix: string\n}\n\nconst RUN_COMMAND = /\\/bridge\\s+([^\\s]+)\\s+--go(?:\\s|$)/u\n\nconst TEXT_SCHEMAS = {\n zh: [\n ['goal', '目标', 'text'],\n ['currentState', '当前状态', 'text'],\n ['keyDecisions', '关键决策与约定', 'list'],\n ['keyFiles', '关键文件', 'list'],\n ['nextStep', '下一步', 'text'],\n ],\n en: [\n ['goal', 'Goal', 'text'],\n ['currentState', 'Current state', 'text'],\n ['keyDecisions', 'Key decisions & conventions', 'list'],\n ['keyFiles', 'Key files', 'list'],\n ['nextStep', 'Next step', 'text'],\n ],\n} as const satisfies Record<'zh' | 'en', readonly (readonly [BridgeTextSectionKey, string, 'text' | 'list'])[]>\n\nconst TEXT_APPENDICES = {\n zh: new Set(['视觉证据——原文搬运,未经二次摘要', '未解析图片']),\n en: new Set(['Visual evidence — verbatim, not summarized', 'Unresolved images']),\n} as const\n\ninterface SourceLine {\n start: number\n contentEnd: number\n end: number\n text: string\n}\n\ninterface MarkdownHeading {\n label: string\n start: number\n lineEnd: number\n}\n\nfunction sourceLines(markdown: string, lineEnding: '\\n' | '\\r\\n'): SourceLine[] {\n const lines: SourceLine[] = []\n let start = 0\n while (start <= markdown.length) {\n const next = markdown.indexOf(lineEnding, start)\n if (next < 0) {\n lines.push({ start, contentEnd: markdown.length, end: markdown.length, text: markdown.slice(start) })\n break\n }\n lines.push({ start, contentEnd: next, end: next + lineEnding.length, text: markdown.slice(start, next) })\n start = next + lineEnding.length\n if (start === markdown.length) {\n lines.push({ start, contentEnd: start, end: start, text: '' })\n break\n }\n }\n return lines\n}\n\nfunction markdownHeadings(markdown: string, lineEnding: '\\n' | '\\r\\n'): MarkdownHeading[] | undefined {\n const headings: MarkdownHeading[] = []\n let fence: { marker: '`' | '~'; length: number } | undefined\n for (const line of sourceLines(markdown, lineEnding)) {\n const fenceMatch = /^ {0,3}(`{3,}|~{3,})(.*)$/u.exec(line.text)\n if (fence) {\n if (fenceMatch && fenceMatch[1]?.[0] === fence.marker\n && (fenceMatch[1]?.length ?? 0) >= fence.length\n && (fenceMatch[2]?.trim() ?? '') === '') {\n fence = undefined\n }\n continue\n }\n if (fenceMatch) {\n const token = fenceMatch[1] ?? ''\n fence = { marker: token[0] as '`' | '~', length: token.length }\n continue\n }\n if (!line.text.startsWith('##')) continue\n const rest = line.text.slice(2)\n if (rest[0] !== ' ' && rest[0] !== '\\t') continue\n let labelStart = 0\n while (labelStart < rest.length && (rest[labelStart] === ' ' || rest[labelStart] === '\\t')) labelStart += 1\n let labelEnd = rest.length\n while (labelEnd > labelStart && (rest[labelEnd - 1] === ' ' || rest[labelEnd - 1] === '\\t')) labelEnd -= 1\n if (labelEnd > labelStart) headings.push({ label: rest.slice(labelStart, labelEnd), start: line.start, lineEnd: line.end })\n }\n return fence ? undefined : headings\n}\n\nfunction documentLineEnding(markdown: string): '\\n' | '\\r\\n' | undefined {\n const endings = markdown.match(/\\r\\n|\\n|\\r/gu)\n if (!endings?.length) return undefined\n const first = endings[0]\n if ((first !== '\\n' && first !== '\\r\\n') || endings.some((ending) => ending !== first)) return undefined\n return first\n}\n\nconst MARKDOWN_BLOCK_START = /^([\\t ]{0,3})(#{1,6}(?:[\\t ]|$)|>(?:[\\t ]|$)|[-+*](?:[\\t ]|$)|\\d+[.)](?:[\\t ]|$)|`{3}|~{3})/u\nconst THEMATIC_OR_SETEXT = /^ {0,3}(?:(?:\\*[\\t ]*){3,}|(?:-[\\t ]*){3,}|(?:_[\\t ]*){3,}|=+[\\t ]*)$/u\nconst TABLE_DELIMITER = /^ {0,3}\\|?[\\t ]*:?-{3,}:?[\\t ]*(?:\\|[\\t ]*:?-{3,}:?[\\t ]*)+\\|?[\\t ]*$/u\nconst LINK_DEFINITION = /^ {0,3}\\[[^\\]]+\\]:[\\t ]*\\S/u\nconst HTML_BLOCK_START = /^ {0,3}<[/!?A-Za-z]/u\n\nfunction hasUnsafeBlock(line: string): boolean {\n return MARKDOWN_BLOCK_START.test(line)\n || THEMATIC_OR_SETEXT.test(line)\n || TABLE_DELIMITER.test(line)\n || LINK_DEFINITION.test(line)\n || /^(?: {4}|\\t)/u.test(line)\n || line.includes('<!--')\n || line.includes('-->')\n || line.includes('--!>')\n || HTML_BLOCK_START.test(line)\n}\n\nfunction parseListItems(\n markdownBody: string,\n lineEnding: '\\n' | '\\r\\n',\n bodyStart: number,\n allowPlain: boolean,\n): { items: BridgeTextListItem[]; style: 'bullet' | 'plain'; text: string } | undefined {\n if (!markdownBody) return { items: [], style: 'bullet', text: '' }\n const lines = sourceLines(markdownBody, lineEnding)\n if (lines.some((line) => !line.text.trim())) return undefined\n const bullet = /^- (.+)$/u.exec(lines[0]?.text ?? '')\n const style = bullet ? 'bullet' : allowPlain ? 'plain' : undefined\n if (!style) return undefined\n\n const items: BridgeTextListItem[] = []\n if (style === 'plain') {\n for (const line of lines) {\n if (hasUnsafeBlock(line.text) || /^[\\t ]*(?:[-+*]|\\d+[.)])[\\t ]+/u.test(line.text)) return undefined\n items.push({\n text: line.text,\n contentStart: bodyStart + line.start,\n contentEnd: bodyStart + line.contentEnd,\n itemStart: bodyStart + line.start,\n itemEnd: bodyStart + line.end,\n })\n }\n } else {\n const starts: number[] = []\n for (const [index, line] of lines.entries()) {\n if (/^- (.+)$/u.test(line.text)) {\n starts.push(index)\n continue\n }\n if (!starts.length || hasUnsafeBlock(line.text) || /^[\\t ]+(?:[-+*]|\\d+[.)])[\\t ]+/u.test(line.text)\n || /^[+*][\\t ]+/u.test(line.text) || /^\\d+[.)][\\t ]+/u.test(line.text)) return undefined\n }\n for (const [itemIndex, lineIndex] of starts.entries()) {\n const first = lines[lineIndex] as SourceLine\n const nextLineIndex = starts[itemIndex + 1] ?? lines.length\n const last = lines[nextLineIndex - 1] as SourceLine\n const firstText = /^- (.+)$/u.exec(first.text)?.[1]\n if (!firstText) return undefined\n const continuationLines = lines.slice(lineIndex + 1, nextLineIndex)\n const continuationPrefixes = continuationLines.map((line) => /^[\\t ]*/u.exec(line.text)?.[0] ?? '')\n const continuation = continuationLines.map((line, index) => line.text.slice(continuationPrefixes[index]?.length ?? 0))\n items.push({\n text: [firstText, ...continuation].join(lineEnding),\n contentStart: bodyStart + first.start + 2,\n contentEnd: bodyStart + last.contentEnd,\n itemStart: bodyStart + first.start,\n itemEnd: bodyStart + (lines[nextLineIndex]?.start ?? markdownBody.length),\n continuationPrefixes,\n })\n }\n }\n return { items, style, text: items.map((item) => item.text).join(lineEnding) }\n}\n\nfunction plainBlockText(markdownBody: string, lineEnding: '\\n' | '\\r\\n'): string {\n return markdownBody\n .split(lineEnding)\n .map((line) => line.replace(/^([\\t ]{0,3})\\\\(?=[#>*+`~_<\\[|!=-])/u, '$1'))\n .join(lineEnding)\n}\n\nfunction isPlainBlock(markdownBody: string, lineEnding: '\\n' | '\\r\\n'): boolean {\n return sourceLines(markdownBody, lineEnding).every((line) => !hasUnsafeBlock(line.text))\n}\n\nfunction parseTextBlock(markdownBody: string, lineEnding: '\\n' | '\\r\\n'): { style: 'plain' | 'bullets', text: string } | undefined {\n const lines = sourceLines(markdownBody, lineEnding)\n if (lines.length && lines.every((line) => /^- (.+)$/u.test(line.text))) {\n return { style: 'bullets', text: lines.map((line) => /^- (.+)$/u.exec(line.text)?.[1] ?? '').join(lineEnding) }\n }\n return isPlainBlock(markdownBody, lineEnding)\n ? { style: 'plain', text: plainBlockText(markdownBody, lineEnding) }\n : undefined\n}\n\nfunction markdownSafePlainText(text: string, lineEnding: '\\n' | '\\r\\n'): string {\n return text\n .split(lineEnding)\n .map((line) => {\n if (/^(?: {4}|\\t)/u.test(line)) throw new Error('Plain-text lines cannot start with four spaces or a tab')\n if (!hasUnsafeBlock(line)) return line\n return line.replace(/^([\\t ]{0,3})(?=\\S)/u, '$1\\\\')\n })\n .join(lineEnding)\n}\n\n/**\n * Project only Bridge's exact bilingual five-section schema into plain fields.\n * Unknown structure fails closed; known visual appendices remain opaque Markdown.\n */\nexport function parseBridgeTextProjection(markdown: string): BridgeTextProjection | undefined {\n const lineEnding = documentLineEnding(markdown)\n if (!lineEnding) return undefined\n const headings = markdownHeadings(markdown, lineEnding)\n if (!headings?.length || headings[0]?.start !== 0) return undefined\n\n const lang = headings[0]?.label === TEXT_SCHEMAS.zh[0][1]\n ? 'zh'\n : headings[0]?.label === TEXT_SCHEMAS.en[0][1]\n ? 'en'\n : undefined\n if (!lang) return undefined\n\n const appendixIndex = headings.findIndex((heading) => TEXT_APPENDICES[lang].has(heading.label))\n const schemaHeadings = appendixIndex < 0 ? headings : headings.slice(0, appendixIndex)\n if (schemaHeadings.length !== TEXT_SCHEMAS[lang].length) return undefined\n if (schemaHeadings.some((heading, index) => heading.label !== TEXT_SCHEMAS[lang][index]?.[1])) return undefined\n\n const firstAppendix = appendixIndex < 0 ? undefined : headings[appendixIndex]\n const editableMarkdown = markdown.slice(0, firstAppendix?.start ?? markdown.length)\n if (editableMarkdown.includes('<!--') || editableMarkdown.includes('-->') || editableMarkdown.includes('--!>')) return undefined\n const sections: BridgeTextSection[] = []\n for (const [index, heading] of schemaHeadings.entries()) {\n const [key, label, kind] = TEXT_SCHEMAS[lang][index] as typeof TEXT_SCHEMAS[typeof lang][number]\n const bodyStart = heading.lineEnd\n const regionEnd = schemaHeadings[index + 1]?.start ?? firstAppendix?.start ?? markdown.length\n let bodyEnd = regionEnd\n while (bodyEnd - lineEnding.length >= bodyStart\n && markdown.slice(bodyEnd - lineEnding.length, bodyEnd) === lineEnding) {\n bodyEnd -= lineEnding.length\n }\n const body = markdown.slice(bodyStart, bodyEnd)\n const list = kind === 'list' ? parseListItems(body, lineEnding, bodyStart, key === 'keyFiles') : undefined\n const textBlock = kind === 'text' ? parseTextBlock(body, lineEnding) : undefined\n if (kind === 'list' && !list) return undefined\n if (kind === 'text' && !textBlock) return undefined\n const text = list?.text ?? textBlock?.text ?? ''\n sections.push({\n key,\n label,\n kind,\n text,\n bodyStart,\n bodyEnd,\n ...(list ? { items: list.items, listStyle: list.style } : {}),\n ...(textBlock ? { textStyle: textBlock.style } : {}),\n })\n }\n return {\n lang,\n markdown,\n lineEnding,\n sections,\n opaqueSuffix: firstAppendix ? markdown.slice(firstAppendix.start) : '',\n }\n}\n\nfunction normalizeLineEndings(text: string, lineEnding: '\\n' | '\\r\\n'): string {\n return text.replace(/\\r\\n|\\n|\\r/gu, lineEnding)\n}\n\n/** Replace one editable body while preserving every byte outside that section. */\nexport function replaceBridgeTextSection(\n projection: BridgeTextProjection,\n key: BridgeTextSectionKey,\n plainText: string,\n): string {\n const section = projection.sections.find((candidate) => candidate.key === key)\n if (!section) throw new Error(`Unknown Bridge text section: ${key}`)\n if (plainText === section.text) return projection.markdown\n const normalized = normalizeLineEndings(plainText, projection.lineEnding)\n let markdownBody: string\n if (section.kind === 'list') {\n const values = normalized.split(projection.lineEnding)\n if (!section.items || values.length !== section.items.length || section.items.some((item) => item.text.includes(projection.lineEnding))) {\n throw new Error('Use Bridge list-item helpers for this section')\n }\n markdownBody = section.listStyle === 'plain'\n ? values.join(projection.lineEnding)\n : values.map((line) => `- ${line}`).join(projection.lineEnding)\n } else {\n markdownBody = section.textStyle === 'bullets'\n ? normalized.split(projection.lineEnding).map((line) => `- ${line}`).join(projection.lineEnding)\n : markdownSafePlainText(normalized, projection.lineEnding)\n }\n return projection.markdown.slice(0, section.bodyStart)\n + markdownBody\n + projection.markdown.slice(section.bodyEnd)\n}\n\nfunction listSection(projection: BridgeTextProjection, key: BridgeTextSectionKey): BridgeTextSection {\n const section = projection.sections.find((candidate) => candidate.key === key)\n if (!section || section.kind !== 'list' || !section.items || !section.listStyle) {\n throw new Error(`Unknown Bridge list section: ${key}`)\n }\n return section\n}\n\nfunction editedListItem(\n text: string,\n style: 'bullet' | 'plain',\n lineEnding: '\\n' | '\\r\\n',\n original?: BridgeTextListItem,\n): string {\n const normalized = normalizeLineEndings(text, lineEnding)\n if (!normalized.trim()) throw new Error('Bridge list item is empty')\n const lines = normalized.split(lineEnding)\n if (lines.some((line) => hasUnsafeBlock(line))) throw new Error('Bridge list item contains Markdown block structure')\n if (style === 'plain' && lines.length > 1) throw new Error('Plain path rows must stay on one line')\n return style === 'bullet'\n ? [\n lines[0],\n ...lines.slice(1).map((line, index) => `${original?.continuationPrefixes?.[index] ?? ' '}${line}`),\n ].join(lineEnding)\n : normalized\n}\n\n/** Replace one list item without rewriting siblings and while retaining wrapped-line indentation. */\nexport function replaceBridgeTextListItem(\n projection: BridgeTextProjection,\n key: BridgeTextSectionKey,\n index: number,\n plainText: string,\n): string {\n const section = listSection(projection, key)\n const item = section.items?.[index]\n if (!item) throw new Error(`Unknown Bridge list item: ${key}[${index}]`)\n if (plainText === item.text) return projection.markdown\n const edited = editedListItem(plainText, section.listStyle as 'bullet' | 'plain', projection.lineEnding, item)\n return projection.markdown.slice(0, item.contentStart) + edited + projection.markdown.slice(item.contentEnd)\n}\n\n/** Remove exactly one original list-item span. */\nexport function removeBridgeTextListItem(\n projection: BridgeTextProjection,\n key: BridgeTextSectionKey,\n index: number,\n): string {\n const section = listSection(projection, key)\n const items = section.items ?? []\n const item = items[index]\n if (!item) throw new Error(`Unknown Bridge list item: ${key}[${index}]`)\n const removeStart = index > 0 && index === items.length - 1\n ? item.itemStart - projection.lineEnding.length\n : item.itemStart\n return projection.markdown.slice(0, removeStart) + projection.markdown.slice(item.itemEnd)\n}\n\n/** Append one item using the section's existing bullet/plain convention. */\nexport function appendBridgeTextListItem(\n projection: BridgeTextProjection,\n key: BridgeTextSectionKey,\n plainText: string,\n): string {\n const section = listSection(projection, key)\n const edited = editedListItem(plainText, section.listStyle as 'bullet' | 'plain', projection.lineEnding)\n const prefix = section.bodyStart === section.bodyEnd ? '' : projection.lineEnding\n const item = section.listStyle === 'bullet' ? `- ${edited}` : edited\n return projection.markdown.slice(0, section.bodyEnd) + prefix + item + projection.markdown.slice(section.bodyEnd)\n}\n\ninterface PreviewHeader {\n lang: 'zh' | 'en'\n sourcePreset: string\n targetPreset: string\n}\n\nfunction previewHeaderOf(line: string): PreviewHeader | undefined {\n const prefix = line.startsWith('─── Handoff · ')\n ? { text: '─── Handoff · ', lang: 'en' as const }\n : line.startsWith('─── 交接摘要 · ')\n ? { text: '─── 交接摘要 · ', lang: 'zh' as const }\n : undefined\n if (!prefix) return undefined\n const route = line.slice(prefix.text.length)\n const arrow = route.indexOf('→')\n if (arrow < 1) return undefined\n const sourcePreset = route.slice(0, arrow).trim()\n const targetTail = route.slice(arrow + 1).trimStart()\n let targetEnd = 0\n while (targetEnd < targetTail.length) {\n const char = targetTail[targetEnd]\n if (char === undefined || /\\s/u.test(char) || char === '(' || char === '(' || char === '─') break\n targetEnd += 1\n }\n const targetPreset = targetTail.slice(0, targetEnd)\n if (!sourcePreset || !targetPreset) return undefined\n return { lang: prefix.lang, sourcePreset, targetPreset }\n}\n\nfunction isDivider(line: string): boolean {\n const trimmed = line.trim()\n return trimmed.length >= 10 && [...trimmed].every((char) => char === '─')\n}\n\nfunction languageOf(text: string): 'zh' | 'en' {\n return /[\\u3400-\\u9fff]/u.test(text) ? 'zh' : 'en'\n}\n\n/** Map the official WebUI document language onto Bridge's supported UI copy. */\nexport function uiLanguageOf(documentLang: string | undefined): 'zh' | 'en' {\n return documentLang?.toLowerCase().startsWith('zh') === true ? 'zh' : 'en'\n}\n\nfunction parsePreview(text: string): BridgeCard | undefined {\n const lines = text.split('\\n')\n const header = previewHeaderOf(lines[0] ?? '')\n if (!header) return undefined\n const divider = lines.findIndex((line, index) => index > 0 && isDivider(line))\n if (divider < 2) return undefined\n const command = RUN_COMMAND.exec(text)\n const targetPreset = command?.[1] ?? header.targetPreset\n if (!targetPreset) return undefined\n\n const tail = lines.slice(divider + 1)\n const stats = tail.find((line) => line.trim() !== '' && !line.startsWith('⚠') && !RUN_COMMAND.test(line)) ?? ''\n const warnings = tail\n .filter((line) => line.startsWith('⚠'))\n .map((line) => line.replace(/^⚠\\s*/u, ''))\n const previewIdLine = tail.find((line) => line.startsWith('Preview ID:') || line.startsWith('预览 ID:'))\n const previewId = previewIdLine?.slice(previewIdLine.indexOf(previewIdLine.startsWith('Preview') ? ':' : ':') + 1).trim()\n const fileLine = tail.find((line) => line.includes(' --file '))\n const fileMarker = fileLine?.lastIndexOf(' --file ') ?? -1\n const summaryFile = fileMarker < 0 ? undefined : fileLine?.slice(fileMarker + ' --file '.length).trim().split(/\\s/u)[0]\n return {\n phase: 'preview',\n lang: header.lang,\n sourcePreset: header.sourcePreset,\n targetPreset,\n ...(previewId ? { previewId } : {}),\n summary: lines.slice(1, divider).join('\\n').trim(),\n ...(summaryFile ? { summaryFile } : {}),\n stats,\n warnings,\n }\n}\n\nfunction parseMigrated(text: string): BridgeCard | undefined {\n const lines = text.split('\\n').map((line) => line.trim()).filter(Boolean)\n const first = lines[0] ?? ''\n const lang: 'zh' | 'en' = first.startsWith('Created a new session') ? 'en' : 'zh'\n const presetPrefix = lang === 'en' ? 'Created a new session in the ' : '已在 '\n const presetSuffix = lang === 'en' ? ' preset' : ' 模式下建好新会话'\n const presetEnd = first.indexOf(presetSuffix, presetPrefix.length)\n const preset = presetEnd < 0 ? undefined : first.slice(presetPrefix.length, presetEnd).trim()\n if (!preset) return undefined\n const targetIndex = lines.findIndex((line) => line.startsWith('Target session:') || line.startsWith('目标会话:'))\n if (targetIndex < 0) return undefined\n const targetLine = lines[targetIndex] ?? ''\n const targetPrefix = targetLine.startsWith('Target session:') ? 'Target session:' : '目标会话:'\n const targetPayload = targetLine.slice(targetPrefix.length).trim()\n const targetSeparator = targetPayload.lastIndexOf(' · ')\n if (targetSeparator < 1) return undefined\n const title = targetPayload.slice(0, targetSeparator).trim()\n const sessionId = targetPayload.slice(targetSeparator + 3).trim()\n if (!title || !sessionId || /\\s/u.test(sessionId)) return undefined\n const remaining = lines.filter((_, index) => index !== 0 && index !== targetIndex)\n return {\n phase: 'migrated',\n lang,\n targetPreset: preset,\n title,\n sessionId,\n details: remaining.filter((line) => !line.startsWith('⚠')),\n warnings: remaining.filter((line) => line.startsWith('⚠')).map((line) => line.replace(/^⚠\\s*/u, '')),\n }\n}\n\n/** Convert one durable `/bridge` outcome into the native card's view model. */\nexport function parseBridgeCard(outcome: BridgeOutcome): BridgeCard {\n if (outcome === null) return { phase: 'running' }\n const text = outcome.text?.trim() ?? ''\n if (outcome.kind === 'error') return { phase: 'error', text }\n return parsePreview(text)\n ?? parseMigrated(text)\n ?? { phase: 'message', text, lang: languageOf(text) }\n}\n\n/** Return a value only when the complete editor document is valid JSON. */\nexport function parseJsonDocument(text: string): object | unknown[] | undefined {\n const trimmed = text.trim()\n if (!trimmed.startsWith('{') && !trimmed.startsWith('[')) return undefined\n try {\n const parsed = JSON.parse(trimmed) as unknown\n return typeof parsed === 'object' && parsed !== null ? parsed : undefined\n } catch {\n return undefined\n }\n}\n\nfunction encodeUtf8Base64Url(text: string): string {\n const bytes = new TextEncoder().encode(text)\n let binary = ''\n for (const byte of bytes) binary += String.fromCharCode(byte)\n return btoa(binary).replaceAll('+', '-').replaceAll('/', '_').replace(/=+$/u, '')\n}\n\n/** Build the hidden-input-safe command used by the native editor confirmation. */\nexport function buildBridgeMigrationCommand(targetPreset: string, summary: string, lang: 'zh' | 'en', previewId: string): string {\n if (!/^[A-Za-z0-9._-]+$/u.test(targetPreset)) throw new Error('Unsupported target preset id')\n if (lang !== 'zh' && lang !== 'en') throw new Error('Unsupported Bridge language')\n if (!/^[A-Za-z0-9-]{8,}$/u.test(previewId)) throw new Error('Unsupported Bridge preview ID')\n if (!summary.trim()) throw new Error('The handoff summary is empty')\n if (summary.length > MAX_EDITED_SUMMARY_CHARS) {\n throw new Error(`The handoff summary exceeds ${MAX_EDITED_SUMMARY_CHARS} characters`)\n }\n return `/bridge ${targetPreset} --go --lang ${lang} --preview-id ${previewId} --summary64 ${encodeUtf8Base64Url(summary)}`\n}\n","/** Official WebUI half: one native `/bridge` command card, not a second WebUI. */\n\nimport { Component, useEffect, useId, useMemo, useRef, useState, type ErrorInfo, type ReactNode } from 'react'\nimport type { Context as ClientContext } from '@deepseek-ai/cordis'\nimport type { SessionId } from '@deepseek-ai/dsh-api-remotes/client'\nimport { JsonTree, MarkdownText } from '@deepseek-ai/dsh-client-ui-primitives'\nimport type { JsonTreeLabels, MarkdownLabels } from '@deepseek-ai/dsh-client-ui-primitives'\nimport type {} from '@deepseek-ai/dsh-api-session-controller/client'\nimport type { CommandRowProps } from '@deepseek-ai/dsh-client-ui-chat/client'\nimport type {} from '@deepseek-ai/dsh-client-ui-conversation/client'\nimport type {} from '@deepseek-ai/dsh-client-ui-renderer/client'\nimport type {} from '@deepseek-ai/dsh-client-ui-session/client'\n\nimport {\n appendBridgeTextListItem,\n buildBridgeMigrationCommand,\n MAX_EDITED_SUMMARY_CHARS,\n parseBridgeCard,\n parseBridgeTextProjection,\n parseJsonDocument,\n removeBridgeTextListItem,\n replaceBridgeTextListItem,\n replaceBridgeTextSection,\n uiLanguageOf,\n type BridgeCard,\n type BridgeOutcome,\n type BridgeTextProjection,\n type BridgeTextSection,\n} from './client-contract.ts'\n\nconst STYLE_ID = 'dsh-plugin-bridge/native-card'\nconst STYLE = `\n.dsh-bridge-card{border:1px solid var(--dsw-alias-border-subtle,light-dark(#dedede,#3f3f46));border-radius:12px;background:var(--dsw-alias-background-primary,light-dark(#fff,#18181b));color:var(--dsw-alias-label-primary,light-dark(#171717,#f4f4f5));overflow:hidden;box-shadow:0 1px 2px rgba(0,0,0,.12)}\n.dsh-bridge-head{display:flex;align-items:center;gap:10px;min-height:44px;padding:0 14px;border-bottom:1px solid var(--dsw-alias-border-subtle,light-dark(#e6e6e6,#3f3f46));background:var(--dsw-alias-background-secondary,light-dark(#fafafa,#202024))}\n.dsh-bridge-mark{display:grid;place-items:center;width:22px;height:22px;border-radius:7px;background:var(--dsw-alias-state-business-secondary,light-dark(#e8f1ff,#22325c));color:var(--dsw-alias-state-business-primary,light-dark(#2869d8,#8eaeff));font:700 12px/1 ui-monospace,SFMono-Regular,Menlo,monospace}\n.dsh-bridge-title{min-width:0;flex:1;font-size:13px;font-weight:650;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.dsh-bridge-route{font:500 11px/1.2 ui-monospace,SFMono-Regular,Menlo,monospace;color:var(--dsw-alias-label-secondary,light-dark(#666,#a1a1aa))}\n.dsh-bridge-body{padding:14px}.dsh-bridge-copy{font-size:13px;line-height:1.55;color:var(--dsw-alias-label-secondary,light-dark(#5f6368,#b4b4bd))}\n.dsh-bridge-toolbar{display:flex;align-items:center;gap:10px;margin-bottom:10px;flex-wrap:wrap}.dsh-bridge-tabs{display:inline-flex;flex-shrink:0;padding:2px;border-radius:8px;background:var(--dsw-alias-background-tertiary,light-dark(#f1f2f4,#29292e))}\n.dsh-bridge-button,.dsh-bridge-tab{border:0;border-radius:7px;font:600 12px/1 -apple-system,BlinkMacSystemFont,\"Segoe UI\",sans-serif;cursor:pointer;transition:background-color .15s ease,color .15s ease,transform .1s ease}\n.dsh-bridge-tab{padding:7px 10px;background:transparent;color:var(--dsw-alias-label-secondary,light-dark(#666,#a1a1aa))}.dsh-bridge-tab[aria-selected=true]{background:var(--dsw-alias-background-primary,light-dark(#fff,#3a3a40));color:var(--dsw-alias-label-primary,light-dark(#171717,#f4f4f5));box-shadow:0 1px 2px rgba(0,0,0,.18)}\n.dsh-bridge-button{padding:8px 11px;background:var(--dsw-alias-background-tertiary,light-dark(#f1f2f4,#303036));color:var(--dsw-alias-label-primary,light-dark(#171717,#f4f4f5))}.dsh-bridge-button[data-primary=true]{background:var(--dsw-alias-state-business-primary,light-dark(#2869d8,#4f7ee8));color:#fff}.dsh-bridge-button:disabled{cursor:not-allowed;opacity:.55}.dsh-bridge-button:not(:disabled):active{transform:translateY(1px)}\n.dsh-bridge-actions{display:flex;gap:8px;flex-wrap:wrap;margin-left:auto}.dsh-bridge-panel{box-sizing:border-box;max-height:min(56vh,520px);overflow:auto;overscroll-behavior:contain;scrollbar-gutter:stable;padding:14px;border:1px solid var(--dsw-alias-border-subtle,light-dark(#e3e5e8,#3f3f46));border-radius:9px;background:var(--dsw-alias-background-primary,light-dark(#fff,#18181b))}\n.dsh-bridge-preview{min-width:0}.dsh-bridge-markdown-editor,.dsh-bridge-text-editor,.dsh-bridge-list-input{box-sizing:border-box;width:100%;border:1px solid var(--dsw-alias-border-strong,light-dark(#c8ccd2,#52525b));border-radius:8px;outline:none;background:var(--dsw-alias-background-primary,light-dark(#fff,#202024));color:var(--dsw-alias-label-primary,light-dark(#171717,#f4f4f5))}\n.dsh-bridge-markdown-editor{min-height:360px;resize:vertical;padding:13px 14px;font:12px/1.65 ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;tab-size:2}.dsh-bridge-text-editor{min-height:92px;resize:vertical;padding:10px 11px;font:13px/1.55 -apple-system,BlinkMacSystemFont,\"Segoe UI\",sans-serif}.dsh-bridge-list-input{min-width:0;min-height:34px;resize:vertical;padding:9px 10px;font:13px/1.4 -apple-system,BlinkMacSystemFont,\"Segoe UI\",sans-serif}\n.dsh-bridge-markdown-editor:focus,.dsh-bridge-text-editor:focus,.dsh-bridge-list-input:focus{border-color:var(--dsw-alias-state-business-primary,#2869d8);box-shadow:0 0 0 3px color-mix(in srgb,var(--dsw-alias-state-business-primary,#2869d8) 18%,transparent)}\n.dsh-bridge-form{display:grid;gap:14px}.dsh-bridge-field{display:grid;gap:7px}.dsh-bridge-field-head{display:flex;align-items:center;justify-content:space-between;gap:8px}.dsh-bridge-field-label{font-size:12px;font-weight:700;color:var(--dsw-alias-label-primary,light-dark(#171717,#f4f4f5))}.dsh-bridge-field-help{font-size:11px;color:var(--dsw-alias-label-tertiary,light-dark(#85898f,#a1a1aa))}\n.dsh-bridge-list{display:grid;gap:7px}.dsh-bridge-list-row{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:7px;align-items:center}.dsh-bridge-list-button{align-self:center;padding:8px 9px}.dsh-bridge-add-button{justify-self:start}.dsh-bridge-appendix{display:grid;gap:7px;padding-top:12px;border-top:1px solid var(--dsw-alias-border-subtle,light-dark(#e3e5e8,#3f3f46))}.dsh-bridge-appendix-copy{font-size:11px;color:var(--dsw-alias-label-tertiary,light-dark(#85898f,#a1a1aa))}\n.dsh-bridge-notice{padding:12px;border-radius:8px;background:var(--dsw-alias-background-secondary,light-dark(#f7f8fa,#29292e));font-size:12px;line-height:1.55;color:var(--dsw-alias-label-secondary,light-dark(#5f6368,#b4b4bd))}.dsh-bridge-notice-actions{display:flex;gap:8px;flex-wrap:wrap;margin-top:10px}.dsh-bridge-draft-notice{display:flex;align-items:center;justify-content:space-between;gap:10px;margin-bottom:10px;padding:9px 10px;border-radius:8px;background:var(--dsw-alias-state-warn-secondary,light-dark(#fff5d8,#443814));color:var(--dsw-alias-state-warn-primary,light-dark(#785a00,#f3d36b));font-size:12px}.dsh-bridge-draft-notice .dsh-bridge-actions{margin-left:0}\n.dsh-bridge-meta{display:flex;gap:8px;flex-wrap:wrap;margin-top:10px;color:var(--dsw-alias-label-tertiary,light-dark(#85898f,#a1a1aa));font-size:11px}.dsh-bridge-chip{padding:4px 7px;border-radius:999px;background:var(--dsw-alias-background-tertiary,light-dark(#f2f3f5,#29292e))}\n.dsh-bridge-warning,.dsh-bridge-error{margin-top:10px;padding:9px 10px;border-radius:8px;font-size:12px;line-height:1.45}.dsh-bridge-warning{background:var(--dsw-alias-state-warn-secondary,light-dark(#fff5d8,#443814));color:var(--dsw-alias-state-warn-primary,light-dark(#785a00,#f3d36b))}.dsh-bridge-error{background:var(--dsw-alias-state-error-secondary,light-dark(#ffe9e7,#4a2325));color:var(--dsw-alias-state-error-primary,light-dark(#b3261e,#ffaaa4));white-space:pre-wrap}\n.dsh-bridge-progress{height:3px;margin-top:12px;border-radius:999px;overflow:hidden;background:var(--dsw-alias-background-tertiary,light-dark(#eceef1,#303036))}.dsh-bridge-progress::after{content:\"\";display:block;width:42%;height:100%;border-radius:inherit;background:var(--dsw-alias-state-business-primary,light-dark(#2869d8,#6d92ff));animation:dsh-bridge-scan 1.35s ease-in-out infinite}\n.dsh-bridge-success{display:grid;gap:10px}.dsh-bridge-session{padding:10px;border-radius:8px;background:var(--dsw-alias-state-success-secondary,light-dark(#e8f7ed,#183a26));font:12px/1.45 ui-monospace,SFMono-Regular,Menlo,monospace;overflow-wrap:anywhere}.dsh-bridge-status{min-height:18px;font-size:11px;color:var(--dsw-alias-label-tertiary,light-dark(#85898f,#a1a1aa))}\n.dsh-bridge-button:focus-visible,.dsh-bridge-tab:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary,#2869d8);outline-offset:2px}@keyframes dsh-bridge-scan{0%{transform:translateX(-110%)}100%{transform:translateX(340%)}}\n@media(max-width:640px){.dsh-bridge-head{align-items:flex-start;flex-wrap:wrap;padding-block:10px}.dsh-bridge-route{width:100%;padding-left:32px}.dsh-bridge-toolbar{align-items:stretch;flex-direction:column}.dsh-bridge-tabs{align-self:flex-start;max-width:100%;overflow-x:auto}.dsh-bridge-panel{max-height:52vh;padding:11px}.dsh-bridge-actions{width:100%;margin-left:0}.dsh-bridge-toolbar>.dsh-bridge-actions .dsh-bridge-button{flex:1}.dsh-bridge-draft-notice{align-items:flex-start;flex-direction:column}.dsh-bridge-list-row{grid-template-columns:minmax(0,1fr)}}\n@media(prefers-reduced-motion:reduce){.dsh-bridge-progress::after{animation:none;width:65%}.dsh-bridge-button,.dsh-bridge-tab{transition:none}}\n`\n\ninterface BridgeInjected {\n readonly execute: (sessionId: SessionId, line: string) => Promise<BridgeOutcome>\n readonly openSession: (sessionId: SessionId) => Promise<void>\n}\n\ninterface CommandRemote {\n execute(sessionId: SessionId, line: string, images: readonly unknown[]): Promise<{\n ok: boolean\n value?: { result: BridgeOutcome }\n error?: { code: string; message: string }\n }>\n}\n\ntype BridgeCommandCardProps = CommandRowProps & BridgeInjected\n\nconst COPY = {\n zh: {\n title: '会话迁移', preparing: '正在生成可编辑的交接摘要', safe: '原会话不会被修改',\n preview: '预览', text: '文本编辑', markdownSource: 'Markdown', copy: '复制摘要', copied: '已复制', confirm: '确认迁移',\n confirming: '正在创建目标会话…', open: '打开目标会话', opening: '正在打开目标会话…',\n json: 'JSON 结构', markdownPreview: 'Markdown 预览', markdownEditor: '交接摘要 Markdown 编辑器', chars: '字符',\n listHelp: '每行一项,无需输入 Markdown 符号', addItem: '添加一项', removeItem: '删除此项',\n appendix: '附录(只读)', appendixHelp: '视觉证据与未解析图片会原样保留;需要修改请切换到 Markdown。',\n textUnavailable: '这份摘要不是可无损转换的标准五段格式。内容没有被修改,请使用 Markdown 编辑。',\n editMarkdown: '使用 Markdown', newPreview: '检测到新的预览;当前编辑稿不会被自动覆盖。',\n keepDraft: '保留编辑稿', loadPreview: '加载新预览', renderFailure: 'Bridge 卡片渲染失败;其他插件和会话不受影响。',\n tooLong: `摘要超过 WebUI 的 ${MAX_EDITED_SUMMARY_CHARS.toLocaleString()} 字符安全上限,请使用摘要文件回退。`,\n fileFallback: '摘要文件', stalePreview: '这张旧预览没有安全确认标识。请重新运行 /bridge 生成预览,或使用摘要文件流程。',\n },\n en: {\n title: 'Session handoff', preparing: 'Generating an editable handoff preview', safe: 'The source session stays untouched',\n preview: 'Preview', text: 'Text', markdownSource: 'Markdown', copy: 'Copy summary', copied: 'Copied', confirm: 'Confirm migration',\n confirming: 'Creating the target session…', open: 'Open target session', opening: 'Opening target session…',\n json: 'JSON structure', markdownPreview: 'Markdown preview', markdownEditor: 'Handoff summary Markdown editor', chars: 'chars',\n listHelp: 'One item per line; no Markdown markers needed', addItem: 'Add item', removeItem: 'Remove item',\n appendix: 'Appendix (read only)', appendixHelp: 'Visual evidence and unresolved images stay exact; use Markdown to edit them.',\n textUnavailable: 'This handoff is not a losslessly editable five-section document. Nothing changed; use Markdown instead.',\n editMarkdown: 'Use Markdown', newPreview: 'A newer preview arrived. Your draft was not overwritten.',\n keepDraft: 'Keep draft', loadPreview: 'Load new preview', renderFailure: 'The Bridge card failed to render. Other plugins and sessions are unaffected.',\n tooLong: `The handoff exceeds the ${MAX_EDITED_SUMMARY_CHARS.toLocaleString()}-character WebUI safety limit. Use the summary-file fallback.`,\n fileFallback: 'Summary file', stalePreview: 'This older preview has no secure confirmation ID. Run /bridge again or use the summary-file workflow.',\n },\n} as const\n\nconst PRIMITIVE_LABELS = {\n zh: {\n markdown: {\n code: { copyLabel: '复制', copiedLabel: '已复制' },\n footnotes: '脚注',\n },\n json: {\n copyValue: '复制值', copyJson: '复制 JSON', copyPath: '复制属性路径',\n copyPrettyJson: '复制格式化 JSON', copyCompactJson: '复制紧凑 JSON',\n copied: '已复制', copyFailed: '复制失败',\n collapseNode: '折叠 JSON 节点', expandNode: '展开 JSON 节点',\n copyButtonTitle: (action: string) => `${action};右键查看更多复制选项`,\n },\n },\n en: {\n markdown: {\n code: { copyLabel: 'Copy', copiedLabel: 'Copied' },\n footnotes: 'Footnotes',\n },\n json: {\n copyValue: 'Copy value', copyJson: 'Copy JSON', copyPath: 'Copy property path',\n copyPrettyJson: 'Copy pretty JSON', copyCompactJson: 'Copy compact JSON',\n copied: 'Copied', copyFailed: 'Copy failed',\n collapseNode: 'Collapse JSON node', expandNode: 'Expand JSON node',\n copyButtonTitle: (action: string) => `${action}; right-click for copy options`,\n },\n },\n} satisfies Record<'zh' | 'en', { markdown: MarkdownLabels; json: JsonTreeLabels }>\n\nfunction Header({ lang, route }: { lang: 'zh' | 'en'; route?: string }) {\n return <div className=\"dsh-bridge-head\">\n <span className=\"dsh-bridge-mark\" aria-hidden>B</span>\n <span className=\"dsh-bridge-title\">{COPY[lang].title}</span>\n {route ? <span className=\"dsh-bridge-route\">{route}</span> : null}\n </div>\n}\n\nfunction RunningCard() {\n const lang = uiLanguageOf(typeof document === 'undefined' ? undefined : document.documentElement.lang)\n const copy = COPY[lang]\n const [seconds, setSeconds] = useState(0)\n useEffect(() => {\n const started = Date.now()\n const timer = window.setInterval(() => { setSeconds(Math.floor((Date.now() - started) / 1000)) }, 1000)\n return () => { window.clearInterval(timer) }\n }, [])\n return <div className=\"dsh-bridge-card\" aria-live=\"polite\">\n <Header lang={lang} />\n <div className=\"dsh-bridge-body\">\n <div className=\"dsh-bridge-copy\">{copy.preparing} · {seconds}s</div>\n <div className=\"dsh-bridge-status\">{copy.safe}</div>\n <div className=\"dsh-bridge-progress\" aria-hidden />\n </div>\n </div>\n}\n\nfunction SummaryView({ summary, lang }: { summary: string; lang: 'zh' | 'en' }) {\n const json = useMemo(() => parseJsonDocument(summary), [summary])\n return <div className=\"dsh-bridge-preview\" aria-label={json === undefined ? COPY[lang].markdownPreview : COPY[lang].json}>\n {json === undefined\n ? <MarkdownText text={summary} labels={PRIMITIVE_LABELS[lang].markdown} />\n : <JsonTree data={json} label={COPY[lang].json} labels={PRIMITIVE_LABELS[lang].json} />}\n </div>\n}\n\nfunction TextListEditor({ lang, onAppend, onChange, onRemove, section }: {\n lang: 'zh' | 'en'\n onAppend: (value: string) => boolean\n onChange: (index: number, value: string) => void\n onRemove: (index: number) => void\n section: BridgeTextSection\n}) {\n const copy = COPY[lang]\n const items = section.items ?? []\n const [draftRows, setDraftRows] = useState<string[]>([])\n const [itemDrafts, setItemDrafts] = useState<Record<number, string>>({})\n const removeDraft = (index: number) => { setDraftRows((current) => current.filter((_, itemIndex) => itemIndex !== index)) }\n return <div className=\"dsh-bridge-list\">\n {items.map((item, index) => <div className=\"dsh-bridge-list-row\" key={`${section.key}-${item.itemStart}`}>\n <textarea\n aria-label={`${section.label} ${index + 1}`}\n className=\"dsh-bridge-list-input\"\n maxLength={MAX_EDITED_SUMMARY_CHARS}\n rows={Math.min(4, item.text.split(/\\r\\n|\\n|\\r/gu).length)}\n value={itemDrafts[index] ?? item.text}\n onChange={(event) => {\n const value = event.currentTarget.value\n setItemDrafts((current) => ({ ...current, [index]: value }))\n if (value) onChange(index, value)\n }}\n onBlur={() => {\n if (itemDrafts[index] === '') onRemove(index)\n setItemDrafts((current) => {\n const next = { ...current }\n delete next[index]\n return next\n })\n }}\n spellCheck\n />\n <button\n aria-label={`${copy.removeItem}: ${section.label} ${index + 1}`}\n className=\"dsh-bridge-button dsh-bridge-list-button\"\n type=\"button\"\n onPointerDown={(event) => { event.preventDefault() }}\n onClick={() => {\n onRemove(index)\n }}\n >−</button>\n </div>)}\n {draftRows.map((item, index) => <div className=\"dsh-bridge-list-row\" key={`${section.key}-draft-${index}`}>\n <textarea\n aria-label={`${section.label} ${items.length + index + 1}`}\n autoFocus={index === draftRows.length - 1}\n className=\"dsh-bridge-list-input\"\n maxLength={MAX_EDITED_SUMMARY_CHARS}\n rows={1}\n value={item}\n onChange={(event) => {\n const value = event.currentTarget.value\n setDraftRows((current) => current.map((row, rowIndex) => rowIndex === index ? value : row))\n }}\n onBlur={() => {\n if (!item.trim() || onAppend(item)) removeDraft(index)\n }}\n spellCheck\n />\n <button\n aria-label={`${copy.removeItem}: ${section.label} ${items.length + index + 1}`}\n className=\"dsh-bridge-button dsh-bridge-list-button\"\n type=\"button\"\n onPointerDown={(event) => { event.preventDefault() }}\n onClick={() => { removeDraft(index) }}\n >−</button>\n </div>)}\n <button\n className=\"dsh-bridge-button dsh-bridge-add-button\"\n type=\"button\"\n onClick={() => { setDraftRows((current) => [...current, '']) }}\n aria-label={`${copy.addItem}: ${section.label}`}\n >+ {copy.addItem}</button>\n </div>\n}\n\nfunction TextHandoffEditor({ idPrefix, lang, onChange, onError, projection }: {\n idPrefix: string\n lang: 'zh' | 'en'\n onChange: (summary: string) => boolean\n onError: (message: string) => void\n projection: BridgeTextProjection\n}) {\n const copy = COPY[lang]\n const safelyApply = (operation: () => string): boolean => {\n try {\n onError('')\n return onChange(operation())\n } catch (cause) {\n onError(cause instanceof Error ? cause.message : String(cause))\n return false\n }\n }\n const updateSection = (section: BridgeTextSection, value: string) => {\n safelyApply(() => replaceBridgeTextSection(projection, section.key, value))\n }\n return <div className=\"dsh-bridge-form\">\n {projection.sections.map((section) => <div\n aria-labelledby={section.kind === 'list' ? `${idPrefix}-${section.key}-label` : undefined}\n className=\"dsh-bridge-field\"\n key={section.key}\n role={section.kind === 'list' ? 'group' : undefined}\n >\n <div className=\"dsh-bridge-field-head\">\n {section.kind === 'text'\n ? <label className=\"dsh-bridge-field-label\" htmlFor={`${idPrefix}-${section.key}`}>{section.label}</label>\n : <div className=\"dsh-bridge-field-label\" id={`${idPrefix}-${section.key}-label`}>{section.label}</div>}\n {section.kind === 'list' ? <span className=\"dsh-bridge-field-help\">{copy.listHelp}</span> : null}\n </div>\n {section.kind === 'text'\n ? <textarea\n className=\"dsh-bridge-text-editor\"\n id={`${idPrefix}-${section.key}`}\n maxLength={MAX_EDITED_SUMMARY_CHARS}\n value={section.text}\n onChange={(event) => { updateSection(section, event.currentTarget.value) }}\n spellCheck\n />\n : <TextListEditor\n lang={lang}\n section={section}\n onAppend={(value) => safelyApply(() => appendBridgeTextListItem(projection, section.key, value))}\n onChange={(index, value) => { safelyApply(() => replaceBridgeTextListItem(projection, section.key, index, value)) }}\n onRemove={(index) => { safelyApply(() => removeBridgeTextListItem(projection, section.key, index)) }}\n />}\n </div>)}\n {projection.opaqueSuffix\n ? <div className=\"dsh-bridge-appendix\">\n <div><div className=\"dsh-bridge-field-label\">{copy.appendix}</div><div className=\"dsh-bridge-appendix-copy\">{copy.appendixHelp}</div></div>\n <SummaryView summary={projection.opaqueSuffix} lang={lang} />\n </div>\n : null}\n </div>\n}\n\ntype EditorMode = 'preview' | 'text' | 'markdown'\nconst EDITOR_MODES: readonly EditorMode[] = ['preview', 'text', 'markdown']\n\nfunction PreviewCard({ card, execute, openSession, sessionId }: {\n card: Extract<BridgeCard, { phase: 'preview' }>\n execute: BridgeInjected['execute']\n openSession: BridgeInjected['openSession']\n sessionId: SessionId\n}) {\n const copy = COPY[card.lang]\n const panelId = useId()\n const [mode, setMode] = useState<EditorMode>('preview')\n const [summary, setSummary] = useState(card.summary)\n const [busy, setBusy] = useState(false)\n const [status, setStatus] = useState('')\n const [error, setError] = useState('')\n const [pendingSummary, setPendingSummary] = useState<string | null>(null)\n const [created, setCreated] = useState<Extract<BridgeCard, { phase: 'migrated' }> | null>(null)\n const lastCardSummary = useRef(card.summary)\n const confirming = useRef(false)\n const tooLong = summary.length > MAX_EDITED_SUMMARY_CHARS\n const textProjection = useMemo(() => tooLong ? undefined : parseBridgeTextProjection(summary), [summary, tooLong])\n const updateSummary = (next: string) => {\n if (next.length > MAX_EDITED_SUMMARY_CHARS) {\n setError(copy.tooLong)\n return false\n }\n setError('')\n setSummary(next)\n return true\n }\n\n useEffect(() => {\n const prior = lastCardSummary.current\n if (card.summary === prior) return\n lastCardSummary.current = card.summary\n if (summary === prior) {\n setSummary(card.summary)\n setPendingSummary(null)\n } else {\n setPendingSummary(card.summary)\n }\n }, [card.summary, summary])\n\n const copySummary = async () => {\n try {\n await navigator.clipboard.writeText(summary)\n setError('')\n setStatus(copy.copied)\n } catch (cause) {\n setStatus('')\n setError(cause instanceof Error ? cause.message : String(cause))\n }\n }\n\n const confirm = async () => {\n if (confirming.current) return\n confirming.current = true\n setBusy(true)\n setError('')\n setStatus(copy.confirming)\n try {\n const outcome = await execute(sessionId, buildBridgeMigrationCommand(card.targetPreset, summary, card.lang, card.previewId ?? ''))\n const result = parseBridgeCard(outcome)\n if (result.phase === 'error') throw new Error(result.text)\n if (result.phase !== 'migrated') throw new Error(card.lang === 'en' ? 'The host returned no target session.' : '宿主没有返回目标会话。')\n setCreated(result)\n setStatus(copy.opening)\n await openSession(result.sessionId)\n } catch (cause) {\n setError(cause instanceof Error ? cause.message : String(cause))\n setStatus('')\n } finally {\n confirming.current = false\n setBusy(false)\n }\n }\n\n if (created) return <MigratedCard card={created} openSession={openSession} status={status} error={error} />\n\n return <div className=\"dsh-bridge-card\">\n <Header lang={card.lang} route={`${card.sourcePreset} → ${card.targetPreset}`} />\n <div className=\"dsh-bridge-body\">\n <div className=\"dsh-bridge-toolbar\">\n <div\n className=\"dsh-bridge-tabs\"\n role=\"tablist\"\n aria-label={copy.title}\n onKeyDown={(event) => {\n if (!['ArrowLeft', 'ArrowRight', 'Home', 'End'].includes(event.key)) return\n event.preventDefault()\n const current = EDITOR_MODES.indexOf(mode)\n const next = event.key === 'Home'\n ? 0\n : event.key === 'End'\n ? EDITOR_MODES.length - 1\n : (current + (event.key === 'ArrowRight' ? 1 : -1) + EDITOR_MODES.length) % EDITOR_MODES.length\n const nextMode = EDITOR_MODES[next] ?? 'preview'\n setMode(nextMode)\n window.requestAnimationFrame(() => { document.getElementById(`${panelId}-${nextMode}`)?.focus() })\n }}\n >\n {([\n ['preview', copy.preview],\n ['text', copy.text],\n ['markdown', copy.markdownSource],\n ] as const).map(([value, label]) => <button\n aria-controls={panelId}\n aria-selected={mode === value}\n className=\"dsh-bridge-tab\"\n id={`${panelId}-${value}`}\n key={value}\n role=\"tab\"\n tabIndex={mode === value ? 0 : -1}\n type=\"button\"\n onClick={() => { setMode(value) }}\n >{label}</button>)}\n </div>\n <div className=\"dsh-bridge-actions\">\n <button className=\"dsh-bridge-button\" type=\"button\" onClick={() => { void copySummary() }}>{copy.copy}</button>\n <button className=\"dsh-bridge-button\" data-primary type=\"button\" disabled={busy || !card.previewId || summary.trim() === '' || tooLong} onClick={() => { void confirm() }}>{busy ? copy.confirming : copy.confirm}</button>\n </div>\n </div>\n {pendingSummary !== null\n ? <div className=\"dsh-bridge-draft-notice\" role=\"status\">\n <span>{copy.newPreview}</span>\n <div className=\"dsh-bridge-actions\">\n <button className=\"dsh-bridge-button\" type=\"button\" onClick={() => { setPendingSummary(null) }}>{copy.keepDraft}</button>\n <button className=\"dsh-bridge-button\" type=\"button\" onClick={() => { setSummary(pendingSummary); setPendingSummary(null) }}>{copy.loadPreview}</button>\n </div>\n </div>\n : null}\n <div aria-labelledby={`${panelId}-${mode}`} className=\"dsh-bridge-panel\" id={panelId} role=\"tabpanel\">\n {tooLong\n ? <div className=\"dsh-bridge-notice\" role=\"alert\">{copy.tooLong}{card.summaryFile ? <><br /><strong>{copy.fileFallback}:</strong> <code>{card.summaryFile}</code></> : null}</div>\n : mode === 'preview'\n ? <SummaryView summary={summary} lang={card.lang} />\n : mode === 'text'\n ? textProjection\n ? <TextHandoffEditor\n idPrefix={panelId}\n lang={card.lang}\n projection={textProjection}\n onChange={updateSummary}\n onError={setError}\n />\n : <div className=\"dsh-bridge-notice\" role=\"status\">\n {copy.textUnavailable}\n <div className=\"dsh-bridge-notice-actions\"><button className=\"dsh-bridge-button\" type=\"button\" onClick={() => { setMode('markdown') }}>{copy.editMarkdown}</button></div>\n </div>\n : <textarea className=\"dsh-bridge-markdown-editor\" aria-label={copy.markdownEditor} maxLength={MAX_EDITED_SUMMARY_CHARS} value={summary} onChange={(event) => { updateSummary(event.currentTarget.value) }} spellCheck={false} />}\n </div>\n <div className=\"dsh-bridge-meta\">\n {card.stats ? <span className=\"dsh-bridge-chip\">{card.stats}</span> : null}\n <span className=\"dsh-bridge-chip\">{summary.length.toLocaleString()} {copy.chars}</span>\n </div>\n {card.warnings.map((warning) => <div className=\"dsh-bridge-warning\" key={warning}>⚠ {warning}</div>)}\n {!card.previewId ? <div className=\"dsh-bridge-warning\">⚠ {copy.stalePreview}</div> : null}\n {status ? <div className=\"dsh-bridge-status\" aria-live=\"polite\">{status}</div> : null}\n {error ? <div className=\"dsh-bridge-error\" role=\"alert\">{error}</div> : null}\n </div>\n </div>\n}\n\nfunction MigratedCard({ card, error = '', openSession, status = '' }: {\n card: Extract<BridgeCard, { phase: 'migrated' }>\n error?: string\n openSession: BridgeInjected['openSession']\n status?: string\n}) {\n const copy = COPY[card.lang]\n const [opening, setOpening] = useState(false)\n const [localError, setLocalError] = useState(error)\n const open = async () => {\n setOpening(true)\n setLocalError('')\n try { await openSession(card.sessionId) } catch (cause) { setLocalError(cause instanceof Error ? cause.message : String(cause)) } finally { setOpening(false) }\n }\n return <div className=\"dsh-bridge-card\">\n <Header lang={card.lang} route={`→ ${card.targetPreset}`} />\n <div className=\"dsh-bridge-body dsh-bridge-success\">\n <div className=\"dsh-bridge-session\"><strong>{card.title}</strong><br />{card.sessionId}</div>\n {card.details.map((detail) => <div className=\"dsh-bridge-copy\" key={detail}>{detail}</div>)}\n <div className=\"dsh-bridge-actions\"><button className=\"dsh-bridge-button\" data-primary type=\"button\" disabled={opening} onClick={() => { void open() }}>{opening ? copy.opening : copy.open}</button></div>\n {status ? <div className=\"dsh-bridge-status\" aria-live=\"polite\">{status}</div> : null}\n {card.warnings.map((warning) => <div className=\"dsh-bridge-warning\" key={warning}>⚠ {warning}</div>)}\n {localError ? <div className=\"dsh-bridge-error\" role=\"alert\">{localError}</div> : null}\n </div>\n </div>\n}\n\nfunction MessageCard({ card }: { card: Extract<BridgeCard, { phase: 'message' | 'error' }> }) {\n const lang = card.phase === 'message' ? card.lang : (/[㐀-鿿]/u.test(card.text) ? 'zh' : 'en')\n return <div className=\"dsh-bridge-card\"><Header lang={lang} /><div className=\"dsh-bridge-body\">\n <div className=\"dsh-bridge-panel\">{card.phase === 'error' ? <div className=\"dsh-bridge-error\" role=\"alert\">{card.text}</div> : <SummaryView summary={card.text} lang={card.lang} />}</div>\n </div></div>\n}\n\nclass BridgeCardBoundary extends Component<{ children: ReactNode; lang: 'zh' | 'en' }, { failed: boolean }> {\n state = { failed: false }\n\n static getDerivedStateFromError(): { failed: boolean } {\n return { failed: true }\n }\n\n componentDidCatch(error: Error, info: ErrorInfo): void {\n console.error('dsh-plugin-bridge card render failed', error, info.componentStack)\n }\n\n render(): ReactNode {\n if (!this.state.failed) return this.props.children\n return <div className=\"dsh-bridge-card\"><Header lang={this.props.lang} /><div className=\"dsh-bridge-body\">\n <div className=\"dsh-bridge-error\" role=\"alert\">{COPY[this.props.lang].renderFailure}</div>\n </div></div>\n }\n}\n\nfunction BridgeCommandCardContent({ node, execute, openSession, sessionId }: BridgeCommandCardProps) {\n const card = useMemo(() => parseBridgeCard(node.outcome), [node.outcome])\n if (card.phase === 'running') return <RunningCard />\n if (card.phase === 'preview') return <PreviewCard card={card} execute={execute} openSession={openSession} sessionId={sessionId} />\n if (card.phase === 'migrated') return <MigratedCard card={card} openSession={openSession} />\n return <MessageCard card={card} />\n}\n\n/** Rich renderer for the durable command lifecycle keyed by name and isolated from every other plugin. */\nexport function BridgeCommandCard(props: BridgeCommandCardProps) {\n const lang = uiLanguageOf(typeof document === 'undefined' ? undefined : document.documentElement.lang)\n const outcomeKey = props.node.outcome === null ? 'running' : `${props.node.outcome.kind}:${props.node.outcome.text ?? ''}`\n return <BridgeCardBoundary key={outcomeKey} lang={lang}><BridgeCommandCardContent {...props} /></BridgeCardBoundary>\n}\n\nasync function openWhenVisible(ctx: ClientContext, sessionId: SessionId): Promise<void> {\n if (ctx.sessions.list.getSnapshot().byId[sessionId] !== undefined) {\n ctx.sessions.open(sessionId)\n return\n }\n await new Promise<void>((resolve, reject) => {\n let dispose = () => {}\n const timeout = window.setTimeout(() => {\n dispose()\n reject(new Error(`Target session ${sessionId} has not reached this browser yet.`))\n }, 5_000)\n dispose = ctx.sessions.list.subscribe(() => {\n if (ctx.sessions.list.getSnapshot().byId[sessionId] === undefined) return\n window.clearTimeout(timeout)\n dispose()\n resolve()\n })\n })\n ctx.sessions.open(sessionId)\n}\n\n/** Client services are supplied by the official WebUI module table. */\n// rc.2 guards the parent `remote` face separately from its `remote.commands`\n// capability; older compatible builds tolerate the redundant parent seat.\nexport const inject = ['slots', 'sessions', 'remote', 'remote.commands']\n\nexport function apply(ctx: ClientContext): void {\n const commands = (ctx as unknown as { remote: { commands: CommandRemote } }).remote.commands\n ctx.effect(() => {\n const prior = document.querySelector(`style[data-plugin-css=\"${STYLE_ID}\"]`)\n if (prior !== null) return () => {}\n const style = document.createElement('style')\n style.dataset.plugin = 'dsh-plugin-bridge'\n style.dataset.pluginCss = STYLE_ID\n style.textContent = STYLE\n document.head.append(style)\n return () => { style.remove() }\n }, 'bridge: native card styles')\n ctx.slots.inject('conversation.chat.commandview', () => ctx.slots.register({\n name: 'conversation.chat.commandview',\n key: 'bridge',\n inject: (): BridgeInjected => ({\n execute: async (sessionId, line) => {\n const result = await commands.execute(sessionId, line, [])\n if (!result.ok) throw new Error(`${result.error?.code ?? 'command-failed'}: ${result.error?.message ?? 'The host rejected the command.'}`)\n if (result.value === undefined) throw new Error('The /bridge command was not admitted by the host.')\n return result.value.result\n },\n openSession: (sessionId) => openWhenVisible(ctx, sessionId),\n }),\n }, BridgeCommandCard))\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"client.js","names":["useState","useMemo","MarkdownText","JsonTree","useId","useRef","Component"],"sources":["../src/client-contract.ts","../src/client.tsx"],"sourcesContent":["/** Pure wire-to-view helpers shared by the native WebUI card and Node tests. */\n\nexport const MAX_EDITED_SUMMARY_CHARS = 24_000\n\nexport type BridgeOutcome = { kind: 'success' | 'error'; text?: string } | null\n\nexport type BridgeCard =\n | { phase: 'running' }\n | {\n phase: 'preview'\n lang: 'zh' | 'en'\n sourcePreset: string\n targetPreset: string\n previewId?: string\n summary: string\n summaryFile?: string\n stats: string\n warnings: string[]\n }\n | {\n phase: 'migrated'\n lang: 'zh' | 'en'\n targetPreset: string\n title: string\n sessionId: string\n details: string[]\n warnings: string[]\n }\n | { phase: 'error'; text: string }\n | { phase: 'message'; text: string; lang: 'zh' | 'en' }\n\nexport type BridgeTextSectionKey =\n | 'goal'\n | 'currentState'\n | 'keyDecisions'\n | 'keyFiles'\n | 'nextStep'\n\nexport interface BridgeTextSection {\n key: BridgeTextSectionKey\n label: string\n kind: 'text' | 'list'\n /** Plain-text editor value. List markers are intentionally omitted. */\n text: string\n /** Exact source span replaced when this field is edited. */\n bodyStart: number\n bodyEnd: number\n items?: BridgeTextListItem[]\n listStyle?: BridgeListStyle\n textStyle?: 'plain' | 'bullets'\n}\n\ntype BridgeListStyle = 'bullet' | 'ordered' | 'plain'\n\nexport interface BridgeTextListItem {\n text: string\n contentStart: number\n contentEnd: number\n itemStart: number\n itemEnd: number\n /** Exact Markdown marker retained when this item is edited. */\n marker?: string\n /** Original indentation for wrapped lines, kept when that item is edited. */\n continuationPrefixes?: string[]\n}\n\nexport interface BridgeTextProjection {\n lang: 'zh' | 'en'\n /** The untouched Markdown document used to enter text mode. */\n markdown: string\n lineEnding: '\\n' | '\\r\\n'\n sections: BridgeTextSection[]\n /** Known appendices are visible but read-only in plain-text mode. */\n opaqueSuffix: string\n}\n\nconst RUN_COMMAND = /\\/bridge\\s+([^\\s]+)\\s+--go(?:\\s|$)/u\n\nconst TEXT_SCHEMAS = {\n zh: [\n ['goal', '目标', 'text'],\n ['currentState', '当前状态', 'text'],\n ['keyDecisions', '关键决策与约定', 'list'],\n ['keyFiles', '关键文件', 'list'],\n ['nextStep', '下一步', 'text'],\n ],\n en: [\n ['goal', 'Goal', 'text'],\n ['currentState', 'Current state', 'text'],\n ['keyDecisions', 'Key decisions & conventions', 'list'],\n ['keyFiles', 'Key files', 'list'],\n ['nextStep', 'Next step', 'text'],\n ],\n} as const satisfies Record<'zh' | 'en', readonly (readonly [BridgeTextSectionKey, string, 'text' | 'list'])[]>\n\nconst TEXT_APPENDICES = {\n zh: new Set(['视觉证据——原文搬运,未经二次摘要', '未解析图片']),\n en: new Set(['Visual evidence — verbatim, not summarized', 'Unresolved images']),\n} as const\n\ninterface SourceLine {\n start: number\n contentEnd: number\n end: number\n text: string\n}\n\ninterface MarkdownHeading {\n label: string\n start: number\n lineEnd: number\n}\n\nfunction sourceLines(markdown: string, lineEnding: '\\n' | '\\r\\n'): SourceLine[] {\n const lines: SourceLine[] = []\n let start = 0\n while (start <= markdown.length) {\n const next = markdown.indexOf(lineEnding, start)\n if (next < 0) {\n lines.push({ start, contentEnd: markdown.length, end: markdown.length, text: markdown.slice(start) })\n break\n }\n lines.push({ start, contentEnd: next, end: next + lineEnding.length, text: markdown.slice(start, next) })\n start = next + lineEnding.length\n if (start === markdown.length) {\n lines.push({ start, contentEnd: start, end: start, text: '' })\n break\n }\n }\n return lines\n}\n\nfunction markdownHeadings(markdown: string, lineEnding: '\\n' | '\\r\\n'): MarkdownHeading[] | undefined {\n const headings: MarkdownHeading[] = []\n let fence: { marker: '`' | '~'; length: number } | undefined\n for (const line of sourceLines(markdown, lineEnding)) {\n const fenceMatch = /^ {0,3}(`{3,}|~{3,})(.*)$/u.exec(line.text)\n if (fence) {\n if (fenceMatch && fenceMatch[1]?.[0] === fence.marker\n && (fenceMatch[1]?.length ?? 0) >= fence.length\n && (fenceMatch[2]?.trim() ?? '') === '') {\n fence = undefined\n }\n continue\n }\n if (fenceMatch) {\n const token = fenceMatch[1] ?? ''\n fence = { marker: token[0] as '`' | '~', length: token.length }\n continue\n }\n if (!line.text.startsWith('##')) continue\n const rest = line.text.slice(2)\n if (rest[0] !== ' ' && rest[0] !== '\\t') continue\n let labelStart = 0\n while (labelStart < rest.length && (rest[labelStart] === ' ' || rest[labelStart] === '\\t')) labelStart += 1\n let labelEnd = rest.length\n while (labelEnd > labelStart && (rest[labelEnd - 1] === ' ' || rest[labelEnd - 1] === '\\t')) labelEnd -= 1\n if (labelEnd > labelStart) headings.push({ label: rest.slice(labelStart, labelEnd), start: line.start, lineEnd: line.end })\n }\n return fence ? undefined : headings\n}\n\nfunction documentLineEnding(markdown: string): '\\n' | '\\r\\n' | undefined {\n const endings = markdown.match(/\\r\\n|\\n|\\r/gu)\n if (!endings?.length) return undefined\n const first = endings[0]\n if ((first !== '\\n' && first !== '\\r\\n') || endings.some((ending) => ending !== first)) return undefined\n return first\n}\n\nconst MARKDOWN_BLOCK_START = /^([\\t ]{0,3})(#{1,6}(?:[\\t ]|$)|>(?:[\\t ]|$)|[-+*](?:[\\t ]|$)|\\d+[.)](?:[\\t ]|$)|`{3}|~{3})/u\nconst THEMATIC_OR_SETEXT = /^ {0,3}(?:(?:\\*[\\t ]*){3,}|(?:-[\\t ]*){3,}|(?:_[\\t ]*){3,}|=+[\\t ]*)$/u\nconst TABLE_DELIMITER = /^ {0,3}\\|?[\\t ]*:?-{3,}:?[\\t ]*(?:\\|[\\t ]*:?-{3,}:?[\\t ]*)+\\|?[\\t ]*$/u\nconst LINK_DEFINITION = /^ {0,3}\\[[^\\]]+\\]:[\\t ]*\\S/u\nconst HTML_BLOCK_START = /^ {0,3}<[/!?A-Za-z]/u\nconst BULLET_LIST_ITEM = /^(- )(.+)$/u\nconst ORDERED_LIST_ITEM = /^(\\d{1,9}[.)] )(.+)$/u\n\nfunction hasUnsafeBlock(line: string): boolean {\n return MARKDOWN_BLOCK_START.test(line)\n || THEMATIC_OR_SETEXT.test(line)\n || TABLE_DELIMITER.test(line)\n || LINK_DEFINITION.test(line)\n || /^(?: {4}|\\t)/u.test(line)\n || line.includes('<!--')\n || line.includes('-->')\n || line.includes('--!>')\n || HTML_BLOCK_START.test(line)\n}\n\nfunction parseListItems(\n markdownBody: string,\n lineEnding: '\\n' | '\\r\\n',\n bodyStart: number,\n allowPlain: boolean,\n): { items: BridgeTextListItem[]; style: BridgeListStyle; text: string } | undefined {\n if (!markdownBody) return { items: [], style: 'bullet', text: '' }\n const lines = sourceLines(markdownBody, lineEnding)\n if (lines.some((line) => !line.text.trim())) return undefined\n const firstLine = lines[0]?.text ?? ''\n const style = BULLET_LIST_ITEM.test(firstLine)\n ? 'bullet'\n : ORDERED_LIST_ITEM.test(firstLine)\n ? 'ordered'\n : allowPlain\n ? 'plain'\n : undefined\n if (!style) return undefined\n\n const items: BridgeTextListItem[] = []\n if (style === 'plain') {\n for (const line of lines) {\n if (hasUnsafeBlock(line.text) || /^[\\t ]*(?:[-+*]|\\d+[.)])[\\t ]+/u.test(line.text)) return undefined\n items.push({\n text: line.text,\n contentStart: bodyStart + line.start,\n contentEnd: bodyStart + line.contentEnd,\n itemStart: bodyStart + line.start,\n itemEnd: bodyStart + line.end,\n })\n }\n } else {\n const itemPattern = style === 'ordered' ? ORDERED_LIST_ITEM : BULLET_LIST_ITEM\n const starts: number[] = []\n for (const [index, line] of lines.entries()) {\n if (itemPattern.test(line.text)) {\n starts.push(index)\n continue\n }\n if (!starts.length || hasUnsafeBlock(line.text) || /^[\\t ]+(?:[-+*]|\\d+[.)])[\\t ]+/u.test(line.text)\n || /^[+*][\\t ]+/u.test(line.text) || /^\\d+[.)][\\t ]+/u.test(line.text)) return undefined\n }\n for (const [itemIndex, lineIndex] of starts.entries()) {\n const first = lines[lineIndex] as SourceLine\n const nextLineIndex = starts[itemIndex + 1] ?? lines.length\n const last = lines[nextLineIndex - 1] as SourceLine\n const itemMatch = itemPattern.exec(first.text)\n const marker = itemMatch?.[1]\n const firstText = itemMatch?.[2]\n if (!marker || !firstText) return undefined\n const continuationLines = lines.slice(lineIndex + 1, nextLineIndex)\n const continuationPrefixes = continuationLines.map((line) => /^[\\t ]*/u.exec(line.text)?.[0] ?? '')\n const continuation = continuationLines.map((line, index) => line.text.slice(continuationPrefixes[index]?.length ?? 0))\n items.push({\n text: [firstText, ...continuation].join(lineEnding),\n contentStart: bodyStart + first.start + marker.length,\n contentEnd: bodyStart + last.contentEnd,\n itemStart: bodyStart + first.start,\n itemEnd: bodyStart + (lines[nextLineIndex]?.start ?? markdownBody.length),\n marker,\n continuationPrefixes,\n })\n }\n }\n return { items, style, text: items.map((item) => item.text).join(lineEnding) }\n}\n\nfunction plainBlockText(markdownBody: string, lineEnding: '\\n' | '\\r\\n'): string {\n return markdownBody\n .split(lineEnding)\n .map((line) => line.replace(/^([\\t ]{0,3})\\\\(?=[#>*+`~_<\\[|!=-])/u, '$1'))\n .join(lineEnding)\n}\n\nfunction isPlainBlock(markdownBody: string, lineEnding: '\\n' | '\\r\\n'): boolean {\n return sourceLines(markdownBody, lineEnding).every((line) => !hasUnsafeBlock(line.text))\n}\n\nfunction parseTextBlock(markdownBody: string, lineEnding: '\\n' | '\\r\\n'): { style: 'plain' | 'bullets', text: string } | undefined {\n const lines = sourceLines(markdownBody, lineEnding)\n if (lines.length && lines.every((line) => /^- (.+)$/u.test(line.text))) {\n return { style: 'bullets', text: lines.map((line) => /^- (.+)$/u.exec(line.text)?.[1] ?? '').join(lineEnding) }\n }\n return isPlainBlock(markdownBody, lineEnding)\n ? { style: 'plain', text: plainBlockText(markdownBody, lineEnding) }\n : undefined\n}\n\nfunction markdownSafePlainText(text: string, lineEnding: '\\n' | '\\r\\n'): string {\n return text\n .split(lineEnding)\n .map((line) => {\n if (/^(?: {4}|\\t)/u.test(line)) throw new Error('Plain-text lines cannot start with four spaces or a tab')\n if (!hasUnsafeBlock(line)) return line\n return line.replace(/^([\\t ]{0,3})(?=\\S)/u, '$1\\\\')\n })\n .join(lineEnding)\n}\n\n/**\n * Project only Bridge's exact bilingual five-section schema into plain fields.\n * Unknown structure fails closed; known visual appendices remain opaque Markdown.\n */\nexport function parseBridgeTextProjection(markdown: string): BridgeTextProjection | undefined {\n const lineEnding = documentLineEnding(markdown)\n if (!lineEnding) return undefined\n const headings = markdownHeadings(markdown, lineEnding)\n if (!headings?.length || headings[0]?.start !== 0) return undefined\n\n const lang = headings[0]?.label === TEXT_SCHEMAS.zh[0][1]\n ? 'zh'\n : headings[0]?.label === TEXT_SCHEMAS.en[0][1]\n ? 'en'\n : undefined\n if (!lang) return undefined\n\n const appendixIndex = headings.findIndex((heading) => TEXT_APPENDICES[lang].has(heading.label))\n const schemaHeadings = appendixIndex < 0 ? headings : headings.slice(0, appendixIndex)\n if (schemaHeadings.length !== TEXT_SCHEMAS[lang].length) return undefined\n if (schemaHeadings.some((heading, index) => heading.label !== TEXT_SCHEMAS[lang][index]?.[1])) return undefined\n\n const firstAppendix = appendixIndex < 0 ? undefined : headings[appendixIndex]\n const editableMarkdown = markdown.slice(0, firstAppendix?.start ?? markdown.length)\n if (editableMarkdown.includes('<!--') || editableMarkdown.includes('-->') || editableMarkdown.includes('--!>')) return undefined\n const sections: BridgeTextSection[] = []\n for (const [index, heading] of schemaHeadings.entries()) {\n const [key, label, kind] = TEXT_SCHEMAS[lang][index] as typeof TEXT_SCHEMAS[typeof lang][number]\n const bodyStart = heading.lineEnd\n const regionEnd = schemaHeadings[index + 1]?.start ?? firstAppendix?.start ?? markdown.length\n let bodyEnd = regionEnd\n while (bodyEnd - lineEnding.length >= bodyStart\n && markdown.slice(bodyEnd - lineEnding.length, bodyEnd) === lineEnding) {\n bodyEnd -= lineEnding.length\n }\n const body = markdown.slice(bodyStart, bodyEnd)\n const list = kind === 'list' ? parseListItems(body, lineEnding, bodyStart, key === 'keyFiles') : undefined\n const textBlock = kind === 'text' ? parseTextBlock(body, lineEnding) : undefined\n if (kind === 'list' && !list) return undefined\n if (kind === 'text' && !textBlock) return undefined\n const text = list?.text ?? textBlock?.text ?? ''\n sections.push({\n key,\n label,\n kind,\n text,\n bodyStart,\n bodyEnd,\n ...(list ? { items: list.items, listStyle: list.style } : {}),\n ...(textBlock ? { textStyle: textBlock.style } : {}),\n })\n }\n return {\n lang,\n markdown,\n lineEnding,\n sections,\n opaqueSuffix: firstAppendix ? markdown.slice(firstAppendix.start) : '',\n }\n}\n\nfunction normalizeLineEndings(text: string, lineEnding: '\\n' | '\\r\\n'): string {\n return text.replace(/\\r\\n|\\n|\\r/gu, lineEnding)\n}\n\n/** Replace one editable body while preserving every byte outside that section. */\nexport function replaceBridgeTextSection(\n projection: BridgeTextProjection,\n key: BridgeTextSectionKey,\n plainText: string,\n): string {\n const section = projection.sections.find((candidate) => candidate.key === key)\n if (!section) throw new Error(`Unknown Bridge text section: ${key}`)\n if (plainText === section.text) return projection.markdown\n const normalized = normalizeLineEndings(plainText, projection.lineEnding)\n let markdownBody: string\n if (section.kind === 'list') {\n const values = normalized.split(projection.lineEnding)\n if (!section.items || values.length !== section.items.length || section.items.some((item) => item.text.includes(projection.lineEnding))) {\n throw new Error('Use Bridge list-item helpers for this section')\n }\n markdownBody = section.listStyle === 'plain'\n ? values.join(projection.lineEnding)\n : values.map((line, index) => `${section.items?.[index]?.marker ?? '- '}${line}`).join(projection.lineEnding)\n } else {\n markdownBody = section.textStyle === 'bullets'\n ? normalized.split(projection.lineEnding).map((line) => `- ${line}`).join(projection.lineEnding)\n : markdownSafePlainText(normalized, projection.lineEnding)\n }\n return projection.markdown.slice(0, section.bodyStart)\n + markdownBody\n + projection.markdown.slice(section.bodyEnd)\n}\n\nfunction listSection(projection: BridgeTextProjection, key: BridgeTextSectionKey): BridgeTextSection {\n const section = projection.sections.find((candidate) => candidate.key === key)\n if (!section || section.kind !== 'list' || !section.items || !section.listStyle) {\n throw new Error(`Unknown Bridge list section: ${key}`)\n }\n return section\n}\n\nfunction editedListItem(\n text: string,\n style: BridgeListStyle,\n lineEnding: '\\n' | '\\r\\n',\n original?: BridgeTextListItem,\n): string {\n const normalized = normalizeLineEndings(text, lineEnding)\n if (!normalized.trim()) throw new Error('Bridge list item is empty')\n const lines = normalized.split(lineEnding)\n if (lines.some((line) => hasUnsafeBlock(line))) throw new Error('Bridge list item contains Markdown block structure')\n if (style === 'plain' && lines.length > 1) throw new Error('Plain path rows must stay on one line')\n return style !== 'plain'\n ? [\n lines[0],\n ...lines.slice(1).map((line, index) => `${original?.continuationPrefixes?.[index] ?? ' '}${line}`),\n ].join(lineEnding)\n : normalized\n}\n\n/** Replace one list item without rewriting siblings and while retaining wrapped-line indentation. */\nexport function replaceBridgeTextListItem(\n projection: BridgeTextProjection,\n key: BridgeTextSectionKey,\n index: number,\n plainText: string,\n): string {\n const section = listSection(projection, key)\n const item = section.items?.[index]\n if (!item) throw new Error(`Unknown Bridge list item: ${key}[${index}]`)\n if (plainText === item.text) return projection.markdown\n const edited = editedListItem(plainText, section.listStyle as BridgeListStyle, projection.lineEnding, item)\n return projection.markdown.slice(0, item.contentStart) + edited + projection.markdown.slice(item.contentEnd)\n}\n\n/** Remove exactly one original list-item span. */\nexport function removeBridgeTextListItem(\n projection: BridgeTextProjection,\n key: BridgeTextSectionKey,\n index: number,\n): string {\n const section = listSection(projection, key)\n const items = section.items ?? []\n const item = items[index]\n if (!item) throw new Error(`Unknown Bridge list item: ${key}[${index}]`)\n const removeStart = index > 0 && index === items.length - 1\n ? item.itemStart - projection.lineEnding.length\n : item.itemStart\n return projection.markdown.slice(0, removeStart) + projection.markdown.slice(item.itemEnd)\n}\n\n/** Append one item using the section's existing Markdown list convention. */\nexport function appendBridgeTextListItem(\n projection: BridgeTextProjection,\n key: BridgeTextSectionKey,\n plainText: string,\n): string {\n const section = listSection(projection, key)\n const edited = editedListItem(plainText, section.listStyle as BridgeListStyle, projection.lineEnding)\n const prefix = section.bodyStart === section.bodyEnd ? '' : projection.lineEnding\n let marker = ''\n if (section.listStyle === 'bullet') marker = '- '\n if (section.listStyle === 'ordered') {\n const previous = section.items?.at(-1)?.marker\n const match = /^(\\d{1,9})([.)]) $/u.exec(previous ?? '')\n const next = match ? Number(match[1]) + 1 : (section.items?.length ?? 0) + 1\n if (!Number.isSafeInteger(next) || next > 999_999_999) {\n throw new Error('Bridge ordered list marker is out of range')\n }\n marker = `${String(next)}${match?.[2] ?? '.'} `\n }\n const item = `${marker}${edited}`\n return projection.markdown.slice(0, section.bodyEnd) + prefix + item + projection.markdown.slice(section.bodyEnd)\n}\n\ninterface PreviewHeader {\n lang: 'zh' | 'en'\n sourcePreset: string\n targetPreset: string\n}\n\nfunction previewHeaderOf(line: string): PreviewHeader | undefined {\n const prefix = line.startsWith('─── Handoff · ')\n ? { text: '─── Handoff · ', lang: 'en' as const }\n : line.startsWith('─── 交接摘要 · ')\n ? { text: '─── 交接摘要 · ', lang: 'zh' as const }\n : undefined\n if (!prefix) return undefined\n const route = line.slice(prefix.text.length)\n const arrow = route.indexOf('→')\n if (arrow < 1) return undefined\n const sourcePreset = route.slice(0, arrow).trim()\n const targetTail = route.slice(arrow + 1).trimStart()\n let targetEnd = 0\n while (targetEnd < targetTail.length) {\n const char = targetTail[targetEnd]\n if (char === undefined || /\\s/u.test(char) || char === '(' || char === '(' || char === '─') break\n targetEnd += 1\n }\n const targetPreset = targetTail.slice(0, targetEnd)\n if (!sourcePreset || !targetPreset) return undefined\n return { lang: prefix.lang, sourcePreset, targetPreset }\n}\n\nfunction isDivider(line: string): boolean {\n const trimmed = line.trim()\n return trimmed.length >= 10 && [...trimmed].every((char) => char === '─')\n}\n\nfunction languageOf(text: string): 'zh' | 'en' {\n return /[\\u3400-\\u9fff]/u.test(text) ? 'zh' : 'en'\n}\n\n/** Map the official WebUI document language onto Bridge's supported UI copy. */\nexport function uiLanguageOf(documentLang: string | undefined): 'zh' | 'en' {\n return documentLang?.toLowerCase().startsWith('zh') === true ? 'zh' : 'en'\n}\n\nfunction parsePreview(text: string): BridgeCard | undefined {\n const lines = text.split('\\n')\n const header = previewHeaderOf(lines[0] ?? '')\n if (!header) return undefined\n const divider = lines.findIndex((line, index) => index > 0 && isDivider(line))\n if (divider < 2) return undefined\n const command = RUN_COMMAND.exec(text)\n const targetPreset = command?.[1] ?? header.targetPreset\n if (!targetPreset) return undefined\n\n const tail = lines.slice(divider + 1)\n const stats = tail.find((line) => line.trim() !== '' && !line.startsWith('⚠') && !RUN_COMMAND.test(line)) ?? ''\n const warnings = tail\n .filter((line) => line.startsWith('⚠'))\n .map((line) => line.replace(/^⚠\\s*/u, ''))\n const previewIdLine = tail.find((line) => line.startsWith('Preview ID:') || line.startsWith('预览 ID:'))\n const previewId = previewIdLine?.slice(previewIdLine.indexOf(previewIdLine.startsWith('Preview') ? ':' : ':') + 1).trim()\n const fileLine = tail.find((line) => line.includes(' --file '))\n const fileMarker = fileLine?.lastIndexOf(' --file ') ?? -1\n const summaryFile = fileMarker < 0 ? undefined : fileLine?.slice(fileMarker + ' --file '.length).trim().split(/\\s/u)[0]\n return {\n phase: 'preview',\n lang: header.lang,\n sourcePreset: header.sourcePreset,\n targetPreset,\n ...(previewId ? { previewId } : {}),\n summary: lines.slice(1, divider).join('\\n').trim(),\n ...(summaryFile ? { summaryFile } : {}),\n stats,\n warnings,\n }\n}\n\nfunction parseMigrated(text: string): BridgeCard | undefined {\n const lines = text.split('\\n').map((line) => line.trim()).filter(Boolean)\n const first = lines[0] ?? ''\n const lang: 'zh' | 'en' = first.startsWith('Created a new session') ? 'en' : 'zh'\n const presetPrefix = lang === 'en' ? 'Created a new session in the ' : '已在 '\n const presetSuffix = lang === 'en' ? ' preset' : ' 模式下建好新会话'\n const presetEnd = first.indexOf(presetSuffix, presetPrefix.length)\n const preset = presetEnd < 0 ? undefined : first.slice(presetPrefix.length, presetEnd).trim()\n if (!preset) return undefined\n const targetIndex = lines.findIndex((line) => line.startsWith('Target session:') || line.startsWith('目标会话:'))\n if (targetIndex < 0) return undefined\n const targetLine = lines[targetIndex] ?? ''\n const targetPrefix = targetLine.startsWith('Target session:') ? 'Target session:' : '目标会话:'\n const targetPayload = targetLine.slice(targetPrefix.length).trim()\n const targetSeparator = targetPayload.lastIndexOf(' · ')\n if (targetSeparator < 1) return undefined\n const title = targetPayload.slice(0, targetSeparator).trim()\n const sessionId = targetPayload.slice(targetSeparator + 3).trim()\n if (!title || !sessionId || /\\s/u.test(sessionId)) return undefined\n const remaining = lines.filter((_, index) => index !== 0 && index !== targetIndex)\n return {\n phase: 'migrated',\n lang,\n targetPreset: preset,\n title,\n sessionId,\n details: remaining.filter((line) => !line.startsWith('⚠')),\n warnings: remaining.filter((line) => line.startsWith('⚠')).map((line) => line.replace(/^⚠\\s*/u, '')),\n }\n}\n\n/** Convert one durable `/bridge` outcome into the native card's view model. */\nexport function parseBridgeCard(outcome: BridgeOutcome): BridgeCard {\n if (outcome === null) return { phase: 'running' }\n const text = outcome.text?.trim() ?? ''\n if (outcome.kind === 'error') return { phase: 'error', text }\n return parsePreview(text)\n ?? parseMigrated(text)\n ?? { phase: 'message', text, lang: languageOf(text) }\n}\n\n/** Return a value only when the complete editor document is valid JSON. */\nexport function parseJsonDocument(text: string): object | unknown[] | undefined {\n const trimmed = text.trim()\n if (!trimmed.startsWith('{') && !trimmed.startsWith('[')) return undefined\n try {\n const parsed = JSON.parse(trimmed) as unknown\n return typeof parsed === 'object' && parsed !== null ? parsed : undefined\n } catch {\n return undefined\n }\n}\n\nfunction encodeUtf8Base64Url(text: string): string {\n const bytes = new TextEncoder().encode(text)\n let binary = ''\n for (const byte of bytes) binary += String.fromCharCode(byte)\n return btoa(binary).replaceAll('+', '-').replaceAll('/', '_').replace(/=+$/u, '')\n}\n\n/** Build the hidden-input-safe command used by the native editor confirmation. */\nexport function buildBridgeMigrationCommand(targetPreset: string, summary: string, lang: 'zh' | 'en', previewId: string): string {\n if (!/^[A-Za-z0-9._-]+$/u.test(targetPreset)) throw new Error('Unsupported target preset id')\n if (lang !== 'zh' && lang !== 'en') throw new Error('Unsupported Bridge language')\n if (!/^[A-Za-z0-9-]{8,}$/u.test(previewId)) throw new Error('Unsupported Bridge preview ID')\n if (!summary.trim()) throw new Error('The handoff summary is empty')\n if (summary.length > MAX_EDITED_SUMMARY_CHARS) {\n throw new Error(`The handoff summary exceeds ${MAX_EDITED_SUMMARY_CHARS} characters`)\n }\n return `/bridge ${targetPreset} --go --lang ${lang} --preview-id ${previewId} --summary64 ${encodeUtf8Base64Url(summary)}`\n}\n","/** Official WebUI half: one native `/bridge` command card, not a second WebUI. */\n\nimport { Component, useEffect, useId, useMemo, useRef, useState, type ErrorInfo, type ReactNode } from 'react'\nimport type { Context as ClientContext } from '@deepseek-ai/cordis'\nimport type { SessionId } from '@deepseek-ai/dsh-api-remotes/client'\nimport { JsonTree, MarkdownText } from '@deepseek-ai/dsh-client-ui-primitives'\nimport type { JsonTreeLabels, MarkdownLabels } from '@deepseek-ai/dsh-client-ui-primitives'\nimport type {} from '@deepseek-ai/dsh-api-session-controller/client'\nimport type { CommandRowProps } from '@deepseek-ai/dsh-client-ui-chat/client'\nimport type {} from '@deepseek-ai/dsh-client-ui-conversation/client'\nimport type {} from '@deepseek-ai/dsh-client-ui-renderer/client'\nimport type {} from '@deepseek-ai/dsh-client-ui-session/client'\n\nimport {\n appendBridgeTextListItem,\n buildBridgeMigrationCommand,\n MAX_EDITED_SUMMARY_CHARS,\n parseBridgeCard,\n parseBridgeTextProjection,\n parseJsonDocument,\n removeBridgeTextListItem,\n replaceBridgeTextListItem,\n replaceBridgeTextSection,\n uiLanguageOf,\n type BridgeCard,\n type BridgeOutcome,\n type BridgeTextProjection,\n type BridgeTextSection,\n} from './client-contract.ts'\n\nconst STYLE_ID = 'dsh-plugin-bridge/native-card'\nconst STYLE = `\n.dsh-bridge-card{border:1px solid var(--dsw-alias-border-subtle,light-dark(#dedede,#3f3f46));border-radius:12px;background:var(--dsw-alias-background-primary,light-dark(#fff,#18181b));color:var(--dsw-alias-label-primary,light-dark(#171717,#f4f4f5));overflow:hidden;box-shadow:0 1px 2px rgba(0,0,0,.12)}\n.dsh-bridge-head{display:flex;align-items:center;gap:10px;min-height:44px;padding:0 14px;border-bottom:1px solid var(--dsw-alias-border-subtle,light-dark(#e6e6e6,#3f3f46));background:var(--dsw-alias-background-secondary,light-dark(#fafafa,#202024))}\n.dsh-bridge-mark{display:grid;place-items:center;width:22px;height:22px;border-radius:7px;background:var(--dsw-alias-state-business-secondary,light-dark(#e8f1ff,#22325c));color:var(--dsw-alias-state-business-primary,light-dark(#2869d8,#8eaeff));font:700 12px/1 ui-monospace,SFMono-Regular,Menlo,monospace}\n.dsh-bridge-title{min-width:0;flex:1;font-size:13px;font-weight:650;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.dsh-bridge-route{font:500 11px/1.2 ui-monospace,SFMono-Regular,Menlo,monospace;color:var(--dsw-alias-label-secondary,light-dark(#666,#a1a1aa))}\n.dsh-bridge-body{padding:14px}.dsh-bridge-copy{font-size:13px;line-height:1.55;color:var(--dsw-alias-label-secondary,light-dark(#5f6368,#b4b4bd))}\n.dsh-bridge-toolbar{display:flex;align-items:center;gap:10px;margin-bottom:10px;flex-wrap:wrap}.dsh-bridge-tabs{display:inline-flex;flex-shrink:0;padding:2px;border-radius:8px;background:var(--dsw-alias-background-tertiary,light-dark(#f1f2f4,#29292e))}\n.dsh-bridge-button,.dsh-bridge-tab{border:0;border-radius:7px;font:600 12px/1 -apple-system,BlinkMacSystemFont,\"Segoe UI\",sans-serif;cursor:pointer;transition:background-color .15s ease,color .15s ease,transform .1s ease}\n.dsh-bridge-tab{padding:7px 10px;background:transparent;color:var(--dsw-alias-label-secondary,light-dark(#666,#a1a1aa))}.dsh-bridge-tab[aria-selected=true]{background:var(--dsw-alias-background-primary,light-dark(#fff,#3a3a40));color:var(--dsw-alias-label-primary,light-dark(#171717,#f4f4f5));box-shadow:0 1px 2px rgba(0,0,0,.18)}\n.dsh-bridge-button{padding:8px 11px;background:var(--dsw-alias-background-tertiary,light-dark(#f1f2f4,#303036));color:var(--dsw-alias-label-primary,light-dark(#171717,#f4f4f5))}.dsh-bridge-button[data-primary=true]{background:var(--dsw-alias-state-business-primary,light-dark(#2869d8,#4f7ee8));color:#fff}.dsh-bridge-button:disabled{cursor:not-allowed;opacity:.55}.dsh-bridge-button:not(:disabled):active{transform:translateY(1px)}\n.dsh-bridge-actions{display:flex;gap:8px;flex-wrap:wrap;margin-left:auto}.dsh-bridge-panel{box-sizing:border-box;max-height:min(56vh,520px);overflow:auto;overscroll-behavior:contain;scrollbar-gutter:stable;padding:14px;border:1px solid var(--dsw-alias-border-subtle,light-dark(#e3e5e8,#3f3f46));border-radius:9px;background:var(--dsw-alias-background-primary,light-dark(#fff,#18181b))}\n.dsh-bridge-preview{min-width:0}.dsh-bridge-markdown-editor,.dsh-bridge-text-editor,.dsh-bridge-list-input{box-sizing:border-box;width:100%;border:1px solid var(--dsw-alias-border-strong,light-dark(#c8ccd2,#52525b));border-radius:8px;outline:none;background:var(--dsw-alias-background-primary,light-dark(#fff,#202024));color:var(--dsw-alias-label-primary,light-dark(#171717,#f4f4f5))}\n.dsh-bridge-markdown-editor{min-height:360px;resize:vertical;padding:13px 14px;font:12px/1.65 ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;tab-size:2}.dsh-bridge-text-editor{min-height:92px;resize:vertical;padding:10px 11px;font:13px/1.55 -apple-system,BlinkMacSystemFont,\"Segoe UI\",sans-serif}.dsh-bridge-list-input{min-width:0;min-height:34px;resize:vertical;padding:9px 10px;font:13px/1.4 -apple-system,BlinkMacSystemFont,\"Segoe UI\",sans-serif}\n.dsh-bridge-markdown-editor:focus,.dsh-bridge-text-editor:focus,.dsh-bridge-list-input:focus{border-color:var(--dsw-alias-state-business-primary,#2869d8);box-shadow:0 0 0 3px color-mix(in srgb,var(--dsw-alias-state-business-primary,#2869d8) 18%,transparent)}\n.dsh-bridge-form{display:grid;gap:14px}.dsh-bridge-field{display:grid;gap:7px}.dsh-bridge-field-head{display:flex;align-items:center;justify-content:space-between;gap:8px}.dsh-bridge-field-label{font-size:12px;font-weight:700;color:var(--dsw-alias-label-primary,light-dark(#171717,#f4f4f5))}.dsh-bridge-field-help{font-size:11px;color:var(--dsw-alias-label-tertiary,light-dark(#85898f,#a1a1aa))}\n.dsh-bridge-list{display:grid;gap:7px}.dsh-bridge-list-row{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:7px;align-items:center}.dsh-bridge-list-button{align-self:center;padding:8px 9px}.dsh-bridge-add-button{justify-self:start}.dsh-bridge-appendix{display:grid;gap:7px;padding-top:12px;border-top:1px solid var(--dsw-alias-border-subtle,light-dark(#e3e5e8,#3f3f46))}.dsh-bridge-appendix-copy{font-size:11px;color:var(--dsw-alias-label-tertiary,light-dark(#85898f,#a1a1aa))}\n.dsh-bridge-notice{padding:12px;border-radius:8px;background:var(--dsw-alias-background-secondary,light-dark(#f7f8fa,#29292e));font-size:12px;line-height:1.55;color:var(--dsw-alias-label-secondary,light-dark(#5f6368,#b4b4bd))}.dsh-bridge-notice-actions{display:flex;gap:8px;flex-wrap:wrap;margin-top:10px}.dsh-bridge-draft-notice{display:flex;align-items:center;justify-content:space-between;gap:10px;margin-bottom:10px;padding:9px 10px;border-radius:8px;background:var(--dsw-alias-state-warn-secondary,light-dark(#fff5d8,#443814));color:var(--dsw-alias-state-warn-primary,light-dark(#785a00,#f3d36b));font-size:12px}.dsh-bridge-draft-notice .dsh-bridge-actions{margin-left:0}\n.dsh-bridge-meta{display:flex;gap:8px;flex-wrap:wrap;margin-top:10px;color:var(--dsw-alias-label-tertiary,light-dark(#85898f,#a1a1aa));font-size:11px}.dsh-bridge-chip{padding:4px 7px;border-radius:999px;background:var(--dsw-alias-background-tertiary,light-dark(#f2f3f5,#29292e))}\n.dsh-bridge-warning,.dsh-bridge-error{margin-top:10px;padding:9px 10px;border-radius:8px;font-size:12px;line-height:1.45}.dsh-bridge-warning{background:var(--dsw-alias-state-warn-secondary,light-dark(#fff5d8,#443814));color:var(--dsw-alias-state-warn-primary,light-dark(#785a00,#f3d36b))}.dsh-bridge-error{background:var(--dsw-alias-state-error-secondary,light-dark(#ffe9e7,#4a2325));color:var(--dsw-alias-state-error-primary,light-dark(#b3261e,#ffaaa4));white-space:pre-wrap}\n.dsh-bridge-progress{height:3px;margin-top:12px;border-radius:999px;overflow:hidden;background:var(--dsw-alias-background-tertiary,light-dark(#eceef1,#303036))}.dsh-bridge-progress::after{content:\"\";display:block;width:42%;height:100%;border-radius:inherit;background:var(--dsw-alias-state-business-primary,light-dark(#2869d8,#6d92ff));animation:dsh-bridge-scan 1.35s ease-in-out infinite}\n.dsh-bridge-success{display:grid;gap:10px}.dsh-bridge-session{padding:10px;border-radius:8px;background:var(--dsw-alias-state-success-secondary,light-dark(#e8f7ed,#183a26));font:12px/1.45 ui-monospace,SFMono-Regular,Menlo,monospace;overflow-wrap:anywhere}.dsh-bridge-status{min-height:18px;font-size:11px;color:var(--dsw-alias-label-tertiary,light-dark(#85898f,#a1a1aa))}\n.dsh-bridge-button:focus-visible,.dsh-bridge-tab:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary,#2869d8);outline-offset:2px}@keyframes dsh-bridge-scan{0%{transform:translateX(-110%)}100%{transform:translateX(340%)}}\n@media(max-width:640px){.dsh-bridge-head{align-items:flex-start;flex-wrap:wrap;padding-block:10px}.dsh-bridge-route{width:100%;padding-left:32px}.dsh-bridge-toolbar{align-items:stretch;flex-direction:column}.dsh-bridge-tabs{align-self:flex-start;max-width:100%;overflow-x:auto}.dsh-bridge-panel{max-height:52vh;padding:11px}.dsh-bridge-actions{width:100%;margin-left:0}.dsh-bridge-toolbar>.dsh-bridge-actions .dsh-bridge-button{flex:1}.dsh-bridge-draft-notice{align-items:flex-start;flex-direction:column}.dsh-bridge-list-row{grid-template-columns:minmax(0,1fr)}}\n@media(prefers-reduced-motion:reduce){.dsh-bridge-progress::after{animation:none;width:65%}.dsh-bridge-button,.dsh-bridge-tab{transition:none}}\n`\n\ninterface BridgeInjected {\n readonly execute: (sessionId: SessionId, line: string) => Promise<BridgeOutcome>\n readonly openSession: (sessionId: SessionId) => Promise<void>\n}\n\ninterface CommandRemote {\n execute(sessionId: SessionId, line: string, images: readonly unknown[]): Promise<{\n ok: boolean\n value?: { result: BridgeOutcome }\n error?: { code: string; message: string }\n }>\n}\n\ntype BridgeCommandCardProps = CommandRowProps & BridgeInjected\n\nconst COPY = {\n zh: {\n title: '会话迁移', preparing: '正在生成可编辑的交接摘要', safe: '原会话不会被修改',\n preview: '预览', text: '文本编辑', markdownSource: 'Markdown', copy: '复制摘要', copied: '已复制', confirm: '确认迁移',\n confirming: '正在创建目标会话…', open: '打开目标会话', opening: '正在打开目标会话…',\n json: 'JSON 结构', markdownPreview: 'Markdown 预览', markdownEditor: '交接摘要 Markdown 编辑器', chars: '字符',\n listHelp: '每行一项,无需输入 Markdown 符号', addItem: '添加一项', removeItem: '删除此项',\n appendix: '附录(只读)', appendixHelp: '视觉证据与未解析图片会原样保留;需要修改请切换到 Markdown。',\n textUnavailable: '这份摘要不是可无损转换的标准五段格式。内容没有被修改,请使用 Markdown 编辑。',\n editMarkdown: '使用 Markdown', newPreview: '检测到新的预览;当前编辑稿不会被自动覆盖。',\n keepDraft: '保留编辑稿', loadPreview: '加载新预览', renderFailure: 'Bridge 卡片渲染失败;其他插件和会话不受影响。',\n tooLong: `摘要超过 WebUI 的 ${MAX_EDITED_SUMMARY_CHARS.toLocaleString()} 字符安全上限,请使用摘要文件回退。`,\n fileFallback: '摘要文件', stalePreview: '这张旧预览没有安全确认标识。请重新运行 /bridge 生成预览,或使用摘要文件流程。',\n },\n en: {\n title: 'Session handoff', preparing: 'Generating an editable handoff preview', safe: 'The source session stays untouched',\n preview: 'Preview', text: 'Text', markdownSource: 'Markdown', copy: 'Copy summary', copied: 'Copied', confirm: 'Confirm migration',\n confirming: 'Creating the target session…', open: 'Open target session', opening: 'Opening target session…',\n json: 'JSON structure', markdownPreview: 'Markdown preview', markdownEditor: 'Handoff summary Markdown editor', chars: 'chars',\n listHelp: 'One item per line; no Markdown markers needed', addItem: 'Add item', removeItem: 'Remove item',\n appendix: 'Appendix (read only)', appendixHelp: 'Visual evidence and unresolved images stay exact; use Markdown to edit them.',\n textUnavailable: 'This handoff is not a losslessly editable five-section document. Nothing changed; use Markdown instead.',\n editMarkdown: 'Use Markdown', newPreview: 'A newer preview arrived. Your draft was not overwritten.',\n keepDraft: 'Keep draft', loadPreview: 'Load new preview', renderFailure: 'The Bridge card failed to render. Other plugins and sessions are unaffected.',\n tooLong: `The handoff exceeds the ${MAX_EDITED_SUMMARY_CHARS.toLocaleString()}-character WebUI safety limit. Use the summary-file fallback.`,\n fileFallback: 'Summary file', stalePreview: 'This older preview has no secure confirmation ID. Run /bridge again or use the summary-file workflow.',\n },\n} as const\n\nconst PRIMITIVE_LABELS = {\n zh: {\n markdown: {\n code: { copyLabel: '复制', copiedLabel: '已复制' },\n footnotes: '脚注',\n },\n json: {\n copyValue: '复制值', copyJson: '复制 JSON', copyPath: '复制属性路径',\n copyPrettyJson: '复制格式化 JSON', copyCompactJson: '复制紧凑 JSON',\n copied: '已复制', copyFailed: '复制失败',\n collapseNode: '折叠 JSON 节点', expandNode: '展开 JSON 节点',\n copyButtonTitle: (action: string) => `${action};右键查看更多复制选项`,\n },\n },\n en: {\n markdown: {\n code: { copyLabel: 'Copy', copiedLabel: 'Copied' },\n footnotes: 'Footnotes',\n },\n json: {\n copyValue: 'Copy value', copyJson: 'Copy JSON', copyPath: 'Copy property path',\n copyPrettyJson: 'Copy pretty JSON', copyCompactJson: 'Copy compact JSON',\n copied: 'Copied', copyFailed: 'Copy failed',\n collapseNode: 'Collapse JSON node', expandNode: 'Expand JSON node',\n copyButtonTitle: (action: string) => `${action}; right-click for copy options`,\n },\n },\n} satisfies Record<'zh' | 'en', { markdown: MarkdownLabels; json: JsonTreeLabels }>\n\nfunction Header({ lang, route }: { lang: 'zh' | 'en'; route?: string }) {\n return <div className=\"dsh-bridge-head\">\n <span className=\"dsh-bridge-mark\" aria-hidden>B</span>\n <span className=\"dsh-bridge-title\">{COPY[lang].title}</span>\n {route ? <span className=\"dsh-bridge-route\">{route}</span> : null}\n </div>\n}\n\nfunction RunningCard() {\n const lang = uiLanguageOf(typeof document === 'undefined' ? undefined : document.documentElement.lang)\n const copy = COPY[lang]\n const [seconds, setSeconds] = useState(0)\n useEffect(() => {\n const started = Date.now()\n const timer = window.setInterval(() => { setSeconds(Math.floor((Date.now() - started) / 1000)) }, 1000)\n return () => { window.clearInterval(timer) }\n }, [])\n return <div className=\"dsh-bridge-card\" aria-live=\"polite\">\n <Header lang={lang} />\n <div className=\"dsh-bridge-body\">\n <div className=\"dsh-bridge-copy\">{copy.preparing} · {seconds}s</div>\n <div className=\"dsh-bridge-status\">{copy.safe}</div>\n <div className=\"dsh-bridge-progress\" aria-hidden />\n </div>\n </div>\n}\n\nfunction SummaryView({ summary, lang }: { summary: string; lang: 'zh' | 'en' }) {\n const json = useMemo(() => parseJsonDocument(summary), [summary])\n return <div className=\"dsh-bridge-preview\" aria-label={json === undefined ? COPY[lang].markdownPreview : COPY[lang].json}>\n {json === undefined\n ? <MarkdownText text={summary} labels={PRIMITIVE_LABELS[lang].markdown} />\n : <JsonTree data={json} label={COPY[lang].json} labels={PRIMITIVE_LABELS[lang].json} />}\n </div>\n}\n\nfunction TextListEditor({ lang, onAppend, onChange, onRemove, section }: {\n lang: 'zh' | 'en'\n onAppend: (value: string) => boolean\n onChange: (index: number, value: string) => void\n onRemove: (index: number) => void\n section: BridgeTextSection\n}) {\n const copy = COPY[lang]\n const items = section.items ?? []\n const [draftRows, setDraftRows] = useState<string[]>([])\n const [itemDrafts, setItemDrafts] = useState<Record<number, string>>({})\n const removeDraft = (index: number) => { setDraftRows((current) => current.filter((_, itemIndex) => itemIndex !== index)) }\n return <div className=\"dsh-bridge-list\">\n {items.map((item, index) => <div className=\"dsh-bridge-list-row\" key={`${section.key}-${item.itemStart}`}>\n <textarea\n aria-label={`${section.label} ${index + 1}`}\n className=\"dsh-bridge-list-input\"\n maxLength={MAX_EDITED_SUMMARY_CHARS}\n rows={Math.min(4, item.text.split(/\\r\\n|\\n|\\r/gu).length)}\n value={itemDrafts[index] ?? item.text}\n onChange={(event) => {\n const value = event.currentTarget.value\n setItemDrafts((current) => ({ ...current, [index]: value }))\n if (value) onChange(index, value)\n }}\n onBlur={() => {\n if (itemDrafts[index] === '') onRemove(index)\n setItemDrafts((current) => {\n const next = { ...current }\n delete next[index]\n return next\n })\n }}\n spellCheck\n />\n <button\n aria-label={`${copy.removeItem}: ${section.label} ${index + 1}`}\n className=\"dsh-bridge-button dsh-bridge-list-button\"\n type=\"button\"\n onPointerDown={(event) => { event.preventDefault() }}\n onClick={() => {\n onRemove(index)\n }}\n >−</button>\n </div>)}\n {draftRows.map((item, index) => <div className=\"dsh-bridge-list-row\" key={`${section.key}-draft-${index}`}>\n <textarea\n aria-label={`${section.label} ${items.length + index + 1}`}\n autoFocus={index === draftRows.length - 1}\n className=\"dsh-bridge-list-input\"\n maxLength={MAX_EDITED_SUMMARY_CHARS}\n rows={1}\n value={item}\n onChange={(event) => {\n const value = event.currentTarget.value\n setDraftRows((current) => current.map((row, rowIndex) => rowIndex === index ? value : row))\n }}\n onBlur={() => {\n if (!item.trim() || onAppend(item)) removeDraft(index)\n }}\n spellCheck\n />\n <button\n aria-label={`${copy.removeItem}: ${section.label} ${items.length + index + 1}`}\n className=\"dsh-bridge-button dsh-bridge-list-button\"\n type=\"button\"\n onPointerDown={(event) => { event.preventDefault() }}\n onClick={() => { removeDraft(index) }}\n >−</button>\n </div>)}\n <button\n className=\"dsh-bridge-button dsh-bridge-add-button\"\n type=\"button\"\n onClick={() => { setDraftRows((current) => [...current, '']) }}\n aria-label={`${copy.addItem}: ${section.label}`}\n >+ {copy.addItem}</button>\n </div>\n}\n\nfunction TextHandoffEditor({ idPrefix, lang, onChange, onError, projection }: {\n idPrefix: string\n lang: 'zh' | 'en'\n onChange: (summary: string) => boolean\n onError: (message: string) => void\n projection: BridgeTextProjection\n}) {\n const copy = COPY[lang]\n const safelyApply = (operation: () => string): boolean => {\n try {\n onError('')\n return onChange(operation())\n } catch (cause) {\n onError(cause instanceof Error ? cause.message : String(cause))\n return false\n }\n }\n const updateSection = (section: BridgeTextSection, value: string) => {\n safelyApply(() => replaceBridgeTextSection(projection, section.key, value))\n }\n return <div className=\"dsh-bridge-form\">\n {projection.sections.map((section) => <div\n aria-labelledby={section.kind === 'list' ? `${idPrefix}-${section.key}-label` : undefined}\n className=\"dsh-bridge-field\"\n key={section.key}\n role={section.kind === 'list' ? 'group' : undefined}\n >\n <div className=\"dsh-bridge-field-head\">\n {section.kind === 'text'\n ? <label className=\"dsh-bridge-field-label\" htmlFor={`${idPrefix}-${section.key}`}>{section.label}</label>\n : <div className=\"dsh-bridge-field-label\" id={`${idPrefix}-${section.key}-label`}>{section.label}</div>}\n {section.kind === 'list' ? <span className=\"dsh-bridge-field-help\">{copy.listHelp}</span> : null}\n </div>\n {section.kind === 'text'\n ? <textarea\n className=\"dsh-bridge-text-editor\"\n id={`${idPrefix}-${section.key}`}\n maxLength={MAX_EDITED_SUMMARY_CHARS}\n value={section.text}\n onChange={(event) => { updateSection(section, event.currentTarget.value) }}\n spellCheck\n />\n : <TextListEditor\n lang={lang}\n section={section}\n onAppend={(value) => safelyApply(() => appendBridgeTextListItem(projection, section.key, value))}\n onChange={(index, value) => { safelyApply(() => replaceBridgeTextListItem(projection, section.key, index, value)) }}\n onRemove={(index) => { safelyApply(() => removeBridgeTextListItem(projection, section.key, index)) }}\n />}\n </div>)}\n {projection.opaqueSuffix\n ? <div className=\"dsh-bridge-appendix\">\n <div><div className=\"dsh-bridge-field-label\">{copy.appendix}</div><div className=\"dsh-bridge-appendix-copy\">{copy.appendixHelp}</div></div>\n <SummaryView summary={projection.opaqueSuffix} lang={lang} />\n </div>\n : null}\n </div>\n}\n\ntype EditorMode = 'preview' | 'text' | 'markdown'\nconst EDITOR_MODES: readonly EditorMode[] = ['preview', 'text', 'markdown']\n\nfunction PreviewCard({ card, execute, openSession, sessionId }: {\n card: Extract<BridgeCard, { phase: 'preview' }>\n execute: BridgeInjected['execute']\n openSession: BridgeInjected['openSession']\n sessionId: SessionId\n}) {\n const copy = COPY[card.lang]\n const panelId = useId()\n const [mode, setMode] = useState<EditorMode>('preview')\n const [summary, setSummary] = useState(card.summary)\n const [busy, setBusy] = useState(false)\n const [status, setStatus] = useState('')\n const [error, setError] = useState('')\n const [pendingSummary, setPendingSummary] = useState<string | null>(null)\n const [created, setCreated] = useState<Extract<BridgeCard, { phase: 'migrated' }> | null>(null)\n const lastCardSummary = useRef(card.summary)\n const confirming = useRef(false)\n const tooLong = summary.length > MAX_EDITED_SUMMARY_CHARS\n const textProjection = useMemo(() => tooLong ? undefined : parseBridgeTextProjection(summary), [summary, tooLong])\n const updateSummary = (next: string) => {\n if (next.length > MAX_EDITED_SUMMARY_CHARS) {\n setError(copy.tooLong)\n return false\n }\n setError('')\n setSummary(next)\n return true\n }\n\n useEffect(() => {\n const prior = lastCardSummary.current\n if (card.summary === prior) return\n lastCardSummary.current = card.summary\n if (summary === prior) {\n setSummary(card.summary)\n setPendingSummary(null)\n } else {\n setPendingSummary(card.summary)\n }\n }, [card.summary, summary])\n\n const copySummary = async () => {\n try {\n await navigator.clipboard.writeText(summary)\n setError('')\n setStatus(copy.copied)\n } catch (cause) {\n setStatus('')\n setError(cause instanceof Error ? cause.message : String(cause))\n }\n }\n\n const confirm = async () => {\n if (confirming.current) return\n confirming.current = true\n setBusy(true)\n setError('')\n setStatus(copy.confirming)\n try {\n const outcome = await execute(sessionId, buildBridgeMigrationCommand(card.targetPreset, summary, card.lang, card.previewId ?? ''))\n const result = parseBridgeCard(outcome)\n if (result.phase === 'error') throw new Error(result.text)\n if (result.phase !== 'migrated') throw new Error(card.lang === 'en' ? 'The host returned no target session.' : '宿主没有返回目标会话。')\n setCreated(result)\n setStatus(copy.opening)\n await openSession(result.sessionId)\n } catch (cause) {\n setError(cause instanceof Error ? cause.message : String(cause))\n setStatus('')\n } finally {\n confirming.current = false\n setBusy(false)\n }\n }\n\n if (created) return <MigratedCard card={created} openSession={openSession} status={status} error={error} />\n\n return <div className=\"dsh-bridge-card\">\n <Header lang={card.lang} route={`${card.sourcePreset} → ${card.targetPreset}`} />\n <div className=\"dsh-bridge-body\">\n <div className=\"dsh-bridge-toolbar\">\n <div\n className=\"dsh-bridge-tabs\"\n role=\"tablist\"\n aria-label={copy.title}\n onKeyDown={(event) => {\n if (!['ArrowLeft', 'ArrowRight', 'Home', 'End'].includes(event.key)) return\n event.preventDefault()\n const current = EDITOR_MODES.indexOf(mode)\n const next = event.key === 'Home'\n ? 0\n : event.key === 'End'\n ? EDITOR_MODES.length - 1\n : (current + (event.key === 'ArrowRight' ? 1 : -1) + EDITOR_MODES.length) % EDITOR_MODES.length\n const nextMode = EDITOR_MODES[next] ?? 'preview'\n setMode(nextMode)\n window.requestAnimationFrame(() => { document.getElementById(`${panelId}-${nextMode}`)?.focus() })\n }}\n >\n {([\n ['preview', copy.preview],\n ['text', copy.text],\n ['markdown', copy.markdownSource],\n ] as const).map(([value, label]) => <button\n aria-controls={panelId}\n aria-selected={mode === value}\n className=\"dsh-bridge-tab\"\n id={`${panelId}-${value}`}\n key={value}\n role=\"tab\"\n tabIndex={mode === value ? 0 : -1}\n type=\"button\"\n onClick={() => { setMode(value) }}\n >{label}</button>)}\n </div>\n <div className=\"dsh-bridge-actions\">\n <button className=\"dsh-bridge-button\" type=\"button\" onClick={() => { void copySummary() }}>{copy.copy}</button>\n <button className=\"dsh-bridge-button\" data-primary type=\"button\" disabled={busy || !card.previewId || summary.trim() === '' || tooLong} onClick={() => { void confirm() }}>{busy ? copy.confirming : copy.confirm}</button>\n </div>\n </div>\n {pendingSummary !== null\n ? <div className=\"dsh-bridge-draft-notice\" role=\"status\">\n <span>{copy.newPreview}</span>\n <div className=\"dsh-bridge-actions\">\n <button className=\"dsh-bridge-button\" type=\"button\" onClick={() => { setPendingSummary(null) }}>{copy.keepDraft}</button>\n <button className=\"dsh-bridge-button\" type=\"button\" onClick={() => { setSummary(pendingSummary); setPendingSummary(null) }}>{copy.loadPreview}</button>\n </div>\n </div>\n : null}\n <div aria-labelledby={`${panelId}-${mode}`} className=\"dsh-bridge-panel\" id={panelId} role=\"tabpanel\">\n {tooLong\n ? <div className=\"dsh-bridge-notice\" role=\"alert\">{copy.tooLong}{card.summaryFile ? <><br /><strong>{copy.fileFallback}:</strong> <code>{card.summaryFile}</code></> : null}</div>\n : mode === 'preview'\n ? <SummaryView summary={summary} lang={card.lang} />\n : mode === 'text'\n ? textProjection\n ? <TextHandoffEditor\n idPrefix={panelId}\n lang={card.lang}\n projection={textProjection}\n onChange={updateSummary}\n onError={setError}\n />\n : <div className=\"dsh-bridge-notice\" role=\"status\">\n {copy.textUnavailable}\n <div className=\"dsh-bridge-notice-actions\"><button className=\"dsh-bridge-button\" type=\"button\" onClick={() => { setMode('markdown') }}>{copy.editMarkdown}</button></div>\n </div>\n : <textarea className=\"dsh-bridge-markdown-editor\" aria-label={copy.markdownEditor} maxLength={MAX_EDITED_SUMMARY_CHARS} value={summary} onChange={(event) => { updateSummary(event.currentTarget.value) }} spellCheck={false} />}\n </div>\n <div className=\"dsh-bridge-meta\">\n {card.stats ? <span className=\"dsh-bridge-chip\">{card.stats}</span> : null}\n <span className=\"dsh-bridge-chip\">{summary.length.toLocaleString()} {copy.chars}</span>\n </div>\n {card.warnings.map((warning) => <div className=\"dsh-bridge-warning\" key={warning}>⚠ {warning}</div>)}\n {!card.previewId ? <div className=\"dsh-bridge-warning\">⚠ {copy.stalePreview}</div> : null}\n {status ? <div className=\"dsh-bridge-status\" aria-live=\"polite\">{status}</div> : null}\n {error ? <div className=\"dsh-bridge-error\" role=\"alert\">{error}</div> : null}\n </div>\n </div>\n}\n\nfunction MigratedCard({ card, error = '', openSession, status = '' }: {\n card: Extract<BridgeCard, { phase: 'migrated' }>\n error?: string\n openSession: BridgeInjected['openSession']\n status?: string\n}) {\n const copy = COPY[card.lang]\n const [opening, setOpening] = useState(false)\n const [localError, setLocalError] = useState(error)\n const open = async () => {\n setOpening(true)\n setLocalError('')\n try { await openSession(card.sessionId) } catch (cause) { setLocalError(cause instanceof Error ? cause.message : String(cause)) } finally { setOpening(false) }\n }\n return <div className=\"dsh-bridge-card\">\n <Header lang={card.lang} route={`→ ${card.targetPreset}`} />\n <div className=\"dsh-bridge-body dsh-bridge-success\">\n <div className=\"dsh-bridge-session\"><strong>{card.title}</strong><br />{card.sessionId}</div>\n {card.details.map((detail) => <div className=\"dsh-bridge-copy\" key={detail}>{detail}</div>)}\n <div className=\"dsh-bridge-actions\"><button className=\"dsh-bridge-button\" data-primary type=\"button\" disabled={opening} onClick={() => { void open() }}>{opening ? copy.opening : copy.open}</button></div>\n {status ? <div className=\"dsh-bridge-status\" aria-live=\"polite\">{status}</div> : null}\n {card.warnings.map((warning) => <div className=\"dsh-bridge-warning\" key={warning}>⚠ {warning}</div>)}\n {localError ? <div className=\"dsh-bridge-error\" role=\"alert\">{localError}</div> : null}\n </div>\n </div>\n}\n\nfunction MessageCard({ card }: { card: Extract<BridgeCard, { phase: 'message' | 'error' }> }) {\n const lang = card.phase === 'message' ? card.lang : (/[㐀-鿿]/u.test(card.text) ? 'zh' : 'en')\n return <div className=\"dsh-bridge-card\"><Header lang={lang} /><div className=\"dsh-bridge-body\">\n <div className=\"dsh-bridge-panel\">{card.phase === 'error' ? <div className=\"dsh-bridge-error\" role=\"alert\">{card.text}</div> : <SummaryView summary={card.text} lang={card.lang} />}</div>\n </div></div>\n}\n\nclass BridgeCardBoundary extends Component<{ children: ReactNode; lang: 'zh' | 'en' }, { failed: boolean }> {\n state = { failed: false }\n\n static getDerivedStateFromError(): { failed: boolean } {\n return { failed: true }\n }\n\n componentDidCatch(error: Error, info: ErrorInfo): void {\n console.error('dsh-plugin-bridge card render failed', error, info.componentStack)\n }\n\n render(): ReactNode {\n if (!this.state.failed) return this.props.children\n return <div className=\"dsh-bridge-card\"><Header lang={this.props.lang} /><div className=\"dsh-bridge-body\">\n <div className=\"dsh-bridge-error\" role=\"alert\">{COPY[this.props.lang].renderFailure}</div>\n </div></div>\n }\n}\n\nfunction BridgeCommandCardContent({ node, execute, openSession, sessionId }: BridgeCommandCardProps) {\n const card = useMemo(() => parseBridgeCard(node.outcome), [node.outcome])\n if (card.phase === 'running') return <RunningCard />\n if (card.phase === 'preview') return <PreviewCard card={card} execute={execute} openSession={openSession} sessionId={sessionId} />\n if (card.phase === 'migrated') return <MigratedCard card={card} openSession={openSession} />\n return <MessageCard card={card} />\n}\n\n/** Rich renderer for the durable command lifecycle keyed by name and isolated from every other plugin. */\nexport function BridgeCommandCard(props: BridgeCommandCardProps) {\n const lang = uiLanguageOf(typeof document === 'undefined' ? undefined : document.documentElement.lang)\n const outcomeKey = props.node.outcome === null ? 'running' : `${props.node.outcome.kind}:${props.node.outcome.text ?? ''}`\n return <BridgeCardBoundary key={outcomeKey} lang={lang}><BridgeCommandCardContent {...props} /></BridgeCardBoundary>\n}\n\nasync function openWhenVisible(ctx: ClientContext, sessionId: SessionId): Promise<void> {\n if (ctx.sessions.list.getSnapshot().byId[sessionId] !== undefined) {\n ctx.sessions.open(sessionId)\n return\n }\n await new Promise<void>((resolve, reject) => {\n let dispose = () => {}\n const timeout = window.setTimeout(() => {\n dispose()\n reject(new Error(`Target session ${sessionId} has not reached this browser yet.`))\n }, 5_000)\n dispose = ctx.sessions.list.subscribe(() => {\n if (ctx.sessions.list.getSnapshot().byId[sessionId] === undefined) return\n window.clearTimeout(timeout)\n dispose()\n resolve()\n })\n })\n ctx.sessions.open(sessionId)\n}\n\n/** Client services are supplied by the official WebUI module table. */\n// rc.2 guards the parent `remote` face separately from its `remote.commands`\n// capability; older compatible builds tolerate the redundant parent seat.\nexport const inject = ['slots', 'sessions', 'remote', 'remote.commands']\n\nexport function apply(ctx: ClientContext): void {\n const commands = (ctx as unknown as { remote: { commands: CommandRemote } }).remote.commands\n ctx.effect(() => {\n const prior = document.querySelector(`style[data-plugin-css=\"${STYLE_ID}\"]`)\n if (prior !== null) return () => {}\n const style = document.createElement('style')\n style.dataset.plugin = 'dsh-plugin-bridge'\n style.dataset.pluginCss = STYLE_ID\n style.textContent = STYLE\n document.head.append(style)\n return () => { style.remove() }\n }, 'bridge: native card styles')\n ctx.slots.inject('conversation.chat.commandview', () => ctx.slots.register({\n name: 'conversation.chat.commandview',\n key: 'bridge',\n inject: (): BridgeInjected => ({\n execute: async (sessionId, line) => {\n const result = await commands.execute(sessionId, line, [])\n if (!result.ok) throw new Error(`${result.error?.code ?? 'command-failed'}: ${result.error?.message ?? 'The host rejected the command.'}`)\n if (result.value === undefined) throw new Error('The /bridge command was not admitted by the host.')\n return result.value.result\n },\n openSession: (sessionId) => openWhenVisible(ctx, sessionId),\n }),\n }, BridgeCommandCard))\n}\n"],"mappings":"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"}
@@ -58,7 +58,7 @@ type ContextLike = AlphaServices & {
58
58
  };
59
59
  /** Probe the real alpha services instead of the adapter's always-present closures. */
60
60
  export declare function probeDshAlphaHost(input: ContextLike): BridgeHostProbe[];
61
- /** Create the semantic BridgeHost over DSH v0.1.2 typed Host controllers. */
61
+ /** Create the semantic BridgeHost over DSH typed Host controllers. */
62
62
  export declare function createDshAlphaHost(input: ContextLike, signal?: AbortSignal): BridgeHost;
63
63
  /** Prefer the stable rc.2 path when present; otherwise use alpha controllers. */
64
64
  export declare function resolveDshHost(input: ContextLike, signal?: AbortSignal): BridgeHost;
@@ -1,10 +1,10 @@
1
1
  /**
2
- * DSH v0.1.2 alpha typed-controller adapter.
2
+ * DSH v0.1.2/v0.1.3 typed-controller adapter.
3
3
  *
4
4
  * The alpha removed the legacy ApiProxy service. Keep that product change at
5
5
  * this boundary: migration code continues to consume BridgeHost, while this
6
- * adapter talks to the Host controllers structurally so the package can still
7
- * be built against the current rc.2 SDK.
6
+ * adapter talks to the Host controllers structurally while the browser half
7
+ * builds against the current client SDK.
8
8
  */
9
9
  import { randomUUID } from 'node:crypto';
10
10
  import { createApiProxyHost, probeApiProxy } from './api-rpc.js';
@@ -117,11 +117,23 @@ function currentModel(row) {
117
117
  };
118
118
  }
119
119
  function paginateHistory(events, beforeSeq, maxMessages) {
120
- const visible = beforeSeq === undefined ? [...events] : events.filter(event => (event.seq ?? -1) < beforeSeq);
120
+ // Snapshot events are ordered. Locate the cursor without copying/scanning
121
+ // the entire prefix on every page; only allocate the returned window.
122
+ let end = events.length;
123
+ if (beforeSeq !== undefined) {
124
+ let low = 0;
125
+ while (low < end) {
126
+ const middle = Math.floor((low + end) / 2);
127
+ if ((events[middle]?.seq ?? -1) < beforeSeq)
128
+ low = middle + 1;
129
+ else
130
+ end = middle;
131
+ }
132
+ }
121
133
  let count = 0;
122
134
  let cut = 0;
123
- for (let index = visible.length - 1; index >= 0; index -= 1) {
124
- const type = visible[index]?.type;
135
+ for (let index = end - 1; index >= 0; index -= 1) {
136
+ const type = events[index]?.type;
125
137
  if (type !== 'user/message' && type !== 'assistant/message')
126
138
  continue;
127
139
  count += 1;
@@ -131,7 +143,7 @@ function paginateHistory(events, beforeSeq, maxMessages) {
131
143
  }
132
144
  }
133
145
  return {
134
- events: visible.slice(cut).map(event => ({ event })),
146
+ events: events.slice(cut, end).map(event => ({ event })),
135
147
  hasMore: cut > 0,
136
148
  };
137
149
  }
@@ -151,13 +163,13 @@ export function probeDshAlphaHost(input) {
151
163
  available: typeof ALPHA_METHODS[method]?.(services) === 'function',
152
164
  }));
153
165
  }
154
- /** Create the semantic BridgeHost over DSH v0.1.2 typed Host controllers. */
166
+ /** Create the semantic BridgeHost over DSH typed Host controllers. */
155
167
  export function createDshAlphaHost(input, signal) {
156
168
  const services = servicesOf(input);
157
169
  const controller = services.sessionController;
158
170
  const abort = signal ?? new AbortController().signal;
159
171
  const host = {
160
- descriptor: Object.freeze({ id: 'dsh-typed-controllers', version: '0.1.2-alpha', transport: 'in-process' }),
172
+ descriptor: Object.freeze({ id: 'dsh-typed-controllers', transport: 'in-process' }),
161
173
  sessions: Object.freeze({
162
174
  list: async (request = {}) => {
163
175
  const list = required('session.list', controller?.list);
@@ -173,6 +185,11 @@ export function createDshAlphaHost(input, signal) {
173
185
  const value = await invoke('session.history', () => inspect.call(controller, request.sessionId, abort));
174
186
  return paginateHistory(value.events, request.beforeSeq, request.maxMessages ?? 60);
175
187
  },
188
+ historyWindow: async (request) => {
189
+ const inspect = required('session.history', controller?.inspect);
190
+ const value = await invoke('session.history', () => inspect.call(controller, request.sessionId, abort));
191
+ return paginateHistory(value.events, undefined, request.maxMessages);
192
+ },
176
193
  models: async ({ sessionId }) => {
177
194
  const list = required('session.list', controller?.list);
178
195
  const catalog = required('session.models', controller?.modelCatalog);
package/lib/host.d.ts CHANGED
@@ -85,6 +85,20 @@ export interface BridgeHost {
85
85
  }[];
86
86
  hasMore?: boolean;
87
87
  }>;
88
+ /** Optional single-read window for hosts that already materialize a complete
89
+ * snapshot. Each invocation reads fresh state; readers must not cache it
90
+ * across commands or worker polls. The budget counts user/assistant message events. */
91
+ historyWindow?(input: {
92
+ sessionId: string;
93
+ maxMessages: number;
94
+ }, options?: {
95
+ timeoutMs?: number;
96
+ }): Promise<{
97
+ events?: {
98
+ event: SessionEvent;
99
+ }[];
100
+ hasMore?: boolean;
101
+ }>;
88
102
  models(input: {
89
103
  sessionId: string;
90
104
  }): Promise<SessionModels>;
package/lib/migrate.js CHANGED
@@ -151,6 +151,12 @@ export async function foldedHistory(input, sessionId, options = {}) {
151
151
  const host = asBridgeHost(input);
152
152
  const pageMessages = options.pageMessages ?? HISTORY_PAGE_MESSAGES;
153
153
  const maxPages = options.maxPages ?? HISTORY_MAX_PAGES;
154
+ if (maxPages <= 0)
155
+ return [];
156
+ if (host.sessions.historyWindow) {
157
+ const window = await host.sessions.historyWindow({ sessionId, maxMessages: pageMessages * maxPages }, { timeoutMs: 60_000 });
158
+ return foldSessionEvents((window.events ?? []).map(entry => entry.event));
159
+ }
154
160
  let events = [];
155
161
  let beforeSeq;
156
162
  for (let page = 0; page < maxPages; page += 1) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-plugin-bridge",
3
- "version": "0.3.1",
3
+ "version": "0.3.3",
4
4
  "description": "Previewable cross-preset session migration for DeepSeek Harness with bounded, fixed-schema handoffs",
5
5
  "type": "module",
6
6
  "main": "lib/index.js",
@@ -14,6 +14,7 @@
14
14
  "reports/native-workbench-2026-08-25.md",
15
15
  "reports/native-workbench-2026-08-25.raw.json",
16
16
  "reports/dsh-0.1.2-alpha.2-compat-2026-08-31.md",
17
+ "reports/dsh-0.1.3-alpha.2-compat-2026-09-08.md",
17
18
  "cordis.patch.yml",
18
19
  "README.md",
19
20
  "README.zh.md"
@@ -60,11 +61,11 @@
60
61
  },
61
62
  "peerDependencies": {
62
63
  "@deepseek-ai/cordis": "^4.0.1",
63
- "@deepseek-ai/dsh-api-remotes": "^0.1.0-rc.7 || ^0.1.1-rc.1 || ^0.1.2-alpha.1",
64
- "@deepseek-ai/dsh-client-ui-chat": "^0.1.0-rc.7 || ^0.1.1-rc.1 || ^0.1.2-alpha.1",
65
- "@deepseek-ai/dsh-client-ui-conversation": "^0.1.0-rc.7 || ^0.1.1-rc.1 || ^0.1.2-alpha.1",
66
- "@deepseek-ai/dsh-client-ui-primitives": "^0.1.0-rc.7 || ^0.1.1-rc.1 || ^0.1.2-alpha.1",
67
- "@deepseek-ai/dsh-client-ui-slots": "^0.1.0-rc.7 || ^0.1.1-rc.1 || ^0.1.2-alpha.1",
64
+ "@deepseek-ai/dsh-api-remotes": "^0.1.0-rc.7 || ^0.1.1-rc.1 || ^0.1.2-alpha.1 || ^0.1.3-alpha.2",
65
+ "@deepseek-ai/dsh-client-ui-chat": "^0.1.0-rc.7 || ^0.1.1-rc.1 || ^0.1.2-alpha.1 || ^0.1.3-alpha.2",
66
+ "@deepseek-ai/dsh-client-ui-conversation": "^0.1.0-rc.7 || ^0.1.1-rc.1 || ^0.1.2-alpha.1 || ^0.1.3-alpha.2",
67
+ "@deepseek-ai/dsh-client-ui-primitives": "^0.1.0-rc.7 || ^0.1.1-rc.1 || ^0.1.2-alpha.1 || ^0.1.3-alpha.2",
68
+ "@deepseek-ai/dsh-client-ui-slots": "^0.1.0-rc.7 || ^0.1.1-rc.1 || ^0.1.2-alpha.1 || ^0.1.3-alpha.2",
68
69
  "react": "^18.2.0"
69
70
  },
70
71
  "peerDependenciesMeta": {
@@ -81,14 +82,14 @@
81
82
  },
82
83
  "devDependencies": {
83
84
  "@deepseek-ai/cordis": "4.0.2",
84
- "@deepseek-ai/dsh-api-remotes": "^0.1.2-alpha.2",
85
- "@deepseek-ai/dsh-api-session-controller": "^0.1.2-alpha.2",
86
- "@deepseek-ai/dsh-client-ui-chat": "^0.1.2-alpha.2",
87
- "@deepseek-ai/dsh-client-ui-conversation": "^0.1.2-alpha.2",
88
- "@deepseek-ai/dsh-client-ui-primitives": "^0.1.2-alpha.2",
89
- "@deepseek-ai/dsh-client-ui-renderer": "^0.1.2-alpha.2",
90
- "@deepseek-ai/dsh-client-ui-session": "^0.1.2-alpha.2",
91
- "@deepseek-ai/dsh-client-ui-slots": "^0.1.2-alpha.2",
85
+ "@deepseek-ai/dsh-api-remotes": "0.1.3-alpha.2",
86
+ "@deepseek-ai/dsh-api-session-controller": "0.1.3-alpha.2",
87
+ "@deepseek-ai/dsh-client-ui-chat": "0.1.3-alpha.2",
88
+ "@deepseek-ai/dsh-client-ui-conversation": "0.1.3-alpha.2",
89
+ "@deepseek-ai/dsh-client-ui-primitives": "0.1.3-alpha.2",
90
+ "@deepseek-ai/dsh-client-ui-renderer": "0.1.3-alpha.2",
91
+ "@deepseek-ai/dsh-client-ui-session": "0.1.3-alpha.2",
92
+ "@deepseek-ai/dsh-client-ui-slots": "0.1.3-alpha.2",
92
93
  "@types/node": "^26.2.0",
93
94
  "@types/react": "~18.3.1",
94
95
  "react": "^18.3.1",
@@ -0,0 +1,65 @@
1
+ # DSH 0.1.3-alpha.2 compatibility and history-window acceptance
2
+
3
+ Date: 2026-09-08 (Asia/Shanghai). **Bridge 0.3.3 release acceptance**. The runtime tests used the implementation candidate based on `d2b9be2`, before its package version was bumped from 0.3.2 to 0.3.3. These results do not apply to the unchanged registry 0.3.2 package.
4
+
5
+ ## Environments and artifact
6
+
7
+ - Official npm DSH `0.1.2-rc.1`: 214 DSH packages at that version; Node 24.19.0.
8
+ - Official npm DSH `0.1.3-alpha.2`: 223 DSH packages at that version; Node 22.23.1.
9
+ - Candidate built from this branch and installed with the official `dsh plugin --profile web add <tarball>` command. The same isolated profile was then opened by alpha.2.
10
+ - `pnpm peers check` reported no peer dependency issues after upgrade.
11
+ - The profile, workspace, credentials copy, browser and host test driver were isolated. Only synthetic Session content was submitted to the configured DeepSeek endpoint. Test drivers and browser recordings are not part of the plugin package.
12
+ - Alpha.2's `fs-ext` was built during installation under Node 22. Attempting to launch that installation under Node 24 produced `ERR_DLOPEN_FAILED`; using the matching Node 22 runtime resolved the environment error. This run does not claim an installed alpha.2/Node 24 test.
13
+
14
+ ## Upgrade and real migration
15
+
16
+ | Check | Result |
17
+ |---|---|
18
+ | Old-host installed command | Doctor 13/13; actual preview and migration via `commands.execute` succeeded |
19
+ | Old-host facts | Project BRIDGE-A13-7813, PostgreSQL, port 7813, planned-but-not-created `src/migration.ts`, and MongoDB prohibition preserved |
20
+ | Old-host target | PTC, paused goal, zero autonomous goal rounds |
21
+ | Same-profile upgrade | Original title retained; source header becomes format v2 |
22
+ | Old log artifacts | All four pre-upgrade JSONL/Zstandard artifacts remain byte-identical by SHA-256 |
23
+ | Source content | Folded user and assistant text exactly matches the pre-upgrade snapshot; no test file was created |
24
+ | Alpha.2 command | Doctor 13/13; preview requested through the installed WebUI |
25
+ | Native editing | Text/Markdown round trip preserves numbered-list continuation; edited Next step reaches target exactly |
26
+ | Default confirmation | Exactly one new target; automatically opened in PTC, goal paused, zero goal rounds |
27
+ | Target response | Restates the critical facts and waits; does not execute tools or create files |
28
+ | Restart | Edited objective and paused state remain intact; old log hashes still match |
29
+
30
+ The reviewed native payload had SHA-256 `cba24d3dc1dd707de9f7cfb1b111ac95311838f166216825115c11c86e987f5e` and included long synthetic text to exercise scrolling. Both the submitted content and target goal retained those exact bytes.
31
+
32
+ ## UI and image fallback
33
+
34
+ - At 1280, 768 and 375 pixels, the document had no horizontal overflow; the preview had its own scrollable body and scrolling it did not move the confirmation controls.
35
+ - A separate 375-pixel check scrolled the confirmation button into view and verified that its center hit the actual button, rather than the fixed composer. Native confirmation then succeeded at the desktop viewport.
36
+ - No page errors were observed during the connected preview/edit/confirm runs. No pixel-baseline comparison or full accessibility audit was performed.
37
+ - A real image was admitted through the official vision route, then cancelled before any assistant message; the source contained one durable image and zero assistant analyses. Its selected model was changed to text-only `deepseek-v4-flash` before migration.
38
+ - Target prompt admission rejected the image with `session/attachment-invalid` and `Model "deepseek-v4-flash" does not support image input`. Bridge returned a visible warning and completed a text-only kickoff containing the unresolved-image warning. The target had zero image blocks and a paused goal.
39
+ - Raw-image delivery to a vision-capable target was not repeated in this run.
40
+
41
+ ## History cost comparison
42
+
43
+ The fixture contains 6,000 synthetic user-message events, created through the old host's Session API and upgraded to v2. The default returned window remains 240 messages. The installed alpha.2 `SessionController.inspect` was instrumented to count reads; results below compare the original `main` implementation against the candidate using the same real controller. The session had no attached Agent during the cold-session query comparison. Five sequential samples were taken per implementation, original first; host/OS caches may affect timing. Heap delta is before/after allocation during a read, **not peak RSS or retained memory**.
44
+
45
+ | Metric | Original 0.3.2 | Candidate |
46
+ |---|---:|---:|
47
+ | Full `inspect` calls per source window | 4 | 1 |
48
+ | Returned message count | 240 | 240 |
49
+ | Median read + fold time | 12.93 ms | 6.70 ms |
50
+ | Median observed heap delta | 5,579,552 B | 5,165,760 B |
51
+ | Folded content equality | Identical | Identical |
52
+
53
+ Original times (ms): 58.612, 12.926, 12.533, 12.958, 11.980. Candidate: 7.643, 6.689, 6.703, 7.015, 6.665. The initial original sample also pays first-read setup. An earlier attached-session comparison showed little wall-clock change (about 4–5 ms in both paths). The reliable improvement is avoiding repeated full reads; this is not an end-to-end model latency or universal speedup claim.
54
+
55
+ The adapter retains no running-state or cross-request history cache. Regression tests additionally cover new events after a window read, current worker turn completion, errors/cancellation, and equality with the paged path across tool and compaction records.
56
+
57
+ ## Removal and verification
58
+
59
+ - Official `dsh plugin --profile web remove dsh-plugin-bridge`, followed by a host restart, removed the dependency, bundle registration and profile package link.
60
+ - The old Session remained readable through the generic command renderer. The browser had zero Bridge cards, zero Bridge style elements, zero Bridge resource requests, and zero observed page errors.
61
+ - Executing `/bridge --doctor` returned no command execution; an independently registered companion command still succeeded.
62
+ - Host restart successfully reopened the same persisted sessions, exercising normal session-lock release. Crash recovery and multi-process lock contention were not separately tested.
63
+ - `npm ci` followed by `npm run verify` passed under Node 22.23.1: 174 tests, build/typecheck, generated artifact checks, datasets and package import smoke. The Node 24.19.0 test run also passed all 174 tests.
64
+ - Summary model calls, UI fixtures and inspection endpoints were restricted to the isolated acceptance environment. No user Session database was edited or deleted.
65
+ - After acceptance, the temporary credential copy, both installed runtimes, synthetic profile, browser process and three test-created summary directories were removed. Sanitized measurement results, check logs and screenshots were retained outside the repository.