@phuetz/code-buddy 0.1.18 → 0.1.19

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 (273) hide show
  1. package/dist/agent/background-tasks.d.ts +49 -0
  2. package/dist/agent/background-tasks.js +153 -0
  3. package/dist/agent/background-tasks.js.map +1 -0
  4. package/dist/agent/definitions/agent-definition-loader.d.ts +21 -0
  5. package/dist/agent/definitions/agent-definition-loader.js +161 -0
  6. package/dist/agent/definitions/agent-definition-loader.js.map +1 -0
  7. package/dist/agent/definitions/index.d.ts +1 -0
  8. package/dist/agent/definitions/index.js +2 -0
  9. package/dist/agent/definitions/index.js.map +1 -0
  10. package/dist/agent/extended-thinking.d.ts +64 -0
  11. package/dist/agent/extended-thinking.js +103 -0
  12. package/dist/agent/extended-thinking.js.map +1 -0
  13. package/dist/agent/prompt-suggestions.d.ts +55 -0
  14. package/dist/agent/prompt-suggestions.js +125 -0
  15. package/dist/agent/prompt-suggestions.js.map +1 -0
  16. package/dist/agent/rewind-manager.d.ts +59 -0
  17. package/dist/agent/rewind-manager.js +124 -0
  18. package/dist/agent/rewind-manager.js.map +1 -0
  19. package/dist/agent/teams/agent-team.d.ts +54 -0
  20. package/dist/agent/teams/agent-team.js +114 -0
  21. package/dist/agent/teams/agent-team.js.map +1 -0
  22. package/dist/agent/teams/index.d.ts +1 -0
  23. package/dist/agent/teams/index.js +2 -0
  24. package/dist/agent/teams/index.js.map +1 -0
  25. package/dist/agent/teams/team-v2.d.ts +166 -0
  26. package/dist/agent/teams/team-v2.js +376 -0
  27. package/dist/agent/teams/team-v2.js.map +1 -0
  28. package/dist/channels/imessage/index.d.ts +40 -0
  29. package/dist/channels/imessage/index.js +69 -0
  30. package/dist/channels/imessage/index.js.map +1 -0
  31. package/dist/channels/line/index.d.ts +36 -0
  32. package/dist/channels/line/index.js +71 -0
  33. package/dist/channels/line/index.js.map +1 -0
  34. package/dist/channels/mattermost/index.d.ts +34 -0
  35. package/dist/channels/mattermost/index.js +56 -0
  36. package/dist/channels/mattermost/index.js.map +1 -0
  37. package/dist/channels/nextcloud-talk/index.d.ts +37 -0
  38. package/dist/channels/nextcloud-talk/index.js +67 -0
  39. package/dist/channels/nextcloud-talk/index.js.map +1 -0
  40. package/dist/channels/niche-channels.d.ts +61 -0
  41. package/dist/channels/niche-channels.js +131 -0
  42. package/dist/channels/niche-channels.js.map +1 -0
  43. package/dist/channels/nostr/index.d.ts +30 -0
  44. package/dist/channels/nostr/index.js +68 -0
  45. package/dist/channels/nostr/index.js.map +1 -0
  46. package/dist/channels/twilio-voice/index.d.ts +37 -0
  47. package/dist/channels/twilio-voice/index.js +76 -0
  48. package/dist/channels/twilio-voice/index.js.map +1 -0
  49. package/dist/channels/whatsapp/index.js +0 -1
  50. package/dist/channels/whatsapp/index.js.map +1 -1
  51. package/dist/channels/zalo/index.d.ts +28 -0
  52. package/dist/channels/zalo/index.js +53 -0
  53. package/dist/channels/zalo/index.js.map +1 -0
  54. package/dist/cloud/cloud-sessions.d.ts +56 -0
  55. package/dist/cloud/cloud-sessions.js +187 -0
  56. package/dist/cloud/cloud-sessions.js.map +1 -0
  57. package/dist/codebuddy/tool-definitions/advanced-tools.d.ts +1 -0
  58. package/dist/codebuddy/tool-definitions/advanced-tools.js +24 -0
  59. package/dist/codebuddy/tool-definitions/advanced-tools.js.map +1 -1
  60. package/dist/codebuddy/tool-definitions/index.d.ts +1 -1
  61. package/dist/codebuddy/tool-definitions/index.js +1 -1
  62. package/dist/codebuddy/tool-definitions/index.js.map +1 -1
  63. package/dist/commands/handlers/auth-handler.d.ts +32 -0
  64. package/dist/commands/handlers/auth-handler.js +137 -0
  65. package/dist/commands/handlers/auth-handler.js.map +1 -0
  66. package/dist/commands/handlers/context-handler.d.ts +46 -0
  67. package/dist/commands/handlers/context-handler.js +102 -0
  68. package/dist/commands/handlers/context-handler.js.map +1 -0
  69. package/dist/commands/handlers/keybindings-handler.d.ts +30 -0
  70. package/dist/commands/handlers/keybindings-handler.js +124 -0
  71. package/dist/commands/handlers/keybindings-handler.js.map +1 -0
  72. package/dist/commands/handlers/session-commands.d.ts +17 -0
  73. package/dist/commands/handlers/session-commands.js +119 -0
  74. package/dist/commands/handlers/session-commands.js.map +1 -0
  75. package/dist/commands/slash/builtin-commands.js +1 -1
  76. package/dist/commands/slash/builtin-commands.js.map +1 -1
  77. package/dist/config/admin-config.d.ts +54 -0
  78. package/dist/config/admin-config.js +144 -0
  79. package/dist/config/admin-config.js.map +1 -0
  80. package/dist/config/advanced-config.d.ts +118 -0
  81. package/dist/config/advanced-config.js +364 -0
  82. package/dist/config/advanced-config.js.map +1 -0
  83. package/dist/config/managed-policies.d.ts +50 -0
  84. package/dist/config/managed-policies.js +120 -0
  85. package/dist/config/managed-policies.js.map +1 -0
  86. package/dist/config/settings-hierarchy.d.ts +59 -0
  87. package/dist/config/settings-hierarchy.js +188 -0
  88. package/dist/config/settings-hierarchy.js.map +1 -0
  89. package/dist/config/tool-profiles.d.ts +37 -0
  90. package/dist/config/tool-profiles.js +150 -0
  91. package/dist/config/tool-profiles.js.map +1 -0
  92. package/dist/config/user-settings.d.ts +31 -0
  93. package/dist/config/user-settings.js +66 -0
  94. package/dist/config/user-settings.js.map +1 -0
  95. package/dist/context/context-files.d.ts +1 -1
  96. package/dist/context/context-files.js +2 -2
  97. package/dist/context/context-files.js.map +1 -1
  98. package/dist/context/partial-summarizer.d.ts +32 -0
  99. package/dist/context/partial-summarizer.js +144 -0
  100. package/dist/context/partial-summarizer.js.map +1 -0
  101. package/dist/desktop/desktop-app.d.ts +44 -0
  102. package/dist/desktop/desktop-app.js +136 -0
  103. package/dist/desktop/desktop-app.js.map +1 -0
  104. package/dist/git/worktree-sessions.d.ts +24 -0
  105. package/dist/git/worktree-sessions.js +93 -0
  106. package/dist/git/worktree-sessions.js.map +1 -0
  107. package/dist/hooks/advanced-hooks.d.ts +110 -0
  108. package/dist/hooks/advanced-hooks.js +256 -0
  109. package/dist/hooks/advanced-hooks.js.map +1 -0
  110. package/dist/hooks/async-hooks.d.ts +73 -0
  111. package/dist/hooks/async-hooks.js +213 -0
  112. package/dist/hooks/async-hooks.js.map +1 -0
  113. package/dist/hooks/env-persistence.d.ts +58 -0
  114. package/dist/hooks/env-persistence.js +195 -0
  115. package/dist/hooks/env-persistence.js.map +1 -0
  116. package/dist/hooks/hook-events.d.ts +36 -0
  117. package/dist/hooks/hook-events.js +55 -0
  118. package/dist/hooks/hook-events.js.map +1 -0
  119. package/dist/hooks/smart-hooks.d.ts +85 -0
  120. package/dist/hooks/smart-hooks.js +199 -0
  121. package/dist/hooks/smart-hooks.js.map +1 -0
  122. package/dist/ide/jetbrains-plugin.d.ts +55 -0
  123. package/dist/ide/jetbrains-plugin.js +156 -0
  124. package/dist/ide/jetbrains-plugin.js.map +1 -0
  125. package/dist/ide/vscode-extension.d.ts +94 -0
  126. package/dist/ide/vscode-extension.js +229 -0
  127. package/dist/ide/vscode-extension.js.map +1 -0
  128. package/dist/index.js +77 -3
  129. package/dist/index.js.map +1 -1
  130. package/dist/input/file-autocomplete.d.ts +42 -0
  131. package/dist/input/file-autocomplete.js +154 -0
  132. package/dist/input/file-autocomplete.js.map +1 -0
  133. package/dist/integrations/chrome-bridge.d.ts +90 -0
  134. package/dist/integrations/chrome-bridge.js +151 -0
  135. package/dist/integrations/chrome-bridge.js.map +1 -0
  136. package/dist/integrations/github-action-runner.d.ts +40 -0
  137. package/dist/integrations/github-action-runner.js +163 -0
  138. package/dist/integrations/github-action-runner.js.map +1 -0
  139. package/dist/integrations/gitlab-ci-runner.d.ts +34 -0
  140. package/dist/integrations/gitlab-ci-runner.js +104 -0
  141. package/dist/integrations/gitlab-ci-runner.js.map +1 -0
  142. package/dist/integrations/pr-session-linker.d.ts +44 -0
  143. package/dist/integrations/pr-session-linker.js +103 -0
  144. package/dist/integrations/pr-session-linker.js.map +1 -0
  145. package/dist/integrations/tailscale.d.ts +36 -0
  146. package/dist/integrations/tailscale.js +101 -0
  147. package/dist/integrations/tailscale.js.map +1 -0
  148. package/dist/lsp/lsp-client.d.ts +68 -0
  149. package/dist/lsp/lsp-client.js +182 -0
  150. package/dist/lsp/lsp-client.js.map +1 -0
  151. package/dist/mcp/connectors.d.ts +28 -0
  152. package/dist/mcp/connectors.js +148 -0
  153. package/dist/mcp/connectors.js.map +1 -0
  154. package/dist/mcp/index.d.ts +7 -4
  155. package/dist/mcp/index.js +7 -4
  156. package/dist/mcp/index.js.map +1 -1
  157. package/dist/mcp/mcp-auto-discovery.d.ts +49 -0
  158. package/dist/mcp/mcp-auto-discovery.js +104 -0
  159. package/dist/mcp/mcp-auto-discovery.js.map +1 -0
  160. package/dist/mcp/mcp-server.d.ts +70 -0
  161. package/dist/mcp/mcp-server.js +374 -0
  162. package/dist/mcp/mcp-server.js.map +1 -0
  163. package/dist/memory/auto-memory.d.ts +53 -0
  164. package/dist/memory/auto-memory.js +250 -0
  165. package/dist/memory/auto-memory.js.map +1 -0
  166. package/dist/memory/hybrid-search.d.ts +51 -0
  167. package/dist/memory/hybrid-search.js +199 -0
  168. package/dist/memory/hybrid-search.js.map +1 -0
  169. package/dist/memory/memory-flush.d.ts +51 -0
  170. package/dist/memory/memory-flush.js +102 -0
  171. package/dist/memory/memory-flush.js.map +1 -0
  172. package/dist/memory/subagent-memory.d.ts +73 -0
  173. package/dist/memory/subagent-memory.js +172 -0
  174. package/dist/memory/subagent-memory.js.map +1 -0
  175. package/dist/nodes/device-node.d.ts +40 -0
  176. package/dist/nodes/device-node.js +117 -0
  177. package/dist/nodes/device-node.js.map +1 -0
  178. package/dist/output/json-schema-output.d.ts +67 -0
  179. package/dist/output/json-schema-output.js +273 -0
  180. package/dist/output/json-schema-output.js.map +1 -0
  181. package/dist/persistence/session-picker.d.ts +22 -0
  182. package/dist/persistence/session-picker.js +47 -0
  183. package/dist/persistence/session-picker.js.map +1 -0
  184. package/dist/persistence/session-store.d.ts +11 -0
  185. package/dist/persistence/session-store.js +17 -0
  186. package/dist/persistence/session-store.js.map +1 -1
  187. package/dist/plugins/git-pinned-marketplace.d.ts +39 -0
  188. package/dist/plugins/git-pinned-marketplace.js +152 -0
  189. package/dist/plugins/git-pinned-marketplace.js.map +1 -0
  190. package/dist/plugins/plugin-manifest.d.ts +116 -0
  191. package/dist/plugins/plugin-manifest.js +283 -0
  192. package/dist/plugins/plugin-manifest.js.map +1 -0
  193. package/dist/sandbox/os-sandbox.d.ts +49 -1
  194. package/dist/sandbox/os-sandbox.js +347 -6
  195. package/dist/sandbox/os-sandbox.js.map +1 -1
  196. package/dist/sdk/agent-sdk.d.ts +61 -0
  197. package/dist/sdk/agent-sdk.js +90 -0
  198. package/dist/sdk/agent-sdk.js.map +1 -0
  199. package/dist/security/permission-modes.d.ts +76 -0
  200. package/dist/security/permission-modes.js +195 -0
  201. package/dist/security/permission-modes.js.map +1 -0
  202. package/dist/security/permission-patterns.d.ts +61 -0
  203. package/dist/security/permission-patterns.js +171 -0
  204. package/dist/security/permission-patterns.js.map +1 -0
  205. package/dist/security/safe-binaries.d.ts +23 -0
  206. package/dist/security/safe-binaries.js +96 -0
  207. package/dist/security/safe-binaries.js.map +1 -0
  208. package/dist/security/sender-policies.d.ts +46 -0
  209. package/dist/security/sender-policies.js +90 -0
  210. package/dist/security/sender-policies.js.map +1 -0
  211. package/dist/server/dashboard.d.ts +53 -0
  212. package/dist/server/dashboard.js +93 -0
  213. package/dist/server/dashboard.js.map +1 -0
  214. package/dist/services/system-prompt-override.d.ts +34 -0
  215. package/dist/services/system-prompt-override.js +64 -0
  216. package/dist/services/system-prompt-override.js.map +1 -0
  217. package/dist/skills/skill-enhancements.d.ts +37 -0
  218. package/dist/skills/skill-enhancements.js +69 -0
  219. package/dist/skills/skill-enhancements.js.map +1 -0
  220. package/dist/telemetry/otel-tracer.d.ts +98 -0
  221. package/dist/telemetry/otel-tracer.js +245 -0
  222. package/dist/telemetry/otel-tracer.js.map +1 -0
  223. package/dist/tools/browser-stub.d.ts +61 -0
  224. package/dist/tools/browser-stub.js +184 -0
  225. package/dist/tools/browser-stub.js.map +1 -0
  226. package/dist/tools/gateway-tool.d.ts +43 -0
  227. package/dist/tools/gateway-tool.js +92 -0
  228. package/dist/tools/gateway-tool.js.map +1 -0
  229. package/dist/tools/image-stub.d.ts +32 -0
  230. package/dist/tools/image-stub.js +97 -0
  231. package/dist/tools/image-stub.js.map +1 -0
  232. package/dist/tools/js-repl.d.ts +78 -0
  233. package/dist/tools/js-repl.js +280 -0
  234. package/dist/tools/js-repl.js.map +1 -0
  235. package/dist/tools/message-tool.d.ts +42 -0
  236. package/dist/tools/message-tool.js +113 -0
  237. package/dist/tools/message-tool.js.map +1 -0
  238. package/dist/ui/cli-enhancements.d.ts +178 -0
  239. package/dist/ui/cli-enhancements.js +430 -0
  240. package/dist/ui/cli-enhancements.js.map +1 -0
  241. package/dist/ui/status-line.d.ts +90 -0
  242. package/dist/ui/status-line.js +160 -0
  243. package/dist/ui/status-line.js.map +1 -0
  244. package/dist/ui/terminal-enhancements.d.ts +34 -0
  245. package/dist/ui/terminal-enhancements.js +97 -0
  246. package/dist/ui/terminal-enhancements.js.map +1 -0
  247. package/dist/ui/ui-enhancements.d.ts +38 -0
  248. package/dist/ui/ui-enhancements.js +116 -0
  249. package/dist/ui/ui-enhancements.js.map +1 -0
  250. package/dist/utils/custom-instructions.js +4 -1
  251. package/dist/utils/custom-instructions.js.map +1 -1
  252. package/dist/utils/init-project.d.ts +1 -1
  253. package/dist/utils/init-project.js +20 -20
  254. package/dist/utils/init-project.js.map +1 -1
  255. package/dist/utils/output-schema-validator.d.ts +40 -0
  256. package/dist/utils/output-schema-validator.js +137 -0
  257. package/dist/utils/output-schema-validator.js.map +1 -0
  258. package/dist/utils/safety-misc.d.ts +24 -0
  259. package/dist/utils/safety-misc.js +91 -0
  260. package/dist/utils/safety-misc.js.map +1 -0
  261. package/dist/utils/session-enhancements.d.ts +40 -0
  262. package/dist/utils/session-enhancements.js +118 -0
  263. package/dist/utils/session-enhancements.js.map +1 -0
  264. package/dist/utils/shell-snapshot.d.ts +38 -0
  265. package/dist/utils/shell-snapshot.js +323 -0
  266. package/dist/utils/shell-snapshot.js.map +1 -0
  267. package/dist/utils/stream-json-formatter.d.ts +77 -0
  268. package/dist/utils/stream-json-formatter.js +61 -0
  269. package/dist/utils/stream-json-formatter.js.map +1 -0
  270. package/dist/workflows/lobster-engine.d.ts +43 -0
  271. package/dist/workflows/lobster-engine.js +167 -0
  272. package/dist/workflows/lobster-engine.js.map +1 -0
  273. package/package.json +3 -6
