agentmemory-cli 1.1.0 → 1.3.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 (72) hide show
  1. package/dist/commands/connect.d.ts +11 -0
  2. package/dist/commands/connect.d.ts.map +1 -0
  3. package/dist/commands/connect.js +232 -0
  4. package/dist/commands/connect.js.map +1 -0
  5. package/dist/commands/delete.d.ts.map +1 -1
  6. package/dist/commands/delete.js +3 -0
  7. package/dist/commands/delete.js.map +1 -1
  8. package/dist/commands/download.d.ts.map +1 -1
  9. package/dist/commands/download.js +3 -0
  10. package/dist/commands/download.js.map +1 -1
  11. package/dist/commands/export.d.ts.map +1 -1
  12. package/dist/commands/export.js +3 -0
  13. package/dist/commands/export.js.map +1 -1
  14. package/dist/commands/files.d.ts.map +1 -1
  15. package/dist/commands/files.js +3 -0
  16. package/dist/commands/files.js.map +1 -1
  17. package/dist/commands/heartbeat.d.ts +65 -0
  18. package/dist/commands/heartbeat.d.ts.map +1 -0
  19. package/dist/commands/heartbeat.js +176 -0
  20. package/dist/commands/heartbeat.js.map +1 -0
  21. package/dist/commands/import.d.ts.map +1 -1
  22. package/dist/commands/import.js +3 -0
  23. package/dist/commands/import.js.map +1 -1
  24. package/dist/commands/init.d.ts.map +1 -1
  25. package/dist/commands/init.js +39 -1
  26. package/dist/commands/init.js.map +1 -1
  27. package/dist/commands/list.d.ts.map +1 -1
  28. package/dist/commands/list.js +3 -0
  29. package/dist/commands/list.js.map +1 -1
  30. package/dist/commands/search.d.ts.map +1 -1
  31. package/dist/commands/search.js +3 -0
  32. package/dist/commands/search.js.map +1 -1
  33. package/dist/commands/secret.d.ts +25 -0
  34. package/dist/commands/secret.d.ts.map +1 -0
  35. package/dist/commands/secret.js +390 -0
  36. package/dist/commands/secret.js.map +1 -0
  37. package/dist/commands/store.d.ts.map +1 -1
  38. package/dist/commands/store.js +3 -0
  39. package/dist/commands/store.js.map +1 -1
  40. package/dist/commands/upload.d.ts.map +1 -1
  41. package/dist/commands/upload.js +3 -0
  42. package/dist/commands/upload.js.map +1 -1
  43. package/dist/index.js +105 -2
  44. package/dist/index.js.map +1 -1
  45. package/dist/lib/api.d.ts +23 -1
  46. package/dist/lib/api.d.ts.map +1 -1
  47. package/dist/lib/api.js +49 -0
  48. package/dist/lib/api.js.map +1 -1
  49. package/dist/lib/autosync.d.ts +14 -0
  50. package/dist/lib/autosync.d.ts.map +1 -0
  51. package/dist/lib/autosync.js +165 -0
  52. package/dist/lib/autosync.js.map +1 -0
  53. package/dist/types.d.ts +59 -0
  54. package/dist/types.d.ts.map +1 -1
  55. package/package.json +1 -1
  56. package/src/commands/connect.ts +216 -0
  57. package/src/commands/delete.ts +4 -0
  58. package/src/commands/download.ts +4 -0
  59. package/src/commands/export.ts +4 -0
  60. package/src/commands/files.ts +4 -0
  61. package/src/commands/heartbeat.ts +241 -0
  62. package/src/commands/import.ts +4 -0
  63. package/src/commands/init.ts +44 -1
  64. package/src/commands/list.ts +4 -0
  65. package/src/commands/search.ts +4 -0
  66. package/src/commands/secret.ts +438 -0
  67. package/src/commands/store.ts +4 -0
  68. package/src/commands/upload.ts +4 -0
  69. package/src/index.ts +124 -2
  70. package/src/lib/api.ts +86 -1
  71. package/src/lib/autosync.ts +160 -0
  72. package/src/types.ts +67 -0
package/src/lib/api.ts CHANGED
@@ -4,7 +4,13 @@ import type {
4
4
  MemoriesListResponse,
5
5
  MemoryCreateResponse,
6
6
  MemorySearchResponse,
7
- MemorySearchResult
7
+ MemorySearchResult,
8
+ Secret,
9
+ SecretListItem,
10
+ SecretsListResponse,
11
+ SecretResponse,
12
+ SecretType,
13
+ SyncConnectResponse
8
14
  } from '../types.js';
9
15
 
