@muxoai/cli 0.1.1 → 0.1.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.
Files changed (3) hide show
  1. package/README.md +11 -0
  2. package/dist/index.js +118 -4
  3. package/package.json +3 -2
package/README.md CHANGED
@@ -43,10 +43,21 @@ muxo logs [workflow] Execution history
43
43
  muxo steps <instanceId> Per-step log for one execution
44
44
  muxo login Store your key in the OS keychain
45
45
  muxo mcp Stdio MCP proxy for agents
46
+ muxo ui Launch the interactive TUI dashboard
46
47
  ```
47
48
 
48
49
  Global flags: `--json`, `--quiet`, `--debug`.
49
50
 
51
+ ## Dashboard
52
+
53
+ ```bash
54
+ muxo ui
55
+ ```
56
+
57
+ A full-screen TUI (from [`@muxoai/tui`](https://www.npmjs.com/package/@muxoai/tui))
58
+ with tabs for overview + budget, capabilities, workflows, runs, keys, and
59
+ credits. Keyboard-first, mouse-friendly.
60
+
50
61
  ## Agent-first
51
62
 
52
63
  Point any MCP client at `https://api.muxo.ai/mcp` (Bearer auth), or use the
package/dist/index.js CHANGED
@@ -396,6 +396,26 @@ function landingPage(title) {
396
396
  </html>
397
397
  `;
398
398
  }
399
+ async function harnessManifest(intent, project) {
400
+ const base = process.env.MUXO_HARNESS_URL;
401
+ if (base === void 0 || base.trim() === "") return void 0;
402
+ try {
403
+ const res = await fetch(`${base.replace(/\/+$/, "")}/architect`, {
404
+ method: "POST",
405
+ headers: { "content-type": "application/json" },
406
+ body: JSON.stringify({ intent, project }),
407
+ signal: AbortSignal.timeout(18e4)
408
+ });
409
+ if (!res.ok) return void 0;
410
+ const body = await res.json();
411
+ const yaml = body.data?.yaml;
412
+ if (typeof yaml !== "string" || yaml.trim() === "") return void 0;
413
+ if (!validateManifest(yaml).ok) return void 0;
414
+ return { yaml, source: "harness" };
415
+ } catch {
416
+ return void 0;
417
+ }
418
+ }
399
419
  async function architectManifest(intent, project, opts) {
400
420
  const key = await resolveKey();
401
421
  if (key === void 0) return void 0;
@@ -417,7 +437,7 @@ async function init(intent, opts) {
417
437
  let source = "template";
418
438
  if (it !== "") {
419
439
  try {
420
- const designed = await architectManifest(it, project, opts);
440
+ const designed = await harnessManifest(it, project) ?? await architectManifest(it, project, opts);
421
441
  if (designed !== void 0) {
422
442
  text = designed.yaml;
423
443
  source = designed.source;
@@ -428,7 +448,8 @@ async function init(intent, opts) {
428
448
  const tpl = matchTemplate(it);
429
449
  if (text === void 0) text = renderManifest(project, it, tpl);
430
450
  await writeFile2("muxo.yaml", text, "utf8");
431
- info(`wrote muxo.yaml${source === "architect" ? " (designed by the muxo architect)" : ""}`, opts);
451
+ const designedBy = source === "harness" ? " (designed by the muxo harness)" : source === "architect" ? " (designed by the muxo architect)" : "";
452
+ info(`wrote muxo.yaml${designedBy}`, opts);
432
453
  const parsed = validateManifest(text);
433
454
  const bundles = parsed.ok && parsed.manifest !== void 0 ? Object.keys(parsed.manifest.bundles ?? {}) : Object.keys(tpl.bundles);
434
455
  if (bundles.length > 0) {
@@ -1046,9 +1067,10 @@ async function capabilities(opts) {
1046
1067
  const rows = data2.capabilities ?? [];
1047
1068
  for (const c of rows) {
1048
1069
  const providers = c.backends.map((b) => b.configured ? b.provider : `${b.provider}*`).join(", ");
1049
- console.log(`${c.available ? "ok " : "-- "}${c.name.padEnd(20)} ${providers}`);
1070
+ console.log(`${c.available ? "ok " : "-- "}${(c.friendly ?? c.name).padEnd(18)} ${c.name.padEnd(22)} ${providers}`);
1050
1071
  }
1051
1072
  console.log("\n* = not configured (missing runtime secrets)");
1073
+ console.log("friendly names work anywhere a capability name does (REST, MCP, CLI, SDK)");
1052
1074
  });
1053
1075
  }
1054
1076
 
@@ -1094,6 +1116,45 @@ async function creditsCommand(action, packId, opts) {
1094
1116
  });
1095
1117
  }
1096
1118
 
1119
+ // src/commands/payments.ts
1120
+ async function paymentsCommand(action, opts) {
1121
+ const api = makeApi({
1122
+ baseUrl: baseUrl(),
1123
+ key: await resolveKey(),
1124
+ debug: opts.debug
1125
+ });
1126
+ if (action === "onboard") {
1127
+ const env2 = await api.post("/payments/onboard");
1128
+ return renderEnvelope(env2, !!opts.json, (data2) => {
1129
+ const d = data2;
1130
+ if (d?.stubbed) {
1131
+ console.log("payouts: stubbed \u2014 set STRIPE_PAYMENTS_SECRET_KEY on the runtime for real onboarding");
1132
+ return;
1133
+ }
1134
+ if (d?.status === "active") {
1135
+ console.log("payouts: already active");
1136
+ return;
1137
+ }
1138
+ if (d?.onboarding_url) {
1139
+ console.log(`payout setup: ${d.onboarding_url}`);
1140
+ console.log("open the link to finish setup, then run `muxo payments status`");
1141
+ return;
1142
+ }
1143
+ console.log(`payouts: ${d?.status ?? "pending"}`);
1144
+ });
1145
+ }
1146
+ const env = await api.get("/payments");
1147
+ return renderEnvelope(env, !!opts.json, (data2) => {
1148
+ const d = data2;
1149
+ console.log(`payouts: ${d?.status ?? "none"}`);
1150
+ if (d?.status === "none") {
1151
+ console.log("run `muxo payments onboard` to accept payments from agents");
1152
+ } else if (d?.status === "pending" || d?.status === "restricted") {
1153
+ console.log("run `muxo payments onboard` to resume setup");
1154
+ }
1155
+ });
1156
+ }
1157
+
1097
1158
  // src/commands/login.ts
1098
1159
  import { createInterface } from "node:readline";
1099
1160
  function promptHidden(promptText) {
@@ -1200,9 +1261,22 @@ var STATIC_TOOLS = [
1200
1261
  { name: "vector_search", description: "Vector search. Inputs: query (required), k?." },
1201
1262
  { name: "email_send", description: "Send an email. Inputs: to, subject, body (all required)." },
1202
1263
  { name: "observability_log", description: "Log an event. Inputs: level (required), message (required)." },
1203
- { name: "queue_emit", description: "Emit an event to a queue. Inputs: topic (required), payload (required)." }
1264
+ { name: "queue_emit", description: "Emit an event to a queue. Inputs: topic (required), payload (required)." },
1265
+ { name: "llm_image", description: "Generate an image from a prompt. Inputs: prompt (required), size?, model?." },
1266
+ { name: "llm_stt", description: "Transcribe audio to text. Inputs: audio_url or audio_base64 (required), model?." },
1267
+ { name: "sms_send", description: "Send an SMS. Inputs: to (required), body (required), from?." },
1268
+ { name: "analytics_track", description: "Track an analytics event. Inputs: event (required), distinct_id?, properties?." },
1269
+ { name: "appsearch_query", description: "Full-text search an app index. Inputs: query (required), index?, limit?." },
1270
+ { name: "memory_store", description: "Store a memory. Inputs: content (required), metadata?." },
1271
+ { name: "memory_search", description: "Search stored memories. Inputs: query (required), k?." },
1272
+ { name: "featureflags_evaluate", description: "Evaluate a feature flag. Inputs: flag (required), context?." },
1273
+ { name: "video_generate", description: "Generate a video from a prompt. Inputs: prompt (required), avatar_id?, voice_id?." },
1274
+ { name: "auth_users", description: "Manage users. Inputs: action (create|get|list|delete), id?, email?, password?, metadata?." },
1275
+ { name: "payments_charge", description: "Accept a payment from an agent (Stripe PaymentIntents / MPP). Inputs: amount (required), currency?, payment_method_types?, payment_method?, confirm?, metadata?." },
1276
+ { name: "payments_refund", description: "Refund a payment. Inputs: payment_intent (required), amount?, reason?." }
1204
1277
  ];
1205
1278
  function excluded(tool) {
1279
+ if (process.env.MUXO_MCP_EXPOSE_ALL === "true") return false;
1206
1280
  return tool.startsWith("deploy_") || tool === "domains_register" || tool === "compute_container";
1207
1281
  }
1208
1282
  function toToolName(capability) {
@@ -1330,6 +1404,27 @@ async function mcp(opts) {
1330
1404
  return 0;
1331
1405
  }
1332
1406
 
1407
+ // src/commands/ui.ts
1408
+ async function ui(opts) {
1409
+ if (process.stdout.isTTY !== true) {
1410
+ console.error("error: `muxo ui` needs an interactive terminal (TTY)");
1411
+ return 1;
1412
+ }
1413
+ let mod;
1414
+ try {
1415
+ mod = await import("@muxoai/tui");
1416
+ } catch (err) {
1417
+ const message = err instanceof Error ? err.message : String(err);
1418
+ if (/Cannot find (module|package)|ERR_MODULE_NOT_FOUND/.test(message)) {
1419
+ console.error("error: @muxoai/tui is not installed \u2014 run `npm i -g @muxoai/tui`");
1420
+ return 1;
1421
+ }
1422
+ throw err;
1423
+ }
1424
+ await mod.run({ baseUrl: baseUrl(), key: await resolveKey(), debug: opts.debug });
1425
+ return 0;
1426
+ }
1427
+
1333
1428
  // src/index.ts
1334
1429
  function flags(cmd) {
1335
1430
  cmd.option("--json", "structured JSON output").option("--quiet", "suppress non-essential output").option("--debug", "log requests to stderr");
@@ -1343,6 +1438,7 @@ Examples:
1343
1438
  muxo run hn-scraper --param max_items=3
1344
1439
  muxo call web.search --data '{"query":"agent infra","limit":3}'
1345
1440
  muxo logs && muxo steps <instanceId>
1441
+ muxo ui # interactive dashboard
1346
1442
 
1347
1443
  Auth: export MUXO_KEY=mk_... Endpoint: export MUXO_API_BASE=https://api.muxo.ai/v1
1348
1444
  Docs: https://api.muxo.ai/docs/quickstart`);
