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.
- package/README.md +198 -0
- package/dist/commands/delete.d.ts +7 -0
- package/dist/commands/delete.d.ts.map +1 -0
- package/dist/commands/delete.js +67 -0
- package/dist/commands/delete.js.map +1 -0
- package/dist/commands/export.d.ts +7 -0
- package/dist/commands/export.d.ts.map +1 -0
- package/dist/commands/export.js +79 -0
- package/dist/commands/export.js.map +1 -0
- package/dist/commands/import.d.ts +6 -0
- package/dist/commands/import.d.ts.map +1 -0
- package/dist/commands/import.js +107 -0
- package/dist/commands/import.js.map +1 -0
- package/dist/commands/init.d.ts +2 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +65 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/list.d.ts +8 -0
- package/dist/commands/list.d.ts.map +1 -0
- package/dist/commands/list.js +55 -0
- package/dist/commands/list.js.map +1 -0
- package/dist/commands/search.d.ts +7 -0
- package/dist/commands/search.d.ts.map +1 -0
- package/dist/commands/search.js +47 -0
- package/dist/commands/search.js.map +1 -0
- package/dist/commands/store.d.ts +8 -0
- package/dist/commands/store.d.ts.map +1 -0
- package/dist/commands/store.js +51 -0
- package/dist/commands/store.js.map +1 -0
- package/dist/commands/sync.d.ts +9 -0
- package/dist/commands/sync.d.ts.map +1 -0
- package/dist/commands/sync.js +90 -0
- package/dist/commands/sync.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +106 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/api.d.ts +14 -0
- package/dist/lib/api.d.ts.map +1 -0
- package/dist/lib/api.js +98 -0
- package/dist/lib/api.js.map +1 -0
- package/dist/lib/config.d.ts +13 -0
- package/dist/lib/config.d.ts.map +1 -0
- package/dist/lib/config.js +123 -0
- package/dist/lib/config.js.map +1 -0
- package/dist/lib/sync.d.ts +43 -0
- package/dist/lib/sync.d.ts.map +1 -0
- package/dist/lib/sync.js +184 -0
- package/dist/lib/sync.js.map +1 -0
- package/dist/types.d.ts +41 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/package.json +44 -0
- package/src/commands/delete.ts +72 -0
- package/src/commands/export.ts +46 -0
- package/src/commands/import.ts +87 -0
- package/src/commands/init.ts +71 -0
- package/src/commands/list.ts +61 -0
- package/src/commands/search.ts +52 -0
- package/src/commands/store.ts +58 -0
- package/src/commands/sync.ts +102 -0
- package/src/index.ts +114 -0
- package/src/lib/api.ts +139 -0
- package/src/lib/config.ts +95 -0
- package/src/lib/sync.ts +186 -0
- package/src/types.ts +47 -0
- package/tsconfig.json +20 -0
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import { searchMemories } from '../lib/api.js';
|
|
3
|
+
import { isConfigured } from '../lib/config.js';
|
|
4
|
+
|
|
5
|
+
interface SearchOptions {
|
|
6
|
+
limit?: string;
|
|
7
|
+
json?: boolean;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export async function searchCommand(
|
|
11
|
+
query: string,
|
|
12
|
+
options: SearchOptions
|
|
13
|
+
): Promise<void> {
|
|
14
|
+
if (!isConfigured()) {
|
|
15
|
+
console.log(chalk.red('ā Not configured. Run "agentmemory init" first.'));
|
|
16
|
+
process.exit(1);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
try {
|
|
20
|
+
const limit = options.limit ? parseInt(options.limit, 10) : 10;
|
|
21
|
+
const memories = await searchMemories(query, limit);
|
|
22
|
+
|
|
23
|
+
if (options.json) {
|
|
24
|
+
console.log(JSON.stringify(memories, null, 2));
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
if (memories.length === 0) {
|
|
29
|
+
console.log(chalk.yellow('No memories found matching your query.'));
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
console.log(chalk.cyan(`\nš Found ${memories.length} memories:\n`));
|
|
34
|
+
|
|
35
|
+
for (const memory of memories) {
|
|
36
|
+
const similarity = (memory.similarity * 100).toFixed(1);
|
|
37
|
+
console.log(chalk.green(`[${similarity}%] `) + chalk.white(memory.content));
|
|
38
|
+
console.log(chalk.dim(` ID: ${memory.id}`));
|
|
39
|
+
if (memory.metadata && Object.keys(memory.metadata).length > 0) {
|
|
40
|
+
console.log(chalk.dim(` Metadata: ${JSON.stringify(memory.metadata)}`));
|
|
41
|
+
}
|
|
42
|
+
console.log();
|
|
43
|
+
}
|
|
44
|
+
} catch (error) {
|
|
45
|
+
if (error instanceof Error) {
|
|
46
|
+
console.log(chalk.red(`ā Error: ${error.message}`));
|
|
47
|
+
} else {
|
|
48
|
+
console.log(chalk.red('ā Unknown error occurred'));
|
|
49
|
+
}
|
|
50
|
+
process.exit(1);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import { storeMemory } from '../lib/api.js';
|
|
3
|
+
import { isConfigured } from '../lib/config.js';
|
|
4
|
+
|
|
5
|
+
interface StoreOptions {
|
|
6
|
+
category?: string;
|
|
7
|
+
metadata?: string;
|
|
8
|
+
json?: boolean;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export async function storeCommand(
|
|
12
|
+
content: string,
|
|
13
|
+
options: StoreOptions
|
|
14
|
+
): Promise<void> {
|
|
15
|
+
if (!isConfigured()) {
|
|
16
|
+
console.log(chalk.red('ā Not configured. Run "agentmemory init" first.'));
|
|
17
|
+
process.exit(1);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
try {
|
|
21
|
+
// Build metadata
|
|
22
|
+
let metadata: Record<string, unknown> = {};
|
|
23
|
+
|
|
24
|
+
if (options.category) {
|
|
25
|
+
metadata.category = options.category;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
if (options.metadata) {
|
|
29
|
+
try {
|
|
30
|
+
const parsed = JSON.parse(options.metadata);
|
|
31
|
+
metadata = { ...metadata, ...parsed };
|
|
32
|
+
} catch {
|
|
33
|
+
console.log(chalk.red('ā Invalid metadata JSON format'));
|
|
34
|
+
process.exit(1);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const memory = await storeMemory(
|
|
39
|
+
content,
|
|
40
|
+
Object.keys(metadata).length > 0 ? metadata : undefined
|
|
41
|
+
);
|
|
42
|
+
|
|
43
|
+
if (options.json) {
|
|
44
|
+
console.log(JSON.stringify(memory, null, 2));
|
|
45
|
+
} else {
|
|
46
|
+
console.log(chalk.green('ā
Memory stored successfully!'));
|
|
47
|
+
console.log(chalk.dim(` ID: ${memory.id}`));
|
|
48
|
+
console.log(chalk.dim(` Created: ${memory.created_at}`));
|
|
49
|
+
}
|
|
50
|
+
} catch (error) {
|
|
51
|
+
if (error instanceof Error) {
|
|
52
|
+
console.log(chalk.red(`ā Error: ${error.message}`));
|
|
53
|
+
} else {
|
|
54
|
+
console.log(chalk.red('ā Unknown error occurred'));
|
|
55
|
+
}
|
|
56
|
+
process.exit(1);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import { isConfigured, getMemoryFilePath } from '../lib/config.js';
|
|
3
|
+
import { syncMemories, getSyncStatus } from '../lib/sync.js';
|
|
4
|
+
|
|
5
|
+
interface SyncOptions {
|
|
6
|
+
push?: boolean;
|
|
7
|
+
pull?: boolean;
|
|
8
|
+
status?: boolean;
|
|
9
|
+
json?: boolean;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export async function syncCommand(options: SyncOptions): Promise<void> {
|
|
13
|
+
if (!isConfigured()) {
|
|
14
|
+
console.log(chalk.red('ā Not configured. Run "agentmemory init" first.'));
|
|
15
|
+
process.exit(1);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const memoryFile = getMemoryFilePath();
|
|
19
|
+
|
|
20
|
+
try {
|
|
21
|
+
// Status only mode
|
|
22
|
+
if (options.status) {
|
|
23
|
+
console.log(chalk.dim('Checking sync status...'));
|
|
24
|
+
const status = await getSyncStatus();
|
|
25
|
+
|
|
26
|
+
if (options.json) {
|
|
27
|
+
console.log(JSON.stringify(status, null, 2));
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
console.log(chalk.cyan('\nš Sync Status:\n'));
|
|
32
|
+
console.log(` Memory file: ${memoryFile}`);
|
|
33
|
+
console.log(` Synced: ${chalk.green(status.synced)}`);
|
|
34
|
+
console.log(` Local only: ${chalk.yellow(status.localOnly.length)}`);
|
|
35
|
+
console.log(` Cloud only: ${chalk.blue(status.cloudOnly.length)}`);
|
|
36
|
+
|
|
37
|
+
if (status.localOnly.length > 0) {
|
|
38
|
+
console.log(chalk.yellow('\n Local memories not in cloud:'));
|
|
39
|
+
for (const m of status.localOnly.slice(0, 5)) {
|
|
40
|
+
const preview = m.content.substring(0, 50);
|
|
41
|
+
console.log(chalk.dim(` ⢠${preview}...`));
|
|
42
|
+
}
|
|
43
|
+
if (status.localOnly.length > 5) {
|
|
44
|
+
console.log(chalk.dim(` ... and ${status.localOnly.length - 5} more`));
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
if (status.cloudOnly.length > 0) {
|
|
49
|
+
console.log(chalk.blue('\n Cloud memories not in local file:'));
|
|
50
|
+
for (const m of status.cloudOnly.slice(0, 5)) {
|
|
51
|
+
const preview = m.content.substring(0, 50);
|
|
52
|
+
console.log(chalk.dim(` ⢠${preview}...`));
|
|
53
|
+
}
|
|
54
|
+
if (status.cloudOnly.length > 5) {
|
|
55
|
+
console.log(chalk.dim(` ... and ${status.cloudOnly.length - 5} more`));
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
console.log();
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// Determine sync direction
|
|
64
|
+
let direction: 'push' | 'pull' | 'both' = 'both';
|
|
65
|
+
if (options.push && !options.pull) {
|
|
66
|
+
direction = 'push';
|
|
67
|
+
} else if (options.pull && !options.push) {
|
|
68
|
+
direction = 'pull';
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
console.log(chalk.dim(`Syncing memories (${direction})...`));
|
|
72
|
+
console.log(chalk.dim(`Memory file: ${memoryFile}\n`));
|
|
73
|
+
|
|
74
|
+
const result = await syncMemories(direction);
|
|
75
|
+
|
|
76
|
+
if (options.json) {
|
|
77
|
+
console.log(JSON.stringify(result, null, 2));
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
console.log(chalk.green('ā
Sync complete!\n'));
|
|
82
|
+
console.log(` š¤ Uploaded: ${chalk.green(result.uploaded)}`);
|
|
83
|
+
console.log(` š„ Downloaded: ${chalk.blue(result.downloaded)}`);
|
|
84
|
+
console.log(` āļø Unchanged: ${chalk.dim(result.unchanged)}`);
|
|
85
|
+
|
|
86
|
+
if (result.errors.length > 0) {
|
|
87
|
+
console.log(chalk.red(`\n ā Errors: ${result.errors.length}`));
|
|
88
|
+
for (const error of result.errors) {
|
|
89
|
+
console.log(chalk.red(` ⢠${error}`));
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
console.log();
|
|
94
|
+
} catch (error) {
|
|
95
|
+
if (error instanceof Error) {
|
|
96
|
+
console.log(chalk.red(`ā Error: ${error.message}`));
|
|
97
|
+
} else {
|
|
98
|
+
console.log(chalk.red('ā Unknown error occurred'));
|
|
99
|
+
}
|
|
100
|
+
process.exit(1);
|
|
101
|
+
}
|
|
102
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { Command } from 'commander';
|
|
4
|
+
import chalk from 'chalk';
|
|
5
|
+
import { initCommand } from './commands/init.js';
|
|
6
|
+
import { storeCommand } from './commands/store.js';
|
|
7
|
+
import { searchCommand } from './commands/search.js';
|
|
8
|
+
import { listCommand } from './commands/list.js';
|
|
9
|
+
import { deleteCommand } from './commands/delete.js';
|
|
10
|
+
import { syncCommand } from './commands/sync.js';
|
|
11
|
+
import { exportCommand } from './commands/export.js';
|
|
12
|
+
import { importCommand } from './commands/import.js';
|
|
13
|
+
|
|
14
|
+
const program = new Command();
|
|
15
|
+
|
|
16
|
+
program
|
|
17
|
+
.name('agentmemory')
|
|
18
|
+
.description('CLI tool for AgentMemory - persistent cloud memory for AI agents')
|
|
19
|
+
.version('1.0.0');
|
|
20
|
+
|
|
21
|
+
// Init command
|
|
22
|
+
program
|
|
23
|
+
.command('init')
|
|
24
|
+
.description('Initialize AgentMemory CLI with your API key')
|
|
25
|
+
.action(initCommand);
|
|
26
|
+
|
|
27
|
+
// Store command
|
|
28
|
+
program
|
|
29
|
+
.command('store <content>')
|
|
30
|
+
.description('Store a new memory')
|
|
31
|
+
.option('-c, --category <category>', 'Category for the memory')
|
|
32
|
+
.option('-m, --metadata <json>', 'Additional metadata as JSON')
|
|
33
|
+
.option('--json', 'Output as JSON')
|
|
34
|
+
.action(storeCommand);
|
|
35
|
+
|
|
36
|
+
// Search command
|
|
37
|
+
program
|
|
38
|
+
.command('search <query>')
|
|
39
|
+
.description('Search memories semantically')
|
|
40
|
+
.option('-l, --limit <number>', 'Maximum number of results', '10')
|
|
41
|
+
.option('--json', 'Output as JSON')
|
|
42
|
+
.action(searchCommand);
|
|
43
|
+
|
|
44
|
+
// List command
|
|
45
|
+
program
|
|
46
|
+
.command('list')
|
|
47
|
+
.description('List all memories')
|
|
48
|
+
.option('-l, --limit <number>', 'Maximum number of results', '50')
|
|
49
|
+
.option('-o, --offset <number>', 'Offset for pagination', '0')
|
|
50
|
+
.option('--json', 'Output as JSON')
|
|
51
|
+
.action(listCommand);
|
|
52
|
+
|
|
53
|
+
// Delete command
|
|
54
|
+
program
|
|
55
|
+
.command('delete <id>')
|
|
56
|
+
.description('Delete a memory by ID')
|
|
57
|
+
.option('-f, --force', 'Skip confirmation')
|
|
58
|
+
.option('--json', 'Output as JSON')
|
|
59
|
+
.action(deleteCommand);
|
|
60
|
+
|
|
61
|
+
// Sync command
|
|
62
|
+
program
|
|
63
|
+
.command('sync')
|
|
64
|
+
.description('Sync memories with local MEMORY.md file')
|
|
65
|
+
.option('--push', 'Only push local to cloud')
|
|
66
|
+
.option('--pull', 'Only pull cloud to local')
|
|
67
|
+
.option('--status', 'Show sync status without making changes')
|
|
68
|
+
.option('--json', 'Output as JSON')
|
|
69
|
+
.action(syncCommand);
|
|
70
|
+
|
|
71
|
+
// Export command
|
|
72
|
+
program
|
|
73
|
+
.command('export')
|
|
74
|
+
.description('Export all memories as JSON')
|
|
75
|
+
.option('-o, --output <file>', 'Output file path')
|
|
76
|
+
.option('-p, --pretty', 'Pretty print JSON')
|
|
77
|
+
.action(exportCommand);
|
|
78
|
+
|
|
79
|
+
// Import command
|
|
80
|
+
program
|
|
81
|
+
.command('import <file>')
|
|
82
|
+
.description('Import memories from JSON file')
|
|
83
|
+
.option('--json', 'Output as JSON')
|
|
84
|
+
.action(importCommand);
|
|
85
|
+
|
|
86
|
+
// Custom help
|
|
87
|
+
program.addHelpText('after', `
|
|
88
|
+
${chalk.cyan('Examples:')}
|
|
89
|
+
$ agentmemory init # Setup with your API key
|
|
90
|
+
$ agentmemory store "User prefers dark mode"
|
|
91
|
+
$ agentmemory search "user preferences"
|
|
92
|
+
$ agentmemory list --limit 10
|
|
93
|
+
$ agentmemory sync # Sync with MEMORY.md
|
|
94
|
+
$ agentmemory export > backup.json
|
|
95
|
+
|
|
96
|
+
${chalk.cyan('Documentation:')}
|
|
97
|
+
https://agentmemory.cloud/docs
|
|
98
|
+
|
|
99
|
+
${chalk.cyan('Get your API key:')}
|
|
100
|
+
https://agentmemory.cloud/dashboard
|
|
101
|
+
`);
|
|
102
|
+
|
|
103
|
+
// Parse arguments
|
|
104
|
+
program.parse();
|
|
105
|
+
|
|
106
|
+
// Show help if no command provided
|
|
107
|
+
if (!process.argv.slice(2).length) {
|
|
108
|
+
console.log(chalk.cyan(`
|
|
109
|
+
š§ AgentMemory CLI v1.0.0
|
|
110
|
+
|
|
111
|
+
Persistent cloud memory for AI agents.
|
|
112
|
+
`));
|
|
113
|
+
program.outputHelp();
|
|
114
|
+
}
|
package/src/lib/api.ts
ADDED
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import { getApiKey, getApiUrl } from './config.js';
|
|
2
|
+
import type {
|
|
3
|
+
Memory,
|
|
4
|
+
MemoriesListResponse,
|
|
5
|
+
MemoryCreateResponse,
|
|
6
|
+
MemorySearchResponse,
|
|
7
|
+
MemorySearchResult
|
|
8
|
+
} from '../types.js';
|
|
9
|
+
|
|
10
|
+
class ApiError extends Error {
|
|
11
|
+
constructor(public statusCode: number, message: string) {
|
|
12
|
+
super(message);
|
|
13
|
+
this.name = 'ApiError';
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
async function request<T>(
|
|
18
|
+
endpoint: string,
|
|
19
|
+
options: RequestInit = {}
|
|
20
|
+
): Promise<T> {
|
|
21
|
+
const apiKey = getApiKey();
|
|
22
|
+
const apiUrl = getApiUrl();
|
|
23
|
+
|
|
24
|
+
if (!apiKey) {
|
|
25
|
+
throw new Error('API key not configured. Run "agentmemory init" first.');
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const url = `${apiUrl}${endpoint}`;
|
|
29
|
+
|
|
30
|
+
const response = await fetch(url, {
|
|
31
|
+
...options,
|
|
32
|
+
headers: {
|
|
33
|
+
'Authorization': `Bearer ${apiKey}`,
|
|
34
|
+
'Content-Type': 'application/json',
|
|
35
|
+
...options.headers,
|
|
36
|
+
},
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
const data = await response.json() as { error?: string } & T;
|
|
40
|
+
|
|
41
|
+
if (!response.ok) {
|
|
42
|
+
throw new ApiError(
|
|
43
|
+
response.status,
|
|
44
|
+
data.error || `Request failed with status ${response.status}`
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return data;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export async function storeMemory(
|
|
52
|
+
content: string,
|
|
53
|
+
metadata?: Record<string, unknown>
|
|
54
|
+
): Promise<Memory> {
|
|
55
|
+
const body: { content: string; metadata?: Record<string, unknown> } = { content };
|
|
56
|
+
if (metadata) {
|
|
57
|
+
body.metadata = metadata;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const response = await request<MemoryCreateResponse>('/memories', {
|
|
61
|
+
method: 'POST',
|
|
62
|
+
body: JSON.stringify(body),
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
return response.memory;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export async function searchMemories(
|
|
69
|
+
query: string,
|
|
70
|
+
limit: number = 10
|
|
71
|
+
): Promise<MemorySearchResult[]> {
|
|
72
|
+
const response = await request<MemorySearchResponse>('/memories/search', {
|
|
73
|
+
method: 'POST',
|
|
74
|
+
body: JSON.stringify({ query, limit }),
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
return response.memories;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export async function listMemories(
|
|
81
|
+
limit: number = 50,
|
|
82
|
+
offset: number = 0
|
|
83
|
+
): Promise<MemoriesListResponse> {
|
|
84
|
+
const response = await request<MemoriesListResponse>(
|
|
85
|
+
`/memories?limit=${limit}&offset=${offset}`
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
return response;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export async function getMemory(id: string): Promise<Memory> {
|
|
92
|
+
const response = await request<{ memory: Memory }>(`/memories/${id}`);
|
|
93
|
+
return response.memory;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export async function updateMemory(
|
|
97
|
+
id: string,
|
|
98
|
+
content: string,
|
|
99
|
+
metadata?: Record<string, unknown>
|
|
100
|
+
): Promise<Memory> {
|
|
101
|
+
const body: { content: string; metadata?: Record<string, unknown> } = { content };
|
|
102
|
+
if (metadata) {
|
|
103
|
+
body.metadata = metadata;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
const response = await request<{ memory: Memory }>(`/memories/${id}`, {
|
|
107
|
+
method: 'PUT',
|
|
108
|
+
body: JSON.stringify(body),
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
return response.memory;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export async function deleteMemory(id: string): Promise<void> {
|
|
115
|
+
await request<{ success: boolean }>(`/memories/${id}`, {
|
|
116
|
+
method: 'DELETE',
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export async function getAllMemories(): Promise<Memory[]> {
|
|
121
|
+
const allMemories: Memory[] = [];
|
|
122
|
+
let offset = 0;
|
|
123
|
+
const limit = 100;
|
|
124
|
+
|
|
125
|
+
while (true) {
|
|
126
|
+
const response = await listMemories(limit, offset);
|
|
127
|
+
allMemories.push(...response.memories);
|
|
128
|
+
|
|
129
|
+
if (response.memories.length < limit) {
|
|
130
|
+
break;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
offset += limit;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
return allMemories;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
export { ApiError };
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import * as fs from 'fs';
|
|
2
|
+
import * as path from 'path';
|
|
3
|
+
import * as os from 'os';
|
|
4
|
+
import type { Config } from '../types.js';
|
|
5
|
+
|
|
6
|
+
const CONFIG_DIR = path.join(os.homedir(), '.agentmemory');
|
|
7
|
+
const CONFIG_FILE = path.join(CONFIG_DIR, 'config.json');
|
|
8
|
+
|
|
9
|
+
const DEFAULT_CONFIG: Config = {
|
|
10
|
+
api_key: '',
|
|
11
|
+
api_url: 'https://agentmemory.cloud/api',
|
|
12
|
+
memory_file: './MEMORY.md'
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export function getConfigDir(): string {
|
|
16
|
+
return CONFIG_DIR;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function getConfigPath(): string {
|
|
20
|
+
return CONFIG_FILE;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function ensureConfigDir(): void {
|
|
24
|
+
if (!fs.existsSync(CONFIG_DIR)) {
|
|
25
|
+
fs.mkdirSync(CONFIG_DIR, { recursive: true });
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function configExists(): boolean {
|
|
30
|
+
return fs.existsSync(CONFIG_FILE);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export function loadConfig(): Config {
|
|
34
|
+
ensureConfigDir();
|
|
35
|
+
|
|
36
|
+
if (!fs.existsSync(CONFIG_FILE)) {
|
|
37
|
+
return { ...DEFAULT_CONFIG };
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
try {
|
|
41
|
+
const content = fs.readFileSync(CONFIG_FILE, 'utf-8');
|
|
42
|
+
const config = JSON.parse(content) as Partial<Config>;
|
|
43
|
+
return { ...DEFAULT_CONFIG, ...config };
|
|
44
|
+
} catch (error) {
|
|
45
|
+
console.error('Error reading config file:', error);
|
|
46
|
+
return { ...DEFAULT_CONFIG };
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export function saveConfig(config: Partial<Config>): void {
|
|
51
|
+
ensureConfigDir();
|
|
52
|
+
|
|
53
|
+
const existingConfig = loadConfig();
|
|
54
|
+
const newConfig = { ...existingConfig, ...config };
|
|
55
|
+
|
|
56
|
+
fs.writeFileSync(CONFIG_FILE, JSON.stringify(newConfig, null, 2));
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export function getApiKey(): string {
|
|
60
|
+
// Check environment variable first
|
|
61
|
+
const envKey = process.env.AGENTMEMORY_API_KEY;
|
|
62
|
+
if (envKey) {
|
|
63
|
+
return envKey;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Fall back to config file
|
|
67
|
+
const config = loadConfig();
|
|
68
|
+
return config.api_key;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export function getApiUrl(): string {
|
|
72
|
+
const envUrl = process.env.AGENTMEMORY_API_URL;
|
|
73
|
+
if (envUrl) {
|
|
74
|
+
return envUrl;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const config = loadConfig();
|
|
78
|
+
return config.api_url;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export function getMemoryFilePath(): string {
|
|
82
|
+
const config = loadConfig();
|
|
83
|
+
return config.memory_file;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export function isConfigured(): boolean {
|
|
87
|
+
const apiKey = getApiKey();
|
|
88
|
+
return apiKey.length > 0 && apiKey.startsWith('am_');
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export function clearConfig(): void {
|
|
92
|
+
if (fs.existsSync(CONFIG_FILE)) {
|
|
93
|
+
fs.unlinkSync(CONFIG_FILE);
|
|
94
|
+
}
|
|
95
|
+
}
|