opencode-mem 2.1.1 → 2.3.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.
Files changed (33) hide show
  1. package/README.md +60 -77
  2. package/dist/config.d.ts +1 -2
  3. package/dist/config.d.ts.map +1 -1
  4. package/dist/config.js +11 -16
  5. package/dist/index.d.ts.map +1 -1
  6. package/dist/index.js +27 -86
  7. package/dist/plugin.d.ts.map +1 -1
  8. package/dist/plugin.js +0 -4
  9. package/dist/services/ai/providers/anthropic-messages.d.ts.map +1 -1
  10. package/dist/services/ai/providers/anthropic-messages.js +11 -17
  11. package/dist/services/ai/providers/openai-chat-completion.d.ts.map +1 -1
  12. package/dist/services/ai/providers/openai-chat-completion.js +11 -17
  13. package/dist/services/ai/providers/openai-responses.d.ts.map +1 -1
  14. package/dist/services/ai/providers/openai-responses.js +11 -17
  15. package/dist/services/api-handlers.d.ts +5 -3
  16. package/dist/services/api-handlers.d.ts.map +1 -1
  17. package/dist/services/api-handlers.js +165 -42
  18. package/dist/services/auto-capture.js +2 -2
  19. package/dist/services/context.d.ts +1 -1
  20. package/dist/services/context.d.ts.map +1 -1
  21. package/dist/services/context.js +1 -10
  22. package/dist/services/deduplication-service.d.ts.map +1 -1
  23. package/dist/services/deduplication-service.js +1 -3
  24. package/dist/services/logger.js +1 -1
  25. package/dist/services/user-memory-learning.d.ts +1 -1
  26. package/dist/services/user-memory-learning.d.ts.map +1 -1
  27. package/dist/services/user-memory-learning.js +5 -3
  28. package/dist/services/user-profile/user-profile-manager.d.ts.map +1 -1
  29. package/dist/services/web-server-worker.js +30 -3
  30. package/dist/web/app.js +254 -47
  31. package/dist/web/index.html +31 -15
  32. package/dist/web/styles.css +309 -0
  33. package/package.json +1 -1
