dsh-reload 1.0.0 → 1.0.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.
- package/README.md +40 -3
- package/client.js +31 -4
- package/package.json +2 -4
package/README.md
CHANGED
|
@@ -23,18 +23,55 @@
|
|
|
23
23
|
|
|
24
24
|
- ⚡ **点一下,改动就生效。** 重新加载文件有改动的插件,**不重启进程、不中断会话**,聊天记录和正在做的事都还在。
|
|
25
25
|
- 🔄 **需要时也能重启。** 有些改动(改 `package.json`、换依赖)必须整机重启,本插件也能一键完成,关掉后自动重新打开。
|
|
26
|
-
- 🛡️
|
|
26
|
+
- 🛡️ **会话或后台任务在跑就不让重启。** 它们跑在 Host 里,重启必然中断,所以直接拒绝并列出是哪些,不会让你误丢工作。**终端不算拦截条件** —— 无头终端、卡死的终端都很常见,硬拦会让你卡在「关不掉也重启不了」的死角,只能强杀进程;所以只把终端列出来提醒,你确认就放行。
|
|
27
27
|
- 🤖 **智能体也能触发。** 内置 `dsh_hot_reload` 工具,改完代码让 AI 自己重载,不用你动手。
|
|
28
28
|
|
|
29
|
+
## 🎯 三条设计原则
|
|
30
|
+
|
|
31
|
+
这个插件刻意做得很薄。三类决定贯穿全部代码:
|
|
32
|
+
|
|
33
|
+
### 1. 走官方路径,不生造分支
|
|
34
|
+
|
|
35
|
+
重载直接调用宿主的 `hmr.reconcileProfile()` —— 就是 DSH 自己重载插件用的那条路径。
|
|
36
|
+
|
|
37
|
+
有些同类插件会自己清 ESM/CJS 模块缓存、手动 dispose fiber、再重新 apply。那套序列很脆弱:顺序错一步,Loader 就会把插件写成 `disabled: true` 并**持久化到你的配置里**。本插件不重写这套逻辑,因此也不会以新的方式出错。
|
|
38
|
+
|
|
39
|
+
**不需要「指定插件」这个参数。** 该重载什么是文件系统的事实,不是模型需要判断的事 —— 宿主比对文件身份,把所有陈旧的模块一次带上,并沿 import 图把共享了改动依赖的插件一起刷新。让调用方点名,反而多出一个「猜错名字、漏掉半个依赖树」的失败模式。
|
|
40
|
+
|
|
41
|
+
所以:宿主怎么保证自己的 HMR 可靠,本插件就怎么可靠。
|
|
42
|
+
|
|
43
|
+
### 2. 不污染模型上下文
|
|
44
|
+
|
|
45
|
+
插件对 AI 的影响只有**一个工具**:
|
|
46
|
+
|
|
47
|
+
| 项 | 本插件 |
|
|
48
|
+
|---|---|
|
|
49
|
+
| 系统提示注入(`systemPrompt.section` / `context`) | **0** |
|
|
50
|
+
| agent 上下文注入(`agent.inject`) | **0** |
|
|
51
|
+
| 注册的 skill | **0** |
|
|
52
|
+
| 工具数量 | **1** |
|
|
53
|
+
| 工具描述长度 | 349 字符 / 约 97 token |
|
|
54
|
+
| 工具参数 | **无**(JSON Schema 为空对象) |
|
|
55
|
+
|
|
56
|
+
同类插件常带 `action` / `target` / `reason` 等参数。本插件一个都不要 —— 该重载什么由文件系统决定,不需要模型判断,也就不存在「模型猜错插件名」这个失败模式。
|
|
57
|
+
|
|
58
|
+
**你的对话上下文里,这个插件只占一个工具位。**
|
|
59
|
+
|
|
60
|
+
### 3. 默认不占界面
|
|
61
|
+
|
|
62
|
+
装好后界面上什么都不会多出来。侧边栏按钮、右下角悬浮按钮**默认关闭**,需要时自己去插件页打开。
|
|
63
|
+
|
|
64
|
+
设置面板顶栏的两个按钮是唯一常驻入口 —— 因为它们是「随时能点到」的兜底,且不占正文空间。
|
|
65
|
+
|
|
29
66
|
## 📸 界面
|
|
30
67
|
|
|
31
68
|
插件自己的设置页,两个按钮加两个开关:
|
|
32
69
|
|
|
33
|
-

|
|
70
|
+

|
|
34
71
|
|
|
35
72
|
打开设置面板时,顶栏右侧始终有这两个按钮,任何设置页都能点到:
|
|
36
73
|
|
|
37
|
-

|
|
74
|
+

