agentmemory-cli 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.
Files changed (68) hide show
  1. package/README.md +198 -0
  2. package/dist/commands/delete.d.ts +7 -0
  3. package/dist/commands/delete.d.ts.map +1 -0
  4. package/dist/commands/delete.js +67 -0
  5. package/dist/commands/delete.js.map +1 -0
  6. package/dist/commands/export.d.ts +7 -0
  7. package/dist/commands/export.d.ts.map +1 -0
  8. package/dist/commands/export.js +79 -0
  9. package/dist/commands/export.js.map +1 -0
  10. package/dist/commands/import.d.ts +6 -0
  11. package/dist/commands/import.d.ts.map +1 -0
  12. package/dist/commands/import.js +107 -0
  13. package/dist/commands/import.js.map +1 -0
  14. package/dist/commands/init.d.ts +2 -0
  15. package/dist/commands/init.d.ts.map +1 -0
  16. package/dist/commands/init.js +65 -0
  17. package/dist/commands/init.js.map +1 -0
  18. package/dist/commands/list.d.ts +8 -0
  19. package/dist/commands/list.d.ts.map +1 -0
  20. package/dist/commands/list.js +55 -0
  21. package/dist/commands/list.js.map +1 -0
  22. package/dist/commands/search.d.ts +7 -0
  23. package/dist/commands/search.d.ts.map +1 -0
  24. package/dist/commands/search.js +47 -0
  25. package/dist/commands/search.js.map +1 -0
  26. package/dist/commands/store.d.ts +8 -0
  27. package/dist/commands/store.d.ts.map +1 -0
  28. package/dist/commands/store.js +51 -0
  29. package/dist/commands/store.js.map +1 -0
  30. package/dist/commands/sync.d.ts +9 -0
  31. package/dist/commands/sync.d.ts.map +1 -0
  32. package/dist/commands/sync.js +90 -0
  33. package/dist/commands/sync.js.map +1 -0
  34. package/dist/index.d.ts +3 -0
  35. package/dist/index.d.ts.map +1 -0
  36. package/dist/index.js +106 -0
  37. package/dist/index.js.map +1 -0
  38. package/dist/lib/api.d.ts +14 -0
  39. package/dist/lib/api.d.ts.map +1 -0
  40. package/dist/lib/api.js +98 -0
  41. package/dist/lib/api.js.map +1 -0
  42. package/dist/lib/config.d.ts +13 -0
  43. package/dist/lib/config.d.ts.map +1 -0
  44. package/dist/lib/config.js +123 -0
  45. package/dist/lib/config.js.map +1 -0
  46. package/dist/lib/sync.d.ts +43 -0
  47. package/dist/lib/sync.d.ts.map +1 -0
  48. package/dist/lib/sync.js +184 -0
  49. package/dist/lib/sync.js.map +1 -0
  50. package/dist/types.d.ts +41 -0
  51. package/dist/types.d.ts.map +1 -0
  52. package/dist/types.js +3 -0
  53. package/dist/types.js.map +1 -0
  54. package/package.json +44 -0
  55. package/src/commands/delete.ts +72 -0
  56. package/src/commands/export.ts +46 -0
  57. package/src/commands/import.ts +87 -0
  58. package/src/commands/init.ts +71 -0
  59. package/src/commands/list.ts +61 -0
  60. package/src/commands/search.ts +52 -0
  61. package/src/commands/store.ts +58 -0
  62. package/src/commands/sync.ts +102 -0
  63. package/src/index.ts +114 -0
  64. package/src/lib/api.ts +139 -0
  65. package/src/lib/config.ts +95 -0
  66. package/src/lib/sync.ts +186 -0
  67. package/src/types.ts +47 -0
  68. package/tsconfig.json +20 -0
