@muxoai/platform 1.2.3 → 1.3.1

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 (41) hide show
  1. package/.agents/plugins/marketplace.json +1 -1
  2. package/.claude-plugin/marketplace.json +19 -4
  3. package/.codex/config.toml +9 -2
  4. package/README.md +72 -28
  5. package/dist/cli.js +1047 -43
  6. package/dist/engine.d.ts +29 -0
  7. package/dist/engine.js +221 -16
  8. package/dist/mcp.d.ts +6 -1
  9. package/dist/mcp.js +120 -26
  10. package/dist/nl.d.ts +34 -0
  11. package/dist/nl.js +601 -0
  12. package/dist/providers/composio-instant.d.ts +1 -0
  13. package/dist/providers/composio-instant.js +6 -5
  14. package/dist/providers/composio-sdk.d.ts +1 -0
  15. package/dist/providers/composio-sdk.js +6 -2
  16. package/dist/providers/stripe-billing.d.ts +13 -3
  17. package/dist/providers/stripe-billing.js +250 -36
  18. package/dist/providers/stripe-projects.js +61 -4
  19. package/dist/providers/supermemory.d.ts +2 -0
  20. package/dist/providers/supermemory.js +58 -40
  21. package/dist/sdk.d.ts +77 -1
  22. package/dist/sdk.js +46 -0
  23. package/dist/server.js +202 -29
  24. package/dist/store.d.ts +19 -2
  25. package/dist/store.js +216 -11
  26. package/dist/types.d.ts +14 -2
  27. package/dist/ui/console-html.js +329 -119
  28. package/package.json +1 -1
  29. package/plugins/muxo/.app.json +1 -1
  30. package/plugins/muxo/.claude-plugin/plugin.json +2 -2
  31. package/plugins/muxo/.codex-plugin/plugin.json +7 -5
  32. package/plugins/muxo/.mcp.json +1 -33
  33. package/plugins/muxo/assets/logo.png +0 -0
  34. package/plugins/muxo/hooks/session-start.sh +1 -1
  35. package/plugins/muxo/plugin.json +63 -6
  36. package/plugins/muxo/skills/muxo/SKILL.md +92 -14
  37. package/plugins/muxo/skills/muxo/agents/openai.yaml +12 -0
  38. package/plugins/muxo/skills/muxo/references/cli.md +4 -2
  39. package/plugins/muxo/skills/muxo/references/mcp.md +15 -9
  40. package/plugins/muxo/skills/setup/SKILL.md +8 -2
  41. package/plugins/muxo/skills/setup/agents/openai.yaml +12 -0
