@scotthuang/engram 0.4.8 → 0.4.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.
@@ -0,0 +1,118 @@
1
+ /**
2
+ * Image Store - 图片本地持久化存储
3
+ *
4
+ * 将图片从临时路径(如微信下发的 /tmp 目录)copy 到持久化目录,
5
+ * 按日期归档,配套生成元数据 JSON 文件,支持 SHA-256 去重。
6
+ *
7
+ * 存储结构:
8
+ * memory-engram/images/YYYY-MM/DD/
9
+ * ├── YYYYMMDD_HHmmss_{hash6}.jpg ← 原图
10
+ * └── YYYYMMDD_HHmmss_{hash6}.json ← 元数据
11
+ */
12
+ export interface ImageMetadata {
13
+ /** 原始文件路径 */
14
+ originalPath: string;
15
+ /** 持久化后的绝对路径 */
16
+ storedPath: string;
17
+ /** 相对于 memory-engram/ 的路径(用于记忆引用) */
18
+ relativePath: string;
19
+ /** 存储时间戳(毫秒) */
20
+ timestamp: number;
21
+ /** 来源渠道 */
22
+ source: string;
23
+ /** 图片文件 SHA-256 hash */
24
+ imageHash: string;
25
+ /** 文件大小(字节) */
26
+ fileSize: number;
27
+ /** 图片描述(由 3.1.2 图片理解填写) */
28
+ description: string;
29
+ /** 识别到的实体(由 3.1.2 图片理解填写) */
30
+ entities: string[];
31
+ /** 人脸识别结果(由 3.2 人脸识别填写) */
32
+ faces: Array<{
33
+ personId: string | null;
34
+ name: string;
35
+ confidence: number;
36
+ bbox: number[];
37
+ }>;
38
+ }
39
+ export interface ImageStoreResult {
40
+ /** 持久化后的绝对路径 */
41
+ storedPath: string;
42
+ /** 相对于 memory-engram/ 的路径(用于记忆引用) */
43
+ relativePath: string;
44
+ /** 完整元数据 */
45
+ metadata: ImageMetadata;
46
+ /** 是否为重复图片(已存在相同 hash) */
47
+ isDuplicate: boolean;
48
+ }
49
+ /**
50
+ * 图片持久化存储管理器
51
+ */
52
+ export declare class ImageStore {
53
+ private workspaceDir;
54
+ /** hash → relativePath 的去重索引 */
55
+ private hashIndex;
56
+ constructor(workspaceDir: string);
57
+ /** memory-engram 根目录 */
58
+ private get engramDir();
59
+ /** images 根目录 */
60
+ private get imagesDir();
61
+ /** hash 索引文件绝对路径 */
62
+ private get hashIndexPath();
63
+ /**
64
+ * 计算文件的 SHA-256 hash
65
+ */
66
+ private computeFileHash;
67
+ /**
68
+ * 加载 hash 去重索引
69
+ */
70
+ private loadHashIndex;
71
+ /**
72
+ * 保存 hash 去重索引
73
+ */
74
+ private saveHashIndex;
75
+ /**
76
+ * 生成本地时间相关的路径组件
77
+ */
78
+ private getTimeParts;
79
+ /**
80
+ * 存储图片到持久化目录
81
+ *
82
+ * @param originalPath 图片的原始路径(如 /tmp/wechat_xxx.jpg)
83
+ * @param options.source 来源渠道(默认 "unknown")
84
+ * @returns 存储结果,包含新路径和元数据
85
+ * @throws 如果文件不存在或扩展名不支持
86
+ */
87
+ storeImage(originalPath: string, options?: {
88
+ source?: string;
89
+ }): Promise<ImageStoreResult>;
90
+ /**
91
+ * 更新图片元数据(用于 3.1.2 填写 description/entities,3.2 填写 faces)
92
+ *
93
+ * @param relativePath 相对于 memory-engram/ 的图片路径
94
+ * @param updates 要更新的字段
95
+ */
96
+ updateMetadata(relativePath: string, updates: Partial<Pick<ImageMetadata, "description" | "entities" | "faces">>): Promise<ImageMetadata | null>;
97
+ /**
98
+ * 根据 hash 查找已存储的图片
99
+ */
100
+ findByHash(imageHash: string): Promise<ImageMetadata | null>;
101
+ /**
102
+ * 列出某天的所有图片
103
+ *
104
+ * @param date 日期字符串 YYYY-MM-DD
105
+ */
106
+ listByDate(date: string): Promise<ImageMetadata[]>;
107
+ /**
108
+ * 获取图片存储统计
109
+ */
110
+ getStats(): Promise<{
111
+ totalImages: number;
112
+ totalSizeBytes: number;
113
+ }>;
114
+ /**
115
+ * 构建元数据对象
116
+ */
117
+ private buildMetadata;
118
+ }
@@ -0,0 +1,289 @@
1
+ /**
2
+ * Image Store - 图片本地持久化存储
3
+ *
4
+ * 将图片从临时路径(如微信下发的 /tmp 目录)copy 到持久化目录,
5
+ * 按日期归档,配套生成元数据 JSON 文件,支持 SHA-256 去重。
6
+ *
7
+ * 存储结构:
8
+ * memory-engram/images/YYYY-MM/DD/
9
+ * ├── YYYYMMDD_HHmmss_{hash6}.jpg ← 原图
10
+ * └── YYYYMMDD_HHmmss_{hash6}.json ← 元数据
11
+ */
12
+ import { promises as fs } from "node:fs";
13
+ import { join, extname } from "node:path";
14
+ import { createHash } from "node:crypto";
15
+ import { createReadStream } from "node:fs";
16
+ import { logger } from "./logger.js";
17
+ // ---- 支持的图片扩展名 ----
18
+ const SUPPORTED_EXTENSIONS = new Set([
19
+ ".jpg", ".jpeg", ".png", ".gif", ".webp", ".bmp", ".tiff", ".tif", ".heic", ".heif", ".svg",
20
+ ]);
21
+ // ---- hash 索引文件路径 ----
22
+ const HASH_INDEX_FILE = "image-hash-index.json";
23
+ /**
24
+ * 图片持久化存储管理器
25
+ */
26
+ export class ImageStore {
27
+ workspaceDir;
28
+ /** hash → relativePath 的去重索引 */
29
+ hashIndex = null;
30
+ constructor(workspaceDir) {
31
+ this.workspaceDir = workspaceDir;
32
+ }
33
+ /** memory-engram 根目录 */
34
+ get engramDir() {
35
+ return join(this.workspaceDir, "memory-engram");
36
+ }
37
+ /** images 根目录 */
38
+ get imagesDir() {
39
+ return join(this.engramDir, "images");
40
+ }
41
+ /** hash 索引文件绝对路径 */
42
+ get hashIndexPath() {
43
+ return join(this.imagesDir, HASH_INDEX_FILE);
44
+ }
45
+ /**
46
+ * 计算文件的 SHA-256 hash
47
+ */
48
+ async computeFileHash(filePath) {
49
+ return new Promise((resolve, reject) => {
50
+ const hash = createHash("sha256");
51
+ const stream = createReadStream(filePath);
52
+ stream.on("data", (chunk) => hash.update(chunk));
53
+ stream.on("end", () => resolve(hash.digest("hex")));
54
+ stream.on("error", reject);
55
+ });
56
+ }
57
+ /**
58
+ * 加载 hash 去重索引
59
+ */
60
+ async loadHashIndex() {
61
+ if (this.hashIndex !== null)
62
+ return this.hashIndex;
63
+ try {
64
+ const raw = await fs.readFile(this.hashIndexPath, "utf-8");
65
+ this.hashIndex = JSON.parse(raw);
66
+ return this.hashIndex;
67
+ }
68
+ catch {
69
+ this.hashIndex = {};
70
+ return this.hashIndex;
71
+ }
72
+ }
73
+ /**
74
+ * 保存 hash 去重索引
75
+ */
76
+ async saveHashIndex() {
77
+ if (!this.hashIndex)
78
+ return;
79
+ await fs.mkdir(this.imagesDir, { recursive: true });
80
+ await fs.writeFile(this.hashIndexPath, JSON.stringify(this.hashIndex, null, 2), "utf-8");
81
+ }
82
+ /**
83
+ * 生成本地时间相关的路径组件
84
+ */
85
+ getTimeParts(now) {
86
+ const y = now.getFullYear();
87
+ const M = String(now.getMonth() + 1).padStart(2, "0");
88
+ const d = String(now.getDate()).padStart(2, "0");
89
+ const h = String(now.getHours()).padStart(2, "0");
90
+ const m = String(now.getMinutes()).padStart(2, "0");
91
+ const s = String(now.getSeconds()).padStart(2, "0");
92
+ return {
93
+ yearMonth: `${y}-${M}`,
94
+ day: d,
95
+ filePrefix: `${y}${M}${d}_${h}${m}${s}`,
96
+ };
97
+ }
98
+ /**
99
+ * 存储图片到持久化目录
100
+ *
101
+ * @param originalPath 图片的原始路径(如 /tmp/wechat_xxx.jpg)
102
+ * @param options.source 来源渠道(默认 "unknown")
103
+ * @returns 存储结果,包含新路径和元数据
104
+ * @throws 如果文件不存在或扩展名不支持
105
+ */
106
+ async storeImage(originalPath, options) {
107
+ const source = options?.source || "unknown";
108
+ logger.info(`[engram:image-store] storeImage called: ${originalPath} (source=${source})`);
109
+ // 1. 校验文件存在
110
+ let stat;
111
+ try {
112
+ stat = await fs.stat(originalPath);
113
+ }
114
+ catch {
115
+ throw new Error(`Image file not found: ${originalPath}`);
116
+ }
117
+ if (!stat.isFile()) {
118
+ throw new Error(`Not a file: ${originalPath}`);
119
+ }
120
+ // 2. 校验扩展名
121
+ const ext = extname(originalPath).toLowerCase();
122
+ if (!SUPPORTED_EXTENSIONS.has(ext)) {
123
+ throw new Error(`Unsupported image format: ${ext} (supported: ${[...SUPPORTED_EXTENSIONS].join(", ")})`);
124
+ }
125
+ // 3. 计算文件 hash
126
+ const imageHash = await this.computeFileHash(originalPath);
127
+ const hash6 = imageHash.slice(0, 6);
128
+ logger.info(`[engram:image-store] File hash: ${imageHash.slice(0, 16)}... size=${stat.size}`);
129
+ // 4. 去重检查
130
+ const hashIndex = await this.loadHashIndex();
131
+ if (hashIndex[imageHash]) {
132
+ const existingRelPath = hashIndex[imageHash];
133
+ const existingAbsPath = join(this.engramDir, existingRelPath);
134
+ // 确认文件还存在(可能被手动删除了)
135
+ try {
136
+ await fs.stat(existingAbsPath);
137
+ // 读取已有元数据
138
+ const metaPath = existingAbsPath.replace(/\.[^.]+$/, ".json");
139
+ let metadata;
140
+ try {
141
+ const raw = await fs.readFile(metaPath, "utf-8");
142
+ metadata = JSON.parse(raw);
143
+ }
144
+ catch {
145
+ // 元数据丢失,重建一个基本的
146
+ metadata = this.buildMetadata(originalPath, existingAbsPath, existingRelPath, imageHash, stat.size, source);
147
+ }
148
+ logger.info(`[engram:image-store] Duplicate detected, existing: ${existingRelPath}`);
149
+ return {
150
+ storedPath: existingAbsPath,
151
+ relativePath: existingRelPath,
152
+ metadata,
153
+ isDuplicate: true,
154
+ };
155
+ }
156
+ catch {
157
+ // 文件已被删除,清除索引,继续存储
158
+ logger.info(`[engram:image-store] Hash index stale (file deleted), re-storing`);
159
+ delete hashIndex[imageHash];
160
+ }
161
+ }
162
+ // 5. 构建目标路径
163
+ const now = new Date();
164
+ const { yearMonth, day, filePrefix } = this.getTimeParts(now);
165
+ const destDir = join(this.imagesDir, yearMonth, day);
166
+ await fs.mkdir(destDir, { recursive: true });
167
+ const fileName = `${filePrefix}_${hash6}${ext}`;
168
+ const destPath = join(destDir, fileName);
169
+ const relativePath = `images/${yearMonth}/${day}/${fileName}`;
170
+ // 6. Copy 文件
171
+ await fs.copyFile(originalPath, destPath);
172
+ logger.info(`[engram:image-store] Copied: ${originalPath} → ${destPath}`);
173
+ // 7. 生成元数据
174
+ const metadata = this.buildMetadata(originalPath, destPath, relativePath, imageHash, stat.size, source);
175
+ const metaPath = join(destDir, `${filePrefix}_${hash6}.json`);
176
+ await fs.writeFile(metaPath, JSON.stringify(metadata, null, 2), "utf-8");
177
+ logger.info(`[engram:image-store] Metadata saved: ${metaPath}`);
178
+ // 8. 更新 hash 索引
179
+ hashIndex[imageHash] = relativePath;
180
+ await this.saveHashIndex();
181
+ return {
182
+ storedPath: destPath,
183
+ relativePath,
184
+ metadata,
185
+ isDuplicate: false,
186
+ };
187
+ }
188
+ /**
189
+ * 更新图片元数据(用于 3.1.2 填写 description/entities,3.2 填写 faces)
190
+ *
191
+ * @param relativePath 相对于 memory-engram/ 的图片路径
192
+ * @param updates 要更新的字段
193
+ */
194
+ async updateMetadata(relativePath, updates) {
195
+ const metaPath = join(this.engramDir, relativePath.replace(/\.[^.]+$/, ".json"));
196
+ try {
197
+ const raw = await fs.readFile(metaPath, "utf-8");
198
+ const metadata = JSON.parse(raw);
199
+ if (updates.description !== undefined)
200
+ metadata.description = updates.description;
201
+ if (updates.entities !== undefined)
202
+ metadata.entities = updates.entities;
203
+ if (updates.faces !== undefined)
204
+ metadata.faces = updates.faces;
205
+ await fs.writeFile(metaPath, JSON.stringify(metadata, null, 2), "utf-8");
206
+ logger.info(`[engram:image-store] Metadata updated: ${metaPath}`);
207
+ return metadata;
208
+ }
209
+ catch (err) {
210
+ logger.error(`[engram:image-store] Failed to update metadata for ${relativePath}: ${err}`);
211
+ return null;
212
+ }
213
+ }
214
+ /**
215
+ * 根据 hash 查找已存储的图片
216
+ */
217
+ async findByHash(imageHash) {
218
+ const hashIndex = await this.loadHashIndex();
219
+ const relativePath = hashIndex[imageHash];
220
+ if (!relativePath)
221
+ return null;
222
+ const metaPath = join(this.engramDir, relativePath.replace(/\.[^.]+$/, ".json"));
223
+ try {
224
+ const raw = await fs.readFile(metaPath, "utf-8");
225
+ return JSON.parse(raw);
226
+ }
227
+ catch {
228
+ return null;
229
+ }
230
+ }
231
+ /**
232
+ * 列出某天的所有图片
233
+ *
234
+ * @param date 日期字符串 YYYY-MM-DD
235
+ */
236
+ async listByDate(date) {
237
+ const match = date.match(/^(\d{4}-\d{2})-(\d{2})$/);
238
+ if (!match)
239
+ return [];
240
+ const yearMonth = match[1];
241
+ const day = match[2];
242
+ const dayDir = join(this.imagesDir, yearMonth, day);
243
+ try {
244
+ const files = await fs.readdir(dayDir);
245
+ const jsonFiles = files.filter(f => f.endsWith(".json"));
246
+ const results = [];
247
+ for (const file of jsonFiles) {
248
+ try {
249
+ const raw = await fs.readFile(join(dayDir, file), "utf-8");
250
+ results.push(JSON.parse(raw));
251
+ }
252
+ catch {
253
+ // skip malformed
254
+ }
255
+ }
256
+ return results.sort((a, b) => a.timestamp - b.timestamp);
257
+ }
258
+ catch {
259
+ return [];
260
+ }
261
+ }
262
+ /**
263
+ * 获取图片存储统计
264
+ */
265
+ async getStats() {
266
+ const hashIndex = await this.loadHashIndex();
267
+ const totalImages = Object.keys(hashIndex).length;
268
+ // 粗略统计,不遍历文件系统
269
+ return { totalImages, totalSizeBytes: 0 };
270
+ }
271
+ /**
272
+ * 构建元数据对象
273
+ */
274
+ buildMetadata(originalPath, storedPath, relativePath, imageHash, fileSize, source) {
275
+ return {
276
+ originalPath,
277
+ storedPath,
278
+ relativePath,
279
+ timestamp: Date.now(),
280
+ source,
281
+ imageHash,
282
+ fileSize,
283
+ description: "",
284
+ entities: [],
285
+ faces: [],
286
+ };
287
+ }
288
+ }
289
+ //# sourceMappingURL=image-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"image-store.js","sourceRoot":"","sources":["../src/image-store.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@scotthuang/engram",
3
- "version": "0.4.8",
3
+ "version": "0.4.9",
4
4
  "description": "分层语义记忆系统 - OpenClaw Plugin",
5
5
  "type": "module",
6
6
  "openclaw": {