@@ -168,24 +168,18 @@ export class OpenAIResponsesProvider extends BaseAIProvider {
168
168
  if (!data || typeof data !== "object") {
169
169
  throw new Error("Response is not an object");
170
170
  }
171
- if (data.memories && Array.isArray(data.memories)) {
172
- const validMemories = data.memories.filter((m) => {
173
- return (m &&
174
- typeof m === "object" &&
175
- typeof m.summary === "string" &&
176
- m.summary.trim().length > 0 &&
177
- (m.scope === "user" || m.scope === "project") &&
178
- typeof m.type === "string" &&
179
- m.type.trim().length > 0);
180
- });
181
- if (validMemories.length === 0) {
182
- throw new Error("No valid memories in response");
183
- }
184
- return { memories: validMemories };
171
+ if (Array.isArray(data)) {
172
+ throw new Error("Response cannot be an array");
185
173
  }
186
- if (data.summary && typeof data.summary === "string" && data.summary.trim().length > 0) {
187
- return data;
174
+ const keys = Object.keys(data);
175
+ if (keys.length === 0) {
176
+ throw new Error("Response object is empty");
177
+ }
178
+ for (const key of keys) {
179
+ if (data[key] === undefined || data[key] === null) {
180
+ throw new Error(`Response field '${key}' is null or undefined`);
181
+ }
188
182
  }
189
- throw new Error("Invalid response format: missing summary or memories field");
183
+ return data;
190
184
  }
191
185
  }
@@ -8,7 +8,6 @@ interface Memory {
8
8
  id: string;
9
9
  content: string;
10
10
  type?: string;
11
- scope: string;
12
11
  createdAt: string;
13
12
  updatedAt?: string;
14
13
  metadata?: Record<string, unknown>;
@@ -37,10 +36,9 @@ interface PaginatedResponse<T> {
37
36
  totalPages: number;
38
37
  }
39
38
  export declare function handleListTags(): Promise<ApiResponse<{
40
- user: TagInfo[];
41
39
  project: TagInfo[];
42
40
  }>>;
43
- export declare function handleListMemories(tag?: string, page?: number, pageSize?: number, scope?: "user" | "project", includePrompts?: boolean): Promise<ApiResponse<PaginatedResponse<Memory | any>>>;
41
+ export declare function handleListMemories(tag?: string, page?: number, pageSize?: number, includePrompts?: boolean): Promise<ApiResponse<PaginatedResponse<Memory | any>>>;
44
42
  export declare function handleAddMemory(data: {
45
43
  content: string;
46
44
  containerTag: string;
@@ -106,5 +104,9 @@ export declare function handleDeletePrompt(id: string, cascade?: boolean): Promi
106
104
  export declare function handleBulkDeletePrompts(ids: string[], cascade?: boolean): Promise<ApiResponse<{
107
105
  deleted: number;
108
106
  }>>;
107
+ export declare function handleGetUserProfile(userId?: string): Promise<ApiResponse<any>>;
108
+ export declare function handleGetProfileChangelog(profileId: string, limit?: number): Promise<ApiResponse<any[]>>;
109
+ export declare function handleGetProfileSnapshot(changelogId: string): Promise<ApiResponse<any>>;
110
+ export declare function handleRefreshProfile(userId?: string): Promise<ApiResponse<any>>;
109
111
  export {};
110
112
  //# sourceMappingURL=api-handlers.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"api-handlers.d.ts","sourceRoot":"","sources":["../../src/services/api-handlers.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"api-handlers.d.ts","sourceRoot":"","sources":["../../src/services/api-handlers.ts"],"names":[],"mappings":"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"}
@@ -33,18 +33,16 @@ function safeJSONParse(jsonString) {
33
33
  function extractScopeFromTag(tag) {
34
34
  const parts = tag.split("_");
35
35
  if (parts.length >= 3) {
36
- const scope = parts[1];
37
36
  const hash = parts.slice(2).join("_");
38
- return { scope, hash };
37
+ return { scope: "project", hash };
39
38
  }
40
- return { scope: "user", hash: tag };
39
+ return { scope: "project", hash: tag };
41
40
  }
42
41
  export async function handleListTags() {
43
42
  try {
44
43
  await embeddingService.warmup();
45
- const userShards = shardManager.getAllShards("user", "");
46
44
  const projectShards = shardManager.getAllShards("project", "");
47
- const allShards = [...userShards, ...projectShards];
45
+ const allShards = [...projectShards];
48
46
  const tagsMap = new Map();
49
47
  for (const shard of allShards) {
50
48
  const db = connectionManager.getConnection(shard.dbPath);
@@ -63,19 +61,15 @@ export async function handleListTags() {
63
61
  }
64
62
  }
65
63
  }
66
- const userTags = [];
67
64
  const projectTags = [];
68
65
  for (const tagInfo of tagsMap.values()) {
69
- if (tagInfo.tag.includes("_user_")) {
70
- userTags.push(tagInfo);
71
- }
72
- else if (tagInfo.tag.includes("_project_")) {
66
+ if (tagInfo.tag.includes("_project_")) {
73
67
  projectTags.push(tagInfo);
74
68
  }
75
69
  }
76
70
  return {
77
71
  success: true,
78
- data: { user: userTags, project: projectTags },
72
+ data: { project: projectTags },
79
73
  };
80
74
  }
81
75
  catch (error) {
@@ -83,7 +77,7 @@ export async function handleListTags() {
83
77
  return { success: false, error: String(error) };
84
78
  }
85
79
  }
86
- export async function handleListMemories(tag, page = 1, pageSize = 20, scope, includePrompts = true) {
80
+ export async function handleListMemories(tag, page = 1, pageSize = 20, includePrompts = true) {
87
81
  try {
88
82
  await embeddingService.warmup();
89
83
  let allMemories = [];
@@ -96,22 +90,12 @@ export async function handleListMemories(tag, page = 1, pageSize = 20, scope, in
96
90
  allMemories.push(...memories);
97
91
  }
98
92
  }
99
- else if (scope) {
100
- const shards = shardManager.getAllShards(scope, "");
93
+ else {
94
+ const shards = shardManager.getAllShards("project", "");
101
95
  for (const shard of shards) {
102
96
  const db = connectionManager.getConnection(shard.dbPath);
103
97
  const memories = vectorSearch.getAllMemories(db);
104
- allMemories.push(...memories.filter((m) => m.container_tag?.includes(`_${scope}_`)));
105
- }
106
- }
107
- else {
108
- const userShards = shardManager.getAllShards("user", "");
109
- const projectShards = shardManager.getAllShards("project", "");
110
- const allShards = [...userShards, ...projectShards];
111
- for (const shard of allShards) {
112
- const db = connectionManager.getConnection(shard.dbPath);
113
- const memories = vectorSearch.getAllMemories(db);
114
- allMemories.push(...memories);
98
+ allMemories.push(...memories.filter((m) => m.container_tag?.includes(`_project_`)));
115
99
  }
116
100
  }
117
101
  const memoriesWithType = allMemories.map((r) => {
@@ -121,7 +105,6 @@ export async function handleListMemories(tag, page = 1, pageSize = 20, scope, in
121
105
  id: r.id,
122
106
  content: r.content,
123
107
  memoryType: r.type,
124
- scope: r.container_tag?.includes("_user_") ? "user" : "project",
125
108
  createdAt: Number(r.created_at),
126
109
  updatedAt: r.updated_at ? Number(r.updated_at) : undefined,
127
110
  metadata,
@@ -136,7 +119,7 @@ export async function handleListMemories(tag, page = 1, pageSize = 20, scope, in
136
119
  };
137
120
  });
138
121
  let timeline = memoriesWithType;
139
- if (includePrompts && scope === "project") {
122
+ if (includePrompts) {
140
123
  const prompts = userPromptManager.getCapturedPrompts(tag);
141
124
  const promptsWithType = prompts.map((p) => ({
142
125
  type: "prompt",
@@ -149,7 +132,40 @@ export async function handleListMemories(tag, page = 1, pageSize = 20, scope, in
149
132
  }));
150
133
  timeline = [...memoriesWithType, ...promptsWithType];
151
134
  }
152
- timeline.sort((a, b) => b.createdAt - a.createdAt);
135
+ const linkedPairs = new Map();
136
+ const standalone = [];
137
+ for (const item of timeline) {
138
+ if (item.type === "memory" && item.linkedPromptId) {
139
+ if (!linkedPairs.has(item.linkedPromptId)) {
140
+ linkedPairs.set(item.linkedPromptId, { memory: item, prompt: null });
141
+ }
142
+ else {
143
+ linkedPairs.get(item.linkedPromptId).memory = item;
144
+ }
145
+ }
146
+ else if (item.type === "prompt" && item.linkedMemoryId) {
147
+ if (!linkedPairs.has(item.id)) {
148
+ linkedPairs.set(item.id, { memory: null, prompt: item });
149
+ }
150
+ else {
151
+ linkedPairs.get(item.id).prompt = item;
152
+ }
153
+ }
154
+ else {
155
+ standalone.push(item);
156
+ }
157
+ }
158
+ const sortedTimeline = [];
159
+ const pairs = Array.from(linkedPairs.values())
160
+ .filter((p) => p.memory && p.prompt)
161
+ .sort((a, b) => b.memory.createdAt - a.memory.createdAt);
162
+ for (const pair of pairs) {
163
+ sortedTimeline.push(pair.memory);
164
+ sortedTimeline.push(pair.prompt);
165
+ }
166
+ standalone.sort((a, b) => b.createdAt - a.createdAt);
167
+ sortedTimeline.push(...standalone);
168
+ timeline = sortedTimeline;
153
169
  const total = timeline.length;
154
170
  const totalPages = Math.ceil(total / pageSize);
155
171
  const offset = (page - 1) * pageSize;
@@ -161,7 +177,6 @@ export async function handleListMemories(tag, page = 1, pageSize = 20, scope, in
161
177
  id: item.id,
162
178
  content: item.content,
163
179
  memoryType: item.memoryType,
164
- scope: item.scope,
165
180
  createdAt: safeToISOString(item.createdAt),
166
181
  updatedAt: item.updatedAt ? safeToISOString(item.updatedAt) : undefined,
167
182
  metadata: item.metadata,
@@ -247,9 +262,8 @@ export async function handleDeleteMemory(id, cascade = false) {
247
262
  if (!id) {
248
263
  return { success: false, error: "id is required" };
249
264
  }
250
- const userShards = shardManager.getAllShards("user", "");
251
265
  const projectShards = shardManager.getAllShards("project", "");
252
- const allShards = [...userShards, ...projectShards];
266
+ const allShards = [...projectShards];
253
267
  let deletedPrompt = false;
254
268
  for (const shard of allShards) {
255
269
  const db = connectionManager.getConnection(shard.dbPath);
@@ -300,9 +314,8 @@ export async function handleUpdateMemory(id, data) {
300
314
  return { success: false, error: "id is required" };
301
315
  }
302
316
  await embeddingService.warmup();
303
- const userShards = shardManager.getAllShards("user", "");
304
317
  const projectShards = shardManager.getAllShards("project", "");
305
- const allShards = [...userShards, ...projectShards];
318
+ const allShards = [...projectShards];
306
319
  let foundShard = null;
307
320
  let existingMemory = null;
308
321
  for (const shard of allShards) {
@@ -369,9 +382,8 @@ export async function handleSearch(query, tag, page = 1, pageSize = 20) {
369
382
  }
370
383
  }
371
384
  else {
372
- const userShards = shardManager.getAllShards("user", "");
373
385
  const projectShards = shardManager.getAllShards("project", "");
374
- const allShards = [...userShards, ...projectShards];
386
+ const allShards = [...projectShards];
375
387
  const uniqueTags = new Set();
376
388
  for (const shard of allShards) {
377
389
  const db = connectionManager.getConnection(shard.dbPath);
@@ -405,7 +417,6 @@ export async function handleSearch(query, tag, page = 1, pageSize = 20) {
405
417
  id: r.id,
406
418
  content: r.memory,
407
419
  type: r.metadata?.type,
408
- scope: r.containerTag?.includes("_user_") ? "user" : "project",
409
420
  createdAt: safeToISOString(r.metadata?.createdAt),
410
421
  updatedAt: r.metadata?.updatedAt ? safeToISOString(r.metadata.updatedAt) : undefined,
411
422
  similarity: Math.round(r.similarity * 100),
@@ -437,9 +448,8 @@ export async function handleSearch(query, tag, page = 1, pageSize = 20) {
437
448
  export async function handleStats() {
438
449
  try {
439
450
  await embeddingService.warmup();
440
- const userShards = shardManager.getAllShards("user", "");
441
451
  const projectShards = shardManager.getAllShards("project", "");
442
- const allShards = [...userShards, ...projectShards];
452
+ const allShards = [...projectShards];
443
453
  let userCount = 0;
444
454
  let projectCount = 0;
445
455
  const typeCount = {};
@@ -477,9 +487,8 @@ export async function handlePinMemory(id) {
477
487
  if (!id) {
478
488
  return { success: false, error: "id is required" };
479
489
  }
480
- const userShards = shardManager.getAllShards("user", "");
481
490
  const projectShards = shardManager.getAllShards("project", "");
482
- const allShards = [...userShards, ...projectShards];
491
+ const allShards = [...projectShards];
483
492
  for (const shard of allShards) {
484
493
  const db = connectionManager.getConnection(shard.dbPath);
485
494
  const memory = vectorSearch.getMemoryById(db, id);
@@ -500,9 +509,8 @@ export async function handleUnpinMemory(id) {
500
509
  if (!id) {
501
510
  return { success: false, error: "id is required" };
502
511
  }
503
- const userShards = shardManager.getAllShards("user", "");
504
512
  const projectShards = shardManager.getAllShards("project", "");
505
- const allShards = [...userShards, ...projectShards];
513
+ const allShards = [...projectShards];
506
514
  for (const shard of allShards) {
507
515
  const db = connectionManager.getConnection(shard.dbPath);
508
516
  const memory = vectorSearch.getMemoryById(db, id);
@@ -605,3 +613,118 @@ export async function handleBulkDeletePrompts(ids, cascade = false) {
605
613
  return { success: false, error: String(error) };
606
614
  }
607
615
  }
616
+ export async function handleGetUserProfile(userId) {
617
+ try {
618
+ const { userProfileManager } = await import("./user-profile/user-profile-manager.js");
619
+ const { getTags } = await import("./tags.js");
620
+ let targetUserId = userId;
621
+ if (!targetUserId) {
622
+ const tags = getTags(process.cwd());
623
+ targetUserId = tags.user.userEmail || "unknown";
624
+ }
625
+ const profile = userProfileManager.getActiveProfile(targetUserId);
626
+ if (!profile) {
627
+ return {
628
+ success: true,
629
+ data: {
630
+ exists: false,
631
+ userId: targetUserId,
632
+ message: "No profile found. Keep chatting to build your profile.",
633
+ },
634
+ };
635
+ }
636
+ const profileData = JSON.parse(profile.profileData);
637
+ return {
638
+ success: true,
639
+ data: {
640
+ exists: true,
641
+ id: profile.id,
642
+ userId: profile.userId,
643
+ displayName: profile.displayName,
644
+ userName: profile.userName,
645
+ userEmail: profile.userEmail,
646
+ version: profile.version,
647
+ createdAt: safeToISOString(profile.createdAt),
648
+ lastAnalyzedAt: safeToISOString(profile.lastAnalyzedAt),
649
+ totalPromptsAnalyzed: profile.totalPromptsAnalyzed,
650
+ profileData,
651
+ },
652
+ };
653
+ }
654
+ catch (error) {
655
+ log("handleGetUserProfile: error", { error: String(error) });
656
+ return { success: false, error: String(error) };
657
+ }
658
+ }
659
+ export async function handleGetProfileChangelog(profileId, limit = 5) {
660
+ try {
661
+ if (!profileId) {
662
+ return { success: false, error: "profileId is required" };
663
+ }
664
+ const { userProfileManager } = await import("./user-profile/user-profile-manager.js");
665
+ const changelogs = userProfileManager.getProfileChangelogs(profileId, limit);
666
+ const formattedChangelogs = changelogs.map((c) => ({
667
+ id: c.id,
668
+ profileId: c.profileId,
669
+ version: c.version,
670
+ changeType: c.changeType,
671
+ changeSummary: c.changeSummary,
672
+ createdAt: safeToISOString(c.createdAt),
673
+ }));
674
+ return { success: true, data: formattedChangelogs };
675
+ }
676
+ catch (error) {
677
+ log("handleGetProfileChangelog: error", { error: String(error) });
678
+ return { success: false, error: String(error) };
679
+ }
680
+ }
681
+ export async function handleGetProfileSnapshot(changelogId) {
682
+ try {
683
+ if (!changelogId) {
684
+ return { success: false, error: "changelogId is required" };
685
+ }
686
+ const { userProfileManager } = await import("./user-profile/user-profile-manager.js");
687
+ const changelogs = userProfileManager.getProfileChangelogs("", 1000);
688
+ const changelog = changelogs.find((c) => c.id === changelogId);
689
+ if (!changelog) {
690
+ return { success: false, error: "Changelog not found" };
691
+ }
692
+ const profileData = JSON.parse(changelog.profileDataSnapshot);
693
+ return {
694
+ success: true,
695
+ data: {
696
+ version: changelog.version,
697
+ createdAt: safeToISOString(changelog.createdAt),
698
+ profileData,
699
+ },
700
+ };
701
+ }
702
+ catch (error) {
703
+ log("handleGetProfileSnapshot: error", { error: String(error) });
704
+ return { success: false, error: String(error) };
705
+ }
706
+ }
707
+ export async function handleRefreshProfile(userId) {
708
+ try {
709
+ const { getTags } = await import("./tags.js");
710
+ const { userPromptManager } = await import("./user-prompt/user-prompt-manager.js");
711
+ let targetUserId = userId;
712
+ if (!targetUserId) {
713
+ const tags = getTags(process.cwd());
714
+ targetUserId = tags.user.userEmail || "unknown";
715
+ }
716
+ const unanalyzedCount = userPromptManager.countUnanalyzedForUserLearning();
717
+ return {
718
+ success: true,
719
+ data: {
720
+ message: "Profile refresh queued",
721
+ unanalyzedPrompts: unanalyzedCount,
722
+ note: "Profile will be updated when threshold is reached",
723
+ },
724
+ };
725
+ }
726
+ catch (error) {
727
+ log("handleRefreshProfile: error", { error: String(error) });
728
+ return { success: false, error: String(error) };
729
+ }
730
+ }
@@ -37,7 +37,7 @@ export async function performAutoCapture(ctx, sessionID, directory) {
37
37
  const tags = getTags(directory);
38
38
  const latestMemory = await getLatestProjectMemory(tags.project.tag);
39
39
  const context = buildMarkdownContext(prompt.content, textResponses, toolCalls, latestMemory);
40
- const summaryResult = await generateSummary(ctx, context, sessionID);
40
+ const summaryResult = await generateSummary(context, sessionID);
41
41
  if (!summaryResult || summaryResult.type === "skip") {
42
42
  log("Auto-capture: skipped non-technical conversation", { sessionID });
43
43
  userPromptManager.deletePrompt(prompt.id);
@@ -179,7 +179,7 @@ function buildMarkdownContext(userPrompt, textResponses, toolCalls, latestMemory
179
179
  }
180
180
  return sections.join("\n");
181
181
  }
182
- async function generateSummary(ctx, context, sessionID) {
182
+ async function generateSummary(context, sessionID) {
183
183
  if (!CONFIG.memoryModel || !CONFIG.memoryApiUrl || !CONFIG.memoryApiKey) {
184
184
  throw new Error("External API not configured for auto-capture");
185
185
  }
@@ -6,6 +6,6 @@ interface MemoryResultMinimal {
6
6
  interface MemoriesResponseMinimal {
7
7
  results?: MemoryResultMinimal[];
8
8
  }
9
- export declare function formatContextForPrompt(userId: string | null, userMemories: MemoriesResponseMinimal, projectMemories: MemoriesResponseMinimal): string;
9
+ export declare function formatContextForPrompt(userId: string | null, projectMemories: MemoriesResponseMinimal): string;
10
10
  export {};
11
11
  //# sourceMappingURL=context.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/services/context.ts"],"names":[],"mappings":"AAGA,UAAU,mBAAmB;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,UAAU,uBAAuB;IAC/B,OAAO,CAAC,EAAE,mBAAmB,EAAE,CAAC;CACjC;AAED,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,MAAM,GAAG,IAAI,EACrB,YAAY,EAAE,uBAAuB,EACrC,eAAe,EAAE,uBAAuB,GACvC,MAAM,CAmCR"}
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/services/context.ts"],"names":[],"mappings":"AAGA,UAAU,mBAAmB;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,UAAU,uBAAuB;IAC/B,OAAO,CAAC,EAAE,mBAAmB,EAAE,CAAC;CACjC;AAED,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,MAAM,GAAG,IAAI,EACrB,eAAe,EAAE,uBAAuB,GACvC,MAAM,CAyBR"}
@@ -1,6 +1,6 @@
1
1
  import { CONFIG } from "../config.js";
2
2
  import { getUserProfileContext } from "./user-profile/profile-context.js";
3
- export function formatContextForPrompt(userId, userMemories, projectMemories) {
3
+ export function formatContextForPrompt(userId, projectMemories) {
4
4
  const parts = ["[MEMORY]"];
5
5
  if (CONFIG.injectProfile && userId) {
6
6
  const profileContext = getUserProfileContext(userId);
@@ -17,15 +17,6 @@ export function formatContextForPrompt(userId, userMemories, projectMemories) {
17
17
  parts.push(`- [${similarity}%] ${content}`);
18
18
  });
19
19
  }
20
- const userResults = userMemories.results || [];
21
- if (userResults.length > 0) {
22
- parts.push("\nRelevant Memories:");
23
- userResults.forEach((mem) => {
24
- const similarity = Math.round(mem.similarity * 100);
25
- const content = mem.memory || mem.chunk || "";
26
- parts.push(`- [${similarity}%] ${content}`);
27
- });
28
- }
29
20
  if (parts.length === 1) {
30
21
  return "";
31
22
  }
@@ -1 +1 @@
1
- {"version":3,"file":"deduplication-service.d.ts","sourceRoot":"","sources":["../../src/services/deduplication-service.ts"],"names":[],"mappings":"AAOA,UAAU,cAAc;IACtB,cAAc,EAAE;QACd,EAAE,EAAE,MAAM,CAAC;QACX,OAAO,EAAE,MAAM,CAAC;QAChB,YAAY,EAAE,MAAM,CAAC;QACrB,SAAS,EAAE,MAAM,CAAC;KACnB,CAAC;IACF,UAAU,EAAE,KAAK,CAAC;QAChB,EAAE,EAAE,MAAM,CAAC;QACX,OAAO,EAAE,MAAM,CAAC;QAChB,UAAU,EAAE,MAAM,CAAC;KACpB,CAAC,CAAC;CACJ;AAED,UAAU,mBAAmB;IAC3B,sBAAsB,EAAE,MAAM,CAAC;IAC/B,mBAAmB,EAAE,cAAc,EAAE,CAAC;CACvC;AAED,qBAAa,oBAAoB;IAC/B,OAAO,CAAC,SAAS,CAAkB;IAE7B,yBAAyB,IAAI,OAAO,CAAC,mBAAmB,CAAC;IAgH/D,OAAO,CAAC,gBAAgB;IAoBxB,SAAS;;;;;CAOV;AAED,eAAO,MAAM,oBAAoB,sBAA6B,CAAC"}
1
+ {"version":3,"file":"deduplication-service.d.ts","sourceRoot":"","sources":["../../src/services/deduplication-service.ts"],"names":[],"mappings":"AAMA,UAAU,cAAc;IACtB,cAAc,EAAE;QACd,EAAE,EAAE,MAAM,CAAC;QACX,OAAO,EAAE,MAAM,CAAC;QAChB,YAAY,EAAE,MAAM,CAAC;QACrB,SAAS,EAAE,MAAM,CAAC;KACnB,CAAC;IACF,UAAU,EAAE,KAAK,CAAC;QAChB,EAAE,EAAE,MAAM,CAAC;QACX,OAAO,EAAE,MAAM,CAAC;QAChB,UAAU,EAAE,MAAM,CAAC;KACpB,CAAC,CAAC;CACJ;AAED,UAAU,mBAAmB;IAC3B,sBAAsB,EAAE,MAAM,CAAC;IAC/B,mBAAmB,EAAE,cAAc,EAAE,CAAC;CACvC;AAED,qBAAa,oBAAoB;IAC/B,OAAO,CAAC,SAAS,CAAkB;IAE7B,yBAAyB,IAAI,OAAO,CAAC,mBAAmB,CAAC;IA+G/D,OAAO,CAAC,gBAAgB;IAoBxB,SAAS;;;;;CAOV;AAED,eAAO,MAAM,oBAAoB,sBAA6B,CAAC"}
@@ -1,4 +1,3 @@
1
- import { embeddingService } from "./embedding.js";
2
1
  import { shardManager } from "./sqlite/shard-manager.js";
3
2
  import { vectorSearch } from "./sqlite/vector-search.js";
4
3
  import { connectionManager } from "./sqlite/connection-manager.js";
@@ -34,10 +33,9 @@ export class DeduplicationService {
34
33
  }
35
34
  contentMap.get(key).push(memory);
36
35
  }
37
- for (const [key, duplicates] of contentMap) {
36
+ for (const [, duplicates] of contentMap) {
38
37
  if (duplicates.length > 1) {
39
38
  duplicates.sort((a, b) => Number(b.created_at) - Number(a.created_at));
40
- const keep = duplicates[0];
41
39
  const toDelete = duplicates.slice(1);
42
40
  for (const dup of toDelete) {
43
41
  try {
@@ -1,6 +1,6 @@
1
1
  import { appendFileSync, writeFileSync, existsSync, mkdirSync } from "fs";
2
2
  import { homedir } from "os";
3
- import { join, dirname } from "path";
3
+ import { join } from "path";
4
4
  const LOG_DIR = join(homedir(), ".opencode-mem");
5
5
  const LOG_FILE = join(LOG_DIR, "opencode-mem.log");
6
6
  if (!existsSync(LOG_DIR)) {
@@ -1,3 +1,3 @@
1
1
  import type { PluginInput } from "@opencode-ai/plugin";
2
- export declare function performUserMemoryLearning(ctx: PluginInput, directory: string): Promise<void>;
2
+ export declare function performUserProfileLearning(ctx: PluginInput, directory: string): Promise<void>;
3
3
  //# sourceMappingURL=user-memory-learning.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"user-memory-learning.d.ts","sourceRoot":"","sources":["../../src/services/user-memory-learning.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AASvD,wBAAsB,yBAAyB,CAC7C,GAAG,EAAE,WAAW,EAChB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,IAAI,CAAC,CA8Ef"}
1
+ {"version":3,"file":"user-memory-learning.d.ts","sourceRoot":"","sources":["../../src/services/user-memory-learning.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AASvD,wBAAsB,0BAA0B,CAC9C,GAAG,EAAE,WAAW,EAChB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,IAAI,CAAC,CA8Ef"}
@@ -3,10 +3,10 @@ import { log } from "./logger.js";
3
3
  import { CONFIG } from "../config.js";
4
4
  import { userPromptManager } from "./user-prompt/user-prompt-manager.js";
5
5
  import { userProfileManager } from "./user-profile/user-profile-manager.js";
6
- export async function performUserMemoryLearning(ctx, directory) {
6
+ export async function performUserProfileLearning(ctx, directory) {
7
7
  try {
8
8
  const count = userPromptManager.countUnanalyzedForUserLearning();
9
- const threshold = CONFIG.userMemoryAnalysisInterval;
9
+ const threshold = CONFIG.userProfileAnalysisInterval;
10
10
  if (count < threshold) {
11
11
  return;
12
12
  }
@@ -135,7 +135,9 @@ Use the update_user_profile tool to save the ${existingProfile ? "updated" : "ne
135
135
  type: "function",
136
136
  function: {
137
137
  name: "update_user_profile",
138
- description: existingProfile ? "Update existing user profile with new insights" : "Create new user profile",
138
+ description: existingProfile
139
+ ? "Update existing user profile with new insights"
140
+ : "Create new user profile",
139
141
  parameters: {
140
142
  type: "object",
141
143
  properties: {
@@ -1 +1 @@
1
- {"version":3,"file":"user-profile-manager.d.ts","sourceRoot":"","sources":["../../../src/services/user-profile/user-profile-manager.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACV,WAAW,EACX,oBAAoB,EACpB,eAAe,EAChB,MAAM,YAAY,CAAC;AAIpB,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,EAAE,CAAW;IACrB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;;IAQhC,OAAO,CAAC,YAAY;IA0CpB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI;IAapD,aAAa,CACX,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,eAAe,EAC5B,eAAe,EAAE,MAAM,GACtB,MAAM;IA8BT,aAAa,CACX,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,eAAe,EAC5B,yBAAyB,EAAE,MAAM,EACjC,aAAa,EAAE,MAAM,GACpB,IAAI;IAuBP,OAAO,CAAC,YAAY;IAqBpB,OAAO,CAAC,oBAAoB;IAiB5B,oBAAoB,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,GAAE,MAAW,GAAG,oBAAoB,EAAE;IAYnF,oBAAoB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IA2B7C,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IAKtC,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI;IAOrD,oBAAoB,IAAI,WAAW,EAAE;IAMrC,OAAO,CAAC,YAAY;IAgBpB,OAAO,CAAC,cAAc;IAYtB,gBAAgB,CACd,QAAQ,EAAE,eAAe,EACzB,OAAO,EAAE,OAAO,CAAC,eAAe,CAAC,GAChC,eAAe;CAyFnB;AAED,eAAO,MAAM,kBAAkB,oBAA2B,CAAC"}
1
+ {"version":3,"file":"user-profile-manager.d.ts","sourceRoot":"","sources":["../../../src/services/user-profile/user-profile-manager.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,WAAW,EAAE,oBAAoB,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAIrF,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,EAAE,CAAW;IACrB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;;IAQhC,OAAO,CAAC,YAAY;IA0CpB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI;IAapD,aAAa,CACX,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,eAAe,EAC5B,eAAe,EAAE,MAAM,GACtB,MAAM;IA8BT,aAAa,CACX,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,eAAe,EAC5B,yBAAyB,EAAE,MAAM,EACjC,aAAa,EAAE,MAAM,GACpB,IAAI;IA6BP,OAAO,CAAC,YAAY;IAqBpB,OAAO,CAAC,oBAAoB;IAiB5B,oBAAoB,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,GAAE,MAAW,GAAG,oBAAoB,EAAE;IAYnF,oBAAoB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IA2B7C,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IAKtC,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI;IAOrD,oBAAoB,IAAI,WAAW,EAAE;IAMrC,OAAO,CAAC,YAAY;IAgBpB,OAAO,CAAC,cAAc;IAYtB,gBAAgB,CAAC,QAAQ,EAAE,eAAe,EAAE,OAAO,EAAE,OAAO,CAAC,eAAe,CAAC,GAAG,eAAe;CAyFhG;AAED,eAAO,MAAM,kBAAkB,oBAA2B,CAAC"}
@@ -1,7 +1,7 @@
1
1
  import { readFileSync } from "node:fs";
2
2
  import { join, dirname } from "node:path";
3
3
  import { fileURLToPath } from "node:url";
4
- import { handleListTags, handleListMemories, handleAddMemory, handleDeleteMemory, handleBulkDelete, handleUpdateMemory, handleSearch, handleStats, handlePinMemory, handleUnpinMemory, handleRunCleanup, handleRunDeduplication, handleDetectMigration, handleRunMigration, handleDeletePrompt, handleBulkDeletePrompts, } from "./api-handlers.js";
4
+ import { handleListTags, handleListMemories, handleAddMemory, handleDeleteMemory, handleBulkDelete, handleUpdateMemory, handleSearch, handleStats, handlePinMemory, handleUnpinMemory, handleRunCleanup, handleRunDeduplication, handleDetectMigration, handleRunMigration, handleDeletePrompt, handleBulkDeletePrompts, handleGetUserProfile, handleGetProfileChangelog, handleGetProfileSnapshot, handleRefreshProfile, } from "./api-handlers.js";
5
5
  const __filename = fileURLToPath(import.meta.url);
6
6
  const __dirname = dirname(__filename);
7
7
  let server = null;
@@ -30,9 +30,8 @@ async function handleRequest(req) {
30
30
  const tag = url.searchParams.get("tag") || undefined;
31
31
  const page = parseInt(url.searchParams.get("page") || "1");
32
32
  const pageSize = parseInt(url.searchParams.get("pageSize") || "20");
33
- const scope = url.searchParams.get("scope");
34
33
  const includePrompts = url.searchParams.get("includePrompts") !== "false";
35
- const result = await handleListMemories(tag, page, pageSize, scope, includePrompts);
34
+ const result = await handleListMemories(tag, page, pageSize, includePrompts);
36
35
  return jsonResponse(result);
37
36
  }
38
37
  if (path === "/api/memories" && method === "POST") {
@@ -133,6 +132,34 @@ async function handleRequest(req) {
133
132
  const result = await handleBulkDeletePrompts(body.ids || [], cascade);
134
133
  return jsonResponse(result);
135
134
  }
135
+ if (path === "/api/user-profile" && method === "GET") {
136
+ const userId = url.searchParams.get("userId") || undefined;
137
+ const result = await handleGetUserProfile(userId);
138
+ return jsonResponse(result);
139
+ }
140
+ if (path === "/api/user-profile/changelog" && method === "GET") {
141
+ const profileId = url.searchParams.get("profileId");
142
+ const limit = parseInt(url.searchParams.get("limit") || "5");
143
+ if (!profileId) {
144
+ return jsonResponse({ success: false, error: "profileId parameter required" });
145
+ }
146
+ const result = await handleGetProfileChangelog(profileId, limit);
147
+ return jsonResponse(result);
148
+ }
149
+ if (path === "/api/user-profile/snapshot" && method === "GET") {
150
+ const changelogId = url.searchParams.get("chlogId");
151
+ if (!changelogId) {
152
+ return jsonResponse({ success: false, error: "changelogId parameter required" });
153
+ }
154
+ const result = await handleGetProfileSnapshot(changelogId);
155
+ return jsonResponse(result);
156
+ }
157
+ if (path === "/api/user-profile/refresh" && method === "POST") {
158
+ const body = (await req.json().catch(() => ({})));
159
+ const userId = body.userId || undefined;
160
+ const result = await handleRefreshProfile(userId);
161
+ return jsonResponse(result);
162
+ }
136
163
  return new Response("Not Found", { status: 404 });
137
164
  }
138
165
  catch (error) {