@windypro-rourou/dsh-logcat 0.4.1 → 0.4.2

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/README.md CHANGED
@@ -43,6 +43,11 @@ DSH Web GUI 的安卓实机调试面板(类似 Android Studio 的 Logcat 视
43
43
  # 方式一(推荐,npm 安装):
44
44
  dsh plugin --profile web add @windypro-rourou/dsh-logcat
45
45
 
46
+ # 更新到最新版(不会自动更新;装旧版时面板/agent 通告会提示有新版本):
47
+ dsh plugin --profile web update # 升到当前 major 内最新
48
+ # 或强制最新:dsh plugin --profile web add @windypro-rourou/dsh-logcat@latest
49
+ # 更新后重启 GUI(dsh web)生效
50
+
46
51
  # 方式二(源码本地链接,实时生效无需重启):把插件链进 web profile,
47
52
  # 并在 ~/.dsh/profiles/web/cordis.patch.yml 增加一行:
48
53
  pnpm --dir "%USERPROFILE%\.dsh\profiles\web" add link:F:\dsh-logcat
package/lib/client.js CHANGED
@@ -114,6 +114,9 @@ window.__ModuleLoader__.load({
114
114
  const [currentPackage, setCurrentPackage] = useState("");
115
115
  const [pkgInput, setPkgInput] = useState("");
116
116
  const [installingAdb, setInstallingAdb] = useState(false);
117
+ const [currentVersion, setCurrentVersion] = useState("");
118
+ const [latestVersion, setLatestVersion] = useState("");
119
+ const [updateAvailable, setUpdateAvailable] = useState(false);
117
120
  const [level, setLevel] = useState("");
118
121
  const [keyword, setKeyword] = useState("");
119
122
  const [autoScroll, setAutoScroll] = useState(true);
@@ -249,6 +252,9 @@ window.__ModuleLoader__.load({
249
252
  setDevices(body.devices ?? []);
250
253
  setStreaming(body.streaming ?? []);
251
254
  setCurrentPackage(body.currentPackage ?? "");
255
+ setCurrentVersion(body.currentVersion ?? "");
256
+ setLatestVersion(body.latestVersion ?? "");
257
+ setUpdateAvailable(body.updateAvailable === true);
252
258
  devicesRef.current = body.devices ?? [];
253
259
  if (serialRef.current === "" || !(body.devices ?? []).some((d) => d.serial === serialRef.current)) {
254
260
  const first = (body.devices ?? []).find((d) => d.state === "device");
@@ -449,6 +455,12 @@ window.__ModuleLoader__.load({
449
455
  : null),
450
456
  h("span", null, "设备 " + devices.length + " · 在线 " + devices.filter((d) => d.state === "device").length),
451
457
  h("span", null, "显示 " + filtered.length + " / 缓冲 " + entries.length + " 行"),
458
+ h("span", { title: "插件版本" }, "v" + (currentVersion || "?")),
459
+ updateAvailable === true
460
+ ? h("span", { style: { color: "#fbc02d" } },
461
+ h("b", null, "新版本 " + latestVersion + " 可更新"),
462
+ "(dsh plugin --profile web update 后重启 GUI)")
463
+ : null,
452
464
  currentPackage !== ""
453
465
  ? h("span", { title: "当前测试应用包名(agent 通过 logcat_set_package 设置)" }, "测试: " + currentPackage)
454
466
  : null,
package/lib/index.js CHANGED
@@ -15,13 +15,32 @@
15
15
  */
16
16
 
17
17
  import { spawn, execFile } from 'node:child_process'
18
- import { existsSync } from 'node:fs'
18
+ import { existsSync, readFileSync } from 'node:fs'
19
19
  import { homedir } from 'node:os'
20
20
  import { dirname, join } from 'node:path'
21
21
  import { createInterface } from 'node:readline'
22
22
  import { WebSocket, WebSocketServer } from 'ws'
23
23
  import { defineTool } from '@deepseek-ai/dsh-tools'
24
24
 
25
+ /** This package's manifest (name + version), read from the installed location. */
26
+ const OWN_MANIFEST = JSON.parse(readFileSync(new URL('../package.json', import.meta.url), 'utf8'))
27
+
28
+ /** Latest published version on npm (cached 1h; null until first check). */
29
+ let latestVersion = null
30
+ let lastVersionCheck = 0
31
+
32
+ /** Refresh the cached latest npm version of this package (offline-safe). */
33
+ async function ensureVersionCheck() {
34
+ if (latestVersion !== null && Date.now() - lastVersionCheck < 3600_000) return
35
+ lastVersionCheck = Date.now()
36
+ try {
37
+ const res = await fetch(`https://registry.npmjs.org/${encodeURIComponent(OWN_MANIFEST.name)}/latest`, {
38
+ signal: AbortSignal.timeout(8000),
39
+ })
40
+ if (res.ok) latestVersion = (await res.json()).version ?? null
41
+ } catch { /* offline / registry unreachable — keep whatever we had */ }
42
+ }
43
+
25
44
  /** Stable cordis plugin name. */
26
45
  export const name = 'logcat'
27
46
 
@@ -48,7 +67,7 @@ export const LOGCAT_GUIDANCE =
48
67
  'adb 命令消耗真实设备资源,破坏性操作(卸载/重启/清数据/杀进程)先向用户确认再执行。' +
49
68
  '用户提到「Logcat / 安卓日志 / 实机调试 / adb 日志 / 逆向 / 读内存 / 抓包定位」时即指本插件,请据此主动协作。'
50
69
 
51
- /** Dynamic model-facing announcement: base guidance plus currently attached devices. */
70
+ /** Dynamic model-facing announcement: base guidance plus live device/package/version facts. */
52
71
  function logcatGuidance(engine) {
53
72
  return () => {
54
73
  const devices = engine.deviceList()
@@ -59,7 +78,10 @@ function logcatGuidance(engine) {
59
78
  const pkgLine = engine.currentPackage !== ''
60
79
  ? `当前测试应用包名:${engine.currentPackage}(logcat_recent 默认按它过滤日志)。`
61
80
  : ''
62
- return `${LOGCAT_GUIDANCE}\n${deviceLine}${pkgLine !== '' ? `\n${pkgLine}` : ''}`
81
+ const versionLine = latestVersion !== null && latestVersion !== OWN_MANIFEST.version
82
+ ? `dsh-logcat 有新版本:已装 ${OWN_MANIFEST.version},最新 ${latestVersion}(用户可执行 dsh plugin --profile web update 后重启 GUI 升级)。`
83
+ : ''
84
+ return `${LOGCAT_GUIDANCE}\n${deviceLine}${pkgLine !== '' ? `\n${pkgLine}` : ''}${versionLine !== '' ? `\n${versionLine}` : ''}`
63
85
  }
64
86
  }
65
87
 
@@ -484,6 +506,7 @@ function makeRoutes(engine) {
484
506
  handler: async (req, res) => {
485
507
  if (!isLoopbackRequest(req)) { writeJson(res, 403, { error: 'forbidden: loopback-only' }); return }
486
508
  if ((req.method ?? 'GET') !== 'GET') { writeJson(res, 405, { error: 'method not allowed' }); return }
509
+ await ensureVersionCheck()
487
510
  writeJson(res, 200, {
488
511
  adbPath: engine.adb,
489
512
  adbVersion: engine.adbVersion,
@@ -491,6 +514,9 @@ function makeRoutes(engine) {
491
514
  devices: engine.deviceList(),
492
515
  streaming: [...engine.streams.keys()],
493
516
  currentPackage: engine.currentPackage,
517
+ currentVersion: OWN_MANIFEST.version,
518
+ latestVersion,
519
+ updateAvailable: latestVersion !== null && latestVersion !== OWN_MANIFEST.version,
494
520
  })
495
521
  },
496
522
  },
@@ -1830,6 +1856,7 @@ export function apply(ctx, config) {
1830
1856
  const initOnce = () => {
1831
1857
  if (inited) return
1832
1858
  inited = true
1859
+ void ensureVersionCheck()
1833
1860
  void engine.init().then((ok) => {
1834
1861
  if (ok) engine.startPolling()
1835
1862
  })
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@windypro-rourou/dsh-logcat",
3
3
  "description": "Android Logcat viewer for the dsh web GUI: auto-connects to any adb device in debug mode, live logcat stream with level/keyword filters, pause/clear/export, plus agent tools (logcat_recent). Hot-pluggable — mounted via ~/.dsh/cordis.patch.yml + a profile node_modules copy, no dsh source changes.",
4
- "version": "0.4.1",
4
+ "version": "0.4.2",
5
5
  "type": "module",
6
6
  "packageManager": "pnpm@11.22.0",
7
7
  "engines": {