dsh-mesh-ui 0.0.8 → 0.0.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/client.js CHANGED
@@ -678,7 +678,7 @@ body.light .dm-edge-label { stroke: rgba(255,255,255,.92); }
678
678
  h('span', null, '⋯')
679
679
  )
680
680
  ),
681
- h('div', { className: 'dm-hint' }, '拓扑 v19 · 内容 ' + Math.round(layout.W) + '×' + Math.round(layout.H) + 'px · 卡 ' + Math.round(layout.cardW) + '×' + Math.round(layout.cardH) + ' · 缩放 ' + Math.round(view.scale * 100) + '% · 滚轮缩放 / 拖拽平移')
681
+ h('div', { className: 'dm-hint' }, '拓扑 v21 · 内容 ' + Math.round(layout.W) + '×' + Math.round(layout.H) + 'px · 卡 ' + Math.round(layout.cardW) + '×' + Math.round(layout.cardH) + ' · 缩放 ' + Math.round(view.scale * 100) + '% · 滚轮缩放 / 拖拽平移')
682
682
  )
683
683
  }
684
684
 
@@ -1293,6 +1293,32 @@ function deviceLinkState(data, peer, lanMap) {
1293
1293
  return v
1294
1294
  }
1295
1295
 
1296
+ // 2026-11-10:设备状态与拓扑同口径 —— 任一链路可达即算在线(HTTP 探测偶发超时不再误判红点)
1297
+ var lanUpByDev = {}
1298
+ ;(data.peers || []).forEach(function (p) {
1299
+ if (!isLanPeer(p)) return
1300
+ var tu = p.tunnel || {}
1301
+ lanUpByDev[peerDeviceKey(p.name)] = tu.probe ? tu.probe.up === true : Boolean(p.up)
1302
+ })
1303
+ function peerLinkState(peer) {
1304
+ var t = peer.tunnel || {}
1305
+ var httpUp = Boolean(peer.up)
1306
+ var tcpUp = t.probe ? t.probe.up === true : false
1307
+ var sk = sakuraTunnelOf(data, peerDeviceKey(peer.name))
1308
+ var sakuraUp = sk ? sk.online === true : null
1309
+ var lanUp = lanUpByDev[peerDeviceKey(peer.name)] === true
1310
+ return {
1311
+ httpUp: httpUp, tcpUp: tcpUp, sakuraUp: sakuraUp, lanUp: lanUp,
1312
+ up: httpUp || tcpUp || sakuraUp === true || lanUp
1313
+ }
1314
+ }
1315
+ function linkStateText(ls) {
1316
+ return "公网 " + ((ls.httpUp || ls.tcpUp) ? "✅" : "❌")
1317
+ + " / 樱花 " + (ls.sakuraUp == null ? "—" : (ls.sakuraUp ? "✅" : "❌"))
1318
+ + (ls.lanUp ? " / LAN ✅" : "")
1319
+ + (ls.httpUp ? "" : "(HTTP 超时,隧道" + (ls.tcpUp ? "通" : "断") + ")")
1320
+ }
1321
+
1296
1322
  var devices = [{
1297
1323
  key: 'local',
1298
1324
  name: nodeDisplay(data.nodeName) + '(本机)',
@@ -1310,11 +1336,12 @@ function deviceLinkState(data, peer, lanMap) {
1310
1336
  ]
1311
1337
  }].concat(peers.map(function (peer) {
1312
1338
  var t = peer.tunnel || {}
1339
+ var ls = peerLinkState(peer)
1313
1340
  var hwp = peer.hardware || {}
1314
1341
  return {
1315
1342
  key: 'peer:' + peer.name,
1316
1343
  name: nodeDisplay(peerDeviceKey(peer.name)),
1317
- up: Boolean(peer.up),
1344
+ up: ls.up,
1318
1345
  rows: [
1319
1346
  ['设备类型', formFactorOf(hwp)],
1320
1347
  ['操作系统', hwp.os || peer.os || '—'],
@@ -1324,7 +1351,8 @@ function deviceLinkState(data, peer, lanMap) {
1324
1351
  ['DSH 版本', dshVerOf(peer)],
1325
1352
  ['IP 类型', ipKindOf(peer)],
1326
1353
  ['端口号', t.port ? String(t.port) : '—'],
1327
- ['公网穿透类型', relayKindOf(peer)]
1354
+ ['公网穿透类型', relayKindOf(peer)],
1355
+ ['链路状态', linkStateText(ls)]
1328
1356
  ]
1329
1357
  }
1330
1358
  }))
@@ -1901,6 +1929,11 @@ body[data-ds-dark-theme] .dm-dg-fs-item.active { background:rgba(88,166,255,.28)
1901
1929
 
1902
1930
  function loadSession() {
1903
1931
  if (!selected || !selected.sessionId) return
1932
+ // 2026-11-10:本机任务(local)没有对端会话,不要发 peer call
1933
+ if (/^(local|self|localhost)$/i.test(String(selected.node || ''))) {
1934
+ flash('bad', '本机任务(local)没有对端会话;请在 DSH 侧栏查看本机会话')
1935
+ return
1936
+ }
1904
1937
  setSessionLoading(true)
1905
1938
  dgFetch(DG_API_SESSION + '?node=' + encodeURIComponent(selected.node) + '&sessionId=' + encodeURIComponent(selected.sessionId) + '&limit=60')
1906
1939
  .then(function (json) {
@@ -2166,7 +2199,7 @@ body[data-ds-dark-theme] .dm-dg-fs-item.active { background:rgba(88,166,255,.28)
2166
2199
  '对端会话',
2167
2200
  h('span', { className: 'dm-dg-sub' }, session ? ('轮次 ' + (session.totalMessages || sessionMessages.length) + ' · 帧 ' + (session.frameCount || '—') + ' · ' + Math.round((session.bytes || 0) / 1024) + ' KB') : '只读'),
2168
2201
  h('span', { className: 'dm-dg-spacer' }),
2169
- h('button', { type: 'button', className: 'dm-dg-btn primary', onClick: loadSession, disabled: sessionLoading || !selected.sessionId },
2202
+ h('button', { type: 'button', className: 'dm-dg-btn primary', onClick: loadSession, disabled: sessionLoading || !selected.sessionId || /^(local|self|localhost)$/i.test(String(selected.node || '')) },
2170
2203
  sessionLoading ? h('span', { className: 'dm-dg-loading' }, h('span', { className: 'dm-dg-spin' }), '加载中') : (session ? '重新加载' : '加载会话'))
2171
2204
  ),
2172
2205
  h('div', { className: 'dm-dg-sec-body' },
package/lib/index.js CHANGED
@@ -176,6 +176,8 @@ export function apply(ctx) {
176
176
  }),
177
177
  readonlyRoute('/api/dsh-mesh/session', async (url) => {
178
178
  const node = String(url.searchParams.get('node') || '')
179
+ // 2026-11-10:本机任务(node=local)没有对端会话,直接给出明确错误,避免 peer call --to local 报 unknown peer
180
+ if (/^(local|self|localhost)$/i.test(node)) return { ok: false, code: "E_LOCAL_NODE", error: "本机任务(local)没有对端会话;请在 DSH 侧栏查看本机会话" }
179
181
  const sessionId = String(url.searchParams.get('sessionId') || '')
180
182
  const limit = Number(url.searchParams.get('limit')) || 40
181
183
  if (!node || !sessionId) return { ok: false, error: 'node and sessionId required' }
package/package.json CHANGED
@@ -1,11 +1,12 @@
1
1
  {
2
2
  "name": "dsh-mesh-ui",
3
- "version": "0.0.8",
3
+ "version": "0.0.11",
4
4
  "description": "DSH settings-page panel for dsh-mesh: AI network topology, peer health, and delegation panel. Read-only; data is collected from the local mesh CLI.",
5
5
  "icon": "icon.svg",
6
6
  "type": "module",
7
7
  "engines": {
8
- "node": "^22.19.0 || >=24.0.0"
8
+ "node": "^22.19.0 || >=24.0.0",
9
+ "dsh": ">=0.2.0-rc.2 <0.3.0"
9
10
  },
10
11
  "main": "lib/index.js",
11
12
  "exports": {
@@ -14,9 +15,7 @@
14
15
  "./package.json": "./package.json"
15
16
  },
16
17
  "dsh": {
17
- "engines": {
18
- "dsh": ">=0.2.0-rc.2"
19
- },
18
+ "manifestVersion": 1,
20
19
  "bundle": {
21
20
  "patch": "./cordis.patch.yml"
22
21
  },
@@ -29,6 +28,7 @@
29
28
  }
30
29
  },
31
30
  "peerDependencies": {
31
+ "@deepseek-ai/dsh": ">=0.2.0-rc.2 <0.3.0",
32
32
  "react": "^18.2.0",
33
33
  "react-dom": "^18.2.0"
34
34
  },