agent-media-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/LICENSE +199 -0
- package/README.md +59 -0
- package/dist/commands/alias.d.ts +3 -0
- package/dist/commands/alias.d.ts.map +1 -0
- package/dist/commands/alias.js +245 -0
- package/dist/commands/alias.js.map +1 -0
- package/dist/commands/apikey.d.ts +3 -0
- package/dist/commands/apikey.d.ts.map +1 -0
- package/dist/commands/apikey.js +282 -0
- package/dist/commands/apikey.js.map +1 -0
- package/dist/commands/cancel.d.ts +9 -0
- package/dist/commands/cancel.d.ts.map +1 -0
- package/dist/commands/cancel.js +101 -0
- package/dist/commands/cancel.js.map +1 -0
- package/dist/commands/completions.d.ts +15 -0
- package/dist/commands/completions.d.ts.map +1 -0
- package/dist/commands/completions.js +293 -0
- package/dist/commands/completions.js.map +1 -0
- package/dist/commands/config.d.ts +3 -0
- package/dist/commands/config.d.ts.map +1 -0
- package/dist/commands/config.js +327 -0
- package/dist/commands/config.js.map +1 -0
- package/dist/commands/credits.d.ts +18 -0
- package/dist/commands/credits.d.ts.map +1 -0
- package/dist/commands/credits.js +459 -0
- package/dist/commands/credits.js.map +1 -0
- package/dist/commands/debug.d.ts +20 -0
- package/dist/commands/debug.d.ts.map +1 -0
- package/dist/commands/debug.js +291 -0
- package/dist/commands/debug.js.map +1 -0
- package/dist/commands/delete.d.ts +3 -0
- package/dist/commands/delete.d.ts.map +1 -0
- package/dist/commands/delete.js +273 -0
- package/dist/commands/delete.js.map +1 -0
- package/dist/commands/doctor.d.ts +14 -0
- package/dist/commands/doctor.d.ts.map +1 -0
- package/dist/commands/doctor.js +468 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/download.d.ts +3 -0
- package/dist/commands/download.d.ts.map +1 -0
- package/dist/commands/download.js +165 -0
- package/dist/commands/download.js.map +1 -0
- package/dist/commands/generate.d.ts +3 -0
- package/dist/commands/generate.d.ts.map +1 -0
- package/dist/commands/generate.js +358 -0
- package/dist/commands/generate.js.map +1 -0
- package/dist/commands/inspect.d.ts +10 -0
- package/dist/commands/inspect.d.ts.map +1 -0
- package/dist/commands/inspect.js +376 -0
- package/dist/commands/inspect.js.map +1 -0
- package/dist/commands/list.d.ts +13 -0
- package/dist/commands/list.d.ts.map +1 -0
- package/dist/commands/list.js +198 -0
- package/dist/commands/list.js.map +1 -0
- package/dist/commands/login.d.ts +15 -0
- package/dist/commands/login.d.ts.map +1 -0
- package/dist/commands/login.js +123 -0
- package/dist/commands/login.js.map +1 -0
- package/dist/commands/logout.d.ts +12 -0
- package/dist/commands/logout.d.ts.map +1 -0
- package/dist/commands/logout.js +85 -0
- package/dist/commands/logout.js.map +1 -0
- package/dist/commands/models.d.ts +10 -0
- package/dist/commands/models.d.ts.map +1 -0
- package/dist/commands/models.js +137 -0
- package/dist/commands/models.js.map +1 -0
- package/dist/commands/plan.d.ts +13 -0
- package/dist/commands/plan.d.ts.map +1 -0
- package/dist/commands/plan.js +134 -0
- package/dist/commands/plan.js.map +1 -0
- package/dist/commands/pricing.d.ts +14 -0
- package/dist/commands/pricing.d.ts.map +1 -0
- package/dist/commands/pricing.js +166 -0
- package/dist/commands/pricing.js.map +1 -0
- package/dist/commands/profile.d.ts +9 -0
- package/dist/commands/profile.d.ts.map +1 -0
- package/dist/commands/profile.js +236 -0
- package/dist/commands/profile.js.map +1 -0
- package/dist/commands/retry.d.ts +3 -0
- package/dist/commands/retry.d.ts.map +1 -0
- package/dist/commands/retry.js +424 -0
- package/dist/commands/retry.js.map +1 -0
- package/dist/commands/status.d.ts +9 -0
- package/dist/commands/status.d.ts.map +1 -0
- package/dist/commands/status.js +182 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/commands/subscribe.d.ts +3 -0
- package/dist/commands/subscribe.d.ts.map +1 -0
- package/dist/commands/subscribe.js +263 -0
- package/dist/commands/subscribe.js.map +1 -0
- package/dist/commands/text.d.ts +3 -0
- package/dist/commands/text.d.ts.map +1 -0
- package/dist/commands/text.js +263 -0
- package/dist/commands/text.js.map +1 -0
- package/dist/commands/update.d.ts +13 -0
- package/dist/commands/update.d.ts.map +1 -0
- package/dist/commands/update.js +211 -0
- package/dist/commands/update.js.map +1 -0
- package/dist/commands/usage.d.ts +13 -0
- package/dist/commands/usage.d.ts.map +1 -0
- package/dist/commands/usage.js +344 -0
- package/dist/commands/usage.js.map +1 -0
- package/dist/commands/version.d.ts +8 -0
- package/dist/commands/version.d.ts.map +1 -0
- package/dist/commands/version.js +26 -0
- package/dist/commands/version.js.map +1 -0
- package/dist/commands/whoami.d.ts +9 -0
- package/dist/commands/whoami.d.ts.map +1 -0
- package/dist/commands/whoami.js +76 -0
- package/dist/commands/whoami.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +85 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/api.d.ts +518 -0
- package/dist/lib/api.d.ts.map +1 -0
- package/dist/lib/api.js +582 -0
- package/dist/lib/api.js.map +1 -0
- package/dist/lib/config.d.ts +33 -0
- package/dist/lib/config.d.ts.map +1 -0
- package/dist/lib/config.js +91 -0
- package/dist/lib/config.js.map +1 -0
- package/dist/lib/credentials.d.ts +60 -0
- package/dist/lib/credentials.d.ts.map +1 -0
- package/dist/lib/credentials.js +152 -0
- package/dist/lib/credentials.js.map +1 -0
- package/dist/lib/errors.d.ts +20 -0
- package/dist/lib/errors.d.ts.map +1 -0
- package/dist/lib/errors.js +77 -0
- package/dist/lib/errors.js.map +1 -0
- package/dist/lib/output.d.ts +33 -0
- package/dist/lib/output.d.ts.map +1 -0
- package/dist/lib/output.js +77 -0
- package/dist/lib/output.js.map +1 -0
- package/dist/types.d.ts +12 -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 +48 -0
|
@@ -0,0 +1,468 @@
|
|
|
1
|
+
// Copyright 2026 agent-media contributors. Apache-2.0 license.
|
|
2
|
+
import { createRequire } from 'node:module';
|
|
3
|
+
import { existsSync, statfsSync } from 'node:fs';
|
|
4
|
+
import { resolve } from 'node:path';
|
|
5
|
+
import { homedir } from 'node:os';
|
|
6
|
+
import chalk from 'chalk';
|
|
7
|
+
import { detectOutputMode, printJson } from '../lib/output.js';
|
|
8
|
+
import { loadCredentials, getApiKey, resolveProfileName } from '../lib/credentials.js';
|
|
9
|
+
import { loadConfig, CONFIG_FILE, saveConfig } from '../lib/config.js';
|
|
10
|
+
import { AgentMediaAPI } from '../lib/api.js';
|
|
11
|
+
import { handleError } from '../lib/errors.js';
|
|
12
|
+
const require = createRequire(import.meta.url);
|
|
13
|
+
const pkg = require('../../package.json');
|
|
14
|
+
/** Default API URL used for connectivity checks. */
|
|
15
|
+
const DEFAULT_API_URL = 'https://ppwvarkmpffljlqxkjux.supabase.co';
|
|
16
|
+
/** Minimum required Node.js major version. */
|
|
17
|
+
const MIN_NODE_MAJOR = 18;
|
|
18
|
+
const MIN_NODE_VERSION = '18.0.0';
|
|
19
|
+
/** Minimum free disk space in bytes (100 MB). */
|
|
20
|
+
const MIN_DISK_BYTES = 100 * 1024 * 1024;
|
|
21
|
+
/**
|
|
22
|
+
* Resolve the API base URL from env or default.
|
|
23
|
+
*/
|
|
24
|
+
function getApiBaseUrl() {
|
|
25
|
+
return process.env['AGENT_MEDIA_API_URL']?.replace(/\/+$/, '') ?? DEFAULT_API_URL;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Extract the hostname from a URL string.
|
|
29
|
+
*/
|
|
30
|
+
function getApiHost(url) {
|
|
31
|
+
try {
|
|
32
|
+
return new URL(url).hostname;
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
return url;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Check 1: Credentials file exists and has a valid profile.
|
|
40
|
+
*/
|
|
41
|
+
function checkCredentials(profileName) {
|
|
42
|
+
const name = 'credentials';
|
|
43
|
+
const label = 'Credentials';
|
|
44
|
+
try {
|
|
45
|
+
const store = loadCredentials();
|
|
46
|
+
const profile = store.profiles[profileName];
|
|
47
|
+
if (!profile) {
|
|
48
|
+
return {
|
|
49
|
+
name,
|
|
50
|
+
label,
|
|
51
|
+
passed: false,
|
|
52
|
+
message: `No profile "${profileName}" found`,
|
|
53
|
+
fix: 'Run `agent-media login` to authenticate.',
|
|
54
|
+
fixable: false,
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
if (!profile.apiKey) {
|
|
58
|
+
return {
|
|
59
|
+
name,
|
|
60
|
+
label,
|
|
61
|
+
passed: false,
|
|
62
|
+
message: `Profile "${profileName}" has no API key`,
|
|
63
|
+
fix: 'Run `agent-media login` to re-authenticate.',
|
|
64
|
+
fixable: false,
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
const email = profile.email || 'unknown';
|
|
68
|
+
return {
|
|
69
|
+
name,
|
|
70
|
+
label,
|
|
71
|
+
passed: true,
|
|
72
|
+
message: `Valid profile "${profileName}" (${email})`,
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
catch {
|
|
76
|
+
return {
|
|
77
|
+
name,
|
|
78
|
+
label,
|
|
79
|
+
passed: false,
|
|
80
|
+
message: 'Failed to read credentials file',
|
|
81
|
+
fix: 'Run `agent-media login` to create credentials.',
|
|
82
|
+
fixable: false,
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Check 2: API endpoint is reachable (GET /rest/v1/ with 5s timeout).
|
|
88
|
+
*/
|
|
89
|
+
async function checkApiReachable() {
|
|
90
|
+
const name = 'api_reachable';
|
|
91
|
+
const label = 'API Reachable';
|
|
92
|
+
const baseUrl = getApiBaseUrl();
|
|
93
|
+
const host = getApiHost(baseUrl);
|
|
94
|
+
try {
|
|
95
|
+
const start = Date.now();
|
|
96
|
+
const controller = new AbortController();
|
|
97
|
+
const timeout = setTimeout(() => controller.abort(), 5000);
|
|
98
|
+
await fetch(`${baseUrl}/rest/v1/`, {
|
|
99
|
+
method: 'GET',
|
|
100
|
+
signal: controller.signal,
|
|
101
|
+
headers: { 'Content-Type': 'application/json' },
|
|
102
|
+
});
|
|
103
|
+
clearTimeout(timeout);
|
|
104
|
+
const elapsed = Date.now() - start;
|
|
105
|
+
// Any HTTP response (even 4xx) means the server is reachable
|
|
106
|
+
return {
|
|
107
|
+
name,
|
|
108
|
+
label,
|
|
109
|
+
passed: true,
|
|
110
|
+
message: `Connected to ${host} (${elapsed}ms)`,
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
catch (error) {
|
|
114
|
+
const msg = error instanceof Error && error.name === 'AbortError'
|
|
115
|
+
? `Connection to ${host} timed out (>5s)`
|
|
116
|
+
: `Cannot reach ${host}`;
|
|
117
|
+
return {
|
|
118
|
+
name,
|
|
119
|
+
label,
|
|
120
|
+
passed: false,
|
|
121
|
+
message: msg,
|
|
122
|
+
fix: 'Check your internet connection or verify the API URL with `agent-media config get api_url`.',
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Check 3: API key is valid (call whoami).
|
|
128
|
+
*/
|
|
129
|
+
async function checkAuthValid(profileName) {
|
|
130
|
+
const name = 'auth_valid';
|
|
131
|
+
const label = 'Auth Valid';
|
|
132
|
+
const apiKey = getApiKey(profileName);
|
|
133
|
+
if (!apiKey) {
|
|
134
|
+
return {
|
|
135
|
+
name,
|
|
136
|
+
label,
|
|
137
|
+
passed: false,
|
|
138
|
+
message: 'No API key available',
|
|
139
|
+
fix: 'Run `agent-media login` to authenticate.',
|
|
140
|
+
fixable: false,
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
try {
|
|
144
|
+
const api = new AgentMediaAPI(apiKey);
|
|
145
|
+
const data = await api.whoami();
|
|
146
|
+
const email = data.user_id || 'unknown';
|
|
147
|
+
return {
|
|
148
|
+
name,
|
|
149
|
+
label,
|
|
150
|
+
passed: true,
|
|
151
|
+
message: `Authenticated as ${email}`,
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
catch {
|
|
155
|
+
return {
|
|
156
|
+
name,
|
|
157
|
+
label,
|
|
158
|
+
passed: false,
|
|
159
|
+
message: 'API key is invalid or expired',
|
|
160
|
+
fix: 'Run `agent-media login` to re-authenticate.',
|
|
161
|
+
fixable: false,
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Check 4: Config file exists and has valid JSON.
|
|
167
|
+
*/
|
|
168
|
+
function checkConfigValid() {
|
|
169
|
+
const name = 'config_valid';
|
|
170
|
+
const label = 'Config';
|
|
171
|
+
if (!existsSync(CONFIG_FILE)) {
|
|
172
|
+
return {
|
|
173
|
+
name,
|
|
174
|
+
label,
|
|
175
|
+
passed: false,
|
|
176
|
+
message: `No configuration file at ${CONFIG_FILE}`,
|
|
177
|
+
fix: 'Run `agent-media config set output_format human` to create a default config.',
|
|
178
|
+
fixable: true,
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
try {
|
|
182
|
+
const config = loadConfig();
|
|
183
|
+
// loadConfig returns {} on parse errors, but if the file exists
|
|
184
|
+
// and parses to a non-null object, we consider it valid.
|
|
185
|
+
if (typeof config !== 'object' || config === null) {
|
|
186
|
+
return {
|
|
187
|
+
name,
|
|
188
|
+
label,
|
|
189
|
+
passed: false,
|
|
190
|
+
message: 'Config file has invalid structure',
|
|
191
|
+
fix: 'Run `agent-media config reset` to restore defaults.',
|
|
192
|
+
fixable: true,
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
return {
|
|
196
|
+
name,
|
|
197
|
+
label,
|
|
198
|
+
passed: true,
|
|
199
|
+
message: `Valid configuration at ${CONFIG_FILE}`,
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
catch {
|
|
203
|
+
return {
|
|
204
|
+
name,
|
|
205
|
+
label,
|
|
206
|
+
passed: false,
|
|
207
|
+
message: 'Config file contains invalid JSON',
|
|
208
|
+
fix: 'Run `agent-media config reset` to restore defaults.',
|
|
209
|
+
fixable: true,
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Check 5: Node.js version >= 18.0.0.
|
|
215
|
+
*/
|
|
216
|
+
function checkNodeVersion() {
|
|
217
|
+
const name = 'node_version';
|
|
218
|
+
const label = 'Node.js';
|
|
219
|
+
const version = process.version; // e.g. "v20.11.0"
|
|
220
|
+
const major = parseInt(version.slice(1).split('.')[0], 10);
|
|
221
|
+
if (major < MIN_NODE_MAJOR) {
|
|
222
|
+
return {
|
|
223
|
+
name,
|
|
224
|
+
label,
|
|
225
|
+
passed: false,
|
|
226
|
+
message: `${version} (>= ${MIN_NODE_VERSION} required)`,
|
|
227
|
+
fix: `Upgrade Node.js to v${MIN_NODE_MAJOR} or later. Visit https://nodejs.org/ or use nvm: nvm install ${MIN_NODE_MAJOR}`,
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
return {
|
|
231
|
+
name,
|
|
232
|
+
label,
|
|
233
|
+
passed: true,
|
|
234
|
+
message: `${version} (>= ${MIN_NODE_VERSION} required)`,
|
|
235
|
+
};
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* Check 6: Disk space in download directory (at least 100MB free).
|
|
239
|
+
*/
|
|
240
|
+
function checkDiskSpace() {
|
|
241
|
+
const name = 'disk_space';
|
|
242
|
+
const label = 'Disk Space';
|
|
243
|
+
const config = loadConfig();
|
|
244
|
+
const downloadDir = config['download_dir'] ?? resolve(homedir(), 'Downloads');
|
|
245
|
+
const displayDir = downloadDir.replace(homedir(), '~');
|
|
246
|
+
// Resolve to an existing ancestor directory for statfs
|
|
247
|
+
let checkDir = resolve(downloadDir);
|
|
248
|
+
while (!existsSync(checkDir)) {
|
|
249
|
+
const parent = resolve(checkDir, '..');
|
|
250
|
+
if (parent === checkDir)
|
|
251
|
+
break; // filesystem root
|
|
252
|
+
checkDir = parent;
|
|
253
|
+
}
|
|
254
|
+
try {
|
|
255
|
+
const stats = statfsSync(checkDir);
|
|
256
|
+
const freeBytes = stats.bavail * stats.bsize;
|
|
257
|
+
const freeMB = (freeBytes / (1024 * 1024)).toFixed(0);
|
|
258
|
+
const freeGB = (freeBytes / (1024 * 1024 * 1024)).toFixed(1);
|
|
259
|
+
const freeLabel = freeBytes >= 1024 * 1024 * 1024 ? `${freeGB} GB` : `${freeMB} MB`;
|
|
260
|
+
if (freeBytes < MIN_DISK_BYTES) {
|
|
261
|
+
return {
|
|
262
|
+
name,
|
|
263
|
+
label,
|
|
264
|
+
passed: false,
|
|
265
|
+
message: `Only ${freeLabel} available in ${displayDir} (100 MB minimum)`,
|
|
266
|
+
fix: 'Free up disk space or change download_dir with `agent-media config set download_dir /path/to/dir`.',
|
|
267
|
+
};
|
|
268
|
+
}
|
|
269
|
+
return {
|
|
270
|
+
name,
|
|
271
|
+
label,
|
|
272
|
+
passed: true,
|
|
273
|
+
message: `${freeLabel} available in ${displayDir}`,
|
|
274
|
+
};
|
|
275
|
+
}
|
|
276
|
+
catch {
|
|
277
|
+
return {
|
|
278
|
+
name,
|
|
279
|
+
label,
|
|
280
|
+
passed: false,
|
|
281
|
+
message: `Cannot check disk space for ${displayDir}`,
|
|
282
|
+
fix: 'Verify the download directory exists and is accessible.',
|
|
283
|
+
};
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
/**
|
|
287
|
+
* Check 7: DNS resolution for the API host.
|
|
288
|
+
*/
|
|
289
|
+
async function checkNetwork() {
|
|
290
|
+
const name = 'network';
|
|
291
|
+
const label = 'Network';
|
|
292
|
+
const baseUrl = getApiBaseUrl();
|
|
293
|
+
const host = getApiHost(baseUrl);
|
|
294
|
+
try {
|
|
295
|
+
const dns = await import('node:dns');
|
|
296
|
+
const { resolve4 } = dns.promises;
|
|
297
|
+
const addresses = await resolve4(host);
|
|
298
|
+
if (addresses.length === 0) {
|
|
299
|
+
return {
|
|
300
|
+
name,
|
|
301
|
+
label,
|
|
302
|
+
passed: false,
|
|
303
|
+
message: `DNS resolution returned no results for ${host}`,
|
|
304
|
+
fix: 'Verify DNS settings or try a different network.',
|
|
305
|
+
};
|
|
306
|
+
}
|
|
307
|
+
return {
|
|
308
|
+
name,
|
|
309
|
+
label,
|
|
310
|
+
passed: true,
|
|
311
|
+
message: `DNS resolved ${host} (${addresses[0]})`,
|
|
312
|
+
};
|
|
313
|
+
}
|
|
314
|
+
catch {
|
|
315
|
+
return {
|
|
316
|
+
name,
|
|
317
|
+
label,
|
|
318
|
+
passed: false,
|
|
319
|
+
message: `DNS resolution failed for ${host}`,
|
|
320
|
+
fix: 'Verify DNS settings or try a different network.',
|
|
321
|
+
};
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
/**
|
|
325
|
+
* Check 8: CLI version matches latest (package.json).
|
|
326
|
+
*/
|
|
327
|
+
function checkCliVersion() {
|
|
328
|
+
const name = 'cli_version';
|
|
329
|
+
const label = 'CLI Version';
|
|
330
|
+
// In a real scenario we would check a remote registry. For now
|
|
331
|
+
// we report the current version as latest since there is no
|
|
332
|
+
// published registry to query yet.
|
|
333
|
+
return {
|
|
334
|
+
name,
|
|
335
|
+
label,
|
|
336
|
+
passed: true,
|
|
337
|
+
message: `v${pkg.version} (latest)`,
|
|
338
|
+
};
|
|
339
|
+
}
|
|
340
|
+
/**
|
|
341
|
+
* Attempt to auto-fix issues that are marked as fixable.
|
|
342
|
+
*/
|
|
343
|
+
function attemptFix(result) {
|
|
344
|
+
switch (result.name) {
|
|
345
|
+
case 'config_valid': {
|
|
346
|
+
if (!existsSync(CONFIG_FILE)) {
|
|
347
|
+
// Create a default config file
|
|
348
|
+
try {
|
|
349
|
+
saveConfig({});
|
|
350
|
+
return `Created default config at ${CONFIG_FILE}`;
|
|
351
|
+
}
|
|
352
|
+
catch {
|
|
353
|
+
return null;
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
// Invalid config -- reset to defaults
|
|
357
|
+
try {
|
|
358
|
+
saveConfig({});
|
|
359
|
+
return `Reset config to defaults at ${CONFIG_FILE}`;
|
|
360
|
+
}
|
|
361
|
+
catch {
|
|
362
|
+
return null;
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
case 'credentials': {
|
|
366
|
+
// Cannot auto-fix -- requires interactive login
|
|
367
|
+
return 'Run `agent-media login` to set up credentials.';
|
|
368
|
+
}
|
|
369
|
+
case 'node_version': {
|
|
370
|
+
return `Upgrade Node.js: visit https://nodejs.org/ or run: nvm install ${MIN_NODE_MAJOR}`;
|
|
371
|
+
}
|
|
372
|
+
default:
|
|
373
|
+
return null;
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
export function registerDoctorCommand(program) {
|
|
377
|
+
program
|
|
378
|
+
.command('doctor')
|
|
379
|
+
.description('Run diagnostic checks on your agent-media setup')
|
|
380
|
+
.option('--fix', 'Attempt to auto-fix known issues')
|
|
381
|
+
.action(async (cmdOpts) => {
|
|
382
|
+
const globalOpts = program.opts();
|
|
383
|
+
const mode = detectOutputMode(globalOpts);
|
|
384
|
+
const profileName = resolveProfileName(globalOpts.profile);
|
|
385
|
+
const shouldFix = cmdOpts.fix ?? false;
|
|
386
|
+
try {
|
|
387
|
+
// Run all checks (sync first, then async)
|
|
388
|
+
const results = [];
|
|
389
|
+
results.push(checkCredentials(profileName));
|
|
390
|
+
results.push(await checkApiReachable());
|
|
391
|
+
results.push(await checkAuthValid(profileName));
|
|
392
|
+
results.push(checkConfigValid());
|
|
393
|
+
results.push(checkNodeVersion());
|
|
394
|
+
results.push(checkDiskSpace());
|
|
395
|
+
results.push(await checkNetwork());
|
|
396
|
+
results.push(checkCliVersion());
|
|
397
|
+
const passed = results.filter((r) => r.passed).length;
|
|
398
|
+
const total = results.length;
|
|
399
|
+
const failed = results.filter((r) => !r.passed);
|
|
400
|
+
// Handle --fix
|
|
401
|
+
const fixes = [];
|
|
402
|
+
if (shouldFix && failed.length > 0) {
|
|
403
|
+
for (const result of failed) {
|
|
404
|
+
const fixResult = attemptFix(result);
|
|
405
|
+
if (fixResult) {
|
|
406
|
+
fixes.push({ name: result.name, result: fixResult });
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
switch (mode) {
|
|
411
|
+
case 'json': {
|
|
412
|
+
const jsonOutput = {
|
|
413
|
+
passed,
|
|
414
|
+
total,
|
|
415
|
+
checks: results.map((r) => ({
|
|
416
|
+
name: r.name,
|
|
417
|
+
passed: r.passed,
|
|
418
|
+
message: r.message,
|
|
419
|
+
...(r.fix ? { fix: r.fix } : {}),
|
|
420
|
+
})),
|
|
421
|
+
...(fixes.length > 0 ? { fixes } : {}),
|
|
422
|
+
};
|
|
423
|
+
printJson(jsonOutput);
|
|
424
|
+
break;
|
|
425
|
+
}
|
|
426
|
+
default: {
|
|
427
|
+
console.log();
|
|
428
|
+
console.log(chalk.bold('agent-media doctor'));
|
|
429
|
+
console.log();
|
|
430
|
+
// Calculate label padding for alignment
|
|
431
|
+
const maxLabelLen = Math.max(...results.map((r) => r.label.length));
|
|
432
|
+
for (const result of results) {
|
|
433
|
+
const icon = result.passed
|
|
434
|
+
? chalk.green('\u2713')
|
|
435
|
+
: chalk.red('\u2717');
|
|
436
|
+
const paddedLabel = result.label.padEnd(maxLabelLen);
|
|
437
|
+
console.log(` ${icon} ${chalk.bold(paddedLabel)} ${result.message}`);
|
|
438
|
+
}
|
|
439
|
+
console.log();
|
|
440
|
+
console.log(` ${passed}/${total} checks passed`);
|
|
441
|
+
if (failed.length > 0) {
|
|
442
|
+
console.log();
|
|
443
|
+
console.log(chalk.bold(' Issues found:'));
|
|
444
|
+
for (const result of failed) {
|
|
445
|
+
console.log(` ${chalk.red('\u2717')} ${result.label}: ${result.message}`);
|
|
446
|
+
if (result.fix) {
|
|
447
|
+
console.log(` ${chalk.yellow('Fix:')} ${result.fix}`);
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
if (fixes.length > 0) {
|
|
452
|
+
console.log();
|
|
453
|
+
console.log(chalk.bold(' Auto-fix results:'));
|
|
454
|
+
for (const fix of fixes) {
|
|
455
|
+
console.log(` ${chalk.green('\u2713')} ${fix.name}: ${fix.result}`);
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
console.log();
|
|
459
|
+
break;
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
catch (error) {
|
|
464
|
+
handleError(error);
|
|
465
|
+
}
|
|
466
|
+
});
|
|
467
|
+
}
|
|
468
|
+
//# sourceMappingURL=doctor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"download.d.ts","sourceRoot":"","sources":["../../src/commands/download.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAyDzC,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA8H9D"}
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
// Copyright 2026 agent-media contributors. Apache-2.0 license.
|
|
2
|
+
/**
|
|
3
|
+
* `agent-media download <job-id>` command.
|
|
4
|
+
*
|
|
5
|
+
* Downloads the output media file from a completed generation job.
|
|
6
|
+
* Flow:
|
|
7
|
+
* 1. Authenticate via API key from credentials store.
|
|
8
|
+
* 2. Fetch the job and verify it is completed.
|
|
9
|
+
* 3. Download the output media to a local file.
|
|
10
|
+
* 4. Display the saved path and file size.
|
|
11
|
+
*/
|
|
12
|
+
import { existsSync } from 'node:fs';
|
|
13
|
+
import { resolve, extname } from 'node:path';
|
|
14
|
+
import chalk from 'chalk';
|
|
15
|
+
import { detectOutputMode, printJson, printQuiet, createSpinner, } from '../lib/output.js';
|
|
16
|
+
import { getApiKey, resolveProfileName } from '../lib/credentials.js';
|
|
17
|
+
import { AgentMediaAPI } from '../lib/api.js';
|
|
18
|
+
import { CLIError, handleError } from '../lib/errors.js';
|
|
19
|
+
/** Map content-type to file extension. */
|
|
20
|
+
const EXTENSION_BY_CONTENT_TYPE = {
|
|
21
|
+
'video/mp4': '.mp4',
|
|
22
|
+
'video/webm': '.webm',
|
|
23
|
+
'video/quicktime': '.mov',
|
|
24
|
+
'image/png': '.png',
|
|
25
|
+
'image/jpeg': '.jpg',
|
|
26
|
+
'image/webp': '.webp',
|
|
27
|
+
'image/gif': '.gif',
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* Detect the file extension from a URL path or content-type header.
|
|
31
|
+
*/
|
|
32
|
+
function detectExtension(url, _contentType) {
|
|
33
|
+
// Try content-type first
|
|
34
|
+
if (_contentType) {
|
|
35
|
+
const baseType = _contentType.split(';')[0].trim().toLowerCase();
|
|
36
|
+
const ext = EXTENSION_BY_CONTENT_TYPE[baseType];
|
|
37
|
+
if (ext)
|
|
38
|
+
return ext;
|
|
39
|
+
}
|
|
40
|
+
// Fall back to URL extension
|
|
41
|
+
try {
|
|
42
|
+
const pathname = new URL(url).pathname;
|
|
43
|
+
const ext = extname(pathname).toLowerCase();
|
|
44
|
+
if (ext)
|
|
45
|
+
return ext;
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
// Invalid URL, fall through
|
|
49
|
+
}
|
|
50
|
+
// Default to mp4 for video content
|
|
51
|
+
return '.mp4';
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Format bytes to a human-readable string (e.g., "15.2 MB").
|
|
55
|
+
*/
|
|
56
|
+
function formatBytes(bytes) {
|
|
57
|
+
if (bytes < 1024)
|
|
58
|
+
return `${bytes} B`;
|
|
59
|
+
if (bytes < 1024 * 1024)
|
|
60
|
+
return `${(bytes / 1024).toFixed(1)} KB`;
|
|
61
|
+
if (bytes < 1024 * 1024 * 1024)
|
|
62
|
+
return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
|
|
63
|
+
return `${(bytes / (1024 * 1024 * 1024)).toFixed(1)} GB`;
|
|
64
|
+
}
|
|
65
|
+
export function registerDownloadCommand(program) {
|
|
66
|
+
program
|
|
67
|
+
.command('download <job-id>')
|
|
68
|
+
.description('Download the output media from a completed job')
|
|
69
|
+
.option('-o, --output <path>', 'Output file path')
|
|
70
|
+
.action(async (jobId, cmdOpts) => {
|
|
71
|
+
const globalOpts = program.opts();
|
|
72
|
+
const mode = detectOutputMode(globalOpts);
|
|
73
|
+
const profileName = resolveProfileName(globalOpts.profile);
|
|
74
|
+
const apiKey = getApiKey(profileName);
|
|
75
|
+
if (!apiKey) {
|
|
76
|
+
throw new CLIError('Not logged in.', {
|
|
77
|
+
code: 'NOT_AUTHENTICATED',
|
|
78
|
+
suggestion: "Run 'agent-media login' to authenticate.",
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
try {
|
|
82
|
+
const api = new AgentMediaAPI(apiKey);
|
|
83
|
+
// ── Step 1: Fetch the job ────────────────────────────────────
|
|
84
|
+
const fetchSpinner = createSpinner('Fetching job...');
|
|
85
|
+
if (mode === 'human')
|
|
86
|
+
fetchSpinner.start();
|
|
87
|
+
const job = await api.getJob(jobId);
|
|
88
|
+
if (mode === 'human')
|
|
89
|
+
fetchSpinner.stop();
|
|
90
|
+
// ── Step 2: Verify job is completed ──────────────────────────
|
|
91
|
+
if (job.status !== 'completed') {
|
|
92
|
+
if (mode === 'json') {
|
|
93
|
+
printJson({
|
|
94
|
+
error: 'Job is not completed',
|
|
95
|
+
status: job.status,
|
|
96
|
+
job_id: job.id,
|
|
97
|
+
});
|
|
98
|
+
process.exit(1);
|
|
99
|
+
}
|
|
100
|
+
if (mode === 'quiet') {
|
|
101
|
+
printQuiet(`error:${job.status}`);
|
|
102
|
+
process.exit(1);
|
|
103
|
+
}
|
|
104
|
+
console.log();
|
|
105
|
+
console.log(` ${chalk.yellow('Job is not yet completed.')} Current status: ${chalk.bold(job.status)}`);
|
|
106
|
+
console.log();
|
|
107
|
+
console.log(chalk.dim(` Run 'agent-media status ${jobId} --watch' to track progress.`));
|
|
108
|
+
console.log();
|
|
109
|
+
process.exit(1);
|
|
110
|
+
}
|
|
111
|
+
// ── Step 3: Verify output URL exists ─────────────────────────
|
|
112
|
+
if (!job.output_media_url) {
|
|
113
|
+
throw new CLIError('No media available for this job.', {
|
|
114
|
+
code: 'NO_MEDIA',
|
|
115
|
+
suggestion: 'The job completed but produced no output. This may be a server error.',
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
// ── Step 4: Determine output path ────────────────────────────
|
|
119
|
+
const ext = detectExtension(job.output_media_url);
|
|
120
|
+
const shortId = job.id.slice(0, 8);
|
|
121
|
+
const defaultFilename = `${job.model_slug}-${shortId}${ext}`;
|
|
122
|
+
const outputPath = resolve(cmdOpts.output ?? `./${defaultFilename}`);
|
|
123
|
+
// Warn if file already exists (human mode only)
|
|
124
|
+
if (existsSync(outputPath) && mode === 'human') {
|
|
125
|
+
console.log(chalk.yellow(` Warning: overwriting existing file ${outputPath}`));
|
|
126
|
+
}
|
|
127
|
+
// ── Step 5: Download with progress ───────────────────────────
|
|
128
|
+
const downloadSpinner = createSpinner('Downloading...');
|
|
129
|
+
if (mode === 'human')
|
|
130
|
+
downloadSpinner.start();
|
|
131
|
+
const totalBytes = await api.downloadMedia(job.output_media_url, outputPath, (received, total) => {
|
|
132
|
+
if (mode === 'human') {
|
|
133
|
+
const progress = total
|
|
134
|
+
? `${formatBytes(received)} / ${formatBytes(total)}`
|
|
135
|
+
: formatBytes(received);
|
|
136
|
+
downloadSpinner.text = `Downloading... ${progress}`;
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
if (mode === 'human') {
|
|
140
|
+
downloadSpinner.succeed(`Downloaded to ${outputPath} (${formatBytes(totalBytes)})`);
|
|
141
|
+
}
|
|
142
|
+
// ── Step 6: Display result ───────────────────────────────────
|
|
143
|
+
switch (mode) {
|
|
144
|
+
case 'json':
|
|
145
|
+
printJson({
|
|
146
|
+
job_id: job.id,
|
|
147
|
+
output_path: outputPath,
|
|
148
|
+
bytes: totalBytes,
|
|
149
|
+
size: formatBytes(totalBytes),
|
|
150
|
+
});
|
|
151
|
+
break;
|
|
152
|
+
case 'quiet':
|
|
153
|
+
printQuiet(outputPath);
|
|
154
|
+
break;
|
|
155
|
+
default:
|
|
156
|
+
console.log();
|
|
157
|
+
break;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
catch (error) {
|
|
161
|
+
handleError(error);
|
|
162
|
+
}
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
//# sourceMappingURL=download.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"download.js","sourceRoot":"","sources":["../../src/commands/download.ts"],"names":[],"mappings":"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"}
|