@aalis/plugin-storage-local 0.1.0

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 ADDED
@@ -0,0 +1,21 @@
1
+ # @aalis/plugin-storage-local
2
+
3
+ 运行时插件
4
+
5
+ ## 角色
6
+
7
+ 运行时插件
8
+
9
+ ## 安装
10
+
11
+ ```bash
12
+ pnpm add @aalis/plugin-storage-local
13
+ ```
14
+
15
+ ## 使用
16
+
17
+ 参考 [docs/architecture.md](../../docs/architecture.md) 与 [docs/guide/third-party-plugin.md](../../docs/guide/third-party-plugin.md)。
18
+
19
+ ## 许可
20
+
21
+ 见仓库根目录 LICENSE。
@@ -0,0 +1,47 @@
1
+ import type { ConfigSchema, Context } from '@aalis/core';
2
+ export declare const name = "@aalis/plugin-storage-local";
3
+ export declare const displayName = "\u672C\u5730\u5B58\u50A8\u6839\uFF08\u547D\u540D + \u8DEF\u5F84\u89E3\u6790\uFF09";
4
+ export declare const subsystem = "storage";
5
+ export declare const provides: string[];
6
+ export declare const inject: {
7
+ optional: string[];
8
+ };
9
+ /**
10
+ * 这个插件不是沙箱。它做三件事:
11
+ *
12
+ * 1. 给若干本机目录起稳定的名字(roots 数组里声明,包括默认 workspace/data/tmp/
13
+ * pluginData/logs,以及用户加的任何根),让上层用 URI 表示文件,避免到处写
14
+ * 宿主机绝对路径。
15
+ * 2. 在每条 API 内对 `..` 穿越做规范化与校验,防止"workspace:/../../etc/passwd"
16
+ * 这类逻辑越界 bug。
17
+ * 3. 把所有读/写/删过一道 logger,作为统一审计点。
18
+ *
19
+ * 它无法阻止 run_python / shell 等子进程在拿到 cwd 之后访问 OS 用户可访问的任何文件——
20
+ * 这种隔离只能靠 OS 用户权限或容器层。请按这个边界来理解和配置。
21
+ *
22
+ * 关于 browsable:仅是给"文件浏览器类 UI"的 hint。当前 plugin-webui-server 的文件页
23
+ * 实际只显示其 fileRoot 配置指向的那一个根(默认 workspace),其它根的 browsable=true
24
+ * 不会让它们出现在文件页里——那些根仅供 agent/工具按 URI 寻址使用。
25
+ *
26
+ * 当 agent 需要访问"内置 5 个根之外"的目录时:
27
+ * - 推荐:在 roots 里加一条具名根(如 share / project_x),路径限定到目标目录
28
+ * - 一刀切:在 roots 里加 { name: host, path: '/' },agent 即可用 host:/绝对路径 访问
29
+ * 宿主机任何位置(高危,启动时会有 WARN 日志)
30
+ */
31
+ export declare const configSchema: ConfigSchema;
32
+ export declare const defaultConfig: {
33
+ roots: RootEntryConfig[];
34
+ };
35
+ interface RootEntryConfig {
36
+ name: string;
37
+ path: string;
38
+ label?: string;
39
+ kind?: string;
40
+ browsable?: boolean;
41
+ readable?: boolean;
42
+ writable?: boolean;
43
+ deletable?: boolean;
44
+ }
45
+ export declare function apply(ctx: Context, config: Record<string, unknown>): Promise<void>;
46
+ export {};
47
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,OAAO,EAAU,MAAM,aAAa,CAAC;AAgBjE,eAAO,MAAM,IAAI,gCAAgC,CAAC;AAClD,eAAO,MAAM,WAAW,sFAAqB,CAAC;AAC9C,eAAO,MAAM,SAAS,YAAY,CAAC;AACnC,eAAO,MAAM,QAAQ,UAAc,CAAC;AACpC,eAAO,MAAM,MAAM;;CAElB,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,eAAO,MAAM,YAAY,EAAE,YA4F1B,CAAC;AAEF,eAAO,MAAM,aAAa;WAoDnB,eAAe,EAAE;CACvB,CAAC;AAEF,UAAU,eAAe;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAycD,wBAAsB,KAAK,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAoDxF"}
package/dist/index.js ADDED
@@ -0,0 +1,686 @@
1
+ import { createReadStream, watch as fsWatch } from 'node:fs';
2
+ import { lstat, mkdir, readdir, readFile, realpath, rename, rm, stat, unlink, writeFile } from 'node:fs/promises';
3
+ import { basename, dirname, extname, isAbsolute, relative, resolve, sep } from 'node:path';
4
+ import { useDoctorService } from '@aalis/plugin-doctor-api';
5
+ import { StorageCapabilities } from '@aalis/plugin-storage-api';
6
+ export const name = '@aalis/plugin-storage-local';
7
+ export const displayName = '本地存储根(命名 + 路径解析)';
8
+ export const subsystem = 'storage';
9
+ export const provides = ['storage'];
10
+ export const inject = {
11
+ optional: ['doctor'],
12
+ };
13
+ /**
14
+ * 这个插件不是沙箱。它做三件事:
15
+ *
16
+ * 1. 给若干本机目录起稳定的名字(roots 数组里声明,包括默认 workspace/data/tmp/
17
+ * pluginData/logs,以及用户加的任何根),让上层用 URI 表示文件,避免到处写
18
+ * 宿主机绝对路径。
19
+ * 2. 在每条 API 内对 `..` 穿越做规范化与校验,防止"workspace:/../../etc/passwd"
20
+ * 这类逻辑越界 bug。
21
+ * 3. 把所有读/写/删过一道 logger,作为统一审计点。
22
+ *
23
+ * 它无法阻止 run_python / shell 等子进程在拿到 cwd 之后访问 OS 用户可访问的任何文件——
24
+ * 这种隔离只能靠 OS 用户权限或容器层。请按这个边界来理解和配置。
25
+ *
26
+ * 关于 browsable:仅是给"文件浏览器类 UI"的 hint。当前 plugin-webui-server 的文件页
27
+ * 实际只显示其 fileRoot 配置指向的那一个根(默认 workspace),其它根的 browsable=true
28
+ * 不会让它们出现在文件页里——那些根仅供 agent/工具按 URI 寻址使用。
29
+ *
30
+ * 当 agent 需要访问"内置 5 个根之外"的目录时:
31
+ * - 推荐:在 roots 里加一条具名根(如 share / project_x),路径限定到目标目录
32
+ * - 一刀切:在 roots 里加 { name: host, path: '/' },agent 即可用 host:/绝对路径 访问
33
+ * 宿主机任何位置(高危,启动时会有 WARN 日志)
34
+ */
35
+ export const configSchema = {
36
+ roots: {
37
+ type: 'array',
38
+ label: '存储根目录',
39
+ description: '所有可用根都在这里声明(包括 workspace/data/tmp 等内置根)。' +
40
+ '直接编辑这个数组:删除不要的、修改 path、加自定义根、加 host:/ 直通根。' +
41
+ 'browsable 是给 WebUI 等浏览器类组件的 hint(注意:当前 WebUI 文件页固定显示 fileRoot 配置指向的那一个根,' +
42
+ '其它根仅作为工具/agent 寻址使用)。',
43
+ default: [
44
+ {
45
+ name: 'workspace',
46
+ path: 'workspace',
47
+ label: 'Workspace',
48
+ kind: 'workspace',
49
+ browsable: true,
50
+ readable: true,
51
+ writable: true,
52
+ deletable: true,
53
+ },
54
+ {
55
+ name: 'data',
56
+ path: 'data',
57
+ label: 'Data',
58
+ kind: 'data',
59
+ browsable: false,
60
+ readable: true,
61
+ writable: true,
62
+ deletable: false,
63
+ },
64
+ {
65
+ name: 'tmp',
66
+ path: 'workspace/.tmp',
67
+ label: '临时文件',
68
+ kind: 'tmp',
69
+ browsable: false,
70
+ readable: true,
71
+ writable: true,
72
+ deletable: true,
73
+ },
74
+ {
75
+ name: 'pluginData',
76
+ path: 'data/plugins',
77
+ label: '插件数据',
78
+ kind: 'pluginData',
79
+ browsable: false,
80
+ readable: true,
81
+ writable: true,
82
+ deletable: true,
83
+ },
84
+ {
85
+ name: 'logs',
86
+ path: 'data',
87
+ label: '日志',
88
+ kind: 'logs',
89
+ browsable: false,
90
+ readable: true,
91
+ writable: false,
92
+ deletable: false,
93
+ },
94
+ // 高危直通:取消注释或改 enabled 字段无意义——存在即注册。如需 host:/ 直通根,把下行加进 roots:
95
+ // { name: 'host', path: '/', label: '宿主机根', kind: 'host', browsable: false, readable: true, writable: false, deletable: false },
96
+ ],
97
+ items: {
98
+ name: {
99
+ type: 'string',
100
+ label: '根名 (URI scheme)',
101
+ description: '只允许字母/数字/下划线/连字符,且需以字母开头;如 workspace、share',
102
+ },
103
+ path: {
104
+ type: 'string',
105
+ label: '本机路径',
106
+ description: '可绝对,亦可相对项目根;不存在时自动创建。指向 / 即注册宿主机直通根(高危)。',
107
+ },
108
+ label: { type: 'string', label: '展示名称', default: '' },
109
+ kind: {
110
+ type: 'string',
111
+ label: '类型标签',
112
+ default: 'custom',
113
+ description: '语义提示:workspace / data / tmp / pluginData / logs / custom / external / shared / host',
114
+ },
115
+ browsable: {
116
+ type: 'boolean',
117
+ label: 'WebUI 浏览器可见 (hint)',
118
+ default: false,
119
+ description: 'hint:当前实现下仅当 webui-server.fileRoot 指向本根时此开关才生效',
120
+ },
121
+ readable: { type: 'boolean', label: '允许读', default: true },
122
+ writable: { type: 'boolean', label: '允许写', default: false },
123
+ deletable: { type: 'boolean', label: '允许删除', default: false },
124
+ },
125
+ },
126
+ };
127
+ export const defaultConfig = {
128
+ roots: [
129
+ {
130
+ name: 'workspace',
131
+ path: 'workspace',
132
+ label: 'Workspace',
133
+ kind: 'workspace',
134
+ browsable: true,
135
+ readable: true,
136
+ writable: true,
137
+ deletable: true,
138
+ },
139
+ {
140
+ name: 'data',
141
+ path: 'data',
142
+ label: 'Data',
143
+ kind: 'data',
144
+ browsable: false,
145
+ readable: true,
146
+ writable: true,
147
+ deletable: false,
148
+ },
149
+ {
150
+ name: 'tmp',
151
+ path: 'workspace/.tmp',
152
+ label: '临时文件',
153
+ kind: 'tmp',
154
+ browsable: false,
155
+ readable: true,
156
+ writable: true,
157
+ deletable: true,
158
+ },
159
+ {
160
+ name: 'pluginData',
161
+ path: 'data/plugins',
162
+ label: '插件数据',
163
+ kind: 'pluginData',
164
+ browsable: false,
165
+ readable: true,
166
+ writable: true,
167
+ deletable: true,
168
+ },
169
+ {
170
+ name: 'logs',
171
+ path: 'data',
172
+ label: '日志',
173
+ kind: 'logs',
174
+ browsable: false,
175
+ readable: true,
176
+ writable: false,
177
+ deletable: false,
178
+ },
179
+ ],
180
+ };
181
+ function isInside(parent, child) {
182
+ const rel = relative(parent, child);
183
+ return rel === '' || (!!rel && !rel.startsWith('..') && !isAbsolute(rel));
184
+ }
185
+ function normalizeRelPath(relPath) {
186
+ return relPath.replace(/^\/+/, '');
187
+ }
188
+ function toUri(root, relPath) {
189
+ const normalized = normalizeRelPath(relPath).replace(/\\/g, '/');
190
+ return `${root}:/${normalized}`;
191
+ }
192
+ function parseUri(uri) {
193
+ const idx = uri.indexOf(':/');
194
+ if (idx <= 0)
195
+ throw new Error(`存储 URI 不合法: ${uri}`);
196
+ const root = uri.slice(0, idx);
197
+ const relPath = normalizeRelPath(uri.slice(idx + 2));
198
+ return { root, relPath };
199
+ }
200
+ /**
201
+ * Per-root 存储服务:每个 root 一个实例 + 一个 ServiceContainer entry。
202
+ *
203
+ * 与 service-granularity 整体方向对齐:每个 entry 暴露的 capabilities 反映该 root 的
204
+ * 真实权限(readable/writable/deletable),消费者用 `ctx.getAllServices('storage', [cap])`
205
+ * 即可静态过滤;按 URI 调度交给 `createStorageGateway(ctx)` helper。
206
+ *
207
+ * 历史上 LocalStorageService 是单实例 + 内部 root 表,依赖 plugin-storage-router 做
208
+ * URI→root 分发。删除 router 后改为这种自包含设计,单文件即可理解整条数据流。
209
+ */
210
+ class ScopedStorageService {
211
+ root;
212
+ logger;
213
+ ctx;
214
+ constructor(root, logger, ctx) {
215
+ this.root = root;
216
+ this.logger = logger;
217
+ this.ctx = ctx;
218
+ }
219
+ /**
220
+ * 读路径 debug 日志去重:同一 key 在 LOG_DEDUP_MS 内只打一次。
221
+ *
222
+ * 背景:checkpoint manifest / file-reader meta / skills 目录在单次回合里会被反复读 list/read/stat,
223
+ * 之前 debug 层级每次都打一行,单次启动加载就能产生数百行噪声。
224
+ * 这里用 LRU + 时间窗口去重,保留首次/边界事件,过滤密集重复。
225
+ * write/delete/download 保持原样(频次低 + 有审计价值)。
226
+ */
227
+ recentLogAt = new Map();
228
+ static LOG_DEDUP_MS = 1000;
229
+ static LOG_DEDUP_MAX = 512;
230
+ debugSampled(key, msg) {
231
+ const now = Date.now();
232
+ const last = this.recentLogAt.get(key);
233
+ if (last !== undefined && now - last < ScopedStorageService.LOG_DEDUP_MS)
234
+ return;
235
+ // LRU:超出上限时清理已过期的条目
236
+ if (this.recentLogAt.size >= ScopedStorageService.LOG_DEDUP_MAX) {
237
+ const cutoff = now - ScopedStorageService.LOG_DEDUP_MS;
238
+ for (const [k, v] of this.recentLogAt) {
239
+ if (v < cutoff)
240
+ this.recentLogAt.delete(k);
241
+ }
242
+ }
243
+ this.recentLogAt.set(key, now);
244
+ this.logger.debug(msg);
245
+ }
246
+ /** 懒解析 checkpoint 服务;仅当回合活跃时调用 beforeMutate */
247
+ async snapshot(uri, op, abs) {
248
+ const cp = this.ctx.getService('checkpoint');
249
+ if (!cp?.isActive())
250
+ return;
251
+ await cp.beforeMutate(uri, op, async () => {
252
+ try {
253
+ const s = await stat(abs);
254
+ if (s.isDirectory())
255
+ return null;
256
+ return { data: await readFile(abs), size: s.size };
257
+ }
258
+ catch {
259
+ return null;
260
+ }
261
+ });
262
+ }
263
+ listRoots() {
264
+ return [this.publicRoot()];
265
+ }
266
+ async list(uri) {
267
+ const relPath = this.parseSelfUri(uri);
268
+ this.requirePermission('readable');
269
+ const abs = await this.resolveExisting(relPath);
270
+ const s = await stat(abs);
271
+ if (!s.isDirectory())
272
+ throw new Error('不是目录');
273
+ const dispUri = toUri(this.root.name, relPath);
274
+ this.debugSampled(`list:${dispUri}`, `storage.list ${dispUri}`);
275
+ const entries = await readdir(abs);
276
+ const result = [];
277
+ for (const name of entries) {
278
+ const childRel = normalizeRelPath(`${relPath}/${name}`);
279
+ try {
280
+ const childAbs = await this.resolveExisting(childRel);
281
+ const childStat = await stat(childAbs);
282
+ result.push({
283
+ name,
284
+ path: childRel,
285
+ uri: toUri(this.root.name, childRel),
286
+ isDirectory: childStat.isDirectory(),
287
+ size: childStat.isDirectory() ? 0 : childStat.size,
288
+ mtime: childStat.mtime.toISOString(),
289
+ ext: childStat.isDirectory() ? '' : extname(name).toLowerCase(),
290
+ });
291
+ }
292
+ catch {
293
+ // 跳过指向根目录外或无法读取的符号链接/条目。
294
+ }
295
+ }
296
+ result.sort((a, b) => {
297
+ if (a.isDirectory !== b.isDirectory)
298
+ return a.isDirectory ? -1 : 1;
299
+ return a.name.localeCompare(b.name);
300
+ });
301
+ return {
302
+ root: this.publicRoot(),
303
+ path: normalizeRelPath(relPath),
304
+ entries: result,
305
+ };
306
+ }
307
+ async stat(uri) {
308
+ const relPath = this.parseSelfUri(uri);
309
+ this.requirePermission('readable');
310
+ const abs = await this.resolveExisting(relPath);
311
+ const dispUri = toUri(this.root.name, relPath);
312
+ this.debugSampled(`stat:${dispUri}`, `storage.stat ${dispUri}`);
313
+ return this.statFromAbs(abs, relPath);
314
+ }
315
+ async readFile(uri, encoding) {
316
+ const relPath = this.parseSelfUri(uri);
317
+ this.requirePermission('readable');
318
+ const abs = await this.resolveExisting(relPath);
319
+ const s = await stat(abs);
320
+ if (s.isDirectory())
321
+ throw new Error('不能读取目录');
322
+ const dispUri = toUri(this.root.name, relPath);
323
+ this.debugSampled(`read:${dispUri}`, `storage.read ${dispUri} size=${s.size}`);
324
+ return encoding ? readFile(abs, encoding) : readFile(abs);
325
+ }
326
+ async createReadStream(uri) {
327
+ const relPath = this.parseSelfUri(uri);
328
+ this.requirePermission('readable');
329
+ const abs = await this.resolveExisting(relPath);
330
+ const fileStat = await this.statFromAbs(abs, relPath);
331
+ if (fileStat.isDirectory)
332
+ throw new Error('不能下载目录');
333
+ this.logger.info(`storage.download ${toUri(this.root.name, relPath)} size=${fileStat.size}`);
334
+ return { stream: createReadStream(abs), stat: fileStat };
335
+ }
336
+ async writeFile(uri, data) {
337
+ const relPath = this.parseSelfUri(uri);
338
+ this.requirePermission('writable');
339
+ if (!relPath)
340
+ throw new Error('不能覆盖根目录');
341
+ const abs = await this.resolveForWrite(relPath);
342
+ await this.snapshot(toUri(this.root.name, relPath), 'write', abs);
343
+ await mkdir(dirname(abs), { recursive: true });
344
+ await writeFile(abs, data);
345
+ this.logger.info(`storage.write ${toUri(this.root.name, relPath)} size=${Buffer.byteLength(data)}`);
346
+ }
347
+ async rename(uri, newName) {
348
+ if (!newName || newName.includes('/') || newName.includes('\\') || newName === '.' || newName === '..') {
349
+ throw new Error('文件名不合法');
350
+ }
351
+ const relPath = this.parseSelfUri(uri);
352
+ this.requirePermission('writable');
353
+ if (!relPath)
354
+ throw new Error('不能重命名根目录');
355
+ const abs = await this.resolveExisting(relPath);
356
+ const newRel = normalizeRelPath(`${dirname(relPath) === '.' ? '' : dirname(relPath)}/${newName}`);
357
+ const target = await this.resolveForWrite(newRel);
358
+ try {
359
+ await lstat(target);
360
+ throw new Error('目标名称已存在');
361
+ }
362
+ catch (err) {
363
+ if (err.code !== 'ENOENT')
364
+ throw err;
365
+ }
366
+ await this.snapshot(toUri(this.root.name, relPath), 'rename', abs);
367
+ await rename(abs, target);
368
+ this.logger.info(`storage.rename ${toUri(this.root.name, relPath)} -> ${toUri(this.root.name, newRel)}`);
369
+ return toUri(this.root.name, newRel);
370
+ }
371
+ async delete(uri) {
372
+ const relPath = this.parseSelfUri(uri);
373
+ this.requirePermission('deletable');
374
+ if (!relPath)
375
+ throw new Error('不能删除根目录');
376
+ const abs = await this.resolveExisting(relPath);
377
+ await this.snapshot(toUri(this.root.name, relPath), 'delete', abs);
378
+ await rm(abs, { recursive: true, force: false });
379
+ this.logger.warn(`storage.delete ${toUri(this.root.name, relPath)}`);
380
+ }
381
+ async resolveLocalPath(uri, access = 'read') {
382
+ const relPath = this.parseSelfUri(uri);
383
+ const permission = access === 'delete' ? 'deletable' : access === 'write' ? 'writable' : 'readable';
384
+ this.requirePermission(permission);
385
+ const abs = access === 'write' ? await this.resolveForWrite(relPath) : await this.resolveExisting(relPath);
386
+ this.logger.debug(`storage.resolveLocalPath ${toUri(this.root.name, relPath)} access=${access}`);
387
+ return abs;
388
+ }
389
+ /**
390
+ * 监听某个 URI 下的变化。基于 fs.watch + 50ms 去抖。
391
+ *
392
+ * - 目录 URI:尝试 recursive 监听整个子树;若平台不支持 recursive,降级为只监听该目录顶层(warn)。
393
+ * - 文件 URI:监听该文件本身。
394
+ * - 事件路径会归一化为相对该 URI 的 storage URI 路径并去抖(同一相对路径 50ms 内只触发一次)。
395
+ */
396
+ watch(uri, listener) {
397
+ const relPath = this.parseSelfUri(uri);
398
+ this.requirePermission('readable');
399
+ const absBase = resolve(this.root.realPath, normalizeRelPath(relPath));
400
+ if (!isInside(this.root.realPath, absBase) && absBase !== this.root.realPath) {
401
+ throw new Error('路径不合法');
402
+ }
403
+ const debounceMs = 50;
404
+ const pending = new Map();
405
+ let closed = false;
406
+ const emit = (eventRelToRoot) => {
407
+ if (closed)
408
+ return;
409
+ const norm = normalizeRelPath(eventRelToRoot).replace(/\\/g, '/');
410
+ const existing = pending.get(norm);
411
+ if (existing)
412
+ clearTimeout(existing);
413
+ const timer = setTimeout(() => {
414
+ pending.delete(norm);
415
+ if (closed)
416
+ return;
417
+ const event = {
418
+ type: 'change',
419
+ uri: toUri(this.root.name, norm),
420
+ path: norm,
421
+ };
422
+ try {
423
+ listener(event);
424
+ }
425
+ catch (err) {
426
+ this.logger.warn(`storage.watch listener 抛错 ${event.uri}: ${err}`);
427
+ }
428
+ }, debounceMs);
429
+ pending.set(norm, timer);
430
+ };
431
+ let watcher;
432
+ const baseRelToRoot = normalizeRelPath(relPath);
433
+ const handle = (filename) => {
434
+ if (!filename) {
435
+ emit(baseRelToRoot);
436
+ return;
437
+ }
438
+ const name = typeof filename === 'string' ? filename : filename.toString('utf8');
439
+ // fs.watch 给的 filename 是相对被监听路径的相对路径
440
+ const rel = baseRelToRoot ? `${baseRelToRoot}/${name.split(sep).join('/')}` : name.split(sep).join('/');
441
+ emit(rel);
442
+ };
443
+ try {
444
+ watcher = fsWatch(absBase, { recursive: true }, (_event, filename) => handle(filename));
445
+ this.logger.debug(`storage.watch ${toUri(this.root.name, baseRelToRoot)} (recursive)`);
446
+ }
447
+ catch (err) {
448
+ const code = err.code;
449
+ if (code === 'ERR_FEATURE_UNAVAILABLE_ON_PLATFORM') {
450
+ this.logger.warn(`storage.watch 当前平台不支持 recursive,仅监听顶层: ${toUri(this.root.name, baseRelToRoot)}`);
451
+ watcher = fsWatch(absBase, (_event, filename) => handle(filename));
452
+ }
453
+ else {
454
+ throw err;
455
+ }
456
+ }
457
+ watcher.on('error', e => this.logger.warn(`storage.watch 错误 ${toUri(this.root.name, baseRelToRoot)}: ${e}`));
458
+ return () => {
459
+ if (closed)
460
+ return;
461
+ closed = true;
462
+ for (const timer of pending.values())
463
+ clearTimeout(timer);
464
+ pending.clear();
465
+ try {
466
+ watcher.close();
467
+ }
468
+ catch {
469
+ // ignore
470
+ }
471
+ this.logger.debug(`storage.watch 已停止 ${toUri(this.root.name, baseRelToRoot)}`);
472
+ };
473
+ }
474
+ // ---- 内部 ----
475
+ parseSelfUri(uri) {
476
+ const { root, relPath } = parseUri(uri);
477
+ if (root !== this.root.name) {
478
+ throw new Error(`URI 根 "${root}" 不属于本 entry (${this.root.name})`);
479
+ }
480
+ return relPath;
481
+ }
482
+ requirePermission(permission) {
483
+ if (!this.root[permission]) {
484
+ throw new Error(`存储根 ${this.root.name} 不允许该操作 (${permission})`);
485
+ }
486
+ }
487
+ async resolveExisting(relPath) {
488
+ const lexical = resolve(this.root.realPath, normalizeRelPath(relPath));
489
+ if (!isInside(this.root.realPath, lexical))
490
+ throw new Error('路径不合法');
491
+ const resolved = await realpath(lexical);
492
+ if (!isInside(this.root.realPath, resolved))
493
+ throw new Error('路径不合法');
494
+ return resolved;
495
+ }
496
+ async resolveForWrite(relPath) {
497
+ const normalized = normalizeRelPath(relPath);
498
+ const lexical = resolve(this.root.realPath, normalized);
499
+ if (!isInside(this.root.realPath, lexical))
500
+ throw new Error('路径不合法');
501
+ const existingParent = await this.findExistingParent(dirname(lexical));
502
+ const parent = await realpath(existingParent);
503
+ if (!isInside(this.root.realPath, parent))
504
+ throw new Error('路径不合法');
505
+ try {
506
+ const target = await lstat(lexical);
507
+ if (target.isSymbolicLink())
508
+ throw new Error('不允许写入符号链接');
509
+ }
510
+ catch (err) {
511
+ if (err.code !== 'ENOENT')
512
+ throw err;
513
+ }
514
+ return lexical;
515
+ }
516
+ async findExistingParent(absPath) {
517
+ let current = absPath;
518
+ while (true) {
519
+ try {
520
+ const s = await lstat(current);
521
+ if (!s.isDirectory())
522
+ throw new Error('父路径不是目录');
523
+ return current;
524
+ }
525
+ catch (err) {
526
+ if (err.code !== 'ENOENT')
527
+ throw err;
528
+ const parent = dirname(current);
529
+ if (parent === current)
530
+ throw err;
531
+ current = parent;
532
+ }
533
+ }
534
+ }
535
+ async statFromAbs(abs, relPath) {
536
+ const s = await stat(abs);
537
+ const path = normalizeRelPath(relPath || relative(this.root.realPath, abs));
538
+ return {
539
+ name: basename(abs),
540
+ path,
541
+ uri: toUri(this.root.name, path),
542
+ isDirectory: s.isDirectory(),
543
+ size: s.size,
544
+ mtime: s.mtime.toISOString(),
545
+ birthtime: s.birthtime.toISOString(),
546
+ ext: s.isDirectory() ? '' : extname(abs).toLowerCase(),
547
+ };
548
+ }
549
+ publicRoot() {
550
+ const { realPath: _realPath, ...info } = this.root;
551
+ return info;
552
+ }
553
+ }
554
+ async function createRoot(name, label, kind, rootPath, options) {
555
+ const abs = resolve(process.cwd(), rootPath);
556
+ // path 已是文件系统根('/')等存在的目录时不需要创建;其它情况 mkdir -p
557
+ if (rootPath !== '/' && rootPath !== '') {
558
+ await mkdir(abs, { recursive: true });
559
+ }
560
+ return {
561
+ name,
562
+ label,
563
+ kind,
564
+ realPath: await realpath(abs),
565
+ ...options,
566
+ };
567
+ }
568
+ const ROOT_NAME_RE = /^[a-zA-Z][a-zA-Z0-9_-]*$/;
569
+ /** 从 raw config.roots 构造可用根。空/异常时回退到 defaultConfig.roots。 */
570
+ async function buildRoots(rawRoots, logger) {
571
+ let entries = Array.isArray(rawRoots) ? rawRoots.slice() : [];
572
+ if (entries.length === 0) {
573
+ logger.warn('storage roots 配置为空,将注册默认 5 个内置根(workspace/data/tmp/pluginData/logs)');
574
+ entries = defaultConfig.roots.slice();
575
+ }
576
+ const out = [];
577
+ const seen = new Set();
578
+ for (const item of entries) {
579
+ if (!item || typeof item !== 'object')
580
+ continue;
581
+ const name = String(item.name || '').trim();
582
+ const path = String(item.path ?? '').trim();
583
+ if (!name || !path) {
584
+ logger.warn(`roots 跳过无效项 (name/path 为空): ${JSON.stringify(item)}`);
585
+ continue;
586
+ }
587
+ if (!ROOT_NAME_RE.test(name)) {
588
+ logger.warn(`roots 跳过非法根名 ${name}(仅允许字母/数字/下划线/连字符,且需以字母开头)`);
589
+ continue;
590
+ }
591
+ if (seen.has(name)) {
592
+ logger.warn(`roots 跳过重复根名 ${name}`);
593
+ continue;
594
+ }
595
+ seen.add(name);
596
+ try {
597
+ const root = await createRoot(name, item.label || name, item.kind || 'custom', path, {
598
+ browsable: item.browsable === true,
599
+ readable: item.readable !== false,
600
+ writable: item.writable === true,
601
+ deletable: item.deletable === true,
602
+ });
603
+ const isHostScope = root.realPath === '/' || root.realPath.length <= 3;
604
+ const log = isHostScope ? logger.warn.bind(logger) : logger.info.bind(logger);
605
+ log(`root ${name}:/ -> ${root.realPath}` +
606
+ ` (browsable=${root.browsable} read=${root.readable} write=${root.writable} delete=${root.deletable})` +
607
+ (isHostScope ? ' ⚠ 该根接近/等于文件系统根,agent 通过此根可访问宿主机大量文件' : ''));
608
+ out.push(root);
609
+ }
610
+ catch (err) {
611
+ logger.warn(`root 注册失败 ${name}: ${err instanceof Error ? err.message : String(err)}`);
612
+ }
613
+ }
614
+ return out;
615
+ }
616
+ export async function apply(ctx, config) {
617
+ const logger = ctx.logger.child('storage');
618
+ const roots = await buildRoots(config.roots, logger);
619
+ if (roots.length === 0)
620
+ throw new Error('plugin-storage-local: 没有任何可用根,请检查 roots 配置');
621
+ // service-granularity:每个 root 单独注册一个 entry。
622
+ // - capabilities 反映该 root 的真实权限(不撒谎、不堆砌全集);
623
+ // - entryId = `${ctx.id}/${root.name}`,便于在 ServiceContainer 中按根定位、避免跨实例同名冲突;
624
+ // - URI 路由由 createStorageGateway(ctx) helper 在调用方完成,不再有 facade。
625
+ for (const root of roots) {
626
+ const caps = [];
627
+ if (root.readable)
628
+ caps.push(StorageCapabilities.List, StorageCapabilities.Read, StorageCapabilities.LocalPath, StorageCapabilities.Watch);
629
+ if (root.writable)
630
+ caps.push(StorageCapabilities.Write);
631
+ if (root.deletable)
632
+ caps.push(StorageCapabilities.Delete);
633
+ if (caps.length === 0) {
634
+ logger.warn(`root ${root.name} 没有任何权限位,跳过注册`);
635
+ continue;
636
+ }
637
+ const scoped = new ScopedStorageService(root, logger, ctx);
638
+ ctx.provide('storage', scoped, {
639
+ entryId: `${ctx.id}/${root.name}`,
640
+ capabilities: caps,
641
+ label: root.label || `本地根 ${root.name}`,
642
+ });
643
+ }
644
+ // 诊断检查项:探测每个 writable root 是否真的可写。
645
+ // 历史上 plugin-doctor 内置了硬编码的 fs.data 检查,但 data/ 仅是默认 root 之一,
646
+ // 不应由 doctor 单独「祝福」。现统一由 storage 插件按当前 roots 配置上报,能反映
647
+ // 用户自定义根(如 host:/、project_x)的真实状态。
648
+ useDoctorService(ctx).registerCheck({
649
+ id: 'storage.roots',
650
+ category: 'filesystem',
651
+ pluginName: name,
652
+ async run() {
653
+ const targets = roots.filter(r => r.writable);
654
+ if (targets.length === 0) {
655
+ return { id: 'storage.roots', category: 'filesystem', level: 'warn', message: '没有任何 writable 存储根' };
656
+ }
657
+ const results = [];
658
+ for (const root of targets) {
659
+ results.push(await probeRootWritable(root.name, root.realPath));
660
+ }
661
+ return results;
662
+ },
663
+ });
664
+ }
665
+ /** 探测某个根目录是否可写:在根下写一个临时文件并立即删除 */
666
+ async function probeRootWritable(rootName, dir) {
667
+ const id = `storage.roots.${rootName}`;
668
+ try {
669
+ await mkdir(dir, { recursive: true });
670
+ const probe = resolve(dir, `.doctor-probe-${process.pid}-${Date.now()}`);
671
+ await writeFile(probe, 'ok');
672
+ await stat(probe);
673
+ await unlink(probe);
674
+ return { id, category: 'filesystem', level: 'ok', message: `根 ${rootName} (${dir}) 可写` };
675
+ }
676
+ catch (err) {
677
+ return {
678
+ id,
679
+ category: 'filesystem',
680
+ level: 'error',
681
+ message: `根 ${rootName} (${dir}) 不可写`,
682
+ detail: err instanceof Error ? err.message : String(err),
683
+ };
684
+ }
685
+ }
686
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,39 @@
1
+ {
2
+ "name": "@aalis/plugin-storage-local",
3
+ "version": "0.1.0",
4
+ "type": "module",
5
+ "keywords": [
6
+ "aalis-plugin"
7
+ ],
8
+ "main": "dist/index.js",
9
+ "types": "dist/index.d.ts",
10
+ "files": [
11
+ "dist"
12
+ ],
13
+ "dependencies": {
14
+ "@aalis/plugin-doctor-api": "^0.1.0",
15
+ "@aalis/plugin-storage-api": "^0.1.0"
16
+ },
17
+ "devDependencies": {
18
+ "@types/node": "^22.0.0",
19
+ "typescript": "^5.7.0",
20
+ "@aalis/core": "0.1.0"
21
+ },
22
+ "peerDependencies": {
23
+ "@aalis/core": "^0.1.0"
24
+ },
25
+ "aalis": {
26
+ "service": {
27
+ "optional": [
28
+ "doctor"
29
+ ],
30
+ "provides": [
31
+ "storage"
32
+ ]
33
+ }
34
+ },
35
+ "scripts": {
36
+ "build": "tsc",
37
+ "dev": "tsc --watch"
38
+ }
39
+ }