agentmemory-cli 1.0.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.
- package/dist/commands/connect.d.ts +11 -0
- package/dist/commands/connect.d.ts.map +1 -0
- package/dist/commands/connect.js +232 -0
- package/dist/commands/connect.js.map +1 -0
- package/dist/commands/delete.d.ts.map +1 -1
- package/dist/commands/delete.js +3 -0
- package/dist/commands/delete.js.map +1 -1
- package/dist/commands/download.d.ts +5 -0
- package/dist/commands/download.d.ts.map +1 -0
- package/dist/commands/download.js +82 -0
- package/dist/commands/download.js.map +1 -0
- package/dist/commands/export.d.ts.map +1 -1
- package/dist/commands/export.js +3 -0
- package/dist/commands/export.js.map +1 -1
- package/dist/commands/files.d.ts +6 -0
- package/dist/commands/files.d.ts.map +1 -0
- package/dist/commands/files.js +101 -0
- package/dist/commands/files.js.map +1 -0
- package/dist/commands/heartbeat.d.ts +65 -0
- package/dist/commands/heartbeat.d.ts.map +1 -0
- package/dist/commands/heartbeat.js +176 -0
- package/dist/commands/heartbeat.js.map +1 -0
- package/dist/commands/import.d.ts.map +1 -1
- package/dist/commands/import.js +3 -0
- package/dist/commands/import.js.map +1 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +39 -1
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/list.d.ts.map +1 -1
- package/dist/commands/list.js +3 -0
- package/dist/commands/list.js.map +1 -1
- package/dist/commands/search.d.ts.map +1 -1
- package/dist/commands/search.js +3 -0
- package/dist/commands/search.js.map +1 -1
- package/dist/commands/secret.d.ts +25 -0
- package/dist/commands/secret.d.ts.map +1 -0
- package/dist/commands/secret.js +390 -0
- package/dist/commands/secret.js.map +1 -0
- package/dist/commands/store.d.ts.map +1 -1
- package/dist/commands/store.js +3 -0
- package/dist/commands/store.js.map +1 -1
- package/dist/commands/upload.d.ts +4 -0
- package/dist/commands/upload.d.ts.map +1 -0
- package/dist/commands/upload.js +110 -0
- package/dist/commands/upload.js.map +1 -0
- package/dist/index.js +136 -2
- package/dist/index.js.map +1 -1
- package/dist/lib/api.d.ts +23 -1
- package/dist/lib/api.d.ts.map +1 -1
- package/dist/lib/api.js +49 -0
- package/dist/lib/api.js.map +1 -1
- package/dist/lib/autosync.d.ts +14 -0
- package/dist/lib/autosync.d.ts.map +1 -0
- package/dist/lib/autosync.js +165 -0
- package/dist/lib/autosync.js.map +1 -0
- package/dist/types.d.ts +59 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +2 -1
- package/src/commands/connect.ts +216 -0
- package/src/commands/delete.ts +4 -0
- package/src/commands/download.ts +105 -0
- package/src/commands/export.ts +4 -0
- package/src/commands/files.ts +119 -0
- package/src/commands/heartbeat.ts +241 -0
- package/src/commands/import.ts +4 -0
- package/src/commands/init.ts +44 -1
- package/src/commands/list.ts +4 -0
- package/src/commands/search.ts +4 -0
- package/src/commands/secret.ts +438 -0
- package/src/commands/store.ts +4 -0
- package/src/commands/upload.ts +117 -0
- package/src/index.ts +158 -2
- package/src/lib/api.ts +86 -1
- package/src/lib/autosync.ts +160 -0
- package/src/types.ts +67 -0
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import * as fs from 'fs';
|
|
3
|
+
import { getApiKey, getMemoryFilePath } from '../lib/config.js';
|
|
4
|
+
import { syncConnect, checkConnection } from '../lib/api.js';
|
|
5
|
+
import { writeMemoryFile } from '../lib/sync.js';
|
|
6
|
+
|
|
7
|
+
// Store sync cache locally
|
|
8
|
+
interface SyncCache {
|
|
9
|
+
last_sync: string;
|
|
10
|
+
memory_count: number;
|
|
11
|
+
secret_count: number;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function getSyncCachePath(): string {
|
|
15
|
+
const configDir = require('path').join(require('os').homedir(), '.agentmemory');
|
|
16
|
+
return require('path').join(configDir, 'sync-cache.json');
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function loadSyncCache(): SyncCache | null {
|
|
20
|
+
const cachePath = getSyncCachePath();
|
|
21
|
+
if (!fs.existsSync(cachePath)) {
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
try {
|
|
25
|
+
return JSON.parse(fs.readFileSync(cachePath, 'utf-8'));
|
|
26
|
+
} catch {
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function saveSyncCache(cache: SyncCache): void {
|
|
32
|
+
const cachePath = getSyncCachePath();
|
|
33
|
+
fs.writeFileSync(cachePath, JSON.stringify(cache, null, 2));
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Connect and auto-sync command
|
|
37
|
+
export async function connectCommand(options: {
|
|
38
|
+
offline?: boolean;
|
|
39
|
+
noMemories?: boolean;
|
|
40
|
+
noSecrets?: boolean;
|
|
41
|
+
json?: boolean;
|
|
42
|
+
}): Promise<void> {
|
|
43
|
+
const apiKey = getApiKey();
|
|
44
|
+
|
|
45
|
+
if (!apiKey) {
|
|
46
|
+
if (options.json) {
|
|
47
|
+
console.log(JSON.stringify({ error: 'Not configured' }));
|
|
48
|
+
} else {
|
|
49
|
+
console.error(chalk.red('Error: Not configured. Run "agentmemory init" first.'));
|
|
50
|
+
}
|
|
51
|
+
process.exit(1);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
if (options.offline) {
|
|
55
|
+
const cache = loadSyncCache();
|
|
56
|
+
if (cache) {
|
|
57
|
+
if (options.json) {
|
|
58
|
+
console.log(JSON.stringify({ status: 'offline', cached: cache }));
|
|
59
|
+
} else {
|
|
60
|
+
console.log(chalk.yellow('Offline mode - using cached data'));
|
|
61
|
+
console.log(chalk.gray(` Last sync: ${cache.last_sync}`));
|
|
62
|
+
console.log(chalk.gray(` Memories: ${cache.memory_count}`));
|
|
63
|
+
console.log(chalk.gray(` Secrets: ${cache.secret_count}`));
|
|
64
|
+
}
|
|
65
|
+
} else {
|
|
66
|
+
if (options.json) {
|
|
67
|
+
console.log(JSON.stringify({ status: 'offline', cached: null }));
|
|
68
|
+
} else {
|
|
69
|
+
console.log(chalk.yellow('Offline mode - no cached data available'));
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
try {
|
|
76
|
+
if (!options.json) {
|
|
77
|
+
console.log(chalk.cyan('🔗 Connecting to AgentMemory...'));
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// Call sync/connect endpoint
|
|
81
|
+
const response = await syncConnect({
|
|
82
|
+
include_files: true,
|
|
83
|
+
memories_limit: 1000,
|
|
84
|
+
secrets_limit: 100,
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
if (options.json) {
|
|
88
|
+
console.log(JSON.stringify(response, null, 2));
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Display connection info
|
|
93
|
+
console.log(chalk.green('✓ Connected successfully!'));
|
|
94
|
+
console.log();
|
|
95
|
+
console.log(chalk.cyan('Agent:'), response.agent.name);
|
|
96
|
+
console.log(chalk.cyan('Plan:'), response.plan.name);
|
|
97
|
+
console.log();
|
|
98
|
+
|
|
99
|
+
// Display sync summary
|
|
100
|
+
console.log(chalk.cyan('Synced data:'));
|
|
101
|
+
console.log(` Memories: ${response.sync.memories.total}${response.sync.memories.has_more ? '+' : ''}`);
|
|
102
|
+
console.log(` Secrets: ${response.sync.secrets.total}${response.sync.secrets.has_more ? '+' : ''}`);
|
|
103
|
+
console.log();
|
|
104
|
+
|
|
105
|
+
// Save to local MEMORY.md if requested
|
|
106
|
+
if (!options.noMemories && response.sync.memories.items.length > 0) {
|
|
107
|
+
const memoryFilePath = getMemoryFilePath();
|
|
108
|
+
writeMemoryFile(memoryFilePath, response.sync.memories.items.map(m => ({
|
|
109
|
+
...m,
|
|
110
|
+
updated_at: m.updated_at || m.created_at,
|
|
111
|
+
})));
|
|
112
|
+
console.log(chalk.green(`✓ Saved ${response.sync.memories.items.length} memories to ${memoryFilePath}`));
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// Display secrets list (names only)
|
|
116
|
+
if (!options.noSecrets && response.sync.secrets.items.length > 0) {
|
|
117
|
+
console.log();
|
|
118
|
+
console.log(chalk.cyan('Available secrets:'));
|
|
119
|
+
for (const secret of response.sync.secrets.items) {
|
|
120
|
+
console.log(` - ${secret.name} (${secret.type})`);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// Save sync cache
|
|
125
|
+
saveSyncCache({
|
|
126
|
+
last_sync: response.sync.synced_at,
|
|
127
|
+
memory_count: response.sync.memories.total,
|
|
128
|
+
secret_count: response.sync.secrets.total,
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
// Show plan limits
|
|
132
|
+
console.log();
|
|
133
|
+
console.log(chalk.gray(`Limits: ${response.sync.memories.total}/${response.plan.limits.memories === Infinity ? '∞' : response.plan.limits.memories} memories, ${response.sync.secrets.total}/${response.plan.limits.secrets === Infinity ? '∞' : response.plan.limits.secrets} secrets`));
|
|
134
|
+
|
|
135
|
+
} catch (error) {
|
|
136
|
+
if (options.json) {
|
|
137
|
+
console.log(JSON.stringify({ error: error instanceof Error ? error.message : 'Unknown error' }));
|
|
138
|
+
} else {
|
|
139
|
+
console.error(chalk.red(`Error: ${error instanceof Error ? error.message : 'Unknown error'}`));
|
|
140
|
+
}
|
|
141
|
+
process.exit(1);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// Quick status check
|
|
146
|
+
export async function statusCommand(options: {
|
|
147
|
+
json?: boolean;
|
|
148
|
+
}): Promise<void> {
|
|
149
|
+
const apiKey = getApiKey();
|
|
150
|
+
|
|
151
|
+
if (!apiKey) {
|
|
152
|
+
if (options.json) {
|
|
153
|
+
console.log(JSON.stringify({ configured: false }));
|
|
154
|
+
} else {
|
|
155
|
+
console.error(chalk.red('Error: Not configured. Run "agentmemory init" first.'));
|
|
156
|
+
}
|
|
157
|
+
process.exit(1);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
try {
|
|
161
|
+
const status = await checkConnection();
|
|
162
|
+
|
|
163
|
+
if (options.json) {
|
|
164
|
+
console.log(JSON.stringify(status, null, 2));
|
|
165
|
+
} else {
|
|
166
|
+
console.log(chalk.green('✓ Connected'));
|
|
167
|
+
console.log();
|
|
168
|
+
console.log(chalk.cyan('Agent:'), status.agent.name);
|
|
169
|
+
console.log(chalk.cyan('Memories:'), status.counts.memories);
|
|
170
|
+
console.log(chalk.cyan('Secrets:'), status.counts.secrets);
|
|
171
|
+
console.log();
|
|
172
|
+
console.log(chalk.gray(`Server time: ${status.server_time}`));
|
|
173
|
+
}
|
|
174
|
+
} catch (error) {
|
|
175
|
+
if (options.json) {
|
|
176
|
+
console.log(JSON.stringify({ connected: false, error: error instanceof Error ? error.message : 'Unknown error' }));
|
|
177
|
+
} else {
|
|
178
|
+
console.error(chalk.red(`Connection failed: ${error instanceof Error ? error.message : 'Unknown error'}`));
|
|
179
|
+
}
|
|
180
|
+
process.exit(1);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// Auto-sync helper (can be called from other commands)
|
|
185
|
+
export async function autoSync(): Promise<boolean> {
|
|
186
|
+
const apiKey = getApiKey();
|
|
187
|
+
if (!apiKey) return false;
|
|
188
|
+
|
|
189
|
+
try {
|
|
190
|
+
const response = await syncConnect({
|
|
191
|
+
include_files: false,
|
|
192
|
+
memories_limit: 1000,
|
|
193
|
+
secrets_limit: 100,
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
// Save to local MEMORY.md
|
|
197
|
+
if (response.sync.memories.items.length > 0) {
|
|
198
|
+
const memoryFilePath = getMemoryFilePath();
|
|
199
|
+
writeMemoryFile(memoryFilePath, response.sync.memories.items.map(m => ({
|
|
200
|
+
...m,
|
|
201
|
+
updated_at: m.updated_at || m.created_at,
|
|
202
|
+
})));
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
// Save sync cache
|
|
206
|
+
saveSyncCache({
|
|
207
|
+
last_sync: response.sync.synced_at,
|
|
208
|
+
memory_count: response.sync.memories.total,
|
|
209
|
+
secret_count: response.sync.secrets.total,
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
return true;
|
|
213
|
+
} catch {
|
|
214
|
+
return false;
|
|
215
|
+
}
|
|
216
|
+
}
|
package/src/commands/delete.ts
CHANGED
|
@@ -2,6 +2,7 @@ import chalk from 'chalk';
|
|
|
2
2
|
import { createInterface } from 'readline';
|
|
3
3
|
import { deleteMemory, getMemory } from '../lib/api.js';
|
|
4
4
|
import { isConfigured } from '../lib/config.js';
|
|
5
|
+
import { autoSync } from '../lib/autosync.js';
|
|
5
6
|
|
|
6
7
|
interface DeleteOptions {
|
|
7
8
|
force?: boolean;
|
|
@@ -31,6 +32,9 @@ export async function deleteCommand(
|
|
|
31
32
|
process.exit(1);
|
|
32
33
|
}
|
|
33
34
|
|
|
35
|
+
// Auto-sync in background (silent)
|
|
36
|
+
autoSync();
|
|
37
|
+
|
|
34
38
|
try {
|
|
35
39
|
// First, get the memory to show what will be deleted
|
|
36
40
|
if (!options.force) {
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import fs from 'fs';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
import { getApiKey, getApiUrl } from '../lib/config.js';
|
|
5
|
+
import { autoSync } from '../lib/autosync.js';
|
|
6
|
+
|
|
7
|
+
interface FileResponse {
|
|
8
|
+
file: {
|
|
9
|
+
id: string;
|
|
10
|
+
name: string;
|
|
11
|
+
type: string;
|
|
12
|
+
size: number;
|
|
13
|
+
url: string;
|
|
14
|
+
download_url: string;
|
|
15
|
+
description: string;
|
|
16
|
+
extracted_text: string;
|
|
17
|
+
metadata: Record<string, unknown>;
|
|
18
|
+
created_at: string;
|
|
19
|
+
};
|
|
20
|
+
error?: string;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export async function downloadCommand(
|
|
24
|
+
fileId: string,
|
|
25
|
+
options: { output?: string; info?: boolean }
|
|
26
|
+
): Promise<void> {
|
|
27
|
+
const apiKey = getApiKey();
|
|
28
|
+
if (!apiKey) {
|
|
29
|
+
console.error(chalk.red('Not configured. Run: agentmemory init'));
|
|
30
|
+
process.exit(1);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Auto-sync in background (silent)
|
|
34
|
+
autoSync();
|
|
35
|
+
|
|
36
|
+
try {
|
|
37
|
+
const apiUrl = getApiUrl();
|
|
38
|
+
const response = await fetch(`${apiUrl}/files/${fileId}`, {
|
|
39
|
+
headers: {
|
|
40
|
+
'Authorization': `Bearer ${apiKey}`,
|
|
41
|
+
},
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
const data = await response.json() as FileResponse;
|
|
45
|
+
|
|
46
|
+
if (!response.ok) {
|
|
47
|
+
console.error(chalk.red(`Error: ${data.error || 'File not found'}`));
|
|
48
|
+
process.exit(1);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const file = data.file;
|
|
52
|
+
|
|
53
|
+
// If --info flag, just show file information
|
|
54
|
+
if (options.info) {
|
|
55
|
+
console.log(chalk.bold(`\nFile Information:\n`));
|
|
56
|
+
console.log(` ${chalk.cyan('Name:')} ${file.name}`);
|
|
57
|
+
console.log(` ${chalk.cyan('Type:')} ${file.type}`);
|
|
58
|
+
console.log(` ${chalk.cyan('Size:')} ${formatSize(file.size)}`);
|
|
59
|
+
console.log(` ${chalk.cyan('Created:')} ${new Date(file.created_at).toLocaleString()}`);
|
|
60
|
+
console.log(` ${chalk.cyan('ID:')} ${file.id}`);
|
|
61
|
+
if (file.description) {
|
|
62
|
+
console.log(` ${chalk.cyan('Description:')} ${file.description}`);
|
|
63
|
+
}
|
|
64
|
+
if (file.extracted_text) {
|
|
65
|
+
console.log(`\n${chalk.cyan('Extracted Content:')}`);
|
|
66
|
+
console.log(chalk.gray(file.extracted_text.slice(0, 500)));
|
|
67
|
+
if (file.extracted_text.length > 500) {
|
|
68
|
+
console.log(chalk.gray('... (truncated)'));
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// Download the file
|
|
75
|
+
if (!file.download_url) {
|
|
76
|
+
console.error(chalk.red('No download URL available'));
|
|
77
|
+
process.exit(1);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
console.log(chalk.blue(`Downloading ${file.name}...`));
|
|
81
|
+
|
|
82
|
+
const downloadResponse = await fetch(file.download_url);
|
|
83
|
+
if (!downloadResponse.ok) {
|
|
84
|
+
console.error(chalk.red('Failed to download file'));
|
|
85
|
+
process.exit(1);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const buffer = Buffer.from(await downloadResponse.arrayBuffer());
|
|
89
|
+
const outputPath = options.output || path.join(process.cwd(), file.name);
|
|
90
|
+
|
|
91
|
+
fs.writeFileSync(outputPath, buffer);
|
|
92
|
+
|
|
93
|
+
console.log(chalk.green(`✓ Downloaded to: ${outputPath}`));
|
|
94
|
+
console.log(chalk.gray(` Size: ${formatSize(buffer.length)}`));
|
|
95
|
+
} catch (error) {
|
|
96
|
+
console.error(chalk.red(`Download failed: ${error instanceof Error ? error.message : 'Unknown error'}`));
|
|
97
|
+
process.exit(1);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function formatSize(bytes: number): string {
|
|
102
|
+
if (bytes < 1024) return `${bytes} B`;
|
|
103
|
+
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
|
|
104
|
+
return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
|
|
105
|
+
}
|
package/src/commands/export.ts
CHANGED
|
@@ -2,6 +2,7 @@ import chalk from 'chalk';
|
|
|
2
2
|
import * as fs from 'fs';
|
|
3
3
|
import { getAllMemories } from '../lib/api.js';
|
|
4
4
|
import { isConfigured } from '../lib/config.js';
|
|
5
|
+
import { autoSync } from '../lib/autosync.js';
|
|
5
6
|
|
|
6
7
|
interface ExportOptions {
|
|
7
8
|
output?: string;
|
|
@@ -14,6 +15,9 @@ export async function exportCommand(options: ExportOptions): Promise<void> {
|
|
|
14
15
|
process.exit(1);
|
|
15
16
|
}
|
|
16
17
|
|
|
18
|
+
// Auto-sync in background (silent)
|
|
19
|
+
autoSync();
|
|
20
|
+
|
|
17
21
|
try {
|
|
18
22
|
console.log(chalk.dim('Fetching all memories...'));
|
|
19
23
|
const memories = await getAllMemories();
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import { getApiKey, getApiUrl } from '../lib/config.js';
|
|
3
|
+
import { autoSync } from '../lib/autosync.js';
|
|
4
|
+
|
|
5
|
+
interface FileMemory {
|
|
6
|
+
id: string;
|
|
7
|
+
content: string;
|
|
8
|
+
file_url: string;
|
|
9
|
+
file_name: string;
|
|
10
|
+
file_type: string;
|
|
11
|
+
file_size: number;
|
|
12
|
+
created_at: string;
|
|
13
|
+
metadata: Record<string, unknown>;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
interface FilesResponse {
|
|
17
|
+
files: FileMemory[];
|
|
18
|
+
total: number;
|
|
19
|
+
limit: number;
|
|
20
|
+
offset: number;
|
|
21
|
+
error?: string;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export async function filesCommand(options: {
|
|
25
|
+
limit?: string;
|
|
26
|
+
type?: string;
|
|
27
|
+
json?: boolean;
|
|
28
|
+
}): Promise<void> {
|
|
29
|
+
const apiKey = getApiKey();
|
|
30
|
+
if (!apiKey) {
|
|
31
|
+
console.error(chalk.red('Not configured. Run: agentmemory init'));
|
|
32
|
+
process.exit(1);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Auto-sync in background (silent)
|
|
36
|
+
autoSync();
|
|
37
|
+
|
|
38
|
+
try {
|
|
39
|
+
const apiUrl = getApiUrl();
|
|
40
|
+
const params = new URLSearchParams();
|
|
41
|
+
if (options.limit) params.set('limit', options.limit);
|
|
42
|
+
if (options.type) params.set('type', options.type);
|
|
43
|
+
|
|
44
|
+
const response = await fetch(`${apiUrl}/files?${params}`, {
|
|
45
|
+
headers: {
|
|
46
|
+
'Authorization': `Bearer ${apiKey}`,
|
|
47
|
+
},
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
const data = await response.json() as FilesResponse;
|
|
51
|
+
|
|
52
|
+
if (!response.ok) {
|
|
53
|
+
console.error(chalk.red(`Error: ${data.error || 'Failed to list files'}`));
|
|
54
|
+
process.exit(1);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (options.json) {
|
|
58
|
+
console.log(JSON.stringify(data, null, 2));
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
if (!data.files || data.files.length === 0) {
|
|
63
|
+
console.log(chalk.yellow('No files found.'));
|
|
64
|
+
console.log(chalk.gray('Upload a file with: agentmemory upload <file>'));
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
console.log(chalk.bold(`\nFiles (${data.total} total):\n`));
|
|
69
|
+
|
|
70
|
+
for (const file of data.files) {
|
|
71
|
+
const category = getFileCategory(file.file_type);
|
|
72
|
+
const icon = getCategoryIcon(category);
|
|
73
|
+
const size = formatSize(file.file_size);
|
|
74
|
+
const date = new Date(file.created_at).toLocaleDateString();
|
|
75
|
+
|
|
76
|
+
console.log(`${icon} ${chalk.cyan(file.file_name)}`);
|
|
77
|
+
console.log(chalk.gray(` ID: ${file.id}`));
|
|
78
|
+
console.log(chalk.gray(` Type: ${file.file_type} | Size: ${size} | Date: ${date}`));
|
|
79
|
+
if (file.content && file.content !== `File: ${file.file_name}`) {
|
|
80
|
+
console.log(chalk.gray(` Description: ${file.content.slice(0, 60)}...`));
|
|
81
|
+
}
|
|
82
|
+
console.log();
|
|
83
|
+
}
|
|
84
|
+
} catch (error) {
|
|
85
|
+
console.error(chalk.red(`Failed to list files: ${error instanceof Error ? error.message : 'Unknown error'}`));
|
|
86
|
+
process.exit(1);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function formatSize(bytes: number): string {
|
|
91
|
+
if (bytes < 1024) return `${bytes} B`;
|
|
92
|
+
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
|
|
93
|
+
return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function getFileCategory(mimeType: string): string {
|
|
97
|
+
if (mimeType.startsWith('image/')) return 'image';
|
|
98
|
+
if (mimeType.startsWith('audio/')) return 'audio';
|
|
99
|
+
if (mimeType.startsWith('video/')) return 'video';
|
|
100
|
+
if (mimeType === 'application/pdf') return 'pdf';
|
|
101
|
+
if (mimeType.includes('word') || mimeType.includes('document')) return 'document';
|
|
102
|
+
if (mimeType.includes('excel') || mimeType.includes('spreadsheet')) return 'spreadsheet';
|
|
103
|
+
if (mimeType.startsWith('text/')) return 'text';
|
|
104
|
+
return 'other';
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function getCategoryIcon(category: string): string {
|
|
108
|
+
const icons: Record<string, string> = {
|
|
109
|
+
image: '🖼️',
|
|
110
|
+
audio: '🎵',
|
|
111
|
+
video: '🎬',
|
|
112
|
+
pdf: '📄',
|
|
113
|
+
document: '📝',
|
|
114
|
+
spreadsheet: '📊',
|
|
115
|
+
text: '📃',
|
|
116
|
+
other: '📁',
|
|
117
|
+
};
|
|
118
|
+
return icons[category] || '📁';
|
|
119
|
+
}
|