memory-gateway-sync 0.11.0 → 0.12.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "memory-gateway-sync",
3
- "version": "0.11.0",
3
+ "version": "0.12.0",
4
4
  "description": "Memory 双写插件:fs.watch 感知变化后同步到外部 Gateway",
5
5
  "type": "module",
6
6
  "main": "index.js",
@@ -0,0 +1,48 @@
1
+ /**
2
+ * 身份解析模块
3
+ *
4
+ * group_id 有值 → scene = "group"
5
+ * group_id 无值 → scene = "owner"
6
+ *
7
+ * owner_id 用于 SQL 数据隔离。
8
+ */
9
+
10
+ export type Scene = "owner" | "group" | "knowledge";
11
+
12
+ export interface ResolvedIdentity {
13
+ scene: Scene;
14
+ owner_id: string;
15
+ group_id: string | null;
16
+ }
17
+
18
+ export interface IdentityParams {
19
+ owner_id?: string;
20
+ group_id?: string;
21
+ }
22
+
23
+ export function resolveIdentity(params: IdentityParams): ResolvedIdentity {
24
+ const testScene = process.env.MEMORY_GATEWAY_TEST_SCENE as Scene | undefined;
25
+ if (testScene) {
26
+ return {
27
+ scene: testScene,
28
+ owner_id: process.env.MEMORY_GATEWAY_TEST_OWNER_ID || "test_owner",
29
+ group_id: process.env.MEMORY_GATEWAY_TEST_GROUP_ID || null,
30
+ };
31
+ }
32
+
33
+ const ownerId = params.owner_id?.trim() || "";
34
+ const groupId = params.group_id?.trim() || null;
35
+
36
+ if (!ownerId) {
37
+ console.warn(
38
+ "[identity] owner_id is empty — " +
39
+ "owner queries will be skipped to prevent cross-user leak."
40
+ );
41
+ }
42
+
43
+ if (groupId) {
44
+ return { scene: "group", owner_id: ownerId, group_id: groupId };
45
+ }
46
+
47
+ return { scene: "owner", owner_id: ownerId, group_id: null };
48
+ }
package/src/index.ts CHANGED
@@ -3,6 +3,7 @@ import fs from "node:fs";
3
3
  import path from "node:path";
4
4
  import crypto from "node:crypto";
5
5
  import os from "node:os";
6
+ import { resolveIdentity, type ResolvedIdentity } from "./identity";
6
7
 
7
8
  // ── 类型 ──────────────────────────────────��───────────────────────────────────
8
9
 
@@ -18,7 +19,9 @@ interface IngestPayload {
18
19
  content: string;
19
20
  release_name: string | null;
20
21
  agentId: string;
21
- userId: string | null;
22
+ userId: string;
23
+ scene: string;
24
+ group_id: string | null;
22
25
  workspaceDir: string;
23
26
  eventType: string;
24
27
  syncedAt: string;
@@ -163,24 +166,30 @@ export default definePluginEntry({
163
166
  }
164
167
  }
165
168
 
166
- // 根据路径解析 userId
167
- // MEMORY.md / memory/owner/* → 环境变量 owner_claw_user_id
168
- // memory/peers/{peerId}/* → 路径中的 peerId
169
- // 其他 null
170
- let userId: string | null = null;
169
+ // 根据路径解析身份
170
+ // MEMORY.md / memory/owner/* → owner_id = ownerClawUserId
171
+ // memory/peers/{peerId}/* → owner_id = 路径中的 peerId
172
+ // memory/groups/{groupId}/* owner_id = ownerClawUserId, group_id = groupId
173
+ // 其他 → owner_id = ownerClawUserId
174
+ let owner_id: string | undefined = ownerClawUserId ?? undefined;
175
+ let group_id: string | undefined;
171
176
  const parts = relativePath.replace(/\\/g, "/").split("/");
172
- if (relativePath === "MEMORY.md" || parts[0] === "memory" && parts[1] === "owner") {
173
- userId = ownerClawUserId;
174
- } else if (parts[0] === "memory" && parts[1] === "peers" && parts.length >= 3) {
175
- userId = parts[2];
177
+ if (parts[0] === "memory" && parts[1] === "peers" && parts.length >= 3) {
178
+ owner_id = parts[2];
179
+ } else if (parts[0] === "memory" && parts[1] === "groups" && parts.length >= 3) {
180
+ group_id = parts[2];
176
181
  }
177
182
 
183
+ const identity = resolveIdentity({ owner_id, group_id });
184
+
178
185
  const payload: IngestPayload = {
179
186
  path: relativePath,
180
187
  content,
181
188
  release_name: parseReleaseName(content) ?? podReleaseName,
182
189
  agentId: ws.agentId,
183
- userId,
190
+ userId: identity.owner_id,
191
+ scene: identity.scene,
192
+ group_id: identity.group_id,
184
193
  workspaceDir: ws.dir,
185
194
  eventType,
186
195
  syncedAt: new Date().toISOString(),