@mengruo/dsh-vision-toolkit 0.1.3 → 0.1.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.i18n.yaml +2 -2
- package/README.md +4 -0
- package/README.zh.md +4 -0
- package/docs/requirements-traceability/README.i18n.yaml +2 -2
- package/docs/requirements-traceability/README.md +1 -1
- package/docs/requirements-traceability/README.zh.md +1 -1
- package/lib/artifact-access.js +20 -2
- package/lib/artifact-access.js.map +1 -1
- package/lib/client.js +22 -7
- package/lib/client.js.map +1 -1
- package/lib/config.js +34 -0
- package/lib/config.js.map +1 -1
- package/lib/errors.js +25 -2
- package/lib/errors.js.map +1 -1
- package/lib/evidence-cache.js +2 -1
- package/lib/evidence-cache.js.map +1 -1
- package/lib/exposure.js +14 -1
- package/lib/exposure.js.map +1 -1
- package/lib/image-input-variants.js +22 -12
- package/lib/image-input-variants.js.map +1 -1
- package/lib/index.js +53 -6
- package/lib/index.js.map +1 -1
- package/lib/paste-images.js +67 -19
- package/lib/paste-images.js.map +1 -1
- package/lib/paths.js +214 -28
- package/lib/paths.js.map +1 -1
- package/lib/runtime-manager.js +76 -10
- package/lib/runtime-manager.js.map +1 -1
- package/lib/runtime.js +80 -12
- package/lib/runtime.js.map +1 -1
- package/lib/storage-history.js +154 -0
- package/lib/storage-history.js.map +1 -0
- package/lib/types/artifact-access.d.ts.map +1 -1
- package/lib/types/client/index.d.ts +6 -1
- package/lib/types/client/index.d.ts.map +1 -1
- package/lib/types/client/paste-images.d.ts +2 -0
- package/lib/types/client/paste-images.d.ts.map +1 -1
- package/lib/types/config.d.ts +22 -0
- package/lib/types/config.d.ts.map +1 -1
- package/lib/types/errors.d.ts +18 -2
- package/lib/types/errors.d.ts.map +1 -1
- package/lib/types/evidence-cache.d.ts +1 -1
- package/lib/types/evidence-cache.d.ts.map +1 -1
- package/lib/types/exposure.d.ts.map +1 -1
- package/lib/types/image-input-variants.d.ts +5 -3
- package/lib/types/image-input-variants.d.ts.map +1 -1
- package/lib/types/index.d.ts.map +1 -1
- package/lib/types/paste-images.d.ts +12 -4
- package/lib/types/paste-images.d.ts.map +1 -1
- package/lib/types/paths.d.ts +31 -5
- package/lib/types/paths.d.ts.map +1 -1
- package/lib/types/runtime-manager.d.ts +28 -4
- package/lib/types/runtime-manager.d.ts.map +1 -1
- package/lib/types/runtime.d.ts +19 -1
- package/lib/types/runtime.d.ts.map +1 -1
- package/lib/types/storage-history.d.ts +63 -0
- package/lib/types/storage-history.d.ts.map +1 -0
- package/lib/types/upstream.d.ts.map +1 -1
- package/lib/types/web.d.ts.map +1 -1
- package/lib/upstream.js +31 -8
- package/lib/upstream.js.map +1 -1
- package/lib/web.js +9 -3
- package/lib/web.js.map +1 -1
- package/package.json +1 -1
- package/src/artifact-access.ts +22 -2
- package/src/client/index.tsx +18 -3
- package/src/client/paste-images.tsx +14 -4
- package/src/config.ts +61 -0
- package/src/errors.ts +25 -2
- package/src/evidence-cache.ts +2 -1
- package/src/exposure.ts +16 -2
- package/src/image-input-variants.ts +21 -6
- package/src/index.ts +65 -6
- package/src/paste-images.ts +81 -19
- package/src/paths.ts +249 -28
- package/src/runtime-manager.ts +93 -10
- package/src/runtime.ts +79 -11
- package/src/storage-history.ts +172 -0
- package/src/upstream.ts +32 -7
- package/src/web.ts +9 -2
package/lib/index.js
CHANGED
|
@@ -10,11 +10,12 @@
|
|
|
10
10
|
* @module @mengruo/dsh-vision-toolkit
|
|
11
11
|
*/
|
|
12
12
|
import { ArtifactAccessController, prepareArtifactAccessKey } from "./artifact-access.js";
|
|
13
|
-
import { Config, VISION_TOOLKIT_SETTINGS_NAMESPACE, resolveConfig, } from "./config.js";
|
|
13
|
+
import { Config, VISION_TOOLKIT_SETTINGS_NAMESPACE, prepareWatchedSettingsGeneration, resolveConfig, } from "./config.js";
|
|
14
14
|
import { VisionToolExposure } from "./exposure.js";
|
|
15
15
|
import { createPasteTakeoverResolver, installImageInputVariants } from "./image-input-variants.js";
|
|
16
16
|
import { VisionToolkitRuntimeManager } from "./runtime-manager.js";
|
|
17
17
|
import { VISION_SKILLS_SKILL } from "./skill.js";
|
|
18
|
+
import { StorageHistoryStore } from "./storage-history.js";
|
|
18
19
|
import { createVisionTools } from "./tools.js";
|
|
19
20
|
import { PLUGIN_VERSION } from "./version.js";
|
|
20
21
|
import { installVisionToolkitWeb, VisionToolkitWebBackend } from "./web.js";
|
|
@@ -37,7 +38,33 @@ export async function apply(ctx, config = {}) {
|
|
|
37
38
|
const artifacts = new ArtifactAccessController(await prepareArtifactAccessKey());
|
|
38
39
|
const lifecycle = new AbortController();
|
|
39
40
|
const disposers = [];
|
|
41
|
+
const storageHistory = new StorageHistoryStore(ctx);
|
|
42
|
+
disposers.push(() => { storageHistory.dispose(); });
|
|
43
|
+
let storageHistoryWarningReported = false;
|
|
40
44
|
let operationalDisposers;
|
|
45
|
+
const persistStorageHistory = async (candidate, required) => {
|
|
46
|
+
try {
|
|
47
|
+
const persisted = await storageHistory.persist(candidate);
|
|
48
|
+
if (persisted)
|
|
49
|
+
return;
|
|
50
|
+
const error = new Error('configured storage history requires @deepseek-ai/dsh-storage-domain when Settings cannot persist it');
|
|
51
|
+
if (required)
|
|
52
|
+
throw error;
|
|
53
|
+
if (!storageHistoryWarningReported) {
|
|
54
|
+
storageHistoryWarningReported = true;
|
|
55
|
+
ctx.logger.warn('dsh-vision-toolkit: %s', error.message);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
catch (error) {
|
|
59
|
+
if (required)
|
|
60
|
+
throw error;
|
|
61
|
+
if (!storageHistoryWarningReported) {
|
|
62
|
+
storageHistoryWarningReported = true;
|
|
63
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
64
|
+
ctx.logger.warn('dsh-vision-toolkit: configured storage history was not persisted. %s', message);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
};
|
|
41
68
|
const ensureOperational = () => {
|
|
42
69
|
if (!manager.ready || operationalDisposers !== undefined)
|
|
43
70
|
return;
|
|
@@ -61,27 +88,47 @@ export async function apply(ctx, config = {}) {
|
|
|
61
88
|
throw error;
|
|
62
89
|
}
|
|
63
90
|
};
|
|
91
|
+
const initialConfig = await storageHistory.restore(settings.get());
|
|
64
92
|
try {
|
|
65
|
-
await manager.initialize(
|
|
93
|
+
await manager.initialize(initialConfig, candidate => persistStorageHistory(candidate.config, false));
|
|
66
94
|
ensureOperational();
|
|
67
95
|
}
|
|
68
96
|
catch (error) {
|
|
97
|
+
const resolvedInitial = resolveConfig(initialConfig);
|
|
98
|
+
if (resolvedInitial.storageDir === undefined
|
|
99
|
+
|| manager.validatedStorageDirectory() === resolvedInitial.storageDir) {
|
|
100
|
+
await persistStorageHistory(initialConfig, false);
|
|
101
|
+
}
|
|
69
102
|
const message = error instanceof Error ? error.message : String(error);
|
|
70
103
|
ctx.logger.error('dsh-vision-toolkit %s: runtime not ready; the vision-skills skill, activation bootstrap, and Agent-scoped visual tools are NOT registered. Settings remain available for repair. %s', PLUGIN_VERSION, message);
|
|
71
104
|
}
|
|
72
105
|
const backend = new VisionToolkitWebBackend(ctx, manager, artifacts, ensureOperational);
|
|
106
|
+
const currentConfig = () => manager.ready
|
|
107
|
+
? manager.currentConfig()
|
|
108
|
+
: resolveConfig(settings.get());
|
|
73
109
|
const pastedImages = new PastedImageBackend(ctx, {
|
|
74
110
|
maxUploadBytes: () => MAX_PASTE_IMAGE_BYTES,
|
|
111
|
+
storageGeneration: () => manager.storageGeneration(),
|
|
75
112
|
});
|
|
76
113
|
// Image-input variants register asynchronously once eligible routes exist;
|
|
77
114
|
// the runtime getter stays lazy so variants appear even when the runtime
|
|
78
115
|
// becomes ready after the first sweep.
|
|
79
|
-
const variants = installImageInputVariants(ctx,
|
|
80
|
-
installVisionToolkitWeb(ctx, backend, artifacts, pastedImages, createPasteTakeoverResolver(ctx,
|
|
116
|
+
const variants = installImageInputVariants(ctx, currentConfig, () => manager.ready ? manager.current() : undefined, () => manager.validatedStorageDirectory());
|
|
117
|
+
installVisionToolkitWeb(ctx, backend, artifacts, pastedImages, createPasteTakeoverResolver(ctx, currentConfig), () => ({ hidden: currentConfig().imageInputVariants.hidden }));
|
|
81
118
|
disposers.push(variants.dispose);
|
|
82
|
-
disposers.push(settings.watch(async (next) => {
|
|
119
|
+
disposers.push(settings.watch(async (next, previous) => {
|
|
83
120
|
try {
|
|
84
|
-
await
|
|
121
|
+
const prepared = await prepareWatchedSettingsGeneration(next, previous, ctx.settings.writable, storageHistory => settings.update({ storageHistory }));
|
|
122
|
+
if (prepared.persistenceError !== undefined) {
|
|
123
|
+
const message = prepared.persistenceError instanceof Error
|
|
124
|
+
? prepared.persistenceError.message
|
|
125
|
+
: String(prepared.persistenceError);
|
|
126
|
+
ctx.logger.warn('dsh-vision-toolkit: activating Settings without persisting internal storage history. %s', message);
|
|
127
|
+
}
|
|
128
|
+
if (prepared.config === undefined)
|
|
129
|
+
return;
|
|
130
|
+
const candidate = await storageHistory.restore(prepared.config);
|
|
131
|
+
await manager.reconfigure(candidate, generation => persistStorageHistory(generation.config, prepared.requiresDurableStorageHistory === true));
|
|
85
132
|
ensureOperational();
|
|
86
133
|
variants.reconcile();
|
|
87
134
|
}
|
package/lib/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAMH,OAAO,EAAE,wBAAwB,EAAE,wBAAwB,EAAE,MAAM,sBAAsB,CAAA;AACzF,OAAO,EACL,MAAM,EACN,iCAAiC,EACjC,aAAa,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/lib/paste-images.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
/**
|
|
1
|
+
/** Plugin-managed storage for images pasted into the DSH Web composer. */
|
|
2
2
|
import { createHash, randomUUID } from 'node:crypto';
|
|
3
|
-
import {
|
|
3
|
+
import { constants as fsConstants } from 'node:fs';
|
|
4
|
+
import { copyFile, lstat, mkdir, open, realpath, rename, rm } from 'node:fs/promises';
|
|
4
5
|
import { basename, extname, isAbsolute, join, relative, resolve, sep } from 'node:path';
|
|
6
|
+
import { resolveWorkspaceStorage } from "./paths.js";
|
|
5
7
|
import { sameOriginPost } from "./web-request.js";
|
|
6
8
|
/** Exact route used by the browser paste integration. */
|
|
7
9
|
export const PASTE_IMAGES_ROUTE = '/_dsh/vision-toolkit/paste-images';
|
|
@@ -12,6 +14,7 @@ export const PASTE_IMAGES_ROUTE = '/_dsh/vision-toolkit/paste-images';
|
|
|
12
14
|
*/
|
|
13
15
|
export const PASTE_POLICY_ROUTE = '/_dsh/vision-toolkit/paste-policy';
|
|
14
16
|
const MAX_NAME_BYTES = 180;
|
|
17
|
+
const MAX_STORAGE_GENERATION_RETRIES = 4;
|
|
15
18
|
/**
|
|
16
19
|
* Hard per-image upload ceiling for pastes. Files between the configured
|
|
17
20
|
* `maxImageBytes` (default 4 MiB) and this ceiling are stored as-is and
|
|
@@ -95,7 +98,7 @@ export function safePastedImageName(raw, mediaType) {
|
|
|
95
98
|
export function ensurePathInside(root, target) {
|
|
96
99
|
const rel = relative(root, target);
|
|
97
100
|
if (rel !== '' && (rel === '..' || rel.startsWith(`..${sep}`) || isAbsolute(rel))) {
|
|
98
|
-
throw new Error(`resolved pasted-image path escapes its
|
|
101
|
+
throw new Error(`resolved pasted-image path escapes its managed root: ${target}`);
|
|
99
102
|
}
|
|
100
103
|
}
|
|
101
104
|
async function ensureManagedDirectory(workspace, path) {
|
|
@@ -108,7 +111,7 @@ async function ensureManagedDirectory(workspace, path) {
|
|
|
108
111
|
}
|
|
109
112
|
const entry = await lstat(path);
|
|
110
113
|
if (entry.isSymbolicLink()) {
|
|
111
|
-
throw new Error(`resolved pasted-image path escapes its
|
|
114
|
+
throw new Error(`resolved pasted-image path escapes its managed root: symbolic link ${path}`);
|
|
112
115
|
}
|
|
113
116
|
if (!entry.isDirectory())
|
|
114
117
|
throw new Error(`pasted-image path is not a directory: ${path}`);
|
|
@@ -118,29 +121,29 @@ async function ensureManagedDirectory(workspace, path) {
|
|
|
118
121
|
}
|
|
119
122
|
/**
|
|
120
123
|
* Resolve the managed per-session image directory used by both browser pastes
|
|
121
|
-
* and native attachment bridging.
|
|
122
|
-
*
|
|
124
|
+
* and native attachment bridging. A configured shared storage root receives a
|
|
125
|
+
* stable workspace-specific child, keeping projects isolated without writing
|
|
126
|
+
* plugin files into the project directory.
|
|
123
127
|
*/
|
|
124
|
-
export async function sessionPasteRoot(ctx, sessionId) {
|
|
128
|
+
export async function sessionPasteRoot(ctx, sessionId, storageDir) {
|
|
125
129
|
const session = ctx.sessions.get(sessionId);
|
|
126
130
|
if (session === undefined)
|
|
127
131
|
throw new Error(`live Session not found: ${sessionId}`);
|
|
128
132
|
const cwd = session.header.cwd;
|
|
129
133
|
if (cwd === undefined || !isAbsolute(cwd))
|
|
130
134
|
throw new Error(`Session has no absolute workspace: ${sessionId}`);
|
|
131
|
-
const
|
|
132
|
-
const
|
|
133
|
-
const pluginRoot = join(visibleWorkspace, '.dsh-vision-toolkit');
|
|
134
|
-
await ensureManagedDirectory(workspace, pluginRoot);
|
|
135
|
+
const storage = await resolveWorkspaceStorage(resolve(cwd), storageDir);
|
|
136
|
+
const pluginRoot = storage.root;
|
|
135
137
|
const temporaryRoot = join(pluginRoot, 'tmp');
|
|
136
|
-
await ensureManagedDirectory(
|
|
138
|
+
await ensureManagedDirectory(pluginRoot, temporaryRoot);
|
|
137
139
|
const requestedRoot = join(temporaryRoot, 'pasted-images');
|
|
138
|
-
const root = await ensureManagedDirectory(
|
|
140
|
+
const root = await ensureManagedDirectory(temporaryRoot, requestedRoot);
|
|
141
|
+
const visibleRoot = join(storage.visibleRoot, 'tmp', 'pasted-images');
|
|
139
142
|
const sessionKey = createHash('sha256').update(sessionId).digest('hex').slice(0, 20);
|
|
140
143
|
const requestedSessionRoot = join(requestedRoot, sessionKey);
|
|
141
144
|
const sessionRoot = await ensureManagedDirectory(root, requestedSessionRoot);
|
|
142
145
|
ensurePathInside(root, sessionRoot);
|
|
143
|
-
return { writeRoot: sessionRoot, visibleRoot:
|
|
146
|
+
return { writeRoot: sessionRoot, visibleRoot: join(visibleRoot, sessionKey) };
|
|
144
147
|
}
|
|
145
148
|
async function writeImage(req, directory, filename, expectedBytes, maxBytes) {
|
|
146
149
|
if (expectedBytes > maxBytes)
|
|
@@ -174,6 +177,24 @@ async function writeImage(req, directory, filename, expectedBytes, maxBytes) {
|
|
|
174
177
|
throw error;
|
|
175
178
|
}
|
|
176
179
|
}
|
|
180
|
+
async function copyImage(source, directory, filename) {
|
|
181
|
+
const id = randomUUID();
|
|
182
|
+
const finalPath = join(directory, `${id}-${filename}`);
|
|
183
|
+
const stagingPath = join(directory, `.${id}.partial`);
|
|
184
|
+
ensurePathInside(directory, finalPath);
|
|
185
|
+
ensurePathInside(directory, stagingPath);
|
|
186
|
+
try {
|
|
187
|
+
await copyFile(source, stagingPath, fsConstants.COPYFILE_EXCL);
|
|
188
|
+
await rename(stagingPath, finalPath);
|
|
189
|
+
return finalPath;
|
|
190
|
+
}
|
|
191
|
+
catch (error) {
|
|
192
|
+
await rm(stagingPath, { force: true }).catch(() => { });
|
|
193
|
+
throw error;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
class PasteStorageChangedError extends Error {
|
|
197
|
+
}
|
|
177
198
|
/** Same-origin, live-Session-bound image upload endpoint. */
|
|
178
199
|
export class PastedImageBackend {
|
|
179
200
|
ctx;
|
|
@@ -182,6 +203,16 @@ export class PastedImageBackend {
|
|
|
182
203
|
this.ctx = ctx;
|
|
183
204
|
this.runtime = runtime;
|
|
184
205
|
}
|
|
206
|
+
storageGeneration() {
|
|
207
|
+
const current = this.runtime.storageGeneration?.();
|
|
208
|
+
if (current !== undefined)
|
|
209
|
+
return current;
|
|
210
|
+
const storageDir = this.runtime.storageDirectory?.();
|
|
211
|
+
return {
|
|
212
|
+
generation: 0,
|
|
213
|
+
...(storageDir === undefined ? {} : { storageDir }),
|
|
214
|
+
};
|
|
215
|
+
}
|
|
185
216
|
async handle(req, res) {
|
|
186
217
|
if (req.method !== 'POST') {
|
|
187
218
|
res.setHeader('Allow', 'POST');
|
|
@@ -192,6 +223,7 @@ export class PastedImageBackend {
|
|
|
192
223
|
requestError(res, 403, 'origin-rejected', 'The request must originate from this DSH Web application');
|
|
193
224
|
return;
|
|
194
225
|
}
|
|
226
|
+
let managedPath;
|
|
195
227
|
try {
|
|
196
228
|
const url = new URL(req.url ?? PASTE_IMAGES_ROUTE, 'http://dsh.internal');
|
|
197
229
|
const sessionId = singleQuery(url, 'sessionId');
|
|
@@ -202,13 +234,29 @@ export class PastedImageBackend {
|
|
|
202
234
|
if (contentLength !== undefined && Number(contentLength) !== size) {
|
|
203
235
|
throw new TypeError('Content-Length does not match the declared size');
|
|
204
236
|
}
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
237
|
+
let storage = this.storageGeneration();
|
|
238
|
+
let directory = await sessionPasteRoot(this.ctx, sessionId, storage.storageDir);
|
|
239
|
+
managedPath = await writeImage(req, directory.writeRoot, filename, size, this.runtime.maxUploadBytes());
|
|
240
|
+
for (let attempt = 0; attempt < MAX_STORAGE_GENERATION_RETRIES; attempt += 1) {
|
|
241
|
+
const current = this.storageGeneration();
|
|
242
|
+
if (current.generation === storage.generation && current.storageDir === storage.storageDir) {
|
|
243
|
+
const absolutePath = join(directory.visibleRoot, basename(managedPath));
|
|
244
|
+
responseJson(res, 201, { ok: true, value: { absolutePath, filename, bytes: size } });
|
|
245
|
+
return;
|
|
246
|
+
}
|
|
247
|
+
const nextDirectory = await sessionPasteRoot(this.ctx, sessionId, current.storageDir);
|
|
248
|
+
const migratedPath = await copyImage(managedPath, nextDirectory.writeRoot, filename);
|
|
249
|
+
await rm(managedPath, { force: true }).catch(() => { });
|
|
250
|
+
managedPath = migratedPath;
|
|
251
|
+
directory = nextDirectory;
|
|
252
|
+
storage = current;
|
|
253
|
+
}
|
|
254
|
+
throw new PasteStorageChangedError('Vision Toolkit settings changed repeatedly during image copy; retry the paste');
|
|
209
255
|
}
|
|
210
256
|
catch (error) {
|
|
211
|
-
|
|
257
|
+
if (managedPath !== undefined)
|
|
258
|
+
await rm(managedPath, { force: true }).catch(() => { });
|
|
259
|
+
const status = error instanceof PasteStorageChangedError ? 409 : error instanceof RangeError ? 413 : 400;
|
|
212
260
|
this.ctx.logger.warn('dsh-vision-toolkit pasted image rejected: %s', message(error));
|
|
213
261
|
requestError(res, status, 'paste-image-rejected', message(error));
|
|
214
262
|
}
|
package/lib/paste-images.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"paste-images.js","sourceRoot":"","sources":["../src/paste-images.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"paste-images.js","sourceRoot":"","sources":["../src/paste-images.ts"],"names":[],"mappings":"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"}
|
package/lib/paths.js
CHANGED
|
@@ -5,9 +5,9 @@
|
|
|
5
5
|
* link is allowed only when its real target stays inside the fence.
|
|
6
6
|
* @module dsh-vision-toolkit/paths
|
|
7
7
|
*/
|
|
8
|
-
import { randomUUID } from 'node:crypto';
|
|
9
|
-
import { cp, link, lstat, mkdir, readdir, realpath, rename, rm, stat } from 'node:fs/promises';
|
|
10
|
-
import { extname, isAbsolute, join, relative, resolve, sep, win32 } from 'node:path';
|
|
8
|
+
import { createHash, randomUUID } from 'node:crypto';
|
|
9
|
+
import { cp, link, lstat, mkdir, mkdtemp, readdir, realpath, rename, rm, stat } from 'node:fs/promises';
|
|
10
|
+
import { dirname, extname, isAbsolute, join, relative, resolve, sep, win32 } from 'node:path';
|
|
11
11
|
import { homedir, tmpdir } from 'node:os';
|
|
12
12
|
import { VisionToolkitError } from "./errors.js";
|
|
13
13
|
/** Supported input image extensions (the upstream client's allowlist). */
|
|
@@ -45,23 +45,205 @@ export function normalizePlatformTempPath(raw, platform = process.platform, temp
|
|
|
45
45
|
return raw;
|
|
46
46
|
return win32.join(tempDirectory, raw.slice('/tmp/'.length));
|
|
47
47
|
}
|
|
48
|
+
/** Stable opaque per-user workspace id used below a shared storage root. */
|
|
49
|
+
export function workspaceStorageId(workspace, userIdentity = typeof process.geteuid === 'function'
|
|
50
|
+
? `uid:${process.geteuid()}`
|
|
51
|
+
: `home:${homedir()}`) {
|
|
52
|
+
return createHash('sha256')
|
|
53
|
+
.update(userIdentity)
|
|
54
|
+
.update('\0')
|
|
55
|
+
.update(workspace)
|
|
56
|
+
.digest('hex')
|
|
57
|
+
.slice(0, 20);
|
|
58
|
+
}
|
|
59
|
+
function currentPosixUid() {
|
|
60
|
+
if (typeof process.geteuid !== 'function') {
|
|
61
|
+
throw new VisionToolkitError('path', 'configured storage directory is not supported on this platform because ownership and permissions cannot be verified');
|
|
62
|
+
}
|
|
63
|
+
return process.geteuid();
|
|
64
|
+
}
|
|
65
|
+
export function assertSecureWorkspaceStorage(info, requested) {
|
|
66
|
+
const currentUid = currentPosixUid();
|
|
67
|
+
if (info.uid !== currentUid || (info.mode & 0o777) !== 0o700) {
|
|
68
|
+
throw new VisionToolkitError('path', `workspace storage directory must be owned by the current user with mode 0700: ${requested}`);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
/** Resolve a shared base and prove every POSIX ancestor is protected from replacement. */
|
|
72
|
+
export async function assertSecureSharedStorageBase(requested) {
|
|
73
|
+
const currentUid = currentPosixUid();
|
|
74
|
+
const requestedPath = resolve(requested);
|
|
75
|
+
const requestedChain = [];
|
|
76
|
+
let requestedCurrent = requestedPath;
|
|
77
|
+
while (true) {
|
|
78
|
+
requestedChain.push(requestedCurrent);
|
|
79
|
+
const parent = dirname(requestedCurrent);
|
|
80
|
+
if (parent === requestedCurrent)
|
|
81
|
+
break;
|
|
82
|
+
requestedCurrent = parent;
|
|
83
|
+
}
|
|
84
|
+
for (const component of requestedChain.reverse()) {
|
|
85
|
+
const info = await lstat(component);
|
|
86
|
+
if (info.isSymbolicLink()) {
|
|
87
|
+
if (info.uid !== 0) {
|
|
88
|
+
throw new VisionToolkitError('path', `configured storage directory contains an untrusted symbolic link: ${component}`);
|
|
89
|
+
}
|
|
90
|
+
continue;
|
|
91
|
+
}
|
|
92
|
+
if (!info.isDirectory()) {
|
|
93
|
+
throw new VisionToolkitError('path', `configured storage path component is not a directory: ${component}`);
|
|
94
|
+
}
|
|
95
|
+
const writableByOthers = (info.mode & 0o022) !== 0;
|
|
96
|
+
const sticky = (info.mode & 0o1000) !== 0;
|
|
97
|
+
if ((info.uid !== currentUid && info.uid !== 0)
|
|
98
|
+
|| (writableByOthers && !sticky))
|
|
99
|
+
throw new VisionToolkitError('path', `configured storage directory has an untrusted path component: ${component}`);
|
|
100
|
+
}
|
|
101
|
+
const canonical = await realpath(requestedPath);
|
|
102
|
+
let current = canonical;
|
|
103
|
+
while (true) {
|
|
104
|
+
const info = await lstat(current);
|
|
105
|
+
const writableByOthers = (info.mode & 0o022) !== 0;
|
|
106
|
+
const sticky = (info.mode & 0o1000) !== 0;
|
|
107
|
+
if (info.isSymbolicLink()
|
|
108
|
+
|| !info.isDirectory()
|
|
109
|
+
|| (info.uid !== currentUid && info.uid !== 0)
|
|
110
|
+
|| (writableByOthers && !sticky))
|
|
111
|
+
throw new VisionToolkitError('path', `configured storage directory has an untrusted path component: ${current}`);
|
|
112
|
+
const parent = dirname(current);
|
|
113
|
+
if (parent === current)
|
|
114
|
+
return canonical;
|
|
115
|
+
current = parent;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
function requestedSharedStorageBase(storageDirRaw) {
|
|
119
|
+
currentPosixUid();
|
|
120
|
+
const configured = normalizePlatformTempPath(expandUserHome(storageDirRaw.trim()));
|
|
121
|
+
if (!isAbsolute(configured)) {
|
|
122
|
+
throw new VisionToolkitError('path', `configured storage directory must be an absolute path: ${storageDirRaw}`);
|
|
123
|
+
}
|
|
124
|
+
return resolve(configured);
|
|
125
|
+
}
|
|
126
|
+
async function ensureSharedStorageBase(storageDirRaw) {
|
|
127
|
+
const requestedBase = requestedSharedStorageBase(storageDirRaw);
|
|
128
|
+
try {
|
|
129
|
+
await mkdir(requestedBase, { recursive: true, mode: 0o700 });
|
|
130
|
+
}
|
|
131
|
+
catch (error) {
|
|
132
|
+
throw new VisionToolkitError('path', `configured storage directory is not writable: ${requestedBase}`, { cause: error });
|
|
133
|
+
}
|
|
134
|
+
try {
|
|
135
|
+
return { requestedBase, base: await assertSecureSharedStorageBase(requestedBase) };
|
|
136
|
+
}
|
|
137
|
+
catch (error) {
|
|
138
|
+
throw new VisionToolkitError('path', `configured storage directory is not accessible: ${requestedBase}`, { cause: error });
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
/** Validate and write-probe a configured shared root before Settings activation. */
|
|
142
|
+
export async function preflightSharedStorageBase(storageDirRaw) {
|
|
143
|
+
const { base } = await ensureSharedStorageBase(storageDirRaw);
|
|
144
|
+
let probe;
|
|
145
|
+
let failure;
|
|
146
|
+
try {
|
|
147
|
+
probe = await mkdtemp(join(base, '.dsh-vision-toolkit-preflight-'));
|
|
148
|
+
assertSecureWorkspaceStorage(await lstat(probe), probe);
|
|
149
|
+
}
|
|
150
|
+
catch (error) {
|
|
151
|
+
failure = error;
|
|
152
|
+
}
|
|
153
|
+
if (probe !== undefined) {
|
|
154
|
+
try {
|
|
155
|
+
await rm(probe, { recursive: true, force: true });
|
|
156
|
+
}
|
|
157
|
+
catch (error) {
|
|
158
|
+
failure ??= error;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
if (failure !== undefined) {
|
|
162
|
+
throw new VisionToolkitError('path', `configured storage directory failed its write preflight: ${base}`, { cause: failure });
|
|
163
|
+
}
|
|
164
|
+
return base;
|
|
165
|
+
}
|
|
166
|
+
async function managedDirectory(parent, requested, label, secureWorkspaceStorage = false) {
|
|
167
|
+
try {
|
|
168
|
+
await mkdir(requested, { mode: 0o700 });
|
|
169
|
+
}
|
|
170
|
+
catch (error) {
|
|
171
|
+
if (!(error instanceof Error && 'code' in error && error.code === 'EEXIST')) {
|
|
172
|
+
throw new VisionToolkitError('path', `${label} is not writable: ${requested}`, { cause: error });
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
let info;
|
|
176
|
+
try {
|
|
177
|
+
info = await lstat(requested);
|
|
178
|
+
}
|
|
179
|
+
catch (error) {
|
|
180
|
+
throw new VisionToolkitError('path', `${label} is not accessible: ${requested}`, { cause: error });
|
|
181
|
+
}
|
|
182
|
+
if (info.isSymbolicLink() || !info.isDirectory()) {
|
|
183
|
+
throw new VisionToolkitError('path', `${label} must be a real directory: ${requested}`);
|
|
184
|
+
}
|
|
185
|
+
if (secureWorkspaceStorage)
|
|
186
|
+
assertSecureWorkspaceStorage(info, requested);
|
|
187
|
+
const canonical = await realpath(requested);
|
|
188
|
+
if (!isWithin(parent, canonical)) {
|
|
189
|
+
throw new VisionToolkitError('path', `${label} escaped its configured root: ${requested}`);
|
|
190
|
+
}
|
|
191
|
+
return canonical;
|
|
192
|
+
}
|
|
48
193
|
/**
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
* @param workspaceRaw - session workspace (or process cwd fallback).
|
|
53
|
-
* @param allowedDirs - configured extra allowed roots.
|
|
54
|
-
* @param outputDirRaw - configured output directory (default `.dsh-vision-toolkit/artifacts`).
|
|
55
|
-
* @returns the resolved policy.
|
|
194
|
+
* Resolve the plugin-managed root for one workspace. Blank configuration keeps
|
|
195
|
+
* the legacy workspace-local `.dsh-vision-toolkit` directory. A configured
|
|
196
|
+
* shared root receives one stable, automatically generated workspace child.
|
|
56
197
|
*/
|
|
57
|
-
export async function
|
|
198
|
+
export async function resolveWorkspaceStorage(workspaceRaw, storageDirRaw) {
|
|
199
|
+
const expandedWorkspace = expandUserHome(workspaceRaw);
|
|
200
|
+
const visibleWorkspace = resolve(expandedWorkspace);
|
|
58
201
|
let workspace;
|
|
59
202
|
try {
|
|
60
|
-
workspace = await realpath(
|
|
203
|
+
workspace = await realpath(visibleWorkspace);
|
|
61
204
|
}
|
|
62
205
|
catch (error) {
|
|
63
206
|
throw new VisionToolkitError('path', `workspace is not accessible: ${workspaceRaw}`, { cause: error });
|
|
64
207
|
}
|
|
208
|
+
if (storageDirRaw === undefined || storageDirRaw.trim().length === 0) {
|
|
209
|
+
const visibleRoot = join(visibleWorkspace, '.dsh-vision-toolkit');
|
|
210
|
+
const root = await managedDirectory(workspace, visibleRoot, 'plugin storage directory');
|
|
211
|
+
return { workspace, root, visibleRoot };
|
|
212
|
+
}
|
|
213
|
+
const { requestedBase, base } = await ensureSharedStorageBase(storageDirRaw);
|
|
214
|
+
const id = workspaceStorageId(workspace);
|
|
215
|
+
const visibleRoot = join(requestedBase, id);
|
|
216
|
+
const root = await managedDirectory(base, join(base, id), 'workspace storage directory', true);
|
|
217
|
+
return { workspace, root, visibleRoot };
|
|
218
|
+
}
|
|
219
|
+
async function resolveReadableWorkspaceStorageRoot(workspace, storageDirRaw) {
|
|
220
|
+
const requestedBase = requestedSharedStorageBase(storageDirRaw);
|
|
221
|
+
const base = await assertSecureSharedStorageBase(requestedBase);
|
|
222
|
+
const requestedRoot = join(base, workspaceStorageId(workspace));
|
|
223
|
+
const info = await lstat(requestedRoot);
|
|
224
|
+
if (info.isSymbolicLink() || !info.isDirectory()) {
|
|
225
|
+
throw new VisionToolkitError('path', `historical workspace storage must be a real directory: ${requestedRoot}`);
|
|
226
|
+
}
|
|
227
|
+
assertSecureWorkspaceStorage(info, requestedRoot);
|
|
228
|
+
const root = await realpath(requestedRoot);
|
|
229
|
+
if (!isWithin(base, root)) {
|
|
230
|
+
throw new VisionToolkitError('path', `historical workspace storage escaped its configured root: ${requestedRoot}`);
|
|
231
|
+
}
|
|
232
|
+
return root;
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* Build the per-invocation path policy: resolve workspace storage, realpath the
|
|
236
|
+
* platform temp directory and allowed directories, and create the artifact
|
|
237
|
+
* directory inside the managed root.
|
|
238
|
+
* @param workspaceRaw - session workspace (or process cwd fallback).
|
|
239
|
+
* @param allowedDirs - configured extra allowed roots.
|
|
240
|
+
* @param storageDirRaw - optional shared storage root.
|
|
241
|
+
* @param readableStorageDirs - previously validated shared roots retained for persisted input paths.
|
|
242
|
+
* @returns the resolved policy.
|
|
243
|
+
*/
|
|
244
|
+
export async function createPathPolicy(workspaceRaw, allowedDirs, storageDirRaw, readableStorageDirs = []) {
|
|
245
|
+
const storage = await resolveWorkspaceStorage(workspaceRaw, storageDirRaw);
|
|
246
|
+
const { workspace } = storage;
|
|
65
247
|
let tempDir;
|
|
66
248
|
const tempDirectoryRaw = platformTempDirectory();
|
|
67
249
|
try {
|
|
@@ -70,7 +252,18 @@ export async function createPathPolicy(workspaceRaw, allowedDirs, outputDirRaw)
|
|
|
70
252
|
catch (error) {
|
|
71
253
|
throw new VisionToolkitError('path', `platform temporary directory is not accessible: ${tempDirectoryRaw}`, { cause: error });
|
|
72
254
|
}
|
|
73
|
-
const roots = [workspace, tempDir];
|
|
255
|
+
const roots = [workspace, tempDir, storage.root];
|
|
256
|
+
for (const raw of readableStorageDirs) {
|
|
257
|
+
if (raw === storageDirRaw)
|
|
258
|
+
continue;
|
|
259
|
+
try {
|
|
260
|
+
roots.push(await resolveReadableWorkspaceStorageRoot(workspace, raw));
|
|
261
|
+
}
|
|
262
|
+
catch {
|
|
263
|
+
// Historical roots are read-only compatibility fences. Missing or newly
|
|
264
|
+
// unsafe roots stay unauthorized without breaking the active runtime.
|
|
265
|
+
}
|
|
266
|
+
}
|
|
74
267
|
for (const raw of allowedDirs) {
|
|
75
268
|
const candidate = expandUserHome(raw);
|
|
76
269
|
const target = isAbsolute(candidate) ? candidate : resolve(workspace, candidate);
|
|
@@ -81,21 +274,14 @@ export async function createPathPolicy(workspaceRaw, allowedDirs, outputDirRaw)
|
|
|
81
274
|
throw new VisionToolkitError('path', `allowedDirs entry is not accessible: ${raw}`, { cause: error });
|
|
82
275
|
}
|
|
83
276
|
}
|
|
84
|
-
const
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
await mkdir(outputRaw, { recursive: true });
|
|
93
|
-
outputDir = await realpath(outputRaw);
|
|
94
|
-
}
|
|
95
|
-
catch (error) {
|
|
96
|
-
throw new VisionToolkitError('path', `output directory is not writable: ${outputRaw}`, { cause: error });
|
|
97
|
-
}
|
|
98
|
-
return { workspace, tempDir, allowedDirs: [...new Set(roots)], outputDir };
|
|
277
|
+
const outputDir = await managedDirectory(storage.root, join(storage.root, 'artifacts'), 'artifact directory');
|
|
278
|
+
return {
|
|
279
|
+
workspace,
|
|
280
|
+
tempDir,
|
|
281
|
+
allowedDirs: [...new Set(roots)],
|
|
282
|
+
storageRoot: storage.root,
|
|
283
|
+
outputDir,
|
|
284
|
+
};
|
|
99
285
|
}
|
|
100
286
|
/**
|
|
101
287
|
* Validate one input image path and return its fence-checked absolute path
|