@stackmemoryai/stackmemory 0.3.17 → 0.3.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 (234) hide show
  1. package/dist/cli/claude-sm.js +51 -5
  2. package/dist/cli/claude-sm.js.map +2 -2
  3. package/dist/cli/codex-sm.js +52 -19
  4. package/dist/cli/codex-sm.js.map +2 -2
  5. package/dist/cli/commands/db.js +143 -0
  6. package/dist/cli/commands/db.js.map +7 -0
  7. package/dist/cli/commands/login.js +50 -0
  8. package/dist/cli/commands/login.js.map +7 -0
  9. package/dist/cli/commands/migrate.js +178 -0
  10. package/dist/cli/commands/migrate.js.map +7 -0
  11. package/dist/cli/commands/onboard.js +158 -2
  12. package/dist/cli/commands/onboard.js.map +2 -2
  13. package/dist/cli/commands/skills.js +15 -2
  14. package/dist/cli/commands/skills.js.map +2 -2
  15. package/dist/cli/index.js +118 -834
  16. package/dist/cli/index.js.map +3 -3
  17. package/dist/core/context/dual-stack-manager.js +1 -1
  18. package/dist/core/context/dual-stack-manager.js.map +1 -1
  19. package/dist/core/context/frame-database.js +1 -0
  20. package/dist/core/context/frame-database.js.map +2 -2
  21. package/dist/core/context/frame-manager.js +59 -2
  22. package/dist/core/context/frame-manager.js.map +2 -2
  23. package/dist/core/database/database-adapter.js +6 -1
  24. package/dist/core/database/database-adapter.js.map +2 -2
  25. package/dist/core/database/sqlite-adapter.js +60 -2
  26. package/dist/core/database/sqlite-adapter.js.map +2 -2
  27. package/dist/integrations/claude-code/subagent-client.js +106 -3
  28. package/dist/integrations/claude-code/subagent-client.js.map +2 -2
  29. package/dist/servers/railway/config.js +51 -0
  30. package/dist/servers/railway/config.js.map +7 -0
  31. package/dist/servers/railway/index-enhanced.js +156 -0
  32. package/dist/servers/railway/index-enhanced.js.map +7 -0
  33. package/dist/servers/railway/index.js +843 -82
  34. package/dist/servers/railway/index.js.map +3 -3
  35. package/dist/servers/railway/minimal.js +48 -3
  36. package/dist/servers/railway/minimal.js.map +2 -2
  37. package/dist/servers/railway/storage-test.js +455 -0
  38. package/dist/servers/railway/storage-test.js.map +7 -0
  39. package/dist/skills/claude-skills.js +13 -12
  40. package/dist/skills/claude-skills.js.map +2 -2
  41. package/dist/skills/recursive-agent-orchestrator.js +27 -18
  42. package/dist/skills/recursive-agent-orchestrator.js.map +2 -2
  43. package/dist/skills/unified-rlm-orchestrator.js.map +2 -2
  44. package/package.json +13 -21
  45. package/scripts/README-TESTING.md +186 -0
  46. package/scripts/analyze-cli-security.js +288 -0
  47. package/scripts/archive/add-phase-tasks-to-linear.js +163 -0
  48. package/scripts/archive/analyze-linear-duplicates.js +214 -0
  49. package/scripts/archive/analyze-remaining-duplicates.js +230 -0
  50. package/scripts/archive/analyze-sta-duplicates.js +292 -0
  51. package/scripts/archive/analyze-sta-graphql.js +399 -0
  52. package/scripts/archive/cancel-duplicate-tasks.ts +246 -0
  53. package/scripts/archive/check-all-duplicates.ts +419 -0
  54. package/scripts/archive/clean-duplicate-tasks.js +114 -0
  55. package/scripts/archive/cleanup-duplicate-tasks.ts +286 -0
  56. package/scripts/archive/create-phase-tasks.js +387 -0
  57. package/scripts/archive/delete-linear-duplicates.js +182 -0
  58. package/scripts/archive/delete-remaining-duplicates.js +158 -0
  59. package/scripts/archive/delete-sta-duplicates.js +201 -0
  60. package/scripts/archive/delete-sta-oauth.js +201 -0
  61. package/scripts/archive/export-sta-tasks.js +62 -0
  62. package/scripts/archive/install-auto-sync.js +266 -0
  63. package/scripts/archive/install-chromadb-hooks.sh +133 -0
  64. package/scripts/archive/install-enhanced-clear-hooks.sh +431 -0
  65. package/scripts/archive/install-post-task-hooks.sh +289 -0
  66. package/scripts/archive/install-stackmemory-hooks.sh +420 -0
  67. package/scripts/archive/merge-linear-duplicates-safe.ts +362 -0
  68. package/scripts/archive/merge-linear-duplicates.ts +180 -0
  69. package/scripts/archive/remove-sta-tasks.js +70 -0
  70. package/scripts/archive/setup-background-sync.sh +168 -0
  71. package/scripts/archive/setup-claude-auto-triggers.sh +181 -0
  72. package/scripts/archive/setup-claude-autostart.sh +305 -0
  73. package/scripts/archive/setup-git-hooks.sh +25 -0
  74. package/scripts/archive/setup-linear-oauth.sh +46 -0
  75. package/scripts/archive/setup-mcp.sh +113 -0
  76. package/scripts/archive/setup-railway-deployment.sh +81 -0
  77. package/scripts/auto-handoff.sh +262 -0
  78. package/scripts/background-sync-manager.js +416 -0
  79. package/scripts/benchmark-performance.ts +57 -0
  80. package/scripts/check-redis.ts +48 -0
  81. package/scripts/chromadb-auto-loader.sh +128 -0
  82. package/scripts/chromadb-context-loader.js +479 -0
  83. package/scripts/claude-chromadb-hook.js +460 -0
  84. package/scripts/claude-code-wrapper.sh +66 -0
  85. package/scripts/claude-linear-skill.js +455 -0
  86. package/scripts/claude-pre-commit.sh +302 -0
  87. package/scripts/claude-sm-autostart.js +532 -0
  88. package/scripts/claude-sm-setup.sh +367 -0
  89. package/scripts/claude-with-chromadb.sh +69 -0
  90. package/scripts/claude-worktree-manager.sh +323 -0
  91. package/scripts/claude-worktree-monitor.sh +371 -0
  92. package/scripts/claude-worktree-setup.sh +327 -0
  93. package/scripts/clean-linear-backlog.js +273 -0
  94. package/scripts/cleanup-old-sessions.sh +57 -0
  95. package/scripts/codex-wrapper.sh +88 -0
  96. package/scripts/create-sandbox.sh +269 -0
  97. package/scripts/debug-linear-update.js +174 -0
  98. package/scripts/delete-linear-tasks.js +167 -0
  99. package/scripts/deploy.sh +89 -0
  100. package/scripts/deployment/railway.sh +352 -0
  101. package/scripts/deployment/test-deployment.js +194 -0
  102. package/scripts/detect-and-rehydrate.js +162 -0
  103. package/scripts/detect-and-rehydrate.mjs +165 -0
  104. package/scripts/development/create-demo-tasks.js +143 -0
  105. package/scripts/development/debug-frame-test.js +16 -0
  106. package/scripts/development/demo-auto-sync.js +128 -0
  107. package/scripts/development/fix-all-imports.js +213 -0
  108. package/scripts/development/fix-imports.js +229 -0
  109. package/scripts/development/fix-lint-loop.cjs +103 -0
  110. package/scripts/development/fix-project-id.ts +161 -0
  111. package/scripts/development/fix-strict-mode-issues.ts +291 -0
  112. package/scripts/development/reorganize-structure.sh +228 -0
  113. package/scripts/development/test-persistence-direct.js +148 -0
  114. package/scripts/development/test-persistence.js +114 -0
  115. package/scripts/development/test-tasks.js +93 -0
  116. package/scripts/development/update-imports.js +212 -0
  117. package/scripts/fetch-linear-status.js +125 -0
  118. package/scripts/git-hooks/README.md +310 -0
  119. package/scripts/git-hooks/branch-context-manager.sh +342 -0
  120. package/scripts/git-hooks/post-checkout-stackmemory.sh +63 -0
  121. package/scripts/git-hooks/post-commit-stackmemory.sh +305 -0
  122. package/scripts/git-hooks/pre-commit-stackmemory.sh +275 -0
  123. package/scripts/hooks/cleanup-shell.sh +130 -0
  124. package/scripts/hooks/task-complete.sh +114 -0
  125. package/scripts/initialize.ts +129 -0
  126. package/scripts/install-claude-hooks-auto.js +104 -0
  127. package/scripts/install-claude-hooks.sh +133 -0
  128. package/scripts/install-global.sh +296 -0
  129. package/scripts/install.sh +235 -0
  130. package/scripts/linear-auto-sync.js +262 -0
  131. package/scripts/linear-auto-sync.sh +161 -0
  132. package/scripts/linear-sync-daemon.js +150 -0
  133. package/scripts/linear-task-review.js +237 -0
  134. package/scripts/list-linear-tasks.ts +178 -0
  135. package/scripts/mcp-proxy.js +66 -0
  136. package/scripts/opencode-wrapper.sh +85 -0
  137. package/scripts/publish-local.js +74 -0
  138. package/scripts/query-chromadb.ts +201 -0
  139. package/scripts/railway-env-setup.sh +39 -0
  140. package/scripts/reconcile-local-tasks.js +170 -0
  141. package/scripts/recreate-frames-db.js +89 -0
  142. package/scripts/setup/claude-integration.js +138 -0
  143. package/scripts/setup/configure-alias.js +125 -0
  144. package/scripts/setup/configure-codex-alias.js +161 -0
  145. package/scripts/setup/configure-opencode-alias.js +175 -0
  146. package/scripts/setup-claude-integration.js +204 -0
  147. package/scripts/setup-claude-integration.sh +183 -0
  148. package/scripts/setup-railway-deployment.sh +37 -0
  149. package/scripts/setup.sh +31 -0
  150. package/scripts/show-linear-summary.ts +172 -0
  151. package/scripts/stackmemory-auto-handoff.sh +231 -0
  152. package/scripts/stackmemory-daemon.sh +40 -0
  153. package/scripts/start-linear-sync-daemon.sh +141 -0
  154. package/scripts/start-temporal-paradox.sh +214 -0
  155. package/scripts/status.ts +159 -0
  156. package/scripts/sync-and-clean-tasks.js +258 -0
  157. package/scripts/sync-frames-from-railway.js +228 -0
  158. package/scripts/sync-linear-graphql.js +303 -0
  159. package/scripts/sync-linear-tasks.js +186 -0
  160. package/scripts/test-auto-triggers.sh +57 -0
  161. package/scripts/test-browser-mcp.js +74 -0
  162. package/scripts/test-chromadb-full.js +115 -0
  163. package/scripts/test-chromadb-hooks.sh +28 -0
  164. package/scripts/test-chromadb-sync.ts +245 -0
  165. package/scripts/test-cli-security.js +293 -0
  166. package/scripts/test-hooks-persistence.sh +220 -0
  167. package/scripts/test-installation-scenarios.sh +359 -0
  168. package/scripts/test-installation.sh +224 -0
  169. package/scripts/test-mcp.js +163 -0
  170. package/scripts/test-pre-publish-quick.sh +75 -0
  171. package/scripts/test-quality-gates.sh +263 -0
  172. package/scripts/test-railway-db.js +222 -0
  173. package/scripts/test-redis-storage.ts +490 -0
  174. package/scripts/test-rlm-basic.sh +122 -0
  175. package/scripts/test-rlm-comprehensive.sh +260 -0
  176. package/scripts/test-rlm-e2e.sh +268 -0
  177. package/scripts/test-rlm-simple.js +90 -0
  178. package/scripts/test-rlm.js +110 -0
  179. package/scripts/test-session-handoff.sh +165 -0
  180. package/scripts/test-shell-integration.sh +275 -0
  181. package/scripts/testing/ab-test-runner.ts +508 -0
  182. package/scripts/testing/collect-metrics.ts +457 -0
  183. package/scripts/testing/quick-effectiveness-demo.js +187 -0
  184. package/scripts/testing/real-performance-test.js +422 -0
  185. package/scripts/testing/run-effectiveness-tests.sh +176 -0
  186. package/scripts/testing/scripts/testing/ab-test-runner.js +363 -0
  187. package/scripts/testing/scripts/testing/collect-metrics.js +292 -0
  188. package/scripts/testing/simple-effectiveness-test.js +310 -0
  189. package/scripts/testing/src/core/context/context-bridge.js +253 -0
  190. package/scripts/testing/src/core/context/frame-manager.js +746 -0
  191. package/scripts/testing/src/core/context/shared-context-layer.js +437 -0
  192. package/scripts/testing/src/core/database/database-adapter.js +54 -0
  193. package/scripts/testing/src/core/errors/index.js +291 -0
  194. package/scripts/testing/src/core/errors/recovery.js +268 -0
  195. package/scripts/testing/src/core/monitoring/logger.js +145 -0
  196. package/scripts/testing/src/core/retrieval/context-retriever.js +516 -0
  197. package/scripts/testing/src/core/session/index.js +1 -0
  198. package/scripts/testing/src/core/session/session-manager.js +323 -0
  199. package/scripts/testing/src/core/trace/cli-trace-wrapper.js +140 -0
  200. package/scripts/testing/src/core/trace/db-trace-wrapper.js +251 -0
  201. package/scripts/testing/src/core/trace/debug-trace.js +398 -0
  202. package/scripts/testing/src/core/trace/index.js +120 -0
  203. package/scripts/testing/src/core/trace/linear-api-wrapper.js +204 -0
  204. package/scripts/update-linear-status.js +268 -0
  205. package/scripts/update-linear-tasks-fixed.js +284 -0
  206. package/scripts/verify-railway-schema.ts +35 -0
  207. package/templates/claude-hooks/hooks.json +5 -0
  208. package/templates/claude-hooks/on-clear.js +56 -0
  209. package/templates/claude-hooks/on-startup.js +56 -0
  210. package/templates/claude-hooks/tool-use-trace.js +67 -0
  211. package/dist/features/tui/components/analytics-panel.js +0 -157
  212. package/dist/features/tui/components/analytics-panel.js.map +0 -7
  213. package/dist/features/tui/components/frame-visualizer.js +0 -377
  214. package/dist/features/tui/components/frame-visualizer.js.map +0 -7
  215. package/dist/features/tui/components/pr-tracker.js +0 -135
  216. package/dist/features/tui/components/pr-tracker.js.map +0 -7
  217. package/dist/features/tui/components/session-monitor.js +0 -299
  218. package/dist/features/tui/components/session-monitor.js.map +0 -7
  219. package/dist/features/tui/components/subagent-fleet.js +0 -395
  220. package/dist/features/tui/components/subagent-fleet.js.map +0 -7
  221. package/dist/features/tui/components/task-board.js +0 -1139
  222. package/dist/features/tui/components/task-board.js.map +0 -7
  223. package/dist/features/tui/index.js +0 -408
  224. package/dist/features/tui/index.js.map +0 -7
  225. package/dist/features/tui/services/data-service.js +0 -641
  226. package/dist/features/tui/services/data-service.js.map +0 -7
  227. package/dist/features/tui/services/linear-task-reader.js +0 -102
  228. package/dist/features/tui/services/linear-task-reader.js.map +0 -7
  229. package/dist/features/tui/services/websocket-client.js +0 -162
  230. package/dist/features/tui/services/websocket-client.js.map +0 -7
  231. package/dist/features/tui/terminal-compat.js +0 -220
  232. package/dist/features/tui/terminal-compat.js.map +0 -7
  233. package/dist/features/tui/types.js +0 -1
  234. package/dist/features/tui/types.js.map +0 -7
