dsh-better-display 0.1.1

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 (300) hide show
  1. package/CHANGELOG.md +51 -0
  2. package/DESIGN.md +72 -0
  3. package/LICENSE +24 -0
  4. package/README.en.md +41 -0
  5. package/README.md +41 -0
  6. package/THIRD_PARTY_NOTICES.md +65 -0
  7. package/cordis.patch.yml +5 -0
  8. package/cordis.yml +4 -0
  9. package/dshx.yml +5 -0
  10. package/lib/client.js +49923 -0
  11. package/lib/client.js.map +1 -0
  12. package/lib/dsh-better-display.js +256 -0
  13. package/lib/types/client/Blocks.d.ts +45 -0
  14. package/lib/types/client/Blocks.d.ts.map +1 -0
  15. package/lib/types/client/Blocks.js +136 -0
  16. package/lib/types/client/Blocks.js.map +1 -0
  17. package/lib/types/client/ChoreographedFlow.d.ts +22 -0
  18. package/lib/types/client/ChoreographedFlow.d.ts.map +1 -0
  19. package/lib/types/client/ChoreographedFlow.js +170 -0
  20. package/lib/types/client/ChoreographedFlow.js.map +1 -0
  21. package/lib/types/client/ClosedProcessSummary.d.ts +9 -0
  22. package/lib/types/client/ClosedProcessSummary.d.ts.map +1 -0
  23. package/lib/types/client/ClosedProcessSummary.js +15 -0
  24. package/lib/types/client/ClosedProcessSummary.js.map +1 -0
  25. package/lib/types/client/LiveFold.d.ts +10 -0
  26. package/lib/types/client/LiveFold.d.ts.map +1 -0
  27. package/lib/types/client/LiveFold.js +39 -0
  28. package/lib/types/client/LiveFold.js.map +1 -0
  29. package/lib/types/client/McpAppFrame.d.ts +32 -0
  30. package/lib/types/client/McpAppFrame.d.ts.map +1 -0
  31. package/lib/types/client/McpAppFrame.js +193 -0
  32. package/lib/types/client/McpAppFrame.js.map +1 -0
  33. package/lib/types/client/Reader.d.ts +3 -0
  34. package/lib/types/client/Reader.d.ts.map +1 -0
  35. package/lib/types/client/Reader.js +537 -0
  36. package/lib/types/client/Reader.js.map +1 -0
  37. package/lib/types/client/ReasoningCard.d.ts +11 -0
  38. package/lib/types/client/ReasoningCard.d.ts.map +1 -0
  39. package/lib/types/client/ReasoningCard.js +301 -0
  40. package/lib/types/client/ReasoningCard.js.map +1 -0
  41. package/lib/types/client/StickyLane.d.ts +8 -0
  42. package/lib/types/client/StickyLane.d.ts.map +1 -0
  43. package/lib/types/client/StickyLane.js +28 -0
  44. package/lib/types/client/StickyLane.js.map +1 -0
  45. package/lib/types/client/TimelineRail.d.ts +10 -0
  46. package/lib/types/client/TimelineRail.d.ts.map +1 -0
  47. package/lib/types/client/TimelineRail.js +168 -0
  48. package/lib/types/client/TimelineRail.js.map +1 -0
  49. package/lib/types/client/ToolActivity.d.ts +17 -0
  50. package/lib/types/client/ToolActivity.d.ts.map +1 -0
  51. package/lib/types/client/ToolActivity.js +192 -0
  52. package/lib/types/client/ToolActivity.js.map +1 -0
  53. package/lib/types/client/TurnMetrics.d.ts +11 -0
  54. package/lib/types/client/TurnMetrics.d.ts.map +1 -0
  55. package/lib/types/client/TurnMetrics.js +44 -0
  56. package/lib/types/client/TurnMetrics.js.map +1 -0
  57. package/lib/types/client/WaitingStatus.d.ts +6 -0
  58. package/lib/types/client/WaitingStatus.d.ts.map +1 -0
  59. package/lib/types/client/WaitingStatus.js +19 -0
  60. package/lib/types/client/WaitingStatus.js.map +1 -0
  61. package/lib/types/client/conversation-scroll.d.ts +19 -0
  62. package/lib/types/client/conversation-scroll.d.ts.map +1 -0
  63. package/lib/types/client/conversation-scroll.js +25 -0
  64. package/lib/types/client/conversation-scroll.js.map +1 -0
  65. package/lib/types/client/deliverables.d.ts +24 -0
  66. package/lib/types/client/deliverables.d.ts.map +1 -0
  67. package/lib/types/client/deliverables.js +104 -0
  68. package/lib/types/client/deliverables.js.map +1 -0
  69. package/lib/types/client/entry-policy.d.ts +10 -0
  70. package/lib/types/client/entry-policy.d.ts.map +1 -0
  71. package/lib/types/client/entry-policy.js +24 -0
  72. package/lib/types/client/entry-policy.js.map +1 -0
  73. package/lib/types/client/entry.d.ts +4 -0
  74. package/lib/types/client/entry.d.ts.map +1 -0
  75. package/lib/types/client/entry.js +34 -0
  76. package/lib/types/client/entry.js.map +1 -0
  77. package/lib/types/client/fold-choreography.d.ts +28 -0
  78. package/lib/types/client/fold-choreography.d.ts.map +1 -0
  79. package/lib/types/client/fold-choreography.js +31 -0
  80. package/lib/types/client/fold-choreography.js.map +1 -0
  81. package/lib/types/client/index.d.ts +7 -0
  82. package/lib/types/client/index.d.ts.map +1 -0
  83. package/lib/types/client/index.js +153 -0
  84. package/lib/types/client/index.js.map +1 -0
  85. package/lib/types/client/live-turn.d.ts +58 -0
  86. package/lib/types/client/live-turn.d.ts.map +1 -0
  87. package/lib/types/client/live-turn.js +144 -0
  88. package/lib/types/client/live-turn.js.map +1 -0
  89. package/lib/types/client/markdown/MarkdownText.d.ts +39 -0
  90. package/lib/types/client/markdown/MarkdownText.d.ts.map +1 -0
  91. package/lib/types/client/markdown/MarkdownText.js +171 -0
  92. package/lib/types/client/markdown/MarkdownText.js.map +1 -0
  93. package/lib/types/client/markdown/cjkFriendlyStrong.d.ts +9 -0
  94. package/lib/types/client/markdown/cjkFriendlyStrong.d.ts.map +1 -0
  95. package/lib/types/client/markdown/cjkFriendlyStrong.js +73 -0
  96. package/lib/types/client/markdown/cjkFriendlyStrong.js.map +1 -0
  97. package/lib/types/client/markdown/incremental.d.ts +69 -0
  98. package/lib/types/client/markdown/incremental.d.ts.map +1 -0
  99. package/lib/types/client/markdown/incremental.js +108 -0
  100. package/lib/types/client/markdown/incremental.js.map +1 -0
  101. package/lib/types/client/markdown/katex.d.ts +27 -0
  102. package/lib/types/client/markdown/katex.d.ts.map +1 -0
  103. package/lib/types/client/markdown/katex.js +88 -0
  104. package/lib/types/client/markdown/katex.js.map +1 -0
  105. package/lib/types/client/markdown/mathCompatibility.d.ts +11 -0
  106. package/lib/types/client/markdown/mathCompatibility.d.ts.map +1 -0
  107. package/lib/types/client/markdown/mathCompatibility.js +293 -0
  108. package/lib/types/client/markdown/mathCompatibility.js.map +1 -0
  109. package/lib/types/client/markdown/parse.d.ts +25 -0
  110. package/lib/types/client/markdown/parse.d.ts.map +1 -0
  111. package/lib/types/client/markdown/parse.js +42 -0
  112. package/lib/types/client/markdown/parse.js.map +1 -0
  113. package/lib/types/client/markdown/render.d.ts +119 -0
  114. package/lib/types/client/markdown/render.d.ts.map +1 -0
  115. package/lib/types/client/markdown/render.js +435 -0
  116. package/lib/types/client/markdown/render.js.map +1 -0
  117. package/lib/types/client/mcp-app.d.ts +50 -0
  118. package/lib/types/client/mcp-app.d.ts.map +1 -0
  119. package/lib/types/client/mcp-app.js +328 -0
  120. package/lib/types/client/mcp-app.js.map +1 -0
  121. package/lib/types/client/message-chrome.d.ts +19 -0
  122. package/lib/types/client/message-chrome.d.ts.map +1 -0
  123. package/lib/types/client/message-chrome.js +42 -0
  124. package/lib/types/client/message-chrome.js.map +1 -0
  125. package/lib/types/client/motion.d.ts +38 -0
  126. package/lib/types/client/motion.d.ts.map +1 -0
  127. package/lib/types/client/motion.js +367 -0
  128. package/lib/types/client/motion.js.map +1 -0
  129. package/lib/types/client/native/ContextBody.d.ts +130 -0
  130. package/lib/types/client/native/ContextBody.d.ts.map +1 -0
  131. package/lib/types/client/native/ContextBody.js +398 -0
  132. package/lib/types/client/native/ContextBody.js.map +1 -0
  133. package/lib/types/client/native/ContextInjectionRow.d.ts +26 -0
  134. package/lib/types/client/native/ContextInjectionRow.d.ts.map +1 -0
  135. package/lib/types/client/native/ContextInjectionRow.js +27 -0
  136. package/lib/types/client/native/ContextInjectionRow.js.map +1 -0
  137. package/lib/types/client/native/ReferenceIcon.d.ts +16 -0
  138. package/lib/types/client/native/ReferenceIcon.d.ts.map +1 -0
  139. package/lib/types/client/native/ReferenceIcon.js +16 -0
  140. package/lib/types/client/native/ReferenceIcon.js.map +1 -0
  141. package/lib/types/client/native/tool-call-model.d.ts +58 -0
  142. package/lib/types/client/native/tool-call-model.d.ts.map +1 -0
  143. package/lib/types/client/native/tool-call-model.js +219 -0
  144. package/lib/types/client/native/tool-call-model.js.map +1 -0
  145. package/lib/types/client/open-file.d.ts +24 -0
  146. package/lib/types/client/primitive-labels.d.ts +10 -0
  147. package/lib/types/client/primitive-labels.d.ts.map +1 -0
  148. package/lib/types/client/primitive-labels.js +37 -0
  149. package/lib/types/client/primitive-labels.js.map +1 -0
  150. package/lib/types/client/projection.d.ts +41 -0
  151. package/lib/types/client/projection.d.ts.map +1 -0
  152. package/lib/types/client/projection.js +112 -0
  153. package/lib/types/client/projection.js.map +1 -0
  154. package/lib/types/client/reasoning-follow.d.ts +6 -0
  155. package/lib/types/client/reasoning-follow.d.ts.map +1 -0
  156. package/lib/types/client/reasoning-follow.js +12 -0
  157. package/lib/types/client/reasoning-follow.js.map +1 -0
  158. package/lib/types/client/settings-copy.d.ts +6 -0
  159. package/lib/types/client/settings-slots.d.ts +16 -0
  160. package/lib/types/client/store.d.ts +17 -0
  161. package/lib/types/client/store.d.ts.map +1 -0
  162. package/lib/types/client/store.js +13 -0
  163. package/lib/types/client/store.js.map +1 -0
  164. package/lib/types/client/stream-buffer.d.ts +29 -0
  165. package/lib/types/client/stream-buffer.d.ts.map +1 -0
  166. package/lib/types/client/stream-buffer.js +113 -0
  167. package/lib/types/client/stream-buffer.js.map +1 -0
  168. package/lib/types/client/streaming.d.ts +18 -0
  169. package/lib/types/client/streaming.d.ts.map +1 -0
  170. package/lib/types/client/streaming.js +77 -0
  171. package/lib/types/client/streaming.js.map +1 -0
  172. package/lib/types/client/timeline.d.ts +26 -0
  173. package/lib/types/client/timeline.d.ts.map +1 -0
  174. package/lib/types/client/timeline.js +48 -0
  175. package/lib/types/client/timeline.js.map +1 -0
  176. package/lib/types/client/tool-activity.d.ts +52 -0
  177. package/lib/types/client/tool-activity.d.ts.map +1 -0
  178. package/lib/types/client/tool-activity.js +178 -0
  179. package/lib/types/client/tool-activity.js.map +1 -0
  180. package/lib/types/client/types.d.ts +66 -0
  181. package/lib/types/client/types.d.ts.map +1 -0
  182. package/lib/types/client/types.js +2 -0
  183. package/lib/types/client/types.js.map +1 -0
  184. package/lib/types/client/waiting-clock.d.ts +17 -0
  185. package/lib/types/client/waiting-clock.d.ts.map +1 -0
  186. package/lib/types/client/waiting-clock.js +24 -0
  187. package/lib/types/client/waiting-clock.js.map +1 -0
  188. package/lib/types/client/word-motion.d.ts +16 -0
  189. package/lib/types/client/word-motion.d.ts.map +1 -0
  190. package/lib/types/client/word-motion.js +89 -0
  191. package/lib/types/client/word-motion.js.map +1 -0
  192. package/lib/types/client/word-timeline.d.ts +28 -0
  193. package/lib/types/client/word-timeline.d.ts.map +1 -0
  194. package/lib/types/client/word-timeline.js +100 -0
  195. package/lib/types/client/word-timeline.js.map +1 -0
  196. package/lib/types/dsh-better-display.d.ts +17 -0
  197. package/lib/types/dsh-better-display.d.ts.map +1 -0
  198. package/lib/types/dsh-better-display.js +53 -0
  199. package/lib/types/dsh-better-display.js.map +1 -0
  200. package/package.json +121 -0
  201. package/scripts/build-motion-fixture.mjs +26 -0
  202. package/scripts/link-harness-dependencies.mjs +51 -0
  203. package/skills/generative-mcpapps/SKILL.md +47 -0
  204. package/skills/generative-mcpapps/examples/interactive_quiz.html +153 -0
  205. package/skills/generative-mcpapps/references/html_boilerplate.md +122 -0
  206. package/skills/generative-mcpapps/references/sep1865_protocol.md +54 -0
  207. package/src/client/Blocks.tsx +205 -0
  208. package/src/client/ChoreographedFlow.tsx +182 -0
  209. package/src/client/ClosedProcessSummary.tsx +19 -0
  210. package/src/client/LiveFold.tsx +43 -0
  211. package/src/client/McpAppFrame.module.css +210 -0
  212. package/src/client/McpAppFrame.tsx +317 -0
  213. package/src/client/Reader.module.css +329 -0
  214. package/src/client/Reader.tsx +814 -0
  215. package/src/client/ReasoningCard.tsx +285 -0
  216. package/src/client/SettingsSection.module.css +147 -0
  217. package/src/client/SettingsSection.tsx +117 -0
  218. package/src/client/StickyLane.tsx +24 -0
  219. package/src/client/TimelineRail.module.css +170 -0
  220. package/src/client/TimelineRail.tsx +262 -0
  221. package/src/client/ToolActivity.tsx +214 -0
  222. package/src/client/TurnMetrics.module.css +139 -0
  223. package/src/client/TurnMetrics.tsx +160 -0
  224. package/src/client/WaitingStatus.tsx +22 -0
  225. package/src/client/conversation-scroll.ts +28 -0
  226. package/src/client/deliverables.ts +122 -0
  227. package/src/client/entry-policy.ts +20 -0
  228. package/src/client/entry.tsx +40 -0
  229. package/src/client/fold-choreography.ts +38 -0
  230. package/src/client/index.tsx +198 -0
  231. package/src/client/live-turn.ts +155 -0
  232. package/src/client/markdown/MarkdownText.module.css +304 -0
  233. package/src/client/markdown/MarkdownText.tsx +187 -0
  234. package/src/client/markdown/cjkFriendlyStrong.ts +84 -0
  235. package/src/client/markdown/incremental.ts +131 -0
  236. package/src/client/markdown/katex.tsx +91 -0
  237. package/src/client/markdown/mathCompatibility.ts +350 -0
  238. package/src/client/markdown/parse.ts +45 -0
  239. package/src/client/markdown/render.tsx +630 -0
  240. package/src/client/markdown/upstream.json +14 -0
  241. package/src/client/mcp-app.ts +323 -0
  242. package/src/client/message-chrome.ts +47 -0
  243. package/src/client/motion.tsx +338 -0
  244. package/src/client/native/ContextBody.module.css +161 -0
  245. package/src/client/native/ContextBody.tsx +591 -0
  246. package/src/client/native/ContextInjectionRow.module.css +62 -0
  247. package/src/client/native/ContextInjectionRow.tsx +72 -0
  248. package/src/client/native/ReferenceIcon.tsx +35 -0
  249. package/src/client/native/tool-call-model.ts +248 -0
  250. package/src/client/native/upstream.json +41 -0
  251. package/src/client/open-file.ts +94 -0
  252. package/src/client/pending-submission.ts +49 -0
  253. package/src/client/primitive-labels.ts +53 -0
  254. package/src/client/projection.ts +118 -0
  255. package/src/client/reasoning-follow.ts +12 -0
  256. package/src/client/settings-copy.ts +53 -0
  257. package/src/client/settings-slots.ts +20 -0
  258. package/src/client/settings.tsx +73 -0
  259. package/src/client/skill-status.ts +78 -0
  260. package/src/client/store.ts +30 -0
  261. package/src/client/stream-buffer.ts +100 -0
  262. package/src/client/streaming.tsx +62 -0
  263. package/src/client/style.d.ts +4 -0
  264. package/src/client/timeline.ts +77 -0
  265. package/src/client/tool-activity.ts +152 -0
  266. package/src/client/types.ts +66 -0
  267. package/src/client/waiting-clock.ts +25 -0
  268. package/src/client/word-motion.tsx +91 -0
  269. package/src/client/word-timeline.ts +96 -0
  270. package/src/dsh-better-display.ts +108 -0
  271. package/src/skill-roots.ts +138 -0
  272. package/src/skill-status.ts +81 -0
  273. package/tests/browser-closed-gap.tsx +20 -0
  274. package/tests/browser-motion.tsx +65 -0
  275. package/tests/browser-sticky-lanes.tsx +22 -0
  276. package/tests/browser-waiting-clock.tsx +14 -0
  277. package/tests/chat-flow-hook.test.ts +66 -0
  278. package/tests/cloud-gate.test.ts +34 -0
  279. package/tests/conversation-scroll.test.ts +47 -0
  280. package/tests/deliverables.test.ts +128 -0
  281. package/tests/entry.test.ts +42 -0
  282. package/tests/fixtures/maid-composer-hide.html +31 -0
  283. package/tests/fold-choreography.test.ts +38 -0
  284. package/tests/history-word-regression.test.ts +16 -0
  285. package/tests/live-turn.test.ts +218 -0
  286. package/tests/mcp-apps.test.ts +157 -0
  287. package/tests/message-chrome.test.ts +29 -0
  288. package/tests/open-file.test.ts +103 -0
  289. package/tests/pending-submission.test.ts +45 -0
  290. package/tests/projection.test.ts +184 -0
  291. package/tests/reasoning-follow.test.ts +34 -0
  292. package/tests/settings-copy.test.ts +63 -0
  293. package/tests/skill-status.test.ts +137 -0
  294. package/tests/stock-install.test.ts +50 -0
  295. package/tests/stream-buffer.test.ts +97 -0
  296. package/tests/timeline.test.ts +59 -0
  297. package/tests/waiting-clock.test.ts +24 -0
  298. package/tests/word-timeline.test.ts +136 -0
  299. package/tsconfig.json +11 -0
  300. package/tsdown.config.ts +49 -0
