@meiyukichan/dsh-sandore 0.1.0-rc.6

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.
Files changed (295) hide show
  1. package/LICENSE +201 -0
  2. package/cordis.patch.yml +39 -0
  3. package/dsh.plugin.json +16 -0
  4. package/lib/client/CommandEditor.d.ts +19 -0
  5. package/lib/client/DagEditor.d.ts +22 -0
  6. package/lib/client/DefinitionDetail.d.ts +13 -0
  7. package/lib/client/DefinitionList.d.ts +19 -0
  8. package/lib/client/DiscussionInput.d.ts +63 -0
  9. package/lib/client/DragHandle.d.ts +16 -0
  10. package/lib/client/EditorPane.d.ts +13 -0
  11. package/lib/client/FlowEditor.d.ts +31 -0
  12. package/lib/client/InstanceList.d.ts +24 -0
  13. package/lib/client/NewInstanceDialog.d.ts +19 -0
  14. package/lib/client/PreviewPanel.d.ts +13 -0
  15. package/lib/client/RunView.d.ts +79 -0
  16. package/lib/client/StepChatPanel.d.ts +34 -0
  17. package/lib/client/TreeNav.d.ts +27 -0
  18. package/lib/client/UnifiedTimeline.d.ts +11 -0
  19. package/lib/client/WorkflowButton.d.ts +11 -0
  20. package/lib/client/WorkflowList.d.ts +18 -0
  21. package/lib/client/WorkflowOverlay.d.ts +6 -0
  22. package/lib/client/chat/AssistantMarkdown.d.ts +22 -0
  23. package/lib/client/chat/CompactionItem.d.ts +24 -0
  24. package/lib/client/chat/ContextBody.d.ts +136 -0
  25. package/lib/client/chat/ContextInjectionRow.d.ts +25 -0
  26. package/lib/client/chat/GenericCommandCard.d.ts +10 -0
  27. package/lib/client/chat/MessageIconActions.d.ts +41 -0
  28. package/lib/client/chat/MessageItem.d.ts +65 -0
  29. package/lib/client/chat/ReasoningRow.d.ts +13 -0
  30. package/lib/client/chat/TurnTailNodeView.d.ts +29 -0
  31. package/lib/client/chat/UserMessageRow.d.ts +18 -0
  32. package/lib/client/chat/attachment/ImageLightbox.d.ts +26 -0
  33. package/lib/client/chat/attachment/MessageImage.d.ts +56 -0
  34. package/lib/client/chat/attachment/image-attachment.d.ts +41 -0
  35. package/lib/client/chat/attachment/image-labels.d.ts +21 -0
  36. package/lib/client/chat/message-chrome.d.ts +51 -0
  37. package/lib/client/chat/reference/ReferenceIcon.d.ts +20 -0
  38. package/lib/client/chat/turn-assistant.d.ts +12 -0
  39. package/lib/client/chat/turn-metrics.d.ts +42 -0
  40. package/lib/client/chat/use-calendar-day.d.ts +5 -0
  41. package/lib/client/chat/use-throttled-visual-update.d.ts +7 -0
  42. package/lib/client/chat-flow.d.ts +110 -0
  43. package/lib/client/composer-selects.d.ts +17 -0
  44. package/lib/client/dag-editor-model.d.ts +141 -0
  45. package/lib/client/describe-error.d.ts +9 -0
  46. package/lib/client/index.d.ts +6 -0
  47. package/lib/client/locales.d.ts +777 -0
  48. package/lib/client/model-faces.d.ts +156 -0
  49. package/lib/client/open-discussion.d.ts +24 -0
  50. package/lib/client/panel-model.d.ts +34 -0
  51. package/lib/client/remote.d.ts +34 -0
  52. package/lib/client/run-view-model.d.ts +304 -0
  53. package/lib/client/sandore-save.d.ts +41 -0
  54. package/lib/client/sandore-sse.d.ts +15 -0
  55. package/lib/client/step-chat-retry.d.ts +44 -0
  56. package/lib/client/tool/GenericToolCard.d.ts +28 -0
  57. package/lib/client/tool/ToolRow.d.ts +95 -0
  58. package/lib/client/tool/diff-card-model.d.ts +63 -0
  59. package/lib/client/tool/read-card-model.d.ts +67 -0
  60. package/lib/client/tool/search-card-model.d.ts +94 -0
  61. package/lib/client/tool/terminal-card-model.d.ts +86 -0
  62. package/lib/client/tool/tool-call-model.d.ts +74 -0
  63. package/lib/client/tool/web-card-model.d.ts +44 -0
  64. package/lib/client/use-focus-refresh.d.ts +1 -0
  65. package/lib/client/workflow-face.d.ts +68 -0
  66. package/lib/client/workflow-store.d.ts +80 -0
  67. package/lib/client/workspace-path.d.ts +15 -0
  68. package/lib/client.js +38389 -0
  69. package/lib/index.js +8854 -0
  70. package/lib/microflow/branch-evaluator.d.ts +290 -0
  71. package/lib/microflow/concurrency-limiter.d.ts +39 -0
  72. package/lib/microflow/errors.d.ts +39 -0
  73. package/lib/microflow/file-utils.d.ts +210 -0
  74. package/lib/microflow/finalize-manager.d.ts +414 -0
  75. package/lib/microflow/fork-session.d.ts +151 -0
  76. package/lib/microflow/index.d.ts +17 -0
  77. package/lib/microflow/internal.d.ts +56 -0
  78. package/lib/microflow/loop-manager.d.ts +127 -0
  79. package/lib/microflow/rules-resolver.d.ts +28 -0
  80. package/lib/microflow/stage-executor.d.ts +362 -0
  81. package/lib/microflow/step-navigator.d.ts +108 -0
  82. package/lib/microflow/step-runner.d.ts +190 -0
  83. package/lib/microflow/subagents.d.ts +380 -0
  84. package/lib/tool/index.d.ts +65 -0
  85. package/lib/typert.host.d.ts +16 -0
  86. package/lib/typert.host.js +25 -0
  87. package/lib/typert.remote-client.d.ts +114 -0
  88. package/lib/typert.remote-client.js +399 -0
  89. package/lib/workflow/ask-tool.d.ts +78 -0
  90. package/lib/workflow/dag-navigator.d.ts +136 -0
  91. package/lib/workflow/domain.d.ts +304 -0
  92. package/lib/workflow/engine-surface.d.ts +70 -0
  93. package/lib/workflow/errors.d.ts +13 -0
  94. package/lib/workflow/host-agent.d.ts +53 -0
  95. package/lib/workflow/index.d.ts +23 -0
  96. package/lib/workflow/interaction-manager.d.ts +170 -0
  97. package/lib/workflow/lifecycle-manager.d.ts +111 -0
  98. package/lib/workflow/persistence.d.ts +35 -0
  99. package/lib/workflow/plugin.d.ts +27 -0
  100. package/lib/workflow/reactive-state.d.ts +27 -0
  101. package/lib/workflow/recovery-manager.d.ts +158 -0
  102. package/lib/workflow/remote.d.ts +139 -0
  103. package/lib/workflow/schema.d.ts +1917 -0
  104. package/lib/workflow/seam.d.ts +254 -0
  105. package/lib/workflow/shell.d.ts +127 -0
  106. package/lib/workflow/sse.d.ts +16 -0
  107. package/lib/workflow/typert/typert.host.d.ts +16 -0
  108. package/lib/workflow/typert/typert.remote-client.d.ts +114 -0
  109. package/lib/workflow/types.d.ts +187 -0
  110. package/lib/workflow/wire.d.ts +256 -0
  111. package/lib/workflow/workflow-engine.d.ts +373 -0
  112. package/lib/workflow/yaml-error.d.ts +22 -0
  113. package/lib/workflow/yaml-parser.d.ts +23 -0
  114. package/package.json +140 -0
  115. package/packages/client/CommandEditor.tsx +73 -0
  116. package/packages/client/DagEditor.module.css +711 -0
  117. package/packages/client/DagEditor.tsx +1203 -0
  118. package/packages/client/DefinitionDetail.module.css +110 -0
  119. package/packages/client/DefinitionDetail.tsx +126 -0
  120. package/packages/client/DefinitionList.tsx +173 -0
  121. package/packages/client/DiscussionInput.tsx +763 -0
  122. package/packages/client/DragHandle.tsx +92 -0
  123. package/packages/client/EditorPane.tsx +70 -0
  124. package/packages/client/FlowEditor.tsx +227 -0
  125. package/packages/client/InstanceList.tsx +250 -0
  126. package/packages/client/NewInstanceDialog.module.css +244 -0
  127. package/packages/client/NewInstanceDialog.tsx +478 -0
  128. package/packages/client/PreviewPanel.tsx +55 -0
  129. package/packages/client/RunView.module.css +246 -0
  130. package/packages/client/RunView.tsx +314 -0
  131. package/packages/client/StepChatPanel.tsx +486 -0
  132. package/packages/client/TreeNav.tsx +294 -0
  133. package/packages/client/UnifiedTimeline.tsx +484 -0
  134. package/packages/client/WorkflowButton.module.css +72 -0
  135. package/packages/client/WorkflowButton.tsx +50 -0
  136. package/packages/client/WorkflowList.tsx +158 -0
  137. package/packages/client/WorkflowOverlay.module.css +390 -0
  138. package/packages/client/WorkflowOverlay.tsx +136 -0
  139. package/packages/client/WorkflowPanel.module.css +247 -0
  140. package/packages/client/chat/AssistantMarkdown.module.css +38 -0
  141. package/packages/client/chat/AssistantMarkdown.tsx +120 -0
  142. package/packages/client/chat/ChatView.module.css +198 -0
  143. package/packages/client/chat/CompactionItem.tsx +85 -0
  144. package/packages/client/chat/ContextBody.module.css +162 -0
  145. package/packages/client/chat/ContextBody.tsx +598 -0
  146. package/packages/client/chat/ContextInjectionRow.module.css +63 -0
  147. package/packages/client/chat/ContextInjectionRow.tsx +78 -0
  148. package/packages/client/chat/GenericCommandCard.module.css +87 -0
  149. package/packages/client/chat/GenericCommandCard.tsx +76 -0
  150. package/packages/client/chat/MessageIconActions.module.css +84 -0
  151. package/packages/client/chat/MessageIconActions.tsx +147 -0
  152. package/packages/client/chat/MessageItem.module.css +293 -0
  153. package/packages/client/chat/MessageItem.tsx +384 -0
  154. package/packages/client/chat/ReasoningRow.module.css +82 -0
  155. package/packages/client/chat/ReasoningRow.tsx +70 -0
  156. package/packages/client/chat/TurnTailNodeView.module.css +10 -0
  157. package/packages/client/chat/TurnTailNodeView.tsx +63 -0
  158. package/packages/client/chat/UserMessageRow.module.css +75 -0
  159. package/packages/client/chat/UserMessageRow.tsx +92 -0
  160. package/packages/client/chat/accessibility.module.css +9 -0
  161. package/packages/client/chat/attachment/ImageLightbox.module.css +45 -0
  162. package/packages/client/chat/attachment/ImageLightbox.tsx +70 -0
  163. package/packages/client/chat/attachment/MessageImage.module.css +70 -0
  164. package/packages/client/chat/attachment/MessageImage.tsx +136 -0
  165. package/packages/client/chat/attachment/image-attachment.ts +98 -0
  166. package/packages/client/chat/attachment/image-labels.ts +34 -0
  167. package/packages/client/chat/message-chrome.ts +96 -0
  168. package/packages/client/chat/reference/ReferenceIcon.tsx +40 -0
  169. package/packages/client/chat/turn-assistant.ts +15 -0
  170. package/packages/client/chat/turn-metrics.ts +102 -0
  171. package/packages/client/chat/use-calendar-day.ts +27 -0
  172. package/packages/client/chat/use-throttled-visual-update.ts +44 -0
  173. package/packages/client/chat-flow.spec.ts +357 -0
  174. package/packages/client/chat-flow.ts +278 -0
  175. package/packages/client/composer-selects.module.css +376 -0
  176. package/packages/client/composer-selects.tsx +531 -0
  177. package/packages/client/dag-editor-model.spec.ts +173 -0
  178. package/packages/client/dag-editor-model.ts +359 -0
  179. package/packages/client/describe-error.spec.ts +18 -0
  180. package/packages/client/describe-error.ts +12 -0
  181. package/packages/client/index.ts +144 -0
  182. package/packages/client/input.module.css +854 -0
  183. package/packages/client/is-conditional-check.spec.ts +34 -0
  184. package/packages/client/locales.ts +789 -0
  185. package/packages/client/model-faces.ts +225 -0
  186. package/packages/client/open-discussion.spec.ts +39 -0
  187. package/packages/client/open-discussion.ts +32 -0
  188. package/packages/client/panel-model.spec.ts +152 -0
  189. package/packages/client/panel-model.ts +72 -0
  190. package/packages/client/preview.module.css +95 -0
  191. package/packages/client/react-dom.d.ts +11 -0
  192. package/packages/client/reactflow-theme.css +91 -0
  193. package/packages/client/remote.spec.ts +41 -0
  194. package/packages/client/remote.ts +46 -0
  195. package/packages/client/run-view-model.spec.ts +641 -0
  196. package/packages/client/run-view-model.ts +636 -0
  197. package/packages/client/sandore-save.spec.ts +146 -0
  198. package/packages/client/sandore-save.ts +97 -0
  199. package/packages/client/sandore-sse.ts +59 -0
  200. package/packages/client/step-chat-retry.spec.ts +70 -0
  201. package/packages/client/step-chat-retry.ts +65 -0
  202. package/packages/client/timeline.module.css +503 -0
  203. package/packages/client/tool/GenericToolCard.tsx +99 -0
  204. package/packages/client/tool/ToolRow.module.css +308 -0
  205. package/packages/client/tool/ToolRow.tsx +328 -0
  206. package/packages/client/tool/diff-card-model.ts +103 -0
  207. package/packages/client/tool/read-card-model.ts +86 -0
  208. package/packages/client/tool/search-card-model.ts +166 -0
  209. package/packages/client/tool/terminal-card-model.ts +225 -0
  210. package/packages/client/tool/tool-call-model.ts +267 -0
  211. package/packages/client/tool/web-card-model.ts +80 -0
  212. package/packages/client/tree-nav.module.css +282 -0
  213. package/packages/client/use-focus-refresh.ts +23 -0
  214. package/packages/client/workflow-face.ts +72 -0
  215. package/packages/client/workflow-store.spec.ts +49 -0
  216. package/packages/client/workflow-store.ts +161 -0
  217. package/packages/client/workspace-path.ts +27 -0
  218. package/packages/css-modules.d.ts +6 -0
  219. package/packages/microflow/branch-evaluator.spec.ts +745 -0
  220. package/packages/microflow/branch-evaluator.ts +1037 -0
  221. package/packages/microflow/concurrency-limiter.ts +70 -0
  222. package/packages/microflow/errors.ts +64 -0
  223. package/packages/microflow/file-utils.spec.ts +604 -0
  224. package/packages/microflow/file-utils.ts +521 -0
  225. package/packages/microflow/finalize-manager.spec.ts +1977 -0
  226. package/packages/microflow/finalize-manager.ts +1464 -0
  227. package/packages/microflow/fork-session.spec.ts +184 -0
  228. package/packages/microflow/fork-session.ts +316 -0
  229. package/packages/microflow/index.ts +17 -0
  230. package/packages/microflow/internal.ts +166 -0
  231. package/packages/microflow/loop-manager.spec.ts +294 -0
  232. package/packages/microflow/loop-manager.ts +255 -0
  233. package/packages/microflow/rules-resolver.spec.ts +147 -0
  234. package/packages/microflow/rules-resolver.ts +58 -0
  235. package/packages/microflow/stage-executor.spec.ts +1577 -0
  236. package/packages/microflow/stage-executor.ts +1478 -0
  237. package/packages/microflow/step-navigator.spec.ts +301 -0
  238. package/packages/microflow/step-navigator.ts +300 -0
  239. package/packages/microflow/step-runner.spec.ts +1132 -0
  240. package/packages/microflow/step-runner.ts +752 -0
  241. package/packages/microflow/subagents.spec.ts +215 -0
  242. package/packages/microflow/subagents.ts +422 -0
  243. package/packages/tests/fixtures/test-workflow.yaml +128 -0
  244. package/packages/tests/mocks/agents.ts +206 -0
  245. package/packages/tests/mocks/llm.ts +46 -0
  246. package/packages/tests/mocks/session-title.ts +31 -0
  247. package/packages/tests/mocks/sessions.ts +131 -0
  248. package/packages/tests/mocks/shell.ts +60 -0
  249. package/packages/tests/mocks/storage-domain.ts +101 -0
  250. package/packages/tests/mocks/subagents.ts +197 -0
  251. package/packages/tests/mocks/subprocess.ts +59 -0
  252. package/packages/tests/mocks/user-questions.ts +33 -0
  253. package/packages/tests/mocks/workspace.ts +52 -0
  254. package/packages/tool/index.spec.ts +287 -0
  255. package/packages/tool/index.ts +348 -0
  256. package/packages/workflow/ask-tool.ts +173 -0
  257. package/packages/workflow/dag-navigator.spec.ts +236 -0
  258. package/packages/workflow/dag-navigator.ts +425 -0
  259. package/packages/workflow/domain.ts +26 -0
  260. package/packages/workflow/engine-surface.ts +71 -0
  261. package/packages/workflow/errors.ts +13 -0
  262. package/packages/workflow/host-agent.spec.ts +92 -0
  263. package/packages/workflow/host-agent.ts +62 -0
  264. package/packages/workflow/index.ts +25 -0
  265. package/packages/workflow/interaction-manager.spec.ts +390 -0
  266. package/packages/workflow/interaction-manager.ts +397 -0
  267. package/packages/workflow/lifecycle-manager.spec.ts +683 -0
  268. package/packages/workflow/lifecycle-manager.ts +288 -0
  269. package/packages/workflow/persistence.spec.ts +109 -0
  270. package/packages/workflow/persistence.ts +64 -0
  271. package/packages/workflow/plugin.ts +39 -0
  272. package/packages/workflow/reactive-state.spec.ts +69 -0
  273. package/packages/workflow/reactive-state.ts +52 -0
  274. package/packages/workflow/recovery-manager.spec.ts +606 -0
  275. package/packages/workflow/recovery-manager.ts +471 -0
  276. package/packages/workflow/remote.spec.ts +1045 -0
  277. package/packages/workflow/remote.ts +479 -0
  278. package/packages/workflow/schema.spec.ts +303 -0
  279. package/packages/workflow/schema.ts +562 -0
  280. package/packages/workflow/seam.ts +293 -0
  281. package/packages/workflow/shell.ts +142 -0
  282. package/packages/workflow/sse.ts +110 -0
  283. package/packages/workflow/typert/typert.host.d.ts +16 -0
  284. package/packages/workflow/typert/typert.host.js +25 -0
  285. package/packages/workflow/typert/typert.remote-client.d.ts +114 -0
  286. package/packages/workflow/typert/typert.remote-client.js +399 -0
  287. package/packages/workflow/types.ts +258 -0
  288. package/packages/workflow/wire.ts +267 -0
  289. package/packages/workflow/workflow-engine-e2e.spec.ts +262 -0
  290. package/packages/workflow/workflow-engine-real-e2e.spec.ts +922 -0
  291. package/packages/workflow/workflow-engine.spec.ts +4389 -0
  292. package/packages/workflow/workflow-engine.ts +2133 -0
  293. package/packages/workflow/yaml-error.ts +29 -0
  294. package/packages/workflow/yaml-parser.spec.ts +757 -0
  295. package/packages/workflow/yaml-parser.ts +287 -0
