makaron-cli 0.11.0 → 0.11.2
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/.claude-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +1 -1
- package/README.md +4 -2
- package/bin/makaron.mjs +108 -45
- package/package.json +1 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "makaron-cli",
|
|
3
|
-
"version": "0.11.
|
|
3
|
+
"version": "0.11.2",
|
|
4
4
|
"description": "AI image editing, video generation, music creation, and marketplace skill workflows via CLI. Agents can self-register, install skills, create projects, and produce creative media.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Makaron AI",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "makaron-cli",
|
|
3
|
-
"version": "0.11.
|
|
3
|
+
"version": "0.11.2",
|
|
4
4
|
"description": "AI image editing, video generation, music creation, and marketplace skill workflows via CLI. Agents can self-register, install skills, create projects, and produce creative media.",
|
|
5
5
|
"displayName": "Makaron",
|
|
6
6
|
"shortDescription": "AI image/video/music creation from the terminal",
|
package/README.md
CHANGED
|
@@ -7,8 +7,10 @@ Makaron is a multimodal AI creative agent. You talk to it via `makaron chat`, an
|
|
|
7
7
|
## Setup
|
|
8
8
|
|
|
9
9
|
```bash
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
# Install makaron-cli globally and add the Makaron Agent Skill.
|
|
11
|
+
npx makaron-cli setup
|
|
12
|
+
|
|
13
|
+
npx makaron-cli --help
|
|
12
14
|
```
|
|
13
15
|
|
|
14
16
|
### Get your API key
|
package/bin/makaron.mjs
CHANGED
|
@@ -15,6 +15,7 @@ import fs from 'fs';
|
|
|
15
15
|
import path from 'path';
|
|
16
16
|
import { createInterface } from 'readline';
|
|
17
17
|
import { execFileSync } from 'child_process';
|
|
18
|
+
import { fileURLToPath } from 'url';
|
|
18
19
|
|
|
19
20
|
// ─── Config ──────────────────────────────────────────────────────────────────
|
|
20
21
|
|
|
@@ -267,12 +268,13 @@ function printChatHelp() {
|
|
|
267
268
|
console.log(`Makaron chat — create and edit with Makaron Agent
|
|
268
269
|
|
|
269
270
|
Usage:
|
|
270
|
-
makaron chat --project <id|auto> [options] "your message"
|
|
271
|
+
makaron chat --project <id|auto> [options] [--skill <id|label|name>] "your message"
|
|
271
272
|
|
|
272
273
|
Options:
|
|
273
274
|
--project <id|auto> Project to work in. Use "auto" to create one.
|
|
274
275
|
--image <file|url> Attach a reference image or screenshot. Repeatable.
|
|
275
276
|
--video <file|url> Attach a video to the project timeline. Repeatable.
|
|
277
|
+
--skill <id|label|name> Use an installed skill or auto-install a matched marketplace skill.
|
|
276
278
|
--model <name> Preferred image/model route.
|
|
277
279
|
--video-model <name> Preferred video model: seedance-fast, seedance, kling, or grok.
|
|
278
280
|
--video-resolution <res> Video resolution: auto, 480p, 720p, 1080p, or 4k.
|
|
@@ -291,6 +293,9 @@ What you can ask:
|
|
|
291
293
|
Video from image or timeline
|
|
292
294
|
makaron chat --project <id> "make this into a 5 second cinematic video"
|
|
293
295
|
|
|
296
|
+
Marketplace skill
|
|
297
|
+
makaron chat --project auto --image selfie.jpg --skill "Football Captain" "make this cinematic"
|
|
298
|
+
|
|
294
299
|
Fix one video moment from a screenshot
|
|
295
300
|
makaron chat --project <id> --image screenshot.png "@4 this frame should be Paris; only fix this moment"
|
|
296
301
|
|
|
@@ -1026,6 +1031,25 @@ async function uploadFileViaSignedUrl(baseUrl, headers, projectId, filePath, con
|
|
|
1026
1031
|
return publicUrl;
|
|
1027
1032
|
}
|
|
1028
1033
|
|
|
1034
|
+
async function uploadImageFilesViaSignedUrl(baseUrl, headers, projectId, imagePaths) {
|
|
1035
|
+
const urls = [];
|
|
1036
|
+
for (const imagePath of imagePaths) {
|
|
1037
|
+
const valid = validateImage(imagePath);
|
|
1038
|
+
if (!valid.ok) {
|
|
1039
|
+
process.stderr.write(`❌ Cannot upload: ${path.basename(imagePath)}\n ${valid.error}\n`);
|
|
1040
|
+
process.exit(1);
|
|
1041
|
+
}
|
|
1042
|
+
process.stderr.write(`📤 Uploading ${path.basename(imagePath)}...\n`);
|
|
1043
|
+
const url = await uploadFileViaSignedUrl(baseUrl, headers, projectId, imagePath, valid.mime);
|
|
1044
|
+
if (!url) {
|
|
1045
|
+
process.stderr.write(`❌ Failed to upload image: ${imagePath}\n`);
|
|
1046
|
+
process.exit(1);
|
|
1047
|
+
}
|
|
1048
|
+
urls.push(url);
|
|
1049
|
+
}
|
|
1050
|
+
return urls;
|
|
1051
|
+
}
|
|
1052
|
+
|
|
1029
1053
|
function imageToArg(imgPath) {
|
|
1030
1054
|
if (imgPath.startsWith('http://') || imgPath.startsWith('https://')) return imgPath;
|
|
1031
1055
|
return readImageAsDataUrl(imgPath);
|
|
@@ -1197,6 +1221,8 @@ function printRootHelp() {
|
|
|
1197
1221
|
console.log(`Makaron CLI — Talk to Makaron Agent from the terminal
|
|
1198
1222
|
|
|
1199
1223
|
Commands:
|
|
1224
|
+
setup Install makaron-cli globally and add the Agent Skill
|
|
1225
|
+
install-skill Install Makaron Agent Skill into your coding agent
|
|
1200
1226
|
register --json Get challenge for agent self-registration
|
|
1201
1227
|
register --verify --challenge-id <id> --answer <n> Verify and save API key
|
|
1202
1228
|
claim Get claim URL for human to link account
|
|
@@ -1208,6 +1234,7 @@ Commands:
|
|
|
1208
1234
|
create --title "name" Create empty project (text-to-image)
|
|
1209
1235
|
|
|
1210
1236
|
chat --project <id> "message" Chat (non-blocking, polls for result)
|
|
1237
|
+
chat --project <id> --skill <id> Use or auto-install a marketplace skill
|
|
1211
1238
|
chat --project <id> --video <file> Attach video to conversation
|
|
1212
1239
|
chat --project <id> -b "message" Background: submit and print runId
|
|
1213
1240
|
chat --project <id> --stream "msg" Legacy: stream SSE in real-time
|
|
@@ -1232,13 +1259,56 @@ Environment:
|
|
|
1232
1259
|
`);
|
|
1233
1260
|
}
|
|
1234
1261
|
|
|
1262
|
+
function installAgentSkill(values = []) {
|
|
1263
|
+
if (hasHelpFlag(values)) {
|
|
1264
|
+
console.log('Usage: makaron install-skill [--global] [--agent <agent>] [--yes]');
|
|
1265
|
+
return;
|
|
1266
|
+
}
|
|
1267
|
+
|
|
1268
|
+
const skillDir = fileURLToPath(new URL('../skills/makaron', import.meta.url));
|
|
1269
|
+
const skillFile = path.join(skillDir, 'SKILL.md');
|
|
1270
|
+
if (!fs.existsSync(skillFile)) {
|
|
1271
|
+
console.error(`Makaron Agent Skill not found at ${skillFile}`);
|
|
1272
|
+
process.exit(1);
|
|
1273
|
+
}
|
|
1274
|
+
|
|
1275
|
+
execFileSync('npx', [
|
|
1276
|
+
'-y',
|
|
1277
|
+
'skills',
|
|
1278
|
+
'add',
|
|
1279
|
+
skillDir,
|
|
1280
|
+
'--skill',
|
|
1281
|
+
'makaron',
|
|
1282
|
+
'--copy',
|
|
1283
|
+
...values,
|
|
1284
|
+
], { stdio: 'inherit' });
|
|
1285
|
+
}
|
|
1286
|
+
|
|
1287
|
+
function setupMakaron(values = []) {
|
|
1288
|
+
if (hasHelpFlag(values)) {
|
|
1289
|
+
console.log('Usage: makaron setup [--agent <agent>]');
|
|
1290
|
+
return;
|
|
1291
|
+
}
|
|
1292
|
+
|
|
1293
|
+
const version = getCliVersion();
|
|
1294
|
+
console.error(`Installing ${NPM_PACKAGE_NAME}@${version} globally...`);
|
|
1295
|
+
execFileSync('npm', ['install', '-g', `${NPM_PACKAGE_NAME}@${version}`], { stdio: 'inherit' });
|
|
1296
|
+
|
|
1297
|
+
const skillArgs = [...values];
|
|
1298
|
+
if (!skillArgs.includes('--global') && !skillArgs.includes('-g')) skillArgs.unshift('--global');
|
|
1299
|
+
if (!skillArgs.includes('--yes') && !skillArgs.includes('-y')) skillArgs.push('--yes');
|
|
1300
|
+
|
|
1301
|
+
console.error('Installing Makaron Agent Skill globally...');
|
|
1302
|
+
installAgentSkill(skillArgs);
|
|
1303
|
+
}
|
|
1304
|
+
|
|
1235
1305
|
function printHelp(topic, subtopic) {
|
|
1236
1306
|
if (topic === 'login') {
|
|
1237
1307
|
console.log('Usage: makaron login');
|
|
1238
1308
|
} else if (topic === 'create') {
|
|
1239
1309
|
console.log('Usage: makaron create --image <file> [--image <file2>] | --image-url <url> | --title "name"');
|
|
1240
1310
|
} else if (topic === 'chat') {
|
|
1241
|
-
|
|
1311
|
+
printChatHelp();
|
|
1242
1312
|
} else if (topic === 'responses' || topic === 'run') {
|
|
1243
1313
|
if (subtopic === 'get') console.log('Usage: makaron responses get <runId> [--wait] [--json] [--pick <field>]');
|
|
1244
1314
|
else if (subtopic === 'watch') console.log('Usage: makaron responses watch <runId> [--jsonl] [--interval <ms>]');
|
|
@@ -1259,6 +1329,10 @@ function printHelp(topic, subtopic) {
|
|
|
1259
1329
|
`);
|
|
1260
1330
|
} else if (topic === 'abort') {
|
|
1261
1331
|
console.log('Usage: makaron abort <runId>');
|
|
1332
|
+
} else if (topic === 'setup') {
|
|
1333
|
+
console.log('Usage: makaron setup [--agent <agent>]');
|
|
1334
|
+
} else if (topic === 'install-skill') {
|
|
1335
|
+
console.log('Usage: makaron install-skill [--global] [--agent <agent>] [--yes]');
|
|
1262
1336
|
} else if (topic === 'skills') {
|
|
1263
1337
|
if (subtopic === 'list') console.log('Usage: makaron skills list [--json]');
|
|
1264
1338
|
else if (subtopic === 'search') console.log('Usage: makaron skills search <query> [--json]');
|
|
@@ -1332,6 +1406,10 @@ if (!command || command === '--help' || command === '-h' || command === 'help')
|
|
|
1332
1406
|
printHelp(command, args[1]);
|
|
1333
1407
|
} else if (command === '--version' || command === '-v' || command === 'version') {
|
|
1334
1408
|
console.log(getCliVersion());
|
|
1409
|
+
} else if (command === 'setup') {
|
|
1410
|
+
setupMakaron(args.slice(1));
|
|
1411
|
+
} else if (command === 'install-skill') {
|
|
1412
|
+
installAgentSkill(args.slice(1));
|
|
1335
1413
|
} else if (command === 'login') {
|
|
1336
1414
|
await login();
|
|
1337
1415
|
} else if (command === 'create') {
|
|
@@ -1403,52 +1481,28 @@ if (!command || command === '--help' || command === '-h' || command === 'help')
|
|
|
1403
1481
|
|
|
1404
1482
|
// --project auto: create a new project (with images/videos if provided)
|
|
1405
1483
|
if (!projectId || projectId === 'auto') {
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
} else {
|
|
1419
|
-
// Create project with images (URLs and/or local files)
|
|
1420
|
-
const base64s = imageFileList.map(imgPath => {
|
|
1421
|
-
process.stderr.write(`📤 Uploading ${path.basename(imgPath)}...\n`);
|
|
1422
|
-
return readImageAsDataUrl(imgPath);
|
|
1423
|
-
});
|
|
1424
|
-
if (imageUrlList.length) process.stderr.write(`📤 Attaching ${imageUrlList.length} URL image(s)...\n`);
|
|
1425
|
-
const body = {};
|
|
1426
|
-
if (base64s.length) body.imageBase64s = base64s;
|
|
1427
|
-
if (imageUrlList.length) body.imageUrls = imageUrlList;
|
|
1428
|
-
const res = await fetch(`${baseUrl}/api/projects/create`, {
|
|
1429
|
-
method: 'POST',
|
|
1430
|
-
headers: { 'Content-Type': 'application/json', ...headers },
|
|
1431
|
-
body: JSON.stringify(body),
|
|
1432
|
-
});
|
|
1433
|
-
if (!res.ok) { process.stderr.write(`❌ Failed to create project: ${await res.text()}\n`); process.exit(1); }
|
|
1434
|
-
const data = await res.json();
|
|
1435
|
-
projectId = data.projectId;
|
|
1436
|
-
process.stderr.write(`📦 Project created: ${projectId} (${data.snapshots?.length || 0} images)\n`);
|
|
1437
|
-
}
|
|
1438
|
-
chatImages.length = 0;
|
|
1439
|
-
imageUrlList.length = 0;
|
|
1440
|
-
imageFileList.length = 0;
|
|
1484
|
+
// Create an empty project first, then attach media by URL. Local images use
|
|
1485
|
+
// signed upload URLs so the agent never depends on the caller's filesystem.
|
|
1486
|
+
process.stderr.write(`📦 Creating new project...\n`);
|
|
1487
|
+
const res = await fetch(`${baseUrl}/api/projects/create`, {
|
|
1488
|
+
method: 'POST',
|
|
1489
|
+
headers: { 'Content-Type': 'application/json', ...headers },
|
|
1490
|
+
body: JSON.stringify({ title: prompt.slice(0, 50) }),
|
|
1491
|
+
});
|
|
1492
|
+
if (!res.ok) { process.stderr.write(`❌ Failed to create project: ${await res.text()}\n`); process.exit(1); }
|
|
1493
|
+
const data = await res.json();
|
|
1494
|
+
projectId = data.projectId;
|
|
1495
|
+
process.stderr.write(`📦 Project created: ${projectId}\n`);
|
|
1441
1496
|
}
|
|
1442
1497
|
// Upload additional images to existing project
|
|
1443
1498
|
if (imageFileList.length > 0 || imageUrlList.length > 0) {
|
|
1444
|
-
const
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1499
|
+
const uploadedImageUrls = imageFileList.length
|
|
1500
|
+
? await uploadImageFilesViaSignedUrl(baseUrl, headers, projectId, imageFileList)
|
|
1501
|
+
: [];
|
|
1502
|
+
const allImageUrls = [...uploadedImageUrls, ...imageUrlList];
|
|
1448
1503
|
if (imageUrlList.length) process.stderr.write(`📤 Attaching ${imageUrlList.length} URL image(s)...\n`);
|
|
1449
1504
|
const body = { _addToProject: projectId };
|
|
1450
|
-
if (
|
|
1451
|
-
if (imageUrlList.length) body.imageUrls = imageUrlList;
|
|
1505
|
+
if (allImageUrls.length) body.imageUrls = allImageUrls;
|
|
1452
1506
|
const res = await fetch(`${baseUrl}/api/projects/create`, {
|
|
1453
1507
|
method: 'POST',
|
|
1454
1508
|
headers: { 'Content-Type': 'application/json', ...headers },
|
|
@@ -1456,10 +1510,19 @@ if (!command || command === '--help' || command === '-h' || command === 'help')
|
|
|
1456
1510
|
});
|
|
1457
1511
|
if (res.ok) {
|
|
1458
1512
|
const data = await res.json();
|
|
1459
|
-
|
|
1513
|
+
const addedCount = data.snapshots?.length || 0;
|
|
1514
|
+
if (addedCount < allImageUrls.length) {
|
|
1515
|
+
process.stderr.write(`❌ Added only ${addedCount}/${allImageUrls.length} image(s) to project; aborting run.\n`);
|
|
1516
|
+
process.exit(1);
|
|
1517
|
+
}
|
|
1518
|
+
process.stderr.write(`📤 Added ${addedCount} image(s) to project\n`);
|
|
1460
1519
|
} else {
|
|
1461
|
-
process.stderr.write(
|
|
1520
|
+
process.stderr.write(`❌ Failed to add images: ${await res.text()}\n`);
|
|
1521
|
+
process.exit(1);
|
|
1462
1522
|
}
|
|
1523
|
+
chatImages.length = 0;
|
|
1524
|
+
imageUrlList.length = 0;
|
|
1525
|
+
imageFileList.length = 0;
|
|
1463
1526
|
}
|
|
1464
1527
|
|
|
1465
1528
|
const resolvedSkill = await resolveChatSkill(baseUrl, headers, activeSkill);
|