@xiaoxiamimengfb/my-opencode-mem 2.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.
Files changed (152) hide show
  1. package/README.md +155 -0
  2. package/dist/config.d.ts +58 -0
  3. package/dist/config.d.ts.map +1 -0
  4. package/dist/config.js +411 -0
  5. package/dist/index.d.ts +3 -0
  6. package/dist/index.d.ts.map +1 -0
  7. package/dist/index.js +427 -0
  8. package/dist/plugin.d.ts +5 -0
  9. package/dist/plugin.d.ts.map +1 -0
  10. package/dist/plugin.js +4 -0
  11. package/dist/services/ai/ai-provider-factory.d.ts +8 -0
  12. package/dist/services/ai/ai-provider-factory.d.ts.map +1 -0
  13. package/dist/services/ai/ai-provider-factory.js +28 -0
  14. package/dist/services/ai/opencode-provider.d.ts +30 -0
  15. package/dist/services/ai/opencode-provider.d.ts.map +1 -0
  16. package/dist/services/ai/opencode-provider.js +332 -0
  17. package/dist/services/ai/provider-config.d.ts +17 -0
  18. package/dist/services/ai/provider-config.d.ts.map +1 -0
  19. package/dist/services/ai/provider-config.js +14 -0
  20. package/dist/services/ai/providers/anthropic-messages.d.ts +12 -0
  21. package/dist/services/ai/providers/anthropic-messages.d.ts.map +1 -0
  22. package/dist/services/ai/providers/anthropic-messages.js +184 -0
  23. package/dist/services/ai/providers/base-provider.d.ts +25 -0
  24. package/dist/services/ai/providers/base-provider.d.ts.map +1 -0
  25. package/dist/services/ai/providers/base-provider.js +23 -0
  26. package/dist/services/ai/providers/google-gemini.d.ts +16 -0
  27. package/dist/services/ai/providers/google-gemini.d.ts.map +1 -0
  28. package/dist/services/ai/providers/google-gemini.js +228 -0
  29. package/dist/services/ai/providers/openai-chat-completion.d.ts +13 -0
  30. package/dist/services/ai/providers/openai-chat-completion.d.ts.map +1 -0
  31. package/dist/services/ai/providers/openai-chat-completion.js +277 -0
  32. package/dist/services/ai/providers/openai-responses.d.ts +14 -0
  33. package/dist/services/ai/providers/openai-responses.d.ts.map +1 -0
  34. package/dist/services/ai/providers/openai-responses.js +182 -0
  35. package/dist/services/ai/session/ai-session-manager.d.ts +21 -0
  36. package/dist/services/ai/session/ai-session-manager.d.ts.map +1 -0
  37. package/dist/services/ai/session/ai-session-manager.js +166 -0
  38. package/dist/services/ai/session/session-types.d.ts +43 -0
  39. package/dist/services/ai/session/session-types.d.ts.map +1 -0
  40. package/dist/services/ai/session/session-types.js +1 -0
  41. package/dist/services/ai/tools/tool-schema.d.ts +41 -0
  42. package/dist/services/ai/tools/tool-schema.d.ts.map +1 -0
  43. package/dist/services/ai/tools/tool-schema.js +24 -0
  44. package/dist/services/ai/validators/user-profile-validator.d.ts +13 -0
  45. package/dist/services/ai/validators/user-profile-validator.d.ts.map +1 -0
  46. package/dist/services/ai/validators/user-profile-validator.js +111 -0
  47. package/dist/services/api-handlers.d.ts +164 -0
  48. package/dist/services/api-handlers.d.ts.map +1 -0
  49. package/dist/services/api-handlers.js +901 -0
  50. package/dist/services/auto-capture.d.ts +3 -0
  51. package/dist/services/auto-capture.d.ts.map +1 -0
  52. package/dist/services/auto-capture.js +306 -0
  53. package/dist/services/cleanup-service.d.ts +23 -0
  54. package/dist/services/cleanup-service.d.ts.map +1 -0
  55. package/dist/services/cleanup-service.js +102 -0
  56. package/dist/services/client.d.ts +118 -0
  57. package/dist/services/client.d.ts.map +1 -0
  58. package/dist/services/client.js +251 -0
  59. package/dist/services/context.d.ts +11 -0
  60. package/dist/services/context.d.ts.map +1 -0
  61. package/dist/services/context.js +24 -0
  62. package/dist/services/deduplication-service.d.ts +30 -0
  63. package/dist/services/deduplication-service.d.ts.map +1 -0
  64. package/dist/services/deduplication-service.js +124 -0
  65. package/dist/services/embedding.d.ts +15 -0
  66. package/dist/services/embedding.d.ts.map +1 -0
  67. package/dist/services/embedding.js +106 -0
  68. package/dist/services/jsonc.d.ts +7 -0
  69. package/dist/services/jsonc.d.ts.map +1 -0
  70. package/dist/services/jsonc.js +76 -0
  71. package/dist/services/language-detector.d.ts +3 -0
  72. package/dist/services/language-detector.d.ts.map +1 -0
  73. package/dist/services/language-detector.js +16 -0
  74. package/dist/services/logger.d.ts +2 -0
  75. package/dist/services/logger.d.ts.map +1 -0
  76. package/dist/services/logger.js +51 -0
  77. package/dist/services/migration-service.d.ts +42 -0
  78. package/dist/services/migration-service.d.ts.map +1 -0
  79. package/dist/services/migration-service.js +250 -0
  80. package/dist/services/privacy.d.ts +3 -0
  81. package/dist/services/privacy.d.ts.map +1 -0
  82. package/dist/services/privacy.js +7 -0
  83. package/dist/services/secret-resolver.d.ts +2 -0
  84. package/dist/services/secret-resolver.d.ts.map +1 -0
  85. package/dist/services/secret-resolver.js +55 -0
  86. package/dist/services/sqlite/connection-manager.d.ts +13 -0
  87. package/dist/services/sqlite/connection-manager.d.ts.map +1 -0
  88. package/dist/services/sqlite/connection-manager.js +74 -0
  89. package/dist/services/sqlite/shard-manager.d.ts +23 -0
  90. package/dist/services/sqlite/shard-manager.d.ts.map +1 -0
  91. package/dist/services/sqlite/shard-manager.js +288 -0
  92. package/dist/services/sqlite/sqlite-bootstrap.d.ts +2 -0
  93. package/dist/services/sqlite/sqlite-bootstrap.d.ts.map +1 -0
  94. package/dist/services/sqlite/sqlite-bootstrap.js +8 -0
  95. package/dist/services/sqlite/types.d.ts +42 -0
  96. package/dist/services/sqlite/types.d.ts.map +1 -0
  97. package/dist/services/sqlite/types.js +1 -0
  98. package/dist/services/sqlite/vector-search.d.ts +29 -0
  99. package/dist/services/sqlite/vector-search.d.ts.map +1 -0
  100. package/dist/services/sqlite/vector-search.js +268 -0
  101. package/dist/services/tags.d.ts +24 -0
  102. package/dist/services/tags.d.ts.map +1 -0
  103. package/dist/services/tags.js +146 -0
  104. package/dist/services/user-memory-learning.d.ts +3 -0
  105. package/dist/services/user-memory-learning.d.ts.map +1 -0
  106. package/dist/services/user-memory-learning.js +231 -0
  107. package/dist/services/user-profile/profile-context.d.ts +2 -0
  108. package/dist/services/user-profile/profile-context.d.ts.map +1 -0
  109. package/dist/services/user-profile/profile-context.js +40 -0
  110. package/dist/services/user-profile/profile-utils.d.ts +3 -0
  111. package/dist/services/user-profile/profile-utils.d.ts.map +1 -0
  112. package/dist/services/user-profile/profile-utils.js +45 -0
  113. package/dist/services/user-profile/types.d.ts +46 -0
  114. package/dist/services/user-profile/types.d.ts.map +1 -0
  115. package/dist/services/user-profile/types.js +1 -0
  116. package/dist/services/user-profile/user-profile-manager.d.ts +23 -0
  117. package/dist/services/user-profile/user-profile-manager.d.ts.map +1 -0
  118. package/dist/services/user-profile/user-profile-manager.js +292 -0
  119. package/dist/services/user-prompt/user-prompt-manager.d.ts +41 -0
  120. package/dist/services/user-prompt/user-prompt-manager.d.ts.map +1 -0
  121. package/dist/services/user-prompt/user-prompt-manager.js +192 -0
  122. package/dist/services/vector-backends/backend-factory.d.ts +3 -0
  123. package/dist/services/vector-backends/backend-factory.d.ts.map +1 -0
  124. package/dist/services/vector-backends/backend-factory.js +104 -0
  125. package/dist/services/vector-backends/exact-scan-backend.d.ts +39 -0
  126. package/dist/services/vector-backends/exact-scan-backend.d.ts.map +1 -0
  127. package/dist/services/vector-backends/exact-scan-backend.js +63 -0
  128. package/dist/services/vector-backends/types.d.ts +51 -0
  129. package/dist/services/vector-backends/types.d.ts.map +1 -0
  130. package/dist/services/vector-backends/types.js +1 -0
  131. package/dist/services/vector-backends/usearch-backend.d.ts +47 -0
  132. package/dist/services/vector-backends/usearch-backend.d.ts.map +1 -0
  133. package/dist/services/vector-backends/usearch-backend.js +174 -0
  134. package/dist/services/web-server-worker.d.ts +2 -0
  135. package/dist/services/web-server-worker.d.ts.map +1 -0
  136. package/dist/services/web-server-worker.js +283 -0
  137. package/dist/services/web-server.d.ts +31 -0
  138. package/dist/services/web-server.d.ts.map +1 -0
  139. package/dist/services/web-server.js +356 -0
  140. package/dist/types/index.d.ts +19 -0
  141. package/dist/types/index.d.ts.map +1 -0
  142. package/dist/types/index.js +1 -0
  143. package/dist/web/app.d.ts +2 -0
  144. package/dist/web/app.d.ts.map +1 -0
  145. package/dist/web/app.js +1194 -0
  146. package/dist/web/favicon.ico +0 -0
  147. package/dist/web/i18n.d.ts +2 -0
  148. package/dist/web/i18n.d.ts.map +1 -0
  149. package/dist/web/i18n.js +265 -0
  150. package/dist/web/index.html +284 -0
  151. package/dist/web/styles.css +1631 -0
  152. package/package.json +71 -0
