@lyhue1991/dsh-soup 0.5.0 → 0.5.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 (3) hide show
  1. package/README.md +1 -0
  2. package/lib/client.js +32 -15
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -40,6 +40,7 @@ DSH(DeepSeek Harness)功能很强:会话、工具、轨迹、Goal 一应
40
40
  - **类型图标**:按品牌色区分文件类型(notebook 橙、markdown 紫、json 黄、pdf 红…)。
41
41
  - **沙箱围栏**:所有文件操作只能落在你的工作区与会话目录内,越界自动拒绝。
42
42
  - **自动刷新**:每 3 秒轻量探测一次目录签名(mtime),有变化才重拉——agent 或终端里的文件增删改无需手动刷新即可出现;面板关闭且无预览时零开销;宿主不可达(如 DSH 重启中)自动指数退避(封顶 60s)。
43
+ - **新建文件夹**:顶部 🗂+ 在当前目录创建文件夹;工具栏顺序为 🗂+ 新建、⬆ 上传、⟳ 刷新、✕ 关闭。
43
44
  - **一键刷新**:顶部 ⟳ 重拉整个文件树,已展开的子目录保持展开不收起。
44
45
 
45
46
  ### 🫚 会话内文件预览(主打 · 姜 · 去腥增香)
package/lib/client.js CHANGED
@@ -98,8 +98,9 @@ window.__ModuleLoader__.load({
98
98
  '.expl-confirm-title{font-size:14px;font-weight:600;margin-bottom:10px;}.expl-confirm-text{font-size:13px;line-height:20px;overflow-wrap:anywhere;}.expl-confirm-actions{display:flex;justify-content:flex-end;gap:8px;margin-top:18px;}' +
99
99
  '.expl-confirm-btn{height:30px;padding:0 14px;border:1px solid var(--dsw-alias-border-l2);border-radius:7px;background:transparent;color:var(--dsw-alias-label-primary);cursor:pointer;font-size:13px;}.expl-confirm-btn:hover{background:var(--dsw-alias-interactive-bg-hover);}.expl-confirm-primary{border-color:var(--dsw-alias-state-business-primary);background:var(--dsw-alias-state-business-primary);color:#fff;}' +
100
100
  '.expl-menu{position:fixed;z-index:1990;min-width:172px;background:var(--dsw-specific-menu);border:1px solid var(--dsw-alias-border-inverted);border-radius:12px;padding:4px;box-shadow:var(--dsw-shadow-lv3);pointer-events:auto;}' +
101
- '.expl-menu-item{display:flex;align-items:center;gap:7px;width:100%;text-align:left;background:transparent;border:none;color:var(--dsw-alias-label-primary);font-size:13px;padding:6px 10px;border-radius:8px;cursor:pointer;line-height:1.4;}' +
102
- '.expl-menu-ico{flex:none;display:inline-flex;align-items:center;}.expl-menu-ico svg{width:14px;height:14px;display:block;}' +
101
+ '.expl-menu-item{display:flex;align-items:center;width:100%;text-align:left;background:transparent;border:none;color:var(--dsw-alias-label-primary);font-size:13px;padding:6px 10px;border-radius:8px;cursor:pointer;line-height:1.4;}' +
102
+ '.expl-menu-ico,.expl-menu-ico-ph{flex:none;display:inline-flex;align-items:center;justify-content:center;width:14px;height:14px;margin-right:7px;}' +
103
+ '.expl-menu-ico svg{width:14px;height:14px;display:block;}' +
103
104
  '.expl-menu-item:hover{background:var(--dsw-alias-interactive-bg-hover);}' +
104
105
  '.expl-danger{color:var(--dsw-alias-state-error-primary);} .expl-menu-item.expl-danger:hover{background:var(--dsw-alias-interactive-bg-hover-danger);}' +
105
106
  '.expl-menu-sep{height:1px;margin:4px 6px;background:var(--dsw-alias-border-l1);}' +
@@ -119,12 +120,13 @@ window.__ModuleLoader__.load({
119
120
  }
120
121
 
121
122
  // ------------------------------------------------------------------
122
- // 工具栏图标:取自 JupyterLab ui-components(BSD-3-Clause,与文件类型
123
- // 图标同源的引用方式),fill 改为 currentColor 以跟随 DSH 主题 token。
124
- // 注意:只引入刷新图标——ICON_CLOSE / ICON_UPLOAD 与 GoalBar 段的
125
- // 同名 React 元素常量冲突(var 提升覆盖),字符样式反而更稳。
123
+ // 工具栏图标:刷新图标取自 JupyterLab ui-components(BSD-3-Clause);
124
+ // fill 改为 currentColor 以跟随 DSH 主题 token。
125
+ // 注意:ICON_CLOSE / ICON_UPLOAD 与 GoalBar 段的同名 React 元素常量
126
+ // 冲突(var 提升覆盖),字符样式反而更稳。
126
127
  // ------------------------------------------------------------------
127
128
  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>'
129
+ var ICON_NEW_FOLDER = '<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24"><path fill="currentColor" d="M20 6h-8l-2-2H4c-1.1 0-1.99.9-1.99 2L2 18c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V8c0-1.1-.9-2-2-2zm-2 7h-3v3h-2v-3h-3v-2h3V8h2v3h3v2z"/></svg>'
128
130
  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>'
129
131
  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>'
130
132
  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>'
@@ -257,6 +259,8 @@ window.__ModuleLoader__.load({
257
259
  'explorer.label': '资源管理器',
258
260
  'explorer.refresh': '刷新',
259
261
  'explorer.refreshTitle': '刷新(保持已展开目录)',
262
+ 'explorer.newFolder': '新建文件夹',
263
+ 'explorer.newFolderTitle': '在当前目录新建文件夹',
260
264
  'explorer.upload': '上传文件',
261
265
  'explorer.close': '关闭',
262
266
  'explorer.closePanel': '关闭资源管理器',
@@ -291,7 +295,7 @@ window.__ModuleLoader__.load({
291
295
  'menu.trash': '🗑 移到废纸篓',
292
296
  'menu.trashMulti': '🗑 移到废纸篓 ({n} 项)',
293
297
  'menu.newFile': '📄 新建文件',
294
- 'menu.newFolder': '📁 新建文件夹',
298
+ 'menu.newFolder': '新建文件夹',
295
299
  'menu.copyPath': '⧉ 复制路径',
296
300
  'menu.download': '⬇ 下载',
297
301
  'menu.deselect': '取消选择',
@@ -325,6 +329,8 @@ window.__ModuleLoader__.load({
325
329
  'explorer.label': 'Explorer',
326
330
  'explorer.refresh': 'Refresh',
327
331
  'explorer.refreshTitle': 'Refresh (keeps expanded folders)',
332
+ 'explorer.newFolder': 'New folder',
333
+ 'explorer.newFolderTitle': 'Create a folder in the current directory',
328
334
  'explorer.upload': 'Upload files',
329
335
  'explorer.close': 'Close',
330
336
  'explorer.closePanel': 'Close explorer',
@@ -359,7 +365,7 @@ window.__ModuleLoader__.load({
359
365
  'menu.trash': '🗑 Move to trash',
360
366
  'menu.trashMulti': '🗑 Move to trash ({n})',
361
367
  'menu.newFile': '📄 New file',
362
- 'menu.newFolder': '📁 New folder',
368
+ 'menu.newFolder': 'New folder',
363
369
  'menu.copyPath': '⧉ Copy path',
364
370
  'menu.download': '⬇ Download',
365
371
  'menu.deselect': 'Clear selection',
@@ -1407,7 +1413,7 @@ window.__ModuleLoader__.load({
1407
1413
  }
1408
1414
  if (node.type === 'directory') {
1409
1415
  items.push({ key: 'newfile', label: T('menu.newFile'), onClick: function () { startNew(node.path, false) } })
1410
- items.push({ key: 'newfolder', label: T('menu.newFolder'), onClick: function () { startNew(node.path, true) }, separatorAfter: true })
1416
+ items.push({ key: 'newfolder', label: [create('span', { className: 'expl-menu-ico', dangerouslySetInnerHTML: { __html: ICON_NEW_FOLDER } }), T('menu.newFolder')], onClick: function () { startNew(node.path, true) }, separatorAfter: true })
1411
1417
  }
1412
1418
  items.push({ key: 'copy', label: T('menu.copyPath'), onClick: function () { copyPath(node) } })
1413
1419
  if (node.type !== 'directory') {
@@ -1415,7 +1421,7 @@ window.__ModuleLoader__.load({
1415
1421
  }
1416
1422
  } else {
1417
1423
  items.push({ key: 'newfile', label: T('menu.newFile'), onClick: function () { startNew(state.cwd, false) } })
1418
- items.push({ key: 'newfolder', label: T('menu.newFolder'), onClick: function () { startNew(state.cwd, true) } })
1424
+ items.push({ key: 'newfolder', label: [create('span', { className: 'expl-menu-ico', dangerouslySetInnerHTML: { __html: ICON_NEW_FOLDER } }), T('menu.newFolder')], onClick: function () { startNew(state.cwd, true) } })
1419
1425
  items.push({ key: 'refresh', label: [create('span', { className: 'expl-menu-ico', dangerouslySetInnerHTML: { __html: ICON_REFRESH } }), T('explorer.refresh')], onClick: refresh, separatorAfter: true })
1420
1426
  if (state.selected.size > 0) items.push({ key: 'none', label: T('menu.deselect'), onClick: function () { setState({ selected: new Set(), lastIndex: null }) } })
1421
1427
  }
@@ -1454,11 +1460,16 @@ window.__ModuleLoader__.load({
1454
1460
  var items = buildMenuItems(menu.node)
1455
1461
  var menuChildren = []
1456
1462
  items.forEach(function (it) {
1463
+ var children = it.label instanceof Array ? it.label : (function () {
1464
+ var match = it.label.match(/^([\u2190-\u2BFF\u{1F000}-\u{1FAFF}])\s*/u)
1465
+ if (match) return [create('span', { className: 'expl-menu-ico' }, match[1]), it.label.slice(match[0].length)]
1466
+ return [create('span', { className: 'expl-menu-ico-ph' }), it.label]
1467
+ })()
1457
1468
  menuChildren.push(create('button', {
1458
1469
  key: it.key,
1459
1470
  className: 'expl-menu-item' + (it.danger ? ' expl-danger' : ''),
1460
1471
  onClick: function () { setState({ menu: null }); it.onClick() },
1461
- }, it.label))
1472
+ }, children))
1462
1473
  if (it.separatorAfter) menuChildren.push(create('div', { key: it.key + '-sep', className: 'expl-menu-sep' }))
1463
1474
  })
1464
1475
  return create('div', { ref: menuRef, className: 'expl-menu', style: { left: pos.x, top: pos.y } }, menuChildren)
@@ -1604,16 +1615,22 @@ window.__ModuleLoader__.load({
1604
1615
  create('div', { className: 'expl-head-btns' },
1605
1616
  create('button', {
1606
1617
  className: 'expl-btn',
1607
- onClick: function () { refreshAll() },
1608
- title: T('explorer.refreshTitle'),
1609
- 'aria-label': T('explorer.refresh'),
1610
- }, create('span', { className: 'expl-icon', dangerouslySetInnerHTML: { __html: ICON_REFRESH } })),
1618
+ onClick: function () { startNew(state.cwd, true) },
1619
+ title: T('explorer.newFolderTitle'),
1620
+ 'aria-label': T('explorer.newFolder'),
1621
+ }, create('span', { className: 'expl-icon', dangerouslySetInnerHTML: { __html: ICON_NEW_FOLDER } })),
1611
1622
  create('button', {
1612
1623
  className: 'expl-btn',
1613
1624
  onClick: function () { if (uploadInputEl) uploadInputEl.click() },
1614
1625
  title: T('explorer.upload'),
1615
1626
  'aria-label': T('explorer.upload'),
1616
1627
  }, '⬆'),
1628
+ create('button', {
1629
+ className: 'expl-btn',
1630
+ onClick: function () { refreshAll() },
1631
+ title: T('explorer.refreshTitle'),
1632
+ 'aria-label': T('explorer.refresh'),
1633
+ }, create('span', { className: 'expl-icon', dangerouslySetInnerHTML: { __html: ICON_REFRESH } })),
1617
1634
  create('button', {
1618
1635
  className: 'expl-btn',
1619
1636
  onClick: function (event) {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@lyhue1991/dsh-soup",
3
3
  "description": "DSH 项目资源管理器:右侧 details 列文件树(并列网格、宽度对齐宿主 details 合同 300-520px),有 Session log 时在其右侧、空白新会话在输入框上方右端提供 📁 切换按钮;支持多选、双击展开/打开、右键菜单(打开/系统打开/重命名/废纸篓/新建/复制路径)、拖拽移动、上传。文件「打开」在会话区新增「文件」标签页(原生 conversation.view,与对话/轨迹同级):文本可编辑 ⌘S 保存、图片预览、二进制提示。附带模型吞吐徽标:输入框正上方显示「正在等待模型...」与彩色 t/s 徽标(数据来自 llm/stream 真实流)。附带 GoalBar 多行展示:把原生单行截断 GoalBar 放开为多行完整显示,编辑用 textarea,工具与数据仍走原生 goal。",
4
- "version": "0.5.0",
4
+ "version": "0.5.1",
5
5
  "type": "module",
6
6
  "main": "lib/index.js",
7
7
  "exports": {