claude-memory-layer 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/commands/memory-forget.md +42 -0
- package/.claude-plugin/commands/memory-history.md +34 -0
- package/.claude-plugin/commands/memory-import.md +56 -0
- package/.claude-plugin/commands/memory-list.md +37 -0
- package/.claude-plugin/commands/memory-search.md +36 -0
- package/.claude-plugin/commands/memory-stats.md +34 -0
- package/.claude-plugin/hooks.json +59 -0
- package/.claude-plugin/plugin.json +24 -0
- package/.history/package_20260201112328.json +45 -0
- package/.history/package_20260201113602.json +45 -0
- package/.history/package_20260201113713.json +45 -0
- package/.history/package_20260201114110.json +45 -0
- package/Memo.txt +558 -0
- package/README.md +520 -0
- package/context.md +636 -0
- package/dist/.claude-plugin/commands/memory-forget.md +42 -0
- package/dist/.claude-plugin/commands/memory-history.md +34 -0
- package/dist/.claude-plugin/commands/memory-import.md +56 -0
- package/dist/.claude-plugin/commands/memory-list.md +37 -0
- package/dist/.claude-plugin/commands/memory-search.md +36 -0
- package/dist/.claude-plugin/commands/memory-stats.md +34 -0
- package/dist/.claude-plugin/hooks.json +59 -0
- package/dist/.claude-plugin/plugin.json +24 -0
- package/dist/cli/index.js +3539 -0
- package/dist/cli/index.js.map +7 -0
- package/dist/core/index.js +4408 -0
- package/dist/core/index.js.map +7 -0
- package/dist/hooks/session-end.js +2971 -0
- package/dist/hooks/session-end.js.map +7 -0
- package/dist/hooks/session-start.js +2969 -0
- package/dist/hooks/session-start.js.map +7 -0
- package/dist/hooks/stop.js +3123 -0
- package/dist/hooks/stop.js.map +7 -0
- package/dist/hooks/user-prompt-submit.js +2960 -0
- package/dist/hooks/user-prompt-submit.js.map +7 -0
- package/dist/services/memory-service.js +2931 -0
- package/dist/services/memory-service.js.map +7 -0
- package/package.json +45 -0
- package/plan.md +1642 -0
- package/scripts/build.ts +102 -0
- package/spec.md +624 -0
- package/specs/citations-system/context.md +243 -0
- package/specs/citations-system/plan.md +495 -0
- package/specs/citations-system/spec.md +371 -0
- package/specs/endless-mode/context.md +305 -0
- package/specs/endless-mode/plan.md +620 -0
- package/specs/endless-mode/spec.md +455 -0
- package/specs/entity-edge-model/context.md +401 -0
- package/specs/entity-edge-model/plan.md +459 -0
- package/specs/entity-edge-model/spec.md +391 -0
- package/specs/evidence-aligner-v2/context.md +401 -0
- package/specs/evidence-aligner-v2/plan.md +303 -0
- package/specs/evidence-aligner-v2/spec.md +312 -0
- package/specs/mcp-desktop-integration/context.md +278 -0
- package/specs/mcp-desktop-integration/plan.md +550 -0
- package/specs/mcp-desktop-integration/spec.md +494 -0
- package/specs/post-tool-use-hook/context.md +319 -0
- package/specs/post-tool-use-hook/plan.md +469 -0
- package/specs/post-tool-use-hook/spec.md +364 -0
- package/specs/private-tags/context.md +288 -0
- package/specs/private-tags/plan.md +412 -0
- package/specs/private-tags/spec.md +345 -0
- package/specs/progressive-disclosure/context.md +346 -0
- package/specs/progressive-disclosure/plan.md +663 -0
- package/specs/progressive-disclosure/spec.md +415 -0
- package/specs/task-entity-system/context.md +297 -0
- package/specs/task-entity-system/plan.md +301 -0
- package/specs/task-entity-system/spec.md +314 -0
- package/specs/vector-outbox-v2/context.md +470 -0
- package/specs/vector-outbox-v2/plan.md +562 -0
- package/specs/vector-outbox-v2/spec.md +466 -0
- package/specs/web-viewer-ui/context.md +384 -0
- package/specs/web-viewer-ui/plan.md +797 -0
- package/specs/web-viewer-ui/spec.md +516 -0
- package/src/cli/index.ts +570 -0
- package/src/core/canonical-key.ts +186 -0
- package/src/core/citation-generator.ts +63 -0
- package/src/core/consolidated-store.ts +279 -0
- package/src/core/consolidation-worker.ts +384 -0
- package/src/core/context-formatter.ts +276 -0
- package/src/core/continuity-manager.ts +336 -0
- package/src/core/edge-repo.ts +324 -0
- package/src/core/embedder.ts +124 -0
- package/src/core/entity-repo.ts +342 -0
- package/src/core/event-store.ts +672 -0
- package/src/core/evidence-aligner.ts +635 -0
- package/src/core/graduation.ts +365 -0
- package/src/core/index.ts +32 -0
- package/src/core/matcher.ts +210 -0
- package/src/core/metadata-extractor.ts +203 -0
- package/src/core/privacy/filter.ts +179 -0
- package/src/core/privacy/index.ts +20 -0
- package/src/core/privacy/tag-parser.ts +145 -0
- package/src/core/progressive-retriever.ts +415 -0
- package/src/core/retriever.ts +235 -0
- package/src/core/task/blocker-resolver.ts +325 -0
- package/src/core/task/index.ts +9 -0
- package/src/core/task/task-matcher.ts +238 -0
- package/src/core/task/task-projector.ts +345 -0
- package/src/core/task/task-resolver.ts +414 -0
- package/src/core/types.ts +841 -0
- package/src/core/vector-outbox.ts +295 -0
- package/src/core/vector-store.ts +182 -0
- package/src/core/vector-worker.ts +488 -0
- package/src/core/working-set-store.ts +244 -0
- package/src/hooks/post-tool-use.ts +127 -0
- package/src/hooks/session-end.ts +78 -0
- package/src/hooks/session-start.ts +57 -0
- package/src/hooks/stop.ts +78 -0
- package/src/hooks/user-prompt-submit.ts +54 -0
- package/src/mcp/handlers.ts +212 -0
- package/src/mcp/index.ts +47 -0
- package/src/mcp/tools.ts +78 -0
- package/src/server/api/citations.ts +101 -0
- package/src/server/api/events.ts +101 -0
- package/src/server/api/index.ts +18 -0
- package/src/server/api/search.ts +98 -0
- package/src/server/api/sessions.ts +111 -0
- package/src/server/api/stats.ts +97 -0
- package/src/server/index.ts +91 -0
- package/src/services/memory-service.ts +626 -0
- package/src/services/session-history-importer.ts +367 -0
- package/tests/canonical-key.test.ts +101 -0
- package/tests/evidence-aligner.test.ts +152 -0
- package/tests/matcher.test.ts +112 -0
- package/tsconfig.json +24 -0
- package/vitest.config.ts +15 -0
package/src/cli/index.ts
ADDED
|
@@ -0,0 +1,570 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Code Memory CLI
|
|
4
|
+
* Command-line interface for memory operations
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { Command } from 'commander';
|
|
8
|
+
import { getDefaultMemoryService } from '../services/memory-service.js';
|
|
9
|
+
import { createSessionHistoryImporter } from '../services/session-history-importer.js';
|
|
10
|
+
|
|
11
|
+
const program = new Command();
|
|
12
|
+
|
|
13
|
+
program
|
|
14
|
+
.name('code-memory')
|
|
15
|
+
.description('Claude Code Memory Plugin CLI')
|
|
16
|
+
.version('1.0.0');
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Search command
|
|
20
|
+
*/
|
|
21
|
+
program
|
|
22
|
+
.command('search <query>')
|
|
23
|
+
.description('Search memories using semantic search')
|
|
24
|
+
.option('-k, --top-k <number>', 'Number of results', '5')
|
|
25
|
+
.option('-s, --min-score <number>', 'Minimum similarity score', '0.7')
|
|
26
|
+
.option('--session <id>', 'Filter by session ID')
|
|
27
|
+
.action(async (query: string, options) => {
|
|
28
|
+
const service = getDefaultMemoryService();
|
|
29
|
+
|
|
30
|
+
try {
|
|
31
|
+
const result = await service.retrieveMemories(query, {
|
|
32
|
+
topK: parseInt(options.topK),
|
|
33
|
+
minScore: parseFloat(options.minScore),
|
|
34
|
+
sessionId: options.session
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
console.log('\nš Search Results\n');
|
|
38
|
+
console.log(`Confidence: ${result.matchResult.confidence}`);
|
|
39
|
+
console.log(`Total memories found: ${result.memories.length}\n`);
|
|
40
|
+
|
|
41
|
+
for (const memory of result.memories) {
|
|
42
|
+
const date = memory.event.timestamp.toISOString().split('T')[0];
|
|
43
|
+
console.log(`---`);
|
|
44
|
+
console.log(`š ${memory.event.eventType} (${date})`);
|
|
45
|
+
console.log(` Score: ${memory.score.toFixed(3)}`);
|
|
46
|
+
console.log(` Session: ${memory.event.sessionId.slice(0, 8)}...`);
|
|
47
|
+
console.log(` Content: ${memory.event.content.slice(0, 200)}${memory.event.content.length > 200 ? '...' : ''}`);
|
|
48
|
+
console.log('');
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
await service.shutdown();
|
|
52
|
+
} catch (error) {
|
|
53
|
+
console.error('Search failed:', error);
|
|
54
|
+
process.exit(1);
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* History command
|
|
60
|
+
*/
|
|
61
|
+
program
|
|
62
|
+
.command('history')
|
|
63
|
+
.description('View conversation history')
|
|
64
|
+
.option('-l, --limit <number>', 'Number of events', '20')
|
|
65
|
+
.option('--session <id>', 'Filter by session ID')
|
|
66
|
+
.option('--type <type>', 'Filter by event type')
|
|
67
|
+
.action(async (options) => {
|
|
68
|
+
const service = getDefaultMemoryService();
|
|
69
|
+
|
|
70
|
+
try {
|
|
71
|
+
let events;
|
|
72
|
+
|
|
73
|
+
if (options.session) {
|
|
74
|
+
events = await service.getSessionHistory(options.session);
|
|
75
|
+
} else {
|
|
76
|
+
events = await service.getRecentEvents(parseInt(options.limit));
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
if (options.type) {
|
|
80
|
+
events = events.filter(e => e.eventType === options.type);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
console.log('\nš Memory History\n');
|
|
84
|
+
console.log(`Total events: ${events.length}\n`);
|
|
85
|
+
|
|
86
|
+
for (const event of events.slice(0, parseInt(options.limit))) {
|
|
87
|
+
const date = event.timestamp.toISOString();
|
|
88
|
+
const icon = event.eventType === 'user_prompt' ? 'š¤' :
|
|
89
|
+
event.eventType === 'agent_response' ? 'š¤' : 'š';
|
|
90
|
+
|
|
91
|
+
console.log(`${icon} [${date}] ${event.eventType}`);
|
|
92
|
+
console.log(` Session: ${event.sessionId.slice(0, 8)}...`);
|
|
93
|
+
console.log(` ${event.content.slice(0, 150)}${event.content.length > 150 ? '...' : ''}`);
|
|
94
|
+
console.log('');
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
await service.shutdown();
|
|
98
|
+
} catch (error) {
|
|
99
|
+
console.error('History failed:', error);
|
|
100
|
+
process.exit(1);
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Stats command
|
|
106
|
+
*/
|
|
107
|
+
program
|
|
108
|
+
.command('stats')
|
|
109
|
+
.description('View memory statistics')
|
|
110
|
+
.action(async () => {
|
|
111
|
+
const service = getDefaultMemoryService();
|
|
112
|
+
|
|
113
|
+
try {
|
|
114
|
+
const stats = await service.getStats();
|
|
115
|
+
|
|
116
|
+
console.log('\nš Memory Statistics\n');
|
|
117
|
+
console.log(`Total Events: ${stats.totalEvents}`);
|
|
118
|
+
console.log(`Vector Count: ${stats.vectorCount}`);
|
|
119
|
+
console.log('\nMemory Levels:');
|
|
120
|
+
|
|
121
|
+
for (const level of stats.levelStats) {
|
|
122
|
+
const bar = 'ā'.repeat(Math.min(20, Math.ceil(level.count / 10)));
|
|
123
|
+
console.log(` ${level.level}: ${bar} ${level.count}`);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
await service.shutdown();
|
|
127
|
+
} catch (error) {
|
|
128
|
+
console.error('Stats failed:', error);
|
|
129
|
+
process.exit(1);
|
|
130
|
+
}
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Forget command
|
|
135
|
+
*/
|
|
136
|
+
program
|
|
137
|
+
.command('forget [eventId]')
|
|
138
|
+
.description('Remove memories from storage')
|
|
139
|
+
.option('--session <id>', 'Forget all events from a session')
|
|
140
|
+
.option('--before <date>', 'Forget events before date (YYYY-MM-DD)')
|
|
141
|
+
.option('--confirm', 'Skip confirmation')
|
|
142
|
+
.action(async (eventId: string | undefined, options) => {
|
|
143
|
+
const service = getDefaultMemoryService();
|
|
144
|
+
|
|
145
|
+
try {
|
|
146
|
+
if (!eventId && !options.session && !options.before) {
|
|
147
|
+
console.error('Please specify an event ID, --session, or --before option');
|
|
148
|
+
process.exit(1);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
if (!options.confirm) {
|
|
152
|
+
console.log('ā ļø This will remove memories from storage.');
|
|
153
|
+
console.log('Add --confirm to proceed.');
|
|
154
|
+
process.exit(0);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// Note: Full forget implementation would require additional EventStore methods
|
|
158
|
+
console.log('šļø Forget functionality requires additional implementation.');
|
|
159
|
+
console.log('Events are append-only; soft-delete markers would be added.');
|
|
160
|
+
|
|
161
|
+
await service.shutdown();
|
|
162
|
+
} catch (error) {
|
|
163
|
+
console.error('Forget failed:', error);
|
|
164
|
+
process.exit(1);
|
|
165
|
+
}
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Process command - manually process pending embeddings
|
|
170
|
+
*/
|
|
171
|
+
program
|
|
172
|
+
.command('process')
|
|
173
|
+
.description('Process pending embeddings')
|
|
174
|
+
.action(async () => {
|
|
175
|
+
const service = getDefaultMemoryService();
|
|
176
|
+
|
|
177
|
+
try {
|
|
178
|
+
console.log('ā³ Processing pending embeddings...');
|
|
179
|
+
const count = await service.processPendingEmbeddings();
|
|
180
|
+
console.log(`ā
Processed ${count} embeddings`);
|
|
181
|
+
|
|
182
|
+
await service.shutdown();
|
|
183
|
+
} catch (error) {
|
|
184
|
+
console.error('Process failed:', error);
|
|
185
|
+
process.exit(1);
|
|
186
|
+
}
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Import command - import existing Claude Code sessions
|
|
191
|
+
*/
|
|
192
|
+
program
|
|
193
|
+
.command('import')
|
|
194
|
+
.description('Import existing Claude Code conversation history')
|
|
195
|
+
.option('-p, --project <path>', 'Import from specific project path')
|
|
196
|
+
.option('-s, --session <file>', 'Import specific session file (JSONL)')
|
|
197
|
+
.option('-a, --all', 'Import all sessions from all projects')
|
|
198
|
+
.option('-l, --limit <number>', 'Limit messages per session')
|
|
199
|
+
.option('-v, --verbose', 'Show detailed progress')
|
|
200
|
+
.action(async (options) => {
|
|
201
|
+
const service = getDefaultMemoryService();
|
|
202
|
+
const importer = createSessionHistoryImporter(service);
|
|
203
|
+
|
|
204
|
+
try {
|
|
205
|
+
await service.initialize();
|
|
206
|
+
|
|
207
|
+
let result;
|
|
208
|
+
|
|
209
|
+
if (options.session) {
|
|
210
|
+
// Import specific session file
|
|
211
|
+
console.log(`\nš„ Importing session: ${options.session}\n`);
|
|
212
|
+
result = await importer.importSessionFile(options.session, {
|
|
213
|
+
projectPath: options.project,
|
|
214
|
+
limit: options.limit ? parseInt(options.limit) : undefined,
|
|
215
|
+
verbose: options.verbose
|
|
216
|
+
});
|
|
217
|
+
} else if (options.project) {
|
|
218
|
+
// Import all sessions from a project
|
|
219
|
+
console.log(`\nš„ Importing project: ${options.project}\n`);
|
|
220
|
+
result = await importer.importProject(options.project, {
|
|
221
|
+
limit: options.limit ? parseInt(options.limit) : undefined,
|
|
222
|
+
verbose: options.verbose
|
|
223
|
+
});
|
|
224
|
+
} else if (options.all) {
|
|
225
|
+
// Import all sessions from all projects
|
|
226
|
+
console.log('\nš„ Importing all sessions from all projects\n');
|
|
227
|
+
result = await importer.importAll({
|
|
228
|
+
limit: options.limit ? parseInt(options.limit) : undefined,
|
|
229
|
+
verbose: options.verbose
|
|
230
|
+
});
|
|
231
|
+
} else {
|
|
232
|
+
// Default: import current project
|
|
233
|
+
const cwd = process.cwd();
|
|
234
|
+
console.log(`\nš„ Importing sessions for current project: ${cwd}\n`);
|
|
235
|
+
result = await importer.importProject(cwd, {
|
|
236
|
+
projectPath: cwd,
|
|
237
|
+
limit: options.limit ? parseInt(options.limit) : undefined,
|
|
238
|
+
verbose: options.verbose
|
|
239
|
+
});
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
// Process embeddings
|
|
243
|
+
console.log('\nā³ Processing embeddings...');
|
|
244
|
+
const embedCount = await service.processPendingEmbeddings();
|
|
245
|
+
|
|
246
|
+
// Show results
|
|
247
|
+
console.log('\nā
Import Complete\n');
|
|
248
|
+
console.log(`Sessions processed: ${result.totalSessions}`);
|
|
249
|
+
console.log(`Total messages: ${result.totalMessages}`);
|
|
250
|
+
console.log(`Imported prompts: ${result.importedPrompts}`);
|
|
251
|
+
console.log(`Imported responses: ${result.importedResponses}`);
|
|
252
|
+
console.log(`Skipped duplicates: ${result.skippedDuplicates}`);
|
|
253
|
+
console.log(`Embeddings processed: ${embedCount}`);
|
|
254
|
+
|
|
255
|
+
if (result.errors.length > 0) {
|
|
256
|
+
console.log(`\nā ļø Errors (${result.errors.length}):`);
|
|
257
|
+
for (const error of result.errors.slice(0, 5)) {
|
|
258
|
+
console.log(` - ${error}`);
|
|
259
|
+
}
|
|
260
|
+
if (result.errors.length > 5) {
|
|
261
|
+
console.log(` ... and ${result.errors.length - 5} more`);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
await service.shutdown();
|
|
266
|
+
} catch (error) {
|
|
267
|
+
console.error('Import failed:', error);
|
|
268
|
+
process.exit(1);
|
|
269
|
+
}
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
/**
|
|
273
|
+
* List command - list available sessions for import
|
|
274
|
+
*/
|
|
275
|
+
program
|
|
276
|
+
.command('list')
|
|
277
|
+
.description('List available Claude Code sessions')
|
|
278
|
+
.option('-p, --project <path>', 'Filter by project path')
|
|
279
|
+
.action(async (options) => {
|
|
280
|
+
const service = getDefaultMemoryService();
|
|
281
|
+
const importer = createSessionHistoryImporter(service);
|
|
282
|
+
|
|
283
|
+
try {
|
|
284
|
+
const sessions = await importer.listAvailableSessions(options.project);
|
|
285
|
+
|
|
286
|
+
console.log('\nš Available Sessions\n');
|
|
287
|
+
console.log(`Found ${sessions.length} session(s)\n`);
|
|
288
|
+
|
|
289
|
+
for (const session of sessions.slice(0, 20)) {
|
|
290
|
+
const date = session.modifiedAt.toISOString().split('T')[0];
|
|
291
|
+
const sizeKB = (session.size / 1024).toFixed(1);
|
|
292
|
+
console.log(`š ${session.sessionId.slice(0, 16)}...`);
|
|
293
|
+
console.log(` Modified: ${date}`);
|
|
294
|
+
console.log(` Size: ${sizeKB} KB`);
|
|
295
|
+
console.log(` Path: ${session.filePath}`);
|
|
296
|
+
console.log('');
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
if (sessions.length > 20) {
|
|
300
|
+
console.log(`... and ${sessions.length - 20} more sessions`);
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
console.log('\nUse "code-memory import --session <path>" to import a specific session');
|
|
304
|
+
} catch (error) {
|
|
305
|
+
console.error('List failed:', error);
|
|
306
|
+
process.exit(1);
|
|
307
|
+
}
|
|
308
|
+
});
|
|
309
|
+
|
|
310
|
+
// ============================================================
|
|
311
|
+
// Endless Mode Commands
|
|
312
|
+
// ============================================================
|
|
313
|
+
|
|
314
|
+
/**
|
|
315
|
+
* Endless Mode parent command
|
|
316
|
+
*/
|
|
317
|
+
const endlessCmd = program
|
|
318
|
+
.command('endless')
|
|
319
|
+
.description('Manage Endless Mode (biomimetic continuous memory)');
|
|
320
|
+
|
|
321
|
+
/**
|
|
322
|
+
* Enable Endless Mode
|
|
323
|
+
*/
|
|
324
|
+
endlessCmd
|
|
325
|
+
.command('enable')
|
|
326
|
+
.description('Enable Endless Mode')
|
|
327
|
+
.action(async () => {
|
|
328
|
+
const service = getDefaultMemoryService();
|
|
329
|
+
|
|
330
|
+
try {
|
|
331
|
+
await service.initialize();
|
|
332
|
+
await service.setMode('endless');
|
|
333
|
+
|
|
334
|
+
console.log('\nā¾ļø Endless Mode Enabled\n');
|
|
335
|
+
console.log('Your conversations will now be continuously integrated');
|
|
336
|
+
console.log('across session boundaries.\n');
|
|
337
|
+
console.log('Features:');
|
|
338
|
+
console.log(' - Working Set: Recent context kept active');
|
|
339
|
+
console.log(' - Consolidation: Automatic memory integration');
|
|
340
|
+
console.log(' - Continuity: Seamless context transitions\n');
|
|
341
|
+
console.log('Use "code-memory endless status" to view current state');
|
|
342
|
+
|
|
343
|
+
await service.shutdown();
|
|
344
|
+
} catch (error) {
|
|
345
|
+
console.error('Enable failed:', error);
|
|
346
|
+
process.exit(1);
|
|
347
|
+
}
|
|
348
|
+
});
|
|
349
|
+
|
|
350
|
+
/**
|
|
351
|
+
* Disable Endless Mode
|
|
352
|
+
*/
|
|
353
|
+
endlessCmd
|
|
354
|
+
.command('disable')
|
|
355
|
+
.description('Disable Endless Mode (return to Session Mode)')
|
|
356
|
+
.action(async () => {
|
|
357
|
+
const service = getDefaultMemoryService();
|
|
358
|
+
|
|
359
|
+
try {
|
|
360
|
+
await service.initialize();
|
|
361
|
+
await service.setMode('session');
|
|
362
|
+
|
|
363
|
+
console.log('\nš Session Mode Enabled\n');
|
|
364
|
+
console.log('Returned to traditional session-based memory.');
|
|
365
|
+
console.log('Existing Endless Mode data is preserved for future use.');
|
|
366
|
+
|
|
367
|
+
await service.shutdown();
|
|
368
|
+
} catch (error) {
|
|
369
|
+
console.error('Disable failed:', error);
|
|
370
|
+
process.exit(1);
|
|
371
|
+
}
|
|
372
|
+
});
|
|
373
|
+
|
|
374
|
+
/**
|
|
375
|
+
* Endless Mode Status
|
|
376
|
+
*/
|
|
377
|
+
endlessCmd
|
|
378
|
+
.command('status')
|
|
379
|
+
.description('Show Endless Mode status')
|
|
380
|
+
.action(async () => {
|
|
381
|
+
const service = getDefaultMemoryService();
|
|
382
|
+
|
|
383
|
+
try {
|
|
384
|
+
await service.initialize();
|
|
385
|
+
const status = await service.getEndlessModeStatus();
|
|
386
|
+
|
|
387
|
+
const modeIcon = status.mode === 'endless' ? 'ā¾ļø' : 'š';
|
|
388
|
+
const modeName = status.mode === 'endless' ? 'Endless Mode' : 'Session Mode';
|
|
389
|
+
|
|
390
|
+
console.log(`\n${modeIcon} ${modeName}\n`);
|
|
391
|
+
|
|
392
|
+
if (status.mode === 'endless') {
|
|
393
|
+
// Continuity score bar
|
|
394
|
+
const continuityBars = 'ā'.repeat(Math.round(status.continuityScore * 10));
|
|
395
|
+
const continuityEmpty = 'ā'.repeat(10 - Math.round(status.continuityScore * 10));
|
|
396
|
+
|
|
397
|
+
console.log('š Status:');
|
|
398
|
+
console.log(` Working Set: ${status.workingSetSize} events`);
|
|
399
|
+
console.log(` Continuity: [${continuityBars}${continuityEmpty}] ${(status.continuityScore * 100).toFixed(0)}%`);
|
|
400
|
+
console.log(` Consolidated: ${status.consolidatedCount} memories`);
|
|
401
|
+
|
|
402
|
+
if (status.lastConsolidation) {
|
|
403
|
+
const ago = Math.round((Date.now() - status.lastConsolidation.getTime()) / 60000);
|
|
404
|
+
console.log(` Last Consolidation: ${ago} minutes ago`);
|
|
405
|
+
} else {
|
|
406
|
+
console.log(' Last Consolidation: Never');
|
|
407
|
+
}
|
|
408
|
+
} else {
|
|
409
|
+
console.log('Endless Mode is disabled.');
|
|
410
|
+
console.log('Use "code-memory endless enable" to activate.');
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
await service.shutdown();
|
|
414
|
+
} catch (error) {
|
|
415
|
+
console.error('Status failed:', error);
|
|
416
|
+
process.exit(1);
|
|
417
|
+
}
|
|
418
|
+
});
|
|
419
|
+
|
|
420
|
+
/**
|
|
421
|
+
* Consolidate command - manually trigger consolidation
|
|
422
|
+
*/
|
|
423
|
+
endlessCmd
|
|
424
|
+
.command('consolidate')
|
|
425
|
+
.description('Manually trigger memory consolidation')
|
|
426
|
+
.action(async () => {
|
|
427
|
+
const service = getDefaultMemoryService();
|
|
428
|
+
|
|
429
|
+
try {
|
|
430
|
+
await service.initialize();
|
|
431
|
+
|
|
432
|
+
if (!service.isEndlessModeActive()) {
|
|
433
|
+
console.log('\nā ļø Endless Mode is not active');
|
|
434
|
+
console.log('Use "code-memory endless enable" first');
|
|
435
|
+
process.exit(1);
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
console.log('\nā³ Running memory consolidation...');
|
|
439
|
+
const count = await service.forceConsolidation();
|
|
440
|
+
|
|
441
|
+
if (count > 0) {
|
|
442
|
+
console.log(`\nā
Consolidated ${count} memory group(s)`);
|
|
443
|
+
} else {
|
|
444
|
+
console.log('\nš No memories to consolidate');
|
|
445
|
+
console.log('(Working set may not have enough events yet)');
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
await service.shutdown();
|
|
449
|
+
} catch (error) {
|
|
450
|
+
console.error('Consolidation failed:', error);
|
|
451
|
+
process.exit(1);
|
|
452
|
+
}
|
|
453
|
+
});
|
|
454
|
+
|
|
455
|
+
/**
|
|
456
|
+
* Working Set command - view current working set
|
|
457
|
+
*/
|
|
458
|
+
endlessCmd
|
|
459
|
+
.command('working-set')
|
|
460
|
+
.alias('ws')
|
|
461
|
+
.description('View current working set')
|
|
462
|
+
.option('-l, --limit <number>', 'Number of events to show', '10')
|
|
463
|
+
.action(async (options) => {
|
|
464
|
+
const service = getDefaultMemoryService();
|
|
465
|
+
|
|
466
|
+
try {
|
|
467
|
+
await service.initialize();
|
|
468
|
+
|
|
469
|
+
if (!service.isEndlessModeActive()) {
|
|
470
|
+
console.log('\nā ļø Endless Mode is not active');
|
|
471
|
+
console.log('Use "code-memory endless enable" first');
|
|
472
|
+
process.exit(1);
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
const workingSet = await service.getWorkingSet();
|
|
476
|
+
|
|
477
|
+
if (!workingSet || workingSet.recentEvents.length === 0) {
|
|
478
|
+
console.log('\nš Working Set is empty');
|
|
479
|
+
console.log('Events will be added as you interact with Claude');
|
|
480
|
+
process.exit(0);
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
console.log('\nš§ Working Set\n');
|
|
484
|
+
console.log(`Total events: ${workingSet.recentEvents.length}`);
|
|
485
|
+
console.log(`Continuity score: ${(workingSet.continuityScore * 100).toFixed(0)}%`);
|
|
486
|
+
console.log(`Last activity: ${workingSet.lastActivity.toISOString()}\n`);
|
|
487
|
+
|
|
488
|
+
const limit = parseInt(options.limit);
|
|
489
|
+
const events = workingSet.recentEvents.slice(0, limit);
|
|
490
|
+
|
|
491
|
+
for (const event of events) {
|
|
492
|
+
const icon = event.eventType === 'user_prompt' ? 'š¤' :
|
|
493
|
+
event.eventType === 'agent_response' ? 'š¤' :
|
|
494
|
+
event.eventType === 'tool_observation' ? 'š§' : 'š';
|
|
495
|
+
const time = event.timestamp.toLocaleTimeString();
|
|
496
|
+
const preview = event.content.slice(0, 80) + (event.content.length > 80 ? '...' : '');
|
|
497
|
+
|
|
498
|
+
console.log(`${icon} [${time}] ${event.eventType}`);
|
|
499
|
+
console.log(` ${preview}`);
|
|
500
|
+
console.log('');
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
if (workingSet.recentEvents.length > limit) {
|
|
504
|
+
console.log(`... and ${workingSet.recentEvents.length - limit} more events`);
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
await service.shutdown();
|
|
508
|
+
} catch (error) {
|
|
509
|
+
console.error('Working set failed:', error);
|
|
510
|
+
process.exit(1);
|
|
511
|
+
}
|
|
512
|
+
});
|
|
513
|
+
|
|
514
|
+
/**
|
|
515
|
+
* Consolidated memories command
|
|
516
|
+
*/
|
|
517
|
+
endlessCmd
|
|
518
|
+
.command('memories')
|
|
519
|
+
.description('View consolidated memories')
|
|
520
|
+
.option('-l, --limit <number>', 'Number of memories to show', '10')
|
|
521
|
+
.option('-q, --query <text>', 'Search consolidated memories')
|
|
522
|
+
.action(async (options) => {
|
|
523
|
+
const service = getDefaultMemoryService();
|
|
524
|
+
|
|
525
|
+
try {
|
|
526
|
+
await service.initialize();
|
|
527
|
+
|
|
528
|
+
let memories;
|
|
529
|
+
|
|
530
|
+
if (options.query) {
|
|
531
|
+
memories = await service.searchConsolidated(options.query, {
|
|
532
|
+
topK: parseInt(options.limit)
|
|
533
|
+
});
|
|
534
|
+
console.log(`\nš Searching for: "${options.query}"\n`);
|
|
535
|
+
} else {
|
|
536
|
+
memories = await service.getConsolidatedMemories(parseInt(options.limit));
|
|
537
|
+
console.log('\nš¾ Consolidated Memories\n');
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
if (memories.length === 0) {
|
|
541
|
+
console.log('No consolidated memories found.');
|
|
542
|
+
if (!service.isEndlessModeActive()) {
|
|
543
|
+
console.log('Enable Endless Mode to start consolidating memories.');
|
|
544
|
+
}
|
|
545
|
+
process.exit(0);
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
console.log(`Showing ${memories.length} memory(ies)\n`);
|
|
549
|
+
|
|
550
|
+
for (const memory of memories) {
|
|
551
|
+
const date = memory.createdAt.toISOString().split('T')[0];
|
|
552
|
+
const confidenceBars = 'ā'.repeat(Math.round(memory.confidence * 5));
|
|
553
|
+
|
|
554
|
+
console.log(`š ${memory.topics.slice(0, 3).join(', ')}`);
|
|
555
|
+
console.log(` Created: ${date}`);
|
|
556
|
+
console.log(` Confidence: [${confidenceBars}] ${(memory.confidence * 100).toFixed(0)}%`);
|
|
557
|
+
console.log(` Sources: ${memory.sourceEvents.length} events`);
|
|
558
|
+
console.log(` Access count: ${memory.accessCount}`);
|
|
559
|
+
console.log(` Summary: ${memory.summary.slice(0, 200)}${memory.summary.length > 200 ? '...' : ''}`);
|
|
560
|
+
console.log('');
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
await service.shutdown();
|
|
564
|
+
} catch (error) {
|
|
565
|
+
console.error('Memories failed:', error);
|
|
566
|
+
process.exit(1);
|
|
567
|
+
}
|
|
568
|
+
});
|
|
569
|
+
|
|
570
|
+
program.parse();
|