10
16
  class ApiError extends Error {
@@ -136,4 +142,83 @@ export async function getAllMemories(): Promise<Memory[]> {
136
142
  return allMemories;
137
143
  }
138
144
 
145
+ // Secrets API functions
146
+
147
+ export async function listSecrets(
148
+ limit: number = 100,
149
+ type?: SecretType
150
+ ): Promise<SecretsListResponse> {
151
+ let endpoint = `/secrets?limit=${limit}`;
152
+ if (type) {
153
+ endpoint += `&type=${type}`;
154
+ }
155
+ return request<SecretsListResponse>(endpoint);
156
+ }
157
+
158
+ export async function getSecret(name: string): Promise<Secret> {
159
+ const response = await request<{ secret: Secret }>(`/secrets/${encodeURIComponent(name)}`);
160
+ return response.secret;
161
+ }
162
+
163
+ export async function setSecret(
164
+ name: string,
165
+ value: string,
166
+ type: SecretType = 'generic',
167
+ description?: string,
168
+ metadata?: Record<string, unknown>
169
+ ): Promise<SecretResponse> {
170
+ const body: {
171
+ name: string;
172
+ value: string;
173
+ type: SecretType;
174
+ description?: string;
175
+ metadata?: Record<string, unknown>;
176
+ } = { name, value, type };
177
+
178
+ if (description) {
179
+ body.description = description;
180
+ }
181
+ if (metadata) {
182
+ body.metadata = metadata;
183
+ }
184
+
185
+ return request<SecretResponse>('/secrets', {
186
+ method: 'POST',
187
+ body: JSON.stringify(body),
188
+ });
189
+ }
190
+
191
+ export async function deleteSecret(name: string): Promise<void> {
192
+ await request<{ message: string; name: string }>(
193
+ `/secrets/${encodeURIComponent(name)}`,
194
+ { method: 'DELETE' }
195
+ );
196
+ }
197
+
198
+ export async function getAllSecrets(): Promise<SecretListItem[]> {
199
+ const response = await listSecrets(500);
200
+ return response.secrets;
201
+ }
202
+
203
+ // Sync connect API
204
+ export async function syncConnect(options?: {
205
+ include_files?: boolean;
206
+ memories_limit?: number;
207
+ secrets_limit?: number;
208
+ }): Promise<SyncConnectResponse> {
209
+ return request<SyncConnectResponse>('/sync/connect', {
210
+ method: 'POST',
211
+ body: JSON.stringify(options || {}),
212
+ });
213
+ }
214
+
215
+ export async function checkConnection(): Promise<{
216
+ connected: boolean;
217
+ agent: { id: string; name: string };
218
+ counts: { memories: number; secrets: number };
219
+ server_time: string;
220
+ }> {
221
+ return request('/sync/connect');
222
+ }
223
+
139
224
  export { ApiError };
@@ -0,0 +1,160 @@
1
+ import * as fs from 'fs';
2
+ import * as path from 'path';
3
+ import * as os from 'os';
4
+ import { getApiKey, getApiUrl, getMemoryFilePath } from './config.js';
5
+
6
+ const CONFIG_DIR = path.join(os.homedir(), '.agentmemory');
7
+ const SYNC_CACHE_FILE = path.join(CONFIG_DIR, 'sync-cache.json');
8
+ const SYNC_INTERVAL_MS = 30000; // Only sync if last sync was 30+ seconds ago
9
+
10
+ interface SyncCache {
11
+ last_sync: string;
12
+ last_sync_ms: number;
13
+ memory_count: number;
14
+ secret_count: number;
15
+ }
16
+
17
+ function loadSyncCache(): SyncCache | null {
18
+ try {
19
+ if (fs.existsSync(SYNC_CACHE_FILE)) {
20
+ return JSON.parse(fs.readFileSync(SYNC_CACHE_FILE, 'utf-8'));
21
+ }
22
+ } catch {
23
+ // Ignore errors
24
+ }
25
+ return null;
26
+ }
27
+
28
+ function saveSyncCache(cache: SyncCache): void {
29
+ try {
30
+ if (!fs.existsSync(CONFIG_DIR)) {
31
+ fs.mkdirSync(CONFIG_DIR, { recursive: true });
32
+ }
33
+ fs.writeFileSync(SYNC_CACHE_FILE, JSON.stringify(cache, null, 2));
34
+ } catch {
35
+ // Ignore errors
36
+ }
37
+ }
38
+
39
+ /**
40
+ * Silent auto-sync - runs at the start of every command
41
+ * - Sends heartbeat to mark agent as online
42
+ * - Syncs memories to local MEMORY.md file
43
+ * - Caches results to avoid syncing too frequently
44
+ * - Never throws errors or prints output (silent)
45
+ */
46
+ export async function autoSync(): Promise<void> {
47
+ const apiKey = getApiKey();
48
+ if (!apiKey) return; // Not configured yet
49
+
50
+ // Check if we synced recently (within 30 seconds)
51
+ const cache = loadSyncCache();
52
+ if (cache && Date.now() - cache.last_sync_ms < SYNC_INTERVAL_MS) {
53
+ return; // Skip sync, too recent
54
+ }
55
+
56
+ const apiUrl = getApiUrl();
57
+
58
+ try {
59
+ // Send heartbeat with sync
60
+ const response = await fetch(`${apiUrl}/heartbeat`, {
61
+ method: 'POST',
62
+ headers: {
63
+ 'Authorization': `Bearer ${apiKey}`,
64
+ 'Content-Type': 'application/json',
65
+ },
66
+ body: JSON.stringify({ sync: true }),
67
+ });
68
+
69
+ if (!response.ok) return;
70
+
71
+ const data = await response.json() as {
72
+ sync?: {
73
+ memories: {
74
+ items: Array<{
75
+ id: string;
76
+ content: string;
77
+ metadata?: Record<string, unknown>;
78
+ created_at: string;
79
+ updated_at?: string;
80
+ }>;
81
+ count: number;
82
+ };
83
+ secrets: {
84
+ count: number;
85
+ };
86
+ synced_at: string;
87
+ };
88
+ };
89
+
90
+ if (!data.sync) return;
91
+
92
+ // Save memories to local MEMORY.md file (silently)
93
+ if (data.sync.memories.items.length > 0) {
94
+ try {
95
+ const memoryFilePath = getMemoryFilePath();
96
+ const dir = path.dirname(memoryFilePath);
97
+ if (!fs.existsSync(dir)) {
98
+ fs.mkdirSync(dir, { recursive: true });
99
+ }
100
+
101
+ const lines: string[] = [
102
+ '# Agent Memory',
103
+ '',
104
+ `> Last synced: ${data.sync.synced_at}`,
105
+ `> Total memories: ${data.sync.memories.count}`,
106
+ '',
107
+ '---',
108
+ '',
109
+ ];
110
+
111
+ for (const memory of data.sync.memories.items) {
112
+ lines.push(`<!-- id: ${memory.id} -->`);
113
+ if (memory.metadata && Object.keys(memory.metadata).length > 0) {
114
+ lines.push(`<!-- metadata: ${JSON.stringify(memory.metadata)} -->`);
115
+ }
116
+ lines.push(memory.content);
117
+ lines.push('');
118
+ lines.push('---');
119
+ lines.push('');
120
+ }
121
+
122
+ fs.writeFileSync(memoryFilePath, lines.join('\n'));
123
+ } catch {
124
+ // Silently ignore file write errors
125
+ }
126
+ }
127
+
128
+ // Update cache
129
+ saveSyncCache({
130
+ last_sync: data.sync.synced_at,
131
+ last_sync_ms: Date.now(),
132
+ memory_count: data.sync.memories.count,
133
+ secret_count: data.sync.secrets.count,
134
+ });
135
+ } catch {
136
+ // Silently ignore all errors - auto-sync should never break commands
137
+ }
138
+ }
139
+
140
+ /**
141
+ * Quick heartbeat - just marks agent as online, no sync
142
+ * Use this for commands that don't need fresh data
143
+ */
144
+ export async function quickHeartbeat(): Promise<void> {
145
+ const apiKey = getApiKey();
146
+ if (!apiKey) return;
147
+
148
+ const apiUrl = getApiUrl();
149
+
150
+ try {
151
+ await fetch(`${apiUrl}/heartbeat`, {
152
+ method: 'GET',
153
+ headers: {
154
+ 'Authorization': `Bearer ${apiKey}`,
155
+ },
156
+ });
157
+ } catch {
158
+ // Silently ignore
159
+ }
160
+ }
package/src/types.ts CHANGED
@@ -45,3 +45,70 @@ export interface SyncStatus {
45
45
  cloud: Memory;
46
46
  }>;
47
47
  }
