dsh-recall-plugin 1.0.3 → 1.0.4
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 +2 -2
- package/lib/client.js +11 -1
- package/lib/index.js +24 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -11,7 +11,6 @@
|
|
|
11
11
|
---
|
|
12
12
|
**在任意一条你发过的消息下方**,**点「↶ 撤回」**,**工作区文件和对话历史一起回到那条消息发出之前的状态**。
|
|
13
13
|
|
|
14
|
-
|
|
15
14
|
## 界面预览
|
|
16
15
|
- 撤回按钮位置
|
|
17
16
|
|
|
@@ -35,8 +34,9 @@
|
|
|
35
34
|
|
|
36
35
|
- 快照在**消息发送时**创建,插件启用前的历史消息没有快照,不显示撤回按钮。
|
|
37
36
|
- 会话第一条用户消息无法回退对话(仅文件回退),因为 fork 需要更早的 turn 边界。
|
|
38
|
-
- 仅支持 Windows(脚本用 PowerShell + git CLI);Linux/macOS
|
|
37
|
+
- 仅支持 Windows(脚本用 PowerShell + git CLI);Linux/macOS 下页面会弹一次性「仅支持 Windows」提示,快照不可用、不显示撤回按钮,也不会产生任何文件副作用。
|
|
39
38
|
- 工作区内嵌套的其他 git 仓库(子目录自带 `.git`)不进快照,其内容不参与回退。
|
|
39
|
+
- MacOS和Linux环境未进行测试
|
|
40
40
|
|
|
41
41
|
## 安装
|
|
42
42
|
|
package/lib/client.js
CHANGED
|
@@ -118,19 +118,29 @@ window.__ModuleLoader__.load({
|
|
|
118
118
|
initedSessionId = sessionId
|
|
119
119
|
initDone = api('init', { sessionId }).then((res) => {
|
|
120
120
|
const notice = res && res.notice
|
|
121
|
+
if (notice && notice.unsupported) {
|
|
122
|
+
showNotice('unsupported', '撤回插件仅支持 Windows,当前平台的快照不可用。')
|
|
123
|
+
}
|
|
121
124
|
if (notice && notice.gitMissing) {
|
|
122
125
|
showNotice('git', '未检测到 git CLI,撤回功能不可用(快照引擎依赖 git)。安装 git 并重启 DSH 后即可使用。')
|
|
123
126
|
}
|
|
124
127
|
if (notice && notice.homeFallback) {
|
|
125
128
|
showNotice('home', 'home 目录不可写,快照已降级存储到项目内 .dsh-recall-snapshots 目录。')
|
|
126
129
|
}
|
|
127
|
-
}).catch(() => {
|
|
130
|
+
}).catch(() => {
|
|
131
|
+
// init 失败(如页面先于 Host API 就绪加载)时清掉标记:否则本会话
|
|
132
|
+
// 内被判定“已初始化”,撤回按钮永不出现;清掉后下一条消息挂载会重试
|
|
133
|
+
if (initedSessionId === sessionId) initedSessionId = null
|
|
134
|
+
})
|
|
128
135
|
return initDone
|
|
129
136
|
}
|
|
130
137
|
|
|
131
138
|
// 消息时间:当天只显示时分,跨天显示月/日 时分
|
|
132
139
|
function clockText(ms) {
|
|
133
140
|
try {
|
|
141
|
+
// time 字段缺失或非法时返回空串:Invalid Date 不会 throw,
|
|
142
|
+
// 不拦会渲染出 "NaN/NaN NaN:NaN" 这样的坏时间戳
|
|
143
|
+
if (!ms || isNaN(new Date(ms).getTime())) return ''
|
|
134
144
|
const d = new Date(ms)
|
|
135
145
|
const now = new Date()
|
|
136
146
|
const sameDay = d.getFullYear() === now.getFullYear() && d.getMonth() === now.getMonth() && d.getDate() === now.getDate()
|
package/lib/index.js
CHANGED
|
@@ -19,6 +19,13 @@ export const inject = ['shell', 'sessions', 'webServer']
|
|
|
19
19
|
const MAX_FILE_BYTES = 104857600
|
|
20
20
|
const HOME_RETRY_MS = 300000
|
|
21
21
|
|
|
22
|
+
// 统一 UTF-8 输出前导:中文等非 ASCII 机器的默认代码页(如 GBK)下,
|
|
23
|
+
// PowerShell 重定向 stdout 按 [Console]::OutputEncoding 编码,而 DSH 按
|
|
24
|
+
// UTF-8 解码——不强制时 homeDirFor/resolveGit 输出里含中文的用户名/路径
|
|
25
|
+
// 会变乱码,store 会指向错误目录。diff/rollback 脚本里早有同款设置,
|
|
26
|
+
// 这里提到 runShell 全局注入一次,其余脚本不改自动受益(PS 5.1 / 7 均支持)。
|
|
27
|
+
const UTF8_PRELUDE = '$OutputEncoding = [Text.UTF8Encoding]::new($false)\ntry { [Console]::OutputEncoding = [Text.UTF8Encoding]::new($false) } catch {}'
|
|
28
|
+
|
|
22
29
|
export function apply(ctx) {
|
|
23
30
|
const shell = ctx.shell
|
|
24
31
|
const sessions = ctx.sessions
|
|
@@ -36,6 +43,12 @@ export function apply(ctx) {
|
|
|
36
43
|
gitExe: null
|
|
37
44
|
}
|
|
38
45
|
|
|
46
|
+
// 非 Windows 平台干净降级:脚本体系(反斜杠路径、Windows git 安装候选、
|
|
47
|
+
// Expand-Archive)绑定 Windows,硬跑不报错但会在项目里创建名字带反斜杠的
|
|
48
|
+
// 垃圾目录。这里整体短路:init 返回 unsupported,Client 弹一次性提示;
|
|
49
|
+
// 其余端点因无快照自然返回「没有可用快照」,全程零文件副作用。
|
|
50
|
+
const supported = process.platform === 'win32'
|
|
51
|
+
|
|
39
52
|
function psq(value) {
|
|
40
53
|
return "'" + String(value).replace(/'/g, "''") + "'"
|
|
41
54
|
}
|
|
@@ -52,7 +65,7 @@ export function apply(ctx) {
|
|
|
52
65
|
async function runShell(command, opts) {
|
|
53
66
|
const sp = ctx.get('sandboxPolicy')
|
|
54
67
|
const spec = shell.resolve({
|
|
55
|
-
command,
|
|
68
|
+
command: UTF8_PRELUDE + '\n' + command,
|
|
56
69
|
timeoutMs: (opts && opts.timeoutMs) || 300000,
|
|
57
70
|
stdoutMaxBytes: (opts && opts.stdoutMaxBytes) || 4194304,
|
|
58
71
|
sandboxPolicy: { mode: 'danger-full-access', workspaceRoot: (sp && sp.workspaceRoot) || process.cwd() }
|
|
@@ -140,6 +153,9 @@ export function apply(ctx) {
|
|
|
140
153
|
// PS 的 Join-Path 可能带出连续反斜杠(旧版脚本遗留 "…\\<hex>" 形态);
|
|
141
154
|
// 折叠成单反斜杠。Windows 把中间的重复分隔符视为同一个目录,
|
|
142
155
|
// 所以与既有快照数据(index.json、影子 git 仓库)路径完全兼容。
|
|
156
|
+
// 开头的双反斜杠是 UNC 前缀(DSH_HOME/用户主目录指到网络盘),
|
|
157
|
+
// 折叠掉会把 \\server\share 变成无效的 \server\share,必须原样保留。
|
|
158
|
+
if (/^\\\\/.test(text)) return '\\\\' + text.slice(2).replace(/\\{2,}/g, '\\')
|
|
143
159
|
return text.replace(/\\{2,}/g, '\\')
|
|
144
160
|
}
|
|
145
161
|
|
|
@@ -607,6 +623,10 @@ export function apply(ctx) {
|
|
|
607
623
|
try {
|
|
608
624
|
const args = await readJsonBody(req)
|
|
609
625
|
if (name === 'init') {
|
|
626
|
+
if (!supported) {
|
|
627
|
+
sendJson(res, 200, { ok: false, root: null, notice: { unsupported: true } })
|
|
628
|
+
return
|
|
629
|
+
}
|
|
610
630
|
const sessionId = args && args.sessionId ? String(args.sessionId) : null
|
|
611
631
|
const root = await resolveRoot(sessionId)
|
|
612
632
|
let notice = null
|
|
@@ -670,6 +690,9 @@ export function apply(ctx) {
|
|
|
670
690
|
}
|
|
671
691
|
}))
|
|
672
692
|
|
|
693
|
+
// 快照事件与启动预热仅在受支持平台注册(见上方 supported 短路说明)
|
|
694
|
+
if (!supported) return
|
|
695
|
+
|
|
673
696
|
// 每条用户消息触发快照(子代理会话跳过)
|
|
674
697
|
ctx.on('session/event', (session, event) => {
|
|
675
698
|
if (!event || event.type !== 'user/message') return
|