@@ -0,0 +1,186 @@
1
+ import * as fs from 'fs';
2
+ import * as path from 'path';
3
+ import { getMemoryFilePath } from './config.js';
4
+ import { getAllMemories, storeMemory } from './api.js';
5
+ import type { Memory } from '../types.js';
6
+
7
+ interface LocalMemory {
8
+ content: string;
9
+ metadata?: Record<string, unknown>;
10
+ id?: string;
11
+ }
12
+
13
+ /**
14
+ * Parse MEMORY.md file into memory entries
15
+ * Expected format:
16
+ *
17
+ * ## Memory Title (optional)
18
+ * Content here...
19
+ *
20
+ * ---
21
+ *
22
+ * ## Another Memory
23
+ * More content...
24
+ */
25
+ export function parseMemoryFile(filePath: string): LocalMemory[] {
26
+ if (!fs.existsSync(filePath)) {
27
+ return [];
28
+ }
29
+
30
+ const content = fs.readFileSync(filePath, 'utf-8');
31
+ const memories: LocalMemory[] = [];
32
+
33
+ // Split by --- separator or ## headers
34
+ const sections = content.split(/\n---\n|\n(?=## )/);
35
+
36
+ for (const section of sections) {
37
+ const trimmed = section.trim();
38
+ if (!trimmed || trimmed === '---') continue;
39
+
40
+ // Check if it has an ID comment (for synced memories)
41
+ const idMatch = trimmed.match(/<!-- id: ([a-f0-9-]+) -->/);
42
+ const id = idMatch ? idMatch[1] : undefined;
43
+
44
+ // Check for category in metadata comment
45
+ const metaMatch = trimmed.match(/<!-- metadata: ({.*?}) -->/);
46
+ let metadata: Record<string, unknown> | undefined;
47
+ if (metaMatch) {
48
+ try {
49
+ metadata = JSON.parse(metaMatch[1]);
50
+ } catch {
51
+ // Ignore invalid metadata
52
+ }
53
+ }
54
+
55
+ // Remove the metadata comments from content
56
+ let cleanContent = trimmed
57
+ .replace(/<!-- id: [a-f0-9-]+ -->\n?/g, '')
58
+ .replace(/<!-- metadata: {.*?} -->\n?/g, '')
59
+ .replace(/^## .+\n?/, '') // Remove header if present
60
+ .trim();
61
+
62
+ if (cleanContent) {
63
+ memories.push({ content: cleanContent, metadata, id });
64
+ }
65
+ }
66
+
67
+ return memories;
68
+ }
69
+
70
+ /**
71
+ * Write memories to MEMORY.md file
72
+ */
73
+ export function writeMemoryFile(filePath: string, memories: Memory[]): void {
74
+ const dir = path.dirname(filePath);
75
+ if (!fs.existsSync(dir)) {
76
+ fs.mkdirSync(dir, { recursive: true });
77
+ }
78
+
79
+ const lines: string[] = [
80
+ '# Agent Memory',
81
+ '',
82
+ `> Last synced: ${new Date().toISOString()}`,
83
+ `> Total memories: ${memories.length}`,
84
+ '',
85
+ '---',
86
+ '',
87
+ ];
88
+
89
+ for (const memory of memories) {
90
+ lines.push(`<!-- id: ${memory.id} -->`);
91
+ if (memory.metadata && Object.keys(memory.metadata).length > 0) {
92
+ lines.push(`<!-- metadata: ${JSON.stringify(memory.metadata)} -->`);
93
+ }
94
+ lines.push(memory.content);
95
+ lines.push('');
96
+ lines.push('---');
97
+ lines.push('');
98
+ }
99
+
100
+ fs.writeFileSync(filePath, lines.join('\n'));
101
+ }
102
+
103
+ export interface SyncResult {
104
+ uploaded: number;
105
+ downloaded: number;
106
+ unchanged: number;
107
+ errors: string[];
108
+ }
109
+
110
+ /**
111
+ * Bidirectional sync between local MEMORY.md and cloud
112
+ */
113
+ export async function syncMemories(direction: 'push' | 'pull' | 'both' = 'both'): Promise<SyncResult> {
114
+ const memoryFilePath = getMemoryFilePath();
115
+ const result: SyncResult = {
116
+ uploaded: 0,
117
+ downloaded: 0,
118
+ unchanged: 0,
119
+ errors: [],
120
+ };
121
+
122
+ // Get cloud memories
123
+ const cloudMemories = await getAllMemories();
124
+ const cloudById = new Map(cloudMemories.map(m => [m.id, m]));
125
+ const cloudByContent = new Map(cloudMemories.map(m => [m.content.trim(), m]));
126
+
127
+ // Get local memories
128
+ const localMemories = parseMemoryFile(memoryFilePath);
129
+
130
+ if (direction === 'push' || direction === 'both') {
131
+ // Upload local memories that don't exist in cloud
132
+ for (const local of localMemories) {
133
+ // Skip if already synced (has ID) or content exists in cloud
134
+ if (local.id && cloudById.has(local.id)) {
135
+ result.unchanged++;
136
+ continue;
137
+ }
138
+
139
+ if (cloudByContent.has(local.content.trim())) {
140
+ result.unchanged++;
141
+ continue;
142
+ }
143
+
144
+ try {
145
+ await storeMemory(local.content, local.metadata);
146
+ result.uploaded++;
147
+ } catch (error) {
148
+ result.errors.push(`Failed to upload: ${local.content.substring(0, 50)}...`);
149
+ }
150
+ }
151
+ }
152
+
153
+ if (direction === 'pull' || direction === 'both') {
154
+ // Refresh cloud memories after push
155
+ const updatedCloudMemories = await getAllMemories();
156
+
157
+ // Write all cloud memories to local file
158
+ writeMemoryFile(memoryFilePath, updatedCloudMemories);
159
+ result.downloaded = updatedCloudMemories.length;
160
+ }
161
+
162
+ return result;
163
+ }
164
+
165
+ /**
166
+ * Get sync status without making changes
167
+ */
168
+ export async function getSyncStatus(): Promise<{
169
+ localOnly: LocalMemory[];
170
+ cloudOnly: Memory[];
171
+ synced: number;
172
+ }> {
173
+ const memoryFilePath = getMemoryFilePath();
174
+ const cloudMemories = await getAllMemories();
175
+ const localMemories = parseMemoryFile(memoryFilePath);
176
+
177
+ const cloudContents = new Set(cloudMemories.map(m => m.content.trim()));
178
+ const localContents = new Set(localMemories.map(m => m.content.trim()));
179
+
180
+ const localOnly = localMemories.filter(m => !cloudContents.has(m.content.trim()));
181
+ const cloudOnly = cloudMemories.filter(m => !localContents.has(m.content.trim()));
182
+
183
+ const synced = localMemories.length - localOnly.length;
184
+
185
+ return { localOnly, cloudOnly, synced };
186
+ }
package/src/types.ts ADDED
@@ -0,0 +1,47 @@
1
+ export interface Config {
2
+ api_key: string;
3
+ api_url: string;
4
+ memory_file: string;
5
+ }
6
+
7
+ export interface Memory {
8
+ id: string;
9
+ content: string;
10
+ metadata?: Record<string, unknown>;
11
+ created_at: string;
12
+ updated_at?: string;
13
+ }
14
+
15
+ export interface MemorySearchResult extends Memory {
16
+ similarity: number;
17
+ }
18
+
19
+ export interface ApiResponse<T> {
20
+ success: boolean;
21
+ data?: T;
22
+ error?: string;
23
+ }
24
+
25
+ export interface MemoriesListResponse {
26
+ memories: Memory[];
27
+ total: number;
28
+ limit: number;
29
+ offset: number;
30
+ }
31
+
32
+ export interface MemoryCreateResponse {
33
+ memory: Memory;
34
+ }
35
+
36
+ export interface MemorySearchResponse {
37
+ memories: MemorySearchResult[];
38
+ }
39
+
40
+ export interface SyncStatus {
41
+ local_only: Memory[];
42
+ cloud_only: Memory[];
43
+ conflicts: Array<{
44
+ local: Memory;
45
+ cloud: Memory;
46
+ }>;
47
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,20 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "NodeNext",
5
+ "moduleResolution": "NodeNext",
6
+ "lib": ["ES2022"],
7
+ "outDir": "./dist",
8
+ "rootDir": "./src",
9
+ "strict": true,
10
+ "esModuleInterop": true,
11
+ "skipLibCheck": true,
12
+ "forceConsistentCasingInFileNames": true,
13
+ "resolveJsonModule": true,
14
+ "declaration": true,
15
+ "declarationMap": true,
16
+ "sourceMap": true
17
+ },
18
+ "include": ["src/**/*"],
19
+ "exclude": ["node_modules", "dist"]
20
+ }