48
+
49
+ // Secrets types
50
+ export type SecretType = 'api_key' | 'credential' | 'connection_string' | 'env_var' | 'generic';
51
+
52
+ export interface Secret {
53
+ id: string;
54
+ name: string;
55
+ value?: string;
56
+ type: SecretType;
57
+ description?: string;
58
+ metadata?: Record<string, unknown>;
59
+ created_at: string;
60
+ updated_at: string;
61
+ }
62
+
63
+ export interface SecretListItem {
64
+ id: string;
65
+ name: string;
66
+ type: SecretType;
67
+ description?: string;
68
+ metadata?: Record<string, unknown>;
69
+ created_at: string;
70
+ updated_at: string;
71
+ }
72
+
73
+ export interface SecretsListResponse {
74
+ secrets: SecretListItem[];
75
+ total: number;
76
+ limit: number;
77
+ offset: number;
78
+ }
79
+
80
+ export interface SecretResponse {
81
+ secret: Secret;
82
+ message?: string;
83
+ }
84
+
85
+ // Sync connect types
86
+ export interface SyncConnectResponse {
87
+ agent: {
88
+ id: string;
89
+ name: string;
90
+ memory_count: number;
91
+ created_at: string;
92
+ };
93
+ plan: {
94
+ name: string;
95
+ activated: boolean;
96
+ limits: {
97
+ memories: number;
98
+ secrets: number;
99
+ };
100
+ };
101
+ sync: {
102
+ memories: {
103
+ items: Memory[];
104
+ total: number;
105
+ has_more: boolean;
106
+ };
107
+ secrets: {
108
+ items: SecretListItem[];
109
+ total: number;
110
+ has_more: boolean;
111
+ };
112
+ synced_at: string;
113
+ };
114
+ }