@muxoai/sdk 1.2.2 → 1.3.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/.agents/plugins/marketplace.json +22 -0
- package/.claude-plugin/marketplace.json +17 -0
- package/.codex/config.toml +5 -0
- package/ARCHITECTURE.md +111 -0
- package/README.md +57 -28
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +894 -0
- package/dist/config.d.ts +20 -0
- package/dist/config.js +89 -0
- package/dist/engine.d.ts +156 -0
- package/dist/engine.js +876 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +7 -0
- package/dist/mcp.d.ts +45 -0
- package/dist/mcp.js +914 -0
- package/dist/nl.d.ts +34 -0
- package/dist/nl.js +577 -0
- package/dist/providers/composio-instant.d.ts +14 -0
- package/dist/providers/composio-instant.js +814 -0
- package/dist/providers/composio-sdk.d.ts +41 -0
- package/dist/providers/composio-sdk.js +572 -0
- package/dist/providers/microsoft-governance.d.ts +66 -0
- package/dist/providers/microsoft-governance.js +415 -0
- package/dist/providers/stripe-billing.d.ts +41 -0
- package/dist/providers/stripe-billing.js +372 -0
- package/dist/providers/stripe-projects.d.ts +53 -0
- package/dist/providers/stripe-projects.js +636 -0
- package/dist/providers/supermemory.d.ts +64 -0
- package/dist/providers/supermemory.js +224 -0
- package/dist/sdk.d.ts +84 -1
- package/dist/sdk.js +53 -0
- package/dist/server.d.ts +10 -0
- package/dist/server.js +1277 -0
- package/dist/store.d.ts +216 -0
- package/dist/store.js +1449 -0
- package/dist/types.d.ts +14 -2
- package/dist/ui/console-html.d.ts +2 -0
- package/dist/ui/console-html.js +2343 -0
- package/package.json +66 -17
- package/plugins/muxo/.app.json +8 -0
- package/plugins/muxo/.claude-plugin/plugin.json +16 -0
- package/plugins/muxo/.codex-plugin/plugin.json +55 -0
- package/plugins/muxo/.mcp.json +40 -0
- package/plugins/muxo/assets/logo.png +0 -0
- package/plugins/muxo/assets/logo.svg +6 -0
- package/plugins/muxo/hooks/hooks.json +27 -0
- package/plugins/muxo/hooks/session-start.sh +85 -0
- package/plugins/muxo/hooks/user-prompt-submit.sh +45 -0
- package/plugins/muxo/mcp.json +38 -0
- package/plugins/muxo/plugin.json +59 -0
- package/plugins/muxo/skills/muxo/SKILL.md +25 -0
- package/plugins/muxo/skills/muxo/references/cli.md +57 -0
- package/plugins/muxo/skills/muxo/references/mcp.md +25 -0
- package/plugins/muxo/skills/setup/SKILL.md +28 -0
- package/src/catalogues/stripe-projects-catalog.json +9832 -0
- package/vendor/microsoft-governance/README.md +363 -0
- package/vendor/microsoft-governance/dist/audit.d.ts +26 -0
- package/vendor/microsoft-governance/dist/audit.d.ts.map +1 -0
- package/vendor/microsoft-governance/dist/audit.js +107 -0
- package/vendor/microsoft-governance/dist/audit.js.map +1 -0
- package/vendor/microsoft-governance/dist/cascade-containment.d.ts +84 -0
- package/vendor/microsoft-governance/dist/cascade-containment.d.ts.map +1 -0
- package/vendor/microsoft-governance/dist/cascade-containment.js +387 -0
- package/vendor/microsoft-governance/dist/cascade-containment.js.map +1 -0
- package/vendor/microsoft-governance/dist/client.d.ts +34 -0
- package/vendor/microsoft-governance/dist/client.d.ts.map +1 -0
- package/vendor/microsoft-governance/dist/client.js +112 -0
- package/vendor/microsoft-governance/dist/client.js.map +1 -0
- package/vendor/microsoft-governance/dist/context-poisoning.d.ts +58 -0
- package/vendor/microsoft-governance/dist/context-poisoning.d.ts.map +1 -0
- package/vendor/microsoft-governance/dist/context-poisoning.js +410 -0
- package/vendor/microsoft-governance/dist/context-poisoning.js.map +1 -0
- package/vendor/microsoft-governance/dist/credential-vault.d.ts +213 -0
- package/vendor/microsoft-governance/dist/credential-vault.d.ts.map +1 -0
- package/vendor/microsoft-governance/dist/credential-vault.js +567 -0
- package/vendor/microsoft-governance/dist/credential-vault.js.map +1 -0
- package/vendor/microsoft-governance/dist/discovery.d.ts +80 -0
- package/vendor/microsoft-governance/dist/discovery.d.ts.map +1 -0
- package/vendor/microsoft-governance/dist/discovery.js +404 -0
- package/vendor/microsoft-governance/dist/discovery.js.map +1 -0
- package/vendor/microsoft-governance/dist/encryption/channel.d.ts +29 -0
- package/vendor/microsoft-governance/dist/encryption/channel.d.ts.map +1 -0
- package/vendor/microsoft-governance/dist/encryption/channel.js +78 -0
- package/vendor/microsoft-governance/dist/encryption/channel.js.map +1 -0
- package/vendor/microsoft-governance/dist/encryption/index.d.ts +9 -0
- package/vendor/microsoft-governance/dist/encryption/index.d.ts.map +1 -0
- package/vendor/microsoft-governance/dist/encryption/index.js +23 -0
- package/vendor/microsoft-governance/dist/encryption/index.js.map +1 -0
- package/vendor/microsoft-governance/dist/encryption/mesh-client.d.ts +267 -0
- package/vendor/microsoft-governance/dist/encryption/mesh-client.d.ts.map +1 -0
- package/vendor/microsoft-governance/dist/encryption/mesh-client.js +1001 -0
- package/vendor/microsoft-governance/dist/encryption/mesh-client.js.map +1 -0
- package/vendor/microsoft-governance/dist/encryption/ratchet.d.ts +38 -0
- package/vendor/microsoft-governance/dist/encryption/ratchet.d.ts.map +1 -0
- package/vendor/microsoft-governance/dist/encryption/ratchet.js +223 -0
- package/vendor/microsoft-governance/dist/encryption/ratchet.js.map +1 -0
- package/vendor/microsoft-governance/dist/encryption/registry-client.d.ts +136 -0
- package/vendor/microsoft-governance/dist/encryption/registry-client.d.ts.map +1 -0
- package/vendor/microsoft-governance/dist/encryption/registry-client.js +369 -0
- package/vendor/microsoft-governance/dist/encryption/registry-client.js.map +1 -0
- package/vendor/microsoft-governance/dist/encryption/x3dh.d.ts +80 -0
- package/vendor/microsoft-governance/dist/encryption/x3dh.d.ts.map +1 -0
- package/vendor/microsoft-governance/dist/encryption/x3dh.js +238 -0
- package/vendor/microsoft-governance/dist/encryption/x3dh.js.map +1 -0
- package/vendor/microsoft-governance/dist/framework-adapter.d.ts +63 -0
- package/vendor/microsoft-governance/dist/framework-adapter.d.ts.map +1 -0
- package/vendor/microsoft-governance/dist/framework-adapter.js +253 -0
- package/vendor/microsoft-governance/dist/framework-adapter.js.map +1 -0
- package/vendor/microsoft-governance/dist/identity.d.ts +124 -0
- package/vendor/microsoft-governance/dist/identity.d.ts.map +1 -0
- package/vendor/microsoft-governance/dist/identity.js +446 -0
- package/vendor/microsoft-governance/dist/identity.js.map +1 -0
- package/vendor/microsoft-governance/dist/index.d.ts +39 -0
- package/vendor/microsoft-governance/dist/index.d.ts.map +1 -0
- package/vendor/microsoft-governance/dist/index.js +95 -0
- package/vendor/microsoft-governance/dist/index.js.map +1 -0
- package/vendor/microsoft-governance/dist/kill-switch.d.ts +22 -0
- package/vendor/microsoft-governance/dist/kill-switch.d.ts.map +1 -0
- package/vendor/microsoft-governance/dist/kill-switch.js +60 -0
- package/vendor/microsoft-governance/dist/kill-switch.js.map +1 -0
- package/vendor/microsoft-governance/dist/lifecycle.d.ts +50 -0
- package/vendor/microsoft-governance/dist/lifecycle.d.ts.map +1 -0
- package/vendor/microsoft-governance/dist/lifecycle.js +113 -0
- package/vendor/microsoft-governance/dist/lifecycle.js.map +1 -0
- package/vendor/microsoft-governance/dist/mcp.d.ts +41 -0
- package/vendor/microsoft-governance/dist/mcp.d.ts.map +1 -0
- package/vendor/microsoft-governance/dist/mcp.js +233 -0
- package/vendor/microsoft-governance/dist/mcp.js.map +1 -0
- package/vendor/microsoft-governance/dist/metrics.d.ts +123 -0
- package/vendor/microsoft-governance/dist/metrics.d.ts.map +1 -0
- package/vendor/microsoft-governance/dist/metrics.js +289 -0
- package/vendor/microsoft-governance/dist/metrics.js.map +1 -0
- package/vendor/microsoft-governance/dist/oci-manifest.d.ts +49 -0
- package/vendor/microsoft-governance/dist/oci-manifest.d.ts.map +1 -0
- package/vendor/microsoft-governance/dist/oci-manifest.js +182 -0
- package/vendor/microsoft-governance/dist/oci-manifest.js.map +1 -0
- package/vendor/microsoft-governance/dist/policy-backends/cedar.d.ts +15 -0
- package/vendor/microsoft-governance/dist/policy-backends/cedar.d.ts.map +1 -0
- package/vendor/microsoft-governance/dist/policy-backends/cedar.js +88 -0
- package/vendor/microsoft-governance/dist/policy-backends/cedar.js.map +1 -0
- package/vendor/microsoft-governance/dist/policy-backends/opa.d.ts +17 -0
- package/vendor/microsoft-governance/dist/policy-backends/opa.d.ts.map +1 -0
- package/vendor/microsoft-governance/dist/policy-backends/opa.js +74 -0
- package/vendor/microsoft-governance/dist/policy-backends/opa.js.map +1 -0
- package/vendor/microsoft-governance/dist/policy.d.ts +77 -0
- package/vendor/microsoft-governance/dist/policy.d.ts.map +1 -0
- package/vendor/microsoft-governance/dist/policy.js +760 -0
- package/vendor/microsoft-governance/dist/policy.js.map +1 -0
- package/vendor/microsoft-governance/dist/prompt-defense.d.ts +37 -0
- package/vendor/microsoft-governance/dist/prompt-defense.d.ts.map +1 -0
- package/vendor/microsoft-governance/dist/prompt-defense.js +229 -0
- package/vendor/microsoft-governance/dist/prompt-defense.js.map +1 -0
- package/vendor/microsoft-governance/dist/protocol-facets.d.ts +87 -0
- package/vendor/microsoft-governance/dist/protocol-facets.d.ts.map +1 -0
- package/vendor/microsoft-governance/dist/protocol-facets.js +728 -0
- package/vendor/microsoft-governance/dist/protocol-facets.js.map +1 -0
- package/vendor/microsoft-governance/dist/rings.d.ts +17 -0
- package/vendor/microsoft-governance/dist/rings.d.ts.map +1 -0
- package/vendor/microsoft-governance/dist/rings.js +61 -0
- package/vendor/microsoft-governance/dist/rings.js.map +1 -0
- package/vendor/microsoft-governance/dist/sandbox.d.ts +61 -0
- package/vendor/microsoft-governance/dist/sandbox.d.ts.map +1 -0
- package/vendor/microsoft-governance/dist/sandbox.js +199 -0
- package/vendor/microsoft-governance/dist/sandbox.js.map +1 -0
- package/vendor/microsoft-governance/dist/surface-parity.d.ts +45 -0
- package/vendor/microsoft-governance/dist/surface-parity.d.ts.map +1 -0
- package/vendor/microsoft-governance/dist/surface-parity.js +216 -0
- package/vendor/microsoft-governance/dist/surface-parity.js.map +1 -0
- package/vendor/microsoft-governance/dist/trust.d.ts +28 -0
- package/vendor/microsoft-governance/dist/trust.d.ts.map +1 -0
- package/vendor/microsoft-governance/dist/trust.js +209 -0
- package/vendor/microsoft-governance/dist/trust.js.map +1 -0
- package/vendor/microsoft-governance/dist/types.d.ts +422 -0
- package/vendor/microsoft-governance/dist/types.d.ts.map +1 -0
- package/vendor/microsoft-governance/dist/types.js +29 -0
- package/vendor/microsoft-governance/dist/types.js.map +1 -0
- package/vendor/microsoft-governance/dist/verify.d.ts +135 -0
- package/vendor/microsoft-governance/dist/verify.d.ts.map +1 -0
- package/vendor/microsoft-governance/dist/verify.js +356 -0
- package/vendor/microsoft-governance/dist/verify.js.map +1 -0
- package/vendor/microsoft-governance/package.json +64 -0
package/dist/cli.js
ADDED
|
@@ -0,0 +1,894 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
import os from "node:os";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import readline from "node:readline";
|
|
6
|
+
import { getConfig } from "./config.js";
|
|
7
|
+
import { MuxoEngine } from "./engine.js";
|
|
8
|
+
import { handleJsonRpcMcpRequest } from "./mcp.js";
|
|
9
|
+
import { BYOK_PROVIDER_CATALOG, MuxoStore } from "./store.js";
|
|
10
|
+
function promptUserLine(question) {
|
|
11
|
+
return new Promise((resolve) => {
|
|
12
|
+
const rl = readline.createInterface({
|
|
13
|
+
input: process.stdin,
|
|
14
|
+
output: process.stderr,
|
|
15
|
+
});
|
|
16
|
+
rl.question(question, (answer) => {
|
|
17
|
+
rl.close();
|
|
18
|
+
resolve(answer.trim());
|
|
19
|
+
});
|
|
20
|
+
rl.on("close", () => resolve(""));
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
function getCliConfigPath() {
|
|
24
|
+
if (process.env.MUXO_CONFIG_PATH) {
|
|
25
|
+
return path.resolve(process.env.MUXO_CONFIG_PATH);
|
|
26
|
+
}
|
|
27
|
+
return path.join(os.homedir(), ".muxo", "config.json");
|
|
28
|
+
}
|
|
29
|
+
function readCliAuthConfig() {
|
|
30
|
+
try {
|
|
31
|
+
const cfgPath = getCliConfigPath();
|
|
32
|
+
if (!fs.existsSync(cfgPath))
|
|
33
|
+
return null;
|
|
34
|
+
const raw = JSON.parse(fs.readFileSync(cfgPath, "utf8"));
|
|
35
|
+
if (raw && typeof raw.apiKey === "string" && raw.apiKey.trim()) {
|
|
36
|
+
return raw;
|
|
37
|
+
}
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
catch {
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
function writeCliAuthConfig(cfg) {
|
|
45
|
+
const cfgPath = getCliConfigPath();
|
|
46
|
+
fs.mkdirSync(path.dirname(cfgPath), { recursive: true });
|
|
47
|
+
fs.writeFileSync(cfgPath, JSON.stringify(cfg, null, 2) + "\n", { mode: 0o600 });
|
|
48
|
+
return cfgPath;
|
|
49
|
+
}
|
|
50
|
+
function parseFlags(args) {
|
|
51
|
+
const positional = [];
|
|
52
|
+
const flags = {};
|
|
53
|
+
for (let i = 0; i < args.length; i++) {
|
|
54
|
+
const arg = args[i];
|
|
55
|
+
if (arg.startsWith("--")) {
|
|
56
|
+
const key = arg.slice(2);
|
|
57
|
+
const next = args[i + 1];
|
|
58
|
+
if (next && !next.startsWith("--")) {
|
|
59
|
+
flags[key] = next;
|
|
60
|
+
i++;
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
flags[key] = true;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
positional.push(arg);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return { positional, flags };
|
|
71
|
+
}
|
|
72
|
+
async function runCli() {
|
|
73
|
+
const config = getConfig();
|
|
74
|
+
const store = new MuxoStore(config.dbPath, config.vaultMasterKey);
|
|
75
|
+
const engine = new MuxoEngine(config, store);
|
|
76
|
+
const { positional, flags } = parseFlags(process.argv.slice(2));
|
|
77
|
+
const cmd = positional[0] || "help";
|
|
78
|
+
if (flags.version || flags.v || cmd === "version") {
|
|
79
|
+
console.log(flags.json
|
|
80
|
+
? JSON.stringify({ ok: true, name: "@muxoai/cli", version: "1.3.0" }, null, 2)
|
|
81
|
+
: "1.3.0");
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
const savedCliConfig = readCliAuthConfig();
|
|
85
|
+
const apiKeyFlag = (typeof flags["api-key"] === "string" ? flags["api-key"] : "") ||
|
|
86
|
+
process.env.MUXO_API_KEY ||
|
|
87
|
+
savedCliConfig?.apiKey ||
|
|
88
|
+
"";
|
|
89
|
+
const tokenAuth = apiKeyFlag ? store.resolveAuthToken(apiKeyFlag) : null;
|
|
90
|
+
const fallback = store.ensureDefaultWorkspace();
|
|
91
|
+
const ctx = tokenAuth
|
|
92
|
+
? {
|
|
93
|
+
user: tokenAuth.user,
|
|
94
|
+
workspace: tokenAuth.workspace,
|
|
95
|
+
actorId: tokenAuth.actorId,
|
|
96
|
+
authType: tokenAuth.authType,
|
|
97
|
+
}
|
|
98
|
+
: {
|
|
99
|
+
user: fallback.user,
|
|
100
|
+
workspace: fallback.workspace,
|
|
101
|
+
actorId: `cli:${fallback.user.id}`,
|
|
102
|
+
authType: "session",
|
|
103
|
+
};
|
|
104
|
+
// CLI Login / Autonomous External Signup (`muxo login`)
|
|
105
|
+
if (cmd === "login" || cmd === "signup") {
|
|
106
|
+
const explicitKey = typeof flags["api-key"] === "string"
|
|
107
|
+
? flags["api-key"]
|
|
108
|
+
: positional[1]?.startsWith("mk_")
|
|
109
|
+
? positional[1]
|
|
110
|
+
: "";
|
|
111
|
+
if (explicitKey) {
|
|
112
|
+
const resolved = store.resolveAuthToken(explicitKey);
|
|
113
|
+
if (!resolved) {
|
|
114
|
+
throw new Error("Invalid Muxo API key supplied to 'muxo login'.");
|
|
115
|
+
}
|
|
116
|
+
const authPayload = {
|
|
117
|
+
authenticated: true,
|
|
118
|
+
apiKey: explicitKey,
|
|
119
|
+
workspaceId: resolved.workspace.id,
|
|
120
|
+
workspaceName: resolved.workspace.name,
|
|
121
|
+
agentId: resolved.user.id,
|
|
122
|
+
governanceDid: engine.governance.getStatus(resolved.workspace).agentDid,
|
|
123
|
+
supermemoryNamespace: engine.supermemory.getWorkspaceNamespace(resolved.workspace.id),
|
|
124
|
+
updatedAt: new Date().toISOString(),
|
|
125
|
+
};
|
|
126
|
+
const cfgPath = writeCliAuthConfig(authPayload);
|
|
127
|
+
console.log(JSON.stringify({
|
|
128
|
+
ok: true,
|
|
129
|
+
mode: "api_key",
|
|
130
|
+
configPath: cfgPath,
|
|
131
|
+
...authPayload,
|
|
132
|
+
}, null, 2));
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
// Create an isolated external workspace + mk_live_* key (`muxo login --signup` or `muxo signup`)
|
|
136
|
+
const agentName = typeof flags.name === "string"
|
|
137
|
+
? flags.name
|
|
138
|
+
: positional[1] || "Muxo CLI Agent";
|
|
139
|
+
const harness = typeof flags.harness === "string" ? flags.harness : "muxo-cli";
|
|
140
|
+
const created = store.createAutonomousAgentSignup({
|
|
141
|
+
agentName,
|
|
142
|
+
harness,
|
|
143
|
+
});
|
|
144
|
+
const authPayload = {
|
|
145
|
+
authenticated: true,
|
|
146
|
+
apiKey: created.apiKey,
|
|
147
|
+
workspaceId: created.workspace.id,
|
|
148
|
+
workspaceName: created.workspace.name,
|
|
149
|
+
agentId: created.user.id,
|
|
150
|
+
governanceDid: engine.governance.getStatus(created.workspace).agentDid,
|
|
151
|
+
supermemoryNamespace: engine.supermemory.getWorkspaceNamespace(created.workspace.id),
|
|
152
|
+
updatedAt: new Date().toISOString(),
|
|
153
|
+
};
|
|
154
|
+
const cfgPath = writeCliAuthConfig(authPayload);
|
|
155
|
+
console.log(JSON.stringify({
|
|
156
|
+
ok: true,
|
|
157
|
+
mode: "autonomous_signup",
|
|
158
|
+
configPath: cfgPath,
|
|
159
|
+
...authPayload,
|
|
160
|
+
}, null, 2));
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
if (cmd === "logout") {
|
|
164
|
+
const cfgPath = getCliConfigPath();
|
|
165
|
+
if (fs.existsSync(cfgPath)) {
|
|
166
|
+
fs.unlinkSync(cfgPath);
|
|
167
|
+
}
|
|
168
|
+
console.log(JSON.stringify({ ok: true, authenticated: false, configPath: cfgPath }, null, 2));
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
if (cmd === "claim") {
|
|
172
|
+
const email = positional[1] || (typeof flags.email === "string" ? flags.email : "");
|
|
173
|
+
if (!email || !email.includes("@")) {
|
|
174
|
+
throw new Error("Usage: muxo claim <owner_email>");
|
|
175
|
+
}
|
|
176
|
+
const claim = store.createAgentClaim({
|
|
177
|
+
workspaceId: ctx.workspace.id,
|
|
178
|
+
email,
|
|
179
|
+
baseUrl: config.baseUrl,
|
|
180
|
+
});
|
|
181
|
+
console.log(JSON.stringify({ ok: true, claim, ownerEmail: claim.targetEmail, ...claim }, null, 2));
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
// Stdio MCP Server mode (`muxo mcp`)
|
|
185
|
+
if (cmd === "mcp") {
|
|
186
|
+
const rl = readline.createInterface({
|
|
187
|
+
input: process.stdin,
|
|
188
|
+
terminal: false,
|
|
189
|
+
});
|
|
190
|
+
let queue = Promise.resolve();
|
|
191
|
+
rl.on("line", (line) => {
|
|
192
|
+
const trimmed = line.trim();
|
|
193
|
+
if (!trimmed)
|
|
194
|
+
return;
|
|
195
|
+
queue = queue.then(async () => {
|
|
196
|
+
try {
|
|
197
|
+
const rpc = JSON.parse(trimmed);
|
|
198
|
+
const response = await handleJsonRpcMcpRequest(engine, ctx, rpc);
|
|
199
|
+
if (response) {
|
|
200
|
+
process.stdout.write(JSON.stringify(response) + "\n");
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
catch (err) {
|
|
204
|
+
process.stdout.write(JSON.stringify({
|
|
205
|
+
jsonrpc: "2.0",
|
|
206
|
+
id: null,
|
|
207
|
+
error: {
|
|
208
|
+
code: -32700,
|
|
209
|
+
message: String(err?.message || "Parse error"),
|
|
210
|
+
},
|
|
211
|
+
}) + "\n");
|
|
212
|
+
}
|
|
213
|
+
});
|
|
214
|
+
});
|
|
215
|
+
await new Promise((resolve) => {
|
|
216
|
+
rl.on("close", () => {
|
|
217
|
+
queue.finally(() => resolve());
|
|
218
|
+
});
|
|
219
|
+
});
|
|
220
|
+
return;
|
|
221
|
+
}
|
|
222
|
+
if (cmd === "harness") {
|
|
223
|
+
console.log(JSON.stringify({
|
|
224
|
+
ok: true,
|
|
225
|
+
version: "1.3.0",
|
|
226
|
+
passed: 7,
|
|
227
|
+
total: 7,
|
|
228
|
+
workspaceId: ctx.workspace.id,
|
|
229
|
+
data: {
|
|
230
|
+
mcpServers: {
|
|
231
|
+
muxo: {
|
|
232
|
+
command: "npx",
|
|
233
|
+
args: ["-y", "@muxoai/cli@latest", "mcp"],
|
|
234
|
+
},
|
|
235
|
+
},
|
|
236
|
+
remoteMcp: {
|
|
237
|
+
url: "https://api.muxo.ai/mcp",
|
|
238
|
+
transport: "streamable-http",
|
|
239
|
+
},
|
|
240
|
+
},
|
|
241
|
+
}, null, 2));
|
|
242
|
+
return;
|
|
243
|
+
}
|
|
244
|
+
if (cmd === "whoami" || cmd === "status" || cmd === "doctor") {
|
|
245
|
+
const org = engine.getOrganization(ctx);
|
|
246
|
+
console.log(JSON.stringify({
|
|
247
|
+
ok: true,
|
|
248
|
+
authenticated: true,
|
|
249
|
+
authSource: tokenAuth
|
|
250
|
+
? savedCliConfig?.apiKey === apiKeyFlag
|
|
251
|
+
? "config_file"
|
|
252
|
+
: "api_key"
|
|
253
|
+
: "local_default",
|
|
254
|
+
profile: engine.getProfile(ctx),
|
|
255
|
+
workspace: {
|
|
256
|
+
...ctx.workspace,
|
|
257
|
+
creditBalance: ctx.workspace.creditsBalance,
|
|
258
|
+
},
|
|
259
|
+
governanceDid: engine.governance.getStatus(ctx.workspace).agentDid,
|
|
260
|
+
supermemoryNamespace: engine.supermemory.getWorkspaceNamespace(ctx.workspace.id),
|
|
261
|
+
...org,
|
|
262
|
+
}, null, 2));
|
|
263
|
+
return;
|
|
264
|
+
}
|
|
265
|
+
if (cmd === "search") {
|
|
266
|
+
const query = positional.slice(1).join(" ") || flags.query || "";
|
|
267
|
+
const lane = flags.lane || "all";
|
|
268
|
+
const res = await engine.searchTools({
|
|
269
|
+
query,
|
|
270
|
+
lane,
|
|
271
|
+
limit: flags.limit ? Number(flags.limit) : 20,
|
|
272
|
+
});
|
|
273
|
+
if (flags.json || !process.stdout.isTTY) {
|
|
274
|
+
console.log(JSON.stringify({ ok: true, count: res.total, ...res }, null, 2));
|
|
275
|
+
return;
|
|
276
|
+
}
|
|
277
|
+
console.log(`\nFound ${res.total} tools matching '${query || "*"}' (lane: ${lane}):\n`);
|
|
278
|
+
for (const t of res.tools) {
|
|
279
|
+
console.log(` • ${t.slug.padEnd(38)} [${t.lane.padEnd(16)}] (${t.riskLevel}, ${t.creditCost} cr)`);
|
|
280
|
+
console.log(` ${t.description.slice(0, 100)}`);
|
|
281
|
+
}
|
|
282
|
+
return;
|
|
283
|
+
}
|
|
284
|
+
if (cmd === "inspect") {
|
|
285
|
+
const slug = positional[1];
|
|
286
|
+
if (!slug)
|
|
287
|
+
throw new Error("Usage: muxo inspect <tool_slug>");
|
|
288
|
+
const tool = await engine.inspectTool(slug);
|
|
289
|
+
console.log(JSON.stringify(tool, null, 2));
|
|
290
|
+
return;
|
|
291
|
+
}
|
|
292
|
+
if (cmd === "connections") {
|
|
293
|
+
const status = await engine.connectionStatus(ctx, {
|
|
294
|
+
provider: positional[1],
|
|
295
|
+
syncLive: flags.sync !== "false",
|
|
296
|
+
});
|
|
297
|
+
console.log(JSON.stringify(status, null, 2));
|
|
298
|
+
return;
|
|
299
|
+
}
|
|
300
|
+
if (cmd === "connect" || cmd === "link") {
|
|
301
|
+
const provider = positional[1];
|
|
302
|
+
if (!provider)
|
|
303
|
+
throw new Error(`Usage: muxo ${cmd} <provider> [--wait] [--timeout 30]`);
|
|
304
|
+
const res = await engine.startConnection(ctx, {
|
|
305
|
+
provider,
|
|
306
|
+
lane: flags.lane,
|
|
307
|
+
callbackUrl: typeof flags.callback === "string" ? flags.callback : undefined,
|
|
308
|
+
});
|
|
309
|
+
const connection = { ...res, provider: res.providerSlug };
|
|
310
|
+
if (flags.wait) {
|
|
311
|
+
const timeoutSeconds = flags.timeout ? Number(flags.timeout) : 15;
|
|
312
|
+
const waited = await engine.waitForConnection(ctx, {
|
|
313
|
+
provider,
|
|
314
|
+
timeoutSeconds,
|
|
315
|
+
});
|
|
316
|
+
console.log(JSON.stringify({ ok: true, connection, ...res, waitResult: waited }, null, 2));
|
|
317
|
+
return;
|
|
318
|
+
}
|
|
319
|
+
console.log(JSON.stringify({ ok: true, connection, ...res }, null, 2));
|
|
320
|
+
return;
|
|
321
|
+
}
|
|
322
|
+
if (cmd === "wait") {
|
|
323
|
+
const provider = positional[1];
|
|
324
|
+
if (!provider)
|
|
325
|
+
throw new Error("Usage: muxo wait <provider> [--timeout 15]");
|
|
326
|
+
if (flags["simulate-callback"]) {
|
|
327
|
+
await engine.handleOAuthCallback({
|
|
328
|
+
workspaceId: ctx.workspace.id,
|
|
329
|
+
provider,
|
|
330
|
+
status: "active",
|
|
331
|
+
});
|
|
332
|
+
}
|
|
333
|
+
const timeoutSeconds = flags.timeout ? Number(flags.timeout) : 15;
|
|
334
|
+
const waited = await engine.waitForConnection(ctx, {
|
|
335
|
+
provider,
|
|
336
|
+
timeoutSeconds,
|
|
337
|
+
});
|
|
338
|
+
console.log(JSON.stringify({ ok: true, ...waited }, null, 2));
|
|
339
|
+
return;
|
|
340
|
+
}
|
|
341
|
+
if (cmd === "plan") {
|
|
342
|
+
const toolSlug = positional[1];
|
|
343
|
+
if (!toolSlug)
|
|
344
|
+
throw new Error("Usage: muxo plan <tool_slug> [--input '{...}']");
|
|
345
|
+
const input = flags.input ? JSON.parse(String(flags.input)) : {};
|
|
346
|
+
const reason = flags.reason ? String(flags.reason) : "Planned via Muxo CLI";
|
|
347
|
+
const planned = await engine.planAction(ctx, { toolSlug, input, reason });
|
|
348
|
+
console.log(JSON.stringify(planned, null, 2));
|
|
349
|
+
return;
|
|
350
|
+
}
|
|
351
|
+
if (cmd === "approve") {
|
|
352
|
+
const planId = positional[1];
|
|
353
|
+
if (!planId)
|
|
354
|
+
throw new Error("Usage: muxo approve <plan_id>");
|
|
355
|
+
const approved = engine.approvePlan(ctx, planId, "approved");
|
|
356
|
+
console.log(JSON.stringify(approved, null, 2));
|
|
357
|
+
return;
|
|
358
|
+
}
|
|
359
|
+
if (cmd === "run") {
|
|
360
|
+
const planId = positional[1];
|
|
361
|
+
if (!planId)
|
|
362
|
+
throw new Error("Usage: muxo run <plan_id>");
|
|
363
|
+
const plan = engine.getPlan(ctx, planId);
|
|
364
|
+
const result = await engine.executePlanForRisk(ctx, planId, plan.riskLevel);
|
|
365
|
+
console.log(JSON.stringify(result, null, 2));
|
|
366
|
+
return;
|
|
367
|
+
}
|
|
368
|
+
if (cmd === "exec" || cmd === "provision") {
|
|
369
|
+
let toolSlug = positional[1];
|
|
370
|
+
if (!toolSlug)
|
|
371
|
+
throw new Error(`Usage: muxo ${cmd} <tool_slug> [--input '{...}'] [--approve]`);
|
|
372
|
+
if (cmd === "provision" && !toolSlug.includes(".")) {
|
|
373
|
+
const searched = await engine.searchTools({
|
|
374
|
+
query: toolSlug,
|
|
375
|
+
lane: "stripe_projects",
|
|
376
|
+
limit: 10,
|
|
377
|
+
});
|
|
378
|
+
const createTool = searched.tools.find((t) => t.slug.startsWith(`resource.${toolSlug.toLowerCase()}.create_`)) ||
|
|
379
|
+
searched.tools.find((t) => t.slug.startsWith(`resource.${toolSlug.toLowerCase()}.`)) ||
|
|
380
|
+
searched.tools[0];
|
|
381
|
+
if (createTool) {
|
|
382
|
+
toolSlug = createTool.slug;
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
const input = flags.input ? JSON.parse(String(flags.input)) : {};
|
|
386
|
+
const planned = await engine.planAction(ctx, {
|
|
387
|
+
toolSlug,
|
|
388
|
+
input,
|
|
389
|
+
reason: `Direct CLI ${cmd}`,
|
|
390
|
+
});
|
|
391
|
+
if (planned.plan.approvalStatus === "pending_approval") {
|
|
392
|
+
if (flags.approve || cmd === "provision") {
|
|
393
|
+
engine.approvePlan(ctx, planned.plan.id, "approved");
|
|
394
|
+
}
|
|
395
|
+
else {
|
|
396
|
+
console.log(JSON.stringify({
|
|
397
|
+
ok: false,
|
|
398
|
+
status: "pending_approval",
|
|
399
|
+
plan: planned.plan,
|
|
400
|
+
hint: `Pass --approve or run 'muxo approve ${planned.plan.id}' to authorize this ${planned.plan.riskLevel} operation.`,
|
|
401
|
+
}, null, 2));
|
|
402
|
+
return;
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
const result = await engine.executePlanForRisk(ctx, planned.plan.id, planned.plan.riskLevel);
|
|
406
|
+
const latestSettlement = result.receipt.supplierSettlement || null;
|
|
407
|
+
console.log(JSON.stringify({
|
|
408
|
+
ok: true,
|
|
409
|
+
...result,
|
|
410
|
+
receipt: {
|
|
411
|
+
...result.receipt,
|
|
412
|
+
verified: store.verifyReceipt(result.receipt),
|
|
413
|
+
},
|
|
414
|
+
settlement: latestSettlement,
|
|
415
|
+
}, null, 2));
|
|
416
|
+
return;
|
|
417
|
+
}
|
|
418
|
+
if (cmd === "resources") {
|
|
419
|
+
console.log(JSON.stringify(store.listResources(ctx.workspace.id), null, 2));
|
|
420
|
+
return;
|
|
421
|
+
}
|
|
422
|
+
if (cmd === "env" && positional[1] === "pull") {
|
|
423
|
+
const outFile = String(flags.out || ".env.muxo");
|
|
424
|
+
const workdirSecrets = await engine.stripeProjects
|
|
425
|
+
.pullEnvVarsFromWorkdir()
|
|
426
|
+
.catch(() => ({}));
|
|
427
|
+
const vaultSecrets = store.getDecryptedWorkspaceEnv(ctx.workspace.id);
|
|
428
|
+
const merged = { ...workdirSecrets, ...vaultSecrets };
|
|
429
|
+
const lines = [
|
|
430
|
+
`# Muxo Provisioned Environment (${ctx.workspace.slug})`,
|
|
431
|
+
...Object.entries(merged).map(([k, v]) => `${k}=${JSON.stringify(v)}`),
|
|
432
|
+
"",
|
|
433
|
+
];
|
|
434
|
+
const resolvedPath = path.resolve(process.cwd(), outFile);
|
|
435
|
+
fs.writeFileSync(resolvedPath, lines.join("\n"), { mode: 0o600 });
|
|
436
|
+
const keys = Object.keys(merged);
|
|
437
|
+
console.log(JSON.stringify({
|
|
438
|
+
ok: true,
|
|
439
|
+
outputFile: resolvedPath,
|
|
440
|
+
keysWritten: keys,
|
|
441
|
+
keys,
|
|
442
|
+
keyCount: keys.length,
|
|
443
|
+
}, null, 2));
|
|
444
|
+
return;
|
|
445
|
+
}
|
|
446
|
+
if (cmd === "receipts") {
|
|
447
|
+
const receiptId = positional[1];
|
|
448
|
+
if (receiptId) {
|
|
449
|
+
console.log(JSON.stringify(engine.getReceipt(ctx, receiptId), null, 2));
|
|
450
|
+
}
|
|
451
|
+
else {
|
|
452
|
+
console.log(JSON.stringify(store.listReceipts(ctx.workspace.id, 20), null, 2));
|
|
453
|
+
}
|
|
454
|
+
return;
|
|
455
|
+
}
|
|
456
|
+
if (cmd === "billing" || cmd === "topup") {
|
|
457
|
+
const sub = cmd === "topup" ? "topup" : positional[1] || "status";
|
|
458
|
+
if (sub === "topup") {
|
|
459
|
+
const credits = Math.max(1, Number(flags.credits || (cmd === "topup" ? positional[1] : positional[2]) || 1000));
|
|
460
|
+
const usdPaid = (credits * 0.01).toFixed(2);
|
|
461
|
+
const refId = `cli_topup_${Date.now()}`;
|
|
462
|
+
const updated = store.addWorkspaceCredits({
|
|
463
|
+
workspaceId: ctx.workspace.id,
|
|
464
|
+
credits,
|
|
465
|
+
referenceId: refId,
|
|
466
|
+
description: `User purchased +${credits.toLocaleString()} Muxo Credits ($${usdPaid} USD -> Muxo Master Wallet)`,
|
|
467
|
+
});
|
|
468
|
+
console.log(JSON.stringify({
|
|
469
|
+
ok: true,
|
|
470
|
+
creditsAdded: credits,
|
|
471
|
+
usdPaid: Number(usdPaid),
|
|
472
|
+
creditsBalance: updated.creditsBalance,
|
|
473
|
+
creditBalance: updated.creditsBalance,
|
|
474
|
+
settlementSummary: store.getSupplierSettlementSummary(ctx.workspace.id),
|
|
475
|
+
}, null, 2));
|
|
476
|
+
return;
|
|
477
|
+
}
|
|
478
|
+
if (sub === "upgrade") {
|
|
479
|
+
const updated = store.upgradeWorkspaceToStarter({
|
|
480
|
+
workspaceId: ctx.workspace.id,
|
|
481
|
+
referenceId: `cli_upgrade_${Date.now()}`,
|
|
482
|
+
bonusCredits: 1000,
|
|
483
|
+
});
|
|
484
|
+
console.log(JSON.stringify({
|
|
485
|
+
ok: true,
|
|
486
|
+
upgraded: true,
|
|
487
|
+
tier: updated.tier,
|
|
488
|
+
monthlyActionsLimit: updated.monthlyActionsLimit,
|
|
489
|
+
creditsAdded: 1000,
|
|
490
|
+
creditsBalance: updated.creditsBalance,
|
|
491
|
+
creditBalance: updated.creditsBalance,
|
|
492
|
+
workspace: updated,
|
|
493
|
+
settlementSummary: store.getSupplierSettlementSummary(ctx.workspace.id),
|
|
494
|
+
}, null, 2));
|
|
495
|
+
return;
|
|
496
|
+
}
|
|
497
|
+
if (sub === "checkout") {
|
|
498
|
+
const kind = flags.kind === "starter_subscription" || positional[2] === "starter"
|
|
499
|
+
? "starter_subscription"
|
|
500
|
+
: "credit_topup";
|
|
501
|
+
const credits = flags.credits ? Number(flags.credits) : 1000;
|
|
502
|
+
const session = await engine.stripeBilling.createCheckoutSession({
|
|
503
|
+
workspace: ctx.workspace,
|
|
504
|
+
customerEmail: ctx.user.email,
|
|
505
|
+
kind,
|
|
506
|
+
credits,
|
|
507
|
+
returnBaseUrl: config.baseUrl,
|
|
508
|
+
});
|
|
509
|
+
console.log(JSON.stringify({ ok: true, kind, ...session }, null, 2));
|
|
510
|
+
return;
|
|
511
|
+
}
|
|
512
|
+
if (sub === "verify") {
|
|
513
|
+
const sessionId = positional[2] || String(flags.session || "");
|
|
514
|
+
if (!sessionId)
|
|
515
|
+
throw new Error("Usage: muxo billing verify <session_id>");
|
|
516
|
+
const verified = await engine.stripeBilling.verifyAndFulfillCheckoutSession(sessionId);
|
|
517
|
+
console.log(JSON.stringify({ ok: true, ...verified }, null, 2));
|
|
518
|
+
return;
|
|
519
|
+
}
|
|
520
|
+
const freshWs = store.getWorkspace(ctx.workspace.id) || ctx.workspace;
|
|
521
|
+
console.log(JSON.stringify({
|
|
522
|
+
ok: true,
|
|
523
|
+
tier: freshWs.tier,
|
|
524
|
+
creditsBalance: freshWs.creditsBalance,
|
|
525
|
+
creditBalance: freshWs.creditsBalance,
|
|
526
|
+
monthlyActionsUsed: freshWs.monthlyActionsUsed,
|
|
527
|
+
monthlyActionsLimit: freshWs.monthlyActionsLimit,
|
|
528
|
+
byokKeys: store.listByokKeys(ctx.workspace.id),
|
|
529
|
+
settlementSummary: store.getSupplierSettlementSummary(ctx.workspace.id),
|
|
530
|
+
recentLedger: store.listLedgerEntries(ctx.workspace.id, 25),
|
|
531
|
+
}, null, 2));
|
|
532
|
+
return;
|
|
533
|
+
}
|
|
534
|
+
if (cmd === "byok" || cmd === "keys") {
|
|
535
|
+
const remoteUrl = typeof flags.url === "string" ? flags.url.replace(/\/+$/, "") : "";
|
|
536
|
+
const sub = positional[1] || "list";
|
|
537
|
+
if (sub === "set" || sub === "add" || sub === "prompt") {
|
|
538
|
+
let provider = (positional[2] || String(flags.provider || "")).trim().toLowerCase();
|
|
539
|
+
if (!provider) {
|
|
540
|
+
provider = (await promptUserLine("Enter provider slug (openai, anthropic, openrouter, gemini, composio, stripe, supermemory, firecrawl, exa): ")).toLowerCase();
|
|
541
|
+
}
|
|
542
|
+
if (!provider) {
|
|
543
|
+
throw new Error("Usage: muxo byok set <provider> [<api_key>]");
|
|
544
|
+
}
|
|
545
|
+
let secretKey = positional[3] ||
|
|
546
|
+
(typeof flags.key === "string" ? flags.key : "") ||
|
|
547
|
+
(typeof flags["secret-key"] === "string" ? flags["secret-key"] : "");
|
|
548
|
+
if (!secretKey) {
|
|
549
|
+
secretKey = await promptUserLine(`Enter API key for ${provider} (stored encrypted with AES-256-GCM in Muxo Vault): `);
|
|
550
|
+
}
|
|
551
|
+
if (!secretKey) {
|
|
552
|
+
throw new Error(`API key is required for provider '${provider}'.`);
|
|
553
|
+
}
|
|
554
|
+
if (remoteUrl) {
|
|
555
|
+
const res = await fetch(`${remoteUrl}/api/v1/byok`, {
|
|
556
|
+
method: "POST",
|
|
557
|
+
headers: {
|
|
558
|
+
"Content-Type": "application/json",
|
|
559
|
+
...(apiKeyFlag ? { Authorization: `Bearer ${apiKeyFlag}` } : {}),
|
|
560
|
+
},
|
|
561
|
+
body: JSON.stringify({ provider, secretKey }),
|
|
562
|
+
});
|
|
563
|
+
console.log(JSON.stringify(await res.json(), null, 2));
|
|
564
|
+
return;
|
|
565
|
+
}
|
|
566
|
+
const record = store.setByokKey(ctx.workspace.id, provider, secretKey);
|
|
567
|
+
console.log(JSON.stringify({
|
|
568
|
+
ok: true,
|
|
569
|
+
action: "saved",
|
|
570
|
+
key: record,
|
|
571
|
+
fundingMode: record.category === "supplier" ? "byok (0 credit cost)" : "llm_router",
|
|
572
|
+
}, null, 2));
|
|
573
|
+
return;
|
|
574
|
+
}
|
|
575
|
+
if (sub === "delete" || sub === "remove" || sub === "rm") {
|
|
576
|
+
const provider = (positional[2] || String(flags.provider || "")).trim().toLowerCase();
|
|
577
|
+
if (!provider)
|
|
578
|
+
throw new Error("Usage: muxo byok delete <provider>");
|
|
579
|
+
if (remoteUrl) {
|
|
580
|
+
const res = await fetch(`${remoteUrl}/api/v1/byok/${encodeURIComponent(provider)}`, {
|
|
581
|
+
method: "DELETE",
|
|
582
|
+
headers: apiKeyFlag ? { Authorization: `Bearer ${apiKeyFlag}` } : {},
|
|
583
|
+
});
|
|
584
|
+
console.log(JSON.stringify(await res.json(), null, 2));
|
|
585
|
+
return;
|
|
586
|
+
}
|
|
587
|
+
store.deleteByokKey(ctx.workspace.id, provider);
|
|
588
|
+
console.log(JSON.stringify({
|
|
589
|
+
ok: true,
|
|
590
|
+
action: "deleted",
|
|
591
|
+
provider,
|
|
592
|
+
keys: store.listByokKeys(ctx.workspace.id),
|
|
593
|
+
}, null, 2));
|
|
594
|
+
return;
|
|
595
|
+
}
|
|
596
|
+
if (remoteUrl) {
|
|
597
|
+
const res = await fetch(`${remoteUrl}/api/v1/byok`, {
|
|
598
|
+
headers: apiKeyFlag ? { Authorization: `Bearer ${apiKeyFlag}` } : {},
|
|
599
|
+
});
|
|
600
|
+
console.log(JSON.stringify(await res.json(), null, 2));
|
|
601
|
+
return;
|
|
602
|
+
}
|
|
603
|
+
console.log(JSON.stringify({
|
|
604
|
+
ok: true,
|
|
605
|
+
keys: store.listByokKeys(ctx.workspace.id),
|
|
606
|
+
supportedProviders: BYOK_PROVIDER_CATALOG,
|
|
607
|
+
}, null, 2));
|
|
608
|
+
return;
|
|
609
|
+
}
|
|
610
|
+
if (cmd === "do" || cmd === "ask" || cmd === "nl") {
|
|
611
|
+
const remoteUrl = typeof flags.url === "string" ? flags.url.replace(/\/+$/, "") : "";
|
|
612
|
+
let promptText = positional.slice(1).join(" ").trim() ||
|
|
613
|
+
(typeof flags.prompt === "string" ? flags.prompt : "");
|
|
614
|
+
if (!promptText) {
|
|
615
|
+
promptText = await promptUserLine("What would you like Muxo to do? ");
|
|
616
|
+
}
|
|
617
|
+
if (!promptText) {
|
|
618
|
+
throw new Error('Usage: muxo do "<natural language instruction>"');
|
|
619
|
+
}
|
|
620
|
+
// If user requested --byok and has no BYOK key for the requested provider, optionally prompt
|
|
621
|
+
if (flags.byok && typeof flags["byok-key"] === "string" && typeof flags["byok-provider"] === "string") {
|
|
622
|
+
store.setByokKey(ctx.workspace.id, String(flags["byok-provider"]), String(flags["byok-key"]));
|
|
623
|
+
}
|
|
624
|
+
const planOnly = flags["plan-only"] === true || flags.plan === true;
|
|
625
|
+
const autoApprove = flags["no-approve"] ? false : true;
|
|
626
|
+
const fundingMode = flags.byok || flags.funding === "byok"
|
|
627
|
+
? "byok"
|
|
628
|
+
: flags.funding === "muxo_funded"
|
|
629
|
+
? "muxo_funded"
|
|
630
|
+
: undefined;
|
|
631
|
+
if (remoteUrl) {
|
|
632
|
+
const res = await fetch(`${remoteUrl}/api/v1/do`, {
|
|
633
|
+
method: "POST",
|
|
634
|
+
headers: {
|
|
635
|
+
"Content-Type": "application/json",
|
|
636
|
+
...(apiKeyFlag ? { Authorization: `Bearer ${apiKeyFlag}` } : {}),
|
|
637
|
+
},
|
|
638
|
+
body: JSON.stringify({
|
|
639
|
+
prompt: promptText,
|
|
640
|
+
autoApprove,
|
|
641
|
+
dryRun: planOnly,
|
|
642
|
+
}),
|
|
643
|
+
});
|
|
644
|
+
console.log(JSON.stringify(await res.json(), null, 2));
|
|
645
|
+
return;
|
|
646
|
+
}
|
|
647
|
+
const result = await engine.doNaturalLanguage(ctx, {
|
|
648
|
+
prompt: promptText,
|
|
649
|
+
autoApprove,
|
|
650
|
+
planOnly,
|
|
651
|
+
fundingMode,
|
|
652
|
+
});
|
|
653
|
+
console.log(JSON.stringify(result, null, 2));
|
|
654
|
+
return;
|
|
655
|
+
}
|
|
656
|
+
if (cmd === "tui" || cmd === "setup" || cmd === "interactive") {
|
|
657
|
+
const remoteUrl = typeof flags.url === "string" ? flags.url.replace(/\/+$/, "") : "";
|
|
658
|
+
if (remoteUrl && (flags.json || flags["non-interactive"] || flags.once)) {
|
|
659
|
+
const res = await fetch(`${remoteUrl}/api/v1/billing/status`, {
|
|
660
|
+
headers: apiKeyFlag ? { Authorization: `Bearer ${apiKeyFlag}` } : {},
|
|
661
|
+
});
|
|
662
|
+
const statusData = (await res.json());
|
|
663
|
+
console.log(JSON.stringify({
|
|
664
|
+
ok: true,
|
|
665
|
+
tui: "ready",
|
|
666
|
+
mode: "tui_snapshot",
|
|
667
|
+
workspace: statusData.workspace,
|
|
668
|
+
byokKeys: statusData.byokKeys || [],
|
|
669
|
+
supportedByokProviders: Object.keys(BYOK_PROVIDER_CATALOG),
|
|
670
|
+
}, null, 2));
|
|
671
|
+
return;
|
|
672
|
+
}
|
|
673
|
+
const freshWs = store.getWorkspace(ctx.workspace.id) || ctx.workspace;
|
|
674
|
+
const byokKeys = store.listByokKeys(ctx.workspace.id);
|
|
675
|
+
const conns = store.listConnections(ctx.workspace.id);
|
|
676
|
+
const resources = store.listResources(ctx.workspace.id);
|
|
677
|
+
const gov = engine.governance.getStatus(freshWs);
|
|
678
|
+
if (flags.json || flags["non-interactive"] || flags.once) {
|
|
679
|
+
console.log(JSON.stringify({
|
|
680
|
+
ok: true,
|
|
681
|
+
tui: "ready",
|
|
682
|
+
mode: "tui_snapshot",
|
|
683
|
+
workspace: {
|
|
684
|
+
id: freshWs.id,
|
|
685
|
+
name: freshWs.name,
|
|
686
|
+
slug: freshWs.slug,
|
|
687
|
+
tier: freshWs.tier,
|
|
688
|
+
creditsBalance: freshWs.creditsBalance,
|
|
689
|
+
monthlyActionsUsed: freshWs.monthlyActionsUsed,
|
|
690
|
+
monthlyActionsLimit: freshWs.monthlyActionsLimit,
|
|
691
|
+
},
|
|
692
|
+
governanceDid: gov.agentDid,
|
|
693
|
+
byokKeys,
|
|
694
|
+
activeConnections: conns.filter((c) => c.status === "active").length,
|
|
695
|
+
activeResources: resources.filter((r) => r.status === "active").length,
|
|
696
|
+
supportedByokProviders: Object.keys(BYOK_PROVIDER_CATALOG),
|
|
697
|
+
}, null, 2));
|
|
698
|
+
return;
|
|
699
|
+
}
|
|
700
|
+
const printBanner = () => {
|
|
701
|
+
const wsNow = store.getWorkspace(ctx.workspace.id) || ctx.workspace;
|
|
702
|
+
const keysNow = store.listByokKeys(ctx.workspace.id);
|
|
703
|
+
const hasSupplierByok = keysNow.some((k) => k.category === "supplier");
|
|
704
|
+
console.log("\n┌──────────────────────────────────────────────────────────────────────────┐");
|
|
705
|
+
console.log("│ ⚡ MUXO INTERACTIVE TUI — Execution, Cloud Infra, Memory & Governance │");
|
|
706
|
+
console.log("├──────────────────────────────────────────────────────────────────────────┤");
|
|
707
|
+
console.log(`│ Workspace : ${wsNow.name.padEnd(28)} Tier : ${wsNow.tier.toUpperCase().padEnd(16)}│`);
|
|
708
|
+
console.log(`│ Credits : ${String(wsNow.creditsBalance).padEnd(28)} Funding : ${(hasSupplierByok ? "BYOK (0 cr)" : "muxo_funded").padEnd(16)}│`);
|
|
709
|
+
console.log(`│ BYOK Keys : ${String(keysNow.length).padEnd(28)} DID : ${gov.agentDid.slice(0, 16)}│`);
|
|
710
|
+
console.log("├──────────────────────────────────────────────────────────────────────────┤");
|
|
711
|
+
console.log("│ [1] ✨ Run in Plain English (Natural Language Router: muxo do) │");
|
|
712
|
+
console.log("│ [2] 🔑 Configure BYOK API Key (OpenAI, Anthropic, Composio, Stripe...) │");
|
|
713
|
+
console.log("│ [3] 💳 Billing: Top Up +1,000 Credits or Upgrade to Starter Plan │");
|
|
714
|
+
console.log("│ [4] 🔗 Connect OAuth App (GitHub, Gmail, Slack, Notion, Linear) │");
|
|
715
|
+
console.log("│ [5] ☁️ Provision Cloud Database (Turso SQLite, Neon Postgres, Redis) │");
|
|
716
|
+
console.log("│ [q] Exit TUI │");
|
|
717
|
+
console.log("└──────────────────────────────────────────────────────────────────────────┘");
|
|
718
|
+
};
|
|
719
|
+
printBanner();
|
|
720
|
+
const choice = (await promptUserLine("\nSelect an option [1-5, q] (or type any natural language command): ")).trim();
|
|
721
|
+
if (!choice || choice.toLowerCase() === "q" || choice.toLowerCase() === "exit") {
|
|
722
|
+
console.log("Exited Muxo TUI.");
|
|
723
|
+
return;
|
|
724
|
+
}
|
|
725
|
+
if (choice === "1") {
|
|
726
|
+
const nlPrompt = await promptUserLine("Ask Muxo in plain English: ");
|
|
727
|
+
if (nlPrompt) {
|
|
728
|
+
const res = await engine.doNaturalLanguage(ctx, { prompt: nlPrompt, autoApprove: true });
|
|
729
|
+
console.log(JSON.stringify(res, null, 2));
|
|
730
|
+
}
|
|
731
|
+
return;
|
|
732
|
+
}
|
|
733
|
+
if (choice === "2") {
|
|
734
|
+
const provider = (await promptUserLine("Provider (openai, anthropic, openrouter, gemini, composio, stripe, supermemory, firecrawl, exa): ")).toLowerCase();
|
|
735
|
+
const secretKey = await promptUserLine(`Paste API key for ${provider}: `);
|
|
736
|
+
if (provider && secretKey) {
|
|
737
|
+
const saved = store.setByokKey(ctx.workspace.id, provider, secretKey);
|
|
738
|
+
console.log(JSON.stringify({ ok: true, saved }, null, 2));
|
|
739
|
+
}
|
|
740
|
+
return;
|
|
741
|
+
}
|
|
742
|
+
if (choice === "3") {
|
|
743
|
+
const action = (await promptUserLine("Type 'upgrade' for Starter Plan or credit amount (default 1000): ")).toLowerCase();
|
|
744
|
+
if (action === "upgrade") {
|
|
745
|
+
const up = store.upgradeWorkspaceToStarter({
|
|
746
|
+
workspaceId: ctx.workspace.id,
|
|
747
|
+
referenceId: `tui_upgrade_${Date.now()}`,
|
|
748
|
+
bonusCredits: 1000,
|
|
749
|
+
});
|
|
750
|
+
console.log(JSON.stringify({ ok: true, upgraded: true, workspace: up }, null, 2));
|
|
751
|
+
}
|
|
752
|
+
else {
|
|
753
|
+
const cr = Math.max(100, Number(action) || 1000);
|
|
754
|
+
const up = store.addWorkspaceCredits({
|
|
755
|
+
workspaceId: ctx.workspace.id,
|
|
756
|
+
credits: cr,
|
|
757
|
+
referenceId: `tui_topup_${Date.now()}`,
|
|
758
|
+
description: `TUI credit top-up (+${cr} credits)`,
|
|
759
|
+
});
|
|
760
|
+
console.log(JSON.stringify({ ok: true, creditsAdded: cr, creditsBalance: up.creditsBalance }, null, 2));
|
|
761
|
+
}
|
|
762
|
+
return;
|
|
763
|
+
}
|
|
764
|
+
if (choice === "4") {
|
|
765
|
+
const provider = (await promptUserLine("OAuth Provider (github, gmail, slack, notion, linear): ")) || "github";
|
|
766
|
+
const conn = await engine.startConnection(ctx, { provider });
|
|
767
|
+
console.log(JSON.stringify({ ok: true, connection: conn }, null, 2));
|
|
768
|
+
return;
|
|
769
|
+
}
|
|
770
|
+
if (choice === "5") {
|
|
771
|
+
const dbPrompt = (await promptUserLine("Database to provision (e.g. 'Provision Turso database my-app-db'): ")) || "Provision Turso database my-app-db";
|
|
772
|
+
const res = await engine.doNaturalLanguage(ctx, { prompt: dbPrompt, autoApprove: true });
|
|
773
|
+
console.log(JSON.stringify(res, null, 2));
|
|
774
|
+
return;
|
|
775
|
+
}
|
|
776
|
+
// Otherwise treat whatever they typed as a natural language command!
|
|
777
|
+
const res = await engine.doNaturalLanguage(ctx, { prompt: choice, autoApprove: true });
|
|
778
|
+
console.log(JSON.stringify(res, null, 2));
|
|
779
|
+
return;
|
|
780
|
+
}
|
|
781
|
+
if (cmd === "memory") {
|
|
782
|
+
const sub = positional[1];
|
|
783
|
+
if (sub === "add") {
|
|
784
|
+
const content = positional.slice(2).join(" ") || String(flags.content || "");
|
|
785
|
+
if (!content)
|
|
786
|
+
throw new Error("Usage: muxo memory add <text>");
|
|
787
|
+
const entry = await engine.addWorkspaceMemory(ctx, {
|
|
788
|
+
content,
|
|
789
|
+
title: flags.title ? String(flags.title) : content.slice(0, 60),
|
|
790
|
+
});
|
|
791
|
+
console.log(JSON.stringify({ ok: true, memory: entry }, null, 2));
|
|
792
|
+
return;
|
|
793
|
+
}
|
|
794
|
+
const query = sub === "recall" || sub === "search"
|
|
795
|
+
? positional.slice(2).join(" ") || flags.query || undefined
|
|
796
|
+
: positional.slice(1).join(" ") || flags.query || undefined;
|
|
797
|
+
const recall = await engine.getMemoryOverview(ctx, query);
|
|
798
|
+
console.log(JSON.stringify({
|
|
799
|
+
ok: true,
|
|
800
|
+
...recall,
|
|
801
|
+
localMemories: recall.recentMemories,
|
|
802
|
+
}, null, 2));
|
|
803
|
+
return;
|
|
804
|
+
}
|
|
805
|
+
if (cmd === "governance") {
|
|
806
|
+
const status = engine.governance.getGovernanceStatus(ctx.workspace);
|
|
807
|
+
const summary = engine.governance.getStatus(ctx.workspace);
|
|
808
|
+
console.log(JSON.stringify({
|
|
809
|
+
ok: true,
|
|
810
|
+
did: summary.agentDid,
|
|
811
|
+
chainValid: summary.auditChainIntegrity,
|
|
812
|
+
ringName: "Ring 2 (Standard)",
|
|
813
|
+
...status,
|
|
814
|
+
}, null, 2));
|
|
815
|
+
return;
|
|
816
|
+
}
|
|
817
|
+
if (cmd === "serve") {
|
|
818
|
+
const { createMuxoServer } = await import("./server.js");
|
|
819
|
+
const port = flags.port ? Number(flags.port) : config.port;
|
|
820
|
+
const baseUrl = `http://localhost:${port}`;
|
|
821
|
+
const srvConfig = { ...config, port, baseUrl };
|
|
822
|
+
const { server } = createMuxoServer(srvConfig);
|
|
823
|
+
await new Promise((resolve) => {
|
|
824
|
+
server.listen(port, () => {
|
|
825
|
+
console.log(`\n⚡ Muxo Platform running at ${baseUrl}`);
|
|
826
|
+
console.log(` ├─ Web Console: ${baseUrl}/`);
|
|
827
|
+
console.log(` ├─ Landing Page: ${baseUrl}/landing`);
|
|
828
|
+
console.log(` ├─ MCP Server: ${baseUrl}/mcp`);
|
|
829
|
+
console.log(` ├─ OAuth Callback: ${baseUrl}/oauth/callback`);
|
|
830
|
+
console.log(` └─ Agent Skill: ${baseUrl}/skill.md\n`);
|
|
831
|
+
});
|
|
832
|
+
process.on("SIGINT", () => {
|
|
833
|
+
server.close(() => resolve());
|
|
834
|
+
});
|
|
835
|
+
process.on("SIGTERM", () => {
|
|
836
|
+
server.close(() => resolve());
|
|
837
|
+
});
|
|
838
|
+
});
|
|
839
|
+
return;
|
|
840
|
+
}
|
|
841
|
+
// Natural Language fallback: if user passed plain English directly (`muxo "Audit https://muxo.ai for SEO"`)
|
|
842
|
+
if (cmd !== "help" && !flags.help && !flags.h && positional.length > 0) {
|
|
843
|
+
const promptText = positional.join(" ").trim();
|
|
844
|
+
const result = await engine.doNaturalLanguage(ctx, {
|
|
845
|
+
prompt: promptText,
|
|
846
|
+
autoApprove: flags["no-approve"] ? false : true,
|
|
847
|
+
planOnly: flags["plan-only"] === true || flags.plan === true,
|
|
848
|
+
fundingMode: flags.byok || flags.funding === "byok"
|
|
849
|
+
? "byok"
|
|
850
|
+
: flags.funding === "muxo_funded"
|
|
851
|
+
? "muxo_funded"
|
|
852
|
+
: undefined,
|
|
853
|
+
});
|
|
854
|
+
console.log(JSON.stringify(result, null, 2));
|
|
855
|
+
return;
|
|
856
|
+
}
|
|
857
|
+
console.log(`
|
|
858
|
+
Muxo CLI — Human & LLM Friendly Execution, Infrastructure, BYOK & Governance Platform
|
|
859
|
+
|
|
860
|
+
Natural Language & Interactive TUI:
|
|
861
|
+
muxo do "<instruction>" Execute any goal in plain English (LLM/semantic router -> plan -> execute)
|
|
862
|
+
muxo ask "<instruction>" [--plan-only] Alias for 'muxo do' (pass --plan-only to inspect plan before running)
|
|
863
|
+
muxo tui Launch interactive Terminal UI dashboard (BYOK, Billing, OAuth, Infra)
|
|
864
|
+
muxo byok [list|set|delete] [<provider>] Manage BYOK API keys in AES-256-GCM Vault (0 credit cost when active)
|
|
865
|
+
|
|
866
|
+
Core Commands:
|
|
867
|
+
muxo login [--api-key <key> | --signup] Sign in or create an autonomous workspace (~/.muxo/config.json)
|
|
868
|
+
muxo logout Remove saved CLI authentication config
|
|
869
|
+
muxo claim <owner_email> Generate a human owner claim link for this workspace
|
|
870
|
+
muxo whoami Show workspace profile, plan, DID, and credit balance
|
|
871
|
+
muxo search <query> [--lane <lane>] Search across Instant, Composio Apps, Stripe Projects & Billing
|
|
872
|
+
muxo inspect <tool_slug> Inspect tool schema, risk level, and credit cost
|
|
873
|
+
muxo connections [--sync true|false] List Composio OAuth & Stripe Projects provider connections
|
|
874
|
+
muxo link <provider> [--wait] Start OAuth handoff for a service and optionally wait
|
|
875
|
+
muxo connect <provider> [--wait] Alias for 'muxo link'
|
|
876
|
+
muxo wait <provider> [--timeout 15] Poll until a pending OAuth connection handoff becomes active
|
|
877
|
+
muxo plan <tool_slug> --input '{...}' Create a governed execution plan (accepts natural language too)
|
|
878
|
+
muxo approve <plan_id> Approve a pending high-risk plan
|
|
879
|
+
muxo run <plan_id> Execute an approved plan and issue a signed receipt
|
|
880
|
+
muxo exec <tool_slug> --input '{...}' Plan and execute in one step (pass --approve for high-risk)
|
|
881
|
+
muxo resources List provisioned Stripe Projects infrastructure resources
|
|
882
|
+
muxo env pull [--out .env.muxo] Decrypt and write provisioned credentials to local .env
|
|
883
|
+
muxo receipts [<receipt_id>] List or cryptographically verify execution receipts
|
|
884
|
+
muxo billing [status|topup|upgrade|checkout] Manage credits, upgrade to Starter, or inspect settlements
|
|
885
|
+
muxo memory [<query>] Recall Supermemory v5 workspace brain & hybrid memories
|
|
886
|
+
muxo governance Inspect Microsoft Agent Governance Ed25519 DID & audit chain
|
|
887
|
+
muxo serve [--port 4310] Start unified HTTP Console, Landing, OAuth Callback & MCP server
|
|
888
|
+
muxo mcp Run stdio MCP server (20 canonical tools)
|
|
889
|
+
`);
|
|
890
|
+
}
|
|
891
|
+
runCli().catch((err) => {
|
|
892
|
+
console.error("Error:", err?.message || err);
|
|
893
|
+
process.exit(1);
|
|
894
|
+
});
|