@@ -0,0 +1,479 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * ChromaDB Context Loader
5
+ * Loads and synchronizes context from ChromaDB for Claude sessions
6
+ */
7
+
8
+ import { CloudClient } from 'chromadb';
9
+ import fs from 'fs';
10
+ import path from 'path';
11
+ import { fileURLToPath } from 'url';
12
+ import dotenv from 'dotenv';
13
+ import chalk from 'chalk';
14
+ import { exec } from 'child_process';
15
+ import { promisify } from 'util';
16
+
17
+ const execAsync = promisify(exec);
18
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
19
+
20
+ // Load environment variables
21
+ dotenv.config({
22
+ path: path.join(__dirname, '..', '.env'),
23
+ override: true,
24
+ silent: true
25
+ });
26
+
27
+ class ContextLoader {
28
+ constructor() {
29
+ this.config = {
30
+ apiKey: process.env.CHROMADB_API_KEY,
31
+ tenant: process.env.CHROMADB_TENANT,
32
+ database: process.env.CHROMADB_DATABASE || 'stackmemory',
33
+ };
34
+
35
+ this.userId = process.env.USER || 'claude';
36
+ this.projectName = path.basename(process.cwd());
37
+ this.client = null;
38
+ this.collection = null;
39
+ }
40
+
41
+ async initialize() {
42
+ try {
43
+ this.client = new CloudClient({
44
+ apiKey: this.config.apiKey,
45
+ tenant: this.config.tenant,
46
+ database: this.config.database,
47
+ });
48
+
49
+ this.collection = await this.client.getOrCreateCollection({
50
+ name: 'claude_contexts',
51
+ });
52
+
53
+ return true;
54
+ } catch (error) {
55
+ console.error(chalk.red('Failed to initialize ChromaDB:'), error.message);
56
+ return false;
57
+ }
58
+ }
59
+
60
+ /**
61
+ * Load recent context from ChromaDB
62
+ */
63
+ async loadRecentContext(hours = 24) {
64
+ console.log(chalk.cyan(`\nšŸ“„ Loading context from last ${hours} hours...\n`));
65
+
66
+ const cutoffTime = Date.now() - (hours * 60 * 60 * 1000);
67
+
68
+ try {
69
+ const results = await this.collection.get({
70
+ where: {
71
+ $and: [
72
+ { user_id: { $eq: this.userId } },
73
+ { project_name: { $eq: this.projectName } },
74
+ { timestamp: { $gte: cutoffTime } }
75
+ ]
76
+ },
77
+ include: ['documents', 'metadatas'],
78
+ });
79
+
80
+ if (!results.documents || results.documents.length === 0) {
81
+ console.log(chalk.yellow('No recent context found'));
82
+ return [];
83
+ }
84
+
85
+ // Group by type
86
+ const contextsByType = {};
87
+ for (let i = 0; i < results.documents.length; i++) {
88
+ const doc = results.documents[i];
89
+ const meta = results.metadatas[i];
90
+ const type = meta.type || 'unknown';
91
+
92
+ if (!contextsByType[type]) {
93
+ contextsByType[type] = [];
94
+ }
95
+
96
+ contextsByType[type].push({
97
+ content: doc,
98
+ metadata: meta,
99
+ time: new Date(meta.timestamp).toLocaleString(),
100
+ });
101
+ }
102
+
103
+ // Display organized context
104
+ console.log(chalk.green(`Found ${results.documents.length} contexts:\n`));
105
+
106
+ for (const [type, contexts] of Object.entries(contextsByType)) {
107
+ console.log(chalk.bold.blue(`\n${type.toUpperCase()} (${contexts.length}):`));
108
+ console.log('─'.repeat(50));
109
+
110
+ for (const ctx of contexts.slice(0, 5)) { // Show first 5 of each type
111
+ console.log(chalk.gray(`[${ctx.time}]`));
112
+ console.log(ctx.content.substring(0, 200));
113
+ if (ctx.content.length > 200) {
114
+ console.log(chalk.gray('...'));
115
+ }
116
+ console.log();
117
+ }
118
+
119
+ if (contexts.length > 5) {
120
+ console.log(chalk.gray(`... and ${contexts.length - 5} more ${type} contexts\n`));
121
+ }
122
+ }
123
+
124
+ return results.documents;
125
+ } catch (error) {
126
+ console.error(chalk.red('Failed to load context:'), error.message);
127
+ return [];
128
+ }
129
+ }
130
+
131
+ /**
132
+ * Load context for specific query
133
+ */
134
+ async loadQueryContext(query, limit = 10) {
135
+ console.log(chalk.cyan(`\nšŸ” Searching for: "${query}"\n`));
136
+
137
+ try {
138
+ const results = await this.collection.query({
139
+ queryTexts: [query],
140
+ nResults: limit,
141
+ where: {
142
+ user_id: this.userId,
143
+ project_name: this.projectName,
144
+ },
145
+ include: ['documents', 'metadatas', 'distances'],
146
+ });
147
+
148
+ if (!results.documents || !results.documents[0] || results.documents[0].length === 0) {
149
+ console.log(chalk.yellow('No matching contexts found'));
150
+ return [];
151
+ }
152
+
153
+ console.log(chalk.green(`Found ${results.documents[0].length} relevant contexts:\n`));
154
+
155
+ for (let i = 0; i < results.documents[0].length; i++) {
156
+ const doc = results.documents[0][i];
157
+ const meta = results.metadatas[0][i];
158
+ const distance = results.distances[0][i];
159
+ const relevance = ((1 - distance) * 100).toFixed(1);
160
+
161
+ console.log(chalk.bold(`${i + 1}. [${meta.type}] Relevance: ${relevance}%`));
162
+ console.log(chalk.gray(`Time: ${new Date(meta.timestamp).toLocaleString()}`));
163
+ console.log('─'.repeat(50));
164
+ console.log(doc.substring(0, 300));
165
+ if (doc.length > 300) {
166
+ console.log(chalk.gray('...'));
167
+ }
168
+ console.log();
169
+ }
170
+
171
+ return results.documents[0];
172
+ } catch (error) {
173
+ console.error(chalk.red('Failed to search context:'), error.message);
174
+ return [];
175
+ }
176
+ }
177
+
178
+ /**
179
+ * Track changes in the project
180
+ */
181
+ async trackChanges() {
182
+ console.log(chalk.cyan('\nšŸ“ Tracking recent changes...\n'));
183
+
184
+ try {
185
+ // Get git status
186
+ const { stdout: gitStatus } = await execAsync('git status --short');
187
+ if (gitStatus) {
188
+ console.log(chalk.bold('Git Changes:'));
189
+ console.log(gitStatus);
190
+
191
+ // Store changes in ChromaDB
192
+ await this.storeContext('file_change', `Git status:\n${gitStatus}`, {
193
+ change_type: 'git_status',
194
+ });
195
+ }
196
+
197
+ // Get recent commits
198
+ const { stdout: gitLog } = await execAsync('git log --oneline -10');
199
+ console.log(chalk.bold('\nRecent Commits:'));
200
+ console.log(gitLog);
201
+
202
+ // Check for uncommitted changes in key files
203
+ const { stdout: diffStat } = await execAsync('git diff --stat');
204
+ if (diffStat) {
205
+ console.log(chalk.bold('\nUncommitted Changes:'));
206
+ console.log(diffStat);
207
+ }
208
+
209
+ // Load recent file change contexts from ChromaDB
210
+ const results = await this.collection.get({
211
+ where: {
212
+ user_id: this.userId,
213
+ project_name: this.projectName,
214
+ type: 'file_change',
215
+ timestamp: { $gte: Date.now() - (24 * 60 * 60 * 1000) }, // Last 24 hours
216
+ },
217
+ include: ['documents', 'metadatas'],
218
+ limit: 10,
219
+ });
220
+
221
+ if (results.documents && results.documents.length > 0) {
222
+ console.log(chalk.bold('\nšŸ“Š Tracked Changes (Last 24h):'));
223
+ console.log('─'.repeat(50));
224
+
225
+ for (let i = 0; i < results.documents.length; i++) {
226
+ const meta = results.metadatas[i];
227
+ const time = new Date(meta.timestamp).toLocaleTimeString();
228
+ console.log(chalk.gray(`[${time}]`), results.documents[i].substring(0, 100));
229
+ }
230
+ }
231
+
232
+ } catch (error) {
233
+ console.error(chalk.red('Failed to track changes:'), error.message);
234
+ }
235
+ }
236
+
237
+ /**
238
+ * Store context in ChromaDB
239
+ */
240
+ async storeContext(type, content, metadata = {}) {
241
+ try {
242
+ const contextId = `${type}_${Date.now()}_${this.userId}`;
243
+
244
+ const docMetadata = {
245
+ user_id: this.userId,
246
+ project_name: this.projectName,
247
+ type: type,
248
+ timestamp: Date.now(),
249
+ ...metadata,
250
+ };
251
+
252
+ await this.collection.add({
253
+ ids: [contextId],
254
+ documents: [content],
255
+ metadatas: [docMetadata],
256
+ });
257
+
258
+ return true;
259
+ } catch (error) {
260
+ console.error(chalk.red(`Failed to store ${type}:`), error.message);
261
+ return false;
262
+ }
263
+ }
264
+
265
+ /**
266
+ * Sync context with StackMemory
267
+ */
268
+ async syncWithStackMemory() {
269
+ console.log(chalk.cyan('\nšŸ”„ Syncing with StackMemory...\n'));
270
+
271
+ try {
272
+ // Get recent contexts from ChromaDB
273
+ const contexts = await this.loadRecentContext(1); // Last hour
274
+
275
+ if (contexts.length === 0) {
276
+ console.log(chalk.yellow('No recent contexts to sync'));
277
+ return;
278
+ }
279
+
280
+ // Save to StackMemory shared context
281
+ const sharedContextDir = path.join(
282
+ process.env.HOME,
283
+ '.stackmemory',
284
+ 'shared-context',
285
+ 'projects'
286
+ );
287
+
288
+ if (!fs.existsSync(sharedContextDir)) {
289
+ fs.mkdirSync(sharedContextDir, { recursive: true });
290
+ }
291
+
292
+ const projectFile = path.join(sharedContextDir, `${this.projectName}.json`);
293
+
294
+ let projectData = {
295
+ name: this.projectName,
296
+ lastSync: new Date().toISOString(),
297
+ contexts: [],
298
+ chromadb_sync: true,
299
+ };
300
+
301
+ if (fs.existsSync(projectFile)) {
302
+ projectData = JSON.parse(fs.readFileSync(projectFile, 'utf8'));
303
+ }
304
+
305
+ // Add ChromaDB contexts
306
+ projectData.contexts.push({
307
+ source: 'chromadb',
308
+ timestamp: Date.now(),
309
+ count: contexts.length,
310
+ summary: `Synced ${contexts.length} contexts from ChromaDB`,
311
+ });
312
+
313
+ // Keep only recent contexts (last 100)
314
+ projectData.contexts = projectData.contexts.slice(-100);
315
+
316
+ fs.writeFileSync(projectFile, JSON.stringify(projectData, null, 2));
317
+
318
+ console.log(chalk.green(`āœ… Synced ${contexts.length} contexts to StackMemory`));
319
+ console.log(chalk.gray(`Location: ${projectFile}`));
320
+
321
+ } catch (error) {
322
+ console.error(chalk.red('Sync failed:'), error.message);
323
+ }
324
+ }
325
+
326
+ /**
327
+ * Generate context summary
328
+ */
329
+ async generateSummary() {
330
+ console.log(chalk.cyan('\nšŸ“Š Context Summary\n'));
331
+
332
+ try {
333
+ // Get all contexts
334
+ const results = await this.collection.get({
335
+ where: {
336
+ user_id: this.userId,
337
+ project_name: this.projectName,
338
+ },
339
+ include: ['metadatas'],
340
+ });
341
+
342
+ if (!results.metadatas || results.metadatas.length === 0) {
343
+ console.log(chalk.yellow('No contexts found'));
344
+ return;
345
+ }
346
+
347
+ // Analyze contexts
348
+ const stats = {
349
+ total: results.metadatas.length,
350
+ byType: {},
351
+ byDay: {},
352
+ oldestTimestamp: Infinity,
353
+ newestTimestamp: 0,
354
+ };
355
+
356
+ for (const meta of results.metadatas) {
357
+ // By type
358
+ const type = meta.type || 'unknown';
359
+ stats.byType[type] = (stats.byType[type] || 0) + 1;
360
+
361
+ // By day
362
+ const day = new Date(meta.timestamp).toLocaleDateString();
363
+ stats.byDay[day] = (stats.byDay[day] || 0) + 1;
364
+
365
+ // Time range
366
+ if (meta.timestamp < stats.oldestTimestamp) {
367
+ stats.oldestTimestamp = meta.timestamp;
368
+ }
369
+ if (meta.timestamp > stats.newestTimestamp) {
370
+ stats.newestTimestamp = meta.timestamp;
371
+ }
372
+ }
373
+
374
+ // Display summary
375
+ console.log(chalk.bold('Context Statistics:'));
376
+ console.log('─'.repeat(50));
377
+ console.log(`Total Contexts: ${chalk.green(stats.total)}`);
378
+ console.log(`Time Range: ${new Date(stats.oldestTimestamp).toLocaleDateString()} - ${new Date(stats.newestTimestamp).toLocaleDateString()}`);
379
+
380
+ console.log(chalk.bold('\nBy Type:'));
381
+ for (const [type, count] of Object.entries(stats.byType)) {
382
+ const percentage = ((count / stats.total) * 100).toFixed(1);
383
+ console.log(` ${type}: ${count} (${percentage}%)`);
384
+ }
385
+
386
+ console.log(chalk.bold('\nRecent Activity:'));
387
+ const recentDays = Object.entries(stats.byDay)
388
+ .sort((a, b) => new Date(b[0]) - new Date(a[0]))
389
+ .slice(0, 5);
390
+
391
+ for (const [day, count] of recentDays) {
392
+ console.log(` ${day}: ${count} contexts`);
393
+ }
394
+
395
+ } catch (error) {
396
+ console.error(chalk.red('Failed to generate summary:'), error.message);
397
+ }
398
+ }
399
+ }
400
+
401
+ // CLI Commands
402
+ async function main() {
403
+ const loader = new ContextLoader();
404
+
405
+ if (!await loader.initialize()) {
406
+ process.exit(1);
407
+ }
408
+
409
+ const command = process.argv[2] || 'load';
410
+ const arg = process.argv[3];
411
+
412
+ switch (command) {
413
+ case 'load':
414
+ // Load recent context
415
+ const hours = parseInt(arg) || 24;
416
+ await loader.loadRecentContext(hours);
417
+ break;
418
+
419
+ case 'search':
420
+ case 'query':
421
+ // Search for specific context
422
+ if (!arg) {
423
+ console.log(chalk.red('Please provide a search query'));
424
+ process.exit(1);
425
+ }
426
+ await loader.loadQueryContext(arg);
427
+ break;
428
+
429
+ case 'changes':
430
+ case 'track':
431
+ // Track recent changes
432
+ await loader.trackChanges();
433
+ break;
434
+
435
+ case 'sync':
436
+ // Sync with StackMemory
437
+ await loader.syncWithStackMemory();
438
+ break;
439
+
440
+ case 'summary':
441
+ case 'stats':
442
+ // Generate summary
443
+ await loader.generateSummary();
444
+ break;
445
+
446
+ case 'auto':
447
+ // Full auto-load workflow
448
+ console.log(chalk.bold.cyan('\nšŸ¤– Auto-Loading Context...\n'));
449
+ await loader.loadRecentContext(24);
450
+ await loader.trackChanges();
451
+ await loader.syncWithStackMemory();
452
+ await loader.generateSummary();
453
+ break;
454
+
455
+ default:
456
+ console.log(chalk.yellow('ChromaDB Context Loader'));
457
+ console.log(chalk.gray('─'.repeat(50)));
458
+ console.log('Commands:');
459
+ console.log(' load [hours] - Load recent context (default: 24h)');
460
+ console.log(' search <query> - Search for specific context');
461
+ console.log(' changes - Track recent file changes');
462
+ console.log(' sync - Sync with StackMemory');
463
+ console.log(' summary - Generate context summary');
464
+ console.log(' auto - Run full auto-load workflow');
465
+ console.log();
466
+ console.log('Examples:');
467
+ console.log(' node chromadb-context-loader.js load 48');
468
+ console.log(' node chromadb-context-loader.js search "API implementation"');
469
+ console.log(' node chromadb-context-loader.js auto');
470
+ }
471
+ }
472
+
473
+ // Run if called directly
474
+ if (import.meta.url === `file://${process.argv[1]}`) {
475
+ main().catch(error => {
476
+ console.error(chalk.red('Fatal error:'), error);
477
+ process.exit(1);
478
+ });
479
+ }