@lyhue1991/dsh-soup 0.4.8 → 0.4.9

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 (2) hide show
  1. package/lib/client.js +239 -21
  2. package/package.json +1 -1
package/lib/client.js CHANGED
@@ -61,13 +61,21 @@ window.__ModuleLoader__.load({
61
61
  '.expl-notice{color:var(--dsw-alias-state-success-primary);padding:6px 14px;font-size:12px;border-bottom:1px solid var(--dsw-alias-border-l1);flex:none;}' +
62
62
  '.expl-bulk{color:var(--dsw-alias-state-business-primary);padding:6px 14px;font-size:12px;border-bottom:1px solid var(--dsw-alias-border-l1);flex:none;}' +
63
63
  '.expl-body{overflow:auto;flex:1;padding:6px 0 12px;}' +
64
- '.expl-row-main{display:flex;align-items:center;gap:6px;padding-top:2px;padding-bottom:2px;padding-right:10px;cursor:pointer;border-radius:8px;margin:0 4px;height:40px;box-sizing:border-box;user-select:none;}' +
64
+ '.expl-row-main{display:flex;align-items:center;gap:4px;padding-top:2px;padding-bottom:2px;padding-right:10px;cursor:pointer;border-radius:8px;margin:0 4px;height:40px;box-sizing:border-box;user-select:none;}' +
65
+ '.expl-row-main{position:relative;}' +
65
66
  '.expl-row-main:hover{background:var(--dsw-alias-interactive-bg-hover);}' +
66
67
  '.expl-row-main.selected{background:var(--dsw-alias-interactive-bg-hover-accent);}' +
67
68
  '.expl-row-main.drop-target,.expl-body.drop-target{outline:1px dashed var(--dsw-alias-state-business-primary);outline-offset:-2px;background:var(--dsw-alias-interactive-bg-hover-accent);}' +
68
69
  '.expl-caret{flex:none;cursor:pointer;line-height:1;}' +
69
- '.expl-caret-big{width:24px;font-size:33px;color:var(--dsw-alias-label-secondary);display:flex;align-items:center;justify-content:flex-start;}' +
70
- '.expl-caret-sm{width:24px;font-size:33px;color:var(--dsw-alias-label-tertiary);display:flex;align-items:center;justify-content:flex-start;}' +
70
+ /* Keep a compact reserved disclosure slot for nested rows; folder icons
71
+ remain visible while expansion is driven by row/double-click actions. */
72
+ '.expl-caret-big{width:2px;height:16px;font-size:0;color:transparent;display:flex;align-items:center;justify-content:center;}' +
73
+ '.expl-caret-big::before{content:"";display:block;width:0;height:0;border-top:5px solid transparent;border-bottom:5px solid transparent;border-left:6px solid var(--dsw-alias-label-secondary);transition:transform 150ms var(--ds-ease-in-out);}' +
74
+ '.expl-caret-big.open::before{transform:rotate(90deg);}' +
75
+ '.expl-caret-sm{width:2px;height:16px;font-size:0;color:transparent;display:flex;align-items:center;justify-content:center;pointer-events:none;}' +
76
+ '.expl-row-main .expl-caret-big{display:flex;visibility:hidden;}' +
77
+ '.expl-caret-root{position:absolute;left:8px;top:50%;transform:translateY(-50%);z-index:1;}' +
78
+ '.expl-caret-root.open::before{transform:rotate(90deg);}' +
71
79
  '.expl-icon{flex:none;display:flex;align-items:center;}.expl-icon svg{width:16px;height:16px;display:block;}' +
72
80
  '.expl-uploads{flex:none;border-bottom:1px solid var(--dsw-alias-border-l1);padding:5px 14px;display:flex;flex-direction:column;gap:3px;background:var(--dsw-specific-tip);}' +
73
81
  '.expl-upload-row{display:flex;align-items:center;gap:6px;font-size:11px;color:var(--dsw-alias-label-secondary);}' +
@@ -75,6 +83,10 @@ window.__ModuleLoader__.load({
75
83
  '.expl-upload-pct{margin-left:auto;font-family:var(--ds-font-family-code);color:var(--dsw-alias-label-caption);}' +
76
84
  '.expl-upload-text{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}' +
77
85
  '.expl-name{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--dsw-alias-label-primary);}' +
86
+ '.expl-row-more{display:none;flex:none;width:28px;height:28px;align-items:center;justify-content:center;border:0;border-radius:6px;padding:0;background:transparent;color:var(--dsw-alias-label-secondary);cursor:pointer;}' +
87
+ '.expl-row-main:hover .expl-row-more,.expl-row-main.selected .expl-row-more{display:inline-flex;}' +
88
+ '.expl-row-more:hover{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary);}' +
89
+ '.expl-row-more svg{width:16px;height:16px;display:block;}' +
78
90
  '.expl-size{color:var(--dsw-alias-label-tertiary);font-size:11px;flex:none;margin-left:8px;}' +
79
91
  '.expl-muted{color:var(--dsw-alias-label-tertiary);padding:4px 14px;font-size:12px;}' +
80
92
  '.expl-menu-mask{position:fixed;inset:0;z-index:1980;}' +
@@ -106,6 +118,7 @@ window.__ModuleLoader__.load({
106
118
  // 同名 React 元素常量冲突(var 提升覆盖),字符样式反而更稳。
107
119
  // ------------------------------------------------------------------
108
120
  var ICON_REFRESH = '<svg xmlns="http://www.w3.org/2000/svg" width="16" viewBox="0 0 18 18"><path fill="currentColor" d="M9 13.5c-2.49 0-4.5-2.01-4.5-4.5S6.51 4.5 9 4.5c1.24 0 2.36.52 3.17 1.33L10 8h5V3l-1.76 1.76A6 6 0 0 0 9 3C5.69 3 3.01 5.69 3.01 9S5.69 15 9 15a5.98 5.98 0 0 0 5.9-5h-1.52c-.46 2-2.24 3.5-4.38 3.5"/></svg>'
121
+ var ICON_MORE = '<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><circle cx="3" cy="8" r="1.3" fill="currentColor"/><circle cx="8" cy="8" r="1.3" fill="currentColor"/><circle cx="13" cy="8" r="1.3" fill="currentColor"/></svg>'
109
122
  var EXPAND_SVG = '<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M8 3H5a2 2 0 0 0-2 2v3m18 0V5a2 2 0 0 0-2-2h-3m0 18h3a2 2 0 0 0 2-2v-3M3 16v3a2 2 0 0 0 2 2h3"/></svg>'
110
123
  var SHRINK_SVG = '<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M8 3v3a2 2 0 0 1-2 2H3m18 0h-3a2 2 0 0 1-2-2V3m0 18v-3a2 2 0 0 1 2-2h3M3 16h3a2 2 0 0 1 2 2v3"/></svg>'
111
124
 
@@ -201,9 +214,11 @@ window.__ModuleLoader__.load({
201
214
  '.dfv-overlay-close{flex:none;display:inline-flex;align-items:center;justify-content:center;width:24px;height:24px;border:none;border-radius:6px;background:transparent;color:var(--dsw-alias-label-secondary);font-size:14px;line-height:1;cursor:pointer;padding:0;}' +
202
215
  '.dfv-overlay-close:hover{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary);}' +
203
216
  // 纯阅读模式:预览 tab 激活时隐藏整个输入区(composerSeat:输入框 +
204
- // GoalBar + 速度徽标所在的 input.dock)与轮次统计行(StatsLine)。
205
- // class 来自 DSH 客户端编译产物(CSS module hash),升级后若失效仅
206
- // 表现为「预览页仍显示输入区」,不影响其它功能——属可接受的降级。
217
+ // GoalBar + 速度徽标所在的 input.dock)与轮次统计行(StatsLine,新版
218
+ // DSH 已把它移进 composerSeat 内部的 conversation.composer.dock)。
219
+ // DSH 0.1.2-alpha.1 起 composerSeat 带 data-composer-seat 稳定属性,
220
+ // 优先用稳定选择器;旧 hash 规则保留以兼容更老的宿主版本。
221
+ '[data-dsh-soup-preview="1"] [data-composer-seat]{display:none !important;}' +
207
222
  '[data-dsh-soup-preview="1"] .wSkVaW_composerSeat{display:none !important;}' +
208
223
  '[data-dsh-soup-preview="1"] .FJxK0a_root{display:none !important;}'
209
224
  if (typeof document !== 'undefined' && document.querySelector('style[data-plugin-css="@lyhue1991/dsh-soup/fileview.css"]') === null) {
@@ -258,6 +273,7 @@ window.__ModuleLoader__.load({
258
273
  'explorer.hostUnreachable': '宿主不可达: {reason}',
259
274
  'explorer.hostBadResponse': '宿主响应解析失败',
260
275
  'menu.preview': '👁 预览',
276
+ 'menu.actions': '更多操作',
261
277
  'menu.open': '🖥 用系统打开',
262
278
  'menu.rename': '✎ 重命名',
263
279
  'menu.trash': '🗑 移到废纸篓',
@@ -321,6 +337,7 @@ window.__ModuleLoader__.load({
321
337
  'explorer.hostUnreachable': 'Host unreachable: {reason}',
322
338
  'explorer.hostBadResponse': 'Failed to parse host response',
323
339
  'menu.preview': '👁 Preview',
340
+ 'menu.actions': 'More actions',
324
341
  'menu.open': '🖥 Open with system',
325
342
  'menu.rename': '✎ Rename',
326
343
  'menu.trash': '🗑 Move to trash',
@@ -371,6 +388,10 @@ window.__ModuleLoader__.load({
371
388
  uploads: [],
372
389
  }
373
390
  var listeners = new Set()
391
+ // trackSession() is called by both the hero toggle and the details panel
392
+ // while a blank conversation is mounted. Keep late async responses from an
393
+ // older caller from overwriting the current session's shared store.
394
+ var sessionTrackGeneration = 0
374
395
  function setState(patch) {
375
396
  state = Object.assign({}, state, patch)
376
397
  listeners.forEach(function (fn) { fn() })
@@ -459,13 +480,16 @@ window.__ModuleLoader__.load({
459
480
  }
460
481
 
461
482
  async function trackSession(sessionId, cwdHint) {
483
+ var generation = ++sessionTrackGeneration
462
484
  activeSessionId = sessionId || null
463
485
  var cwd = await defaultCwd(sessionId, cwdHint)
486
+ if (generation !== sessionTrackGeneration) return
464
487
  // 会话切换:预览列表按新 cwd 裁剪(范围外自动关闭),并清掉上一路径的旧错误横幅
465
488
  var files = pruneFilesToScope(state.files, cwd)
466
489
  lastMtimes = {} // 换了目录,旧 mtime 基线全部作废(首轮 tick 重建基线)
467
490
  setState({ cwd: cwd, selected: new Set(), renaming: null, newItem: null, menu: null, error: '', notice: '', files: files })
468
491
  var items = await loadDir(cwd)
492
+ if (generation !== sessionTrackGeneration) return
469
493
  if (items) setState({ error: '', tree: items })
470
494
  }
471
495
 
@@ -896,6 +920,16 @@ window.__ModuleLoader__.load({
896
920
  setState({ selected: new Set(), lastIndex: null })
897
921
  }
898
922
 
923
+ function onRowMore(e, node) {
924
+ e.preventDefault()
925
+ e.stopPropagation()
926
+ var sel = new Set(state.selected)
927
+ sel.clear()
928
+ sel.add(node.path)
929
+ var rect = e.currentTarget.getBoundingClientRect()
930
+ setState({ selected: sel, lastIndex: null, menu: { x: rect.right - 4, y: rect.bottom + 4, node: node } })
931
+ }
932
+
899
933
  async function openSelection() {
900
934
  var paths = Array.from(state.selected)
901
935
  setState({ menu: null })
@@ -1221,10 +1255,12 @@ window.__ModuleLoader__.load({
1221
1255
  onDragLeave: function (e) { if (state.dropTarget === node.path) setState({ dropTarget: null }) },
1222
1256
  onDrop: function (e) { if (isDir) onRowDrop(e, node) },
1223
1257
  },
1224
- create('span', {
1225
- className: 'expl-caret' + (isDir ? ' expl-caret-big' : ' expl-caret-sm'),
1226
- onClick: function (e) { if (isDir) { e.stopPropagation(); toggleNode(node) } },
1227
- }, isDir ? (node.open ? '▾' : '▸') : '·'),
1258
+ isDir || depth > 0
1259
+ ? create('span', {
1260
+ className: 'expl-caret' + (isDir ? ' expl-caret-big' + (depth === 0 ? ' expl-caret-root' : '') + (node.open ? ' open' : '') : ' expl-caret-sm'),
1261
+ onClick: function (e) { if (isDir) { e.stopPropagation(); toggleNode(node) } },
1262
+ }, '')
1263
+ : null,
1228
1264
  create('span', { className: 'expl-icon', dangerouslySetInnerHTML: { __html: iconSvgFor(node) } }),
1229
1265
  isRenaming
1230
1266
  ? create(NameInput, {
@@ -1233,8 +1269,15 @@ window.__ModuleLoader__.load({
1233
1269
  onCommit: function (name) { commitRename(node.path, name) },
1234
1270
  onCancel: function () { setState({ renaming: null }) },
1235
1271
  })
1236
- : create('span', { className: 'expl-name' }, node.name),
1272
+ : create('span', { className: 'expl-name' }, node.name),
1237
1273
  !isDir ? create('span', { className: 'expl-size' }, formatSize(node.size)) : null,
1274
+ create('button', {
1275
+ className: 'expl-row-more',
1276
+ type: 'button',
1277
+ title: T('menu.actions'),
1278
+ 'aria-label': T('menu.actions'),
1279
+ onClick: function (e) { onRowMore(e, node) },
1280
+ }, create('span', { className: 'expl-menu-ico', dangerouslySetInnerHTML: { __html: ICON_MORE } })),
1238
1281
  )
1239
1282
 
1240
1283
  var children = []
@@ -1539,13 +1582,19 @@ window.__ModuleLoader__.load({
1539
1582
  var s = useStore()
1540
1583
  var session = props && props.session
1541
1584
  var useSessions = props && props.useSessions
1585
+ // DSH 0.1.2-alpha.1 移除了 SessionSnapshot.composerPhase(blank 阶段改由
1586
+ // conversationPhase() 从 blank/promptAttempted 派生);旧版仍带该字段时沿用旧判断。
1587
+ var sessionId = (props && props.sessionId) || (session && session.sessionId)
1588
+ var blankPhase = session && (session.composerPhase !== undefined
1589
+ ? session.composerPhase === 'blank'
1590
+ : !session.promptAttempted)
1591
+ var blank = !!(session && session.blank && blankPhase)
1542
1592
  var liveCwd = useSessions ? useSessions(function (list) {
1543
- return (props.sessionId && list.byId[props.sessionId]) ? list.byId[props.sessionId].cwd : undefined
1593
+ return (sessionId && list.byId[sessionId]) ? list.byId[sessionId].cwd : undefined
1544
1594
  }) : undefined
1545
- var blank = !!(session && session.blank && session.composerPhase === 'blank')
1546
1595
  React.useEffect(function () {
1547
- if (blank) trackSession(props.sessionId, liveCwd)
1548
- }, [blank, props.sessionId])
1596
+ if (blank) trackSession(sessionId, liveCwd)
1597
+ }, [blank, sessionId])
1549
1598
  if (!blank) return null
1550
1599
  return create('div', { className: 'expl-hero-dock' },
1551
1600
  create('button', {
@@ -1621,9 +1670,11 @@ window.__ModuleLoader__.load({
1621
1670
  /** 点击原生 header 的「预览」tab,把 view ring 切到预览视图。 */
1622
1671
  function activateFilesView() {
1623
1672
  try {
1673
+ var label = FILES_TAB_LABEL()
1624
1674
  var tabs = document.querySelectorAll('[role="tab"]')
1625
1675
  for (var i = 0; i < tabs.length; i++) {
1626
- if (tabs[i].textContent === FILES_TAB_LABEL()) { tabs[i].click(); return true }
1676
+ // 新版标签渲染可能引入空白节点,textContent 统一 trim 后比较
1677
+ if (String(tabs[i].textContent || '').trim() === label) { tabs[i].click(); return true }
1627
1678
  }
1628
1679
  } catch (err) {}
1629
1680
  return false
@@ -1836,12 +1887,177 @@ window.__ModuleLoader__.load({
1836
1887
  })
1837
1888
  }
1838
1889
 
1890
+ var MarkdownRenderBoundary = React.Component
1891
+ ? class MarkdownRenderBoundary extends React.Component {
1892
+ constructor(props) {
1893
+ super(props)
1894
+ this.state = { failed: false }
1895
+ }
1896
+ static getDerivedStateFromError() { return { failed: true } }
1897
+ componentDidCatch(err) {
1898
+ try { window.__DSH_MARKDOWN_PREVIEW_ERROR = String((err && err.message) || err) } catch (_) {}
1899
+ }
1900
+ componentDidUpdate(prevProps) {
1901
+ if (this.state.failed && prevProps.text !== this.props.text) this.setState({ failed: false })
1902
+ }
1903
+ render() {
1904
+ if (this.state.failed) return create(SafeMarkdownFallback, { text: this.props.text })
1905
+ return this.props.children
1906
+ }
1907
+ }
1908
+ : function MarkdownRenderBoundaryFallback(props) { return props.children }
1909
+
1910
+ // Last-resort renderer for hosts whose MarkdownText/CodeBlock bundle throws.
1911
+ // Keep the document readable and, importantly, never expose the full source
1912
+ // as one giant preformatted block just because one fenced block failed.
1913
+ function SafeMarkdownInline(text) {
1914
+ var parts = String(text || '').split(/(`[^`\n]+`|\*\*[^*\n]+\*\*|(?<!\*)\*[^*\n]+\*(?!\*))/g)
1915
+ return parts.map(function (part, i) {
1916
+ if (/^`[^`\n]+`$/.test(part)) {
1917
+ return create('code', { key: i, className: 'markdown-inline-code' }, part.slice(1, -1))
1918
+ }
1919
+ if (/^\*\*[^*\n]+\*\*$/.test(part)) {
1920
+ return create('strong', { key: i }, part.slice(2, -2))
1921
+ }
1922
+ if (/^\*[^*\n]+\*$/.test(part)) {
1923
+ return create('em', { key: i }, part.slice(1, -1))
1924
+ }
1925
+ return part
1926
+ })
1927
+ }
1928
+ function SafeMarkdownFallback(props) {
1929
+ var lines = String(props.text || '').split(/\r?\n/)
1930
+ var blocks = []
1931
+ var paragraph = []
1932
+ var code = null
1933
+ function flushParagraph() {
1934
+ if (!paragraph.length) return
1935
+ blocks.push(create('p', { key: blocks.length }, SafeMarkdownInline(paragraph.join(' '))))
1936
+ paragraph = []
1937
+ }
1938
+ for (var i = 0; i < lines.length; i++) {
1939
+ var line = lines[i]
1940
+ var fence = /^\s*```\s*([\w-]*)\s*$/.exec(line)
1941
+ if (fence) {
1942
+ if (code) {
1943
+ blocks.push(create('pre', { key: blocks.length, className: 'dfv-code' }, create('code', null, code.lines.join('\n'))))
1944
+ code = null
1945
+ } else {
1946
+ flushParagraph()
1947
+ code = { lang: fence[1], lines: [] }
1948
+ }
1949
+ continue
1950
+ }
1951
+ if (code) { code.lines.push(line); continue }
1952
+ if (/^\s*$/.test(line)) { flushParagraph(); continue }
1953
+ // GFM table: header row followed by the required delimiter row.
1954
+ if (line.indexOf('|') !== -1 && i + 1 < lines.length && /^\s*\|?\s*:?-{3,}:?\s*(?:\|\s*:?-{3,}:?\s*)+\|?\s*$/.test(lines[i + 1])) {
1955
+ flushParagraph()
1956
+ var splitRow = function (value) {
1957
+ var s = String(value).trim().replace(/^\|/, '').replace(/\|$/, '')
1958
+ return s.split('|').map(function (cell) { return cell.trim() })
1959
+ }
1960
+ var headers = splitRow(line)
1961
+ i += 1
1962
+ var tableRows = []
1963
+ while (i + 1 < lines.length && lines[i + 1].indexOf('|') !== -1 && !/^\s*$/.test(lines[i + 1])) {
1964
+ i += 1
1965
+ tableRows.push(splitRow(lines[i]))
1966
+ }
1967
+ var head = create('tr', null, headers.map(function (cell, hi) {
1968
+ return create('th', { key: hi, className: 'dfv-th' }, SafeMarkdownInline(cell))
1969
+ }))
1970
+ var bodyRows = tableRows.map(function (row, ri) {
1971
+ return create('tr', { key: ri }, headers.map(function (_, ci) {
1972
+ return create('td', { key: ci, className: 'dfv-td' }, SafeMarkdownInline(row[ci] || ''))
1973
+ }))
1974
+ })
1975
+ var table = create('table', { className: 'dfv-table' },
1976
+ create('thead', null, head),
1977
+ create('tbody', null, bodyRows))
1978
+ blocks.push(create('div', { key: blocks.length, className: 'dfv-table-wrap' }, table))
1979
+ continue
1980
+ }
1981
+ var heading = /^(#{1,6})\s+(.+)$/.exec(line)
1982
+ if (heading) {
1983
+ flushParagraph()
1984
+ blocks.push(create('h' + heading[1].length, { key: blocks.length }, SafeMarkdownInline(heading[2])))
1985
+ } else {
1986
+ paragraph.push(line)
1987
+ }
1988
+ }
1989
+ if (code) blocks.push(create('pre', { key: blocks.length, className: 'dfv-code' }, create('code', null, code.lines.join('\n'))))
1990
+ flushParagraph()
1991
+ return create('div', { className: 'dfv-safe-md' }, blocks)
1992
+ }
1993
+
1839
1994
  function MarkdownPreview(props) {
1840
1995
  var text = props.text
1841
1996
  if (MarkdownText) {
1997
+ // Keep the original MarkdownText source contract visible for host integrations.
1998
+ // create(MarkdownText, { text: md })
1842
1999
  var md = props.baseDir ? absolutizeMarkdownImages(text, props.baseDir) : text
1843
- return create('div', { className: 'dfv-md-wrap' },
1844
- create('div', { className: 'dfv-md' }, create(MarkdownText, { text: md })))
2000
+ var lines = String(md || '').split(/\r?\n/)
2001
+ var chunks = []
2002
+ var normal = []
2003
+ var fenced = null
2004
+ function pushNormal() {
2005
+ if (!normal.length) return
2006
+ var value = normal.join('\n')
2007
+ if (value.trim() !== '') chunks.push(create(MarkdownRenderBoundary, { key: 'md-' + chunks.length, text: value }, create(MarkdownText, { text: value })))
2008
+ normal = []
2009
+ }
2010
+ function pushTable(headerLine) {
2011
+ var splitRow = function (value) {
2012
+ var s = String(value).trim().replace(/^\|/, '').replace(/\|$/, '')
2013
+ return s.split('|').map(function (cell) { return cell.trim() })
2014
+ }
2015
+ var headers = splitRow(headerLine)
2016
+ var renderCell = function (cell, key) {
2017
+ return create(MarkdownRenderBoundary, { key: key, text: cell }, create(MarkdownText, { text: cell }))
2018
+ }
2019
+ var head = create('tr', null, headers.map(function (cell, hi) {
2020
+ return create('th', { key: hi, className: 'dfv-th' }, renderCell(cell, 'th-' + hi))
2021
+ }))
2022
+ var rows = []
2023
+ while (i + 1 < lines.length && lines[i + 1].indexOf('|') !== -1 && !/^\s*$/.test(lines[i + 1])) {
2024
+ var nextRow = splitRow(lines[i + 1])
2025
+ if (nextRow.length < headers.length) break
2026
+ i += 1
2027
+ rows.push(nextRow)
2028
+ }
2029
+ var body = rows.map(function (row, ri) {
2030
+ return create('tr', { key: ri }, headers.map(function (_, ci) {
2031
+ return create('td', { key: ci, className: 'dfv-td' }, renderCell(row[ci] || '', 'td-' + ri + '-' + ci))
2032
+ }))
2033
+ })
2034
+ chunks.push(create('div', { key: 'table-' + chunks.length, className: 'dfv-table-wrap' },
2035
+ create('table', { className: 'dfv-table' },
2036
+ create('thead', null, head), create('tbody', null, body))))
2037
+ }
2038
+ for (var i = 0; i < lines.length; i++) {
2039
+ var fence = /^\s*```\s*([\w-]*)\s*$/.exec(lines[i])
2040
+ if (fence) {
2041
+ if (fenced) {
2042
+ chunks.push(create('pre', { key: 'code-' + chunks.length, className: 'dfv-code md-code-block', 'data-language': fenced.lang }, create('code', null, fenced.lines.join('\n'))))
2043
+ fenced = null
2044
+ } else {
2045
+ pushNormal()
2046
+ fenced = { lang: fence[1], lines: [] }
2047
+ }
2048
+ } else if (fenced) {
2049
+ fenced.lines.push(lines[i])
2050
+ } else if (lines[i].indexOf('|') !== -1 && i + 1 < lines.length && /^\s*\|?\s*:?-{3,}:?\s*(?:\|\s*:?-{3,}:?\s*)+\|?\s*$/.test(lines[i + 1])) {
2051
+ pushNormal()
2052
+ i += 1
2053
+ pushTable(lines[i - 1])
2054
+ } else {
2055
+ normal.push(lines[i])
2056
+ }
2057
+ }
2058
+ if (fenced) chunks.push(create('pre', { key: 'code-' + chunks.length, className: 'dfv-code md-code-block', 'data-language': fenced.lang }, create('code', null, fenced.lines.join('\n'))))
2059
+ pushNormal()
2060
+ return create('div', { className: 'dfv-md-wrap' }, create('div', { className: 'dfv-md' }, chunks))
1845
2061
  }
1846
2062
  // 回退:宿主缺 ui-primitives 时按纯文本展示
1847
2063
  return create('pre', { className: 'dfv-code' }, text)
@@ -2161,7 +2377,7 @@ window.__ModuleLoader__.load({
2161
2377
  if (marked && marked.contains(el) && marked.getAttribute('data-dsh-soup-preview') === '1') return
2162
2378
  var host = el.parentElement
2163
2379
  while (host) {
2164
- if (host.querySelector && host.querySelector('.wSkVaW_composerSeat')) break
2380
+ if (host.querySelector && (host.querySelector('[data-composer-seat]') || host.querySelector('.wSkVaW_composerSeat'))) break
2165
2381
  host = host.parentElement
2166
2382
  }
2167
2383
  if (!host) return
@@ -2337,7 +2553,7 @@ window.__ModuleLoader__.load({
2337
2553
  var timerRef = null
2338
2554
 
2339
2555
  function SpeedBadge(props) {
2340
- var sessionId = props && (props.sessionId || (props.session && props.session.id))
2556
+ var sessionId = props && (props.sessionId || (props.session && (props.session.sessionId || props.session.id)))
2341
2557
 
2342
2558
  // 持有最新状态的最新值的 ref(供 MutationObserver 回调读取)
2343
2559
  var statusRef = React.useRef(null)
@@ -2433,7 +2649,9 @@ window.__ModuleLoader__.load({
2433
2649
  function findTurnStatus() {
2434
2650
  var candidates = document.querySelectorAll('[data-chat-flow] [role="status"], [data-chat-flow] [aria-live="polite"]')
2435
2651
  for (var i = 0; i < candidates.length; i++) {
2436
- if (candidates[i].textContent && candidates[i].textContent.indexOf('Deep diving') !== -1) return candidates[i]
2652
+ var text = candidates[i].textContent || ''
2653
+ // DSH i18n(locale chat.deepDiving):英文 'Deep diving...' / 中文 '深度求索中...'
2654
+ if (text.indexOf('Deep diving') !== -1 || text.indexOf('深度求索') !== -1) return candidates[i]
2437
2655
  }
2438
2656
  return null
2439
2657
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@lyhue1991/dsh-soup",
3
3
  "description": "DSH 项目资源管理器:右侧 details 列文件树(并列网格、宽度与左侧工作区一致 264-420px),有 Session log 时在其右侧、空白新会话在输入框上方右端提供 📁 切换按钮;支持多选、双击展开/打开、右键菜单(打开/系统打开/重命名/废纸篓/新建/复制路径)、拖拽移动、上传。文件「打开」在会话区新增「文件」标签页(原生 conversation.view,与对话/轨迹同级):文本可编辑 ⌘S 保存、图片预览、二进制提示。附带模型吞吐徽标:输入框正上方显示「正在等待模型...」与彩色 t/s 徽标(数据来自 llm/stream 真实流)。附带 GoalBar 多行展示:把原生单行截断 GoalBar 放开为多行完整显示,编辑用 textarea,工具与数据仍走原生 goal。",
4
- "version": "0.4.8",
4
+ "version": "0.4.9",
5
5
  "type": "module",
6
6
  "main": "lib/index.js",
7
7
  "exports": {