makefx 2.0.1 → 2.0.3
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/CHANGELOG.md +9 -0
- package/dist/makefx.js +64 -31
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,15 @@
|
|
|
3
3
|
The 1.x packages were built from the first version of makefx.app and do not
|
|
4
4
|
work with the current service.
|
|
5
5
|
|
|
6
|
+
## 2.0.3 — 2026-09-26
|
|
7
|
+
|
|
8
|
+
- `create` refuses a prompt longer than the model's published `prompt_max_chars` before spending credits, and counts prompt length in characters rather than UTF-16 units, as the service does.
|
|
9
|
+
|
|
10
|
+
## 2.0.2 — 2026-09-26
|
|
11
|
+
|
|
12
|
+
- `create --wait --json` now prints each asset's final ready or failed state instead of the queued state captured before waiting, and exits 1 with the failed asset's error when waiting ends in failure.
|
|
13
|
+
- Usage and unexpected errors are now also written as JSON to stdout under `--json`, and the `upload` error for an unrecognized file extension now names the supported upload types.
|
|
14
|
+
|
|
6
15
|
## 2.0.1 — 2026-09-24
|
|
7
16
|
|
|
8
17
|
- Always print the login authorization URL, callback port, and an SSH tunnel command with the detected hostname so remote login can be completed from a local browser.
|
package/dist/makefx.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
// src/index.ts
|
|
4
|
-
import
|
|
4
|
+
import process5 from "node:process";
|
|
5
5
|
|
|
6
6
|
// src/lib/project.ts
|
|
7
7
|
var SERVICE_NAME = "makefx.app";
|
|
@@ -13,7 +13,7 @@ var ENVIRONMENT_ORIGINS = {
|
|
|
13
13
|
};
|
|
14
14
|
|
|
15
15
|
// src/lib/version.ts
|
|
16
|
-
var CLI_VERSION = true ? "2.0.
|
|
16
|
+
var CLI_VERSION = true ? "2.0.3" : "0.0.0-dev";
|
|
17
17
|
|
|
18
18
|
// src/commands/convenience.ts
|
|
19
19
|
import { randomUUID } from "node:crypto";
|
|
@@ -870,6 +870,7 @@ async function handleOpen(parsed, dependencies = defaults) {
|
|
|
870
870
|
|
|
871
871
|
// src/commands/create.ts
|
|
872
872
|
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
873
|
+
import process2 from "node:process";
|
|
873
874
|
|
|
874
875
|
// src/lib/json-schema.ts
|
|
875
876
|
import { isDeepStrictEqual } from "node:util";
|
|
@@ -1093,7 +1094,7 @@ function validateJsonSchema(schema, input) {
|
|
|
1093
1094
|
// src/commands/create.ts
|
|
1094
1095
|
var defaults2 = {
|
|
1095
1096
|
client: authenticatedToolClient,
|
|
1096
|
-
write: (text2) =>
|
|
1097
|
+
write: (text2) => process2.stdout.write(`${text2}
|
|
1097
1098
|
`),
|
|
1098
1099
|
id: randomUUID2
|
|
1099
1100
|
};
|
|
@@ -1246,7 +1247,7 @@ function prepareCreate(parsed) {
|
|
|
1246
1247
|
throw new CliUsageError("--request-id must be at most 64 characters.");
|
|
1247
1248
|
}
|
|
1248
1249
|
const prompt = optional2(parsed, "prompt") ?? "";
|
|
1249
|
-
if (prompt.length > 8e3) throw new CliUsageError("--prompt must be at most 8000 characters.");
|
|
1250
|
+
if (Array.from(prompt).length > 8e3) throw new CliUsageError("--prompt must be at most 8000 characters.");
|
|
1250
1251
|
return {
|
|
1251
1252
|
spaceId: required2(parsed, "space"),
|
|
1252
1253
|
kind,
|
|
@@ -1307,12 +1308,19 @@ function catalogModels(document) {
|
|
|
1307
1308
|
`list_models returned a malformed catalog: ${error instanceof Error ? error.message : "invalid params_schema."}`
|
|
1308
1309
|
);
|
|
1309
1310
|
}
|
|
1311
|
+
const promptMaxChars = model.prompt_max_chars;
|
|
1312
|
+
if (promptMaxChars !== void 0 && (typeof promptMaxChars !== "number" || !Number.isSafeInteger(promptMaxChars) || promptMaxChars < 1)) {
|
|
1313
|
+
throw new Error(
|
|
1314
|
+
`list_models returned a malformed catalog: model "${model.id}" prompt_max_chars must be a positive integer.`
|
|
1315
|
+
);
|
|
1316
|
+
}
|
|
1310
1317
|
return {
|
|
1311
1318
|
id: model.id,
|
|
1312
1319
|
kind: model.kind,
|
|
1313
1320
|
availability: model.availability,
|
|
1314
1321
|
hidden: model.hidden,
|
|
1315
|
-
paramsSchema: model.params_schema
|
|
1322
|
+
paramsSchema: model.params_schema,
|
|
1323
|
+
...promptMaxChars === void 0 ? {} : { promptMaxChars }
|
|
1316
1324
|
};
|
|
1317
1325
|
});
|
|
1318
1326
|
}
|
|
@@ -1325,6 +1333,11 @@ function createToolArguments(prepared, entry, requestId) {
|
|
|
1325
1333
|
`Model "${prepared.model}" is unavailable. Run models --space ${prepared.spaceId} to list the catalog.`
|
|
1326
1334
|
);
|
|
1327
1335
|
}
|
|
1336
|
+
if (entry.promptMaxChars !== void 0 && prepared.recipeMode !== "exact" && Array.from(prepared.prompt).length > entry.promptMaxChars) {
|
|
1337
|
+
throw new CliUsageError(
|
|
1338
|
+
`--prompt must be at most ${entry.promptMaxChars} characters for model "${prepared.model}".`
|
|
1339
|
+
);
|
|
1340
|
+
}
|
|
1328
1341
|
const validation = validateJsonSchema(entry.paramsSchema, prepared.params);
|
|
1329
1342
|
if (!validation.ok) {
|
|
1330
1343
|
const field = validation.issue.field.replace(/^params\.?/, "") || "params";
|
|
@@ -1360,13 +1373,13 @@ async function handleCreate(parsed, dependencies = defaults2) {
|
|
|
1360
1373
|
}
|
|
1361
1374
|
const args = createToolArguments(prepared, entry, dependencies.id());
|
|
1362
1375
|
const created = await client.call("create_asset", args);
|
|
1363
|
-
|
|
1376
|
+
let assets = Array.isArray(created.assets) ? created.assets : [];
|
|
1364
1377
|
if (parsed.options.wait === "true" && !assets.some(({ renders_in }) => renders_in === "browser")) {
|
|
1365
1378
|
const spaceId2 = prepared.spaceId;
|
|
1366
|
-
|
|
1379
|
+
assets = await Promise.all(
|
|
1367
1380
|
assets.map(async (asset) => {
|
|
1368
1381
|
const assetId = asset.asset_id;
|
|
1369
|
-
if (typeof assetId !== "string") return
|
|
1382
|
+
if (typeof assetId !== "string") return asset;
|
|
1370
1383
|
while (true) {
|
|
1371
1384
|
const result = await client.call("get_asset", {
|
|
1372
1385
|
space_id: spaceId2,
|
|
@@ -1374,16 +1387,26 @@ async function handleCreate(parsed, dependencies = defaults2) {
|
|
|
1374
1387
|
wait_seconds: 60
|
|
1375
1388
|
});
|
|
1376
1389
|
const current = result.asset;
|
|
1377
|
-
if (current?.status === "ready")
|
|
1378
|
-
|
|
1379
|
-
const error = current.error;
|
|
1380
|
-
return error?.message ?? `Asset ${assetId} failed.`;
|
|
1390
|
+
if (current?.status === "ready" || current?.status === "failed") {
|
|
1391
|
+
return current ? { ...asset, ...current } : asset;
|
|
1381
1392
|
}
|
|
1382
1393
|
}
|
|
1383
1394
|
})
|
|
1384
1395
|
);
|
|
1385
|
-
|
|
1386
|
-
|
|
1396
|
+
created.assets = assets;
|
|
1397
|
+
const failed = assets.filter((asset) => asset.status === "failed");
|
|
1398
|
+
if (failed.length > 0) {
|
|
1399
|
+
if (parsed.options.json === "true") {
|
|
1400
|
+
dependencies.write(JSON.stringify(created, null, 2));
|
|
1401
|
+
process2.exitCode = 1;
|
|
1402
|
+
return;
|
|
1403
|
+
}
|
|
1404
|
+
const messages = failed.map((asset) => {
|
|
1405
|
+
const error = asset.error;
|
|
1406
|
+
return error?.message ?? `Asset ${String(asset.asset_id)} failed.`;
|
|
1407
|
+
});
|
|
1408
|
+
throw new Error(messages.join("\n"));
|
|
1409
|
+
}
|
|
1387
1410
|
}
|
|
1388
1411
|
if (parsed.options.json === "true") {
|
|
1389
1412
|
dependencies.write(JSON.stringify(created, null, 2));
|
|
@@ -1397,7 +1420,7 @@ async function handleCreate(parsed, dependencies = defaults2) {
|
|
|
1397
1420
|
}
|
|
1398
1421
|
|
|
1399
1422
|
// src/commands/login.ts
|
|
1400
|
-
import
|
|
1423
|
+
import process3 from "node:process";
|
|
1401
1424
|
import { hostname } from "node:os";
|
|
1402
1425
|
async function handleLogin(parsed) {
|
|
1403
1426
|
const isLocal = parsed.options.local === "true";
|
|
@@ -1408,7 +1431,7 @@ async function handleLogin(parsed) {
|
|
|
1408
1431
|
const insecure = isLocal;
|
|
1409
1432
|
if (insecure) {
|
|
1410
1433
|
console.log("\u26A0\uFE0F SSL certificate verification disabled (local dev mode)");
|
|
1411
|
-
|
|
1434
|
+
process3.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
|
|
1412
1435
|
}
|
|
1413
1436
|
console.log(`Starting login for environment "${env}" using ${baseUrl}`);
|
|
1414
1437
|
const server = await discoverAuthorizationServer(baseUrl);
|
|
@@ -1496,20 +1519,20 @@ async function handleLogout(parsed) {
|
|
|
1496
1519
|
}
|
|
1497
1520
|
|
|
1498
1521
|
// src/commands/mcp.ts
|
|
1499
|
-
import
|
|
1522
|
+
import process4 from "node:process";
|
|
1500
1523
|
async function handleMcp(parsed) {
|
|
1501
1524
|
const env = parsed.options.local === "true" ? "local" : parsed.options.env ?? DEFAULT_ENVIRONMENT;
|
|
1502
1525
|
const loginHint = `Run: ${cliCommand()} login --env ${env}`;
|
|
1503
1526
|
const stored = await loadStoredConfig(env);
|
|
1504
1527
|
if (!stored) {
|
|
1505
1528
|
console.error(`Not logged in for "${env}". ${loginHint}`);
|
|
1506
|
-
|
|
1529
|
+
process4.exitCode = 1;
|
|
1507
1530
|
return;
|
|
1508
1531
|
}
|
|
1509
1532
|
const config = await ensureFreshConfig(stored);
|
|
1510
1533
|
if (!config) {
|
|
1511
1534
|
console.error(`Credentials for "${env}" have expired. ${loginHint}`);
|
|
1512
|
-
|
|
1535
|
+
process4.exitCode = 1;
|
|
1513
1536
|
return;
|
|
1514
1537
|
}
|
|
1515
1538
|
const bridge = createMcpBridge({ config });
|
|
@@ -1519,15 +1542,15 @@ async function handleMcp(parsed) {
|
|
|
1519
1542
|
case "accepted":
|
|
1520
1543
|
return;
|
|
1521
1544
|
case "response":
|
|
1522
|
-
if (outcome.text)
|
|
1545
|
+
if (outcome.text) process4.stdout.write(`${outcome.text}
|
|
1523
1546
|
`);
|
|
1524
1547
|
return;
|
|
1525
1548
|
case "unauthorized":
|
|
1526
|
-
if (outcome.text)
|
|
1549
|
+
if (outcome.text) process4.stdout.write(`${outcome.text}
|
|
1527
1550
|
`);
|
|
1528
1551
|
console.error(`Access to "${env}" was revoked or has expired. ${loginHint}`);
|
|
1529
|
-
|
|
1530
|
-
|
|
1552
|
+
process4.exitCode = 1;
|
|
1553
|
+
process4.stdin.destroy();
|
|
1531
1554
|
return;
|
|
1532
1555
|
case "unreachable":
|
|
1533
1556
|
console.error(`MCP request failed: ${outcome.message}`);
|
|
@@ -1536,8 +1559,8 @@ async function handleMcp(parsed) {
|
|
|
1536
1559
|
}
|
|
1537
1560
|
let buffer = "";
|
|
1538
1561
|
const pending = [];
|
|
1539
|
-
|
|
1540
|
-
for await (const chunk of
|
|
1562
|
+
process4.stdin.setEncoding("utf8");
|
|
1563
|
+
for await (const chunk of process4.stdin) {
|
|
1541
1564
|
buffer += chunk;
|
|
1542
1565
|
let newline = buffer.indexOf("\n");
|
|
1543
1566
|
while (newline !== -1) {
|
|
@@ -2339,7 +2362,12 @@ function uploadMime(parsed, path2) {
|
|
|
2339
2362
|
const explicit = optional5(parsed, "mime");
|
|
2340
2363
|
if (explicit) return explicit;
|
|
2341
2364
|
const inferred = MIME_BY_EXTENSION[extname(path2).toLowerCase()];
|
|
2342
|
-
if (!inferred)
|
|
2365
|
+
if (!inferred) {
|
|
2366
|
+
const supported = Object.keys(MIME_BY_EXTENSION).sort().join(", ");
|
|
2367
|
+
throw new CliUsageError(
|
|
2368
|
+
`Cannot infer media type from --file; supported uploads are ${supported} \u2014 pass --mime <type> to override.`
|
|
2369
|
+
);
|
|
2370
|
+
}
|
|
2343
2371
|
return inferred;
|
|
2344
2372
|
}
|
|
2345
2373
|
function declaredRecipe(parsed) {
|
|
@@ -2563,11 +2591,16 @@ function reportCommandError(error, json2, output) {
|
|
|
2563
2591
|
return 1;
|
|
2564
2592
|
}
|
|
2565
2593
|
if (error instanceof CliUsageError) {
|
|
2594
|
+
if (json2) output.stdout(`${JSON.stringify({ code: "usage", message: error.message })}
|
|
2595
|
+
`);
|
|
2566
2596
|
output.stderr(`Error: ${error.message}
|
|
2567
2597
|
`);
|
|
2568
2598
|
return 2;
|
|
2569
2599
|
}
|
|
2570
|
-
|
|
2600
|
+
const message = error instanceof Error ? error.message : "Unexpected error occurred";
|
|
2601
|
+
if (json2) output.stdout(`${JSON.stringify({ code: "error", message })}
|
|
2602
|
+
`);
|
|
2603
|
+
output.stderr(`Error: ${message}
|
|
2571
2604
|
`);
|
|
2572
2605
|
return 1;
|
|
2573
2606
|
}
|
|
@@ -2862,7 +2895,7 @@ async function handleSpaceVisibilityCommand(command, parsed, dependencies = defa
|
|
|
2862
2895
|
|
|
2863
2896
|
// src/index.ts
|
|
2864
2897
|
async function main() {
|
|
2865
|
-
const [, , command, ...args] =
|
|
2898
|
+
const [, , command, ...args] = process5.argv;
|
|
2866
2899
|
try {
|
|
2867
2900
|
if (!command || command === "--help") {
|
|
2868
2901
|
printHelp();
|
|
@@ -2882,9 +2915,9 @@ async function main() {
|
|
|
2882
2915
|
await dispatchCommand(command, parsed);
|
|
2883
2916
|
} catch (error) {
|
|
2884
2917
|
const parsed = parseArgs(args);
|
|
2885
|
-
|
|
2886
|
-
stdout: (text2) =>
|
|
2887
|
-
stderr: (text2) =>
|
|
2918
|
+
process5.exitCode = reportCommandError(error, parsed.options.json === "true", {
|
|
2919
|
+
stdout: (text2) => process5.stdout.write(text2),
|
|
2920
|
+
stderr: (text2) => process5.stderr.write(text2)
|
|
2888
2921
|
});
|
|
2889
2922
|
}
|
|
2890
2923
|
}
|