@@ -0,0 +1,82 @@
1
+ /* ReasoningRow.module.css:抄自 DSH ui-conversation chat/ReasoningRow.module.css。 */
2
+ .root {
3
+ display: flex;
4
+ flex-direction: column;
5
+ }
6
+
7
+ .row {
8
+ position: relative;
9
+ overflow: hidden;
10
+ }
11
+
12
+ .root[data-state='running'] .row::after {
13
+ content: '';
14
+ position: absolute;
15
+ inset-block: 0;
16
+ left: 0;
17
+ width: 300px;
18
+ background: linear-gradient(
19
+ 90deg,
20
+ transparent 0%,
21
+ color-mix(in srgb, var(--dsw-alias-bg-base) 60%, transparent) 55%,
22
+ transparent 100%
23
+ );
24
+ animation: dsh-reasoning-row-sweep 2.6s ease-out infinite;
25
+ pointer-events: none;
26
+ }
27
+
28
+ @keyframes dsh-reasoning-row-sweep {
29
+ 0% { left: -300px; }
30
+ 90%, 100% { left: 100%; }
31
+ }
32
+
33
+ .leading {
34
+ flex-shrink: 0;
35
+ }
36
+
37
+ .chevron {
38
+ color: var(--dsw-alias-label-secondary);
39
+ }
40
+
41
+ .title {
42
+ font-weight: 400;
43
+ }
44
+
45
+ .separator {
46
+ flex: none;
47
+ width: 2px;
48
+ height: 2px;
49
+ margin: 0 8px;
50
+ border-radius: 1px;
51
+ background: var(--dsw-alias-label-caption);
52
+ }
53
+
54
+ .summary {
55
+ min-width: 0;
56
+ overflow: hidden;
57
+ flex: 1 1 auto;
58
+ color: var(--dsw-alias-label-tertiary);
59
+ font-size: 14px;
60
+ line-height: 24px;
61
+ text-overflow: ellipsis;
62
+ white-space: nowrap;
63
+ }
64
+
65
+ .summary[data-follow-end] {
66
+ text-overflow: clip;
67
+ }
68
+
69
+ .thinkBody {
70
+ padding: 4px 0 4px 22px;
71
+ color: var(--dsw-alias-label-tertiary);
72
+ font-size: 14px;
73
+ line-height: 24px;
74
+ white-space: pre-wrap;
75
+ word-break: break-word;
76
+ }
77
+
78
+ @media (prefers-reduced-motion: reduce) {
79
+ .root[data-state='running'] .row::after {
80
+ animation: none;
81
+ }
82
+ }
@@ -0,0 +1,70 @@
1
+ /**
2
+ * ReasoningRow:抄自 DSH `packages/client/ui-conversation/src/client/chat/ReasoningRow.tsx`。
3
+ * assistant reasoning 披露行(Think 摘要行,展开=缩进灰字),独立于工具卡片呈现。
4
+ * locale 面收窄为 sandore 命名空间,其余逐字保留。
5
+ * @module @deepseek-ai/dsh-client-ui-sandore/src/client/chat/ReasoningRow
6
+ */
7
+ import { useEffect, useRef, useState } from 'react'
8
+ import { DisclosureRow, IconThinkOutline14 } from '@deepseek-ai/dsh-client-ui-primitives'
9
+ import type { TranslateNS } from '@deepseek-ai/dsh-client-ui-slots'
10
+ import { useThrottledVisualUpdate } from './use-throttled-visual-update.ts'
11
+ import a11yCss from './accessibility.module.css'
12
+ import css from './ReasoningRow.module.css'
13
+
14
+ function firstLine(text: string): string {
15
+ const newline = text.indexOf('\n')
16
+ return newline === -1 ? text : text.slice(0, newline)
17
+ }
18
+
19
+ function latestLine(text: string): string {
20
+ const visible = text.trimEnd()
21
+ const newline = visible.lastIndexOf('\n')
22
+ return newline === -1 ? visible : visible.slice(newline + 1)
23
+ }
24
+
25
+ /**
26
+ * Render one assistant reasoning block as the Think disclosure row.
27
+ * @param props.text - complete or streaming reasoning text.
28
+ * @param props.running - whether this block is the streaming tail.
29
+ * @param props.t - sandore locale seat for the running status.
30
+ * @returns the reasoning disclosure.
31
+ */
32
+ export function ReasoningRow({ text, running, t }: { text: string; running: boolean; t: TranslateNS<'sandore'> }) {
33
+ const [expanded, setExpanded] = useState(false)
34
+ const summaryRef = useRef<HTMLSpanElement>(null)
35
+ const summary = running ? latestLine(text) : firstLine(text)
36
+ const scheduleSummaryScroll = useThrottledVisualUpdate(() => {
37
+ const element = summaryRef.current
38
+ if (element === null) return
39
+ element.scrollLeft = running ? element.scrollWidth - element.clientWidth : 0
40
+ })
41
+ useEffect(() => {
42
+ scheduleSummaryScroll()
43
+ }, [running, scheduleSummaryScroll, summary])
44
+
45
+ return (
46
+ <div className={css.root} data-variant="think" data-state={running ? 'running' : 'ok'}>
47
+ {running && <span className={a11yCss.visuallyHidden}>{t('row.running')}</span>}
48
+ <DisclosureRow
49
+ rowClassName={css.row}
50
+ leadingClassName={css.leading}
51
+ titleClassName={css.title}
52
+ chevronClassName={css.chevron}
53
+ icon={<IconThinkOutline14 size={14} />}
54
+ title="Think"
55
+ open={expanded}
56
+ expandable
57
+ expandOnRowClick
58
+ onToggle={() => { setExpanded(value => !value) }}
59
+ collapsedContent={(
60
+ <>
61
+ <span className={css.separator} aria-hidden />
62
+ <span ref={summaryRef} className={css.summary} data-follow-end={running || undefined}>{summary}</span>
63
+ </>
64
+ )}
65
+ >
66
+ <div className={css.thinkBody}>{text}</div>
67
+ </DisclosureRow>
68
+ </div>
69
+ )
70
+ }
@@ -0,0 +1,10 @@
1
+ /* TurnTailNodeView.module.css:抄自 DSH ui-conversation chat/TurnTailNodeView.module.css(逐字)。 */
2
+ .root {
3
+ display: flex;
4
+ flex-direction: column;
5
+ gap: 16px;
6
+ }
7
+
8
+ .actions {
9
+ margin-left: -6px;
10
+ }
@@ -0,0 +1,63 @@
1
+ /**
2
+ * TurnTailNodeView:抄自 DSH `packages/client/ui-conversation/src/client/chat/TurnTailNodeView.tsx`。
3
+ * 已完结 turn 的本地动作与特性尾部:时间 + 运行时长/TTFT/吞吐 + 复制 + 分支(fork)。
4
+ * 裁剪:`conversation.chat.turnTail` chain 与 `conversation.chat.assistant-actions` list
5
+ * 两个 slot(sandore 面板不注册任何会话级 slot,等价于 DSH 无条目注入时的空链);
6
+ * `hasLaterChatNode` 判断由 chat-flow 派生为 `branchUnavailable` 传入。locale 面收窄为
7
+ * sandore 命名空间。其余逐字保留。
8
+ * @module @deepseek-ai/dsh-client-ui-sandore/src/client/chat/TurnTailNodeView
9
+ */
10
+ import { memo } from 'react'
11
+ import type { TranslateNS } from '@deepseek-ai/dsh-client-ui-slots'
12
+ import { MessageIconActions } from './MessageIconActions.tsx'
13
+ import css from './TurnTailNodeView.module.css'
14
+
15
+ /** turn-tail 展示数据(chat-flow 派生;字段对齐 DSH TurnTailChatData 的展示面)。 */
16
+ export interface StepChatTailData {
17
+ /** 已完结 turn 号。 */
18
+ turn: number
19
+ /** 结算 assistant 节点 seq(分支锚点)。 */
20
+ seq: number
21
+ /** 结算时间(Unix epoch ms;时钟用)。 */
22
+ time: number
23
+ /** 结算 assistant 的拼接文本(复制按钮取文本)。 */
24
+ text: string
25
+ /** Turn 壁钟时长 ms;turn/start|end 均在窗口内时可用。 */
26
+ runMs?: number | undefined
27
+ /** Turn 首步 TTFT ms;未记录时省略。 */
28
+ ttftMs?: number | undefined
29
+ /** Turn 解码吞吐;未记录时省略。 */
30
+ tokensPerSecond?: number | undefined
31
+ /** 分支不可用(结算 assistant 非 turn 尾部等;chat-flow 派生)。 */
32
+ branchUnavailable: boolean
33
+ }
34
+
35
+ /** Turn-local actions and feature tail over the closing Assistant, independent of Assistant placement. */
36
+ export const TurnTailNodeView = memo(function TurnTailNodeView({
37
+ data, onBranch, t,
38
+ }: {
39
+ /** 由 chat-flow 派生的 turn-tail 展示数据。 */
40
+ data: StepChatTailData
41
+ /** 分支回调:以结算 seq 为锚 fork 会话(`sessions.fork`,与 DSH forkAt 同语义)。 */
42
+ onBranch: (seq: number) => void
43
+ /** sandore locale seat。 */
44
+ t: TranslateNS<'sandore'>
45
+ }) {
46
+ const runMs = data.runMs
47
+ return (
48
+ <div className={css.root} data-turn-tail={data.turn} data-time-hover-root>
49
+ <MessageIconActions
50
+ text={data.text}
51
+ time={data.time}
52
+ runMs={runMs}
53
+ ttftMs={data.ttftMs}
54
+ tokensPerSecond={data.tokensPerSecond}
55
+ clock="end"
56
+ onBranch={() => { onBranch(data.seq) }}
57
+ branchUnavailable={data.branchUnavailable}
58
+ className={css.actions}
59
+ t={t}
60
+ />
61
+ </div>
62
+ )
63
+ })
@@ -0,0 +1,75 @@
1
+ /* UserMessageRow.module.css:sandore 面板的用户消息行式样式(非 DSH 抄入——DSH 用户消息是
2
+ 右侧气泡;面板按「左侧行式」需求实现,视觉对齐 ToolRow / ContextInjectionRow 的
3
+ DisclosureRow 体系:24px 单行、16px leading 槽、2x2 分隔点、单行省略摘要、展开体)。 */
4
+
5
+ /* 展开时行底留 4px,与上下文注入行的展开节奏一致。 */
6
+ .root[data-open] {
7
+ padding-bottom: 4px;
8
+ }
9
+
10
+ /* 展开/悬停预览的 chevron 颜色(与 ToolRow / ContextInjectionRow 一致)。 */
11
+ .chevron {
12
+ color: var(--dsw-alias-label-secondary);
13
+ }
14
+
15
+ /* 标题与摘要之间的分隔点(ToolRow / ContextInjectionRow 同款 2x2 圆点)。 */
16
+ .sep {
17
+ flex: none;
18
+ width: 2px;
19
+ height: 2px;
20
+ margin: 0 8px;
21
+ border-radius: 1px;
22
+ background: var(--dsw-alias-label-caption);
23
+ }
24
+
25
+ /* 单行用户消息摘要:FILL 截断 + 省略号;多行文本(换行)被 `white-space: nowrap`
26
+ 折叠为单行,超宽时 `text-overflow: ellipsis` 截断。 */
27
+ .summary {
28
+ flex: 1 1 auto;
29
+ min-width: 0;
30
+ overflow: hidden;
31
+ color: var(--dsw-alias-label-tertiary);
32
+ font-size: 14px;
33
+ line-height: 24px;
34
+ text-overflow: ellipsis;
35
+ white-space: nowrap;
36
+ }
37
+
38
+ /* 尾部时钟(同用户气泡的时钟 chrome):flex:none 不参与省略——窄行先截摘要再截时钟,
39
+ ToolRow summarySuffix 同款语义;tabular-nums 让时钟宽度稳定。 */
40
+ .clock {
41
+ flex: none;
42
+ margin-left: 8px;
43
+ color: var(--dsw-alias-label-caption);
44
+ font-size: 12px;
45
+ line-height: 18px;
46
+ font-variant-numeric: tabular-nums;
47
+ white-space: nowrap;
48
+ }
49
+
50
+ /* 展开体:完整用户消息文本框。几何对齐 ContextInjectionRow 的展开体(22px 缩进、圆角 8、
51
+ code-block 底),但用正文字号(14/24)而非代码字号;pre-wrap 保留用户消息的换行分段。 */
52
+ .body {
53
+ box-sizing: border-box;
54
+ display: flex;
55
+ flex-direction: column;
56
+ gap: 8px;
57
+ width: calc(100% - 22px);
58
+ max-height: 240px;
59
+ margin: 4px 0 0 22px;
60
+ overflow: auto;
61
+ padding: 10px 16px 12px 12px;
62
+ border: none;
63
+ border-radius: 8px;
64
+ background: var(--dsw-alias-markdown-code-block);
65
+ color: var(--dsw-alias-label-secondary);
66
+ }
67
+
68
+ /* 完整消息文本:保留换行 + 任意位置断行(长 URL/长词不撑破文本框)。 */
69
+ .bodyText {
70
+ white-space: pre-wrap;
71
+ overflow-wrap: anywhere;
72
+ font-size: 14px;
73
+ line-height: 24px;
74
+ color: var(--dsw-alias-label-secondary);
75
+ }
@@ -0,0 +1,92 @@
1
+ /**
2
+ * UserMessageRow:sandore 面板的用户消息行式渲染(非 DSH 抄入——DSH 的用户消息是右侧气泡,
3
+ * 面板按「左侧行式」需求实现,视觉对齐 ToolRow / ContextInjectionRow 的 DisclosureRow
4
+ * chrome:16px leading 槽(用户图标,hover/展开变 chevron)+ "User Message" 标签 + 分隔点 +
5
+ * 单行省略摘要 + 尾部时钟;整行点击(Enter/Space)展开完整用户消息文本框)。
6
+ *
7
+ * 数据面:`UserMessageNode` / `SteeringMessageNode`(公开 `ConversationNode`,二者同走
8
+ * 用户行渲染)——`content: ContentBlock[]` 提取纯文本(text 块以换行拼接)作单行摘要
9
+ * (CSS 单行省略,换行被折叠);展开体显示完整文本(pre-wrap 保留换行)+ 图片画廊
10
+ * (align start,与左对齐行式一致)+ 其余块经 JsonBlock 披露(与右气泡的 extra block 同款)。
11
+ * 展开态为组件本地 view state。
12
+ * @module @deepseek-ai/dsh-client-ui-sandore/src/client/chat/UserMessageRow
13
+ */
14
+ import { memo, useState } from 'react'
15
+ import type { ConversationNode } from '@deepseek-ai/dsh-client-runtime/client'
16
+ import { DisclosureRow, IconUserOutline16, JsonBlock } from '@deepseek-ai/dsh-client-ui-primitives'
17
+ import type { TranslateNS } from '@deepseek-ai/dsh-client-ui-slots'
18
+ import type { SandoreRenderMessageImages } from './attachment/MessageImage.tsx'
19
+ import { formatMessageClock } from './message-chrome.ts'
20
+ import css from './UserMessageRow.module.css'
21
+
22
+ type UserNode = Extract<ConversationNode, { kind: 'user' | 'steering' }>
23
+ type UserImage = Extract<UserNode['content'][number], { type: 'image' }>
24
+
25
+ /** 内容块拆分:text 纯文本拼接 / image 附件(供画廊)/ 其余块(JsonBlock 披露)。 */
26
+ function contentParts(content: readonly unknown[]): {
27
+ text: string
28
+ images: { attachment: UserImage['attachment'] }[]
29
+ rest: unknown[]
30
+ } {
31
+ const texts: string[] = []
32
+ const images: { attachment: UserImage['attachment'] }[] = []
33
+ const rest: unknown[] = []
34
+ for (const block of content) {
35
+ const b = block as { type?: string; text?: string; attachment?: unknown }
36
+ if (b.type === 'text' && typeof b.text === 'string') texts.push(b.text)
37
+ else if (b.type === 'image' && b.attachment !== undefined) {
38
+ images.push({ attachment: (b as UserImage).attachment })
39
+ }
40
+ else rest.push(block)
41
+ }
42
+ // 多 text 块以换行拼接:单行摘要由 CSS `white-space: nowrap` 折叠换行,展开体 pre-wrap 保留分段。
43
+ return { text: texts.join('\n'), images, rest }
44
+ }
45
+
46
+ /**
47
+ * 用户消息行:DisclosureRow 行式(左对齐)——用户图标 + "User Message" 标签 + 分隔点 +
48
+ * 单行省略的用户消息文本 + 尾部时钟;点击整行展开完整用户消息文本框。
49
+ * @param props - 用户/steering 节点、图片画廊渲染器与 locale。
50
+ * @returns 折叠为单行的用户消息披露行。
51
+ */
52
+ export const UserMessageRow = memo(function UserMessageRow({ node, renderMessageImages, t }: {
53
+ node: UserNode
54
+ renderMessageImages: SandoreRenderMessageImages
55
+ t: TranslateNS<'sandore'>
56
+ }) {
57
+ const [expanded, setExpanded] = useState(false)
58
+ const { text, images, rest } = contentParts(node.content)
59
+ const truncated = (total: number): string => t('json.truncated', { total })
60
+ // 空消息(无文本/图片/其他块)只有标题,不可展开。
61
+ const expandable = text !== '' || images.length > 0 || rest.length > 0
62
+ return (
63
+ <DisclosureRow
64
+ className={css.root}
65
+ chevronClassName={css.chevron}
66
+ icon={<IconUserOutline16 size={16} />}
67
+ title={t('message.userMessage')}
68
+ open={expanded}
69
+ expandable={expandable}
70
+ expandOnRowClick
71
+ onToggle={() => { setExpanded(value => !value) }}
72
+ collapsedContent={text !== '' && (
73
+ /* ToolRow / ContextInjectionRow 的摘要形态:分隔点 + 单行省略文本;时钟 flex:none
74
+ 排在摘要之后,窄行先截摘要再截时钟(summarySuffix 同款语义)。 */
75
+ <>
76
+ <span className={css.sep} aria-hidden />
77
+ <span className={css.summary} data-user-summary>{text}</span>
78
+ <span className={css.clock} data-user-clock>{formatMessageClock(node.time, t)}</span>
79
+ </>
80
+ )}
81
+ >
82
+ {/* 展开体(DisclosureRow children):完整用户消息内容——图片画廊 + 完整文本 + 其余块。 */}
83
+ <div className={css.body} data-user-message-body>
84
+ {images.length > 0 && renderMessageImages({ images, align: 'start' })}
85
+ {text !== '' && <div className={css.bodyText} data-user-body-text>{text}</div>}
86
+ {rest.map((block, i) => (
87
+ <JsonBlock key={i} label={t('message.extraBlock')} payload={block} truncatedLabel={truncated} />
88
+ ))}
89
+ </div>
90
+ </DisclosureRow>
91
+ )
92
+ })
@@ -0,0 +1,9 @@
1
+ /* accessibility.module.css:抄自 DSH ui-conversation chat/accessibility.module.css(视觉隐藏)。 */
2
+ .visuallyHidden {
3
+ position: absolute;
4
+ width: 1px;
5
+ height: 1px;
6
+ overflow: hidden;
7
+ clip: rect(0 0 0 0);
8
+ white-space: nowrap;
9
+ }
@@ -0,0 +1,45 @@
1
+ /* ImageLightbox.module.css:抄自 DSH ui-attachment ImageLightbox.module.css(逐字)。 */
2
+ .backdrop {
3
+ position: fixed;
4
+ inset: 0;
5
+ z-index: 1000;
6
+ display: grid;
7
+ place-items: center;
8
+ padding: 40px;
9
+ }
10
+
11
+ /* Same mask recipe as the Modal primitive and the settings dialog. A separate
12
+ layer, not a background on .backdrop: backdrop-filter there would blur the
13
+ previewed image and the close control along with the page. */
14
+ .mask {
15
+ position: absolute;
16
+ inset: 0;
17
+ background: var(--dsw-alias-bg-mask-1);
18
+ backdrop-filter: var(--dsw-mask-blur);
19
+ }
20
+
21
+ .image {
22
+ position: relative;
23
+ max-width: min(100%, 1600px);
24
+ max-height: calc(100vh - 80px);
25
+ object-fit: contain;
26
+ border-radius: 12px;
27
+ background: var(--dsw-specific-input-major);
28
+ box-shadow: var(--dsw-shadow-lv3);
29
+ }
30
+
31
+ .close {
32
+ position: fixed;
33
+ top: 20px;
34
+ right: 20px;
35
+ z-index: 1;
36
+ display: grid;
37
+ place-items: center;
38
+ width: 36px;
39
+ height: 36px;
40
+ border: 1px solid var(--dsw-alias-border-l2-darkmode-thin);
41
+ border-radius: 999px;
42
+ background: var(--dsw-specific-input-major);
43
+ color: var(--dsw-alias-label-primary);
44
+ cursor: pointer;
45
+ }
@@ -0,0 +1,70 @@
1
+ /**
2
+ * ImageLightbox:抄自 DSH `packages/client/ui-attachment/src/ImageLightbox.tsx`(逐字)。
3
+ * 点击缩略图打开的文档级原图预览:Esc / 背景按下 / 关闭按钮关闭,卸载时恢复焦点到
4
+ * 打开者;经 body portal 渲染(避免被 transform/filter 祖先困住)。
5
+ * @module @deepseek-ai/dsh-client-ui-sandore/src/client/chat/attachment/ImageLightbox
6
+ */
7
+ import { useEffect, useRef } from 'react'
8
+ import { createPortal } from 'react-dom'
9
+ import { IconCloseOutline16 } from '@deepseek-ai/dsh-client-ui-primitives'
10
+ import css from './ImageLightbox.module.css'
11
+
12
+ /** Lightbox strings the owner resolves from its own locale namespace. */
13
+ export interface ImageLightboxLabels {
14
+ /** Accessible name of the preview dialog. */
15
+ dialog: string
16
+ /** Accessible label of the close control. */
17
+ close: string
18
+ }
19
+
20
+ /**
21
+ * Document-level original-image preview opened by clicking a thumbnail.
22
+ * Closes on Escape, backdrop press, or the close control, and restores focus
23
+ * to the opener on unmount. Rendered through a body portal: an opener inside
24
+ * a transformed or filtered ancestor would otherwise trap the fixed backdrop
25
+ * in that ancestor's box instead of covering the viewport.
26
+ *
27
+ * @param props.src - the original image URL.
28
+ * @param props.alt - the image's alt text.
29
+ * @param props.labels - dialog and close-control strings.
30
+ * @param props.onClose - dismiss callback owned by the opener.
31
+ * @returns the modal preview dialog.
32
+ */
33
+ export function ImageLightbox({ src, alt, labels, onClose }: {
34
+ src: string
35
+ alt: string
36
+ labels: ImageLightboxLabels
37
+ onClose: () => void
38
+ }) {
39
+ const closeRef = useRef<HTMLButtonElement | null>(null)
40
+ const restoreRef = useRef<HTMLElement | null>(null)
41
+
42
+ useEffect(() => {
43
+ restoreRef.current = document.activeElement instanceof HTMLElement ? document.activeElement : null
44
+ closeRef.current?.focus()
45
+ const onKeyDown = (event: globalThis.KeyboardEvent): void => {
46
+ if (event.key === 'Escape') onClose()
47
+ }
48
+ window.addEventListener('keydown', onKeyDown)
49
+ return () => {
50
+ window.removeEventListener('keydown', onKeyDown)
51
+ restoreRef.current?.focus()
52
+ }
53
+ }, [onClose])
54
+
55
+ return createPortal(
56
+ <div
57
+ className={css.backdrop}
58
+ role="dialog"
59
+ aria-modal="true"
60
+ aria-label={labels.dialog}
61
+ >
62
+ <div className={css.mask} aria-hidden="true" onMouseDown={onClose} />
63
+ <img className={css.image} src={src} alt={alt} />
64
+ <button ref={closeRef} type="button" className={css.close} aria-label={labels.close} onClick={onClose}>
65
+ <IconCloseOutline16 size={16} />
66
+ </button>
67
+ </div>,
68
+ document.body,
69
+ )
70
+ }
@@ -0,0 +1,70 @@
1
+ /* MessageImage.module.css:抄自 DSH ui-attachment MessageImage.module.css(逐字)。 */
2
+ .gallery {
3
+ display: flex;
4
+ flex-wrap: wrap;
5
+ gap: 10px;
6
+ max-width: 100%;
7
+ }
8
+
9
+ .gallery[data-align='end'] {
10
+ justify-content: flex-end;
11
+ align-self: flex-end;
12
+ }
13
+
14
+ .gallery[data-align='start'] {
15
+ justify-content: flex-start;
16
+ align-self: flex-start;
17
+ }
18
+
19
+ .frame {
20
+ display: grid;
21
+ flex: 0 0 auto;
22
+ place-items: center;
23
+ min-width: 44px;
24
+ min-height: 44px;
25
+ padding: 0;
26
+ overflow: hidden;
27
+ border: 1px solid var(--dsw-alias-border-l2-darkmode-thin);
28
+ border-radius: 16px;
29
+ background: var(--dsw-alias-interactive-bg-hover);
30
+ cursor: zoom-in;
31
+ }
32
+
33
+ .frame[data-variant='tile'] {
34
+ width: 64px;
35
+ height: 64px;
36
+ min-width: 64px;
37
+ min-height: 64px;
38
+ }
39
+
40
+ .frame img {
41
+ display: block;
42
+ width: 100%;
43
+ height: 100%;
44
+ object-fit: cover;
45
+ }
46
+
47
+ .loading,
48
+ .error {
49
+ color: var(--dsw-alias-label-tertiary);
50
+ font-size: 12px;
51
+ line-height: 18px;
52
+ }
53
+
54
+ .error {
55
+ max-width: 240px;
56
+ padding: 10px 12px;
57
+ border: 1px solid var(--dsw-alias-border-l2-darkmode-thin);
58
+ border-radius: 10px;
59
+ background: var(--dsw-alias-interactive-bg-hover-danger);
60
+ cursor: pointer;
61
+ }
62
+
63
+ /* A failed tile keeps the 64px grid cell instead of growing to its copy. */
64
+ .error[data-variant='tile'] {
65
+ width: 64px;
66
+ height: 64px;
67
+ padding: 4px;
68
+ overflow: hidden;
69
+ border-radius: 16px;
70
+ }