|
|
38
75
|
|
|
39
76
|
> 插件默认**不往界面上加任何东西**,需要侧边栏按钮或右下角悬浮按钮时,自己去插件页打开开关。
|
|
40
77
|
|
package/client.js
CHANGED
|
@@ -84,6 +84,7 @@ window.__ModuleLoader__.load({
|
|
|
84
84
|
'modal.ok': '知道了',
|
|
85
85
|
'modal.confirmTitle': '重启客户端?',
|
|
86
86
|
'modal.confirmDesc': 'DSH 会关闭并自动重新打开。当前没有任务在运行。重启期间窗口会短暂消失。',
|
|
87
|
+
'modal.confirmTerminalsDesc': 'DSH 会关闭并自动重新打开。下面这些终端会一起关掉——如果里面还有进程在跑,它们会被中断。会话和后台任务才是阻止重启的原因,终端不会。',
|
|
87
88
|
'modal.confirmCancel': '取消',
|
|
88
89
|
'modal.confirmOk': '重启客户端',
|
|
89
90
|
'modal.restarting': '正在重启 DSH…',
|
|
@@ -125,6 +126,7 @@ window.__ModuleLoader__.load({
|
|
|
125
126
|
'modal.ok': 'Got it',
|
|
126
127
|
'modal.confirmTitle': 'Restart the app?',
|
|
127
128
|
'modal.confirmDesc': 'DSH will close and reopen automatically. No tasks are running. The window disappears briefly.',
|
|
129
|
+
'modal.confirmTerminalsDesc': 'DSH will close and reopen automatically. These terminals close with it - anything still running inside them is cut off. Terminals alone never block a restart; sessions and background jobs do.',
|
|
128
130
|
'modal.confirmCancel': 'Cancel',
|
|
129
131
|
'modal.confirmOk': 'Restart app',
|
|
130
132
|
'modal.restarting': 'Restarting DSH…',
|
|
@@ -568,8 +570,15 @@ window.__ModuleLoader__.load({
|
|
|
568
570
|
/**
|
|
569
571
|
* 点「重启客户端」的第一步:查状态,决定弹提示框还是确认框。
|
|
570
572
|
*
|
|
571
|
-
*
|
|
572
|
-
*
|
|
573
|
+
* 三种情况,分流依据是**重启会不会毁掉用户看不见的工作**:
|
|
574
|
+
*
|
|
575
|
+
* - 会话或后台任务在跑 → 只读提示框(**没有重启选项**)。它们跑在
|
|
576
|
+
* Host 里,重启必然中断,用户还没法从界面上看出「断在半路」的状态。
|
|
577
|
+
* - 只有终端开着 → 确认框,**并把终端列出来**。终端不参与 `active`
|
|
578
|
+
* 判定(见 lib/activity.js):无头终端、已卡死的终端都很常见,把它
|
|
579
|
+
* 当成硬拦截会让用户卡在「关不掉也重启不了」的死角,只能强杀进程
|
|
580
|
+
* —— 那比重启更糟。所以改成「说清楚会关掉哪些,你确认就放行」。
|
|
581
|
+
* - 什么都没有 → 普通确认框。
|
|
573
582
|
*/
|
|
574
583
|
async function beginRestart(openModal) {
|
|
575
584
|
if (state.reloading || state.restarting) return
|
|
@@ -587,6 +596,12 @@ window.__ModuleLoader__.load({
|
|
|
587
596
|
openModal({ kind: 'busy', activity: status.activity })
|
|
588
597
|
return
|
|
589
598
|
}
|
|
599
|
+
// 终端只提醒、不拦截:把它们交给确认框展示。
|
|
600
|
+
const terminals = status.activity?.terminals ?? []
|
|
601
|
+
if (terminals.length > 0) {
|
|
602
|
+
openModal({ kind: 'confirm', activity: status.activity })
|
|
603
|
+
return
|
|
604
|
+
}
|
|
590
605
|
openModal({ kind: 'confirm' })
|
|
591
606
|
} catch (error) {
|
|
592
607
|
showToast(currentT('toast.statusFailed').replace('{message}', String(error?.message ?? error)), true)
|
|
@@ -652,7 +667,16 @@ window.__ModuleLoader__.load({
|
|
|
652
667
|
}, [onClose])
|
|
653
668
|
|
|
654
669
|
const title = spec.kind === 'busy' ? t('modal.busyTitle') : isConfirm ? t('modal.confirmTitle') : spec.title
|
|
655
|
-
|
|
670
|
+
// 确认框带 activity 时,说明「只有终端在开着」:换个说法,别再说
|
|
671
|
+
// 「当前没有任务在运行」——那句话在终端可见的情况下是自相矛盾的。
|
|
672
|
+
const hasTerminals = isConfirm && (spec.activity?.terminals?.length ?? 0) > 0
|
|
673
|
+
const desc = spec.kind === 'busy'
|
|
674
|
+
? t('modal.busyDesc')
|
|
675
|
+
: hasTerminals
|
|
676
|
+
? t('modal.confirmTerminalsDesc')
|
|
677
|
+
: isConfirm
|
|
678
|
+
? t('modal.confirmDesc')
|
|
679
|
+
: spec.desc
|
|
656
680
|
|
|
657
681
|
const children = [
|
|
658
682
|
h('div', { className: 'dshr-modal-head', key: 'head' }, title),
|
|
@@ -660,7 +684,10 @@ window.__ModuleLoader__.load({
|
|
|
660
684
|
'div',
|
|
661
685
|
{ className: 'dshr-modal-body', key: 'body' },
|
|
662
686
|
h('div', { className: 'dshr-modal-desc' }, desc),
|
|
663
|
-
|
|
687
|
+
// 提示框列出「谁在拦」,终端确认框列出「哪些会被一起关掉」。
|
|
688
|
+
spec.kind === 'busy' || hasTerminals
|
|
689
|
+
? h(TaskList, { activity: spec.activity, t })
|
|
690
|
+
: null,
|
|
664
691
|
),
|
|
665
692
|
h(
|
|
666
693
|
'div',
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-reload",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.1",
|
|
4
4
|
"description": "Hot-reload changed DeepSeek Harness plugins and optionally restart the desktop client, without opening and closing DSH by hand.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.js",
|
|
@@ -21,9 +21,7 @@
|
|
|
21
21
|
"lib",
|
|
22
22
|
"cordis.patch.yml",
|
|
23
23
|
"locale/*.json",
|
|
24
|
-
"icon.svg"
|
|
25
|
-
"README.md",
|
|
26
|
-
"LICENSE"
|
|
24
|
+
"icon.svg"
|
|
27
25
|
],
|
|
28
26
|
"keywords": [
|
|
29
27
|
"dsh",
|