@@ -1441,6 +1537,19 @@ Docs: https://api.muxo.ai/docs/quickstart`);
1441
1537
  creditsBuy.action(async (pack, opts, cmd) => {
1442
1538
  process.exitCode = await creditsCommand("buy", pack, { ...cmd.parent.opts(), ...opts });
1443
1539
  });
1540
+ const payments = program.command("payments");
1541
+ flags(payments);
1542
+ payments.description("Payout setup for accepting payments from agents");
1543
+ const paymentsOnboard = payments.command("onboard");
1544
+ flags(paymentsOnboard);
1545
+ paymentsOnboard.action(async (opts, cmd) => {
1546
+ process.exitCode = await paymentsCommand("onboard", { ...cmd.parent.opts(), ...opts });
1547
+ });
1548
+ const paymentsStatus = payments.command("status");
1549
+ flags(paymentsStatus);
1550
+ paymentsStatus.action(async (opts, cmd) => {
1551
+ process.exitCode = await paymentsCommand("status", { ...cmd.parent.opts(), ...opts });
1552
+ });
1444
1553
  const rollbackCmd = program.command("rollback [version]");
1445
1554
  flags(rollbackCmd);
1446
1555
  rollbackCmd.description("Re-apply a previous manifest snapshot").action(async (version, opts) => {
@@ -1466,6 +1575,11 @@ Docs: https://api.muxo.ai/docs/quickstart`);
1466
1575
  mcpCmd.description("Stdio MCP proxy wrapping the muxo API").action(async (opts) => {
1467
1576
  process.exitCode = await mcp(opts);
1468
1577
  });
1578
+ const uiCmd = program.command("ui");
1579
+ flags(uiCmd);
1580
+ uiCmd.description("Launch the interactive TUI dashboard (status, capabilities, workflows, runs, keys, credits)").action(async (opts) => {
1581
+ process.exitCode = await ui(opts);
1582
+ });
1469
1583
  await program.parseAsync(process.argv);
1470
1584
  }
1471
1585
  main().catch((err) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@muxoai/cli",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "description": "Muxo CLI: one key for your whole stack — scaffold, validate, apply, run, and monitor agent workflows.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -39,7 +39,8 @@
39
39
  "prepublishOnly": "npm run build"
40
40
  },
41
41
  "dependencies": {
42
- "@muxoai/core": "^0.1.1",
42
+ "@muxoai/core": "^0.1.3",
43
+ "@muxoai/tui": "^0.1.1",
43
44
  "commander": "^12.0.0",
44
45
  "yaml": "^2.4.0",
45
46
  "zod": "^3.23.0"