@muxoai/platform 1.3.0 → 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.
- package/.agents/plugins/marketplace.json +1 -1
- package/.claude-plugin/marketplace.json +19 -4
- package/.codex/config.toml +9 -2
- package/README.md +54 -19
- package/dist/cli.js +780 -94
- package/dist/engine.d.ts +1 -0
- package/dist/engine.js +52 -4
- package/dist/mcp.d.ts +6 -1
- package/dist/mcp.js +108 -22
- package/dist/nl.js +60 -36
- package/dist/providers/composio-instant.d.ts +1 -0
- package/dist/providers/composio-instant.js +6 -5
- package/dist/providers/composio-sdk.d.ts +1 -0
- package/dist/providers/composio-sdk.js +6 -2
- package/dist/providers/stripe-billing.js +14 -4
- package/dist/providers/stripe-projects.js +61 -4
- package/dist/providers/supermemory.d.ts +2 -0
- package/dist/providers/supermemory.js +58 -40
- package/dist/server.js +85 -27
- package/dist/store.d.ts +1 -0
- package/dist/store.js +20 -4
- package/dist/ui/console-html.js +134 -114
- package/package.json +1 -1
- package/plugins/muxo/.app.json +1 -1
- package/plugins/muxo/.claude-plugin/plugin.json +2 -2
- package/plugins/muxo/.codex-plugin/plugin.json +7 -5
- package/plugins/muxo/.mcp.json +1 -33
- package/plugins/muxo/assets/logo.png +0 -0
- package/plugins/muxo/hooks/session-start.sh +1 -1
- package/plugins/muxo/plugin.json +63 -6
- package/plugins/muxo/skills/muxo/SKILL.md +92 -14
- package/plugins/muxo/skills/muxo/agents/openai.yaml +12 -0
- package/plugins/muxo/skills/muxo/references/cli.md +4 -2
- package/plugins/muxo/skills/muxo/references/mcp.md +15 -9
- package/plugins/muxo/skills/setup/SKILL.md +8 -2
- package/plugins/muxo/skills/setup/agents/openai.yaml +12 -0
package/dist/cli.js
CHANGED
|
@@ -70,37 +70,104 @@ function parseFlags(args) {
|
|
|
70
70
|
return { positional, flags };
|
|
71
71
|
}
|
|
72
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
73
|
const { positional, flags } = parseFlags(process.argv.slice(2));
|
|
77
74
|
const cmd = positional[0] || "help";
|
|
78
75
|
if (flags.version || flags.v || cmd === "version") {
|
|
79
76
|
console.log(flags.json
|
|
80
|
-
? JSON.stringify({ ok: true, name: "@muxoai/cli", version: "1.3.
|
|
81
|
-
: "1.3.
|
|
77
|
+
? JSON.stringify({ ok: true, name: "@muxoai/cli", version: "1.3.1" }, null, 2)
|
|
78
|
+
: "1.3.1");
|
|
82
79
|
return;
|
|
83
80
|
}
|
|
84
81
|
const savedCliConfig = readCliAuthConfig();
|
|
85
|
-
|
|
82
|
+
let apiKeyFlag = (typeof flags["api-key"] === "string" ? flags["api-key"] : "") ||
|
|
86
83
|
process.env.MUXO_API_KEY ||
|
|
87
84
|
savedCliConfig?.apiKey ||
|
|
88
85
|
"";
|
|
89
|
-
const
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
86
|
+
const explicitUrlFlag = (typeof flags.url === "string"
|
|
87
|
+
? flags.url
|
|
88
|
+
: process.env.MUXO_API_URL || "").replace(/\/+$/, "");
|
|
89
|
+
const useLocalDb = Boolean((process.env.MUXO_DB_PATH || flags.local) && !explicitUrlFlag);
|
|
90
|
+
const remoteUrl = useLocalDb
|
|
91
|
+
? ""
|
|
92
|
+
: (explicitUrlFlag || savedCliConfig?.apiUrl || "https://api.muxo.ai").replace(/\/+$/, "");
|
|
93
|
+
const remoteFetch = async (pathname, opts) => {
|
|
94
|
+
const keyToUse = opts?.apiKey ?? apiKeyFlag;
|
|
95
|
+
const headers = {
|
|
96
|
+
Accept: "application/json",
|
|
97
|
+
};
|
|
98
|
+
if (opts?.body !== undefined) {
|
|
99
|
+
headers["Content-Type"] = "application/json";
|
|
100
|
+
}
|
|
101
|
+
if (keyToUse) {
|
|
102
|
+
headers["Authorization"] = `Bearer ${keyToUse}`;
|
|
103
|
+
}
|
|
104
|
+
const res = await fetch(`${remoteUrl}${pathname}`, {
|
|
105
|
+
method: opts?.method || "GET",
|
|
106
|
+
headers,
|
|
107
|
+
body: opts?.body !== undefined ? JSON.stringify(opts.body) : undefined,
|
|
108
|
+
});
|
|
109
|
+
const data = (await res.json().catch(() => ({})));
|
|
110
|
+
if (!res.ok && data.error) {
|
|
111
|
+
throw new Error(String(data.error));
|
|
112
|
+
}
|
|
113
|
+
return data;
|
|
114
|
+
};
|
|
115
|
+
const signupHostedWorkspace = async (agentName, harness) => {
|
|
116
|
+
const createdRemote = await remoteFetch("/api/v1/agents/signup", {
|
|
117
|
+
method: "POST",
|
|
118
|
+
body: { agentName, harness },
|
|
119
|
+
apiKey: "",
|
|
120
|
+
});
|
|
121
|
+
if (!createdRemote || !createdRemote.apiKey) {
|
|
122
|
+
throw new Error(`Hosted signup at ${remoteUrl}/api/v1/agents/signup failed to return an API key.`);
|
|
123
|
+
}
|
|
124
|
+
const authPayload = {
|
|
125
|
+
authenticated: true,
|
|
126
|
+
apiKey: String(createdRemote.apiKey),
|
|
127
|
+
apiUrl: remoteUrl,
|
|
128
|
+
workspaceId: String(createdRemote.workspaceId || createdRemote.workspace?.id || ""),
|
|
129
|
+
workspaceName: String(createdRemote.workspace?.name || `${agentName} Workspace`),
|
|
130
|
+
agentId: String(createdRemote.agentId || createdRemote.user?.id || "usr_agent"),
|
|
131
|
+
governanceDid: String(createdRemote.governanceDid || ""),
|
|
132
|
+
supermemoryNamespace: String(createdRemote.supermemoryNamespace || ""),
|
|
133
|
+
updatedAt: new Date().toISOString(),
|
|
103
134
|
};
|
|
135
|
+
return { authPayload, rawResponse: createdRemote };
|
|
136
|
+
};
|
|
137
|
+
const config = getConfig();
|
|
138
|
+
let _store = null;
|
|
139
|
+
let _engine = null;
|
|
140
|
+
const getStore = () => {
|
|
141
|
+
if (!_store) {
|
|
142
|
+
_store = new MuxoStore(config.dbPath, config.vaultMasterKey);
|
|
143
|
+
}
|
|
144
|
+
return _store;
|
|
145
|
+
};
|
|
146
|
+
const getEngine = () => {
|
|
147
|
+
if (!_engine) {
|
|
148
|
+
_engine = new MuxoEngine(config, getStore());
|
|
149
|
+
}
|
|
150
|
+
return _engine;
|
|
151
|
+
};
|
|
152
|
+
const getLocalContext = () => {
|
|
153
|
+
const store = getStore();
|
|
154
|
+
const tokenAuth = apiKeyFlag ? store.resolveAuthToken(apiKeyFlag) : null;
|
|
155
|
+
const fallback = store.ensureDefaultWorkspace();
|
|
156
|
+
const ctx = tokenAuth
|
|
157
|
+
? {
|
|
158
|
+
user: tokenAuth.user,
|
|
159
|
+
workspace: tokenAuth.workspace,
|
|
160
|
+
actorId: tokenAuth.actorId,
|
|
161
|
+
authType: tokenAuth.authType,
|
|
162
|
+
}
|
|
163
|
+
: {
|
|
164
|
+
user: fallback.user,
|
|
165
|
+
workspace: fallback.workspace,
|
|
166
|
+
actorId: `cli:${fallback.user.id}`,
|
|
167
|
+
authType: "session",
|
|
168
|
+
};
|
|
169
|
+
return { store, engine: getEngine(), ctx, tokenAuth };
|
|
170
|
+
};
|
|
104
171
|
// CLI Login / Autonomous External Signup (`muxo login`)
|
|
105
172
|
if (cmd === "login" || cmd === "signup") {
|
|
106
173
|
const explicitKey = typeof flags["api-key"] === "string"
|
|
@@ -109,6 +176,34 @@ async function runCli() {
|
|
|
109
176
|
? positional[1]
|
|
110
177
|
: "";
|
|
111
178
|
if (explicitKey) {
|
|
179
|
+
if (remoteUrl) {
|
|
180
|
+
const boot = await remoteFetch("/api/v1/bootstrap", {
|
|
181
|
+
apiKey: explicitKey,
|
|
182
|
+
});
|
|
183
|
+
const ws = boot.organization || {};
|
|
184
|
+
const usr = boot.profile?.user || {};
|
|
185
|
+
const authPayload = {
|
|
186
|
+
authenticated: true,
|
|
187
|
+
apiKey: explicitKey,
|
|
188
|
+
apiUrl: remoteUrl,
|
|
189
|
+
workspaceId: String(ws.id || boot.profile?.workspaceId || ""),
|
|
190
|
+
workspaceName: String(ws.name || "Muxo Workspace"),
|
|
191
|
+
agentId: String(usr.id || "usr_agent"),
|
|
192
|
+
governanceDid: String(boot.governance?.agentDid || ""),
|
|
193
|
+
supermemoryNamespace: String(boot.supermemory?.namespace || ""),
|
|
194
|
+
updatedAt: new Date().toISOString(),
|
|
195
|
+
};
|
|
196
|
+
const cfgPath = writeCliAuthConfig(authPayload);
|
|
197
|
+
console.log(JSON.stringify({
|
|
198
|
+
ok: true,
|
|
199
|
+
mode: "api_key",
|
|
200
|
+
configPath: cfgPath,
|
|
201
|
+
workspace: ws,
|
|
202
|
+
...authPayload,
|
|
203
|
+
}, null, 2));
|
|
204
|
+
return;
|
|
205
|
+
}
|
|
206
|
+
const { store, engine } = getLocalContext();
|
|
112
207
|
const resolved = store.resolveAuthToken(explicitKey);
|
|
113
208
|
if (!resolved) {
|
|
114
209
|
throw new Error("Invalid Muxo API key supplied to 'muxo login'.");
|
|
@@ -137,6 +232,23 @@ async function runCli() {
|
|
|
137
232
|
? flags.name
|
|
138
233
|
: positional[1] || "Muxo CLI Agent";
|
|
139
234
|
const harness = typeof flags.harness === "string" ? flags.harness : "muxo-cli";
|
|
235
|
+
if (remoteUrl) {
|
|
236
|
+
const { authPayload, rawResponse } = await signupHostedWorkspace(agentName, harness);
|
|
237
|
+
const cfgPath = writeCliAuthConfig(authPayload);
|
|
238
|
+
console.log(JSON.stringify({
|
|
239
|
+
ok: true,
|
|
240
|
+
mode: "autonomous_signup",
|
|
241
|
+
configPath: cfgPath,
|
|
242
|
+
workspace: rawResponse.workspace,
|
|
243
|
+
creditsBalance: rawResponse.workspace?.creditsBalance ?? 250,
|
|
244
|
+
mcpEndpoint: rawResponse.mcpEndpoint || `${remoteUrl}/mcp`,
|
|
245
|
+
skillUrl: rawResponse.skillUrl || `${remoteUrl}/skill.md`,
|
|
246
|
+
claimEndpoint: rawResponse.claimEndpoint || `${remoteUrl}/api/v1/agents/claim`,
|
|
247
|
+
...authPayload,
|
|
248
|
+
}, null, 2));
|
|
249
|
+
return;
|
|
250
|
+
}
|
|
251
|
+
const { store, engine } = getLocalContext();
|
|
140
252
|
const created = store.createAutonomousAgentSignup({
|
|
141
253
|
agentName,
|
|
142
254
|
harness,
|
|
@@ -168,11 +280,113 @@ async function runCli() {
|
|
|
168
280
|
console.log(JSON.stringify({ ok: true, authenticated: false, configPath: cfgPath }, null, 2));
|
|
169
281
|
return;
|
|
170
282
|
}
|
|
283
|
+
// One-command setup (`muxo setup` / `muxo init` / `muxo install`):
|
|
284
|
+
// 1. Auto-creates or loads ~/.muxo/config.json with 250 starter credits
|
|
285
|
+
// 2. Writes .mcp.json in target directory (or ~/.cursor/mcp.json & ~/.factory/mcp.json if present)
|
|
286
|
+
if (cmd === "setup" || cmd === "init" || cmd === "install") {
|
|
287
|
+
let activeConfig = savedCliConfig;
|
|
288
|
+
if (!activeConfig || !activeConfig.apiKey || flags.fresh) {
|
|
289
|
+
const agentName = typeof flags.name === "string" ? flags.name : "Muxo Agent";
|
|
290
|
+
if (remoteUrl) {
|
|
291
|
+
const { authPayload } = await signupHostedWorkspace(agentName, "muxo-setup");
|
|
292
|
+
activeConfig = authPayload;
|
|
293
|
+
}
|
|
294
|
+
else {
|
|
295
|
+
const { store, engine } = getLocalContext();
|
|
296
|
+
const created = store.createAutonomousAgentSignup({
|
|
297
|
+
agentName,
|
|
298
|
+
harness: "muxo-setup",
|
|
299
|
+
});
|
|
300
|
+
activeConfig = {
|
|
301
|
+
authenticated: true,
|
|
302
|
+
apiKey: created.apiKey,
|
|
303
|
+
workspaceId: created.workspace.id,
|
|
304
|
+
workspaceName: created.workspace.name,
|
|
305
|
+
agentId: created.user.id,
|
|
306
|
+
governanceDid: engine.governance.getStatus(created.workspace).agentDid,
|
|
307
|
+
supermemoryNamespace: engine.supermemory.getWorkspaceNamespace(created.workspace.id),
|
|
308
|
+
updatedAt: new Date().toISOString(),
|
|
309
|
+
};
|
|
310
|
+
}
|
|
311
|
+
writeCliAuthConfig(activeConfig);
|
|
312
|
+
}
|
|
313
|
+
const mcpServerUrl = remoteUrl
|
|
314
|
+
? `${remoteUrl}/mcp`
|
|
315
|
+
: "https://api.muxo.ai/mcp";
|
|
316
|
+
const mcpEntry = {
|
|
317
|
+
type: "http",
|
|
318
|
+
url: mcpServerUrl,
|
|
319
|
+
headers: {
|
|
320
|
+
Authorization: `Bearer ${activeConfig.apiKey}`,
|
|
321
|
+
},
|
|
322
|
+
};
|
|
323
|
+
const targetDir = typeof flags.dir === "string" ? path.resolve(flags.dir) : process.cwd();
|
|
324
|
+
const writtenFiles = [];
|
|
325
|
+
const mergeMcpJsonFile = (filePath) => {
|
|
326
|
+
try {
|
|
327
|
+
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
328
|
+
let existing = {};
|
|
329
|
+
if (fs.existsSync(filePath)) {
|
|
330
|
+
existing = JSON.parse(fs.readFileSync(filePath, "utf8")) || {};
|
|
331
|
+
}
|
|
332
|
+
existing.mcpServers = {
|
|
333
|
+
...(existing.mcpServers || {}),
|
|
334
|
+
muxo: mcpEntry,
|
|
335
|
+
};
|
|
336
|
+
fs.writeFileSync(filePath, JSON.stringify(existing, null, 2) + "\n");
|
|
337
|
+
writtenFiles.push(filePath);
|
|
338
|
+
}
|
|
339
|
+
catch {
|
|
340
|
+
// Ignore non-writable paths
|
|
341
|
+
}
|
|
342
|
+
};
|
|
343
|
+
// Always write .mcp.json in targetDir when requested or if in a project
|
|
344
|
+
mergeMcpJsonFile(path.join(targetDir, ".mcp.json"));
|
|
345
|
+
const resultPayload = {
|
|
346
|
+
ok: true,
|
|
347
|
+
workspaceId: activeConfig.workspaceId,
|
|
348
|
+
workspaceName: activeConfig.workspaceName,
|
|
349
|
+
apiKey: activeConfig.apiKey,
|
|
350
|
+
mcpUrl: mcpServerUrl,
|
|
351
|
+
configPath: getCliConfigPath(),
|
|
352
|
+
configuredFiles: writtenFiles,
|
|
353
|
+
};
|
|
354
|
+
if (flags.json || !process.stdout.isTTY) {
|
|
355
|
+
console.log(JSON.stringify(resultPayload, null, 2));
|
|
356
|
+
}
|
|
357
|
+
else {
|
|
358
|
+
console.log(`\n✓ Muxo is ready!`);
|
|
359
|
+
console.log(` Workspace : ${activeConfig.workspaceName} (${activeConfig.workspaceId})`);
|
|
360
|
+
console.log(` API Key : ${activeConfig.apiKey}`);
|
|
361
|
+
console.log(` MCP URL : ${mcpServerUrl}`);
|
|
362
|
+
console.log(` MCP Config: ${writtenFiles.join(", ")}`);
|
|
363
|
+
console.log(`\nTry it now:`);
|
|
364
|
+
console.log(` muxo do "check dns A records for muxo.ai"`);
|
|
365
|
+
console.log(` muxo tui\n`);
|
|
366
|
+
}
|
|
367
|
+
return;
|
|
368
|
+
}
|
|
171
369
|
if (cmd === "claim") {
|
|
172
370
|
const email = positional[1] || (typeof flags.email === "string" ? flags.email : "");
|
|
173
371
|
if (!email || !email.includes("@")) {
|
|
174
372
|
throw new Error("Usage: muxo claim <owner_email>");
|
|
175
373
|
}
|
|
374
|
+
if (remoteUrl) {
|
|
375
|
+
const res = await remoteFetch("/api/v1/agents/claim", {
|
|
376
|
+
method: "POST",
|
|
377
|
+
body: { email },
|
|
378
|
+
});
|
|
379
|
+
const claimObj = res.claim || res;
|
|
380
|
+
console.log(JSON.stringify({
|
|
381
|
+
ok: true,
|
|
382
|
+
claim: claimObj,
|
|
383
|
+
ownerEmail: res.ownerEmail || claimObj?.targetEmail || email,
|
|
384
|
+
claimSlug: res.claimSlug || claimObj?.claimCode,
|
|
385
|
+
...claimObj,
|
|
386
|
+
}, null, 2));
|
|
387
|
+
return;
|
|
388
|
+
}
|
|
389
|
+
const { store, ctx } = getLocalContext();
|
|
176
390
|
const claim = store.createAgentClaim({
|
|
177
391
|
workspaceId: ctx.workspace.id,
|
|
178
392
|
email,
|
|
@@ -183,11 +397,22 @@ async function runCli() {
|
|
|
183
397
|
}
|
|
184
398
|
// Stdio MCP Server mode (`muxo mcp`)
|
|
185
399
|
if (cmd === "mcp") {
|
|
400
|
+
if (remoteUrl && !apiKeyFlag) {
|
|
401
|
+
try {
|
|
402
|
+
const { authPayload } = await signupHostedWorkspace("Muxo MCP Agent", "muxo-mcp-stdio");
|
|
403
|
+
writeCliAuthConfig(authPayload);
|
|
404
|
+
apiKeyFlag = authPayload.apiKey;
|
|
405
|
+
}
|
|
406
|
+
catch {
|
|
407
|
+
// Proceed with remote default workspace if signup fails
|
|
408
|
+
}
|
|
409
|
+
}
|
|
186
410
|
const rl = readline.createInterface({
|
|
187
411
|
input: process.stdin,
|
|
188
412
|
terminal: false,
|
|
189
413
|
});
|
|
190
414
|
let queue = Promise.resolve();
|
|
415
|
+
let mcpSessionId = "";
|
|
191
416
|
rl.on("line", (line) => {
|
|
192
417
|
const trimmed = line.trim();
|
|
193
418
|
if (!trimmed)
|
|
@@ -195,6 +420,35 @@ async function runCli() {
|
|
|
195
420
|
queue = queue.then(async () => {
|
|
196
421
|
try {
|
|
197
422
|
const rpc = JSON.parse(trimmed);
|
|
423
|
+
if (remoteUrl) {
|
|
424
|
+
const headers = {
|
|
425
|
+
"Content-Type": "application/json",
|
|
426
|
+
Accept: "application/json",
|
|
427
|
+
};
|
|
428
|
+
if (apiKeyFlag) {
|
|
429
|
+
headers["Authorization"] = `Bearer ${apiKeyFlag}`;
|
|
430
|
+
}
|
|
431
|
+
if (mcpSessionId) {
|
|
432
|
+
headers["Mcp-Session-Id"] = mcpSessionId;
|
|
433
|
+
}
|
|
434
|
+
const res = await fetch(`${remoteUrl}/mcp`, {
|
|
435
|
+
method: "POST",
|
|
436
|
+
headers,
|
|
437
|
+
body: JSON.stringify(rpc),
|
|
438
|
+
});
|
|
439
|
+
const sid = res.headers.get("mcp-session-id");
|
|
440
|
+
if (sid)
|
|
441
|
+
mcpSessionId = sid;
|
|
442
|
+
if (rpc.id !== undefined && res.status !== 202 && res.status !== 204) {
|
|
443
|
+
const text = await res.text();
|
|
444
|
+
if (text.trim()) {
|
|
445
|
+
const parsed = JSON.parse(text);
|
|
446
|
+
process.stdout.write(JSON.stringify(parsed) + "\n");
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
return;
|
|
450
|
+
}
|
|
451
|
+
const { engine, ctx } = getLocalContext();
|
|
198
452
|
const response = await handleJsonRpcMcpRequest(engine, ctx, rpc);
|
|
199
453
|
if (response) {
|
|
200
454
|
process.stdout.write(JSON.stringify(response) + "\n");
|
|
@@ -220,12 +474,16 @@ async function runCli() {
|
|
|
220
474
|
return;
|
|
221
475
|
}
|
|
222
476
|
if (cmd === "harness") {
|
|
477
|
+
let workspaceId = savedCliConfig?.workspaceId || "ws_muxo_default";
|
|
478
|
+
if (!remoteUrl) {
|
|
479
|
+
workspaceId = getLocalContext().ctx.workspace.id;
|
|
480
|
+
}
|
|
223
481
|
console.log(JSON.stringify({
|
|
224
482
|
ok: true,
|
|
225
|
-
version: "1.3.
|
|
483
|
+
version: "1.3.1",
|
|
226
484
|
passed: 7,
|
|
227
485
|
total: 7,
|
|
228
|
-
workspaceId
|
|
486
|
+
workspaceId,
|
|
229
487
|
data: {
|
|
230
488
|
mcpServers: {
|
|
231
489
|
muxo: {
|
|
@@ -234,7 +492,7 @@ async function runCli() {
|
|
|
234
492
|
},
|
|
235
493
|
},
|
|
236
494
|
remoteMcp: {
|
|
237
|
-
url: "https://api.muxo.ai/mcp
|
|
495
|
+
url: `${remoteUrl || "https://api.muxo.ai"}/mcp`,
|
|
238
496
|
transport: "streamable-http",
|
|
239
497
|
},
|
|
240
498
|
},
|
|
@@ -242,6 +500,47 @@ async function runCli() {
|
|
|
242
500
|
return;
|
|
243
501
|
}
|
|
244
502
|
if (cmd === "whoami" || cmd === "status" || cmd === "doctor") {
|
|
503
|
+
if (remoteUrl) {
|
|
504
|
+
const boot = await remoteFetch("/api/v1/bootstrap");
|
|
505
|
+
const ws = {
|
|
506
|
+
...(boot.organization || {}),
|
|
507
|
+
...(boot.profile?.workspace || {}),
|
|
508
|
+
};
|
|
509
|
+
const creditsBal = ws.creditsBalance ??
|
|
510
|
+
ws.creditBalance ??
|
|
511
|
+
boot.organization?.usage?.creditsBalance ??
|
|
512
|
+
0;
|
|
513
|
+
const usr = boot.profile?.user || {};
|
|
514
|
+
console.log(JSON.stringify({
|
|
515
|
+
ok: true,
|
|
516
|
+
authenticated: Boolean(apiKeyFlag),
|
|
517
|
+
authSource: apiKeyFlag
|
|
518
|
+
? savedCliConfig?.apiKey === apiKeyFlag
|
|
519
|
+
? "config_file"
|
|
520
|
+
: "api_key"
|
|
521
|
+
: "hosted_default",
|
|
522
|
+
apiUrl: remoteUrl,
|
|
523
|
+
profile: {
|
|
524
|
+
id: usr.id,
|
|
525
|
+
name: usr.name,
|
|
526
|
+
email: usr.email,
|
|
527
|
+
user: usr,
|
|
528
|
+
workspaceId: ws.id,
|
|
529
|
+
workspaceName: ws.name,
|
|
530
|
+
tier: ws.tier,
|
|
531
|
+
},
|
|
532
|
+
workspace: {
|
|
533
|
+
...ws,
|
|
534
|
+
creditsBalance: creditsBal,
|
|
535
|
+
creditBalance: creditsBal,
|
|
536
|
+
},
|
|
537
|
+
organization: boot.organization || ws,
|
|
538
|
+
governanceDid: boot.governance?.agentDid,
|
|
539
|
+
supermemoryNamespace: boot.supermemory?.namespace,
|
|
540
|
+
}, null, 2));
|
|
541
|
+
return;
|
|
542
|
+
}
|
|
543
|
+
const { engine, ctx, tokenAuth } = getLocalContext();
|
|
245
544
|
const org = engine.getOrganization(ctx);
|
|
246
545
|
console.log(JSON.stringify({
|
|
247
546
|
ok: true,
|
|
@@ -265,10 +564,31 @@ async function runCli() {
|
|
|
265
564
|
if (cmd === "search") {
|
|
266
565
|
const query = positional.slice(1).join(" ") || flags.query || "";
|
|
267
566
|
const lane = flags.lane || "all";
|
|
567
|
+
const limit = flags.limit ? Number(flags.limit) : 20;
|
|
568
|
+
if (remoteUrl) {
|
|
569
|
+
const qs = new URLSearchParams({
|
|
570
|
+
query,
|
|
571
|
+
lane: String(lane),
|
|
572
|
+
limit: String(limit),
|
|
573
|
+
});
|
|
574
|
+
const res = await remoteFetch(`/api/v1/tools?${qs.toString()}`);
|
|
575
|
+
const tools = Array.isArray(res.tools) ? res.tools : [];
|
|
576
|
+
if (flags.json || !process.stdout.isTTY) {
|
|
577
|
+
console.log(JSON.stringify({ ok: true, count: res.count ?? tools.length, total: res.count ?? tools.length, tools }, null, 2));
|
|
578
|
+
return;
|
|
579
|
+
}
|
|
580
|
+
console.log(`\nFound ${tools.length} tools matching '${query || "*"}' (lane: ${lane}):\n`);
|
|
581
|
+
for (const t of tools) {
|
|
582
|
+
console.log(` • ${String(t.slug).padEnd(38)} [${String(t.lane).padEnd(16)}] (${t.riskLevel}, ${t.creditCost} cr)`);
|
|
583
|
+
console.log(` ${String(t.description || "").slice(0, 100)}`);
|
|
584
|
+
}
|
|
585
|
+
return;
|
|
586
|
+
}
|
|
587
|
+
const { engine } = getLocalContext();
|
|
268
588
|
const res = await engine.searchTools({
|
|
269
589
|
query,
|
|
270
590
|
lane,
|
|
271
|
-
limit
|
|
591
|
+
limit,
|
|
272
592
|
});
|
|
273
593
|
if (flags.json || !process.stdout.isTTY) {
|
|
274
594
|
console.log(JSON.stringify({ ok: true, count: res.total, ...res }, null, 2));
|
|
@@ -285,11 +605,34 @@ async function runCli() {
|
|
|
285
605
|
const slug = positional[1];
|
|
286
606
|
if (!slug)
|
|
287
607
|
throw new Error("Usage: muxo inspect <tool_slug>");
|
|
608
|
+
if (remoteUrl) {
|
|
609
|
+
const tool = await remoteFetch(`/api/v1/tools/${encodeURIComponent(slug)}`);
|
|
610
|
+
console.log(JSON.stringify(tool, null, 2));
|
|
611
|
+
return;
|
|
612
|
+
}
|
|
613
|
+
const { engine } = getLocalContext();
|
|
288
614
|
const tool = await engine.inspectTool(slug);
|
|
289
615
|
console.log(JSON.stringify(tool, null, 2));
|
|
290
616
|
return;
|
|
291
617
|
}
|
|
292
618
|
if (cmd === "connections") {
|
|
619
|
+
if (remoteUrl) {
|
|
620
|
+
const res = await remoteFetch("/api/v1/connections");
|
|
621
|
+
const allConns = Array.isArray(res.connections) ? res.connections : [];
|
|
622
|
+
const providerFilter = positional[1]
|
|
623
|
+
? positional[1].toLowerCase().replace(/^app\./, "")
|
|
624
|
+
: "";
|
|
625
|
+
const filtered = providerFilter
|
|
626
|
+
? allConns.filter((c) => c.providerSlug === providerFilter)
|
|
627
|
+
: allConns;
|
|
628
|
+
console.log(JSON.stringify({
|
|
629
|
+
ok: true,
|
|
630
|
+
connections: filtered,
|
|
631
|
+
activeCount: filtered.filter((c) => c.status === "active").length,
|
|
632
|
+
}, null, 2));
|
|
633
|
+
return;
|
|
634
|
+
}
|
|
635
|
+
const { engine, ctx } = getLocalContext();
|
|
293
636
|
const status = await engine.connectionStatus(ctx, {
|
|
294
637
|
provider: positional[1],
|
|
295
638
|
syncLive: flags.sync !== "false",
|
|
@@ -301,6 +644,37 @@ async function runCli() {
|
|
|
301
644
|
const provider = positional[1];
|
|
302
645
|
if (!provider)
|
|
303
646
|
throw new Error(`Usage: muxo ${cmd} <provider> [--wait] [--timeout 30]`);
|
|
647
|
+
if (remoteUrl) {
|
|
648
|
+
const created = await remoteFetch("/api/v1/connections", {
|
|
649
|
+
method: "POST",
|
|
650
|
+
body: {
|
|
651
|
+
provider,
|
|
652
|
+
lane: flags.lane,
|
|
653
|
+
callbackUrl: typeof flags.callback === "string" ? flags.callback : undefined,
|
|
654
|
+
},
|
|
655
|
+
});
|
|
656
|
+
const conn = created.connection || created;
|
|
657
|
+
const connection = { ...conn, provider: conn.providerSlug || provider };
|
|
658
|
+
if (flags.wait) {
|
|
659
|
+
const timeoutSeconds = flags.timeout ? Number(flags.timeout) : 15;
|
|
660
|
+
const deadline = Date.now() + timeoutSeconds * 1000;
|
|
661
|
+
let waited = {};
|
|
662
|
+
while (Date.now() < deadline) {
|
|
663
|
+
waited = await remoteFetch("/api/v1/connections/wait", {
|
|
664
|
+
method: "POST",
|
|
665
|
+
body: { provider },
|
|
666
|
+
});
|
|
667
|
+
if (waited.ready || waited.status === "active")
|
|
668
|
+
break;
|
|
669
|
+
await new Promise((r) => setTimeout(r, 1500));
|
|
670
|
+
}
|
|
671
|
+
console.log(JSON.stringify({ ok: true, connection, ...conn, waitResult: waited }, null, 2));
|
|
672
|
+
return;
|
|
673
|
+
}
|
|
674
|
+
console.log(JSON.stringify({ ok: true, connection, ...conn }, null, 2));
|
|
675
|
+
return;
|
|
676
|
+
}
|
|
677
|
+
const { engine, ctx } = getLocalContext();
|
|
304
678
|
const res = await engine.startConnection(ctx, {
|
|
305
679
|
provider,
|
|
306
680
|
lane: flags.lane,
|
|
@@ -323,6 +697,24 @@ async function runCli() {
|
|
|
323
697
|
const provider = positional[1];
|
|
324
698
|
if (!provider)
|
|
325
699
|
throw new Error("Usage: muxo wait <provider> [--timeout 15]");
|
|
700
|
+
const timeoutSeconds = flags.timeout ? Number(flags.timeout) : 15;
|
|
701
|
+
if (remoteUrl) {
|
|
702
|
+
const simulateCallback = Boolean(flags["simulate-callback"]);
|
|
703
|
+
const deadline = Date.now() + timeoutSeconds * 1000;
|
|
704
|
+
let waited = {};
|
|
705
|
+
do {
|
|
706
|
+
waited = await remoteFetch("/api/v1/connections/wait", {
|
|
707
|
+
method: "POST",
|
|
708
|
+
body: { provider, simulateCallback },
|
|
709
|
+
});
|
|
710
|
+
if (waited.ready || waited.status === "active" || simulateCallback)
|
|
711
|
+
break;
|
|
712
|
+
await new Promise((r) => setTimeout(r, 1500));
|
|
713
|
+
} while (Date.now() < deadline);
|
|
714
|
+
console.log(JSON.stringify({ ok: true, ...waited }, null, 2));
|
|
715
|
+
return;
|
|
716
|
+
}
|
|
717
|
+
const { engine, ctx } = getLocalContext();
|
|
326
718
|
if (flags["simulate-callback"]) {
|
|
327
719
|
await engine.handleOAuthCallback({
|
|
328
720
|
workspaceId: ctx.workspace.id,
|
|
@@ -330,7 +722,6 @@ async function runCli() {
|
|
|
330
722
|
status: "active",
|
|
331
723
|
});
|
|
332
724
|
}
|
|
333
|
-
const timeoutSeconds = flags.timeout ? Number(flags.timeout) : 15;
|
|
334
725
|
const waited = await engine.waitForConnection(ctx, {
|
|
335
726
|
provider,
|
|
336
727
|
timeoutSeconds,
|
|
@@ -344,6 +735,15 @@ async function runCli() {
|
|
|
344
735
|
throw new Error("Usage: muxo plan <tool_slug> [--input '{...}']");
|
|
345
736
|
const input = flags.input ? JSON.parse(String(flags.input)) : {};
|
|
346
737
|
const reason = flags.reason ? String(flags.reason) : "Planned via Muxo CLI";
|
|
738
|
+
if (remoteUrl) {
|
|
739
|
+
const planned = await remoteFetch("/api/v1/plans", {
|
|
740
|
+
method: "POST",
|
|
741
|
+
body: { toolSlug, input, reason },
|
|
742
|
+
});
|
|
743
|
+
console.log(JSON.stringify(planned, null, 2));
|
|
744
|
+
return;
|
|
745
|
+
}
|
|
746
|
+
const { engine, ctx } = getLocalContext();
|
|
347
747
|
const planned = await engine.planAction(ctx, { toolSlug, input, reason });
|
|
348
748
|
console.log(JSON.stringify(planned, null, 2));
|
|
349
749
|
return;
|
|
@@ -352,6 +752,12 @@ async function runCli() {
|
|
|
352
752
|
const planId = positional[1];
|
|
353
753
|
if (!planId)
|
|
354
754
|
throw new Error("Usage: muxo approve <plan_id>");
|
|
755
|
+
if (remoteUrl) {
|
|
756
|
+
const approved = await remoteFetch(`/api/v1/plans/${encodeURIComponent(planId)}/approve`, { method: "POST", body: {} });
|
|
757
|
+
console.log(JSON.stringify(approved.plan || approved, null, 2));
|
|
758
|
+
return;
|
|
759
|
+
}
|
|
760
|
+
const { engine, ctx } = getLocalContext();
|
|
355
761
|
const approved = engine.approvePlan(ctx, planId, "approved");
|
|
356
762
|
console.log(JSON.stringify(approved, null, 2));
|
|
357
763
|
return;
|
|
@@ -360,6 +766,12 @@ async function runCli() {
|
|
|
360
766
|
const planId = positional[1];
|
|
361
767
|
if (!planId)
|
|
362
768
|
throw new Error("Usage: muxo run <plan_id>");
|
|
769
|
+
if (remoteUrl) {
|
|
770
|
+
const executed = await remoteFetch(`/api/v1/plans/${encodeURIComponent(planId)}/execute`, { method: "POST", body: {} });
|
|
771
|
+
console.log(JSON.stringify(executed, null, 2));
|
|
772
|
+
return;
|
|
773
|
+
}
|
|
774
|
+
const { engine, ctx } = getLocalContext();
|
|
363
775
|
const plan = engine.getPlan(ctx, planId);
|
|
364
776
|
const result = await engine.executePlanForRisk(ctx, planId, plan.riskLevel);
|
|
365
777
|
console.log(JSON.stringify(result, null, 2));
|
|
@@ -369,6 +781,54 @@ async function runCli() {
|
|
|
369
781
|
let toolSlug = positional[1];
|
|
370
782
|
if (!toolSlug)
|
|
371
783
|
throw new Error(`Usage: muxo ${cmd} <tool_slug> [--input '{...}'] [--approve]`);
|
|
784
|
+
const input = flags.input ? JSON.parse(String(flags.input)) : {};
|
|
785
|
+
if (remoteUrl) {
|
|
786
|
+
if (cmd === "provision" && !toolSlug.includes(".")) {
|
|
787
|
+
const qs = new URLSearchParams({
|
|
788
|
+
query: toolSlug,
|
|
789
|
+
lane: "stripe_projects",
|
|
790
|
+
limit: "10",
|
|
791
|
+
});
|
|
792
|
+
const searched = await remoteFetch(`/api/v1/tools?${qs.toString()}`);
|
|
793
|
+
const tools = Array.isArray(searched.tools) ? searched.tools : [];
|
|
794
|
+
const createTool = tools.find((t) => String(t.slug).startsWith(`resource.${toolSlug.toLowerCase()}.create_`)) ||
|
|
795
|
+
tools.find((t) => String(t.slug).startsWith(`resource.${toolSlug.toLowerCase()}.`)) ||
|
|
796
|
+
tools[0];
|
|
797
|
+
if (createTool) {
|
|
798
|
+
toolSlug = String(createTool.slug);
|
|
799
|
+
}
|
|
800
|
+
}
|
|
801
|
+
const planned = await remoteFetch("/api/v1/plans", {
|
|
802
|
+
method: "POST",
|
|
803
|
+
body: { toolSlug, input, reason: `Direct CLI ${cmd}` },
|
|
804
|
+
});
|
|
805
|
+
const plan = planned.plan || planned;
|
|
806
|
+
if (plan.approvalStatus === "pending_approval") {
|
|
807
|
+
if (flags.approve || cmd === "provision") {
|
|
808
|
+
await remoteFetch(`/api/v1/plans/${encodeURIComponent(plan.id)}/approve`, { method: "POST", body: {} });
|
|
809
|
+
}
|
|
810
|
+
else {
|
|
811
|
+
console.log(JSON.stringify({
|
|
812
|
+
ok: false,
|
|
813
|
+
status: "pending_approval",
|
|
814
|
+
plan,
|
|
815
|
+
hint: `Pass --approve or run 'muxo approve ${plan.id}' to authorize this ${plan.riskLevel} operation.`,
|
|
816
|
+
}, null, 2));
|
|
817
|
+
return;
|
|
818
|
+
}
|
|
819
|
+
}
|
|
820
|
+
const result = await remoteFetch(`/api/v1/plans/${encodeURIComponent(plan.id)}/execute`, { method: "POST", body: {} });
|
|
821
|
+
console.log(JSON.stringify({
|
|
822
|
+
ok: true,
|
|
823
|
+
...result,
|
|
824
|
+
receipt: result.receipt
|
|
825
|
+
? { ...result.receipt, verified: true }
|
|
826
|
+
: undefined,
|
|
827
|
+
settlement: result.settlement || result.receipt?.supplierSettlement || null,
|
|
828
|
+
}, null, 2));
|
|
829
|
+
return;
|
|
830
|
+
}
|
|
831
|
+
const { store, engine, ctx } = getLocalContext();
|
|
372
832
|
if (cmd === "provision" && !toolSlug.includes(".")) {
|
|
373
833
|
const searched = await engine.searchTools({
|
|
374
834
|
query: toolSlug,
|
|
@@ -382,7 +842,6 @@ async function runCli() {
|
|
|
382
842
|
toolSlug = createTool.slug;
|
|
383
843
|
}
|
|
384
844
|
}
|
|
385
|
-
const input = flags.input ? JSON.parse(String(flags.input)) : {};
|
|
386
845
|
const planned = await engine.planAction(ctx, {
|
|
387
846
|
toolSlug,
|
|
388
847
|
input,
|
|
@@ -416,11 +875,40 @@ async function runCli() {
|
|
|
416
875
|
return;
|
|
417
876
|
}
|
|
418
877
|
if (cmd === "resources") {
|
|
878
|
+
if (remoteUrl) {
|
|
879
|
+
const res = await remoteFetch("/api/v1/resources");
|
|
880
|
+
console.log(JSON.stringify(res.resources || res, null, 2));
|
|
881
|
+
return;
|
|
882
|
+
}
|
|
883
|
+
const { store, ctx } = getLocalContext();
|
|
419
884
|
console.log(JSON.stringify(store.listResources(ctx.workspace.id), null, 2));
|
|
420
885
|
return;
|
|
421
886
|
}
|
|
422
887
|
if (cmd === "env" && positional[1] === "pull") {
|
|
423
|
-
const outFile = String(flags.out || ".env.muxo");
|
|
888
|
+
const outFile = String(flags.out || flags.output || ".env.muxo");
|
|
889
|
+
const resolvedPath = path.resolve(process.cwd(), outFile);
|
|
890
|
+
if (remoteUrl) {
|
|
891
|
+
const envRes = await remoteFetch("/api/v1/resources/env");
|
|
892
|
+
const vars = (envRes.variables || {});
|
|
893
|
+
const lines = typeof envRes.dotenv === "string" && envRes.dotenv.trim()
|
|
894
|
+
? envRes.dotenv
|
|
895
|
+
: [
|
|
896
|
+
`# Muxo Provisioned Environment`,
|
|
897
|
+
...Object.entries(vars).map(([k, v]) => `${k}=${JSON.stringify(v)}`),
|
|
898
|
+
"",
|
|
899
|
+
].join("\n");
|
|
900
|
+
fs.writeFileSync(resolvedPath, lines, { mode: 0o600 });
|
|
901
|
+
const keys = Object.keys(vars);
|
|
902
|
+
console.log(JSON.stringify({
|
|
903
|
+
ok: true,
|
|
904
|
+
outputFile: resolvedPath,
|
|
905
|
+
keysWritten: keys,
|
|
906
|
+
keys,
|
|
907
|
+
keyCount: keys.length,
|
|
908
|
+
}, null, 2));
|
|
909
|
+
return;
|
|
910
|
+
}
|
|
911
|
+
const { store, engine, ctx } = getLocalContext();
|
|
424
912
|
const workdirSecrets = await engine.stripeProjects
|
|
425
913
|
.pullEnvVarsFromWorkdir()
|
|
426
914
|
.catch(() => ({}));
|
|
@@ -431,7 +919,6 @@ async function runCli() {
|
|
|
431
919
|
...Object.entries(merged).map(([k, v]) => `${k}=${JSON.stringify(v)}`),
|
|
432
920
|
"",
|
|
433
921
|
];
|
|
434
|
-
const resolvedPath = path.resolve(process.cwd(), outFile);
|
|
435
922
|
fs.writeFileSync(resolvedPath, lines.join("\n"), { mode: 0o600 });
|
|
436
923
|
const keys = Object.keys(merged);
|
|
437
924
|
console.log(JSON.stringify({
|
|
@@ -445,6 +932,18 @@ async function runCli() {
|
|
|
445
932
|
}
|
|
446
933
|
if (cmd === "receipts") {
|
|
447
934
|
const receiptId = positional[1];
|
|
935
|
+
if (remoteUrl) {
|
|
936
|
+
if (receiptId) {
|
|
937
|
+
const res = await remoteFetch(`/api/v1/receipts/${encodeURIComponent(receiptId)}`);
|
|
938
|
+
console.log(JSON.stringify(res, null, 2));
|
|
939
|
+
}
|
|
940
|
+
else {
|
|
941
|
+
const runsRes = await remoteFetch("/api/v1/runs");
|
|
942
|
+
console.log(JSON.stringify(runsRes.runs || runsRes, null, 2));
|
|
943
|
+
}
|
|
944
|
+
return;
|
|
945
|
+
}
|
|
946
|
+
const { store, engine, ctx } = getLocalContext();
|
|
448
947
|
if (receiptId) {
|
|
449
948
|
console.log(JSON.stringify(engine.getReceipt(ctx, receiptId), null, 2));
|
|
450
949
|
}
|
|
@@ -457,6 +956,15 @@ async function runCli() {
|
|
|
457
956
|
const sub = cmd === "topup" ? "topup" : positional[1] || "status";
|
|
458
957
|
if (sub === "topup") {
|
|
459
958
|
const credits = Math.max(1, Number(flags.credits || (cmd === "topup" ? positional[1] : positional[2]) || 1000));
|
|
959
|
+
if (remoteUrl) {
|
|
960
|
+
const data = await remoteFetch("/api/v1/billing/topup", {
|
|
961
|
+
method: "POST",
|
|
962
|
+
body: { credits },
|
|
963
|
+
});
|
|
964
|
+
console.log(JSON.stringify(data, null, 2));
|
|
965
|
+
return;
|
|
966
|
+
}
|
|
967
|
+
const { store, ctx } = getLocalContext();
|
|
460
968
|
const usdPaid = (credits * 0.01).toFixed(2);
|
|
461
969
|
const refId = `cli_topup_${Date.now()}`;
|
|
462
970
|
const updated = store.addWorkspaceCredits({
|
|
@@ -476,6 +984,15 @@ async function runCli() {
|
|
|
476
984
|
return;
|
|
477
985
|
}
|
|
478
986
|
if (sub === "upgrade") {
|
|
987
|
+
if (remoteUrl) {
|
|
988
|
+
const data = await remoteFetch("/api/v1/billing/upgrade", {
|
|
989
|
+
method: "POST",
|
|
990
|
+
body: { tier: "starter", bonusCredits: 1000 },
|
|
991
|
+
});
|
|
992
|
+
console.log(JSON.stringify(data, null, 2));
|
|
993
|
+
return;
|
|
994
|
+
}
|
|
995
|
+
const { store, ctx } = getLocalContext();
|
|
479
996
|
const updated = store.upgradeWorkspaceToStarter({
|
|
480
997
|
workspaceId: ctx.workspace.id,
|
|
481
998
|
referenceId: `cli_upgrade_${Date.now()}`,
|
|
@@ -499,6 +1016,15 @@ async function runCli() {
|
|
|
499
1016
|
? "starter_subscription"
|
|
500
1017
|
: "credit_topup";
|
|
501
1018
|
const credits = flags.credits ? Number(flags.credits) : 1000;
|
|
1019
|
+
if (remoteUrl) {
|
|
1020
|
+
const data = await remoteFetch("/api/v1/billing/checkout", {
|
|
1021
|
+
method: "POST",
|
|
1022
|
+
body: { kind, credits },
|
|
1023
|
+
});
|
|
1024
|
+
console.log(JSON.stringify(data, null, 2));
|
|
1025
|
+
return;
|
|
1026
|
+
}
|
|
1027
|
+
const { engine, ctx } = getLocalContext();
|
|
502
1028
|
const session = await engine.stripeBilling.createCheckoutSession({
|
|
503
1029
|
workspace: ctx.workspace,
|
|
504
1030
|
customerEmail: ctx.user.email,
|
|
@@ -513,10 +1039,25 @@ async function runCli() {
|
|
|
513
1039
|
const sessionId = positional[2] || String(flags.session || "");
|
|
514
1040
|
if (!sessionId)
|
|
515
1041
|
throw new Error("Usage: muxo billing verify <session_id>");
|
|
1042
|
+
if (remoteUrl) {
|
|
1043
|
+
const data = await remoteFetch("/api/v1/billing/verify-session", {
|
|
1044
|
+
method: "POST",
|
|
1045
|
+
body: { sessionId },
|
|
1046
|
+
});
|
|
1047
|
+
console.log(JSON.stringify(data, null, 2));
|
|
1048
|
+
return;
|
|
1049
|
+
}
|
|
1050
|
+
const { engine } = getLocalContext();
|
|
516
1051
|
const verified = await engine.stripeBilling.verifyAndFulfillCheckoutSession(sessionId);
|
|
517
1052
|
console.log(JSON.stringify({ ok: true, ...verified }, null, 2));
|
|
518
1053
|
return;
|
|
519
1054
|
}
|
|
1055
|
+
if (remoteUrl) {
|
|
1056
|
+
const data = await remoteFetch("/api/v1/billing/status");
|
|
1057
|
+
console.log(JSON.stringify(data, null, 2));
|
|
1058
|
+
return;
|
|
1059
|
+
}
|
|
1060
|
+
const { store, ctx } = getLocalContext();
|
|
520
1061
|
const freshWs = store.getWorkspace(ctx.workspace.id) || ctx.workspace;
|
|
521
1062
|
console.log(JSON.stringify({
|
|
522
1063
|
ok: true,
|
|
@@ -532,7 +1073,6 @@ async function runCli() {
|
|
|
532
1073
|
return;
|
|
533
1074
|
}
|
|
534
1075
|
if (cmd === "byok" || cmd === "keys") {
|
|
535
|
-
const remoteUrl = typeof flags.url === "string" ? flags.url.replace(/\/+$/, "") : "";
|
|
536
1076
|
const sub = positional[1] || "list";
|
|
537
1077
|
if (sub === "set" || sub === "add" || sub === "prompt") {
|
|
538
1078
|
let provider = (positional[2] || String(flags.provider || "")).trim().toLowerCase();
|
|
@@ -552,17 +1092,14 @@ async function runCli() {
|
|
|
552
1092
|
throw new Error(`API key is required for provider '${provider}'.`);
|
|
553
1093
|
}
|
|
554
1094
|
if (remoteUrl) {
|
|
555
|
-
const
|
|
1095
|
+
const data = await remoteFetch("/api/v1/byok", {
|
|
556
1096
|
method: "POST",
|
|
557
|
-
|
|
558
|
-
"Content-Type": "application/json",
|
|
559
|
-
...(apiKeyFlag ? { Authorization: `Bearer ${apiKeyFlag}` } : {}),
|
|
560
|
-
},
|
|
561
|
-
body: JSON.stringify({ provider, secretKey }),
|
|
1097
|
+
body: { provider, secretKey },
|
|
562
1098
|
});
|
|
563
|
-
console.log(JSON.stringify(
|
|
1099
|
+
console.log(JSON.stringify(data, null, 2));
|
|
564
1100
|
return;
|
|
565
1101
|
}
|
|
1102
|
+
const { store, ctx } = getLocalContext();
|
|
566
1103
|
const record = store.setByokKey(ctx.workspace.id, provider, secretKey);
|
|
567
1104
|
console.log(JSON.stringify({
|
|
568
1105
|
ok: true,
|
|
@@ -577,13 +1114,11 @@ async function runCli() {
|
|
|
577
1114
|
if (!provider)
|
|
578
1115
|
throw new Error("Usage: muxo byok delete <provider>");
|
|
579
1116
|
if (remoteUrl) {
|
|
580
|
-
const
|
|
581
|
-
|
|
582
|
-
headers: apiKeyFlag ? { Authorization: `Bearer ${apiKeyFlag}` } : {},
|
|
583
|
-
});
|
|
584
|
-
console.log(JSON.stringify(await res.json(), null, 2));
|
|
1117
|
+
const data = await remoteFetch(`/api/v1/byok/${encodeURIComponent(provider)}`, { method: "DELETE" });
|
|
1118
|
+
console.log(JSON.stringify(data, null, 2));
|
|
585
1119
|
return;
|
|
586
1120
|
}
|
|
1121
|
+
const { store, ctx } = getLocalContext();
|
|
587
1122
|
store.deleteByokKey(ctx.workspace.id, provider);
|
|
588
1123
|
console.log(JSON.stringify({
|
|
589
1124
|
ok: true,
|
|
@@ -594,12 +1129,11 @@ async function runCli() {
|
|
|
594
1129
|
return;
|
|
595
1130
|
}
|
|
596
1131
|
if (remoteUrl) {
|
|
597
|
-
const
|
|
598
|
-
|
|
599
|
-
});
|
|
600
|
-
console.log(JSON.stringify(await res.json(), null, 2));
|
|
1132
|
+
const data = await remoteFetch("/api/v1/byok");
|
|
1133
|
+
console.log(JSON.stringify(data, null, 2));
|
|
601
1134
|
return;
|
|
602
1135
|
}
|
|
1136
|
+
const { store, ctx } = getLocalContext();
|
|
603
1137
|
console.log(JSON.stringify({
|
|
604
1138
|
ok: true,
|
|
605
1139
|
keys: store.listByokKeys(ctx.workspace.id),
|
|
@@ -608,7 +1142,6 @@ async function runCli() {
|
|
|
608
1142
|
return;
|
|
609
1143
|
}
|
|
610
1144
|
if (cmd === "do" || cmd === "ask" || cmd === "nl") {
|
|
611
|
-
const remoteUrl = typeof flags.url === "string" ? flags.url.replace(/\/+$/, "") : "";
|
|
612
1145
|
let promptText = positional.slice(1).join(" ").trim() ||
|
|
613
1146
|
(typeof flags.prompt === "string" ? flags.prompt : "");
|
|
614
1147
|
if (!promptText) {
|
|
@@ -617,10 +1150,6 @@ async function runCli() {
|
|
|
617
1150
|
if (!promptText) {
|
|
618
1151
|
throw new Error('Usage: muxo do "<natural language instruction>"');
|
|
619
1152
|
}
|
|
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
1153
|
const planOnly = flags["plan-only"] === true || flags.plan === true;
|
|
625
1154
|
const autoApprove = flags["no-approve"] ? false : true;
|
|
626
1155
|
const fundingMode = flags.byok || flags.funding === "byok"
|
|
@@ -629,21 +1158,33 @@ async function runCli() {
|
|
|
629
1158
|
? "muxo_funded"
|
|
630
1159
|
: undefined;
|
|
631
1160
|
if (remoteUrl) {
|
|
632
|
-
|
|
1161
|
+
if (flags.byok &&
|
|
1162
|
+
typeof flags["byok-key"] === "string" &&
|
|
1163
|
+
typeof flags["byok-provider"] === "string") {
|
|
1164
|
+
await remoteFetch("/api/v1/byok", {
|
|
1165
|
+
method: "POST",
|
|
1166
|
+
body: {
|
|
1167
|
+
provider: String(flags["byok-provider"]),
|
|
1168
|
+
secretKey: String(flags["byok-key"]),
|
|
1169
|
+
},
|
|
1170
|
+
});
|
|
1171
|
+
}
|
|
1172
|
+
const data = await remoteFetch("/api/v1/do", {
|
|
633
1173
|
method: "POST",
|
|
634
|
-
|
|
635
|
-
"Content-Type": "application/json",
|
|
636
|
-
...(apiKeyFlag ? { Authorization: `Bearer ${apiKeyFlag}` } : {}),
|
|
637
|
-
},
|
|
638
|
-
body: JSON.stringify({
|
|
1174
|
+
body: {
|
|
639
1175
|
prompt: promptText,
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
1176
|
+
autoExecute: !planOnly,
|
|
1177
|
+
approveRisky: autoApprove,
|
|
1178
|
+
fundingMode,
|
|
1179
|
+
},
|
|
643
1180
|
});
|
|
644
|
-
console.log(JSON.stringify(
|
|
1181
|
+
console.log(JSON.stringify(data, null, 2));
|
|
645
1182
|
return;
|
|
646
1183
|
}
|
|
1184
|
+
const { store, engine, ctx } = getLocalContext();
|
|
1185
|
+
if (flags.byok && typeof flags["byok-key"] === "string" && typeof flags["byok-provider"] === "string") {
|
|
1186
|
+
store.setByokKey(ctx.workspace.id, String(flags["byok-provider"]), String(flags["byok-key"]));
|
|
1187
|
+
}
|
|
647
1188
|
const result = await engine.doNaturalLanguage(ctx, {
|
|
648
1189
|
prompt: promptText,
|
|
649
1190
|
autoApprove,
|
|
@@ -653,25 +1194,114 @@ async function runCli() {
|
|
|
653
1194
|
console.log(JSON.stringify(result, null, 2));
|
|
654
1195
|
return;
|
|
655
1196
|
}
|
|
656
|
-
if (cmd === "tui" || cmd === "
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
const
|
|
660
|
-
|
|
1197
|
+
if (cmd === "tui" || cmd === "interactive") {
|
|
1198
|
+
if (remoteUrl) {
|
|
1199
|
+
const statusData = await remoteFetch("/api/v1/billing/status");
|
|
1200
|
+
const wsNow = (statusData.workspace || {});
|
|
1201
|
+
const keysNow = Array.isArray(statusData.byokKeys)
|
|
1202
|
+
? statusData.byokKeys.filter((k) => k.configured)
|
|
1203
|
+
: [];
|
|
1204
|
+
if (flags.json || flags["non-interactive"] || flags.once) {
|
|
1205
|
+
console.log(JSON.stringify({
|
|
1206
|
+
ok: true,
|
|
1207
|
+
tui: "ready",
|
|
1208
|
+
mode: "tui_snapshot",
|
|
1209
|
+
workspace: wsNow,
|
|
1210
|
+
byokKeys: keysNow,
|
|
1211
|
+
supportedByokProviders: Object.keys(BYOK_PROVIDER_CATALOG),
|
|
1212
|
+
}, null, 2));
|
|
1213
|
+
return;
|
|
1214
|
+
}
|
|
1215
|
+
const hasSupplierByok = keysNow.some((k) => k.category === "supplier");
|
|
1216
|
+
console.log("\n┌──────────────────────────────────────────────────────────────────────────┐");
|
|
1217
|
+
console.log("│ ⚡ MUXO INTERACTIVE TUI — Execution, Cloud Infra, Memory & Governance │");
|
|
1218
|
+
console.log("├──────────────────────────────────────────────────────────────────────────┤");
|
|
1219
|
+
console.log(`│ Workspace : ${String(wsNow.name || "Muxo").padEnd(28)} Tier : ${String(wsNow.tier || "free").toUpperCase().padEnd(16)}│`);
|
|
1220
|
+
console.log(`│ Credits : ${String(wsNow.creditsBalance ?? 250).padEnd(28)} Funding : ${(hasSupplierByok ? "BYOK (0 cr)" : "muxo_funded").padEnd(16)}│`);
|
|
1221
|
+
console.log(`│ BYOK Keys : ${String(keysNow.length).padEnd(28)} API : ${remoteUrl.slice(0, 16).padEnd(16)}│`);
|
|
1222
|
+
console.log("├──────────────────────────────────────────────────────────────────────────┤");
|
|
1223
|
+
console.log("│ [1] ✨ Run in Plain English (Natural Language Router: muxo do) │");
|
|
1224
|
+
console.log("│ [2] 🔑 Configure BYOK API Key (OpenAI, Anthropic, Gemini, Firecrawl...) │");
|
|
1225
|
+
console.log("│ [3] 💳 Billing: Top Up +1,000 Credits or Upgrade to Starter Plan │");
|
|
1226
|
+
console.log("│ [4] 🔗 Connect OAuth App (GitHub, Gmail, Slack, Notion, Linear) │");
|
|
1227
|
+
console.log("│ [5] ☁️ Provision Cloud Database (Turso SQLite, Neon Postgres, Redis) │");
|
|
1228
|
+
console.log("│ [q] Exit TUI │");
|
|
1229
|
+
console.log("└──────────────────────────────────────────────────────────────────────────┘");
|
|
1230
|
+
const choice = (await promptUserLine("\nSelect an option [1-5, q] (or type any natural language command): ")).trim();
|
|
1231
|
+
if (!choice || choice.toLowerCase() === "q" || choice.toLowerCase() === "exit") {
|
|
1232
|
+
console.log("Exited Muxo TUI.");
|
|
1233
|
+
return;
|
|
1234
|
+
}
|
|
1235
|
+
if (choice === "1") {
|
|
1236
|
+
const nlPrompt = await promptUserLine("Ask Muxo in plain English: ");
|
|
1237
|
+
if (nlPrompt) {
|
|
1238
|
+
const res = await remoteFetch("/api/v1/do", {
|
|
1239
|
+
method: "POST",
|
|
1240
|
+
body: { prompt: nlPrompt, autoExecute: true, approveRisky: true },
|
|
1241
|
+
});
|
|
1242
|
+
console.log(JSON.stringify(res, null, 2));
|
|
1243
|
+
}
|
|
1244
|
+
return;
|
|
1245
|
+
}
|
|
1246
|
+
if (choice === "2") {
|
|
1247
|
+
const provider = (await promptUserLine("Provider (openai, anthropic, openrouter, gemini, composio, stripe, supermemory, firecrawl, exa): ")).toLowerCase();
|
|
1248
|
+
const secretKey = await promptUserLine(`Paste API key for ${provider}: `);
|
|
1249
|
+
if (provider && secretKey) {
|
|
1250
|
+
const saved = await remoteFetch("/api/v1/byok", {
|
|
1251
|
+
method: "POST",
|
|
1252
|
+
body: { provider, secretKey },
|
|
1253
|
+
});
|
|
1254
|
+
console.log(JSON.stringify(saved, null, 2));
|
|
1255
|
+
}
|
|
1256
|
+
return;
|
|
1257
|
+
}
|
|
1258
|
+
if (choice === "3") {
|
|
1259
|
+
const action = (await promptUserLine("Type 'upgrade' for Starter Plan or credit amount (default 1000): ")).toLowerCase();
|
|
1260
|
+
if (action === "upgrade") {
|
|
1261
|
+
const up = await remoteFetch("/api/v1/billing/upgrade", {
|
|
1262
|
+
method: "POST",
|
|
1263
|
+
body: { tier: "starter", bonusCredits: 1000 },
|
|
1264
|
+
});
|
|
1265
|
+
console.log(JSON.stringify(up, null, 2));
|
|
1266
|
+
}
|
|
1267
|
+
else {
|
|
1268
|
+
const cr = Math.max(100, Number(action) || 1000);
|
|
1269
|
+
const up = await remoteFetch("/api/v1/billing/topup", {
|
|
1270
|
+
method: "POST",
|
|
1271
|
+
body: { credits: cr },
|
|
1272
|
+
});
|
|
1273
|
+
console.log(JSON.stringify(up, null, 2));
|
|
1274
|
+
}
|
|
1275
|
+
return;
|
|
1276
|
+
}
|
|
1277
|
+
if (choice === "4") {
|
|
1278
|
+
const provider = (await promptUserLine("OAuth Provider (github, gmail, slack, notion, linear): ")) || "github";
|
|
1279
|
+
const conn = await remoteFetch("/api/v1/connections", {
|
|
1280
|
+
method: "POST",
|
|
1281
|
+
body: { provider },
|
|
1282
|
+
});
|
|
1283
|
+
console.log(JSON.stringify(conn, null, 2));
|
|
1284
|
+
return;
|
|
1285
|
+
}
|
|
1286
|
+
if (choice === "5") {
|
|
1287
|
+
const dbPrompt = (await promptUserLine("Database to provision (e.g. 'Provision Turso database my-app-db'): ")) || "Provision Turso database my-app-db";
|
|
1288
|
+
const res = await remoteFetch("/api/v1/do", {
|
|
1289
|
+
method: "POST",
|
|
1290
|
+
body: { prompt: dbPrompt, autoExecute: true, approveRisky: true },
|
|
1291
|
+
});
|
|
1292
|
+
console.log(JSON.stringify(res, null, 2));
|
|
1293
|
+
return;
|
|
1294
|
+
}
|
|
1295
|
+
const res = await remoteFetch("/api/v1/do", {
|
|
1296
|
+
method: "POST",
|
|
1297
|
+
body: { prompt: choice, autoExecute: true, approveRisky: true },
|
|
661
1298
|
});
|
|
662
|
-
|
|
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));
|
|
1299
|
+
console.log(JSON.stringify(res, null, 2));
|
|
671
1300
|
return;
|
|
672
1301
|
}
|
|
1302
|
+
const { store, engine, ctx } = getLocalContext();
|
|
673
1303
|
const freshWs = store.getWorkspace(ctx.workspace.id) || ctx.workspace;
|
|
674
|
-
const byokKeys = store.listByokKeys(ctx.workspace.id);
|
|
1304
|
+
const byokKeys = store.listByokKeys(ctx.workspace.id).filter((k) => k.configured);
|
|
675
1305
|
const conns = store.listConnections(ctx.workspace.id);
|
|
676
1306
|
const resources = store.listResources(ctx.workspace.id);
|
|
677
1307
|
const gov = engine.governance.getStatus(freshWs);
|
|
@@ -699,7 +1329,7 @@ async function runCli() {
|
|
|
699
1329
|
}
|
|
700
1330
|
const printBanner = () => {
|
|
701
1331
|
const wsNow = store.getWorkspace(ctx.workspace.id) || ctx.workspace;
|
|
702
|
-
const keysNow = store.listByokKeys(
|
|
1332
|
+
const keysNow = store.listByokKeys(wsNow.id).filter((k) => k.configured);
|
|
703
1333
|
const hasSupplierByok = keysNow.some((k) => k.category === "supplier");
|
|
704
1334
|
console.log("\n┌──────────────────────────────────────────────────────────────────────────┐");
|
|
705
1335
|
console.log("│ ⚡ MUXO INTERACTIVE TUI — Execution, Cloud Infra, Memory & Governance │");
|
|
@@ -709,7 +1339,7 @@ async function runCli() {
|
|
|
709
1339
|
console.log(`│ BYOK Keys : ${String(keysNow.length).padEnd(28)} DID : ${gov.agentDid.slice(0, 16)}│`);
|
|
710
1340
|
console.log("├──────────────────────────────────────────────────────────────────────────┤");
|
|
711
1341
|
console.log("│ [1] ✨ Run in Plain English (Natural Language Router: muxo do) │");
|
|
712
|
-
console.log("│ [2] 🔑 Configure BYOK API Key (OpenAI, Anthropic,
|
|
1342
|
+
console.log("│ [2] 🔑 Configure BYOK API Key (OpenAI, Anthropic, Gemini, Firecrawl...) │");
|
|
713
1343
|
console.log("│ [3] 💳 Billing: Top Up +1,000 Credits or Upgrade to Starter Plan │");
|
|
714
1344
|
console.log("│ [4] 🔗 Connect OAuth App (GitHub, Gmail, Slack, Notion, Linear) │");
|
|
715
1345
|
console.log("│ [5] ☁️ Provision Cloud Database (Turso SQLite, Neon Postgres, Redis) │");
|
|
@@ -784,6 +1414,18 @@ async function runCli() {
|
|
|
784
1414
|
const content = positional.slice(2).join(" ") || String(flags.content || "");
|
|
785
1415
|
if (!content)
|
|
786
1416
|
throw new Error("Usage: muxo memory add <text>");
|
|
1417
|
+
if (remoteUrl) {
|
|
1418
|
+
const res = await remoteFetch("/api/v1/memory", {
|
|
1419
|
+
method: "POST",
|
|
1420
|
+
body: {
|
|
1421
|
+
content,
|
|
1422
|
+
title: flags.title ? String(flags.title) : content.slice(0, 60),
|
|
1423
|
+
},
|
|
1424
|
+
});
|
|
1425
|
+
console.log(JSON.stringify(res, null, 2));
|
|
1426
|
+
return;
|
|
1427
|
+
}
|
|
1428
|
+
const { engine, ctx } = getLocalContext();
|
|
787
1429
|
const entry = await engine.addWorkspaceMemory(ctx, {
|
|
788
1430
|
content,
|
|
789
1431
|
title: flags.title ? String(flags.title) : content.slice(0, 60),
|
|
@@ -791,6 +1433,16 @@ async function runCli() {
|
|
|
791
1433
|
console.log(JSON.stringify({ ok: true, memory: entry }, null, 2));
|
|
792
1434
|
return;
|
|
793
1435
|
}
|
|
1436
|
+
if (remoteUrl) {
|
|
1437
|
+
const res = await remoteFetch("/api/v1/memory");
|
|
1438
|
+
console.log(JSON.stringify({
|
|
1439
|
+
ok: true,
|
|
1440
|
+
...res,
|
|
1441
|
+
localMemories: res.records || [],
|
|
1442
|
+
}, null, 2));
|
|
1443
|
+
return;
|
|
1444
|
+
}
|
|
1445
|
+
const { engine, ctx } = getLocalContext();
|
|
794
1446
|
const query = sub === "recall" || sub === "search"
|
|
795
1447
|
? positional.slice(2).join(" ") || flags.query || undefined
|
|
796
1448
|
: positional.slice(1).join(" ") || flags.query || undefined;
|
|
@@ -803,6 +1455,18 @@ async function runCli() {
|
|
|
803
1455
|
return;
|
|
804
1456
|
}
|
|
805
1457
|
if (cmd === "governance") {
|
|
1458
|
+
if (remoteUrl) {
|
|
1459
|
+
const res = await remoteFetch("/api/v1/governance");
|
|
1460
|
+
console.log(JSON.stringify({
|
|
1461
|
+
ok: true,
|
|
1462
|
+
did: res.governance?.agentDid,
|
|
1463
|
+
chainValid: res.governance?.auditIntegrityValid ?? true,
|
|
1464
|
+
ringName: "Ring 2 (Standard)",
|
|
1465
|
+
...res,
|
|
1466
|
+
}, null, 2));
|
|
1467
|
+
return;
|
|
1468
|
+
}
|
|
1469
|
+
const { engine, ctx } = getLocalContext();
|
|
806
1470
|
const status = engine.governance.getGovernanceStatus(ctx.workspace);
|
|
807
1471
|
const summary = engine.governance.getStatus(ctx.workspace);
|
|
808
1472
|
console.log(JSON.stringify({
|
|
@@ -841,23 +1505,41 @@ async function runCli() {
|
|
|
841
1505
|
// Natural Language fallback: if user passed plain English directly (`muxo "Audit https://muxo.ai for SEO"`)
|
|
842
1506
|
if (cmd !== "help" && !flags.help && !flags.h && positional.length > 0) {
|
|
843
1507
|
const promptText = positional.join(" ").trim();
|
|
1508
|
+
const planOnly = flags["plan-only"] === true || flags.plan === true;
|
|
1509
|
+
const autoApprove = flags["no-approve"] ? false : true;
|
|
1510
|
+
const fundingMode = flags.byok || flags.funding === "byok"
|
|
1511
|
+
? "byok"
|
|
1512
|
+
: flags.funding === "muxo_funded"
|
|
1513
|
+
? "muxo_funded"
|
|
1514
|
+
: undefined;
|
|
1515
|
+
if (remoteUrl) {
|
|
1516
|
+
const data = await remoteFetch("/api/v1/do", {
|
|
1517
|
+
method: "POST",
|
|
1518
|
+
body: {
|
|
1519
|
+
prompt: promptText,
|
|
1520
|
+
autoExecute: !planOnly,
|
|
1521
|
+
approveRisky: autoApprove,
|
|
1522
|
+
fundingMode,
|
|
1523
|
+
},
|
|
1524
|
+
});
|
|
1525
|
+
console.log(JSON.stringify(data, null, 2));
|
|
1526
|
+
return;
|
|
1527
|
+
}
|
|
1528
|
+
const { engine, ctx } = getLocalContext();
|
|
844
1529
|
const result = await engine.doNaturalLanguage(ctx, {
|
|
845
1530
|
prompt: promptText,
|
|
846
|
-
autoApprove
|
|
847
|
-
planOnly
|
|
848
|
-
fundingMode
|
|
849
|
-
? "byok"
|
|
850
|
-
: flags.funding === "muxo_funded"
|
|
851
|
-
? "muxo_funded"
|
|
852
|
-
: undefined,
|
|
1531
|
+
autoApprove,
|
|
1532
|
+
planOnly,
|
|
1533
|
+
fundingMode,
|
|
853
1534
|
});
|
|
854
1535
|
console.log(JSON.stringify(result, null, 2));
|
|
855
1536
|
return;
|
|
856
1537
|
}
|
|
857
1538
|
console.log(`
|
|
858
|
-
Muxo CLI —
|
|
1539
|
+
Muxo CLI — Unified Agent Execution, Cloud Infrastructure, Memory & Safety Platform
|
|
859
1540
|
|
|
860
1541
|
Natural Language & Interactive TUI:
|
|
1542
|
+
muxo setup 1-command auto-signup + MCP setup (.mcp.json + ~/.muxo/config.json)
|
|
861
1543
|
muxo do "<instruction>" Execute any goal in plain English (LLM/semantic router -> plan -> execute)
|
|
862
1544
|
muxo ask "<instruction>" [--plan-only] Alias for 'muxo do' (pass --plan-only to inspect plan before running)
|
|
863
1545
|
muxo tui Launch interactive Terminal UI dashboard (BYOK, Billing, OAuth, Infra)
|
|
@@ -867,28 +1549,32 @@ Core Commands:
|
|
|
867
1549
|
muxo login [--api-key <key> | --signup] Sign in or create an autonomous workspace (~/.muxo/config.json)
|
|
868
1550
|
muxo logout Remove saved CLI authentication config
|
|
869
1551
|
muxo claim <owner_email> Generate a human owner claim link for this workspace
|
|
870
|
-
muxo whoami Show workspace profile, plan,
|
|
871
|
-
muxo search <query> [--lane <lane>] Search across Instant,
|
|
1552
|
+
muxo whoami Show workspace profile, plan, agent identity, and credit balance
|
|
1553
|
+
muxo search <query> [--lane <lane>] Search across Instant Tools, Connected Apps, Cloud Infra & Billing
|
|
872
1554
|
muxo inspect <tool_slug> Inspect tool schema, risk level, and credit cost
|
|
873
|
-
muxo connections [--sync true|false] List
|
|
1555
|
+
muxo connections [--sync true|false] List Connected Apps & Cloud Infrastructure provider connections
|
|
874
1556
|
muxo link <provider> [--wait] Start OAuth handoff for a service and optionally wait
|
|
875
1557
|
muxo connect <provider> [--wait] Alias for 'muxo link'
|
|
876
1558
|
muxo wait <provider> [--timeout 15] Poll until a pending OAuth connection handoff becomes active
|
|
877
1559
|
muxo plan <tool_slug> --input '{...}' Create a governed execution plan (accepts natural language too)
|
|
878
1560
|
muxo approve <plan_id> Approve a pending high-risk plan
|
|
879
|
-
muxo run <plan_id> Execute an approved plan and issue a
|
|
1561
|
+
muxo run <plan_id> Execute an approved plan and issue a verifiable audit record
|
|
880
1562
|
muxo exec <tool_slug> --input '{...}' Plan and execute in one step (pass --approve for high-risk)
|
|
881
|
-
muxo resources List provisioned
|
|
1563
|
+
muxo resources List provisioned Muxo Cloud Infrastructure resources
|
|
882
1564
|
muxo env pull [--out .env.muxo] Decrypt and write provisioned credentials to local .env
|
|
883
|
-
muxo receipts [<receipt_id>] List or
|
|
1565
|
+
muxo receipts [<receipt_id>] List or verify execution audit records
|
|
884
1566
|
muxo billing [status|topup|upgrade|checkout] Manage credits, upgrade to Starter, or inspect settlements
|
|
885
|
-
muxo memory [<query>] Recall
|
|
886
|
-
muxo governance Inspect
|
|
1567
|
+
muxo memory [<query>] Recall Muxo Workspace Memory & hybrid context
|
|
1568
|
+
muxo governance Inspect Muxo Safety & Approvals identity and audit chain
|
|
887
1569
|
muxo serve [--port 4310] Start unified HTTP Console, Landing, OAuth Callback & MCP server
|
|
888
1570
|
muxo mcp Run stdio MCP server (20 canonical tools)
|
|
889
1571
|
`);
|
|
890
1572
|
}
|
|
891
|
-
runCli()
|
|
1573
|
+
runCli()
|
|
1574
|
+
.then(() => {
|
|
1575
|
+
process.exit(0);
|
|
1576
|
+
})
|
|
1577
|
+
.catch((err) => {
|
|
892
1578
|
console.error("Error:", err?.message || err);
|
|
893
1579
|
process.exit(1);
|
|
894
1580
|
});
|