opencode-mem 2.3.6 → 2.4.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 (34) hide show
  1. package/dist/config.d.ts +0 -1
  2. package/dist/config.d.ts.map +1 -1
  3. package/dist/config.js +4 -38
  4. package/dist/index.d.ts.map +1 -1
  5. package/dist/index.js +38 -80
  6. package/dist/services/ai/providers/anthropic-messages.d.ts.map +1 -1
  7. package/dist/services/ai/providers/anthropic-messages.js +11 -7
  8. package/dist/services/ai/providers/base-provider.d.ts +3 -3
  9. package/dist/services/ai/providers/base-provider.d.ts.map +1 -1
  10. package/dist/services/ai/providers/openai-chat-completion.d.ts.map +1 -1
  11. package/dist/services/ai/providers/openai-chat-completion.js +11 -6
  12. package/dist/services/ai/providers/openai-responses.d.ts.map +1 -1
  13. package/dist/services/ai/providers/openai-responses.js +4 -2
  14. package/dist/services/ai/validators/user-profile-validator.d.ts +0 -1
  15. package/dist/services/ai/validators/user-profile-validator.d.ts.map +1 -1
  16. package/dist/services/ai/validators/user-profile-validator.js +0 -17
  17. package/dist/services/api-handlers.d.ts +32 -3
  18. package/dist/services/api-handlers.d.ts.map +1 -1
  19. package/dist/services/api-handlers.js +89 -13
  20. package/dist/services/auto-capture.js +11 -4
  21. package/dist/services/logger.d.ts.map +1 -1
  22. package/dist/services/logger.js +3 -1
  23. package/dist/services/sqlite/connection-manager.d.ts.map +1 -1
  24. package/dist/services/user-memory-learning.js +9 -14
  25. package/dist/services/user-profile/types.d.ts +0 -5
  26. package/dist/services/user-profile/types.d.ts.map +1 -1
  27. package/dist/services/user-profile/user-profile-manager.d.ts.map +1 -1
  28. package/dist/services/user-profile/user-profile-manager.js +0 -7
  29. package/dist/services/user-prompt/user-prompt-manager.d.ts +2 -0
  30. package/dist/services/user-prompt/user-prompt-manager.d.ts.map +1 -1
  31. package/dist/services/user-prompt/user-prompt-manager.js +21 -0
  32. package/dist/web/app.js +196 -114
  33. package/dist/web/styles.css +202 -122
  34. package/package.json +1 -1
@@ -381,19 +381,22 @@ export async function handleSearch(query, tag, page = 1, pageSize = 20) {
381
381
  }
382
382
  await embeddingService.warmup();
383
383
  const queryVector = await embeddingService.embedWithTimeout(query);
384
- let allResults = [];
384
+ let memoryResults = [];
385
+ let promptResults = [];
385
386
  if (tag) {
386
387
  const { scope, hash } = extractScopeFromTag(tag);
387
388
  const shards = shardManager.getAllShards(scope, hash);
388
389
  for (const shard of shards) {
389
390
  try {
390
391
  const results = vectorSearch.searchInShard(shard, queryVector, tag, pageSize * 2);
391
- allResults.push(...results);
392
+ memoryResults.push(...results);
392
393
  }
393
394
  catch (error) {
394
395
  log("Shard search error", { shardId: shard.id, error: String(error) });
395
396
  }
396
397
  }
398
+ const projectPath = getProjectPathFromTag(tag);
399
+ promptResults = userPromptManager.searchPrompts(query, projectPath, pageSize * 2);
397
400
  }
