@deepseek-ai/dsh-client-ui-chat 0.1.5-alpha.1 → 0.1.5-alpha.2

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.i18n.yaml CHANGED
@@ -2,5 +2,5 @@
2
2
  # side as of the last confirmed-consistent state. Both languages carry equal authority;
3
3
  # after editing either side, bring the other along and re-record with:
4
4
  # pnpm run verify-translation-pairing --write packages/client/ui-chat/README.md
5
- README.md: b5a837f927b483a1f72e8282032fce29683bc237
6
- README.zh.md: f6b8018434251e46875bfd5cc0b0a242cdf2a439
5
+ README.md: 860dcb9eeb9c92a14d9128d9d8c95c29796726f8
6
+ README.zh.md: 4dd06a16b19b14cacc0ded603cc1cf8869dd1a43
package/README.md CHANGED
@@ -10,6 +10,8 @@ English | [中文](README.zh.md)
10
10
 
11
11
  Use this package to render a browser chat from recorded Session conversations, including historical images, localized actions, and restored scroll position. Compact display folds completed-turn process rows while keeping the final answer and independently useful context visible; packed historical Assistant runs remain collapsed. Local transcript and steering submissions appear immediately, remain in their original surface, and disappear atomically when authoritative Session records arrive, while queued submissions stay outside Chat. The package does not assemble or modify model requests.
12
12
 
13
+ File-mention providers receive the viewed Session ID with the closing-turn owner, so links into inherited history can address the fork itself.
14
+
13
15
  ## Table of Contents
14
16
 
