opencode-mem 2.3.1 → 2.3.3

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.
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAyXA,eAAO,MAAM,MAAM;;;;;;;;;;;;;;;;oBAwBb,aAAa,GACb,kBAAkB,GAClB,WAAW;;;;;;;;;;;;;;;;;;;CAyBhB,CAAC;AAEF,wBAAgB,YAAY,IAAI,OAAO,CAEtC"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAyXA,eAAO,MAAM,MAAM;;;;;;;;;;;;;;;;oBA0Bb,aAAa,GACb,kBAAkB,GAClB,WAAW;;;;;;;;;;;;;;;;;;;CAyBhB,CAAC;AAEF,wBAAgB,YAAY,IAAI,OAAO,CAEtC"}
package/dist/config.js CHANGED
@@ -309,7 +309,9 @@ function getEmbeddingDimensions(model) {
309
309
  }
310
310
  export const CONFIG = {
311
311
  storagePath: expandPath(fileConfig.storagePath ?? DEFAULTS.storagePath),
312
- customSqlitePath: fileConfig.customSqlitePath ? expandPath(fileConfig.customSqlitePath) : undefined,
312
+ customSqlitePath: fileConfig.customSqlitePath
313
+ ? expandPath(fileConfig.customSqlitePath)
314
+ : undefined,
313
315
  embeddingModel: fileConfig.embeddingModel ?? DEFAULTS.embeddingModel,
314
316
  embeddingDimensions: fileConfig.embeddingDimensions ??
315
317
  getEmbeddingDimensions(fileConfig.embeddingModel ?? DEFAULTS.embeddingModel),
@@ -8,6 +8,5 @@ export declare class AnthropicMessagesProvider extends BaseAIProvider {
8
8
  supportsSession(): boolean;
9
9
  executeToolCall(systemPrompt: string, userPrompt: string, toolSchema: ChatCompletionTool, sessionId: string): Promise<ToolCallResult>;
10
10
  private extractToolUse;
11
- private validateResponse;
12
11
  }
13
12
  //# sourceMappingURL=anthropic-messages.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"anthropic-messages.d.ts","sourceRoot":"","sources":["../../../../src/services/ai/providers/anthropic-messages.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,KAAK,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACzE,OAAO,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAC;AACpE,OAAO,EAAuB,KAAK,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AA2BvF,qBAAa,yBAA0B,SAAQ,cAAc;IAC3D,OAAO,CAAC,gBAAgB,CAAmB;gBAE/B,MAAM,EAAE,GAAG,EAAE,gBAAgB,EAAE,gBAAgB;IAK3D,eAAe,IAAI,MAAM;IAIzB,eAAe,IAAI,OAAO;IAIpB,eAAe,CACnB,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,kBAAkB,EAC9B,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,cAAc,CAAC;IAmJ1B,OAAO,CAAC,cAAc;IActB,OAAO,CAAC,gBAAgB;CAsBzB"}
1
+ {"version":3,"file":"anthropic-messages.d.ts","sourceRoot":"","sources":["../../../../src/services/ai/providers/anthropic-messages.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,KAAK,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACzE,OAAO,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAC;AACpE,OAAO,EAAuB,KAAK,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AA4BvF,qBAAa,yBAA0B,SAAQ,cAAc;IAC3D,OAAO,CAAC,gBAAgB,CAAmB;gBAE/B,MAAM,EAAE,GAAG,EAAE,gBAAgB,EAAE,gBAAgB;IAK3D,eAAe,IAAI,MAAM;IAIzB,eAAe,IAAI,OAAO;IAIpB,eAAe,CACnB,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,kBAAkB,EAC9B,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,cAAc,CAAC;IA2K1B,OAAO,CAAC,cAAc;CAavB"}
@@ -2,6 +2,7 @@ import { BaseAIProvider } from "./base-provider.js";
2
2
  import { AISessionManager } from "../session/ai-session-manager.js";
3
3
  import { ToolSchemaConverter } from "../tools/tool-schema.js";
4
4
  import { log } from "../../logger.js";
5
+ import { UserProfileValidator } from "../validators/user-profile-validator.js";
5
6
  export class AnthropicMessagesProvider extends BaseAIProvider {
6
7
  aiSessionManager;
7
8
  constructor(config, aiSessionManager) {
@@ -95,11 +96,35 @@ export class AnthropicMessagesProvider extends BaseAIProvider {
95
96
  });
96
97
  const toolUse = this.extractToolUse(data, toolSchema.function.name);
97
98
  if (toolUse) {
98
- return {
99
- success: true,
100
- data: this.validateResponse(toolUse),
101
- iterations,
102
- };
99
+ try {
100
+ const result = UserProfileValidator.validate(toolUse);
101
+ if (!result.valid) {
102
+ throw new Error(result.errors.join(", "));
103
+ }
104
+ return {
105
+ success: true,
106
+ data: result.data,
107
+ iterations,
108
+ };
109
+ }
110
+ catch (validationError) {
111
+ const errorStack = validationError instanceof Error ? validationError.stack : undefined;
112
+ log("Anthropic tool response validation failed", {
113
+ error: String(validationError),
114
+ stack: errorStack,
115
+ errorType: validationError instanceof Error
116
+ ? validationError.constructor.name
117
+ : typeof validationError,
118
+ toolName: toolSchema.function.name,
119
+ iteration: iterations,
120
+ rawData: JSON.stringify(toolUse).slice(0, 500),
121
+ });
122
+ return {
123
+ success: false,
124
+ error: `Validation failed: ${String(validationError)}`,
125
+ iterations,
126
+ };
127
+ }
103
128
  }
104
129
  if (data.stop_reason === "end_turn") {
105
130
  const retrySequence = this.aiSessionManager.getLastSequence(session.id) + 1;
@@ -149,22 +174,4 @@ export class AnthropicMessagesProvider extends BaseAIProvider {
149
174
  }
150
175
  return null;
151
176
  }
152
- validateResponse(data) {
153
- if (!data || typeof data !== "object") {
154
- throw new Error("Response is not an object");
155
- }
156
- if (Array.isArray(data)) {
157
- throw new Error("Response cannot be an array");
158
- }
159
- const keys = Object.keys(data);
160
- if (keys.length === 0) {
161
- throw new Error("Response object is empty");
162
- }
163
- for (const key of keys) {
164
- if (data[key] === undefined || data[key] === null) {
165
- throw new Error(`Response field '${key}' is null or undefined`);
166
- }
167
- }
168
- return data;
169
- }
170
177
  }
@@ -7,6 +7,5 @@ export declare class OpenAIChatCompletionProvider extends BaseAIProvider {
7
7
  getProviderName(): string;
8
8
  supportsSession(): boolean;
9
9
  executeToolCall(systemPrompt: string, userPrompt: string, toolSchema: ChatCompletionTool, sessionId: string): Promise<ToolCallResult>;
10
- private validateResponse;
11
10
  }
12
11
  //# sourceMappingURL=openai-chat-completion.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"openai-chat-completion.d.ts","sourceRoot":"","sources":["../../../../src/services/ai/providers/openai-chat-completion.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,KAAK,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACzE,OAAO,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAC;AACpE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAkBlE,qBAAa,4BAA6B,SAAQ,cAAc;IAC9D,OAAO,CAAC,gBAAgB,CAAmB;gBAE/B,MAAM,EAAE,GAAG,EAAE,gBAAgB,EAAE,gBAAgB;IAK3D,eAAe,IAAI,MAAM;IAIzB,eAAe,IAAI,OAAO;IAIpB,eAAe,CACnB,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,kBAAkB,EAC9B,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,cAAc,CAAC;IA2K1B,OAAO,CAAC,gBAAgB;CAsBzB"}
1
+ {"version":3,"file":"openai-chat-completion.d.ts","sourceRoot":"","sources":["../../../../src/services/ai/providers/openai-chat-completion.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,KAAK,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACzE,OAAO,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAC;AACpE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAmBlE,qBAAa,4BAA6B,SAAQ,cAAc;IAC9D,OAAO,CAAC,gBAAgB,CAAmB;gBAE/B,MAAM,EAAE,GAAG,EAAE,gBAAgB,EAAE,gBAAgB;IAK3D,eAAe,IAAI,MAAM;IAIzB,eAAe,IAAI,OAAO;IAIpB,eAAe,CACnB,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,kBAAkB,EAC9B,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,cAAc,CAAC;CAmM3B"}
@@ -1,6 +1,7 @@
1
1
  import { BaseAIProvider } from "./base-provider.js";
2
2
  import { AISessionManager } from "../session/ai-session-manager.js";
3
3
  import { log } from "../../logger.js";
4
+ import { UserProfileValidator } from "../validators/user-profile-validator.js";
4
5
  export class OpenAIChatCompletionProvider extends BaseAIProvider {
5
6
  aiSessionManager;
6
7
  constructor(config, aiSessionManager) {
@@ -114,12 +115,36 @@ export class OpenAIChatCompletionProvider extends BaseAIProvider {
114
115
  if (choice.message.tool_calls && choice.message.tool_calls.length > 0) {
115
116
  const toolCall = choice.message.tool_calls[0];
116
117
  if (toolCall && toolCall.function.name === toolSchema.function.name) {
117
- const parsed = JSON.parse(toolCall.function.arguments);
118
- return {
119
- success: true,
120
- data: this.validateResponse(parsed),
121
- iterations,
122
- };
118
+ try {
119
+ const parsed = JSON.parse(toolCall.function.arguments);
120
+ const result = UserProfileValidator.validate(parsed);
121
+ if (!result.valid) {
122
+ throw new Error(result.errors.join(", "));
123
+ }
124
+ return {
125
+ success: true,
126
+ data: result.data,
127
+ iterations,
128
+ };
129
+ }
130
+ catch (validationError) {
131
+ const errorStack = validationError instanceof Error ? validationError.stack : undefined;
132
+ log("OpenAI tool response validation failed", {
133
+ error: String(validationError),
134
+ stack: errorStack,
135
+ errorType: validationError instanceof Error
136
+ ? validationError.constructor.name
137
+ : typeof validationError,
138
+ toolName: toolSchema.function.name,
139
+ iteration: iterations,
140
+ rawArguments: toolCall.function.arguments.slice(0, 500),
141
+ });
142
+ return {
143
+ success: false,
144
+ error: `Validation failed: ${String(validationError)}`,
145
+ iterations,
146
+ };
147
+ }
123
148
  }
124
149
  }
125
150
  const retrySequence = this.aiSessionManager.getLastSequence(session.id) + 1;
@@ -154,22 +179,4 @@ export class OpenAIChatCompletionProvider extends BaseAIProvider {
154
179
  iterations,
155
180
  };
156
181
  }
157
- validateResponse(data) {
158
- if (!data || typeof data !== "object") {
159
- throw new Error("Response is not an object");
160
- }
161
- if (Array.isArray(data)) {
162
- throw new Error("Response cannot be an array");
163
- }
164
- const keys = Object.keys(data);
165
- if (keys.length === 0) {
166
- throw new Error("Response object is empty");
167
- }
168
- for (const key of keys) {
169
- if (data[key] === undefined || data[key] === null) {
170
- throw new Error(`Response field '${key}' is null or undefined`);
171
- }
172
- }
173
- return data;
174
- }
175
182
  }
@@ -0,0 +1,14 @@
1
+ import type { UserProfileData } from "../../user-profile/types.js";
2
+ export interface ValidationResult {
3
+ valid: boolean;
4
+ errors: string[];
5
+ data?: UserProfileData;
6
+ }
7
+ export declare class UserProfileValidator {
8
+ static validate(data: any): ValidationResult;
9
+ private static validatePreferences;
10
+ private static validatePatterns;
11
+ private static validateWorkflows;
12
+ private static validateSkillLevel;
13
+ }
14
+ //# sourceMappingURL=user-profile-validator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"user-profile-validator.d.ts","sourceRoot":"","sources":["../../../../src/services/ai/validators/user-profile-validator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAEnE,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,IAAI,CAAC,EAAE,eAAe,CAAC;CACxB;AAED,qBAAa,oBAAoB;IAC/B,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE,GAAG,GAAG,gBAAgB;IA0C5C,OAAO,CAAC,MAAM,CAAC,mBAAmB;IA6BlC,OAAO,CAAC,MAAM,CAAC,gBAAgB;IAqB/B,OAAO,CAAC,MAAM,CAAC,iBAAiB;IAuBhC,OAAO,CAAC,MAAM,CAAC,kBAAkB;CAalC"}
@@ -0,0 +1,128 @@
1
+ export class UserProfileValidator {
2
+ static validate(data) {
3
+ const errors = [];
4
+ if (!data || typeof data !== "object") {
5
+ return { valid: false, errors: ["Response is not an object"] };
6
+ }
7
+ if (Array.isArray(data)) {
8
+ return { valid: false, errors: ["Response cannot be an array"] };
9
+ }
10
+ const keys = Object.keys(data);
11
+ if (keys.length === 0) {
12
+ return { valid: false, errors: ["Response object is empty"] };
13
+ }
14
+ for (const key of keys) {
15
+ if (data[key] === undefined || data[key] === null) {
16
+ errors.push(`Field '${key}' is null or undefined`);
17
+ }
18
+ }
19
+ if (errors.length > 0) {
20
+ return { valid: false, errors };
21
+ }
22
+ if (data.preferences) {
23
+ const prefErrors = this.validatePreferences(data.preferences);
24
+ errors.push(...prefErrors);
25
+ }
26
+ if (data.patterns) {
27
+ const patternErrors = this.validatePatterns(data.patterns);
28
+ errors.push(...patternErrors);
29
+ }
30
+ if (data.workflows) {
31
+ const workflowErrors = this.validateWorkflows(data.workflows);
32
+ errors.push(...workflowErrors);
33
+ }
34
+ if (data.skillLevel) {
35
+ const skillErrors = this.validateSkillLevel(data.skillLevel);
36
+ errors.push(...skillErrors);
37
+ }
38
+ if (errors.length > 0) {
39
+ return { valid: false, errors };
40
+ }
41
+ return { valid: true, errors: [], data: data };
42
+ }
43
+ static validatePreferences(preferences) {
44
+ const errors = [];
45
+ if (!Array.isArray(preferences)) {
46
+ return ["preferences must be an array"];
47
+ }
48
+ for (let i = 0; i < preferences.length; i++) {
49
+ const pref = preferences[i];
50
+ if (!pref || typeof pref !== "object") {
51
+ errors.push(`preferences[${i}] is not an object`);
52
+ continue;
53
+ }
54
+ if (!pref.category || typeof pref.category !== "string") {
55
+ errors.push(`preferences[${i}].category is missing or invalid`);
56
+ }
57
+ if (!pref.description || typeof pref.description !== "string") {
58
+ errors.push(`preferences[${i}].description is missing or invalid`);
59
+ }
60
+ if (typeof pref.confidence !== "number") {
61
+ errors.push(`preferences[${i}].confidence is missing or invalid`);
62
+ }
63
+ if (!Array.isArray(pref.evidence)) {
64
+ errors.push(`preferences[${i}].evidence must be an array`);
65
+ }
66
+ else if (pref.evidence.length === 0) {
67
+ errors.push(`preferences[${i}].evidence cannot be empty`);
68
+ }
69
+ }
70
+ return errors;
71
+ }
72
+ static validatePatterns(patterns) {
73
+ const errors = [];
74
+ if (!Array.isArray(patterns)) {
75
+ return ["patterns must be an array"];
76
+ }
77
+ for (let i = 0; i < patterns.length; i++) {
78
+ const pattern = patterns[i];
79
+ if (!pattern || typeof pattern !== "object") {
80
+ errors.push(`patterns[${i}] is not an object`);
81
+ continue;
82
+ }
83
+ if (!pattern.category || typeof pattern.category !== "string") {
84
+ errors.push(`patterns[${i}].category is missing or invalid`);
85
+ }
86
+ if (!pattern.description || typeof pattern.description !== "string") {
87
+ errors.push(`patterns[${i}].description is missing or invalid`);
88
+ }
89
+ }
90
+ return errors;
91
+ }
92
+ static validateWorkflows(workflows) {
93
+ const errors = [];
94
+ if (!Array.isArray(workflows)) {
95
+ return ["workflows must be an array"];
96
+ }
97
+ for (let i = 0; i < workflows.length; i++) {
98
+ const workflow = workflows[i];
99
+ if (!workflow || typeof workflow !== "object") {
100
+ errors.push(`workflows[${i}] is not an object`);
101
+ continue;
102
+ }
103
+ if (!workflow.description || typeof workflow.description !== "string") {
104
+ errors.push(`workflows[${i}].description is missing or invalid`);
105
+ }
106
+ if (!Array.isArray(workflow.steps)) {
107
+ errors.push(`workflows[${i}].steps must be an array`);
108
+ }
109
+ else if (workflow.steps.length === 0) {
110
+ errors.push(`workflows[${i}].steps cannot be empty`);
111
+ }
112
+ }
113
+ return errors;
114
+ }
115
+ static validateSkillLevel(skillLevel) {
116
+ const errors = [];
117
+ if (typeof skillLevel !== "object") {
118
+ return ["skillLevel must be an object"];
119
+ }
120
+ if (!skillLevel.overall || typeof skillLevel.overall !== "string") {
121
+ errors.push("skillLevel.overall is missing or invalid");
122
+ }
123
+ if (!skillLevel.domains || typeof skillLevel.domains !== "object") {
124
+ errors.push("skillLevel.domains must be an object");
125
+ }
126
+ return errors;
127
+ }
128
+ }
@@ -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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"}
@@ -38,6 +38,19 @@ function extractScopeFromTag(tag) {
38
38
  }
39
39
  return { scope: "project", hash: tag };
40
40
  }
41
+ function getProjectPathFromTag(tag) {
42
+ const projectShards = shardManager.getAllShards("project", "");
43
+ for (const shard of projectShards) {
44
+ const db = connectionManager.getConnection(shard.dbPath);
45
+ const tags = vectorSearch.getDistinctTags(db);
46
+ for (const t of tags) {
47
+ if (t.container_tag === tag && t.project_path) {
48
+ return t.project_path;
49
+ }
50
+ }
51
+ }
52
+ return undefined;
53
+ }
41
54
  export async function handleListTags() {
42
55
  try {
43
56
  await embeddingService.warmup();
@@ -120,7 +133,8 @@ export async function handleListMemories(tag, page = 1, pageSize = 20, includePr
120
133
  });
121
134
  let timeline = memoriesWithType;
122
135
  if (includePrompts) {
123
- const prompts = userPromptManager.getCapturedPrompts(tag);
136
+ const projectPath = tag ? getProjectPathFromTag(tag) : undefined;
137
+ const prompts = userPromptManager.getCapturedPrompts(projectPath);
124
138
  const promptsWithType = prompts.map((p) => ({
125
139
  type: "prompt",
126
140
  id: p.id,
@@ -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;AAMtC,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,WAAW,CAAoC;IACvD,OAAO,CAAC,gBAAgB,CAAS;IAEjC,OAAO,CAAC,eAAe;IAyEvB,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"}
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;AAMtC,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,WAAW,CAAoC;IACvD,OAAO,CAAC,gBAAgB,CAAS;IAEjC,OAAO,CAAC,eAAe;IAqEvB,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"}
@@ -23,8 +23,7 @@ export class ConnectionManager {
23
23
  log("Using custom SQLite library", { path: customPath });
24
24
  }
25
25
  catch (error) {
26
- throw new Error(`Failed to load custom SQLite library: ${error}\n` +
27
- `Path: ${customPath}`);
26
+ throw new Error(`Failed to load custom SQLite library: ${error}\n` + `Path: ${customPath}`);
28
27
  }
29
28
  }
30
29
  else {
@@ -45,8 +44,7 @@ export class ConnectionManager {
45
44
  log("Auto-detected and using Homebrew SQLite", { path: foundPath });
46
45
  }
47
46
  catch (error) {
48
- throw new Error(`Failed to load Homebrew SQLite: ${error}\n` +
49
- `Path: ${foundPath}`);
47
+ throw new Error(`Failed to load Homebrew SQLite: ${error}\n` + `Path: ${foundPath}`);
50
48
  }
51
49
  }
52
50
  else {
@@ -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,0BAA0B,CAC9C,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,CAmFf"}
@@ -44,7 +44,12 @@ export async function performUserProfileLearning(ctx, directory) {
44
44
  .catch(() => { });
45
45
  }
46
46
  catch (error) {
47
- log("User memory learning error", { error: String(error) });
47
+ const errorStack = error instanceof Error ? error.stack : undefined;
48
+ log("User memory learning error", {
49
+ error: String(error),
50
+ stack: errorStack,
51
+ errorType: error instanceof Error ? error.constructor.name : typeof error,
52
+ });
48
53
  await ctx.client?.tui
49
54
  .showToast({
50
55
  body: {
@@ -0,0 +1,3 @@
1
+ export declare const safeArray: <T>(arr: T[] | null | undefined) => T[];
2
+ export declare const safeObject: <T extends object>(obj: T | null | undefined, fallback: T) => T;
3
+ //# sourceMappingURL=profile-utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"profile-utils.d.ts","sourceRoot":"","sources":["../../../src/services/user-profile/profile-utils.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,SAAS,GAAI,CAAC,EAAE,KAAK,CAAC,EAAE,GAAG,IAAI,GAAG,SAAS,KAAG,CAAC,EAAe,CAAC;AAC5E,eAAO,MAAM,UAAU,GAAI,CAAC,SAAS,MAAM,EAAE,KAAK,CAAC,GAAG,IAAI,GAAG,SAAS,EAAE,UAAU,CAAC,KAAG,CACrE,CAAC"}
@@ -0,0 +1,2 @@
1
+ export const safeArray = (arr) => arr ?? [];
2
+ export const safeObject = (obj, fallback) => obj ?? fallback;
@@ -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;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
+ {"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"}
@@ -2,6 +2,7 @@ import { Database } from "bun:sqlite";
2
2
  import { join } from "node:path";
3
3
  import { connectionManager } from "../sqlite/connection-manager.js";
4
4
  import { CONFIG } from "../../config.js";
5
+ import { safeArray, safeObject } from "./profile-utils.js";
5
6
  const USER_PROFILES_DB_NAME = "user-profiles.db";
6
7
  export class UserProfileManager {
7
8
  db;
@@ -190,10 +191,10 @@ export class UserProfileManager {
190
191
  }
191
192
  mergeProfileData(existing, updates) {
192
193
  const merged = {
193
- preferences: [...existing.preferences],
194
- patterns: [...existing.patterns],
195
- workflows: [...existing.workflows],
196
- skillLevel: { ...existing.skillLevel },
194
+ preferences: safeArray(existing?.preferences),
195
+ patterns: safeArray(existing?.patterns),
196
+ workflows: safeArray(existing?.workflows),
197
+ skillLevel: safeObject(existing?.skillLevel, { overall: "intermediate", domains: {} }),
197
198
  };
198
199
  if (updates.preferences) {
199
200
  for (const newPref of updates.preferences) {
@@ -204,7 +205,9 @@ export class UserProfileManager {
204
205
  merged.preferences[existingIndex] = {
205
206
  ...newPref,
206
207
  confidence: Math.min(1, existing.confidence + 0.1),
207
- evidence: [...new Set([...existing.evidence, ...newPref.evidence])].slice(0, 5),
208
+ evidence: [
209
+ ...new Set([...safeArray(existing.evidence), ...safeArray(newPref.evidence)]),
210
+ ].slice(0, 5),
208
211
  lastUpdated: Date.now(),
209
212
  };
210
213
  }
@@ -258,7 +261,7 @@ export class UserProfileManager {
258
261
  if (updates.skillLevel) {
259
262
  merged.skillLevel = {
260
263
  overall: updates.skillLevel.overall || merged.skillLevel.overall,
261
- domains: { ...merged.skillLevel.domains, ...updates.skillLevel.domains },
264
+ domains: { ...merged.skillLevel.domains, ...safeObject(updates.skillLevel.domains, {}) },
262
265
  };
263
266
  }
264
267
  return merged;
package/dist/web/app.js CHANGED
@@ -938,6 +938,10 @@ document.addEventListener("DOMContentLoaded", async () => {
938
938
  document.getElementById("tag-filter").addEventListener("change", () => {
939
939
  state.selectedTag = document.getElementById("tag-filter").value;
940
940
  state.currentPage = 1;
941
+ state.isSearching = false;
942
+ state.searchQuery = "";
943
+ document.getElementById("search-input").value = "";
944
+ document.getElementById("clear-search-btn").classList.add("hidden");
941
945
  loadMemories();
942
946
  });
943
947
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-mem",
3
- "version": "2.3.1",
3
+ "version": "2.3.3",
4
4
  "description": "OpenCode plugin that gives coding agents persistent memory using local vector database",
5
5
  "type": "module",
6
6
  "main": "dist/plugin.js",