@moxxy/cli 1.2.8 → 1.2.10

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@moxxy/cli",
3
- "version": "1.2.8",
3
+ "version": "1.2.10",
4
4
  "description": "CLI for the Moxxy agentic framework — manage agents, skills, plugins, channels, and vaults from the terminal",
5
5
  "type": "module",
6
6
  "license": "MIT",
package/src/cli.js CHANGED
@@ -222,7 +222,9 @@ async function main() {
222
222
  setup: { label: 'Setup', hint: 'init, gateway, doctor' },
223
223
  agents: { label: 'Agents', hint: 'agents, skills, templates' },
224
224
  security: { label: 'Security', hint: 'auth tokens & secrets' },
225
- integrations: { label: 'Integrations', hint: 'providers, channels, MCP, plugins' },
225
+ integrations: { label: 'Integrations', hint: 'channels, MCP' },
226
+ providers: { label: 'Providers', hint: 'manage AI providers' },
227
+ plugins: { label: 'Plugins', hint: 'manage plugins & extensions' },
226
228
  tools: { label: 'Tools', hint: 'events stream' },
227
229
  system: { label: 'System', hint: 'settings, update & uninstall' },
228
230
  };
@@ -243,12 +245,16 @@ async function main() {
243
245
  { value: 'vault', label: 'Vault', hint: 'manage secrets' },
244
246
  ],
245
247
  integrations: [
246
- { value: 'provider', label: 'Provider', hint: 'list providers' },
247
248
  { value: 'channel', label: 'Channel', hint: 'manage Telegram/Discord channels' },
248
249
  { value: 'mcp', label: 'MCP', hint: 'manage MCP servers for agents' },
249
- { value: 'plugin', label: 'Plugin', hint: 'manage plugins & extensions' },
250
250
  { value: 'heartbeat', label: 'Heartbeat', hint: 'schedule heartbeat rules' },
251
251
  ],
252
+ providers: [
253
+ { value: 'provider', label: 'Provider', hint: 'list providers' },
254
+ ],
255
+ plugins: [
256
+ { value: 'plugin', label: 'Plugin', hint: 'manage plugins & extensions' },
257
+ ],
252
258
  tools: [
253
259
  { value: 'events', label: 'Events', hint: 'stream live events' },
254
260
  ],
@@ -298,13 +304,18 @@ async function main() {
298
304
  const submenu = SUBMENUS[selected];
299
305
  if (!submenu) continue;
300
306
 
301
- const subSelected = await p.select({
302
- message: `${MENU_GROUPS[selected].label}`,
303
- options: submenu,
304
- });
307
+ let subSelected;
308
+ if (submenu.length === 1) {
309
+ subSelected = submenu[0].value;
310
+ } else {
311
+ subSelected = await p.select({
312
+ message: `${MENU_GROUPS[selected].label}`,
313
+ options: submenu,
314
+ });
305
315
 
306
- if (p.isCancel(subSelected)) {
307
- continue;
316
+ if (p.isCancel(subSelected)) {
317
+ continue;
318
+ }
308
319
  }
309
320
 
310
321
  try {
@@ -1,9 +1,24 @@
1
- import { p, handleCancel, withSpinner, showResult } from '../ui.js';
1
+ import { p, handleCancel, isInteractive, withSpinner, showResult } from '../ui.js';
2
2
  import { showHelp } from '../help.js';
3
3
  import { parseFlags } from './auth.js';
4
4
 
5
5
  export async function runChannel(client, args) {
6
- const [subcommand, ...rest] = args;
6
+ let [subcommand, ...rest] = args;
7
+
8
+ if (!subcommand && isInteractive()) {
9
+ subcommand = await p.select({
10
+ message: 'Channel action',
11
+ options: [
12
+ { value: 'list', label: 'List channels', hint: 'show registered channels' },
13
+ { value: 'create', label: 'Create channel', hint: 'register a new channel' },
14
+ { value: 'pair', label: 'Pair channel', hint: 'bind a channel to an agent' },
15
+ { value: 'bindings', label: 'List bindings', hint: 'show channel-agent bindings' },
16
+ { value: 'unbind', label: 'Unbind channel', hint: 'remove a channel-agent binding' },
17
+ { value: 'delete', label: 'Delete channel', hint: 'remove a channel' },
18
+ ],
19
+ });
20
+ handleCancel(subcommand);
21
+ }
7
22
 
8
23
  switch (subcommand) {
9
24
  case 'create':
@@ -340,27 +340,30 @@ function sleep(ms) {
340
340
  }
341
341
 
342
342
  function tryOpenUrl(url) {
343
- let cmd;
344
- let args;
343
+ const candidates = [];
345
344
 
346
345
  if (process.platform === 'darwin') {
347
- cmd = 'open';
348
- args = [url];
346
+ candidates.push({ cmd: 'open', args: [url] });
349
347
  } else if (process.platform === 'win32') {
350
- cmd = 'cmd';
351
- args = ['/c', 'start', '', url];
348
+ candidates.push({ cmd: 'cmd', args: ['/c', 'start', '', url] });
352
349
  } else {
353
- cmd = 'xdg-open';
354
- args = [url];
350
+ candidates.push(
351
+ { cmd: 'xdg-open', args: [url] },
352
+ { cmd: 'sensible-browser', args: [url] },
353
+ { cmd: 'x-www-browser', args: [url] },
354
+ );
355
355
  }
356
356
 
357
- try {
358
- const child = spawn(cmd, args, { stdio: 'ignore', detached: true });
359
- child.unref();
360
- return true;
361
- } catch {
362
- return false;
357
+ for (const { cmd, args } of candidates) {
358
+ try {
359
+ const child = spawn(cmd, args, { stdio: 'ignore', detached: true });
360
+ child.unref();
361
+ return true;
362
+ } catch {
363
+ // try next candidate
364
+ }
363
365
  }
366
+ return false;
364
367
  }
365
368
 
366
369
  function createCodeVerifier() {