@goodandready/dsh-time-machine 0.1.8 → 0.1.9
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 +5 -0
- package/README.ru.md +5 -0
- package/README.zh.md +5 -0
- package/lib/index.js +63 -58
- package/package.json +2 -3
package/README.md
CHANGED
|
@@ -119,6 +119,11 @@ dsh-time-machine:
|
|
|
119
119
|
|
|
120
120
|
## 📋 Release Notes
|
|
121
121
|
|
|
122
|
+
### v0.1.9 — Event Bus Harmonization & Dependency Cleanup
|
|
123
|
+
* **Changed in v0.1.9**: Harmonized event bus subscriptions to prevent duplicate checkpoints. Native DSH `session/event` bus takes precedence, with legacy `ctx.events` used strictly as a fallback when `ctx.on` is unavailable.
|
|
124
|
+
* **Changed in v0.1.9**: Removed unused `@deepseek-ai/dsh-credentials` from `peerDependencies`.
|
|
125
|
+
* **Added in v0.1.9**: Standardized project design contract in `docs/design/DESIGN.md`.
|
|
126
|
+
|
|
122
127
|
### v0.1.7 — Critical Safety, Staging Isolation & Native Event Bus
|
|
123
128
|
* **Changed in v0.1.7**: Safe workspace rollback via `read-tree` + `checkout-index` + `clean -fd`. Rolling back to a checkpoint never modifies branch `HEAD` or severs git commit history.
|
|
124
129
|
* **Changed in v0.1.7**: User staging area protection. Checkpoints now isolate git index creation through `GIT_INDEX_FILE`, preventing disruption of pre-staged files in `.git/index`.
|
package/README.ru.md
CHANGED
|
@@ -119,6 +119,11 @@ dsh-time-machine:
|
|
|
119
119
|
|
|
120
120
|
## 📋 История версий (Release Notes)
|
|
121
121
|
|
|
122
|
+
### v0.1.9 — Гармонизация шины событий и очистка зависимостей
|
|
123
|
+
* **Changed in v0.1.9**: Устранено потенциальное дублирование авто-снапшотов. Нативная шина событий DSH `session/event` теперь имеет приоритет, а legacy `ctx.events` подключается строго как fallback при отсутствии `ctx.on`.
|
|
124
|
+
* **Changed in v0.1.9**: Удалена неиспользуемая зависимость `@deepseek-ai/dsh-credentials` из `peerDependencies`.
|
|
125
|
+
* **Added in v0.1.9**: Добавлен дизайн-контракт проекта `docs/design/DESIGN.md`.
|
|
126
|
+
|
|
122
127
|
### v0.1.7 — Безопасность истории веток, изоляция индекса и события DSH
|
|
123
128
|
* **Changed in v0.1.7**: Безопасный откат рабочего каталога через `read-tree` + `checkout-index` + `clean -fd`. Устранена критическая проблема переноса `HEAD` ветки на сиротский коммит.
|
|
124
129
|
* **Changed in v0.1.7**: Защита пользовательского индекса Git. Чекпоинты создаются с изолированным `GIT_INDEX_FILE`, предотвращая перезапись подготовленных файлов в `.git/index`.
|
package/README.zh.md
CHANGED
|
@@ -94,6 +94,11 @@ dsh-time-machine:
|
|
|
94
94
|
|
|
95
95
|
## 📋 版本更新记录 (Release Notes)
|
|
96
96
|
|
|
97
|
+
### v0.1.9 — 事件总线统一与依赖清理
|
|
98
|
+
* **Changed in v0.1.9**: 统一事件总线监听逻辑,杜绝自动快照重复触发。优先使用原生 DSH `session/event` 总线,仅在缺失 `ctx.on` 时启用 legacy `ctx.events` 回退。
|
|
99
|
+
* **Changed in v0.1.9**: 从 `peerDependencies` 中移除未使用的 `@deepseek-ai/dsh-credentials`。
|
|
100
|
+
* **Added in v0.1.9**: 新增项目设计规范文档 `docs/design/DESIGN.md`。
|
|
101
|
+
|
|
97
102
|
### v0.1.7 — 分支历史安全、暂存区隔离与 DSH 原生事件总线
|
|
98
103
|
* **Changed in v0.1.7**: 安全工作区回滚。改用 `read-tree` + `checkout-index` + `clean -fd`,彻底杜绝回滚时误将分支 `HEAD` 覆盖为孤立提交的严重缺陷。
|
|
99
104
|
* **Changed in v0.1.7**: 保护用户 Git 暂存区。快照操作通过独立的 `GIT_INDEX_FILE` 执行,不会覆盖 `.git/index` 中已暂存的文件。
|
package/lib/index.js
CHANGED
|
@@ -56,66 +56,71 @@ export function apply(ctx, config) {
|
|
|
56
56
|
};
|
|
57
57
|
|
|
58
58
|
// 1. Native DSH session/event bus (Cordis standard in DSH)
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
if (
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
if (
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
59
|
+
// When native session/event bus is present, use it exclusively to prevent double-fire.
|
|
60
|
+
const hasNativeEvents = typeof ctx.on === 'function';
|
|
61
|
+
|
|
62
|
+
if (hasNativeEvents) {
|
|
63
|
+
ctx.effect(() => {
|
|
64
|
+
const off = ctx.on('session/event', (session, event) => {
|
|
65
|
+
const sid = (session && session.id) || sessionIdOf(event, ctx);
|
|
66
|
+
const type = event && event.type;
|
|
67
|
+
if (type === 'turn/start') {
|
|
68
|
+
const turnId = event.turnId || event.data?.turnId || Date.now();
|
|
69
|
+
autoSnap(`auto:turn:${turnId}`, sid);
|
|
70
|
+
} else if (type === 'approval/asked') {
|
|
71
|
+
const tool = event.tool || event.data?.toolName || event.data?.tool || 'approval';
|
|
72
|
+
autoSnap(`auto:approval:${tool}`, sid);
|
|
73
|
+
} else if (type === 'turn/end') {
|
|
74
|
+
if (!getConfig().autoSnapshotEnabled) return;
|
|
75
|
+
const outcome = String((event && (event.outcome || event.data?.outcome || event.result?.outcome || event.result?.status)) || '');
|
|
76
|
+
if (!sid) return;
|
|
77
|
+
if (outcome === 'success' || outcome === 'ok' || outcome === 'done') {
|
|
78
|
+
engine.pruneSnapshots(sid, 3).catch(() => {});
|
|
79
|
+
}
|
|
80
|
+
} else if (type === 'tool/error' || type === 'command/error') {
|
|
81
|
+
if (getConfig().autoHealPrompt) {
|
|
82
|
+
const tool = event.tool || event.data?.toolName || 'command';
|
|
83
|
+
autoSnap(`auto:error:${tool}`, sid);
|
|
84
|
+
}
|
|
80
85
|
}
|
|
86
|
+
});
|
|
87
|
+
return () => { try { typeof off === 'function' && off(); } catch {} };
|
|
88
|
+
}, 'dsh-time-machine: native session events');
|
|
89
|
+
} else {
|
|
90
|
+
// 2. Legacy/mock events bus fallback (for unit tests and non-standard environments without ctx.on)
|
|
91
|
+
try {
|
|
92
|
+
if (ctx.events && typeof ctx.events.on === 'function') {
|
|
93
|
+
ctx.effect(() => {
|
|
94
|
+
const offs = [];
|
|
95
|
+
try {
|
|
96
|
+
offs.push(ctx.events.on('turn/start', (ev) => {
|
|
97
|
+
const sid = sessionIdOf(ev, ctx);
|
|
98
|
+
autoSnap(`auto:turn:${ev?.turnId || Date.now()}`, sid);
|
|
99
|
+
}));
|
|
100
|
+
} catch {}
|
|
101
|
+
try {
|
|
102
|
+
offs.push(ctx.events.on('approval/asked', (ev) => {
|
|
103
|
+
const sid = sessionIdOf(ev, ctx);
|
|
104
|
+
const tool = ev?.tool || ev?.name || 'approval';
|
|
105
|
+
autoSnap(`auto:approval:${tool}`, sid);
|
|
106
|
+
}));
|
|
107
|
+
} catch {}
|
|
108
|
+
try {
|
|
109
|
+
offs.push(ctx.events.on('turn/end', (ev) => {
|
|
110
|
+
if (!getConfig().autoSnapshotEnabled) return;
|
|
111
|
+
const outcome = String((ev && (ev.outcome || ev.result?.outcome || ev.result?.status)) || '');
|
|
112
|
+
const sid = sessionIdOf(ev, ctx);
|
|
113
|
+
if (!sid) return;
|
|
114
|
+
if (outcome === 'success' || outcome === 'ok' || outcome === 'done') {
|
|
115
|
+
engine.pruneSnapshots(sid, 3).catch(() => {});
|
|
116
|
+
}
|
|
117
|
+
}));
|
|
118
|
+
} catch {}
|
|
119
|
+
return () => { for (const off of offs) try { typeof off === 'function' && off(); } catch {} };
|
|
120
|
+
}, 'dsh-time-machine: auto snapshot events fallback');
|
|
81
121
|
}
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
}, 'dsh-time-machine: native session events');
|
|
85
|
-
|
|
86
|
-
// 2. Legacy/mock events bus fallback (for unit tests and non-standard environments)
|
|
87
|
-
try {
|
|
88
|
-
if (ctx.events && typeof ctx.events.on === 'function') {
|
|
89
|
-
ctx.effect(() => {
|
|
90
|
-
const offs = [];
|
|
91
|
-
try {
|
|
92
|
-
offs.push(ctx.events.on('turn/start', (ev) => {
|
|
93
|
-
const sid = sessionIdOf(ev, ctx);
|
|
94
|
-
autoSnap(`auto:turn:${ev?.turnId || Date.now()}`, sid);
|
|
95
|
-
}));
|
|
96
|
-
} catch {}
|
|
97
|
-
try {
|
|
98
|
-
offs.push(ctx.events.on('approval/asked', (ev) => {
|
|
99
|
-
const sid = sessionIdOf(ev, ctx);
|
|
100
|
-
const tool = ev?.tool || ev?.name || 'approval';
|
|
101
|
-
autoSnap(`auto:approval:${tool}`, sid);
|
|
102
|
-
}));
|
|
103
|
-
} catch {}
|
|
104
|
-
try {
|
|
105
|
-
offs.push(ctx.events.on('turn/end', (ev) => {
|
|
106
|
-
if (!getConfig().autoSnapshotEnabled) return;
|
|
107
|
-
const outcome = String((ev && (ev.outcome || ev.result?.outcome || ev.result?.status)) || '');
|
|
108
|
-
const sid = sessionIdOf(ev, ctx);
|
|
109
|
-
if (!sid) return;
|
|
110
|
-
if (outcome === 'success' || outcome === 'ok' || outcome === 'done') {
|
|
111
|
-
engine.pruneSnapshots(sid, 3).catch(() => {});
|
|
112
|
-
}
|
|
113
|
-
}));
|
|
114
|
-
} catch {}
|
|
115
|
-
return () => { for (const off of offs) try { typeof off === 'function' && off(); } catch {} };
|
|
116
|
-
}, 'dsh-time-machine: auto snapshot events');
|
|
117
|
-
}
|
|
118
|
-
} catch {}
|
|
122
|
+
} catch {}
|
|
123
|
+
}
|
|
119
124
|
|
|
120
125
|
// tools (session-aware)
|
|
121
126
|
const registerTools = (tctx) => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@goodandready/dsh-time-machine",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.9",
|
|
4
4
|
"description": "DSH plugin for smart checkpoints, workspace safety guards, and instant rollback",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "lib/index.js",
|
|
@@ -47,7 +47,6 @@
|
|
|
47
47
|
},
|
|
48
48
|
"peerDependencies": {
|
|
49
49
|
"@deepseek-ai/cordis": "^4.0.1",
|
|
50
|
-
"@deepseek-ai/dsh-credentials": "^0.1.0-rc.6",
|
|
51
50
|
"@deepseek-ai/dsh-host-webserver": "^0.1.0-rc.6",
|
|
52
51
|
"@deepseek-ai/dsh-settings": "^0.1.0-rc.6",
|
|
53
52
|
"@deepseek-ai/dsh-tools": "^0.1.0-rc.6",
|
|
@@ -56,4 +55,4 @@
|
|
|
56
55
|
"publishConfig": {
|
|
57
56
|
"access": "public"
|
|
58
57
|
}
|
|
59
|
-
}
|
|
58
|
+
}
|