dsh-rewind-plugin 0.15.2 → 0.16.0-alpha.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/SECURITY.md +2 -2
- package/lib/client.js +9 -8
- package/lib/index.js +10 -20
- package/package.json +56 -51
- package/lib/types/session-cwd.d.ts +0 -27
package/SECURITY.md
CHANGED
|
@@ -120,8 +120,8 @@ hides the `[target, marker]` span from the rendered transcript.
|
|
|
120
120
|
- **Restores name only recorded paths**: the store contains resolved display
|
|
121
121
|
paths of the session's own write-class tool calls (plus boundary re-checks
|
|
122
122
|
over that same tracked set) — a restore can never write an arbitrary path.
|
|
123
|
-
- **Path resolution rule**: relative paths resolve against the session
|
|
124
|
-
|
|
123
|
+
- **Path resolution rule**: relative paths resolve against the session's current
|
|
124
|
+
working directory, read from the same service the fs tools resolve through.
|
|
125
125
|
- **Bounded backups**: `prune` keeps the newest 100 anchor groups per session
|
|
126
126
|
(`MAX_ANCHOR_GROUPS`), except groups a non-terminal restore journal still
|
|
127
127
|
references (pinned so the op can be finished), so backup accumulation stays
|
package/lib/client.js
CHANGED
|
@@ -1359,9 +1359,9 @@ function createRewindBridge(deps) {
|
|
|
1359
1359
|
}
|
|
1360
1360
|
|
|
1361
1361
|
// src/client/build-info.ts
|
|
1362
|
-
var PLUGIN_VERSION = true ? "0.
|
|
1362
|
+
var PLUGIN_VERSION = true ? "0.16.0-alpha.1" : "dev";
|
|
1363
1363
|
var PLUGIN_PACKAGE = "dsh-rewind-plugin";
|
|
1364
|
-
var BUILD_HASH = true ? "
|
|
1364
|
+
var BUILD_HASH = true ? "f36f8be8" : "dev";
|
|
1365
1365
|
|
|
1366
1366
|
// src/client/locales.ts
|
|
1367
1367
|
var zh = {
|
|
@@ -1586,10 +1586,10 @@ function apply(ctx) {
|
|
|
1586
1586
|
};
|
|
1587
1587
|
const restoreImages = async (sessionId, images) => {
|
|
1588
1588
|
if (images.length === 0) return;
|
|
1589
|
-
const
|
|
1589
|
+
const session = sessionOf(sessionId);
|
|
1590
1590
|
const conversation = ctx.get("conversation");
|
|
1591
1591
|
const scope = ctx.sessions.scope?.(sessionId);
|
|
1592
|
-
if (
|
|
1592
|
+
if (session === void 0 || conversation?.input === void 0 || conversation.createDrafts === void 0 || scope === void 0) {
|
|
1593
1593
|
rewindLog.warn("refill", "image restore unavailable (conversation services not ready)");
|
|
1594
1594
|
return;
|
|
1595
1595
|
}
|
|
@@ -1601,11 +1601,12 @@ function apply(ctx) {
|
|
|
1601
1601
|
continue;
|
|
1602
1602
|
}
|
|
1603
1603
|
try {
|
|
1604
|
-
const
|
|
1605
|
-
|
|
1606
|
-
|
|
1604
|
+
const result = await session.readAttachment(ref.attachmentId);
|
|
1605
|
+
if (!result.ok) throw result.error;
|
|
1606
|
+
const bytes = result.value.data;
|
|
1607
|
+
files.push(new File([bytes], ref.name ?? `image-${index + 1}.${extension}`, { type: ref.mediaType }));
|
|
1607
1608
|
} catch (error) {
|
|
1608
|
-
rewindLog.warn("refill", `image
|
|
1609
|
+
rewindLog.warn("refill", `image read threw for ${ref.attachmentId}`, error);
|
|
1609
1610
|
}
|
|
1610
1611
|
}
|
|
1611
1612
|
if (files.length === 0) return;
|
package/lib/index.js
CHANGED
|
@@ -224,14 +224,6 @@ function planRewind(events, surface, target) {
|
|
|
224
224
|
};
|
|
225
225
|
}
|
|
226
226
|
|
|
227
|
-
// src/session-cwd.ts
|
|
228
|
-
function sessionCwd(cwd) {
|
|
229
|
-
return cwd;
|
|
230
|
-
}
|
|
231
|
-
function execSessionCwd(exec) {
|
|
232
|
-
return sessionCwd(exec.agent?.session.header.cwd);
|
|
233
|
-
}
|
|
234
|
-
|
|
235
227
|
// src/snapshot.ts
|
|
236
228
|
import { createHash } from "node:crypto";
|
|
237
229
|
import { chmod, copyFile, lstat, mkdir, open, readFile, readdir, realpath, rename, rm, stat, writeFile } from "node:fs/promises";
|
|
@@ -2388,10 +2380,7 @@ function anchorSeqOf(session, cache) {
|
|
|
2388
2380
|
}
|
|
2389
2381
|
async function resolveTarget(fs, path, cwd, signal) {
|
|
2390
2382
|
try {
|
|
2391
|
-
return await fs.resolve(path, {
|
|
2392
|
-
...cwd !== void 0 ? { cwd } : {},
|
|
2393
|
-
signal
|
|
2394
|
-
});
|
|
2383
|
+
return await fs.resolve(path, { cwd, signal });
|
|
2395
2384
|
} catch {
|
|
2396
2385
|
return void 0;
|
|
2397
2386
|
}
|
|
@@ -2400,20 +2389,20 @@ function isNotFoundError(error) {
|
|
|
2400
2389
|
const code = error?.code;
|
|
2401
2390
|
return code === "ENOENT" || code === "FS_NOT_FOUND";
|
|
2402
2391
|
}
|
|
2403
|
-
async function captureBefore(fs, store, exec, pending) {
|
|
2392
|
+
async function captureBefore(fs, workingDirectory, store, exec, pending) {
|
|
2404
2393
|
if (!TRACKED_TOOLS.has(exec.name)) return;
|
|
2405
|
-
const
|
|
2406
|
-
if (
|
|
2394
|
+
const agent = exec.agent;
|
|
2395
|
+
if (agent === void 0) return;
|
|
2396
|
+
if (isSubagentSession(agent.session)) return;
|
|
2407
2397
|
const path = mutationPathOf(exec);
|
|
2408
2398
|
if (path === void 0) return;
|
|
2409
|
-
const cwd =
|
|
2399
|
+
const cwd = await workingDirectory.ensure(agent, exec.signal);
|
|
2410
2400
|
const target = await resolveTarget(fs, path, cwd, exec.signal);
|
|
2411
2401
|
if (target === void 0) return;
|
|
2412
2402
|
const info = await fs.stat(target, exec.signal).catch((error) => {
|
|
2413
2403
|
if (isNotFoundError(error)) return void 0;
|
|
2414
2404
|
throw error;
|
|
2415
2405
|
});
|
|
2416
|
-
if (session === void 0) return;
|
|
2417
2406
|
if (info !== void 0 && info.type !== "file") return;
|
|
2418
2407
|
if (info !== void 0 && store.isOverFileCap(info.size)) return;
|
|
2419
2408
|
const key = `${exec.agent?.id ?? "anon"}:${exec.callId}`;
|
|
@@ -2421,7 +2410,7 @@ async function captureBefore(fs, store, exec, pending) {
|
|
|
2421
2410
|
pending.set(key, { path: target.displayPath, backup: null });
|
|
2422
2411
|
return;
|
|
2423
2412
|
}
|
|
2424
|
-
const staged = await store.stageCapture(session.id, key);
|
|
2413
|
+
const staged = await store.stageCapture(agent.session.id, key);
|
|
2425
2414
|
let backup;
|
|
2426
2415
|
try {
|
|
2427
2416
|
await copyFile2(target.displayPath, staged);
|
|
@@ -2959,12 +2948,13 @@ function apply(ctx, config) {
|
|
|
2959
2948
|
}
|
|
2960
2949
|
})();
|
|
2961
2950
|
}, { global: true });
|
|
2962
|
-
ctx.inject(["fs"], (scope) => {
|
|
2951
|
+
ctx.inject(["fs", "workingDirectory"], (scope) => {
|
|
2963
2952
|
const fs = scope.fs;
|
|
2953
|
+
const workingDirectory = scope.workingDirectory;
|
|
2964
2954
|
fsService = fs;
|
|
2965
2955
|
scope.on("tools/execute", async (exec, next) => {
|
|
2966
2956
|
try {
|
|
2967
|
-
await captureBefore(fs, store, exec, pending);
|
|
2957
|
+
await captureBefore(fs, workingDirectory, store, exec, pending);
|
|
2968
2958
|
} catch (error) {
|
|
2969
2959
|
ctx.logger.warn(`[dsh-rewind] before-capture failed for ${exec.name}: ${error instanceof Error ? error.message : String(error)}`);
|
|
2970
2960
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-rewind-plugin",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.16.0-alpha.1",
|
|
4
4
|
"description": "In-window conversation rewind with workspace file restore · 同窗口内对话回退并可还原工作区文件",
|
|
5
5
|
"icon": "./assets/icon.svg",
|
|
6
6
|
"keywords": [
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
"license": "MIT",
|
|
21
21
|
"engines": {
|
|
22
22
|
"node": "^22.19.0 || >=24.0.0",
|
|
23
|
-
"dsh": ">=0.2.
|
|
23
|
+
"dsh": ">=0.2.1-alpha.2"
|
|
24
24
|
},
|
|
25
25
|
"type": "module",
|
|
26
26
|
"main": "lib/index.js",
|
|
@@ -74,20 +74,21 @@
|
|
|
74
74
|
},
|
|
75
75
|
"peerDependencies": {
|
|
76
76
|
"@deepseek-ai/cordis": "^4.0.1",
|
|
77
|
-
"@deepseek-ai/dsh-client-locale": "^0.2.
|
|
78
|
-
"@deepseek-ai/dsh-client-ui-commands": "^0.2.
|
|
79
|
-
"@deepseek-ai/dsh-client-ui-plugin-manager": "^0.2.
|
|
80
|
-
"@deepseek-ai/dsh-client-ui-primitives": "^0.2.
|
|
81
|
-
"@deepseek-ai/dsh-client-ui-settings": "^0.2.
|
|
82
|
-
"@deepseek-ai/dsh-client-ui-slots": "^0.2.
|
|
83
|
-
"@deepseek-ai/dsh-commands": "^0.2.
|
|
84
|
-
"@deepseek-ai/dsh-fs": "^0.2.
|
|
85
|
-
"@deepseek-ai/dsh-home-paths": "^0.2.
|
|
86
|
-
"@deepseek-ai/dsh-llm": "^0.2.
|
|
87
|
-
"@deepseek-ai/dsh-sandbox": "^0.2.
|
|
88
|
-
"@deepseek-ai/dsh-session": "^0.2.
|
|
89
|
-
"@deepseek-ai/dsh-settings": "^0.2.
|
|
90
|
-
"@deepseek-ai/dsh-tools": "^0.2.
|
|
77
|
+
"@deepseek-ai/dsh-client-locale": "^0.2.1-alpha.2",
|
|
78
|
+
"@deepseek-ai/dsh-client-ui-commands": "^0.2.1-alpha.2",
|
|
79
|
+
"@deepseek-ai/dsh-client-ui-plugin-manager": "^0.2.1-alpha.2",
|
|
80
|
+
"@deepseek-ai/dsh-client-ui-primitives": "^0.2.1-alpha.2",
|
|
81
|
+
"@deepseek-ai/dsh-client-ui-settings": "^0.2.1-alpha.2",
|
|
82
|
+
"@deepseek-ai/dsh-client-ui-slots": "^0.2.1-alpha.2",
|
|
83
|
+
"@deepseek-ai/dsh-commands": "^0.2.1-alpha.2",
|
|
84
|
+
"@deepseek-ai/dsh-fs": "^0.2.1-alpha.2",
|
|
85
|
+
"@deepseek-ai/dsh-home-paths": "^0.2.1-alpha.2",
|
|
86
|
+
"@deepseek-ai/dsh-llm": "^0.2.1-alpha.2",
|
|
87
|
+
"@deepseek-ai/dsh-sandbox": "^0.2.1-alpha.2",
|
|
88
|
+
"@deepseek-ai/dsh-session": "^0.2.1-alpha.2",
|
|
89
|
+
"@deepseek-ai/dsh-settings": "^0.2.1-alpha.2",
|
|
90
|
+
"@deepseek-ai/dsh-tools": "^0.2.1-alpha.2",
|
|
91
|
+
"@deepseek-ai/dsh-working-directory": "^0.2.1-alpha.2",
|
|
91
92
|
"@deepseek-ai/schemastery": "^3.18.4"
|
|
92
93
|
},
|
|
93
94
|
"peerDependenciesMeta": {
|
|
@@ -136,6 +137,9 @@
|
|
|
136
137
|
"@deepseek-ai/dsh-tools": {
|
|
137
138
|
"optional": true
|
|
138
139
|
},
|
|
140
|
+
"@deepseek-ai/dsh-working-directory": {
|
|
141
|
+
"optional": true
|
|
142
|
+
},
|
|
139
143
|
"@deepseek-ai/schemastery": {
|
|
140
144
|
"optional": true
|
|
141
145
|
}
|
|
@@ -143,41 +147,42 @@
|
|
|
143
147
|
"devDependencies": {
|
|
144
148
|
"@deepseek-ai/cordis": "4.0.3",
|
|
145
149
|
"@deepseek-ai/cosmokit": "1.8.4",
|
|
146
|
-
"@deepseek-ai/dsh-agent": "0.2.1-alpha.
|
|
147
|
-
"@deepseek-ai/dsh-api-session-controller": "0.2.1-alpha.
|
|
148
|
-
"@deepseek-ai/dsh-attachment": "0.2.1-alpha.
|
|
149
|
-
"@deepseek-ai/dsh-client-connection": "0.2.1-alpha.
|
|
150
|
-
"@deepseek-ai/dsh-client-locale": "0.2.1-alpha.
|
|
151
|
-
"@deepseek-ai/dsh-client-store": "0.2.1-alpha.
|
|
152
|
-
"@deepseek-ai/dsh-client-ui-commands": "0.2.1-alpha.
|
|
153
|
-
"@deepseek-ai/dsh-client-ui-conversation": "0.2.1-alpha.
|
|
154
|
-
"@deepseek-ai/dsh-client-ui-input-trigger": "0.2.1-alpha.
|
|
155
|
-
"@deepseek-ai/dsh-client-ui-plugin-manager": "0.2.1-alpha.
|
|
156
|
-
"@deepseek-ai/dsh-client-ui-primitives": "0.2.1-alpha.
|
|
157
|
-
"@deepseek-ai/dsh-client-ui-session": "0.2.1-alpha.
|
|
158
|
-
"@deepseek-ai/dsh-client-ui-settings": "0.2.1-alpha.
|
|
159
|
-
"@deepseek-ai/dsh-client-ui-slots": "0.2.1-alpha.
|
|
160
|
-
"@deepseek-ai/dsh-command-compact": "0.2.1-alpha.
|
|
161
|
-
"@deepseek-ai/dsh-commands": "0.2.1-alpha.
|
|
162
|
-
"@deepseek-ai/dsh-compaction": "0.2.1-alpha.
|
|
163
|
-
"@deepseek-ai/dsh-compaction-basic": "0.2.1-alpha.
|
|
164
|
-
"@deepseek-ai/dsh-compaction-image-offload": "0.2.1-alpha.
|
|
165
|
-
"@deepseek-ai/dsh-fs": "0.2.1-alpha.
|
|
166
|
-
"@deepseek-ai/dsh-goal": "0.2.1-alpha.
|
|
167
|
-
"@deepseek-ai/dsh-home-paths": "0.2.1-alpha.
|
|
168
|
-
"@deepseek-ai/dsh-llm": "0.2.1-alpha.
|
|
169
|
-
"@deepseek-ai/dsh-plan-mode": "0.2.1-alpha.
|
|
170
|
-
"@deepseek-ai/dsh-sandbox": "0.2.1-alpha.
|
|
171
|
-
"@deepseek-ai/dsh-scope": "0.2.1-alpha.
|
|
172
|
-
"@deepseek-ai/dsh-session": "0.2.1-alpha.
|
|
173
|
-
"@deepseek-ai/dsh-session-projection": "0.2.1-alpha.
|
|
174
|
-
"@deepseek-ai/dsh-session-stats": "0.2.1-alpha.
|
|
175
|
-
"@deepseek-ai/dsh-session-title": "0.2.1-alpha.
|
|
176
|
-
"@deepseek-ai/dsh-settings": "0.2.1-alpha.
|
|
177
|
-
"@deepseek-ai/dsh-token-meter": "0.2.1-alpha.
|
|
178
|
-
"@deepseek-ai/dsh-tools": "0.2.1-alpha.
|
|
179
|
-
"@deepseek-ai/dsh-typert-protocol": "0.2.1-alpha.
|
|
180
|
-
"@deepseek-ai/dsh-user-questions": "0.2.1-alpha.
|
|
150
|
+
"@deepseek-ai/dsh-agent": "0.2.1-alpha.2",
|
|
151
|
+
"@deepseek-ai/dsh-api-session-controller": "0.2.1-alpha.2",
|
|
152
|
+
"@deepseek-ai/dsh-attachment": "0.2.1-alpha.2",
|
|
153
|
+
"@deepseek-ai/dsh-client-connection": "0.2.1-alpha.2",
|
|
154
|
+
"@deepseek-ai/dsh-client-locale": "0.2.1-alpha.2",
|
|
155
|
+
"@deepseek-ai/dsh-client-store": "0.2.1-alpha.2",
|
|
156
|
+
"@deepseek-ai/dsh-client-ui-commands": "0.2.1-alpha.2",
|
|
157
|
+
"@deepseek-ai/dsh-client-ui-conversation": "0.2.1-alpha.2",
|
|
158
|
+
"@deepseek-ai/dsh-client-ui-input-trigger": "0.2.1-alpha.2",
|
|
159
|
+
"@deepseek-ai/dsh-client-ui-plugin-manager": "0.2.1-alpha.2",
|
|
160
|
+
"@deepseek-ai/dsh-client-ui-primitives": "0.2.1-alpha.2",
|
|
161
|
+
"@deepseek-ai/dsh-client-ui-session": "0.2.1-alpha.2",
|
|
162
|
+
"@deepseek-ai/dsh-client-ui-settings": "0.2.1-alpha.2",
|
|
163
|
+
"@deepseek-ai/dsh-client-ui-slots": "0.2.1-alpha.2",
|
|
164
|
+
"@deepseek-ai/dsh-command-compact": "0.2.1-alpha.2",
|
|
165
|
+
"@deepseek-ai/dsh-commands": "0.2.1-alpha.2",
|
|
166
|
+
"@deepseek-ai/dsh-compaction": "0.2.1-alpha.2",
|
|
167
|
+
"@deepseek-ai/dsh-compaction-basic": "0.2.1-alpha.2",
|
|
168
|
+
"@deepseek-ai/dsh-compaction-image-offload": "0.2.1-alpha.2",
|
|
169
|
+
"@deepseek-ai/dsh-fs": "0.2.1-alpha.2",
|
|
170
|
+
"@deepseek-ai/dsh-goal": "0.2.1-alpha.2",
|
|
171
|
+
"@deepseek-ai/dsh-home-paths": "0.2.1-alpha.2",
|
|
172
|
+
"@deepseek-ai/dsh-llm": "0.2.1-alpha.2",
|
|
173
|
+
"@deepseek-ai/dsh-plan-mode": "0.2.1-alpha.2",
|
|
174
|
+
"@deepseek-ai/dsh-sandbox": "0.2.1-alpha.2",
|
|
175
|
+
"@deepseek-ai/dsh-scope": "0.2.1-alpha.2",
|
|
176
|
+
"@deepseek-ai/dsh-session": "0.2.1-alpha.2",
|
|
177
|
+
"@deepseek-ai/dsh-session-projection": "0.2.1-alpha.2",
|
|
178
|
+
"@deepseek-ai/dsh-session-stats": "0.2.1-alpha.2",
|
|
179
|
+
"@deepseek-ai/dsh-session-title": "0.2.1-alpha.2",
|
|
180
|
+
"@deepseek-ai/dsh-settings": "0.2.1-alpha.2",
|
|
181
|
+
"@deepseek-ai/dsh-token-meter": "0.2.1-alpha.2",
|
|
182
|
+
"@deepseek-ai/dsh-tools": "0.2.1-alpha.2",
|
|
183
|
+
"@deepseek-ai/dsh-typert-protocol": "0.2.1-alpha.2",
|
|
184
|
+
"@deepseek-ai/dsh-user-questions": "0.2.1-alpha.2",
|
|
185
|
+
"@deepseek-ai/dsh-working-directory": "0.2.1-alpha.2",
|
|
181
186
|
"@deepseek-ai/schemastery": "3.18.4",
|
|
182
187
|
"@types/node": "^24.0.0",
|
|
183
188
|
"@types/react": "^18.3.31",
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Session-cwd resolution for snapshot tracking reads, mirroring the fs tools'
|
|
3
|
-
* own rule (`@deepseek-ai/dsh-tool-fs/session-cwd.ts`): relative paths
|
|
4
|
-
* resolve against the calling agent's session workspace
|
|
5
|
-
* (`exec.agent.session.header.cwd`), not the server's launch dir.
|
|
6
|
-
*
|
|
7
|
-
* Pure functions: the session cwd is returned verbatim. The fs tools no longer
|
|
8
|
-
* canonicalize a parent-traversing cwd (alpha line), so neither does the
|
|
9
|
-
* plugin — snapshot tracking must resolve to the same base the tool wrote to.
|
|
10
|
-
*
|
|
11
|
-
* @module dsh-rewind/session-cwd
|
|
12
|
-
*/
|
|
13
|
-
import type { ToolExecution } from '@deepseek-ai/dsh-tools';
|
|
14
|
-
/**
|
|
15
|
-
* The session workspace cwd to resolve a requested path against, or undefined
|
|
16
|
-
* when no session cwd applies (the filesystem backend then uses its own
|
|
17
|
-
* default base).
|
|
18
|
-
* @param cwd - the session's `header.cwd`, if any.
|
|
19
|
-
* @returns the cwd unchanged.
|
|
20
|
-
*/
|
|
21
|
-
export declare function sessionCwd(cwd: string | undefined): string | undefined;
|
|
22
|
-
/**
|
|
23
|
-
* Session cwd for one tool execution (same rule as the fs tools).
|
|
24
|
-
* @param exec - the tool-execution context; only its optional `agent` is read.
|
|
25
|
-
* @returns the calling agent's session cwd, or undefined for a non-agent caller.
|
|
26
|
-
*/
|
|
27
|
-
export declare function execSessionCwd(exec: ToolExecution): string | undefined;
|