package/dist/server.js CHANGED
@@ -10,35 +10,51 @@ import { renderConsoleHtml, renderLandingHtml } from "./ui/console-html.js";
10
10
  function renderSkillMarkdown(baseUrl) {
11
11
  return `---
12
12
  name: muxo
13
- description: Discover, plan, and execute governed actions across Connected Apps (Composio SDK), Instant Tools (Composio Instant), Cloud Infrastructure (Stripe Projects), Contextual Memory (Supermemory v5), and Cryptographic Governance (Microsoft Agent Governance Toolkit) through Muxo.
13
+ description: Discover, plan, and execute governed actions across Connected Apps (app.*), Instant Tools (instant.*), Cloud Infrastructure (resource.*), Workspace Memory, and Safety Guardrails through Muxo.
14
14
  ---
15
15
 
16
- # Muxo — Unified Agent Execution, Infrastructure, Memory & Governance Platform
16
+ # Muxo — Unified Agent Execution, Infrastructure, Memory & Safety Platform
17
17
 
18
- Muxo provides one governed interface over 4 pillars so agents and customers only ever interact with Muxo:
18
+ Muxo provides one unified interface across 4 capabilities so agents and users only ever interact with Muxo:
19
19
 
20
- 1. **Instant Tools (\`instant.*\`)**: Zero-OAuth tools powered by Composio Instant (\`instant.web.search\`, \`instant.web.scrape\`, \`instant.hackernews.top_stories\`, \`instant.github.repo_intel\`, \`instant.dns.lookup\`).
21
- 2. **Connected Apps (\`app.*\`)**: Managed OAuth SaaS integrations powered by Composio SDK (\`app.github.*\`, \`app.gmail.*\`, \`app.slack.*\`, \`app.notion.*\`, \`app.linear.*\`, etc.).
22
- 3. **Cloud Infrastructure (\`resource.*\`)**: Database, cache, storage, and hosting provisioning powered by Stripe Projects (\`resource.neon.*\`, \`resource.supabase.*\`, \`resource.turso.*\`, \`resource.cloudflare.*\`, \`resource.vercel.*\`, etc.) with AES-256-GCM secret custody in Muxo Vault.
23
- 4. **Supermemory v5 Brain & Microsoft Agent Governance**: Every \`plan_action\` recalls isolated workspace context (\`/ns/muxo-v5-<hash>\`) and runs \`Agent ──► McpSecurityScanner ──► PolicyEngine ──► AgentIdentity (Ed25519 DID) ──► AuditLogger ──► DecisionRecord\`.
20
+ 1. **Instant Tools (\`instant.*\`)**: Zero-OAuth tools ready immediately (\`instant.web.search\`, \`instant.web.scrape\`, \`instant.web.crawl\`, \`instant.seo.audit\`, \`instant.hackernews.top_stories\`, \`instant.github.repo_intel\`, \`instant.dns.lookup\`).
21
+ 2. **Connected Apps (\`app.*\`)**: Managed OAuth SaaS integrations (\`app.github.*\`, \`app.gmail.*\`, \`app.slack.*\`, \`app.notion.*\`, \`app.linear.*\`, etc.).
22
+ 3. **Cloud Infrastructure (\`resource.*\`)**: Database, cache, storage, and hosting provisioning (\`resource.neon.*\`, \`resource.supabase.*\`, \`resource.turso.*\`, \`resource.cloudflare.*\`, \`resource.vercel.*\`, etc.) with AES-256-GCM secret custody in Muxo Vault.
23
+ 4. **Workspace Memory & Safety Guardrails**: Every \`plan_action\` recalls isolated workspace context (\`/ns/muxo-v5-<hash>\`), scans inputs for prompt injection, enforces risk-lane approval policies, and records a verifiable audit log.
24
24
 
25
- ## Installable Muxo Plugin (OpenAI Codex, ChatGPT, Claude Code & Factory Droid)
25
+ ## Installable Muxo Plugin (Claude Code, OpenAI Codex, Claude Desktop & ChatGPT)
26
+
27
+ > **Requirement:** \`@muxoai/cli\` requires **Node.js 22+** (\`node >= 22.0.0\`).
26
28
 
27
29
  \`\`\`bash
28
- # Install Muxo CLI & sign in (or auto-provision an isolated external workspace)
29
- npm install -g muxo-platform
30
+ # Install Muxo CLI & sign in against the hosted workspace (Node.js 22+)
31
+ npm install -g @muxoai/cli@latest
30
32
  muxo login --signup --name "my-agent"
31
33
 
34
+ # Claude Code marketplace (muxo@muxo):
35
+ claude plugin marketplace add ${baseUrl}/.claude-plugin/marketplace.json
36
+ claude plugin install muxo@muxo
37
+
38
+ # OpenAI Codex: add a Git repo or local marketplace directory containing .agents/plugins/marketplace.json,
39
+ # or configure [mcp_servers.muxo] in ~/.codex/config.toml (url = "${baseUrl}/mcp")
40
+
41
+ # Claude Desktop:
42
+ # - Hosted MCP: Settings -> Connectors -> Add custom connector -> ${baseUrl}/mcp
43
+ # - Local stdio server: configure npx -y @muxoai/cli@latest mcp in claude_desktop_config.json
44
+
45
+ # ChatGPT:
46
+ # - Plugins -> + -> Add custom MCP server -> ${baseUrl}/mcp (OAuth supports CIMD or DCR)
47
+
32
48
  # Link OAuth apps with live browser handoff + polling recovery
33
49
  muxo link github --wait
34
50
 
35
51
  # Plugin manifests served by this instance:
36
- # - ${baseUrl}/.agents/plugins/marketplace.json (OpenAI Codex / ChatGPT)
37
- # - ${baseUrl}/.claude-plugin/marketplace.json (Claude Code / Factory Droid)
52
+ # - ${baseUrl}/.agents/plugins/marketplace.json (OpenAI Codex local/Git marketplace manifest)
53
+ # - ${baseUrl}/.claude-plugin/marketplace.json (Claude Code marketplace manifest)
38
54
  # - ${baseUrl}/api/v1/plugin
39
55
  \`\`\`
40
56
 
41
- ## Autonomous Agent 2-Call Signup (Zero Browser Required)
57
+ ## CLI-First Autonomous Agent 2-Call Signup
42
58
 
43
59
  \`\`\`bash
44
60
  # 1. Create an autonomous workspace + mk_live_* API key
@@ -154,7 +170,7 @@ export function createMuxoServer(customConfig) {
154
170
  ok: true,
155
171
  status: "ready",
156
172
  service: "muxo-platform",
157
- version: "1.2.3",
173
+ version: "1.3.1",
158
174
  environment: "production",
159
175
  live_execution: true,
160
176
  customer_billing: true,
@@ -241,10 +257,21 @@ export function createMuxoServer(customConfig) {
241
257
  ],
242
258
  code_challenge_methods_supported: ["S256", "plain"],
243
259
  client_id_metadata_document_supported: true,
260
+ authorization_response_iss_parameter_supported: true,
244
261
  service_documentation: `${config.docsUrl}/quickstart`,
245
262
  });
246
263
  return;
247
264
  }
265
+ if (pathname === "/.well-known/openai-apps-challenge" && req.method === "GET") {
266
+ const challenge = process.env.OPENAI_APPS_CHALLENGE ||
267
+ "muxo-openai-apps-domain-verified";
268
+ res.writeHead(200, {
269
+ "Content-Type": "text/plain; charset=utf-8",
270
+ "Access-Control-Allow-Origin": "*",
271
+ });
272
+ res.end(challenge);
273
+ return;
274
+ }
248
275
  if (pathname === "/oauth/register" && req.method === "POST") {
249
276
  const body = JSON.parse((await readBody(req)) || "{}");
250
277
  const clientId = typeof body.client_id === "string" && body.client_id.trim()
@@ -311,16 +338,22 @@ export function createMuxoServer(customConfig) {
311
338
  apiKey: issuedKey,
312
339
  expiresAt: Date.now() + 10 * 60 * 1000,
313
340
  });
341
+ const proto = String(req.headers["x-forwarded-proto"] || "http").split(",")[0].trim();
342
+ const requestOrigin = req.headers.host
343
+ ? `${proto}://${req.headers.host}`
344
+ : config.baseUrl;
314
345
  const redirectTarget = new URL(redirectUri);
315
346
  redirectTarget.searchParams.set("code", code);
316
347
  if (stateParam)
317
348
  redirectTarget.searchParams.set("state", stateParam);
349
+ redirectTarget.searchParams.set("iss", requestOrigin);
318
350
  if (url.searchParams.get("format") === "json" ||
319
351
  String(req.headers.accept || "").includes("application/json")) {
320
352
  sendJson(res, 200, {
321
353
  ok: true,
322
354
  code,
323
355
  state: stateParam || null,
356
+ iss: requestOrigin,
324
357
  client_id: clientId,
325
358
  redirect_uri: redirectTarget.toString(),
326
359
  });
@@ -409,11 +442,16 @@ export function createMuxoServer(customConfig) {
409
442
  }
410
443
  if (pathname === "/oauth/userinfo" && req.method === "GET") {
411
444
  const ctx = resolveContext(req);
445
+ const nickname = (ctx.user.email || "").split("@")[0] ||
446
+ ctx.user.name.toLowerCase().replace(/\s+/g, ".") ||
447
+ ctx.user.id;
412
448
  sendJson(res, 200, {
413
449
  sub: ctx.user.id,
414
450
  id: ctx.user.id,
415
451
  name: ctx.user.name,
416
452
  email: ctx.user.email,
453
+ email_verified: true,
454
+ nickname,
417
455
  workspace_id: ctx.workspace.id,
418
456
  workspace_name: ctx.workspace.name,
419
457
  tier: ctx.workspace.tier,
@@ -426,7 +464,7 @@ export function createMuxoServer(customConfig) {
426
464
  openapi: "3.1.0",
427
465
  info: {
428
466
  title: "Muxo Unified Agent Execution, Infrastructure, Memory & Governance API",
429
- version: "1.2.3",
467
+ version: "1.3.1",
430
468
  description: "One governed boundary over Connected Apps (Composio SDK), Instant Tools (Composio Instant), Cloud Infrastructure (Stripe Projects), Supermemory v5 Brain, and Microsoft Agent Governance Toolkit.",
431
469
  },
432
470
  servers: [{ url: config.baseUrl }],
@@ -475,12 +513,12 @@ Or via HTTP:
475
513
  curl -sX POST ${config.baseUrl}/api/v1/agents/signup -H "Content-Type: application/json" -d '{"agentName":"my-agent"}'
476
514
  \`\`\`
477
515
 
478
- ## 2. OAuth Connection Handoff (Composio Plugin Pattern)
516
+ ## 2. OAuth Connection Handoff
479
517
  When \`plan_action\` targets an unconnected \`app.<provider>.*\` tool, Muxo returns \`authHandoff.redirectUrl\`.
480
518
  Open the URL in a browser, complete OAuth (which redirects to \`${config.baseUrl}/oauth/callback\`), and call \`wait_for_connection({ provider })\` or \`muxo link <provider> --wait\`.
481
519
 
482
- ## 3. Merchant-of-Record Credit Settlement
483
- Users purchase Muxo Credits (\`POST /api/v1/billing/topup\` or \`muxo billing topup 1000\`), and Muxo settles wholesale supplier costs across Composio and Stripe Projects from Muxo's master accounts (\`fundingMode: "muxo_funded"\`).
520
+ ## 3. Credit Billing & BYOK Support
521
+ Users purchase Muxo Credits (\`POST /api/v1/billing/topup\` or \`muxo billing topup 1000\`), and Muxo settles upstream execution costs from Muxo's master accounts (\`fundingMode: "muxo_funded"\`), or users can configure their own BYOK provider keys for 0-credit execution.
484
522
  `);
485
523
  return;
486
524
  }
@@ -507,7 +545,7 @@ Users purchase Muxo Credits (\`POST /api/v1/billing/topup\` or \`muxo billing to
507
545
  }
508
546
  if (pathname === "/llms.txt" && req.method === "GET") {
509
547
  res.writeHead(200, { "Content-Type": "text/plain; charset=utf-8" });
510
- res.end(`# Muxo\n> Unified execution, cloud provisioning, Supermemory v5 brain, and Microsoft Agent Governance boundary.\n\n- Skill Document: ${config.baseUrl}/skill.md\n- Auth Guide: ${config.baseUrl}/auth.md\n- OpenAPI 3.1 Spec: ${config.baseUrl}/api/openapi.json\n- MCP Endpoint: ${config.baseUrl}/mcp\n- OAuth Callback Handoff: ${config.baseUrl}/oauth/callback\n- Plugin Marketplace (Codex/OpenAI): ${config.baseUrl}/.agents/plugins/marketplace.json\n- Plugin Marketplace (Claude/Droid): ${config.baseUrl}/.claude-plugin/marketplace.json\n- Console (app.muxo.ai): ${config.baseUrl}/\n- Landing & Provider Canvas (muxo.ai): ${config.baseUrl}/landing\n- Documentation (docs.muxo.ai): ${config.docsUrl}\n`);
548
+ res.end(`# Muxo\n> Unified agent execution across Connected Apps, Instant Tools, Cloud Infrastructure, Workspace Memory, and Safety Guardrails.\n\n- Skill Document: ${config.baseUrl}/skill.md\n- Auth Guide: ${config.baseUrl}/auth.md\n- OpenAPI 3.1 Spec: ${config.baseUrl}/api/openapi.json\n- MCP Endpoint: ${config.baseUrl}/mcp\n- OAuth Callback Handoff: ${config.baseUrl}/oauth/callback\n- Plugin Marketplace (Codex/OpenAI): ${config.baseUrl}/.agents/plugins/marketplace.json\n- Plugin Marketplace (Claude/Droid): ${config.baseUrl}/.claude-plugin/marketplace.json\n- Console (app.muxo.ai): ${config.baseUrl}/\n- Landing & Provider Canvas (muxo.ai): ${config.baseUrl}/landing\n- Documentation (docs.muxo.ai): ${config.docsUrl}\n`);
511
549
  return;
512
550
  }
513
551
  // Serve Installable Muxo Plugin Manifests & Metadata (Portable OpenAI Agent Plugins + Codex + Claude)
@@ -616,6 +654,11 @@ Users purchase Muxo Credits (\`POST /api/v1/billing/topup\` or \`muxo billing to
616
654
  sendJson(res, 404, { ok: false, error: "Invalid or expired agent claim link" });
617
655
  return;
618
656
  }
657
+ const claimConsoleKey = store.createApiKey({
658
+ workspaceId: redeemed.workspace.id,
659
+ name: `Owner Claim Session (${redeemed.targetEmail})`,
660
+ environment: "live",
661
+ }).secretKey;
619
662
  const wantsHtml = url.searchParams.get("format") !== "json" &&
620
663
  String(req.headers.accept || "").includes("text/html");
621
664
  if (wantsHtml) {
@@ -640,7 +683,7 @@ Users purchase Muxo Credits (\`POST /api/v1/billing/topup\` or \`muxo billing to
640
683
  <div class="badge">Ownership Bound</div>
641
684
  <h1>Workspace Claimed</h1>
642
685
  <p>Workspace <code>${redeemed.workspace.name}</code> (${redeemed.workspace.id}) claimed by <strong>${redeemed.targetEmail}</strong>.</p>
643
- <a class="btn" href="/?claimed=${encodeURIComponent(redeemed.workspace.slug)}">Open Muxo Console →</a>
686
+ <a class="btn" href="/?claimed=${encodeURIComponent(redeemed.workspace.slug)}&api_key=${encodeURIComponent(claimConsoleKey)}">Open Muxo Console →</a>
644
687
  </div>
645
688
  </body>
646
689
  </html>`);
@@ -649,6 +692,7 @@ Users purchase Muxo Credits (\`POST /api/v1/billing/topup\` or \`muxo billing to
649
692
  sendJson(res, 200, {
650
693
  ok: true,
651
694
  message: `Workspace '${redeemed.workspace.name}' claimed by ${redeemed.targetEmail}`,
695
+ apiKey: claimConsoleKey,
652
696
  claim: redeemed,
653
697
  });
654
698
  return;
@@ -735,8 +779,8 @@ Users purchase Muxo Credits (\`POST /api/v1/billing/topup\` or \`muxo billing to
735
779
  });
736
780
  return;
737
781
  }
738
- // Streamable HTTP MCP Endpoint (POST /mcp, GET /mcp, DELETE /mcp)
739
- if (pathname === "/mcp" && req.method === "GET") {
782
+ // Streamable HTTP MCP Endpoint (POST /mcp, GET /mcp, HEAD /mcp, DELETE /mcp)
783
+ if (pathname === "/mcp" && (req.method === "GET" || req.method === "HEAD")) {
740
784
  const accept = String(req.headers.accept || "");
741
785
  const sessionId = String(req.headers["mcp-session-id"] || "") ||
742
786
  `mcp_sess_${crypto.randomBytes(8).toString("hex")}`;
@@ -747,8 +791,11 @@ Users purchase Muxo Credits (\`POST /api/v1/billing/topup\` or \`muxo billing to
747
791
  Connection: "keep-alive",
748
792
  "Mcp-Session-Id": sessionId,
749
793
  "Access-Control-Allow-Origin": "*",
794
+ "Access-Control-Expose-Headers": "Mcp-Session-Id",
750
795
  });
751
- res.write(`event: endpoint\ndata: ${JSON.stringify({ uri: `${config.baseUrl}/mcp`, sessionId })}\n\n`);
796
+ if (req.method !== "HEAD") {
797
+ res.write(`event: endpoint\ndata: ${JSON.stringify({ uri: `${config.baseUrl}/mcp`, sessionId })}\n\n`);
798
+ }
752
799
  res.end();
753
800
  return;
754
801
  }
@@ -758,12 +805,12 @@ Users purchase Muxo Credits (\`POST /api/v1/billing/topup\` or \`muxo billing to
758
805
  protocolVersion: "2025-06-18",
759
806
  serverInfo: {
760
807
  name: "muxo-mcp-server",
761
- version: "1.2.3",
808
+ version: "1.3.1",
762
809
  },
763
810
  instructions: MUXO_MCP_SERVER_INSTRUCTIONS,
764
811
  toolsCount: MUXO_MCP_TOOLS.length,
765
812
  skillsCount: getMuxoMcpSkills().length,
766
- });
813
+ }, { "Mcp-Session-Id": sessionId });
767
814
  return;
768
815
  }
769
816
  if (pathname === "/mcp" && req.method === "DELETE") {
@@ -838,6 +885,7 @@ Users purchase Muxo Credits (\`POST /api/v1/billing/topup\` or \`muxo billing to
838
885
  landingUrl: `${config.baseUrl}/landing`,
839
886
  },
840
887
  apiKeys: store.listApiKeys(ctx.workspace.id),
888
+ byokKeys: store.listByokKeys(ctx.workspace.id),
841
889
  defaultApiKey: bootstrap.defaultApiKey || null,
842
890
  connections: store.listConnections(ctx.workspace.id),
843
891
  resources: store.listResources(ctx.workspace.id),
@@ -859,7 +907,12 @@ Users purchase Muxo Credits (\`POST /api/v1/billing/topup\` or \`muxo billing to
859
907
  email,
860
908
  baseUrl: config.baseUrl,
861
909
  });
862
- sendJson(res, 201, { ok: true, claim, ...claim });
910
+ sendJson(res, 201, {
911
+ ok: true,
912
+ claim: { ...claim, ownerEmail: email },
913
+ ...claim,
914
+ ownerEmail: email,
915
+ });
863
916
  return;
864
917
  }
865
918
  // Microsoft Agent Governance Status & Audit Verification
@@ -1041,7 +1094,11 @@ Users purchase Muxo Credits (\`POST /api/v1/billing/topup\` or \`muxo billing to
1041
1094
  const planId = decodeURIComponent(planExecuteMatch[1]);
1042
1095
  const plan = engine.getPlan(ctx, planId);
1043
1096
  const result = await engine.executePlanForRisk(ctx, planId, plan.riskLevel);
1044
- sendJson(res, 200, { ok: true, ...result });
1097
+ sendJson(res, 200, {
1098
+ ok: true,
1099
+ ...result,
1100
+ settlement: result.receipt?.supplierSettlement || null,
1101
+ });
1045
1102
  return;
1046
1103
  }
1047
1104
  // Runs & Receipts
@@ -1058,7 +1115,91 @@ Users purchase Muxo Credits (\`POST /api/v1/billing/topup\` or \`muxo billing to
1058
1115
  sendJson(res, 200, { ok: true, ...verified });
1059
1116
  return;
1060
1117
  }
1118
+ // BYOK (Bring Your Own Key) Encrypted Vault Management
1119
+ if (pathname === "/api/v1/byok" && req.method === "GET") {
1120
+ sendJson(res, 200, {
1121
+ ok: true,
1122
+ workspaceId: ctx.workspace.id,
1123
+ keys: store.listByokKeys(ctx.workspace.id),
1124
+ });
1125
+ return;
1126
+ }
1127
+ if (pathname === "/api/v1/byok" && req.method === "POST") {
1128
+ const body = JSON.parse((await readBody(req)) || "{}");
1129
+ const provider = String(body.provider || "").trim();
1130
+ const secretKey = String(body.secretKey || body.apiKey || body.key || "").trim();
1131
+ if (!provider || !secretKey) {
1132
+ sendJson(res, 400, {
1133
+ ok: false,
1134
+ error: "Both 'provider' and 'secretKey' are required",
1135
+ });
1136
+ return;
1137
+ }
1138
+ const record = store.setByokKey(ctx.workspace.id, provider, secretKey);
1139
+ sendJson(res, 201, {
1140
+ ok: true,
1141
+ key: record,
1142
+ keys: store.listByokKeys(ctx.workspace.id),
1143
+ });
1144
+ return;
1145
+ }
1146
+ if (pathname.startsWith("/api/v1/byok/") && req.method === "DELETE") {
1147
+ const provider = decodeURIComponent(pathname.slice("/api/v1/byok/".length));
1148
+ const deleted = store.deleteByokKey(ctx.workspace.id, provider);
1149
+ sendJson(res, 200, {
1150
+ ok: true,
1151
+ deleted,
1152
+ provider,
1153
+ keys: store.listByokKeys(ctx.workspace.id),
1154
+ });
1155
+ return;
1156
+ }
1157
+ // Natural Language Intent & Governed Execution Endpoint
1158
+ if ((pathname === "/api/v1/do" || pathname === "/v1/do") &&
1159
+ req.method === "POST") {
1160
+ const body = JSON.parse((await readBody(req)) || "{}");
1161
+ const prompt = String(body.prompt || body.instruction || body.query || body.command || "").trim();
1162
+ if (!prompt) {
1163
+ sendJson(res, 400, {
1164
+ ok: false,
1165
+ error: "Missing 'prompt' or 'instruction' in request body",
1166
+ });
1167
+ return;
1168
+ }
1169
+ const result = await engine.doNaturalLanguage(ctx, {
1170
+ prompt,
1171
+ input: body.input && typeof body.input === "object"
1172
+ ? body.input
1173
+ : undefined,
1174
+ autoApprove: body.autoApprove !== false,
1175
+ dryRun: body.dryRun === true,
1176
+ });
1177
+ sendJson(res, 200, result);
1178
+ return;
1179
+ }
1061
1180
  // Live Stripe Billing, Credit Top-Up & Supplier Settlement Ledger
1181
+ if (pathname === "/api/v1/billing/status" && req.method === "GET") {
1182
+ const ws = store.getWorkspace(ctx.workspace.id);
1183
+ const settlementSummary = store.getSupplierSettlementSummary(ctx.workspace.id);
1184
+ const byokKeys = store.listByokKeys(ctx.workspace.id);
1185
+ sendJson(res, 200, {
1186
+ ok: true,
1187
+ workspaceId: ws.id,
1188
+ workspace: ws,
1189
+ tier: ws.tier,
1190
+ creditsBalance: ws.creditsBalance,
1191
+ creditBalance: ws.creditsBalance,
1192
+ monthlyActionsUsed: ws.monthlyActionsUsed,
1193
+ monthlyActionsLimit: ws.monthlyActionsLimit,
1194
+ stripeConfigured: engine.stripeBilling.isConfigured,
1195
+ stripeCustomerId: ws.stripeCustomerId,
1196
+ stripeSubscriptionId: ws.stripeSubscriptionId,
1197
+ settlementSummary,
1198
+ byokKeys,
1199
+ entries: store.listLedgerEntries(ctx.workspace.id, 25),
1200
+ });
1201
+ return;
1202
+ }
1062
1203
  if (pathname === "/api/v1/billing/ledger" && req.method === "GET") {
1063
1204
  sendJson(res, 200, {
1064
1205
  ok: true,
@@ -1091,27 +1232,59 @@ Users purchase Muxo Credits (\`POST /api/v1/billing/topup\` or \`muxo billing to
1091
1232
  sendJson(res, 200, {
1092
1233
  ok: true,
1093
1234
  creditsAdded: credits,
1235
+ creditBalance: updatedWorkspace.creditsBalance,
1236
+ creditsBalance: updatedWorkspace.creditsBalance,
1094
1237
  usdPaid: Number(usdPaid),
1095
1238
  workspace: updatedWorkspace,
1096
1239
  settlementSummary: store.getSupplierSettlementSummary(ctx.workspace.id),
1097
1240
  });
1098
1241
  return;
1099
1242
  }
1243
+ if (pathname === "/api/v1/billing/upgrade" && req.method === "POST") {
1244
+ const body = JSON.parse((await readBody(req)) || "{}");
1245
+ const referenceId = String(body.referenceId || "").trim() ||
1246
+ `upgrade_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
1247
+ const bonusCredits = body.bonusCredits !== undefined ? Number(body.bonusCredits) : 1000;
1248
+ const updatedWorkspace = store.upgradeWorkspaceToStarter({
1249
+ workspaceId: ctx.workspace.id,
1250
+ stripeCustomerId: ctx.workspace.stripeCustomerId ||
1251
+ `cus_muxo_${ctx.workspace.id.slice(3, 11)}`,
1252
+ stripeSubscriptionId: ctx.workspace.stripeSubscriptionId ||
1253
+ `sub_muxo_${referenceId.slice(-10)}`,
1254
+ referenceId,
1255
+ bonusCredits,
1256
+ });
1257
+ sendJson(res, 200, {
1258
+ ok: true,
1259
+ tier: updatedWorkspace.tier,
1260
+ creditsBalance: updatedWorkspace.creditsBalance,
1261
+ creditBalance: updatedWorkspace.creditsBalance,
1262
+ workspace: updatedWorkspace,
1263
+ settlementSummary: store.getSupplierSettlementSummary(ctx.workspace.id),
1264
+ });
1265
+ return;
1266
+ }
1100
1267
  if (pathname === "/api/v1/billing/checkout" && req.method === "POST") {
1101
1268
  const body = JSON.parse((await readBody(req)) || "{}");
1102
1269
  const kind = body.kind === "credit_topup" ? "credit_topup" : "starter_subscription";
1270
+ const credits = body.credits ? Number(body.credits) : 1000;
1103
1271
  const session = await engine.stripeBilling.createCheckoutSession({
1104
1272
  workspace: ctx.workspace,
1105
1273
  customerEmail: ctx.user.email,
1106
1274
  kind,
1107
- returnBaseUrl: config.baseUrl,
1275
+ credits,
1276
+ returnBaseUrl: body.returnBaseUrl ? String(body.returnBaseUrl) : config.baseUrl,
1108
1277
  });
1109
1278
  sendJson(res, 200, { ok: true, ...session });
1110
1279
  return;
1111
1280
  }
1112
1281
  if (pathname === "/api/v1/billing/verify-session" && req.method === "POST") {
1113
1282
  const body = JSON.parse((await readBody(req)) || "{}");
1114
- const verified = await engine.stripeBilling.verifyAndFulfillCheckoutSession(String(body.sessionId || ""));
1283
+ const verified = await engine.stripeBilling.verifyAndFulfillCheckoutSession(String(body.sessionId || ""), ctx.workspace.id, body.kind === "credit_topup"
1284
+ ? "credit_topup"
1285
+ : body.kind === "starter_subscription"
1286
+ ? "starter_subscription"
1287
+ : undefined);
1115
1288
  sendJson(res, 200, { ok: true, ...verified });
1116
1289
  return;
1117
1290
  }
package/dist/store.d.ts CHANGED
@@ -1,5 +1,10 @@
1
1
  import { DatabaseSync } from "node:sqlite";
2
- import type { ActionPlan, ApiKeyRecord, ConnectionRecord, ExecutionReceipt, ExecutionRun, GovernanceDecisionRecord, GovernancePolicy, LedgerEntry, MemoryContextSummary, ProviderLane, ProvisionedResource, RiskLevel, SupplierSettlement, SupplierSettlementSummary, User, Workspace, WorkspaceMemoryRecord } from "./types.js";
2
+ import type { ActionPlan, ApiKeyRecord, ByokKeyRecord, ConnectionRecord, ExecutionReceipt, ExecutionRun, GovernanceDecisionRecord, GovernancePolicy, LedgerEntry, MemoryContextSummary, ProviderLane, ProvisionedResource, RiskLevel, SupplierSettlement, SupplierSettlementSummary, User, Workspace, WorkspaceMemoryRecord } from "./types.js";
3
+ export declare const BYOK_PROVIDER_CATALOG: Record<string, {
4
+ category: "llm" | "supplier";
5
+ envVarName: string;
6
+ label: string;
7
+ }>;
3
8
  export declare class MuxoStore {
4
9
  readonly db: DatabaseSync;
5
10
  private readonly vaultKey;
@@ -23,6 +28,7 @@ export declare class MuxoStore {
23
28
  user: User;
24
29
  workspace: Workspace;
25
30
  sessionToken: string;
31
+ apiKey: string;
26
32
  };
27
33
  loginUser(email: string, password: string): {
28
34
  user: User;
@@ -77,6 +83,16 @@ export declare class MuxoStore {
77
83
  getResource(workspaceId: string, resourceNameOrId: string): ProvisionedResource | null;
78
84
  listResources(workspaceId: string): ProvisionedResource[];
79
85
  getDecryptedWorkspaceEnv(workspaceId: string): Record<string, string>;
86
+ normalizeByokProvider(providerInput: string): {
87
+ provider: string;
88
+ category: "llm" | "supplier";
89
+ envVarName: string;
90
+ };
91
+ setByokKey(workspaceId: string, providerInput: string, secretKey: string): ByokKeyRecord;
92
+ getByokKey(workspaceId: string, providerInput: string): string | null;
93
+ deleteByokKey(workspaceId: string, providerInput: string): boolean;
94
+ listByokKeys(workspaceId: string): ByokKeyRecord[];
95
+ hasByokForLane(workspaceId: string, lane: ProviderLane, toolSlug?: string): boolean;
80
96
  createPlan(params: {
81
97
  workspaceId: string;
82
98
  actorId: string;
@@ -126,6 +142,7 @@ export declare class MuxoStore {
126
142
  stripeCustomerId?: string | null;
127
143
  stripeSubscriptionId?: string | null;
128
144
  referenceId: string;
145
+ bonusCredits?: number;
129
146
  }): Workspace;
130
147
  addWorkspaceCredits(params: {
131
148
  workspaceId: string;
@@ -142,7 +159,7 @@ export declare class MuxoStore {
142
159
  referenceId: string | null;
143
160
  description: string;
144
161
  }): LedgerEntry;
145
- computeSupplierSettlement(lane: ProviderLane, toolSlug: string, creditCost: number, settlementStatus?: "settled_by_muxo_master_wallet" | "planned_muxo_master_wallet"): SupplierSettlement;
162
+ computeSupplierSettlement(lane: ProviderLane, toolSlug: string, creditCost: number, settlementStatus?: "settled_by_muxo_master_wallet" | "planned_muxo_master_wallet" | "settled_by_customer_byok" | "planned_customer_byok", workspaceId?: string): SupplierSettlement;
146
163
  getSupplierSettlementSummary(workspaceId: string): SupplierSettlementSummary;
147
164
  listLedgerEntries(workspaceId: string, limit?: number): LedgerEntry[];
148
165
  saveMemoryRecord(params: {