15
17
  - [System prompt row](#system-prompt-row)
@@ -37,7 +39,7 @@ A completed Turn shows an expandable usage row only when the loaded window inclu
37
39
  <a id="turn-process-folding"></a>
38
40
  ## Turn Process Folding
39
41
 
40
- Settings → General exposes a persisted `Normal` / `Compact` conversation-display preference in the `ui-chat` namespace; `Compact` is the default. Normal leaves process rows visible and renders no Turn-process control. In Compact mode, the System prompt remains independently visible before the opening User throughout the Turn. Context injection, reasoning, Assistant material, Tool rows, and Retry rows remain expanded while a Turn is open. At `turn/end`, its latest Step becomes the final-answer boundary only when it contains non-blank text, an image, or an unknown visible block—and no Tool-call block; preceding Context injection, reasoning, earlier Assistant material, Tool rows, and Retry rows then collapse by default. The control reports Turn-wide durable counts for non-subagent Tool calls, reply-bearing Assistant messages before the final answer, and subagent delegation calls; zero-valued segments are omitted, the Tool and subagent figures are mutually exclusive, and neither System prompt nor Context injection contributes a count. When all three counts are zero, the process still folds and the control reads `Thought for a while`. A full-width divider below the summary separates it from the answer or expanded process rows. User and steering messages, System prompt, error, max-token, and turn-tail rows stay outside, and a closed Turn with no final answer keeps all process evidence visible. A newly available process control is inserted without changing the relative order of existing rows: opening human input precedes the control and process rows from their first projection, while System prompt remains above that input. While older history remains available through Load earlier, process controls stay absent and no members are hidden; once history is complete, every eligible closed Turn uses the collapsed default immediately. Stable Chat Node Seats keep every renderer mounted, hidden members add no flow spacing, and a closed control sits 8px above its answer only when no independent input intervenes. Completion collapse does not depend on tail-follow position, so a reader above the tail may see the transcript reflow. An automatic collapse that would hide keyboard focus keeps the group open and leaves focus in place; a manual close focuses the process control before hiding its members. The session-scoped store records only manually expanded Turn-and-answer-Step generations; a different answer generation starts collapsed.
42
+ Settings → General exposes a persisted, localized `Normal` / `Compact` conversation-display preference in the `ui-chat` namespace; `Compact` is the default. Normal leaves process rows visible and renders no Turn-process control. In Compact mode, the System prompt remains independently visible before the opening User throughout the Turn. Context injection, reasoning, Assistant material, Tool rows, and Retry rows remain expanded while a Turn is open. At `turn/end`, its latest Step becomes the final-answer boundary only when it contains non-blank text, an image, or an unknown visible block—and no Tool-call block; preceding Context injection, reasoning, earlier Assistant material, Tool rows, and Retry rows then collapse by default. The control reports Turn-wide durable counts for non-subagent Tool calls, reply-bearing Assistant messages before the final answer, and subagent delegation calls; zero-valued segments are omitted, the Tool and subagent figures are mutually exclusive, and neither System prompt nor Context injection contributes a count. When all three counts are zero, the process still folds and the control reads `Thought for a while`. A full-width divider below the summary separates it from the answer or expanded process rows. User and steering messages, System prompt, error, max-token, and turn-tail rows stay outside, and a closed Turn with no final answer keeps all process evidence visible. A newly available process control is inserted without changing the relative order of existing rows: opening human input precedes the control and process rows from their first projection, while System prompt remains above that input. While older history remains available through Load earlier, process controls stay absent and no members are hidden; once history is complete, every eligible closed Turn uses the collapsed default immediately. Stable Chat Node Seats keep every renderer mounted, hidden members add no flow spacing, and a closed control sits 8px above its answer only when no independent input intervenes. Completion collapse does not depend on tail-follow position, so a reader above the tail may see the transcript reflow. An automatic collapse that would hide keyboard focus keeps the group open and leaves focus in place; a manual close focuses the process control before hiding its members. The session-scoped store records only manually expanded Turn-and-answer-Step generations; a different answer generation starts collapsed.
41
43
 
42
44
  -----
43
45
 
package/README.zh.md CHANGED
@@ -10,6 +10,8 @@ kind: "package-reference"
10
10
 
11
11
  使用本包可在浏览器中渲染已记录的 Session 对话,包括历史图片、本地化操作和滚动位置恢复。紧凑显示会收起已完成轮次的过程行,同时保持最终答案和独立有用的上下文可见;已打包的历史 Assistant 连续消息保持收起。本地 transcript 与 steering 提交会立即显示并保留在原区域,在权威 Session 记录到达时原子地消失,而 queued 提交始终不进入 Chat。本包不组装或修改模型请求。
12
12
 
13
+ 文件引用提供方同时接收当前查看的 Session ID 与收尾 turn 的属主信息,因此继承历史中的链接可以指向 fork 自身。
14
+
13
15
  ## 目录
14
16
 
15
17
  - [系统提示词行](#system-prompt-row)
@@ -39,7 +41,7 @@ kind: "package-reference"
39
41
  <a id="turn-process-folding"></a>
40
42
  ## 轮次过程折叠
41
43
 
42
- 「设置 → 通用设置」提供持久化到 `ui-chat` 命名空间的 `Normal` / `Compact` 对话显示偏好,默认使用 `Compact`。Normal 保持所有过程行可见且不渲染轮次过程控件。Compact 模式下,系统提示词在整个轮次中始终独立显示于开场 User 上方。轮次打开期间,上下文注入、推理、Assistant 内容、工具行与重试行始终展开。到 `turn/end` 时,最后一个步骤只有在包含非空文本、图片或未知可见块且不含工具调用块时才成为最终正文边界;边界之前的上下文注入、推理、较早 Assistant 内容、工具行与重试行随后默认收起。控件展示覆盖整个轮次的非 subagent 工具调用数、最终正文之前带回复内容的 Assistant 消息数和 subagent 委派数;值为 0 的分段省略,工具调用与 subagent 两项互斥,系统提示词与上下文注入都不增加计数。三项全为 0 时过程仍会收起,控件标题显示「已思考」(英文为 `Thought for a while`)。摘要下方的通栏分隔线将其与正文或展开后的过程行隔开。用户与 steering 消息、系统提示词、错误、最大 token 与 turn-tail 行留在过程组外;关闭时没有最终正文的轮次保留全部过程证据。新的过程控件插入时不会改变既有行的相对顺序:开场人工输入从首次投影起便位于控件和过程行之前,系统提示词则始终位于该输入上方。只要仍可通过「加载更早」获取历史,过程控件就不出现,也不会隐藏任何成员;历史加载完整后,每个合格的已关闭轮次立即使用默认收起状态。稳定 Chat Node Seat 会让每个 renderer 保持挂载,隐藏成员不产生消息流间距;只有中间没有独立输入时,收起控件才与正文相隔 8px。完成后的收起不依赖是否跟随尾部,因此正在上方阅读的用户可能看到 transcript 高度变化。若自动收起会隐藏当前键盘焦点,则过程组保持展开且焦点留在原处;手动收起会先把焦点移到过程控件,再隐藏成员。会话作用域 store 只记录用户手动展开的「轮次 + 正文步骤」generation;不同正文 generation 默认收起。
44
+ 「设置 → 通用设置」提供持久化到 `ui-chat` 命名空间的「标准」/「紧凑」对话显示偏好,默认使用「紧凑」。标准模式保持所有过程行可见且不渲染轮次过程控件。紧凑模式下,系统提示词在整个轮次中始终独立显示于开场 User 上方。轮次打开期间,上下文注入、推理、Assistant 内容、工具行与重试行始终展开。到 `turn/end` 时,最后一个步骤只有在包含非空文本、图片或未知可见块且不含工具调用块时才成为最终正文边界;边界之前的上下文注入、推理、较早 Assistant 内容、工具行与重试行随后默认收起。控件展示覆盖整个轮次的非 subagent 工具调用数、最终正文之前带回复内容的 Assistant 消息数和 subagent 委派数;值为 0 的分段省略,工具调用与 subagent 两项互斥,系统提示词与上下文注入都不增加计数。三项全为 0 时过程仍会收起,控件标题显示「已思考」(英文为 `Thought for a while`)。摘要下方的通栏分隔线将其与正文或展开后的过程行隔开。用户与 steering 消息、系统提示词、错误、最大 token 与 turn-tail 行留在过程组外;关闭时没有最终正文的轮次保留全部过程证据。新的过程控件插入时不会改变既有行的相对顺序:开场人工输入从首次投影起便位于控件和过程行之前,系统提示词则始终位于该输入上方。只要仍可通过「加载更早」获取历史,过程控件就不出现,也不会隐藏任何成员;历史加载完整后,每个合格的已关闭轮次立即使用默认收起状态。稳定 Chat Node Seat 会让每个 renderer 保持挂载,隐藏成员不产生消息流间距;只有中间没有独立输入时,收起控件才与正文相隔 8px。完成后的收起不依赖是否跟随尾部,因此正在上方阅读的用户可能看到 transcript 高度变化。若自动收起会隐藏当前键盘焦点,则过程组保持展开且焦点留在原处;手动收起会先把焦点移到过程控件,再隐藏成员。会话作用域 store 只记录用户手动展开的「轮次 + 正文步骤」generation;不同正文 generation 默认收起。
43
45
 
44
46
  -----
45
47
 
package/lib/client.js CHANGED
@@ -21,26 +21,14 @@ window.__ModuleLoader__.load({
21
21
  return path.split("/").map(encodeSegment).join("/");
22
22
  }
23
23
  /**
24
- * Build the address of a file inside one Session's workspace.
25
- * @param sessionId - the Session whose workspace root the path is relative to.
26
- * @param path - workspace-relative path; backslashes are normalized to `/`, and a leading `./` or `/` is dropped.
24
+ * Build the address of a file read through one Session.
25
+ * @param sessionId - the Session whose Host workspace resolves the path.
26
+ * @param path - absolute or workspace-relative path; backslashes are normalized to `/`, and leading `./` prefixes are dropped.
27
27
  * @returns the `dsh-resource://file/session/<sessionId>/<path>` address.
28
28
  */
29
29
  function sessionFileAddress(sessionId, path) {
30
- const relative = path.replace(/\\/g, "/").replace(/^(?:\.\/)+/, "").replace(/^\/+/, "");
31
- return `${FILE_ADDRESS_PREFIX}session/${encodeSegment(sessionId)}/${encodePath(relative)}`;
32
- }
33
- /**
34
- * Build the address of a file by its absolute path.
35
- * @param path - absolute path; backslashes are normalized to `/` and the leading `/` is dropped,
36
- * except that a UNC path (`\\server\share`) keeps one empty first segment.
37
- * @returns the `dsh-resource://file/absolute/<path>` address.
38
- */
39
- function absoluteFileAddress(path) {
40
- const normalized = path.replace(/\\/g, "/");
41
- const unc = normalized.startsWith("//");
42
- const absolute = normalized.replace(/^\/+/, "");
43
- return `${FILE_ADDRESS_PREFIX}absolute/${unc ? "/" : ""}${encodePath(absolute)}`;
30
+ const normalized = path.replace(/\\/g, "/").replace(/^(?:\.\/)+/, "");
31
+ return `${FILE_ADDRESS_PREFIX}session/${encodeSegment(sessionId)}/${encodePath(normalized)}`;
44
32
  }
45
33
  //#endregion
46
34
  //#region ../../util/workspace-path/src/index.ts
@@ -63,8 +51,8 @@ window.__ModuleLoader__.load({
63
51
  /**
64
52
  * The address for a path as a caller holds it: a relative path, or an absolute
65
53
  * path inside the Session's workspace, becomes a `session`-scoped address; an
66
- * absolute path outside it, or one whose workspace root is unknown, becomes an
67
- * `absolute`-scoped address.
54
+ * absolute path outside it, or one whose workspace root is unknown, keeps its
55
+ * absolute path in that Session's address.
68
56
  * @param sessionId - the Session the path is read in.
69
57
  * @param cwd - that Session's workspace root, when known.
70
58
  * @param path - absolute or workspace-relative path, in either separator spelling.
@@ -76,7 +64,7 @@ window.__ModuleLoader__.load({
76
64
  const root = cwd === void 0 ? "" : cwd.replace(/\\/g, "/").replace(/\/+$/, "");
77
65
  if (root !== "" && normalized === root) return sessionFileAddress(sessionId, "");
78
66
  if (root !== "" && normalized.startsWith(`${root}/`)) return sessionFileAddress(sessionId, normalized.slice(root.length + 1));
79
- return absoluteFileAddress(normalized);
67
+ return sessionFileAddress(sessionId, normalized);
80
68
  }
81
69
  //#endregion
82
70
  //#region lib/types/client/contract/snapshot.js
@@ -164,7 +152,7 @@ window.__ModuleLoader__.load({
164
152
  }
165
153
  //#endregion
166
154
  //#region \0dsh-css:/home/runner/work/deepseek-harness/deepseek-harness/packages/client/ui-chat/src/client/chat/MessageItem.module.css.mjs
167
- const css$15 = ".Sixlwa_userRow{flex-direction:column;align-items:flex-end;gap:6px;display:flex}.Sixlwa_userStack{min-width:0;max-width:min(calc(var(--dsh-chat-content-width,748px) * .702), 82%);flex-direction:column;align-items:flex-end;gap:8px;display:flex}.Sixlwa_bubble{background:var(--dsw-specific-bubble);max-width:100%;font-size:var(--dsh-content-font-size,14px);line-height:calc(22px + var(--dsh-content-font-delta,0px));color:var(--dsw-alias-label-primary);white-space:pre-wrap;word-break:break-word;border-radius:22px;padding:10px 16px}.Sixlwa_referenceSummary{color:var(--dsw-alias-label-tertiary);font-size:var(--dsh-content-font-size-secondary,13px);line-height:calc(18px + var(--dsh-content-font-delta-secondary,0px))}.Sixlwa_contextRow,.Sixlwa_compactionRow{padding:2px 0}.Sixlwa_compactionButton{width:100%;height:calc(24px + var(--dsh-content-font-delta,0px));min-width:0;color:inherit;font:inherit;text-align:left;background:0 0;border:none;border-radius:6px;align-items:center;padding:0;display:flex}.Sixlwa_compactionButton:not(:disabled){cursor:pointer}.Sixlwa_compactionButton:not(:disabled):hover{background:var(--dsw-alias-interactive-bg-hover)}.Sixlwa_compactionLeading{width:calc(16px + var(--dsh-content-font-delta,0px));height:calc(16px + var(--dsh-content-font-delta,0px));color:var(--dsw-alias-label-secondary);flex:none;place-items:center;margin-right:6px;display:inline-grid}.Sixlwa_compactionLeading svg{width:calc(14px + var(--dsh-content-font-delta,0px));height:calc(14px + var(--dsh-content-font-delta,0px))}.Sixlwa_compactionContextIcon,.Sixlwa_compactionDisclosureIcon{grid-area:1/1;justify-content:center;align-items:center;display:inline-flex}.Sixlwa_compactionDisclosureIcon,.Sixlwa_compactionButton:not(:disabled):hover .Sixlwa_compactionContextIcon,.Sixlwa_compactionButton:not(:disabled):focus-visible .Sixlwa_compactionContextIcon{opacity:0}.Sixlwa_compactionButton:not(:disabled):hover .Sixlwa_compactionDisclosureIcon,.Sixlwa_compactionButton:not(:disabled):focus-visible .Sixlwa_compactionDisclosureIcon{opacity:1}.Sixlwa_compactionTitle{font-size:var(--dsh-content-font-size-secondary,13px);line-height:calc(24px + var(--dsh-content-font-delta,0px));color:var(--dsw-alias-label-primary-dimmed);flex:none}.Sixlwa_compactionSep{background:var(--dsw-alias-label-caption);border-radius:1px;flex:none;width:2px;height:2px;margin:0 8px}.Sixlwa_compactionSummary{min-width:0;color:var(--dsw-alias-label-tertiary);font-size:var(--dsh-content-font-size-secondary,13px);line-height:calc(24px + var(--dsh-content-font-delta,0px));text-overflow:ellipsis;white-space:nowrap;flex:auto;overflow:hidden}.Sixlwa_compactionBody{padding:4px 0 4px calc(22px + var(--dsh-content-font-delta,0px));color:var(--dsw-alias-label-tertiary);font-size:var(--dsh-content-font-size-secondary,13px);line-height:calc(24px + var(--dsh-content-font-delta,0px))}.Sixlwa_retryRow{color:var(--dsw-alias-label-tertiary);font-size:var(--dsh-content-font-size-secondary,13px);line-height:calc(20px + var(--dsh-content-font-delta-secondary,0px))}.Sixlwa_retrySummary{width:fit-content;color:inherit;cursor:pointer;user-select:none;border-radius:3px;align-items:center;gap:7px;padding:2px 0;list-style:none;display:inline-flex}.Sixlwa_retrySummary::-webkit-details-marker{display:none}.Sixlwa_retrySummary:after{content:\"\";opacity:.8;border-bottom:1.5px solid;border-right:1.5px solid;width:6px;height:6px;transition:transform .12s;transform:rotate(-45deg)}.Sixlwa_retrySummary:hover{color:var(--dsw-alias-label-secondary)}.Sixlwa_retrySummary:focus-visible{outline:1.5px solid var(--dsw-alias-button-info-fill);outline-offset:2px}.Sixlwa_retryText{color:inherit}.Sixlwa_retryRow[data-active] .Sixlwa_retryText{background:linear-gradient(90deg, var(--dsw-alias-label-tertiary) 0%, var(--dsw-alias-label-tertiary) 40%, var(--dsw-alias-label-secondary) 50%, var(--dsw-alias-label-tertiary) 60%, var(--dsw-alias-label-tertiary) 100%);color:#0000;background-position:100%;background-size:200% 100%;background-clip:text;animation:1.6s ease-in-out infinite Sixlwa_retry-shimmer}.Sixlwa_retryRow[open] .Sixlwa_retrySummary:after{transform:rotate(45deg)}.Sixlwa_retryDetails{overflow-wrap:anywhere;font-size:var(--dsh-content-font-size-secondary,13px);line-height:calc(18px + var(--dsh-content-font-delta-secondary,0px));gap:2px;margin-top:3px;padding-left:14px;display:grid}.Sixlwa_retryDetailLabel{color:var(--dsw-alias-label-secondary)}.Sixlwa_turnErrorRow{font-size:var(--dsh-content-font-size-secondary,13px);line-height:calc(20px + var(--dsh-content-font-delta-secondary,0px));grid-template-columns:10px minmax(0,1fr) auto;align-items:start;gap:8px;padding:2px 0;display:grid}.Sixlwa_turnErrorDot{margin-top:5px}.Sixlwa_turnErrorCopy{overflow-wrap:anywhere;min-width:0}.Sixlwa_turnErrorTitle{color:var(--dsw-alias-state-error-primary);margin-right:6px;font-weight:600}.Sixlwa_turnErrorMessage{color:var(--dsw-alias-label-secondary)}.Sixlwa_turnErrorCode{color:var(--dsw-alias-label-tertiary);font:var(--dsw-font-markdown-code-block-small)}.Sixlwa_maxTokensTitle{color:var(--dsw-alias-state-warn-primary);margin-right:6px;font-weight:600}@keyframes Sixlwa_retry-shimmer{0%{background-position:100%}to{background-position:0}}@media (prefers-reduced-motion:reduce){.Sixlwa_retryRow[data-active] .Sixlwa_retryText{color:inherit;background:0 0;animation:none}}.Sixlwa_attachmentRow{flex-wrap:wrap;justify-content:flex-end;gap:8px;max-width:100%;display:flex}.Sixlwa_fileCard{border:.5px solid var(--dsw-alias-border-l2,#0000001f);background:var(--dsw-specific-input-major,transparent);box-sizing:border-box;border-radius:16px;flex:0 0 240px;align-items:center;gap:10px;width:240px;min-height:64px;padding:8px 12px;display:inline-flex}.Sixlwa_fileIcon{flex:none;width:24px;height:28px}.Sixlwa_fileContent{flex-direction:column;flex:1;min-width:0;display:flex}.Sixlwa_fileName{white-space:nowrap;text-overflow:ellipsis;color:var(--dsw-alias-label-primary);font-size:14px;font-weight:500;line-height:22px;overflow:hidden}.Sixlwa_fileMeta{white-space:nowrap;text-overflow:ellipsis;color:var(--dsw-alias-label-tertiary,#00000073);font-size:12px;line-height:15px;overflow:hidden}";
155
+ const css$15 = ".Sixlwa_userRow{flex-direction:column;align-items:flex-end;gap:6px;display:flex}.Sixlwa_userStack{min-width:0;max-width:min(calc(var(--dsh-chat-content-width,748px) * .702), 82%);flex-direction:column;align-items:flex-end;gap:8px;display:flex}.Sixlwa_bubble{background:var(--dsw-specific-bubble);max-width:100%;font-size:var(--dsh-content-font-size,14px);line-height:calc(22px + var(--dsh-content-font-delta,0px));color:var(--dsw-alias-label-primary);white-space:pre-wrap;word-break:break-word;border-radius:22px;padding:10px 16px}.Sixlwa_referenceSummary{color:var(--dsw-alias-label-tertiary);font-size:var(--dsh-content-font-size-secondary,13px);line-height:calc(18px + var(--dsh-content-font-delta-secondary,0px))}.Sixlwa_contextRow,.Sixlwa_compactionRow{padding:2px 0}.Sixlwa_compactionButton{width:100%;height:calc(24px + var(--dsh-content-font-delta,0px));min-width:0;color:inherit;font:inherit;text-align:left;background:0 0;border:none;border-radius:6px;align-items:center;padding:0;display:flex}.Sixlwa_compactionButton:not(:disabled){cursor:pointer}.Sixlwa_compactionButton:not(:disabled):hover{background:var(--dsw-alias-interactive-bg-hover)}.Sixlwa_compactionLeading{width:calc(16px + var(--dsh-content-font-delta,0px));height:calc(16px + var(--dsh-content-font-delta,0px));color:var(--dsw-alias-label-secondary);flex:none;place-items:center;margin-right:6px;display:inline-grid}.Sixlwa_compactionLeading svg{width:calc(14px + var(--dsh-content-font-delta,0px));height:calc(14px + var(--dsh-content-font-delta,0px))}.Sixlwa_compactionContextIcon,.Sixlwa_compactionDisclosureIcon{grid-area:1/1;justify-content:center;align-items:center;display:inline-flex}.Sixlwa_compactionDisclosureIcon,.Sixlwa_compactionButton:not(:disabled):hover .Sixlwa_compactionContextIcon,.Sixlwa_compactionButton:not(:disabled):focus-visible .Sixlwa_compactionContextIcon{opacity:0}.Sixlwa_compactionButton:not(:disabled):hover .Sixlwa_compactionDisclosureIcon,.Sixlwa_compactionButton:not(:disabled):focus-visible .Sixlwa_compactionDisclosureIcon{opacity:1}.Sixlwa_compactionTitle{font-size:var(--dsh-content-font-size-secondary,13px);line-height:calc(24px + var(--dsh-content-font-delta,0px));color:var(--dsw-alias-label-primary-dimmed);flex:none}.Sixlwa_compactionSep{background:var(--dsw-alias-label-caption);border-radius:1px;flex:none;width:2px;height:2px;margin:0 8px}.Sixlwa_compactionSummary{min-width:0;color:var(--dsw-alias-label-tertiary);font-size:var(--dsh-content-font-size-secondary,13px);line-height:calc(24px + var(--dsh-content-font-delta,0px));text-overflow:ellipsis;white-space:nowrap;flex:auto;overflow:hidden}.Sixlwa_compactionBody{padding:4px 0 4px calc(22px + var(--dsh-content-font-delta,0px));color:var(--dsw-alias-label-tertiary);font-size:var(--dsh-content-font-size-secondary,13px);line-height:calc(24px + var(--dsh-content-font-delta,0px))}.Sixlwa_retryRow{color:var(--dsw-alias-label-tertiary);font-size:var(--dsh-content-font-size-secondary,13px);line-height:calc(20px + var(--dsh-content-font-delta-secondary,0px))}.Sixlwa_retrySummary{width:fit-content;color:inherit;cursor:pointer;user-select:none;border-radius:3px;align-items:center;gap:7px;padding:2px 0;list-style:none;display:inline-flex}.Sixlwa_retrySummary::-webkit-details-marker{display:none}.Sixlwa_retrySummary:after{content:\"\";opacity:.8;border-bottom:1.5px solid;border-right:1.5px solid;width:6px;height:6px;transition:transform .12s;transform:rotate(-45deg)}.Sixlwa_retrySummary:hover{color:var(--dsw-alias-label-secondary)}.Sixlwa_retrySummary:focus-visible{outline:1.5px solid var(--dsw-alias-button-info-fill);outline-offset:2px}.Sixlwa_retryText{color:inherit}.Sixlwa_retryRow[data-active] .Sixlwa_retryText{background:linear-gradient(90deg, var(--dsw-alias-label-tertiary) 0%, var(--dsw-alias-label-tertiary) 40%, var(--dsw-alias-label-secondary) 50%, var(--dsw-alias-label-tertiary) 60%, var(--dsw-alias-label-tertiary) 100%);color:#0000;background-position:100%;background-size:200% 100%;background-clip:text;animation:1.6s ease-in-out infinite Sixlwa_retry-shimmer}.Sixlwa_retryRow[open] .Sixlwa_retrySummary:after{transform:rotate(45deg)}.Sixlwa_retryDetails{overflow-wrap:anywhere;font-size:var(--dsh-content-font-size-secondary,13px);line-height:calc(18px + var(--dsh-content-font-delta-secondary,0px));gap:2px;margin-top:3px;padding-left:14px;display:grid}.Sixlwa_retryDetailLabel{color:var(--dsw-alias-label-secondary)}.Sixlwa_turnErrorRow{font-size:var(--dsh-content-font-size-secondary,13px);line-height:calc(20px + var(--dsh-content-font-delta-secondary,0px));grid-template-columns:10px minmax(0,1fr) auto;align-items:start;gap:8px;padding:2px 0;display:grid}.Sixlwa_turnErrorDot{margin-top:5px}.Sixlwa_turnErrorCopy{overflow-wrap:anywhere;min-width:0}.Sixlwa_turnErrorTitle{color:var(--dsw-alias-state-error-primary);margin-right:6px;font-weight:600}.Sixlwa_turnErrorMessage{color:var(--dsw-alias-label-secondary)}.Sixlwa_turnErrorCode{color:var(--dsw-alias-label-tertiary);font:var(--dsw-font-markdown-code-block-small)}.Sixlwa_maxTokensTitle{color:var(--dsw-alias-state-warn-primary);margin-right:6px;font-weight:600}@keyframes Sixlwa_retry-shimmer{0%{background-position:100%}to{background-position:0}}@media (prefers-reduced-motion:reduce){.Sixlwa_retryRow[data-active] .Sixlwa_retryText{color:inherit;background:0 0;animation:none}}.Sixlwa_attachmentRow{flex-wrap:wrap;justify-content:flex-end;gap:8px;max-width:100%;display:flex}.Sixlwa_fileCard{border:.5px solid var(--dsw-alias-border-l2,#0000001f);background:var(--dsw-specific-input-major,transparent);box-sizing:border-box;border-radius:16px;flex:0 0 240px;align-items:center;gap:10px;width:240px;min-height:64px;padding:8px 12px;display:inline-flex}.Sixlwa_fileIcon{flex:none;width:28px;height:28px}.Sixlwa_fileContent{flex-direction:column;flex:1;min-width:0;display:flex}.Sixlwa_fileName{white-space:nowrap;text-overflow:ellipsis;color:var(--dsw-alias-label-primary);font-size:14px;font-weight:500;line-height:22px;overflow:hidden}.Sixlwa_fileMeta{white-space:nowrap;text-overflow:ellipsis;color:var(--dsw-alias-label-tertiary,#00000073);font-size:12px;line-height:15px;overflow:hidden}";
168
156
  const tagId$15 = "@deepseek-ai/dsh-client-ui-chat/MessageItem.module.css";
169
157
  if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$15) + "]") === null) {
170
158
  const tag = document.createElement("style");
@@ -1109,11 +1097,6 @@ window.__ModuleLoader__.load({
1109
1097
  }
1110
1098
  //#endregion
1111
1099
  //#region lib/types/client/chat/MessageItem.js
1112
- function extensionOf(name) {
1113
- const dot = name.lastIndexOf(".");
1114
- if (dot <= 0 || dot === name.length - 1) return "";
1115
- return name.slice(dot + 1).toUpperCase().slice(0, 8);
1116
- }
1117
1100
  function contentParts(content) {
1118
1101
  const texts = [];
1119
1102
  const attachments = [];
@@ -1270,14 +1253,17 @@ window.__ModuleLoader__.load({
1270
1253
  }) }, `image:${index}`) : (0, react_jsx_runtime.jsxs)("span", {
1271
1254
  className: MessageItem_module_css_default.fileCard,
1272
1255
  title: attachment.file.name,
1273
- children: [(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.DocumentFileIcon, { className: MessageItem_module_css_default.fileIcon }), (0, react_jsx_runtime.jsxs)("span", {
1256
+ children: [(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.FileTypeIcon, {
1257
+ path: attachment.file.name,
1258
+ className: MessageItem_module_css_default.fileIcon
1259
+ }), (0, react_jsx_runtime.jsxs)("span", {
1274
1260
  className: MessageItem_module_css_default.fileContent,
1275
1261
  children: [(0, react_jsx_runtime.jsx)("span", {
1276
1262
  className: MessageItem_module_css_default.fileName,
1277
1263
  children: attachment.file.name
1278
1264
  }), (0, react_jsx_runtime.jsx)("span", {
1279
1265
  className: MessageItem_module_css_default.fileMeta,
1280
- children: [extensionOf(attachment.file.name), (0, _deepseek_ai_dsh_client_ui_primitives.fileSizeText)(attachment.file.bytes)].filter(Boolean).join(" ")
1266
+ children: [(0, _deepseek_ai_dsh_client_ui_primitives.fileExtension)(attachment.file.name).toUpperCase().slice(0, 8), (0, _deepseek_ai_dsh_client_ui_primitives.fileSizeText)(attachment.file.bytes)].filter(Boolean).join(" ")
1281
1267
  })]
1282
1268
  })]
1283
1269
  }, `file:${index}`))
@@ -2659,8 +2645,8 @@ window.__ModuleLoader__.load({
2659
2645
  "chat.turnNavigation.turn": "第 {turn} 轮",
2660
2646
  "settings.transcript.title": "对话显示",
2661
2647
  "settings.transcript.description": "控制已完成轮次的过程内容",
2662
- "settings.transcript.normal": "Normal",
2663
- "settings.transcript.compact": "Compact",
2648
+ "settings.transcript.normal": "标准",
2649
+ "settings.transcript.compact": "紧凑",
2664
2650
  "fileOpen.title": "无法打开文件",
2665
2651
  "fileOpen.unknown": "无法打开此文件",
2666
2652
  "message.extraBlock": "附加内容块",
@@ -8330,7 +8316,7 @@ window.__ModuleLoader__.load({
8330
8316
  chatNode: (key) => chat.getSnapshot().nodes.source(key),
8331
8317
  chatNodeProcess: (key) => chat.getSnapshot().nodes.processSource(key)
8332
8318
  },
8333
- fileMentions: (owner) => ctx.get("chatFileMentions")?.forClosing(owner),
8319
+ fileMentions: (owner) => ctx.get("chatFileMentions")?.forClosing(owner, sessionId),
8334
8320
  openFile: async (path, options) => {
8335
8321
  const cwd = ctx.sessions.list.getSnapshot().byId[sessionId]?.cwd;
8336
8322
  const url = fileAddressFor(sessionId, cwd, path);
@@ -1,6 +1,6 @@
1
1
  /** Chat-owned Slot declarations and composed component props. */
2
2
  import type { MessageId } from '@deepseek-ai/dsh-llm/brand';
3
- import type { SessionSeq } from '@deepseek-ai/dsh-session/types';
3
+ import type { SessionId, SessionSeq } from '@deepseek-ai/dsh-session/types';
4
4
  import type { CommandNode, CompactionSummaryNode, ConversationLocationDataStore, ConversationTurnDataMap, MessageImageLoader, MessageImagesOwnerProps, RenderMessageImages, TurnLocation } from '@deepseek-ai/dsh-client-ui-conversation/client';
5
5
  import type { InjectFace, KeyedSnapshotSelectorHook, PropsLocale, PropsRenderSlots, PropsRuntime, PropsStore, SlotHookFactory, SnapshotSelectorHook } from '@deepseek-ai/dsh-client-ui-slots';
6
6
  import type { SnapshotStore } from '@deepseek-ai/dsh-client-store';
@@ -37,9 +37,10 @@ export interface ChatFileMentions {
37
37
  /**
38
38
  * Resolve prose links for one closing Turn.
39
39
  * @param owner - closing-Turn identity and file opener.
40
+ * @param sessionId - viewed Session, including when history is inherited from a fork.
40
41
  * @returns link resolver when available.
41
42
  */
42
- forClosing(owner: TurnTailOwnerProps): MarkdownFileMentions | undefined;
43
+ forClosing(owner: TurnTailOwnerProps, sessionId: SessionId): MarkdownFileMentions | undefined;
43
44
  }
44
45
  declare module '@deepseek-ai/cordis' {
45
46
  interface Context {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@deepseek-ai/dsh-client-ui-chat",
3
3
  "description": "Chat Conversation target, node definitions, renderers, and details surface",
4
- "version": "0.1.5-alpha.1",
4
+ "version": "0.1.5-alpha.2",
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },
@@ -52,36 +52,36 @@
52
52
  "react": "^18.2.0",
53
53
  "react-dom": "^18.2.0",
54
54
  "@deepseek-ai/cordis": "^4.0.2",
55
- "@deepseek-ai/dsh-agent": "^0.1.5-alpha.1",
56
- "@deepseek-ai/dsh-api-remotes": "^0.1.5-alpha.1",
57
- "@deepseek-ai/dsh-api-session-controller": "^0.1.5-alpha.1",
58
- "@deepseek-ai/dsh-api-workspace-controller": "^0.1.5-alpha.1",
59
- "@deepseek-ai/dsh-client-store": "^0.1.5-alpha.1",
60
- "@deepseek-ai/dsh-client-ui-approval": "^0.1.5-alpha.1",
61
- "@deepseek-ai/dsh-client-ui-conversation": "^0.1.5-alpha.1",
62
- "@deepseek-ai/dsh-client-ui-layout": "^0.1.5-alpha.1",
63
- "@deepseek-ai/dsh-client-ui-primitives": "^0.1.5-alpha.1",
64
- "@deepseek-ai/dsh-attachment": "^0.1.5-alpha.1",
65
- "@deepseek-ai/dsh-api-workspace-files": "^0.1.5-alpha.1",
66
- "@deepseek-ai/dsh-client-locale": "^0.1.5-alpha.1",
67
- "@deepseek-ai/dsh-client-ui-session": "^0.1.5-alpha.1",
68
- "@deepseek-ai/dsh-client-ui-renderer": "^0.1.5-alpha.1",
69
- "@deepseek-ai/dsh-client-ui-settings": "^0.1.5-alpha.1",
70
- "@deepseek-ai/dsh-client-ui-sidebar-right": "^0.1.5-alpha.1",
71
- "@deepseek-ai/dsh-client-ui-slots": "^0.1.5-alpha.1",
72
- "@deepseek-ai/dsh-client-ui-workspace": "^0.1.5-alpha.1",
73
- "@deepseek-ai/dsh-commands": "^0.1.5-alpha.1",
74
- "@deepseek-ai/dsh-compaction": "^0.1.5-alpha.1",
75
- "@deepseek-ai/dsh-llm": "^0.1.5-alpha.1",
76
- "@deepseek-ai/dsh-llm-retry": "^0.1.5-alpha.1",
77
- "@deepseek-ai/dsh-client-ui-sidebar-textpreview": "^0.1.5-alpha.1",
78
- "@deepseek-ai/dsh-session-stats": "^0.1.5-alpha.1",
79
- "@deepseek-ai/dsh-settings": "^0.1.5-alpha.1",
80
- "@deepseek-ai/dsh-token-meter": "^0.1.5-alpha.1",
81
- "@deepseek-ai/dsh-session-turn-outline": "^0.1.5-alpha.1",
82
- "@deepseek-ai/dsh-tools": "^0.1.5-alpha.1",
83
- "@deepseek-ai/dsh-util-workspace-path": "^0.1.5-alpha.1",
84
- "@deepseek-ai/dsh-session": "^0.1.5-alpha.1"
55
+ "@deepseek-ai/dsh-agent": "^0.1.5-alpha.2",
56
+ "@deepseek-ai/dsh-api-remotes": "^0.1.5-alpha.2",
57
+ "@deepseek-ai/dsh-api-session-controller": "^0.1.5-alpha.2",
58
+ "@deepseek-ai/dsh-api-workspace-controller": "^0.1.5-alpha.2",
59
+ "@deepseek-ai/dsh-api-workspace-files": "^0.1.5-alpha.2",
60
+ "@deepseek-ai/dsh-attachment": "^0.1.5-alpha.2",
61
+ "@deepseek-ai/dsh-client-locale": "^0.1.5-alpha.2",
62
+ "@deepseek-ai/dsh-client-store": "^0.1.5-alpha.2",
63
+ "@deepseek-ai/dsh-client-ui-approval": "^0.1.5-alpha.2",
64
+ "@deepseek-ai/dsh-client-ui-conversation": "^0.1.5-alpha.2",
65
+ "@deepseek-ai/dsh-client-ui-layout": "^0.1.5-alpha.2",
66
+ "@deepseek-ai/dsh-client-ui-primitives": "^0.1.5-alpha.2",
67
+ "@deepseek-ai/dsh-client-ui-renderer": "^0.1.5-alpha.2",
68
+ "@deepseek-ai/dsh-client-ui-sidebar-right": "^0.1.5-alpha.2",
69
+ "@deepseek-ai/dsh-client-ui-slots": "^0.1.5-alpha.2",
70
+ "@deepseek-ai/dsh-client-ui-workspace": "^0.1.5-alpha.2",
71
+ "@deepseek-ai/dsh-commands": "^0.1.5-alpha.2",
72
+ "@deepseek-ai/dsh-compaction": "^0.1.5-alpha.2",
73
+ "@deepseek-ai/dsh-llm": "^0.1.5-alpha.2",
74
+ "@deepseek-ai/dsh-llm-retry": "^0.1.5-alpha.2",
75
+ "@deepseek-ai/dsh-session": "^0.1.5-alpha.2",
76
+ "@deepseek-ai/dsh-session-stats": "^0.1.5-alpha.2",
77
+ "@deepseek-ai/dsh-session-turn-outline": "^0.1.5-alpha.2",
78
+ "@deepseek-ai/dsh-settings": "^0.1.5-alpha.2",
79
+ "@deepseek-ai/dsh-token-meter": "^0.1.5-alpha.2",
80
+ "@deepseek-ai/dsh-tools": "^0.1.5-alpha.2",
81
+ "@deepseek-ai/dsh-util-workspace-path": "^0.1.5-alpha.2",
82
+ "@deepseek-ai/dsh-client-ui-settings": "^0.1.5-alpha.2",
83
+ "@deepseek-ai/dsh-client-ui-sidebar-documentpreview": "^0.1.5-alpha.2",
84
+ "@deepseek-ai/dsh-client-ui-session": "^0.1.5-alpha.2"
85
85
  },
86
86
  "dependencies": {
87
87
  "@deepseek-ai/schemastery": "^3.18.2"