398
401
  else {
399
402
  const projectShards = shardManager.getAllShards("project", "");
@@ -414,26 +417,33 @@ export async function handleSearch(query, tag, page = 1, pageSize = 20) {
414
417
  for (const shard of shards) {
415
418
  try {
416
419
  const results = vectorSearch.searchInShard(shard, queryVector, containerTag, pageSize);
417
- allResults.push(...results);
420
+ memoryResults.push(...results);
418
421
  }
419
422
  catch (error) {
420
423
  log("Shard search error", { shardId: shard.id, error: String(error) });
421
424
  }
422
425
  }
423
426
  }
424
- }
425
- const sortedResults = allResults.sort((a, b) => b.similarity - a.similarity);
426
- const total = sortedResults.length;
427
- const totalPages = Math.ceil(total / pageSize);
428
- const offset = (page - 1) * pageSize;
429
- const paginatedResults = sortedResults.slice(offset, offset + pageSize);
430
- const memories = paginatedResults.map((r) => ({
427
+ promptResults = userPromptManager.searchPrompts(query, undefined, pageSize * 2);
428
+ }
429
+ const formattedPrompts = promptResults.map((p) => ({
430
+ type: "prompt",
431
+ id: p.id,
432
+ sessionId: p.sessionId,
433
+ content: p.content,
434
+ createdAt: safeToISOString(p.createdAt),
435
+ projectPath: p.projectPath,
436
+ linkedMemoryId: p.linkedMemoryId,
437
+ similarity: 1.0,
438
+ }));
439
+ const formattedMemories = memoryResults.map((r) => ({
440
+ type: "memory",
431
441
  id: r.id,
432
442
  content: r.memory,
433
- type: r.metadata?.type,
443
+ memoryType: r.metadata?.type,
434
444
  createdAt: safeToISOString(r.metadata?.createdAt),
435
445
  updatedAt: r.metadata?.updatedAt ? safeToISOString(r.metadata.updatedAt) : undefined,
436
- similarity: Math.round(r.similarity * 100),
446
+ similarity: r.similarity,
437
447
  metadata: r.metadata,
438
448
  displayName: r.displayName,
439
449
  userName: r.userName,
@@ -442,11 +452,77 @@ export async function handleSearch(query, tag, page = 1, pageSize = 20) {
442
452
  projectName: r.projectName,
443
453
  gitRepoUrl: r.gitRepoUrl,
444
454
  isPinned: r.isPinned === 1,
455
+ linkedPromptId: r.metadata?.promptId,
445
456
  }));
457
+ const combinedResults = [...formattedMemories, ...formattedPrompts].sort((a, b) => (b.similarity || 0) - (a.similarity || 0) || b.createdAt.localeCompare(a.createdAt));
458
+ const total = combinedResults.length;
459
+ const totalPages = Math.ceil(total / pageSize);
460
+ const offset = (page - 1) * pageSize;
461
+ const paginatedResults = combinedResults.slice(offset, offset + pageSize);
462
+ const missingPromptIds = new Set();
463
+ const missingMemoryIds = new Set();
464
+ for (const item of paginatedResults) {
465
+ if (item.type === "memory" && item.linkedPromptId) {
466
+ const hasPrompt = paginatedResults.some((p) => p.id === item.linkedPromptId);
467
+ if (!hasPrompt)
468
+ missingPromptIds.add(item.linkedPromptId);
469
+ }
470
+ else if (item.type === "prompt" && item.linkedMemoryId) {
471
+ const hasMemory = paginatedResults.some((m) => m.id === item.linkedMemoryId);
472
+ if (!hasMemory)
473
+ missingMemoryIds.add(item.linkedMemoryId);
474
+ }
475
+ }
476
+ if (missingPromptIds.size > 0) {
477
+ const extraPrompts = userPromptManager.getPromptsByIds(Array.from(missingPromptIds));
478
+ for (const p of extraPrompts) {
479
+ paginatedResults.push({
480
+ type: "prompt",
481
+ id: p.id,
482
+ sessionId: p.sessionId,
483
+ content: p.content,
484
+ createdAt: safeToISOString(p.createdAt),
485
+ projectPath: p.projectPath,
486
+ linkedMemoryId: p.linkedMemoryId,
487
+ similarity: 0,
488
+ isContext: true,
489
+ });
490
+ }
491
+ }
492
+ if (missingMemoryIds.size > 0) {
493
+ const projectShards = shardManager.getAllShards("project", "");
494
+ for (const shard of projectShards) {
495
+ const db = connectionManager.getConnection(shard.dbPath);
496
+ for (const mid of missingMemoryIds) {
497
+ const m = vectorSearch.getMemoryById(db, mid);
498
+ if (m && !paginatedResults.some((existing) => existing.id === m.id)) {
499
+ paginatedResults.push({
500
+ type: "memory",
501
+ id: m.id,
502
+ content: m.content,
503
+ memoryType: m.type,
504
+ createdAt: safeToISOString(m.created_at),
505
+ updatedAt: m.updated_at ? safeToISOString(m.updated_at) : undefined,
506
+ similarity: 0,
507
+ metadata: safeJSONParse(m.metadata),
508
+ displayName: m.display_name,
509
+ userName: m.user_name,
510
+ userEmail: m.user_email,
511
+ projectPath: m.project_path,
512
+ projectName: m.project_name,
513
+ gitRepoUrl: m.git_repo_url,
514
+ isPinned: m.is_pinned === 1,
515
+ linkedPromptId: safeJSONParse(m.metadata)?.promptId,
516
+ isContext: true,
517
+ });
518
+ }
519
+ }
520
+ }
521
+ }
446
522
  return {
447
523
  success: true,
448
524
  data: {
449
- items: memories,
525
+ items: paginatedResults,
450
526
  total,
451
527
  page,
452
528
  pageSize,
@@ -181,7 +181,7 @@ function buildMarkdownContext(userPrompt, textResponses, toolCalls, latestMemory
181
181
  return sections.join("\n");
182
182
  }
183
183
  async function generateSummary(context, sessionID) {
184
- if (!CONFIG.memoryModel || !CONFIG.memoryApiUrl || !CONFIG.memoryApiKey) {
184
+ if (!CONFIG.memoryModel || !CONFIG.memoryApiUrl) {
185
185
  throw new Error("External API not configured for auto-capture");
186
186
  }
187
187
  const { AIProviderFactory } = await import("./ai/ai-provider-factory.js");
@@ -200,24 +200,31 @@ RULES:
200
200
  2. SKIP non-technical by returning type="skip"
201
201
  3. NO meta-commentary or behavior analysis
202
202
  4. Include specific file names, functions, technical details
203
+ 5. DETECT the language used by the user. You MUST write the summary and reasoning in that SAME language.
203
204
 
204
205
  FORMAT:
205
206
  ## Request
206
- [1-2 sentences: what was requested]
207
+ [1-2 sentences: what was requested, in user's language]
207
208
 
208
209
  ## Outcome
209
- [1-2 sentences: what was done, include files/functions]
210
+ [1-2 sentences: what was done, include files/functions, in user's language]
210
211
 
211
212
  SKIP if: greetings, casual chat, no code/decisions made
212
213
  CAPTURE if: code changed, bug fixed, feature added, decision made
213
214
 
214
215
  EXAMPLES:
215
- Technical → type="feature":
216
+ Technical (English) → type="feature":
216
217
  ## Request
217
218
  Fix function returning null.
218
219
  ## Outcome
219
220
  Changed searchMemories() to listMemories() in auto-capture.ts:166.
220
221
 
222
+ Technical (Indonesian) → type="feature":
223
+ ## Request
224
+ Perbaiki fungsi yang mengembalikan null.
225
+ ## Outcome
226
+ Mengubah searchMemories() menjadi listMemories() di auto-capture.ts:166.
227
+
221
228
  Non-technical → type="skip", summary="":
222
229
  User greeted, AI introduced capabilities.`;
223
230
  const userPrompt = `${context}
@@ -1 +1 @@
1
- {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/services/logger.ts"],"names":[],"mappings":"AAkBA,wBAAgB,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,QAOlD"}
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/services/logger.ts"],"names":[],"mappings":"AAoBA,wBAAgB,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,QAOlD"}
@@ -10,7 +10,9 @@ function ensureLoggerInitialized() {
10
10
  if (!existsSync(LOG_DIR)) {
11
11
  mkdirSync(LOG_DIR, { recursive: true });
12
12
  }
13
- writeFileSync(LOG_FILE, `\n--- Session started: ${new Date().toISOString()} ---\n`, { flag: "a" });
13
+ writeFileSync(LOG_FILE, `\n--- Session started: ${new Date().toISOString()} ---\n`, {
14
+ flag: "a",
15
+ });
14
16
  globalThis[GLOBAL_LOGGER_KEY] = true;
15
17
  }
16
18
  export function log(message, data) {
@@ -1 +1 @@
1
- {"version":3,"file":"connection-manager.d.ts","sourceRoot":"","sources":["../../../src/services/sqlite/connection-manager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAOtC,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,WAAW,CAAoC;IACvD,OAAO,CAAC,gBAAgB,CAAS;IAEjC,OAAO,CAAC,eAAe;IA+EzB,OAAO,CAAC,YAAY;IAqBlB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,QAAQ;IAmBvC,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IASrC,QAAQ,IAAI,IAAI;CAWjB;AAED,eAAO,MAAM,iBAAiB,mBAA0B,CAAC"}
1
+ {"version":3,"file":"connection-manager.d.ts","sourceRoot":"","sources":["../../../src/services/sqlite/connection-manager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAOtC,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,WAAW,CAAoC;IACvD,OAAO,CAAC,gBAAgB,CAAS;IAEjC,OAAO,CAAC,eAAe;IA+EvB,OAAO,CAAC,YAAY;IAqBpB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,QAAQ;IAmBvC,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IASrC,QAAQ,IAAI,IAAI;CAWjB;AAED,eAAO,MAAM,iBAAiB,mBAA0B,CAAC"}
@@ -112,14 +112,15 @@ Identify and ${existingProfile ? "update" : "create"}:
112
112
  - Development sequences, habits, learning style
113
113
  - Break down into steps if applicable
114
114
 
115
- 4. **Skill Level**
116
- - Overall: beginner/intermediate/advanced
117
- - Per-domain assessment (e.g., typescript: advanced, docker: beginner)
118
-
119
115
  ${existingProfile ? "Merge with existing profile, incrementing frequencies and updating confidence scores." : "Create initial profile with conservative confidence scores."}`;
120
116
  }
121
117
  async function analyzeUserProfile(context, existingProfile) {
122
- if (!CONFIG.memoryModel || !CONFIG.memoryApiUrl || !CONFIG.memoryApiKey) {
118
+ if (!CONFIG.memoryModel || !CONFIG.memoryApiUrl) {
119
+ log("User Profile Config Check Failed:", {
120
+ memoryModel: CONFIG.memoryModel,
121
+ memoryApiUrl: CONFIG.memoryApiUrl,
122
+ memoryApiKey: CONFIG.memoryApiKey,
123
+ });
123
124
  throw new Error("External API not configured for user memory learning");
124
125
  }
125
126
  const { AIProviderFactory } = await import("./ai/ai-provider-factory.js");
@@ -135,6 +136,8 @@ async function analyzeUserProfile(context, existingProfile) {
135
136
 
136
137
  Your task is to analyze user prompts and ${existingProfile ? "update" : "create"} a comprehensive user profile.
137
138
 
139
+ CRITICAL: Detect the language used by the user. You MUST output all descriptions and text in the SAME language as the user's prompts.
140
+
138
141
  Use the update_user_profile tool to save the ${existingProfile ? "updated" : "new"} profile.`;
139
142
  const toolSchema = {
140
143
  type: "function",
@@ -181,16 +184,8 @@ Use the update_user_profile tool to save the ${existingProfile ? "updated" : "ne
181
184
  required: ["description", "steps"],
182
185
  },
183
186
  },
184
- skillLevel: {
185
- type: "object",
186
- properties: {
187
- overall: { type: "string", enum: ["beginner", "intermediate", "advanced"] },
188
- domains: { type: "object", additionalProperties: { type: "string" } },
189
- },
190
- required: ["overall", "domains"],
191
- },
192
187
  },
193
- required: ["preferences", "patterns", "workflows", "skillLevel"],
188
+ required: ["preferences", "patterns", "workflows"],
194
189
  },
195
190
  },
196
191
  };
@@ -16,15 +16,10 @@ export interface UserProfileWorkflow {
16
16
  steps: string[];
17
17
  frequency: number;
18
18
  }
19
- export interface UserProfileSkillLevel {
20
- overall: string;
21
- domains: Record<string, string>;
22
- }
23
19
  export interface UserProfileData {
24
20
  preferences: UserProfilePreference[];
25
21
  patterns: UserProfilePattern[];
26
22
  workflows: UserProfileWorkflow[];
27
- skillLevel: UserProfileSkillLevel;
28
23
  }
29
24
  export interface UserProfile {
30
25
  id: string;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/services/user-profile/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,qBAAqB;IACpC,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,mBAAmB;IAClC,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACjC;AAED,MAAM,WAAW,eAAe;IAC9B,WAAW,EAAE,qBAAqB,EAAE,CAAC;IACrC,QAAQ,EAAE,kBAAkB,EAAE,CAAC;IAC/B,SAAS,EAAE,mBAAmB,EAAE,CAAC;IACjC,UAAU,EAAE,qBAAqB,CAAC;CACnC;AAED,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;IACvB,oBAAoB,EAAE,MAAM,CAAC;IAC7B,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,oBAAoB;IACnC,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,SAAS,EAAE,MAAM,CAAC;CACnB"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/services/user-profile/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,qBAAqB;IACpC,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,mBAAmB;IAClC,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,eAAe;IAC9B,WAAW,EAAE,qBAAqB,EAAE,CAAC;IACrC,QAAQ,EAAE,kBAAkB,EAAE,CAAC;IAC/B,SAAS,EAAE,mBAAmB,EAAE,CAAC;CAClC;AAED,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;IACvB,oBAAoB,EAAE,MAAM,CAAC;IAC7B,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,oBAAoB;IACnC,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,SAAS,EAAE,MAAM,CAAC;CACnB"}
@@ -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,EAAE,WAAW,EAAE,oBAAoB,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAKrF,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;CA2FhG;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;AAKrF,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;CAmFhG;AAED,eAAO,MAAM,kBAAkB,oBAA2B,CAAC"}
@@ -194,7 +194,6 @@ export class UserProfileManager {
194
194
  preferences: safeArray(existing?.preferences),
195
195
  patterns: safeArray(existing?.patterns),
196
196
  workflows: safeArray(existing?.workflows),
197
- skillLevel: safeObject(existing?.skillLevel, { overall: "intermediate", domains: {} }),
198
197
  };
199
198
  if (updates.preferences) {
200
199
  for (const newPref of updates.preferences) {
@@ -258,12 +257,6 @@ export class UserProfileManager {
258
257
  merged.workflows.sort((a, b) => b.frequency - a.frequency);
259
258
  merged.workflows = merged.workflows.slice(0, CONFIG.userProfileMaxWorkflows);
260
259
  }
261
- if (updates.skillLevel) {
262
- merged.skillLevel = {
263
- overall: updates.skillLevel.overall || merged.skillLevel.overall,
264
- domains: { ...merged.skillLevel.domains, ...safeObject(updates.skillLevel.domains, {}) },
265
- };
266
- }
267
260
  return merged;
268
261
  }
269
262
  }
@@ -32,6 +32,8 @@ export declare class UserPromptManager {
32
32
  linkMemoryToPrompt(promptId: string, memoryId: string): void;
33
33
  getPromptById(promptId: string): UserPrompt | null;
34
34
  getCapturedPrompts(projectPath?: string): UserPrompt[];
35
+ searchPrompts(query: string, projectPath?: string, limit?: number): UserPrompt[];
36
+ getPromptsByIds(ids: string[]): UserPrompt[];
35
37
  private rowToPrompt;
36
38
  }
37
39
  export declare const userPromptManager: UserPromptManager;
@@ -1 +1 @@
1
- {"version":3,"file":"user-prompt-manager.d.ts","sourceRoot":"","sources":["../../../src/services/user-prompt/user-prompt-manager.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,OAAO,CAAC;IAClB,oBAAoB,EAAE,OAAO,CAAC;IAC9B,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/B;AAED,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,EAAE,CAAW;IACrB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;;IAQhC,OAAO,CAAC,YAAY;IA+BpB,UAAU,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM;IAa9F,uBAAuB,CAAC,SAAS,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI;IAc7D,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAKpC,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAKtC,sBAAsB,IAAI,MAAM;IAMhC,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU,EAAE;IAYjD,sBAAsB,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,IAAI;IAUjD,8BAA8B,IAAI,MAAM;IAQxC,yBAAyB,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU,EAAE;IAYtD,0BAA0B,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAKlD,kCAAkC,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,IAAI;IAU7D,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,eAAe,EAAE,MAAM,EAAE,CAAA;KAAE;IAiBpF,kBAAkB,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI;IAK5D,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI;IAOlD,kBAAkB,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,UAAU,EAAE;IAgBtD,OAAO,CAAC,WAAW;CAapB;AAED,eAAO,MAAM,iBAAiB,mBAA0B,CAAC"}
1
+ {"version":3,"file":"user-prompt-manager.d.ts","sourceRoot":"","sources":["../../../src/services/user-prompt/user-prompt-manager.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,OAAO,CAAC;IAClB,oBAAoB,EAAE,OAAO,CAAC;IAC9B,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/B;AAED,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,EAAE,CAAW;IACrB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;;IAQhC,OAAO,CAAC,YAAY;IA+BpB,UAAU,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM;IAa9F,uBAAuB,CAAC,SAAS,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI;IAc7D,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAKpC,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAKtC,sBAAsB,IAAI,MAAM;IAMhC,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU,EAAE;IAYjD,sBAAsB,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,IAAI;IAUjD,8BAA8B,IAAI,MAAM;IAQxC,yBAAyB,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU,EAAE;IAYtD,0BAA0B,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAKlD,kCAAkC,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,IAAI;IAU7D,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,eAAe,EAAE,MAAM,EAAE,CAAA;KAAE;IAiBpF,kBAAkB,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI;IAK5D,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI;IAOlD,kBAAkB,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,UAAU,EAAE;IAgBtD,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,EAAE,KAAK,GAAE,MAAW,GAAG,UAAU,EAAE;IAiBpF,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,UAAU,EAAE;IAQ5C,OAAO,CAAC,WAAW;CAapB;AAED,eAAO,MAAM,iBAAiB,mBAA0B,CAAC"}
@@ -147,6 +147,27 @@ export class UserPromptManager {
147
147
  const rows = stmt.all(...params);
148
148
  return rows.map((row) => this.rowToPrompt(row));
149
149
  }
150
+ searchPrompts(query, projectPath, limit = 20) {
151
+ let sql = `SELECT * FROM user_prompts WHERE content LIKE ? AND captured = 1`;
152
+ const params = [`%${query}%`];
153
+ if (projectPath) {
154
+ sql += ` AND project_path = ?`;
155
+ params.push(projectPath);
156
+ }
157
+ sql += ` ORDER BY created_at DESC LIMIT ?`;
158
+ params.push(limit);
159
+ const stmt = this.db.prepare(sql);
160
+ const rows = stmt.all(...params);
161
+ return rows.map((row) => this.rowToPrompt(row));
162
+ }
163
+ getPromptsByIds(ids) {
164
+ if (ids.length === 0)
165
+ return [];
166
+ const placeholders = ids.map(() => "?").join(",");
167
+ const stmt = this.db.prepare(`SELECT * FROM user_prompts WHERE id IN (${placeholders})`);
168
+ const rows = stmt.all(...ids);
169
+ return rows.map((row) => this.rowToPrompt(row));
170
+ }
150
171
  rowToPrompt(row) {
151
172
  return {
152
173
  id: row.id,