@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.
- package/dist/cli/claude-sm.js +51 -5
- package/dist/cli/claude-sm.js.map +2 -2
- package/dist/cli/codex-sm.js +52 -19
- package/dist/cli/codex-sm.js.map +2 -2
- package/dist/cli/commands/db.js +143 -0
- package/dist/cli/commands/db.js.map +7 -0
- package/dist/cli/commands/login.js +50 -0
- package/dist/cli/commands/login.js.map +7 -0
- package/dist/cli/commands/migrate.js +178 -0
- package/dist/cli/commands/migrate.js.map +7 -0
- package/dist/cli/commands/onboard.js +158 -2
- package/dist/cli/commands/onboard.js.map +2 -2
- package/dist/cli/commands/skills.js +15 -2
- package/dist/cli/commands/skills.js.map +2 -2
- package/dist/cli/index.js +118 -834
- package/dist/cli/index.js.map +3 -3
- package/dist/core/context/dual-stack-manager.js +1 -1
- package/dist/core/context/dual-stack-manager.js.map +1 -1
- package/dist/core/context/frame-database.js +1 -0
- package/dist/core/context/frame-database.js.map +2 -2
- package/dist/core/context/frame-manager.js +59 -2
- package/dist/core/context/frame-manager.js.map +2 -2
- package/dist/core/database/database-adapter.js +6 -1
- package/dist/core/database/database-adapter.js.map +2 -2
- package/dist/core/database/sqlite-adapter.js +60 -2
- package/dist/core/database/sqlite-adapter.js.map +2 -2
- package/dist/integrations/claude-code/subagent-client.js +106 -3
- package/dist/integrations/claude-code/subagent-client.js.map +2 -2
- package/dist/servers/railway/config.js +51 -0
- package/dist/servers/railway/config.js.map +7 -0
- package/dist/servers/railway/index-enhanced.js +156 -0
- package/dist/servers/railway/index-enhanced.js.map +7 -0
- package/dist/servers/railway/index.js +843 -82
- package/dist/servers/railway/index.js.map +3 -3
- package/dist/servers/railway/minimal.js +48 -3
- package/dist/servers/railway/minimal.js.map +2 -2
- package/dist/servers/railway/storage-test.js +455 -0
- package/dist/servers/railway/storage-test.js.map +7 -0
- package/dist/skills/claude-skills.js +13 -12
- package/dist/skills/claude-skills.js.map +2 -2
- package/dist/skills/recursive-agent-orchestrator.js +27 -18
- package/dist/skills/recursive-agent-orchestrator.js.map +2 -2
- package/dist/skills/unified-rlm-orchestrator.js.map +2 -2
- package/package.json +13 -21
- package/scripts/README-TESTING.md +186 -0
- package/scripts/analyze-cli-security.js +288 -0
- package/scripts/archive/add-phase-tasks-to-linear.js +163 -0
- package/scripts/archive/analyze-linear-duplicates.js +214 -0
- package/scripts/archive/analyze-remaining-duplicates.js +230 -0
- package/scripts/archive/analyze-sta-duplicates.js +292 -0
- package/scripts/archive/analyze-sta-graphql.js +399 -0
- package/scripts/archive/cancel-duplicate-tasks.ts +246 -0
- package/scripts/archive/check-all-duplicates.ts +419 -0
- package/scripts/archive/clean-duplicate-tasks.js +114 -0
- package/scripts/archive/cleanup-duplicate-tasks.ts +286 -0
- package/scripts/archive/create-phase-tasks.js +387 -0
- package/scripts/archive/delete-linear-duplicates.js +182 -0
- package/scripts/archive/delete-remaining-duplicates.js +158 -0
- package/scripts/archive/delete-sta-duplicates.js +201 -0
- package/scripts/archive/delete-sta-oauth.js +201 -0
- package/scripts/archive/export-sta-tasks.js +62 -0
- package/scripts/archive/install-auto-sync.js +266 -0
- package/scripts/archive/install-chromadb-hooks.sh +133 -0
- package/scripts/archive/install-enhanced-clear-hooks.sh +431 -0
- package/scripts/archive/install-post-task-hooks.sh +289 -0
- package/scripts/archive/install-stackmemory-hooks.sh +420 -0
- package/scripts/archive/merge-linear-duplicates-safe.ts +362 -0
- package/scripts/archive/merge-linear-duplicates.ts +180 -0
- package/scripts/archive/remove-sta-tasks.js +70 -0
- package/scripts/archive/setup-background-sync.sh +168 -0
- package/scripts/archive/setup-claude-auto-triggers.sh +181 -0
- package/scripts/archive/setup-claude-autostart.sh +305 -0
- package/scripts/archive/setup-git-hooks.sh +25 -0
- package/scripts/archive/setup-linear-oauth.sh +46 -0
- package/scripts/archive/setup-mcp.sh +113 -0
- package/scripts/archive/setup-railway-deployment.sh +81 -0
- package/scripts/auto-handoff.sh +262 -0
- package/scripts/background-sync-manager.js +416 -0
- package/scripts/benchmark-performance.ts +57 -0
- package/scripts/check-redis.ts +48 -0
- package/scripts/chromadb-auto-loader.sh +128 -0
- package/scripts/chromadb-context-loader.js +479 -0
- package/scripts/claude-chromadb-hook.js +460 -0
- package/scripts/claude-code-wrapper.sh +66 -0
- package/scripts/claude-linear-skill.js +455 -0
- package/scripts/claude-pre-commit.sh +302 -0
- package/scripts/claude-sm-autostart.js +532 -0
- package/scripts/claude-sm-setup.sh +367 -0
- package/scripts/claude-with-chromadb.sh +69 -0
- package/scripts/claude-worktree-manager.sh +323 -0
- package/scripts/claude-worktree-monitor.sh +371 -0
- package/scripts/claude-worktree-setup.sh +327 -0
- package/scripts/clean-linear-backlog.js +273 -0
- package/scripts/cleanup-old-sessions.sh +57 -0
- package/scripts/codex-wrapper.sh +88 -0
- package/scripts/create-sandbox.sh +269 -0
- package/scripts/debug-linear-update.js +174 -0
- package/scripts/delete-linear-tasks.js +167 -0
- package/scripts/deploy.sh +89 -0
- package/scripts/deployment/railway.sh +352 -0
- package/scripts/deployment/test-deployment.js +194 -0
- package/scripts/detect-and-rehydrate.js +162 -0
- package/scripts/detect-and-rehydrate.mjs +165 -0
- package/scripts/development/create-demo-tasks.js +143 -0
- package/scripts/development/debug-frame-test.js +16 -0
- package/scripts/development/demo-auto-sync.js +128 -0
- package/scripts/development/fix-all-imports.js +213 -0
- package/scripts/development/fix-imports.js +229 -0
- package/scripts/development/fix-lint-loop.cjs +103 -0
- package/scripts/development/fix-project-id.ts +161 -0
- package/scripts/development/fix-strict-mode-issues.ts +291 -0
- package/scripts/development/reorganize-structure.sh +228 -0
- package/scripts/development/test-persistence-direct.js +148 -0
- package/scripts/development/test-persistence.js +114 -0
- package/scripts/development/test-tasks.js +93 -0
- package/scripts/development/update-imports.js +212 -0
- package/scripts/fetch-linear-status.js +125 -0
- package/scripts/git-hooks/README.md +310 -0
- package/scripts/git-hooks/branch-context-manager.sh +342 -0
- package/scripts/git-hooks/post-checkout-stackmemory.sh +63 -0
- package/scripts/git-hooks/post-commit-stackmemory.sh +305 -0
- package/scripts/git-hooks/pre-commit-stackmemory.sh +275 -0
- package/scripts/hooks/cleanup-shell.sh +130 -0
- package/scripts/hooks/task-complete.sh +114 -0
- package/scripts/initialize.ts +129 -0
- package/scripts/install-claude-hooks-auto.js +104 -0
- package/scripts/install-claude-hooks.sh +133 -0
- package/scripts/install-global.sh +296 -0
- package/scripts/install.sh +235 -0
- package/scripts/linear-auto-sync.js +262 -0
- package/scripts/linear-auto-sync.sh +161 -0
- package/scripts/linear-sync-daemon.js +150 -0
- package/scripts/linear-task-review.js +237 -0
- package/scripts/list-linear-tasks.ts +178 -0
- package/scripts/mcp-proxy.js +66 -0
- package/scripts/opencode-wrapper.sh +85 -0
- package/scripts/publish-local.js +74 -0
- package/scripts/query-chromadb.ts +201 -0
- package/scripts/railway-env-setup.sh +39 -0
- package/scripts/reconcile-local-tasks.js +170 -0
- package/scripts/recreate-frames-db.js +89 -0
- package/scripts/setup/claude-integration.js +138 -0
- package/scripts/setup/configure-alias.js +125 -0
- package/scripts/setup/configure-codex-alias.js +161 -0
- package/scripts/setup/configure-opencode-alias.js +175 -0
- package/scripts/setup-claude-integration.js +204 -0
- package/scripts/setup-claude-integration.sh +183 -0
- package/scripts/setup-railway-deployment.sh +37 -0
- package/scripts/setup.sh +31 -0
- package/scripts/show-linear-summary.ts +172 -0
- package/scripts/stackmemory-auto-handoff.sh +231 -0
- package/scripts/stackmemory-daemon.sh +40 -0
- package/scripts/start-linear-sync-daemon.sh +141 -0
- package/scripts/start-temporal-paradox.sh +214 -0
- package/scripts/status.ts +159 -0
- package/scripts/sync-and-clean-tasks.js +258 -0
- package/scripts/sync-frames-from-railway.js +228 -0
- package/scripts/sync-linear-graphql.js +303 -0
- package/scripts/sync-linear-tasks.js +186 -0
- package/scripts/test-auto-triggers.sh +57 -0
- package/scripts/test-browser-mcp.js +74 -0
- package/scripts/test-chromadb-full.js +115 -0
- package/scripts/test-chromadb-hooks.sh +28 -0
- package/scripts/test-chromadb-sync.ts +245 -0
- package/scripts/test-cli-security.js +293 -0
- package/scripts/test-hooks-persistence.sh +220 -0
- package/scripts/test-installation-scenarios.sh +359 -0
- package/scripts/test-installation.sh +224 -0
- package/scripts/test-mcp.js +163 -0
- package/scripts/test-pre-publish-quick.sh +75 -0
- package/scripts/test-quality-gates.sh +263 -0
- package/scripts/test-railway-db.js +222 -0
- package/scripts/test-redis-storage.ts +490 -0
- package/scripts/test-rlm-basic.sh +122 -0
- package/scripts/test-rlm-comprehensive.sh +260 -0
- package/scripts/test-rlm-e2e.sh +268 -0
- package/scripts/test-rlm-simple.js +90 -0
- package/scripts/test-rlm.js +110 -0
- package/scripts/test-session-handoff.sh +165 -0
- package/scripts/test-shell-integration.sh +275 -0
- package/scripts/testing/ab-test-runner.ts +508 -0
- package/scripts/testing/collect-metrics.ts +457 -0
- package/scripts/testing/quick-effectiveness-demo.js +187 -0
- package/scripts/testing/real-performance-test.js +422 -0
- package/scripts/testing/run-effectiveness-tests.sh +176 -0
- package/scripts/testing/scripts/testing/ab-test-runner.js +363 -0
- package/scripts/testing/scripts/testing/collect-metrics.js +292 -0
- package/scripts/testing/simple-effectiveness-test.js +310 -0
- package/scripts/testing/src/core/context/context-bridge.js +253 -0
- package/scripts/testing/src/core/context/frame-manager.js +746 -0
- package/scripts/testing/src/core/context/shared-context-layer.js +437 -0
- package/scripts/testing/src/core/database/database-adapter.js +54 -0
- package/scripts/testing/src/core/errors/index.js +291 -0
- package/scripts/testing/src/core/errors/recovery.js +268 -0
- package/scripts/testing/src/core/monitoring/logger.js +145 -0
- package/scripts/testing/src/core/retrieval/context-retriever.js +516 -0
- package/scripts/testing/src/core/session/index.js +1 -0
- package/scripts/testing/src/core/session/session-manager.js +323 -0
- package/scripts/testing/src/core/trace/cli-trace-wrapper.js +140 -0
- package/scripts/testing/src/core/trace/db-trace-wrapper.js +251 -0
- package/scripts/testing/src/core/trace/debug-trace.js +398 -0
- package/scripts/testing/src/core/trace/index.js +120 -0
- package/scripts/testing/src/core/trace/linear-api-wrapper.js +204 -0
- package/scripts/update-linear-status.js +268 -0
- package/scripts/update-linear-tasks-fixed.js +284 -0
- package/scripts/verify-railway-schema.ts +35 -0
- package/templates/claude-hooks/hooks.json +5 -0
- package/templates/claude-hooks/on-clear.js +56 -0
- package/templates/claude-hooks/on-startup.js +56 -0
- package/templates/claude-hooks/tool-use-trace.js +67 -0
- package/dist/features/tui/components/analytics-panel.js +0 -157
- package/dist/features/tui/components/analytics-panel.js.map +0 -7
- package/dist/features/tui/components/frame-visualizer.js +0 -377
- package/dist/features/tui/components/frame-visualizer.js.map +0 -7
- package/dist/features/tui/components/pr-tracker.js +0 -135
- package/dist/features/tui/components/pr-tracker.js.map +0 -7
- package/dist/features/tui/components/session-monitor.js +0 -299
- package/dist/features/tui/components/session-monitor.js.map +0 -7
- package/dist/features/tui/components/subagent-fleet.js +0 -395
- package/dist/features/tui/components/subagent-fleet.js.map +0 -7
- package/dist/features/tui/components/task-board.js +0 -1139
- package/dist/features/tui/components/task-board.js.map +0 -7
- package/dist/features/tui/index.js +0 -408
- package/dist/features/tui/index.js.map +0 -7
- package/dist/features/tui/services/data-service.js +0 -641
- package/dist/features/tui/services/data-service.js.map +0 -7
- package/dist/features/tui/services/linear-task-reader.js +0 -102
- package/dist/features/tui/services/linear-task-reader.js.map +0 -7
- package/dist/features/tui/services/websocket-client.js +0 -162
- package/dist/features/tui/services/websocket-client.js.map +0 -7
- package/dist/features/tui/terminal-compat.js +0 -220
- package/dist/features/tui/terminal-compat.js.map +0 -7
- package/dist/features/tui/types.js +0 -1
- 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
|
+
}
|