@@ -0,0 +1,250 @@
1
+ /**
2
+ * Auto-Memory System
3
+ *
4
+ * Automatically extracts and stores memories from agent interactions.
5
+ * Supports three scopes: user, project, and local.
6
+ * Memories are stored in MEMORY.md files at scope-appropriate paths.
7
+ */
8
+ import fs from 'fs';
9
+ import path from 'path';
10
+ import os from 'os';
11
+ import { logger } from '../utils/logger.js';
12
+ // ============================================================================
13
+ // Keyword Patterns for Analysis
14
+ // ============================================================================
15
+ const ANALYSIS_PATTERNS = [
16
+ {
17
+ category: 'project-structure',
18
+ patterns: [
19
+ /(?:project|repo|codebase) (?:uses?|is built with|structure[ds]?) ([^.]+)/i,
20
+ /(?:main|entry|root) (?:file|directory|folder) (?:is|at) ([^\s.]+)/i,
21
+ /monorepo (?:with|using|containing) ([^.]+)/i,
22
+ ],
23
+ },
24
+ {
25
+ category: 'user-preference',
26
+ patterns: [
27
+ /(?:i |we |please )prefer ([^.]+)/i,
28
+ /(?:always|never) (?:use|do|include) ([^.]+)/i,
29
+ /(?:my|our) (?:preferred|favorite) ([^.]+)/i,
30
+ ],
31
+ },
32
+ {
33
+ category: 'error-solution',
34
+ patterns: [
35
+ /(?:fix|solution|resolved|workaround)[:\s]+([^.]+)/i,
36
+ /(?:the error|the issue|the bug) (?:was|is) (?:caused by|due to|fixed by) ([^.]+)/i,
37
+ ],
38
+ },
39
+ {
40
+ category: 'architecture',
41
+ patterns: [
42
+ /(?:architecture|pattern|design) (?:is|uses?|follows?) ([^.]+)/i,
43
+ /(?:we use|using) (?:the )?([^.]*(?:pattern|architecture|approach))/i,
44
+ ],
45
+ },
46
+ {
47
+ category: 'important-file',
48
+ patterns: [
49
+ /(?:important|key|critical|config) files?[:\s]+([^\n.]+)/i,
50
+ /(?:don't|do not|never) (?:edit|modify|touch|delete) ([^\s.]+)/i,
51
+ ],
52
+ },
53
+ ];
54
+ // ============================================================================
55
+ // AutoMemoryManager
56
+ // ============================================================================
57
+ export class AutoMemoryManager {
58
+ projectDir;
59
+ memories = new Map();
60
+ constructor(projectDir = process.cwd()) {
61
+ this.projectDir = projectDir;
62
+ this.loadAllMemories();
63
+ }
64
+ /**
65
+ * Analyze context and response for potential memories to extract
66
+ */
67
+ analyzeForMemories(context, response) {
68
+ const extracted = [];
69
+ const combined = `${context}\n${response}`;
70
+ for (const { category, patterns } of ANALYSIS_PATTERNS) {
71
+ for (const pattern of patterns) {
72
+ const match = combined.match(pattern);
73
+ if (match && match[1]) {
74
+ const key = `${category}-${Date.now()}-${Math.random().toString(36).slice(2, 6)}`;
75
+ const entry = {
76
+ key,
77
+ value: match[0].trim(),
78
+ scope: 'project',
79
+ timestamp: Date.now(),
80
+ source: 'agent',
81
+ };
82
+ extracted.push(entry);
83
+ }
84
+ }
85
+ }
86
+ return extracted;
87
+ }
88
+ /**
89
+ * Write a memory entry to the appropriate MEMORY.md file
90
+ */
91
+ writeMemory(key, value, scope = 'project') {
92
+ const entry = {
93
+ key,
94
+ value,
95
+ scope,
96
+ timestamp: Date.now(),
97
+ source: 'user',
98
+ };
99
+ this.memories.set(`${scope}:${key}`, entry);
100
+ const memoryPath = this.getMemoryPath(scope);
101
+ const dir = path.dirname(memoryPath);
102
+ if (!fs.existsSync(dir)) {
103
+ fs.mkdirSync(dir, { recursive: true });
104
+ }
105
+ this.saveMemoryFile(scope);
106
+ logger.debug(`Memory written: ${key} (${scope})`, { source: 'AutoMemoryManager' });
107
+ }
108
+ /**
109
+ * Search all scoped memory files for relevant entries
110
+ */
111
+ recallMemories(context) {
112
+ const contextLower = context.toLowerCase();
113
+ const words = contextLower.split(/\s+/).filter((w) => w.length > 3);
114
+ const results = [];
115
+ for (const entry of this.memories.values()) {
116
+ const entryText = `${entry.key} ${entry.value}`.toLowerCase();
117
+ let score = 0;
118
+ for (const word of words) {
119
+ if (entryText.includes(word)) {
120
+ score++;
121
+ }
122
+ }
123
+ if (score > 0) {
124
+ results.push(entry);
125
+ }
126
+ }
127
+ // Sort by relevance (more matching words first), then by recency
128
+ results.sort((a, b) => {
129
+ return b.timestamp - a.timestamp;
130
+ });
131
+ return results;
132
+ }
133
+ /**
134
+ * Get the file path for a given memory scope
135
+ */
136
+ getMemoryPath(scope) {
137
+ switch (scope) {
138
+ case 'user':
139
+ return path.join(os.homedir(), '.codebuddy', 'memory', 'MEMORY.md');
140
+ case 'project':
141
+ return path.join(this.projectDir, '.codebuddy', 'memory', 'MEMORY.md');
142
+ case 'local':
143
+ return path.join(this.projectDir, '.codebuddy', 'memory', 'local', 'MEMORY.md');
144
+ }
145
+ }
146
+ /**
147
+ * List all memories, optionally filtered by scope
148
+ */
149
+ listMemories(scope) {
150
+ const entries = Array.from(this.memories.values());
151
+ if (scope) {
152
+ return entries.filter((e) => e.scope === scope);
153
+ }
154
+ return entries;
155
+ }
156
+ /**
157
+ * Delete a memory entry by key and optional scope
158
+ */
159
+ deleteMemory(key, scope) {
160
+ if (scope) {
161
+ const compositeKey = `${scope}:${key}`;
162
+ const deleted = this.memories.delete(compositeKey);
163
+ if (deleted) {
164
+ this.saveMemoryFile(scope);
165
+ }
166
+ return deleted;
167
+ }
168
+ // Try all scopes
169
+ let deleted = false;
170
+ for (const s of ['user', 'project', 'local']) {
171
+ const compositeKey = `${s}:${key}`;
172
+ if (this.memories.delete(compositeKey)) {
173
+ this.saveMemoryFile(s);
174
+ deleted = true;
175
+ }
176
+ }
177
+ return deleted;
178
+ }
179
+ /**
180
+ * Get a summary of recalled memories count
181
+ */
182
+ getRecallSummary() {
183
+ const count = this.memories.size;
184
+ return `Recalled ${count} memories`;
185
+ }
186
+ // ============================================================================
187
+ // Private Methods
188
+ // ============================================================================
189
+ loadAllMemories() {
190
+ for (const scope of ['user', 'project', 'local']) {
191
+ this.loadMemoryFile(scope);
192
+ }
193
+ }
194
+ loadMemoryFile(scope) {
195
+ const memoryPath = this.getMemoryPath(scope);
196
+ try {
197
+ if (!fs.existsSync(memoryPath)) {
198
+ return;
199
+ }
200
+ const content = fs.readFileSync(memoryPath, 'utf-8');
201
+ const lines = content.split('\n');
202
+ for (const line of lines) {
203
+ // Parse entries in format: - **key**: value [timestamp] [source]
204
+ const match = line.match(/^-\s*\*\*([^*]+)\*\*:\s*(.+?)(?:\s*\[(\d+)\])?\s*(?:\[(\w+)\])?\s*$/);
205
+ if (match) {
206
+ const entry = {
207
+ key: match[1],
208
+ value: match[2].trim(),
209
+ scope,
210
+ timestamp: match[3] ? parseInt(match[3], 10) : Date.now(),
211
+ source: match[4] || 'user',
212
+ };
213
+ this.memories.set(`${scope}:${entry.key}`, entry);
214
+ }
215
+ }
216
+ }
217
+ catch (error) {
218
+ logger.debug(`Failed to load memory file ${memoryPath}: ${error}`, { source: 'AutoMemoryManager' });
219
+ }
220
+ }
221
+ saveMemoryFile(scope) {
222
+ const memoryPath = this.getMemoryPath(scope);
223
+ const entries = this.listMemories(scope);
224
+ let content = `# Code Buddy Auto-Memory (${scope})\n\n`;
225
+ content += `## Memories\n\n`;
226
+ for (const entry of entries) {
227
+ content += `- **${entry.key}**: ${entry.value} [${entry.timestamp}] [${entry.source}]\n`;
228
+ }
229
+ content += `\n---\n*Last updated: ${new Date().toISOString()}*\n`;
230
+ const dir = path.dirname(memoryPath);
231
+ if (!fs.existsSync(dir)) {
232
+ fs.mkdirSync(dir, { recursive: true });
233
+ }
234
+ fs.writeFileSync(memoryPath, content);
235
+ }
236
+ }
237
+ // ============================================================================
238
+ // Singleton
239
+ // ============================================================================
240
+ let instance = null;
241
+ export function getAutoMemoryManager(projectDir) {
242
+ if (!instance || projectDir) {
243
+ instance = new AutoMemoryManager(projectDir);
244
+ }
245
+ return instance;
246
+ }
247
+ export function resetAutoMemory() {
248
+ instance = null;
249
+ }
250
+ //# sourceMappingURL=auto-memory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auto-memory.js","sourceRoot":"","sources":["../../src/memory/auto-memory.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Hybrid Memory Search
3
+ *
4
+ * Combines BM25 keyword search with semantic vector search
5
+ * for high-quality memory retrieval. Currently BM25 is fully
6
+ * implemented; semantic search is a stub for future embedding integration.
7
+ */
8
+ export interface SearchResult {
9
+ key: string;
10
+ value: string;
11
+ score: number;
12
+ source: 'bm25' | 'semantic' | 'hybrid';
13
+ }
14
+ export declare class BM25Index {
15
+ private documents;
16
+ private tokenizedDocs;
17
+ private docLengths;
18
+ private avgDocLength;
19
+ private df;
20
+ private k1;
21
+ private b;
22
+ constructor(k1?: number, b?: number);
23
+ addDocument(id: string, text: string): void;
24
+ search(query: string, limit?: number): SearchResult[];
25
+ removeDocument(id: string): void;
26
+ getDocumentCount(): number;
27
+ private tokenize;
28
+ private updateAvgDocLength;
29
+ }
30
+ export declare class HybridMemorySearch {
31
+ private static instance;
32
+ private bm25Index;
33
+ private bm25Weight;
34
+ private semanticWeight;
35
+ private constructor();
36
+ static getInstance(): HybridMemorySearch;
37
+ static resetInstance(): void;
38
+ index(entries: Array<{
39
+ key: string;
40
+ value: string;
41
+ }>): void;
42
+ search(query: string, limit?: number): SearchResult[];
43
+ setWeights(bm25Weight: number, semanticWeight: number): void;
44
+ getStats(): {
45
+ documentCount: number;
46
+ bm25Weight: number;
47
+ semanticWeight: number;
48
+ };
49
+ clear(): void;
50
+ private mergeResults;
51
+ }
@@ -0,0 +1,199 @@
1
+ /**
2
+ * Hybrid Memory Search
3
+ *
4
+ * Combines BM25 keyword search with semantic vector search
5
+ * for high-quality memory retrieval. Currently BM25 is fully
6
+ * implemented; semantic search is a stub for future embedding integration.
7
+ */
8
+ import { logger } from '../utils/logger.js';
9
+ // ============================================================================
10
+ // BM25Index
11
+ // ============================================================================
12
+ export class BM25Index {
13
+ documents = new Map();
14
+ tokenizedDocs = new Map();
15
+ docLengths = new Map();
16
+ avgDocLength = 0;
17
+ df = new Map(); // document frequency
18
+ k1;
19
+ b;
20
+ constructor(k1 = 1.5, b = 0.75) {
21
+ this.k1 = k1;
22
+ this.b = b;
23
+ }
24
+ addDocument(id, text) {
25
+ // Remove if exists to update
26
+ if (this.documents.has(id)) {
27
+ this.removeDocument(id);
28
+ }
29
+ this.documents.set(id, text);
30
+ const tokens = this.tokenize(text);
31
+ this.tokenizedDocs.set(id, tokens);
32
+ this.docLengths.set(id, tokens.length);
33
+ // Update document frequency
34
+ const uniqueTokens = new Set(tokens);
35
+ for (const token of uniqueTokens) {
36
+ this.df.set(token, (this.df.get(token) || 0) + 1);
37
+ }
38
+ this.updateAvgDocLength();
39
+ logger.debug('Document added to BM25 index', { id });
40
+ }
41
+ search(query, limit = 10) {
42
+ const queryTokens = this.tokenize(query);
43
+ const n = this.documents.size;
44
+ if (n === 0)
45
+ return [];
46
+ const scores = [];
47
+ for (const [docId, tokens] of this.tokenizedDocs.entries()) {
48
+ let score = 0;
49
+ const dl = this.docLengths.get(docId) || 0;
50
+ for (const qToken of queryTokens) {
51
+ const docFreq = this.df.get(qToken) || 0;
52
+ if (docFreq === 0)
53
+ continue;
54
+ // IDF = ln((N - df + 0.5) / (df + 0.5) + 1)
55
+ const idf = Math.log((n - docFreq + 0.5) / (docFreq + 0.5) + 1);
56
+ // Term frequency in document
57
+ const tf = tokens.filter(t => t === qToken).length;
58
+ // BM25 score component
59
+ const tfNorm = (tf * (this.k1 + 1)) / (tf + this.k1 * (1 - this.b + this.b * dl / this.avgDocLength));
60
+ score += idf * tfNorm;
61
+ }
62
+ if (score > 0) {
63
+ scores.push({ id: docId, score });
64
+ }
65
+ }
66
+ scores.sort((a, b) => b.score - a.score);
67
+ return scores.slice(0, limit).map(s => ({
68
+ key: s.id,
69
+ value: this.documents.get(s.id) || '',
70
+ score: s.score,
71
+ source: 'bm25',
72
+ }));
73
+ }
74
+ removeDocument(id) {
75
+ const tokens = this.tokenizedDocs.get(id);
76
+ if (tokens) {
77
+ const uniqueTokens = new Set(tokens);
78
+ for (const token of uniqueTokens) {
79
+ const count = this.df.get(token) || 0;
80
+ if (count <= 1) {
81
+ this.df.delete(token);
82
+ }
83
+ else {
84
+ this.df.set(token, count - 1);
85
+ }
86
+ }
87
+ }
88
+ this.documents.delete(id);
89
+ this.tokenizedDocs.delete(id);
90
+ this.docLengths.delete(id);
91
+ this.updateAvgDocLength();
92
+ }
93
+ getDocumentCount() {
94
+ return this.documents.size;
95
+ }
96
+ tokenize(text) {
97
+ return text
98
+ .toLowerCase()
99
+ .replace(/[^\w\s]/g, ' ')
100
+ .split(/\s+/)
101
+ .filter(t => t.length > 0);
102
+ }
103
+ updateAvgDocLength() {
104
+ if (this.docLengths.size === 0) {
105
+ this.avgDocLength = 0;
106
+ return;
107
+ }
108
+ let total = 0;
109
+ for (const len of this.docLengths.values()) {
110
+ total += len;
111
+ }
112
+ this.avgDocLength = total / this.docLengths.size;
113
+ }
114
+ }
115
+ // ============================================================================
116
+ // HybridMemorySearch
117
+ // ============================================================================
118
+ export class HybridMemorySearch {
119
+ static instance = null;
120
+ bm25Index;
121
+ bm25Weight = 0.7;
122
+ semanticWeight = 0.3;
123
+ constructor() {
124
+ this.bm25Index = new BM25Index();
125
+ }
126
+ static getInstance() {
127
+ if (!HybridMemorySearch.instance) {
128
+ HybridMemorySearch.instance = new HybridMemorySearch();
129
+ }
130
+ return HybridMemorySearch.instance;
131
+ }
132
+ static resetInstance() {
133
+ HybridMemorySearch.instance = null;
134
+ }
135
+ index(entries) {
136
+ for (const entry of entries) {
137
+ this.bm25Index.addDocument(entry.key, entry.value);
138
+ }
139
+ logger.debug('Indexed entries', { count: entries.length });
140
+ }
141
+ search(query, limit = 10) {
142
+ // BM25 search
143
+ const bm25Results = this.bm25Index.search(query, limit);
144
+ // Semantic search stub - returns empty for now
145
+ const semanticResults = [];
146
+ // If no semantic results, use BM25 at full weight
147
+ if (semanticResults.length === 0) {
148
+ return bm25Results.map(r => ({
149
+ ...r,
150
+ source: 'hybrid',
151
+ }));
152
+ }
153
+ // Hybrid merge (for future use when semantic is implemented)
154
+ return this.mergeResults(bm25Results, semanticResults, limit);
155
+ }
156
+ setWeights(bm25Weight, semanticWeight) {
157
+ this.bm25Weight = bm25Weight;
158
+ this.semanticWeight = semanticWeight;
159
+ }
160
+ getStats() {
161
+ return {
162
+ documentCount: this.bm25Index.getDocumentCount(),
163
+ bm25Weight: this.bm25Weight,
164
+ semanticWeight: this.semanticWeight,
165
+ };
166
+ }
167
+ clear() {
168
+ this.bm25Index = new BM25Index();
169
+ }
170
+ mergeResults(bm25, semantic, limit) {
171
+ const merged = new Map();
172
+ for (const r of bm25) {
173
+ merged.set(r.key, {
174
+ key: r.key,
175
+ value: r.value,
176
+ score: r.score * this.bm25Weight,
177
+ source: 'hybrid',
178
+ });
179
+ }
180
+ for (const r of semantic) {
181
+ const existing = merged.get(r.key);
182
+ if (existing) {
183
+ existing.score += r.score * this.semanticWeight;
184
+ }
185
+ else {
186
+ merged.set(r.key, {
187
+ key: r.key,
188
+ value: r.value,
189
+ score: r.score * this.semanticWeight,
190
+ source: 'hybrid',
191
+ });
192
+ }
193
+ }
194
+ return Array.from(merged.values())
195
+ .sort((a, b) => b.score - a.score)
196
+ .slice(0, limit);
197
+ }
198
+ }
199
+ //# sourceMappingURL=hybrid-search.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hybrid-search.js","sourceRoot":"","sources":["../../src/memory/hybrid-search.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Pre-Threshold Memory Flush + Plugin Memory Backends
3
+ * Flushes context before compaction and supports pluggable memory backends.
4
+ */
5
+ export interface SearchResult {
6
+ key: string;
7
+ value: string;
8
+ score: number;
9
+ }
10
+ export interface MemoryBackend {
11
+ name: string;
12
+ search(query: string, limit?: number): SearchResult[];
13
+ index(entries: Array<{
14
+ key: string;
15
+ value: string;
16
+ }>): void;
17
+ clear(): void;
18
+ }
19
+ export declare class PreThresholdFlusher {
20
+ private static instance;
21
+ private lastFlushTime;
22
+ private flushCount;
23
+ private flushPath;
24
+ constructor(flushPath?: string);
25
+ static getInstance(): PreThresholdFlusher;
26
+ static resetInstance(): void;
27
+ shouldFlush(currentTokens: number, maxTokens: number, threshold?: number): boolean;
28
+ flush(context: {
29
+ messages: unknown[];
30
+ keyFacts: string[];
31
+ }): {
32
+ flushed: boolean;
33
+ path: string;
34
+ };
35
+ getFlushPath(): string;
36
+ getLastFlushTime(): number;
37
+ getFlushCount(): number;
38
+ }
39
+ export declare class MemoryBackendManager {
40
+ private static instance;
41
+ private backends;
42
+ private activeBackendName;
43
+ constructor();
44
+ static getInstance(): MemoryBackendManager;
45
+ static resetInstance(): void;
46
+ registerBackend(backend: MemoryBackend): void;
47
+ getBackend(name: string): MemoryBackend | undefined;
48
+ setActiveBackend(name: string): void;
49
+ getActiveBackend(): MemoryBackend;
50
+ listBackends(): string[];
51
+ }
@@ -0,0 +1,102 @@
1
+ /**
2
+ * Pre-Threshold Memory Flush + Plugin Memory Backends
3
+ * Flushes context before compaction and supports pluggable memory backends.
4
+ */
5
+ import { logger } from '../utils/logger.js';
6
+ export class PreThresholdFlusher {
7
+ static instance = null;
8
+ lastFlushTime = 0;
9
+ flushCount = 0;
10
+ flushPath;
11
+ constructor(flushPath) {
12
+ this.flushPath = flushPath || '.codebuddy/memory-flush.json';
13
+ }
14
+ static getInstance() {
15
+ if (!PreThresholdFlusher.instance) {
16
+ PreThresholdFlusher.instance = new PreThresholdFlusher();
17
+ }
18
+ return PreThresholdFlusher.instance;
19
+ }
20
+ static resetInstance() {
21
+ PreThresholdFlusher.instance = null;
22
+ }
23
+ shouldFlush(currentTokens, maxTokens, threshold) {
24
+ const t = threshold ?? 0.8;
25
+ return currentTokens / maxTokens > t;
26
+ }
27
+ flush(context) {
28
+ this.lastFlushTime = Date.now();
29
+ this.flushCount++;
30
+ logger.debug(`Memory flush #${this.flushCount}: ${context.keyFacts.length} key facts`);
31
+ return { flushed: true, path: this.flushPath };
32
+ }
33
+ getFlushPath() {
34
+ return this.flushPath;
35
+ }
36
+ getLastFlushTime() {
37
+ return this.lastFlushTime;
38
+ }
39
+ getFlushCount() {
40
+ return this.flushCount;
41
+ }
42
+ }
43
+ class DefaultMemoryBackend {
44
+ name = 'default';
45
+ store = new Map();
46
+ search(query, limit) {
47
+ const results = [];
48
+ const queryLower = query.toLowerCase();
49
+ for (const [key, value] of this.store) {
50
+ const text = `${key} ${value}`.toLowerCase();
51
+ if (text.includes(queryLower)) {
52
+ results.push({ key, value, score: 1.0 });
53
+ }
54
+ }
55
+ return limit ? results.slice(0, limit) : results;
56
+ }
57
+ index(entries) {
58
+ for (const entry of entries) {
59
+ this.store.set(entry.key, entry.value);
60
+ }
61
+ }
62
+ clear() {
63
+ this.store.clear();
64
+ }
65
+ }
66
+ export class MemoryBackendManager {
67
+ static instance = null;
68
+ backends = new Map();
69
+ activeBackendName = 'default';
70
+ constructor() {
71
+ this.backends.set('default', new DefaultMemoryBackend());
72
+ }
73
+ static getInstance() {
74
+ if (!MemoryBackendManager.instance) {
75
+ MemoryBackendManager.instance = new MemoryBackendManager();
76
+ }
77
+ return MemoryBackendManager.instance;
78
+ }
79
+ static resetInstance() {
80
+ MemoryBackendManager.instance = null;
81
+ }
82
+ registerBackend(backend) {
83
+ this.backends.set(backend.name, backend);
84
+ logger.debug(`Registered memory backend: ${backend.name}`);
85
+ }
86
+ getBackend(name) {
87
+ return this.backends.get(name);
88
+ }
89
+ setActiveBackend(name) {
90
+ if (!this.backends.has(name)) {
91
+ throw new Error(`Memory backend '${name}' not found`);
92
+ }
93
+ this.activeBackendName = name;
94
+ }
95
+ getActiveBackend() {
96
+ return this.backends.get(this.activeBackendName);
97
+ }
98
+ listBackends() {
99
+ return Array.from(this.backends.keys());
100
+ }
101
+ }
102
+ //# sourceMappingURL=memory-flush.js.map