@@ -0,0 +1,146 @@
1
+ import { createHash } from "node:crypto";
2
+ import { execSync } from "node:child_process";
3
+ import { CONFIG } from "../config.js";
4
+ import { sep, normalize, resolve, isAbsolute, basename, dirname } from "node:path";
5
+ import { realpathSync, existsSync } from "node:fs";
6
+ function sha256(input) {
7
+ return createHash("sha256").update(input).digest("hex").slice(0, 16);
8
+ }
9
+ export function getGitEmail() {
10
+ try {
11
+ const email = execSync("git config user.email", {
12
+ encoding: "utf-8",
13
+ stdio: ["ignore", "pipe", "ignore"],
14
+ }).trim();
15
+ return email || null;
16
+ }
17
+ catch {
18
+ return null;
19
+ }
20
+ }
21
+ export function getGitName() {
22
+ try {
23
+ const name = execSync("git config user.name", {
24
+ encoding: "utf-8",
25
+ stdio: ["ignore", "pipe", "ignore"],
26
+ }).trim();
27
+ return name || null;
28
+ }
29
+ catch {
30
+ return null;
31
+ }
32
+ }
33
+ export function getGitRepoUrl(directory) {
34
+ try {
35
+ const url = execSync("git config --get remote.origin.url", {
36
+ encoding: "utf-8",
37
+ cwd: directory,
38
+ stdio: ["ignore", "pipe", "ignore"],
39
+ }).trim();
40
+ return url || null;
41
+ }
42
+ catch {
43
+ return null;
44
+ }
45
+ }
46
+ export function getGitCommonDir(directory) {
47
+ try {
48
+ const commonDir = execSync("git rev-parse --git-common-dir", {
49
+ encoding: "utf-8",
50
+ cwd: directory,
51
+ stdio: ["ignore", "pipe", "ignore"],
52
+ }).trim();
53
+ if (!commonDir) {
54
+ return null;
55
+ }
56
+ const resolved = isAbsolute(commonDir)
57
+ ? normalize(commonDir)
58
+ : normalize(resolve(directory, commonDir));
59
+ if (existsSync(resolved)) {
60
+ return realpathSync(resolved);
61
+ }
62
+ return resolved;
63
+ }
64
+ catch {
65
+ return null;
66
+ }
67
+ }
68
+ export function getGitTopLevel(directory) {
69
+ try {
70
+ const topLevel = execSync("git rev-parse --show-toplevel", {
71
+ encoding: "utf-8",
72
+ cwd: directory,
73
+ stdio: ["ignore", "pipe", "ignore"],
74
+ }).trim();
75
+ return topLevel || null;
76
+ }
77
+ catch {
78
+ return null;
79
+ }
80
+ }
81
+ export function getProjectRoot(directory) {
82
+ const commonDir = getGitCommonDir(directory);
83
+ if (commonDir && basename(commonDir) === ".git") {
84
+ return dirname(commonDir);
85
+ }
86
+ const topLevel = getGitTopLevel(directory);
87
+ if (topLevel) {
88
+ return topLevel;
89
+ }
90
+ return directory;
91
+ }
92
+ export function getProjectIdentity(directory) {
93
+ const commonDir = getGitCommonDir(directory);
94
+ if (commonDir) {
95
+ return `git-common:${commonDir}`;
96
+ }
97
+ const gitRepoUrl = getGitRepoUrl(directory);
98
+ if (gitRepoUrl) {
99
+ return `remote:${gitRepoUrl}`;
100
+ }
101
+ return `path:${normalize(directory)}`;
102
+ }
103
+ export function getProjectName(directory) {
104
+ // Normalize path to handle both Unix and Windows separators
105
+ const normalized = normalize(directory);
106
+ const parts = normalized.split(sep).filter((p) => p);
107
+ return parts[parts.length - 1] || directory;
108
+ }
109
+ export function getUserTagInfo() {
110
+ const email = CONFIG.userEmailOverride || getGitEmail();
111
+ const name = CONFIG.userNameOverride || getGitName();
112
+ if (email) {
113
+ return {
114
+ tag: `${CONFIG.containerTagPrefix}_user_${sha256(email)}`,
115
+ displayName: name || email,
116
+ userName: name || undefined,
117
+ userEmail: email,
118
+ };
119
+ }
120
+ const fallback = name || process.env.USER || process.env.USERNAME || "anonymous";
121
+ return {
122
+ tag: `${CONFIG.containerTagPrefix}_user_${sha256(fallback)}`,
123
+ displayName: fallback,
124
+ userName: fallback,
125
+ userEmail: undefined,
126
+ };
127
+ }
128
+ export function getProjectTagInfo(directory) {
129
+ const projectRoot = getProjectRoot(directory);
130
+ const projectName = getProjectName(projectRoot);
131
+ const gitRepoUrl = getGitRepoUrl(directory);
132
+ const projectIdentity = getProjectIdentity(projectRoot);
133
+ return {
134
+ tag: `${CONFIG.containerTagPrefix}_project_${sha256(projectIdentity)}`,
135
+ displayName: projectRoot,
136
+ projectPath: projectRoot,
137
+ projectName,
138
+ gitRepoUrl: gitRepoUrl || undefined,
139
+ };
140
+ }
141
+ export function getTags(directory) {
142
+ return {
143
+ user: getUserTagInfo(),
144
+ project: getProjectTagInfo(directory),
145
+ };
146
+ }
@@ -0,0 +1,3 @@
1
+ import type { PluginInput } from "@opencode-ai/plugin";
2
+ export declare function performUserProfileLearning(ctx: PluginInput, directory: string): Promise<void>;
3
+ //# sourceMappingURL=user-memory-learning.d.ts.map
@@ -0,0 +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;AAWvD,wBAAsB,0BAA0B,CAC9C,GAAG,EAAE,WAAW,EAChB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,IAAI,CAAC,CAsEf"}
@@ -0,0 +1,231 @@
1
+ import { getTags } from "./tags.js";
2
+ import { log } from "./logger.js";
3
+ import { CONFIG } from "../config.js";
4
+ import { userPromptManager } from "./user-prompt/user-prompt-manager.js";
5
+ import { userProfileManager } from "./user-profile/user-profile-manager.js";
6
+ let isLearningRunning = false;
7
+ export async function performUserProfileLearning(ctx, directory) {
8
+ if (isLearningRunning)
9
+ return;
10
+ isLearningRunning = true;
11
+ try {
12
+ const count = userPromptManager.countUnanalyzedForUserLearning();
13
+ const threshold = CONFIG.userProfileAnalysisInterval;
14
+ if (count < threshold) {
15
+ return;
16
+ }
17
+ const prompts = userPromptManager.getPromptsForUserLearning(threshold);
18
+ if (prompts.length === 0) {
19
+ return;
20
+ }
21
+ const tags = getTags(directory);
22
+ const userId = tags.user.userEmail || "unknown";
23
+ const existingProfile = userProfileManager.getActiveProfile(userId);
24
+ const context = buildUserAnalysisContext(prompts, existingProfile);
25
+ const updatedProfileData = await analyzeUserProfile(context, existingProfile);
26
+ if (!updatedProfileData) {
27
+ userPromptManager.markMultipleAsUserLearningCaptured(prompts.map((p) => p.id));
28
+ return;
29
+ }
30
+ if (existingProfile) {
31
+ const changeSummary = generateChangeSummary(JSON.parse(existingProfile.profileData), updatedProfileData);
32
+ userProfileManager.updateProfile(existingProfile.id, updatedProfileData, prompts.length, changeSummary);
33
+ }
34
+ else {
35
+ userProfileManager.createProfile(userId, tags.user.displayName || "Unknown", tags.user.userName || "unknown", tags.user.userEmail || "unknown", updatedProfileData, prompts.length);
36
+ }
37
+ userPromptManager.markMultipleAsUserLearningCaptured(prompts.map((p) => p.id));
38
+ if (CONFIG.showUserProfileToasts) {
39
+ await ctx.client?.tui
40
+ .showToast({
41
+ body: {
42
+ title: "User Profile Updated",
43
+ message: `Analyzed ${prompts.length} prompts and updated your profile`,
44
+ variant: "success",
45
+ duration: 3000,
46
+ },
47
+ })
48
+ .catch(() => { });
49
+ }
50
+ }
51
+ finally {
52
+ isLearningRunning = false;
53
+ }
54
+ }
55
+ function generateChangeSummary(oldProfile, newProfile) {
56
+ const changes = [];
57
+ const prefDiff = newProfile.preferences.length - oldProfile.preferences.length;
58
+ if (prefDiff > 0)
59
+ changes.push(`+${prefDiff} preferences`);
60
+ const patternDiff = newProfile.patterns.length - oldProfile.patterns.length;
61
+ if (patternDiff > 0)
62
+ changes.push(`+${patternDiff} patterns`);
63
+ const workflowDiff = newProfile.workflows.length - oldProfile.workflows.length;
64
+ if (workflowDiff > 0)
65
+ changes.push(`+${workflowDiff} workflows`);
66
+ return changes.length > 0 ? changes.join(", ") : "Profile refinement";
67
+ }
68
+ function buildUserAnalysisContext(prompts, existingProfile) {
69
+ const existingProfileSection = existingProfile
70
+ ? `
71
+ ## Existing User Profile
72
+
73
+ ${existingProfile.profileData}
74
+
75
+ **Instructions**: Merge new insights with the existing profile. Update confidence scores for reinforced patterns, add new patterns, and refine existing ones.`
76
+ : `
77
+ **Instructions**: Create a new user profile from scratch based on the prompts below.`;
78
+ return `# User Profile Analysis
79
+
80
+ Analyze ${prompts.length} user prompts to ${existingProfile ? "update" : "create"} the user profile.
81
+
82
+ ${existingProfileSection}
83
+
84
+ ## Recent Prompts
85
+
86
+ ${prompts.map((p, i) => `${i + 1}. ${p.content}`).join("\n\n")}
87
+
88
+ ## Analysis Guidelines
89
+
90
+ Identify and ${existingProfile ? "update" : "create"}:
91
+
92
+ 1. **Preferences** (max ${CONFIG.userProfileMaxPreferences})
93
+ - Code style, communication style, tool preferences
94
+ - Assign confidence 0.5-1.0 based on evidence strength
95
+ - Include 1-3 example prompts as evidence
96
+
97
+ 2. **Patterns** (max ${CONFIG.userProfileMaxPatterns})
98
+ - Recurring topics, problem domains, technical interests
99
+ - Track frequency of occurrence
100
+
101
+ 3. **Workflows** (max ${CONFIG.userProfileMaxWorkflows})
102
+ - Development sequences, habits, learning style
103
+ - Break down into steps if applicable
104
+
105
+ ${existingProfile ? "Merge with existing profile, incrementing frequencies and updating confidence scores." : "Create initial profile with conservative confidence scores."}`;
106
+ }
107
+ async function analyzeUserProfile(context, existingProfile) {
108
+ if (CONFIG.opencodeProvider && CONFIG.opencodeModel) {
109
+ const { isProviderConnected, getStatePath, generateStructuredOutput } = await import("./ai/opencode-provider.js");
110
+ if (!isProviderConnected(CONFIG.opencodeProvider)) {
111
+ throw new Error(`opencode provider '${CONFIG.opencodeProvider}' is not connected. Check your opencode provider configuration.`);
112
+ }
113
+ const systemPrompt = `You are a user behavior analyst for a coding assistant.
114
+
115
+ Your task is to analyze user prompts and ${existingProfile ? "update" : "create"} a comprehensive user profile.
116
+
117
+ CRITICAL: Detect the language used by the user in their prompts. You MUST output all descriptions, categories, and text in the SAME language as the user's prompts.
118
+
119
+ Use the update_user_profile tool to save the ${existingProfile ? "updated" : "new"} profile.`;
120
+ const { z } = await import("zod");
121
+ const schema = z.object({
122
+ preferences: z.array(z.object({
123
+ category: z.string(),
124
+ description: z.string(),
125
+ confidence: z.number(),
126
+ evidence: z.array(z.string()),
127
+ })),
128
+ patterns: z.array(z.object({
129
+ category: z.string(),
130
+ description: z.string(),
131
+ })),
132
+ workflows: z.array(z.object({
133
+ description: z.string(),
134
+ steps: z.array(z.string()),
135
+ })),
136
+ });
137
+ const result = await generateStructuredOutput({
138
+ providerName: CONFIG.opencodeProvider,
139
+ modelId: CONFIG.opencodeModel,
140
+ statePath: getStatePath(),
141
+ systemPrompt,
142
+ userPrompt: context,
143
+ schema,
144
+ temperature: CONFIG.memoryTemperature === false ? undefined : (CONFIG.memoryTemperature ?? 0.3),
145
+ });
146
+ if (existingProfile) {
147
+ const existingData = JSON.parse(existingProfile.profileData);
148
+ return userProfileManager.mergeProfileData(existingData, result);
149
+ }
150
+ return result;
151
+ }
152
+ if (!CONFIG.memoryModel || !CONFIG.memoryApiUrl) {
153
+ log("User Profile Config Check Failed:", {
154
+ memoryModel: CONFIG.memoryModel,
155
+ memoryApiUrl: CONFIG.memoryApiUrl,
156
+ memoryApiKey: CONFIG.memoryApiKey,
157
+ });
158
+ throw new Error("External API not configured for user memory learning");
159
+ }
160
+ const { AIProviderFactory } = await import("./ai/ai-provider-factory.js");
161
+ const { buildMemoryProviderConfig } = await import("./ai/provider-config.js");
162
+ const providerConfig = buildMemoryProviderConfig(CONFIG);
163
+ const provider = AIProviderFactory.createProvider(CONFIG.memoryProvider, providerConfig);
164
+ const systemPrompt = `You are a user behavior analyst for a coding assistant.
165
+
166
+ Your task is to analyze user prompts and ${existingProfile ? "update" : "create"} a comprehensive user profile.
167
+
168
+ CRITICAL: Detect the language used by the user in their prompts. You MUST output all descriptions, categories, and text in the SAME language as the user's prompts.
169
+
170
+ Use the update_user_profile tool to save the ${existingProfile ? "updated" : "new"} profile.`;
171
+ const toolSchema = {
172
+ type: "function",
173
+ function: {
174
+ name: "update_user_profile",
175
+ description: existingProfile
176
+ ? "Update existing user profile with new insights"
177
+ : "Create new user profile",
178
+ parameters: {
179
+ type: "object",
180
+ properties: {
181
+ preferences: {
182
+ type: "array",
183
+ items: {
184
+ type: "object",
185
+ properties: {
186
+ category: { type: "string" },
187
+ description: { type: "string" },
188
+ confidence: { type: "number", minimum: 0, maximum: 1 },
189
+ evidence: { type: "array", items: { type: "string" }, maxItems: 3 },
190
+ },
191
+ required: ["category", "description", "confidence", "evidence"],
192
+ },
193
+ },
194
+ patterns: {
195
+ type: "array",
196
+ items: {
197
+ type: "object",
198
+ properties: {
199
+ category: { type: "string" },
200
+ description: { type: "string" },
201
+ },
202
+ required: ["category", "description"],
203
+ },
204
+ },
205
+ workflows: {
206
+ type: "array",
207
+ items: {
208
+ type: "object",
209
+ properties: {
210
+ description: { type: "string" },
211
+ steps: { type: "array", items: { type: "string" } },
212
+ },
213
+ required: ["description", "steps"],
214
+ },
215
+ },
216
+ },
217
+ required: ["preferences", "patterns", "workflows"],
218
+ },
219
+ },
220
+ };
221
+ const result = await provider.executeToolCall(systemPrompt, context, toolSchema, `user-profile-${Date.now()}`);
222
+ if (!result.success || !result.data) {
223
+ throw new Error(result.error || "Failed to analyze user profile");
224
+ }
225
+ const rawData = result.data;
226
+ if (existingProfile) {
227
+ const existingData = JSON.parse(existingProfile.profileData);
228
+ return userProfileManager.mergeProfileData(existingData, rawData);
229
+ }
230
+ return rawData;
231
+ }
@@ -0,0 +1,2 @@
1
+ export declare function getUserProfileContext(userId: string): string | null;
2
+ //# sourceMappingURL=profile-context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"profile-context.d.ts","sourceRoot":"","sources":["../../../src/services/user-profile/profile-context.ts"],"names":[],"mappings":"AAGA,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CA6CnE"}
@@ -0,0 +1,40 @@
1
+ import { userProfileManager } from "./user-profile-manager.js";
2
+ export function getUserProfileContext(userId) {
3
+ const profile = userProfileManager.getActiveProfile(userId);
4
+ if (!profile) {
5
+ return null;
6
+ }
7
+ const profileData = JSON.parse(profile.profileData);
8
+ const parts = [];
9
+ if (profileData.preferences.length > 0) {
10
+ parts.push("User Preferences:");
11
+ profileData.preferences
12
+ .sort((a, b) => b.confidence - a.confidence)
13
+ .slice(0, 5)
14
+ .forEach((pref) => {
15
+ parts.push(`- [${pref.category}] ${pref.description}`);
16
+ });
17
+ }
18
+ if (profileData.patterns.length > 0) {
19
+ parts.push("\nUser Patterns:");
20
+ profileData.patterns
21
+ .sort((a, b) => b.frequency - a.frequency)
22
+ .slice(0, 5)
23
+ .forEach((pattern) => {
24
+ parts.push(`- [${pattern.category}] ${pattern.description}`);
25
+ });
26
+ }
27
+ if (profileData.workflows.length > 0) {
28
+ parts.push("\nUser Workflows:");
29
+ profileData.workflows
30
+ .sort((a, b) => b.frequency - a.frequency)
31
+ .slice(0, 3)
32
+ .forEach((workflow) => {
33
+ parts.push(`- ${workflow.description}`);
34
+ });
35
+ }
36
+ if (parts.length === 0) {
37
+ return null;
38
+ }
39
+ return parts.join("\n");
40
+ }
@@ -0,0 +1,3 @@
1
+ export declare const safeArray: <T>(arr: any) => T[];
2
+ export declare const safeObject: <T extends object>(obj: any, 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,GAAG,KAAG,CAAC,EA0BxC,CAAC;AAEF,eAAO,MAAM,UAAU,GAAI,CAAC,SAAS,MAAM,EAAE,KAAK,GAAG,EAAE,UAAU,CAAC,KAAG,CAWpE,CAAC"}
@@ -0,0 +1,45 @@
1
+ export const safeArray = (arr) => {
2
+ if (!arr)
3
+ return [];
4
+ let result = arr;
5
+ if (typeof result === "string") {
6
+ try {
7
+ result = JSON.parse(result);
8
+ }
9
+ catch {
10
+ try {
11
+ result = JSON.parse(result.trim().replace(/,$/, ""));
12
+ }
13
+ catch {
14
+ return [];
15
+ }
16
+ }
17
+ }
18
+ if (!Array.isArray(result))
19
+ return [];
20
+ const flattened = [];
21
+ const walk = (item) => {
22
+ if (Array.isArray(item)) {
23
+ item.forEach(walk);
24
+ }
25
+ else if (item) {
26
+ flattened.push(item);
27
+ }
28
+ };
29
+ walk(result);
30
+ return flattened;
31
+ };
32
+ export const safeObject = (obj, fallback) => {
33
+ if (!obj)
34
+ return fallback;
35
+ let result = obj;
36
+ if (typeof result === "string") {
37
+ try {
38
+ result = JSON.parse(result);
39
+ }
40
+ catch {
41
+ return fallback;
42
+ }
43
+ }
44
+ return result && typeof result === "object" && !Array.isArray(result) ? result : fallback;
45
+ };
@@ -0,0 +1,46 @@
1
+ export interface UserProfilePreference {
2
+ category: string;
3
+ description: string;
4
+ confidence: number;
5
+ evidence: string[];
6
+ lastUpdated: number;
7
+ }
8
+ export interface UserProfilePattern {
9
+ category: string;
10
+ description: string;
11
+ frequency: number;
12
+ lastSeen: number;
13
+ }
14
+ export interface UserProfileWorkflow {
15
+ description: string;
16
+ steps: string[];
17
+ frequency: number;
18
+ }
19
+ export interface UserProfileData {
20
+ preferences: UserProfilePreference[];
21
+ patterns: UserProfilePattern[];
22
+ workflows: UserProfileWorkflow[];
23
+ }
24
+ export interface UserProfile {
25
+ id: string;
26
+ userId: string;
27
+ displayName: string;
28
+ userName: string;
29
+ userEmail: string;
30
+ profileData: string;
31
+ version: number;
32
+ createdAt: number;
33
+ lastAnalyzedAt: number;
34
+ totalPromptsAnalyzed: number;
35
+ isActive: boolean;
36
+ }
37
+ export interface UserProfileChangelog {
38
+ id: string;
39
+ profileId: string;
40
+ version: number;
41
+ changeType: string;
42
+ changeSummary: string;
43
+ profileDataSnapshot: string;
44
+ createdAt: number;
45
+ }
46
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +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,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"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,23 @@
1
+ import type { UserProfile, UserProfileChangelog, UserProfileData } from "./types.js";
2
+ export declare class UserProfileManager {
3
+ private db;
4
+ private readonly dbPath;
5
+ constructor();
6
+ private initDatabase;
7
+ getActiveProfile(userId: string): UserProfile | null;
8
+ createProfile(userId: string, displayName: string, userName: string, userEmail: string, profileData: UserProfileData, promptsAnalyzed: number): string;
9
+ updateProfile(profileId: string, profileData: UserProfileData, additionalPromptsAnalyzed: number, changeSummary: string): void;
10
+ private addChangelog;
11
+ private cleanupOldChangelogs;
12
+ getProfileChangelogs(profileId: string, limit?: number): UserProfileChangelog[];
13
+ applyConfidenceDecay(profileId: string): void;
14
+ deleteProfile(profileId: string): void;
15
+ getProfileById(profileId: string): UserProfile | null;
16
+ getAllActiveProfiles(): UserProfile[];
17
+ private rowToProfile;
18
+ private rowToChangelog;
19
+ mergeProfileData(existing: UserProfileData, updates: Partial<UserProfileData>): UserProfileData;
20
+ private ensureArray;
21
+ }
22
+ export declare const userProfileManager: UserProfileManager;
23
+ //# sourceMappingURL=user-profile-manager.d.ts.map
@@ -0,0 +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;AAQrF,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,EAAE,CAAe;IACzB,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;IAoCT,aAAa,CACX,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,eAAe,EAC5B,yBAAyB,EAAE,MAAM,EACjC,aAAa,EAAE,MAAM,GACpB,IAAI;IAmCP,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;IA0F/F,OAAO,CAAC,WAAW;CAWpB;AAED,eAAO,MAAM,kBAAkB,oBAA2B,CAAC"}