@@ -0,0 +1,144 @@
1
+ import { assistantSegments, hasVisibleBody } from './projection.js';
2
+ export function liveFoldEnabled(boundary) {
3
+ return boundary.status === 'open';
4
+ }
5
+ export function foldSummary(steps) {
6
+ let reasoning = 0;
7
+ let body = 0;
8
+ let tool = 0;
9
+ let extra = 0;
10
+ for (const step of steps) {
11
+ if (step.kind === 'reasoning')
12
+ reasoning += 1;
13
+ else if (step.kind === 'body')
14
+ body += 1;
15
+ else if (step.kind === 'tool')
16
+ tool += 1;
17
+ else if (step.kind !== 'user')
18
+ extra += 1;
19
+ }
20
+ const parts = [];
21
+ if (reasoning)
22
+ parts.push(`思考×${reasoning}`);
23
+ if (body)
24
+ parts.push(`输出×${body}`);
25
+ if (tool)
26
+ parts.push(`工具×${tool}`);
27
+ if (extra)
28
+ parts.push(`记录×${extra}`);
29
+ return parts.join(' · ') || '此前步骤';
30
+ }
31
+ /** One chain: fold only when a new reasoning step has prior body/tool/reasoning. */
32
+ export function splitChain(chain) {
33
+ const lastReasoning = chain.findLastIndex(step => step.kind === 'reasoning');
34
+ if (lastReasoning < 0)
35
+ return { fold: null, open: chain };
36
+ const prior = chain.slice(0, lastReasoning);
37
+ if (!prior.length)
38
+ return { fold: null, open: chain };
39
+ const trigger = prior.some(step => step.kind === 'reasoning' || step.kind === 'body' || step.kind === 'tool');
40
+ if (!trigger)
41
+ return { fold: null, open: chain };
42
+ return { fold: prior, open: chain.slice(lastReasoning) };
43
+ }
44
+ function skipReasoning(part) {
45
+ return part.kind === 'reasoning' && !part.blocks.some(block => block.kind === 'reasoning' && block.text.trim() !== '');
46
+ }
47
+ function skipBody(part) {
48
+ return part.kind === 'body' && !hasVisibleBody(part.blocks);
49
+ }
50
+ function stepsFromAssistant(nodeKey, data, toolsByCallId, consumed) {
51
+ const marks = [];
52
+ for (const part of assistantSegments(data.blocks)) {
53
+ if (skipReasoning(part) || skipBody(part))
54
+ continue;
55
+ marks.push({
56
+ at: part.start,
57
+ step: {
58
+ kind: part.kind,
59
+ key: `${nodeKey}:${part.kind}:${part.start}`,
60
+ nodeKey,
61
+ start: part.start,
62
+ blocks: part.blocks,
63
+ step: data.step,
64
+ },
65
+ });
66
+ }
67
+ data.blocks.forEach((block, index) => {
68
+ if (block.kind !== 'tool-call' || !block.callId)
69
+ return;
70
+ const tool = toolsByCallId.get(block.callId);
71
+ if (!tool || consumed.has(tool.callId))
72
+ return;
73
+ consumed.add(tool.callId);
74
+ marks.push({ at: index, step: { kind: 'tool', key: tool.key, entry: tool } });
75
+ });
76
+ marks.sort((left, right) => left.at - right.at || left.step.key.localeCompare(right.step.key));
77
+ return marks.map(mark => mark.step);
78
+ }
79
+ /** Expand readerFlow into source-ordered live steps using existing block boundaries. */
80
+ export function segmentLiveTurn(flow, get) {
81
+ const steps = [];
82
+ const consumed = new Set();
83
+ const toolsByCallId = new Map();
84
+ for (const entry of flow) {
85
+ if (entry.kind === 'tool')
86
+ toolsByCallId.set(entry.callId, entry);
87
+ }
88
+ for (const entry of flow) {
89
+ if (entry.kind === 'tool') {
90
+ if (!consumed.has(entry.callId)) {
91
+ steps.push({ kind: 'tool', key: entry.key, entry });
92
+ consumed.add(entry.callId);
93
+ }
94
+ continue;
95
+ }
96
+ const node = get(entry.nodeKey);
97
+ if (!node || node.visibility === 'hidden' || node.kind === 'turn-tail')
98
+ continue;
99
+ if (node.kind === 'user' || node.kind === 'steering') {
100
+ steps.push({ kind: 'user', key: entry.key, nodeKey: entry.nodeKey });
101
+ continue;
102
+ }
103
+ if (node.kind === 'assistant-step') {
104
+ steps.push(...stepsFromAssistant(entry.nodeKey, node.data, toolsByCallId, consumed));
105
+ continue;
106
+ }
107
+ steps.push({ kind: 'other', key: entry.key, nodeKey: entry.nodeKey });
108
+ }
109
+ return steps;
110
+ }
111
+ export function presentLiveTurn(steps, boundary, autoFold = true) {
112
+ const live = autoFold && liveFoldEnabled(boundary);
113
+ const items = [];
114
+ let chain = [];
115
+ const flush = () => {
116
+ if (!chain.length)
117
+ return;
118
+ if (!live) {
119
+ for (const step of chain)
120
+ items.push({ kind: 'open', key: step.key, step });
121
+ chain = [];
122
+ return;
123
+ }
124
+ const { fold, open } = splitChain(chain);
125
+ if (fold?.length) {
126
+ items.push({ kind: 'fold', key: `live-fold:${chain[0].key}`, steps: fold, summary: foldSummary(fold) });
127
+ }
128
+ for (const step of open)
129
+ items.push({ kind: 'open', key: step.key, step });
130
+ chain = [];
131
+ };
132
+ for (const step of steps) {
133
+ if (step.kind === 'user') {
134
+ flush();
135
+ items.push({ kind: 'user', key: step.key, step });
136
+ }
137
+ else {
138
+ chain.push(step);
139
+ }
140
+ }
141
+ flush();
142
+ return items;
143
+ }
144
+ //# sourceMappingURL=live-turn.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"live-turn.js","sourceRoot":"","sources":["../../../src/client/live-turn.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Untrusted assistant-Markdown renderer over the direct mdast pipeline:
3
+ * `parse.ts` grammars, the incremental streaming parser, and `render.tsx`.
4
+ * While a message streams, all but the trailing two blocks freeze as cached
5
+ * React elements and only the source tail behind them re-parses per chunk,
6
+ * so per-chunk work tracks the tail size instead of the whole reply. Frozen
7
+ * blocks keep their source-offset keys when they cross the freeze boundary,
8
+ * so React reconciles instead of remounting. Known deviation while
9
+ * streaming: a reference-style link or footnote whose definition sits on the
10
+ * other side of the freeze boundary renders literally until the settled
11
+ * full parse self-heals it.
12
+ */
13
+ import type { MarkdownCodeLabels, MarkdownFileMentions, MarkdownRenderContext } from './render.js';
14
+ export type { MarkdownCodeLabels, MarkdownFileMentions } from './render.js';
15
+ /**
16
+ * Render untrusted assistant-authored Markdown as semantic React elements.
17
+ * @param props - Markdown source text preserved by the session projection;
18
+ * `streaming` renders fences and TeX plain (highlighting and KaTeX land on
19
+ * the finalize swap) and parses incrementally across chunks; `codeLabels`
20
+ * forwards localized copy-button labels to fence CodeBlocks — pass a
21
+ * reference-stable object (memoized per locale revision), because a new
22
+ * identity discards the streaming render cache mid-message. `fileMentions`
23
+ * links inline-code tokens its resolver recognizes as real files; this is
24
+ * the single streaming gate — it applies to settled renders only, because a
25
+ * streaming message's vocabulary is not final and frozen cached elements
26
+ * must not bake in handlers that could go stale.
27
+ * @returns A GFM document with TeX math rendered through KaTeX; raw HTML,
28
+ * relative links, and unsafe protocols are disabled, while absolute HTTP(S)
29
+ * images render directly.
30
+ */
31
+ export declare const MarkdownText: import("react").MemoExoticComponent<({ text, streaming, codeLabels, fileMentions, renderText, renderAtom }: {
32
+ text: string;
33
+ streaming?: boolean;
34
+ codeLabels?: MarkdownCodeLabels | undefined;
35
+ fileMentions?: MarkdownFileMentions | undefined;
36
+ renderText?: MarkdownRenderContext["renderText"];
37
+ renderAtom?: MarkdownRenderContext["renderAtom"];
38
+ }) => import("react").JSX.Element>;
39
+ //# sourceMappingURL=MarkdownText.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MarkdownText.d.ts","sourceRoot":"","sources":["../../../../src/client/markdown/MarkdownText.tsx"],"names":[],"mappings":"AACA;;;;;;;;;;;GAWG;AAUH,OAAO,KAAK,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,qBAAqB,EAAoB,MAAM,aAAa,CAAA;AAIpH,YAAY,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAA;AA0H3E;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,YAAY,8GAA6G;IACpI,IAAI,EAAE,MAAM,CAAA;IACZ,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,UAAU,CAAC,EAAE,kBAAkB,GAAG,SAAS,CAAA;IAC3C,YAAY,CAAC,EAAE,oBAAoB,GAAG,SAAS,CAAA;IAC/C,UAAU,CAAC,EAAE,qBAAqB,CAAC,YAAY,CAAC,CAAA;IAChD,UAAU,CAAC,EAAE,qBAAqB,CAAC,YAAY,CAAC,CAAA;CACjD,iCAeC,CAAA"}
@@ -0,0 +1,171 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ // Adapted from DeepSeek Harness b150a551b8d465e31e418e1b2eaf5e79bbb7d28e (MIT). See THIRD_PARTY_NOTICES.md.
3
+ /**
4
+ * Untrusted assistant-Markdown renderer over the direct mdast pipeline:
5
+ * `parse.ts` grammars, the incremental streaming parser, and `render.tsx`.
6
+ * While a message streams, all but the trailing two blocks freeze as cached
7
+ * React elements and only the source tail behind them re-parses per chunk,
8
+ * so per-chunk work tracks the tail size instead of the whole reply. Frozen
9
+ * blocks keep their source-offset keys when they cross the freeze boundary,
10
+ * so React reconciles instead of remounting. Known deviation while
11
+ * streaming: a reference-style link or footnote whose definition sits on the
12
+ * other side of the freeze boundary renders literally until the settled
13
+ * full parse self-heals it.
14
+ */
15
+ import { memo, useMemo, useRef } from 'react';
16
+ import { IncrementalMarkdownParser } from './incremental.js';
17
+ import { parseGfm, parseGfmWithMath } from './parse.js';
18
+ import { collectReferenceTargets, createReferenceTargets, renderBlocks, renderFootnoteSection, wrapBlockChildren, } from './render.js';
19
+ // KaTeX CSS is supplied once by the shared DSH UI-primitives client bundle.
20
+ import css from './MarkdownText.module.css';
21
+ /** One settled full render: parse with math, resolve references, append the footnote section. */
22
+ function renderSettled(text, codeLabels, fileMentions, renderText, renderAtom) {
23
+ const root = parseGfmWithMath(text);
24
+ const targets = createReferenceTargets();
25
+ collectReferenceTargets(root.children, targets);
26
+ const context = {
27
+ renderText,
28
+ renderAtom,
29
+ streaming: false,
30
+ codeLabels,
31
+ fileMentions,
32
+ targets,
33
+ footnoteOrder: [],
34
+ footnoteCounts: new Map(),
35
+ };
36
+ const blocks = wrapBlockChildren(renderBlocks(root.children.map((node, index) => ({ node, key: node.position?.start.offset ?? -(index + 1) })), context), false);
37
+ const section = renderFootnoteSection(context);
38
+ return section === null ? blocks : [...blocks, '\n', section];
39
+ }
40
+ /**
41
+ * Streaming render state for one growing message: the incremental parser,
42
+ * the frozen blocks' cached elements, and the reference/footnote state their
43
+ * rendering consumed (footnote numbering assigned to frozen references is
44
+ * final, so the tail continues from a copy of it each frame).
45
+ */
46
+ class StreamingRenderer {
47
+ codeLabels;
48
+ renderText;
49
+ renderAtom;
50
+ parser = new IncrementalMarkdownParser(parseGfm);
51
+ generation = -1;
52
+ frozenCount = 0;
53
+ frozenElements = [];
54
+ frozenTargets = createReferenceTargets();
55
+ frozenFootnoteOrder = [];
56
+ frozenFootnoteCounts = new Map();
57
+ lastText = null;
58
+ lastRendered = [];
59
+ /** @param codeLabels - Fence copy labels baked into cached elements; the owner replaces the renderer when they change. */
60
+ constructor(codeLabels, renderText, renderAtom) {
61
+ this.codeLabels = codeLabels;
62
+ this.renderText = renderText;
63
+ this.renderAtom = renderAtom;
64
+ }
65
+ /**
66
+ * Render the current accumulated text. Idempotent per text value, so React
67
+ * may re-execute the calling render freely.
68
+ * @param text - The full accumulated markdown source.
69
+ * @returns Frozen elements, re-rendered tail, and the footnote section.
70
+ */
71
+ render(text) {
72
+ if (text === this.lastText)
73
+ return this.lastRendered;
74
+ const { frozen, tail, generation } = this.parser.update(text);
75
+ if (generation !== this.generation) {
76
+ this.generation = generation;
77
+ this.frozenCount = 0;
78
+ this.frozenElements = [];
79
+ this.frozenTargets = createReferenceTargets();
80
+ this.frozenFootnoteOrder = [];
81
+ this.frozenFootnoteCounts = new Map();
82
+ }
83
+ const newlyFrozen = frozen.slice(this.frozenCount);
84
+ collectReferenceTargets(newlyFrozen.map(block => block.node), this.frozenTargets);
85
+ // Targets visible this frame: everything frozen so far plus the current
86
+ // tail parse — a newly frozen block's references resolved against the
87
+ // same parse tree its definitions came from.
88
+ const frameTargets = {
89
+ definitions: new Map(this.frozenTargets.definitions),
90
+ footnotes: new Map(this.frozenTargets.footnotes),
91
+ };
92
+ collectReferenceTargets(tail.map(block => block.node), frameTargets);
93
+ if (newlyFrozen.length > 0) {
94
+ const frozenContext = {
95
+ renderText: this.renderText,
96
+ renderAtom: this.renderAtom,
97
+ streaming: true,
98
+ codeLabels: this.codeLabels,
99
+ fileMentions: undefined,
100
+ targets: frameTargets,
101
+ footnoteOrder: this.frozenFootnoteOrder,
102
+ footnoteCounts: this.frozenFootnoteCounts,
103
+ };
104
+ // Separator newlines are cached alongside the elements so the
105
+ // assembled children match the settled pipeline's block wrapping.
106
+ const batch = [...this.frozenElements];
107
+ for (const element of renderBlocks(newlyFrozen, frozenContext)) {
108
+ if (batch.length > 0)
109
+ batch.push('\n');
110
+ batch.push(element);
111
+ }
112
+ this.frozenElements = batch;
113
+ this.frozenCount = frozen.length;
114
+ }
115
+ const tailContext = {
116
+ renderText: this.renderText,
117
+ renderAtom: this.renderAtom,
118
+ streaming: true,
119
+ codeLabels: this.codeLabels,
120
+ fileMentions: undefined,
121
+ targets: frameTargets,
122
+ footnoteOrder: [...this.frozenFootnoteOrder],
123
+ footnoteCounts: new Map(this.frozenFootnoteCounts),
124
+ };
125
+ const children = [...this.frozenElements];
126
+ for (const element of renderBlocks(tail, tailContext)) {
127
+ if (children.length > 0)
128
+ children.push('\n');
129
+ children.push(element);
130
+ }
131
+ const section = renderFootnoteSection(tailContext);
132
+ if (section !== null)
133
+ children.push('\n', section);
134
+ this.lastText = text;
135
+ this.lastRendered = children;
136
+ return this.lastRendered;
137
+ }
138
+ }
139
+ /**
140
+ * Render untrusted assistant-authored Markdown as semantic React elements.
141
+ * @param props - Markdown source text preserved by the session projection;
142
+ * `streaming` renders fences and TeX plain (highlighting and KaTeX land on
143
+ * the finalize swap) and parses incrementally across chunks; `codeLabels`
144
+ * forwards localized copy-button labels to fence CodeBlocks — pass a
145
+ * reference-stable object (memoized per locale revision), because a new
146
+ * identity discards the streaming render cache mid-message. `fileMentions`
147
+ * links inline-code tokens its resolver recognizes as real files; this is
148
+ * the single streaming gate — it applies to settled renders only, because a
149
+ * streaming message's vocabulary is not final and frozen cached elements
150
+ * must not bake in handlers that could go stale.
151
+ * @returns A GFM document with TeX math rendered through KaTeX; raw HTML,
152
+ * relative links, and unsafe protocols are disabled, while absolute HTTP(S)
153
+ * images render directly.
154
+ */
155
+ export const MarkdownText = memo(function MarkdownText({ text, streaming = false, codeLabels, fileMentions, renderText, renderAtom }) {
156
+ const streamRef = useRef(null);
157
+ const streamLabelsRef = useRef(codeLabels);
158
+ const children = useMemo(() => {
159
+ if (!streaming) {
160
+ streamRef.current = null;
161
+ return renderSettled(text, codeLabels, fileMentions, renderText, renderAtom);
162
+ }
163
+ if (streamRef.current === null || streamLabelsRef.current !== codeLabels) {
164
+ streamRef.current = new StreamingRenderer(codeLabels, renderText, renderAtom);
165
+ streamLabelsRef.current = codeLabels;
166
+ }
167
+ return streamRef.current.render(text);
168
+ }, [text, streaming, codeLabels, fileMentions, renderText, renderAtom]);
169
+ return _jsx("div", { className: css.markdown, children: children });
170
+ });
171
+ //# sourceMappingURL=MarkdownText.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MarkdownText.js","sourceRoot":"","sources":["../../../../src/client/markdown/MarkdownText.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ /** Let asterisk strong emphasis close after punctuation when CJK prose continues without whitespace. */
2
+ import type { Extension } from 'micromark-util-types';
3
+ /**
4
+ * Extend CommonMark asterisk strong emphasis for punctuation-delimited CJK
5
+ * prose, as a micromark syntax extension for `fromMarkdown`.
6
+ * @returns The micromark syntax extension.
7
+ */
8
+ export declare function cjkFriendlyStrong(): Extension;
9
+ //# sourceMappingURL=cjkFriendlyStrong.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cjkFriendlyStrong.d.ts","sourceRoot":"","sources":["../../../../src/client/markdown/cjkFriendlyStrong.ts"],"names":[],"mappings":"AACA,wGAAwG;AAMxG,OAAO,KAAK,EAAa,SAAS,EAAoB,MAAM,sBAAsB,CAAA;AAqElF;;;;GAIG;AACH,wBAAgB,iBAAiB,IAAI,SAAS,CAE7C"}
@@ -0,0 +1,73 @@
1
+ // Adapted from DeepSeek Harness b150a551b8d465e31e418e1b2eaf5e79bbb7d28e (MIT). See THIRD_PARTY_NOTICES.md.
2
+ /** Let asterisk strong emphasis close after punctuation when CJK prose continues without whitespace. */
3
+ import { attention } from 'micromark-core-commonmark';
4
+ import { unicodePunctuation } from 'micromark-util-character';
5
+ import { classifyCharacter } from 'micromark-util-classify-character';
6
+ import { codes, constants } from 'micromark-util-symbol';
7
+ const cjkCharacter = new RegExp([
8
+ '\\p{Script_Extensions=Han}',
9
+ '\\p{Script_Extensions=Hiragana}',
10
+ '\\p{Script_Extensions=Katakana}',
11
+ '\\p{Script_Extensions=Hangul}',
12
+ '\\p{Script_Extensions=Bopomofo}',
13
+ ].join('|'), 'u');
14
+ function isCjkCharacter(code) {
15
+ return code !== null && code >= 0 && cjkCharacter.test(String.fromCodePoint(code));
16
+ }
17
+ const tokenizeCjkFriendlyAttention = function (effects, ok, nok) {
18
+ const configuredAttentionMarkers = this.parser.constructs.attentionMarkers.null;
19
+ if (configuredAttentionMarkers === undefined) {
20
+ throw new Error('micromark CommonMark attention markers are unavailable');
21
+ }
22
+ const attentionMarkers = configuredAttentionMarkers;
23
+ const previous = this.previous;
24
+ const before = classifyCharacter(previous);
25
+ let marker = codes.eof;
26
+ return start;
27
+ function start(code) {
28
+ /* v8 ignore next -- this text construct is dispatched only for an asterisk. */
29
+ if (code !== codes.asterisk)
30
+ return nok(code);
31
+ marker = code;
32
+ effects.enter('attentionSequence');
33
+ return inside(code);
34
+ }
35
+ function inside(code) {
36
+ if (code === marker) {
37
+ effects.consume(code);
38
+ return inside;
39
+ }
40
+ const token = effects.exit('attentionSequence');
41
+ const after = classifyCharacter(code);
42
+ const open = !after || (after === constants.characterGroupPunctuation && Boolean(before))
43
+ || attentionMarkers.includes(code);
44
+ const commonMarkClose = !before
45
+ || (before === constants.characterGroupPunctuation && Boolean(after))
46
+ || attentionMarkers.includes(previous);
47
+ const markerCount = token.end.offset - token.start.offset;
48
+ const cjkStrongClose = markerCount >= 2
49
+ && unicodePunctuation(previous)
50
+ && isCjkCharacter(code);
51
+ const close = commonMarkClose || cjkStrongClose;
52
+ token._open = open;
53
+ token._close = close;
54
+ return ok(code);
55
+ }
56
+ };
57
+ const cjkFriendlyAttention = {
58
+ name: 'cjkFriendlyAttention',
59
+ resolveAll: attention.resolveAll,
60
+ tokenize: tokenizeCjkFriendlyAttention,
61
+ };
62
+ const cjkFriendlyStrongExtension = {
63
+ text: { [codes.asterisk]: cjkFriendlyAttention },
64
+ };
65
+ /**
66
+ * Extend CommonMark asterisk strong emphasis for punctuation-delimited CJK
67
+ * prose, as a micromark syntax extension for `fromMarkdown`.
68
+ * @returns The micromark syntax extension.
69
+ */
70
+ export function cjkFriendlyStrong() {
71
+ return cjkFriendlyStrongExtension;
72
+ }
73
+ //# sourceMappingURL=cjkFriendlyStrong.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cjkFriendlyStrong.js","sourceRoot":"","sources":["../../../../src/client/markdown/cjkFriendlyStrong.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,69 @@
1
+ /**
2
+ * Incremental block-level markdown parsing for an append-only text stream.
3
+ *
4
+ * Re-parsing the whole accumulated document on every streaming chunk is
5
+ * quadratic in the final reply length. CommonMark block parsing is line-based
6
+ * and appended text can only reshape the parse frontier — the last top-level
7
+ * block (a paragraph becoming a setext heading or a table, a list continuing
8
+ * after a blank line, an unclosed fence swallowing lines) — so earlier blocks
9
+ * are final. This parser therefore freezes all but the trailing
10
+ * {@link UNSTABLE_TAIL_BLOCKS} blocks and re-parses only the source tail
11
+ * behind them: each source region is parsed O(1) times over the stream
12
+ * instead of once per chunk.
13
+ *
14
+ * The freeze boundary comes from the parser's own `position` offsets, never
15
+ * from custom source scanning. The cut sits at the *end offset* of the last
16
+ * frozen block (not the next block's start): a following block's start offset
17
+ * excludes up to three spaces of insignificant leading indentation, which is
18
+ * harmless to drop, but cutting at the previous end also keeps the
19
+ * inter-block blank lines in the tail so the sliced source stays verbatim.
20
+ *
21
+ * Known deviation, shared with any prefix-freeze scheme: micromark resolves
22
+ * reference-style links and footnotes document-wide at parse time, so a
23
+ * reference whose definition lands on the other side of the freeze boundary
24
+ * renders literally until the settled full parse self-heals it.
25
+ */
26
+ import type { Root, RootContent } from 'mdast';
27
+ /** A top-level mdast block plus a render key that is stable across chunks. */
28
+ export interface PositionedBlock {
29
+ /** The parsed block. Positions inside it are relative to its parse slice. */
30
+ readonly node: RootContent;
31
+ /**
32
+ * The block's start offset in the full source text. Stable from the frame
33
+ * a block first appears through freezing, so React reconciles rather than
34
+ * remounts when a block crosses the freeze boundary.
35
+ */
36
+ readonly key: number;
37
+ }
38
+ /** One {@link IncrementalMarkdownParser.update} result. */
39
+ export interface IncrementalBlocks {
40
+ /** Blocks that can no longer change; grows monotonically per generation. */
41
+ readonly frozen: readonly PositionedBlock[];
42
+ /** The re-parsed unstable tail (at most {@link UNSTABLE_TAIL_BLOCKS} blocks plus growth). */
43
+ readonly tail: readonly PositionedBlock[];
44
+ /** Bumped whenever non-append input discards the frozen prefix; callers drop caches keyed on it. */
45
+ readonly generation: number;
46
+ }
47
+ /**
48
+ * Append-only incremental parser over a caller-supplied grammar. One instance
49
+ * accumulates one streaming document; non-append input resets it.
50
+ */
51
+ export declare class IncrementalMarkdownParser {
52
+ private readonly parse;
53
+ private prevText;
54
+ private tailStart;
55
+ private frozen;
56
+ private generation;
57
+ private cached;
58
+ /** @param parse - Grammar shared with whatever renders the blocks, so boundaries agree. */
59
+ constructor(parse: (text: string) => Root);
60
+ /**
61
+ * Fold the current accumulated text and return the frozen/tail split.
62
+ * Idempotent for identical input (the previous result is returned as-is),
63
+ * so callers may invoke it from render paths that re-execute.
64
+ * @param text - The full accumulated markdown source.
65
+ * @returns Frozen and tail blocks with stream-stable render keys.
66
+ */
67
+ update(text: string): IncrementalBlocks;
68
+ }
69
+ //# sourceMappingURL=incremental.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"incremental.d.ts","sourceRoot":"","sources":["../../../../src/client/markdown/incremental.ts"],"names":[],"mappings":"AACA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,OAAO,CAAA;AAS9C,8EAA8E;AAC9E,MAAM,WAAW,eAAe;IAC9B,6EAA6E;IAC7E,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAA;IAC1B;;;;OAIG;IACH,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;CACrB;AAED,2DAA2D;AAC3D,MAAM,WAAW,iBAAiB;IAChC,4EAA4E;IAC5E,QAAQ,CAAC,MAAM,EAAE,SAAS,eAAe,EAAE,CAAA;IAC3C,6FAA6F;IAC7F,QAAQ,CAAC,IAAI,EAAE,SAAS,eAAe,EAAE,CAAA;IACzC,oGAAoG;IACpG,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;CAC5B;AAeD;;;GAGG;AACH,qBAAa,yBAAyB;IAQxB,OAAO,CAAC,QAAQ,CAAC,KAAK;IAPlC,OAAO,CAAC,QAAQ,CAAK;IACrB,OAAO,CAAC,SAAS,CAAI;IACrB,OAAO,CAAC,MAAM,CAAwB;IACtC,OAAO,CAAC,UAAU,CAAI;IACtB,OAAO,CAAC,MAAM,CAAiC;IAE/C,2FAA2F;gBAC9D,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI;IAE1D;;;;;;OAMG;IACH,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,iBAAiB;CAsCxC"}