plazbot-cli 0.4.0 → 0.5.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/README.md +67 -111
- package/dist/cli.js +26 -11
- package/dist/commands/agent/ai-config.js +264 -63
- package/dist/commands/agent/chat.js +16 -11
- package/dist/commands/agent/copy.js +49 -13
- package/dist/commands/agent/create.js +62 -17
- package/dist/commands/agent/delete.js +50 -39
- package/dist/commands/agent/enable-widget.js +47 -27
- package/dist/commands/agent/export.js +179 -88
- package/dist/commands/agent/files.js +155 -73
- package/dist/commands/agent/get.js +24 -16
- package/dist/commands/agent/index.js +12 -10
- package/dist/commands/agent/list.js +20 -11
- package/dist/commands/agent/monitor.js +101 -53
- package/dist/commands/agent/on-message.js +55 -32
- package/dist/commands/agent/set.js +230 -82
- package/dist/commands/agent/templates.js +259 -156
- package/dist/commands/agent/tools.js +356 -123
- package/dist/commands/agent/update.js +69 -28
- package/dist/commands/agent/validate.js +72 -40
- package/dist/commands/agent/wizard.js +240 -329
- package/dist/commands/auth/browser-login.js +37 -31
- package/dist/commands/auth/login.js +49 -45
- package/dist/commands/auth/logout.js +20 -11
- package/dist/commands/auth/status.js +36 -12
- package/dist/commands/auth/workspace.js +61 -27
- package/dist/commands/portal/add-agent.js +106 -45
- package/dist/commands/portal/add-link.js +25 -28
- package/dist/commands/portal/clear-links.js +39 -19
- package/dist/commands/portal/create.js +66 -37
- package/dist/commands/portal/delete.js +40 -45
- package/dist/commands/portal/get.js +21 -54
- package/dist/commands/portal/index.js +12 -12
- package/dist/commands/portal/list.js +34 -52
- package/dist/commands/portal/shared.js +92 -0
- package/dist/commands/portal/update.js +100 -70
- package/dist/commands/whatsapp/broadcast.js +169 -77
- package/dist/commands/whatsapp/channels.js +167 -65
- package/dist/commands/whatsapp/chat.js +45 -46
- package/dist/commands/whatsapp/connect-flow.js +16 -15
- package/dist/commands/whatsapp/connect.js +36 -21
- package/dist/commands/whatsapp/delete-webhook.js +42 -25
- package/dist/commands/whatsapp/index.js +15 -16
- package/dist/commands/whatsapp/register-webhook.js +43 -26
- package/dist/commands/whatsapp/send-template.js +62 -61
- package/dist/commands/whatsapp/send.js +46 -33
- package/dist/commands/whatsapp/setup.js +62 -52
- package/dist/commands/whatsapp/shared.js +75 -0
- package/dist/commands/whatsapp/widget.js +82 -45
- package/dist/commands/workers/deploy.js +80 -58
- package/dist/commands/workers/index.js +8 -8
- package/dist/commands/workers/list.js +42 -20
- package/dist/commands/workers/logs.js +139 -36
- package/dist/commands/workers/remove.js +45 -47
- package/dist/commands/workers/secret.js +159 -83
- package/dist/commands/workers/test.js +108 -60
- package/dist/schemas/agent.config.schema.json +183 -8
- package/dist/studio/api/sseClient.js +1 -1
- package/dist/studio/api/studioApi.js +8 -0
- package/dist/studio/components/App.js +12 -0
- package/dist/studio/components/Footer.js +1 -1
- package/dist/studio/index.js +77 -14
- package/dist/studio/runOneShot.js +62 -23
- package/dist/studio/runRepl.js +5 -5
- package/dist/studio/slash/handlers.js +11 -8
- package/dist/studio/state/store.js +1 -1
- package/dist/utils/agent-errors.js +14 -11
- package/dist/utils/agent-patch.js +60 -0
- package/dist/utils/banner.js +9 -5
- package/dist/utils/confirm.js +31 -0
- package/dist/utils/credentials.js +13 -3
- package/dist/utils/logger.js +13 -10
- package/dist/utils/output.js +78 -0
- package/dist/utils/phone.js +22 -0
- package/dist/utils/ui.js +14 -11
- package/package.json +2 -2
|
@@ -3,10 +3,10 @@ import os from 'node:os';
|
|
|
3
3
|
import axios from 'axios';
|
|
4
4
|
import chalk from 'chalk';
|
|
5
5
|
import inquirer from 'inquirer';
|
|
6
|
-
import { apiBaseUrl, appBaseUrl, saveCredentials } from '../../utils/credentials.js';
|
|
6
|
+
import { apiBaseUrl, appBaseUrl, parseZone, saveCredentials } from '../../utils/credentials.js';
|
|
7
|
+
import { fail, CliError } from '../../utils/output.js';
|
|
7
8
|
import { openBrowser } from '../../utils/open-browser.js';
|
|
8
9
|
import { createSpinner, theme } from '../../utils/ui.js';
|
|
9
|
-
import { logger } from '../../utils/logger.js';
|
|
10
10
|
import { addExamples, addNotes } from '../../utils/help.js';
|
|
11
11
|
const sleep = (ms) => new Promise(r => setTimeout(r, ms));
|
|
12
12
|
/**
|
|
@@ -16,16 +16,23 @@ const sleep = (ms) => new Promise(r => setTimeout(r, ms));
|
|
|
16
16
|
export async function runBrowserLogin(options) {
|
|
17
17
|
let zone;
|
|
18
18
|
if (options.zone) {
|
|
19
|
-
|
|
19
|
+
const parsed = parseZone(options.zone);
|
|
20
|
+
if (!parsed) {
|
|
21
|
+
throw new CliError(`Invalid zone "${options.zone}".`, 'invalid_zone', 'Use --zone LA (Americas) or --zone EU (Europe).');
|
|
22
|
+
}
|
|
23
|
+
zone = parsed;
|
|
20
24
|
}
|
|
21
25
|
else {
|
|
26
|
+
if (!process.stdin.isTTY) {
|
|
27
|
+
throw new CliError('The zone is required without an interactive terminal.', 'missing_zone', 'Pass --zone LA or --zone EU.');
|
|
28
|
+
}
|
|
22
29
|
const answer = await inquirer.prompt([{
|
|
23
30
|
type: 'list',
|
|
24
31
|
name: 'zone',
|
|
25
|
-
message: '
|
|
32
|
+
message: 'Where did you create your Plazbot account?',
|
|
26
33
|
choices: [
|
|
27
|
-
{ name: '
|
|
28
|
-
{ name: '
|
|
34
|
+
{ name: 'Americas (appla.plazbot.com)', value: 'LA' },
|
|
35
|
+
{ name: 'Europe (appeu.plazbot.com)', value: 'EU' },
|
|
29
36
|
],
|
|
30
37
|
}]);
|
|
31
38
|
zone = answer.zone;
|
|
@@ -38,22 +45,22 @@ export async function runBrowserLogin(options) {
|
|
|
38
45
|
data = start.data?.success ? start.data?.data : undefined;
|
|
39
46
|
}
|
|
40
47
|
catch (error) {
|
|
41
|
-
throw new
|
|
48
|
+
throw new CliError(`Could not reach Plazbot (${axios.isAxiosError(error) ? error.message : 'network error'}).`, 'network_error', 'Check your internet connection and try again.');
|
|
42
49
|
}
|
|
43
50
|
if (!data?.deviceCode) {
|
|
44
|
-
throw new
|
|
51
|
+
throw new CliError('Could not start the login.', 'login_start_failed', 'Try again in a few seconds.');
|
|
45
52
|
}
|
|
46
53
|
const url = `${appBaseUrl(zone, dev)}/cli/authorize?code=${encodeURIComponent(data.userCode)}&r=${encodeURIComponent(data.requestToken)}`;
|
|
47
54
|
console.log();
|
|
48
|
-
console.log(`
|
|
55
|
+
console.log(` Your verification code: ${chalk.bold.hex('#22d3ee')(data.userCode)}`);
|
|
49
56
|
console.log();
|
|
50
57
|
const opened = options.browser !== false && openBrowser(url);
|
|
51
58
|
console.log(theme.muted(opened
|
|
52
|
-
? '
|
|
53
|
-
: '
|
|
59
|
+
? ' We opened your browser. If it did not open, go to:'
|
|
60
|
+
: ' Open this link in your browser:'));
|
|
54
61
|
console.log(` ${chalk.underline(url)}`);
|
|
55
62
|
console.log();
|
|
56
|
-
const spinner = createSpinner('
|
|
63
|
+
const spinner = createSpinner('Waiting for authorization in the browser... (Ctrl+C to cancel)');
|
|
57
64
|
spinner.start();
|
|
58
65
|
const deadline = Date.now() + data.expiresIn * 1000;
|
|
59
66
|
const intervalMs = Math.max(2, data.interval || 3) * 1000;
|
|
@@ -72,8 +79,8 @@ export async function runBrowserLogin(options) {
|
|
|
72
79
|
}
|
|
73
80
|
}
|
|
74
81
|
if (!approved) {
|
|
75
|
-
spinner.fail('
|
|
76
|
-
throw new
|
|
82
|
+
spinner.fail('The code expired before it was authorized.');
|
|
83
|
+
throw new CliError('Login timed out.', 'login_expired', "Run 'plazbot login' again.");
|
|
77
84
|
}
|
|
78
85
|
const credentials = {
|
|
79
86
|
apiKey: approved.apiKey,
|
|
@@ -85,37 +92,36 @@ export async function runBrowserLogin(options) {
|
|
|
85
92
|
source: 'login',
|
|
86
93
|
};
|
|
87
94
|
await saveCredentials(credentials);
|
|
88
|
-
spinner.succeed(`
|
|
95
|
+
spinner.succeed(`Signed in to ${chalk.bold(approved.workspaceName || approved.workspaceId)} (${credentials.zone})`);
|
|
89
96
|
if (approved.email)
|
|
90
|
-
console.log(theme.muted(`
|
|
97
|
+
console.log(theme.muted(` Account: ${approved.email}`));
|
|
91
98
|
console.log();
|
|
92
99
|
return credentials;
|
|
93
100
|
}
|
|
94
101
|
export const browserLoginCommand = new Command('login')
|
|
95
|
-
.description('
|
|
96
|
-
.option('-z, --zone <zone>', '
|
|
97
|
-
.option('--no-browser', '
|
|
98
|
-
.option('--dev', '
|
|
102
|
+
.description('Sign in with your browser (no API key to copy)')
|
|
103
|
+
.option('-z, --zone <zone>', 'Zone where you created your account: LA (Americas) or EU (Europe)')
|
|
104
|
+
.option('--no-browser', 'Do not open the browser, only print the link')
|
|
105
|
+
.option('--dev', 'Use development environment', false)
|
|
99
106
|
.action(async (options) => {
|
|
100
107
|
try {
|
|
101
108
|
await runBrowserLogin(options);
|
|
102
|
-
console.log(theme.muted('
|
|
103
|
-
console.log(` ${chalk.cyan('plazbot whatsapp setup')} ${theme.muted('
|
|
104
|
-
console.log(` ${chalk.cyan('plazbot whoami')} ${theme.muted('
|
|
105
|
-
console.log(` ${chalk.cyan('plazbot workspace list')} ${theme.muted('
|
|
109
|
+
console.log(theme.muted(' Next steps:'));
|
|
110
|
+
console.log(` ${chalk.cyan('plazbot whatsapp setup')} ${theme.muted('Connect WhatsApp and send your first message')}`);
|
|
111
|
+
console.log(` ${chalk.cyan('plazbot whoami')} ${theme.muted('Show the active session')}`);
|
|
112
|
+
console.log(` ${chalk.cyan('plazbot workspace list')} ${theme.muted('Switch workspace')}`);
|
|
106
113
|
console.log();
|
|
107
114
|
}
|
|
108
115
|
catch (error) {
|
|
109
|
-
|
|
110
|
-
process.exit(1);
|
|
116
|
+
fail(error);
|
|
111
117
|
}
|
|
112
118
|
});
|
|
113
119
|
addExamples(browserLoginCommand, [
|
|
114
|
-
{ description: '
|
|
115
|
-
{ description: '
|
|
116
|
-
{ description: '
|
|
120
|
+
{ description: 'Sign in (asks for the zone and opens the browser)', command: 'plazbot login' },
|
|
121
|
+
{ description: 'Account in Europe', command: 'plazbot login --zone EU' },
|
|
122
|
+
{ description: 'Server without a browser: only print the link', command: 'plazbot login --no-browser' },
|
|
117
123
|
]);
|
|
118
124
|
addNotes(browserLoginCommand, [
|
|
119
|
-
'
|
|
120
|
-
'
|
|
125
|
+
'In CI or servers use environment variables: PLAZBOT_API_KEY, PLAZBOT_WORKSPACE_ID and PLAZBOT_ZONE (or plazbot init).',
|
|
126
|
+
'You can revoke access in the app: Settings → Developer.',
|
|
121
127
|
]);
|
|
@@ -1,64 +1,68 @@
|
|
|
1
1
|
import { Command } from 'commander';
|
|
2
|
-
import
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
import { parseZone, saveCredentials } from '../../utils/credentials.js';
|
|
3
4
|
import { logger } from '../../utils/logger.js';
|
|
4
|
-
import { addExamples } from '../../utils/help.js';
|
|
5
|
+
import { addExamples, addNotes } from '../../utils/help.js';
|
|
6
|
+
import { jsonOption, isJsonMode, printJson, fail, CliError } from '../../utils/output.js';
|
|
5
7
|
export const loginCommand = new Command('init')
|
|
6
|
-
.description('
|
|
7
|
-
.
|
|
8
|
-
.requiredOption('-
|
|
9
|
-
.requiredOption('-
|
|
10
|
-
.
|
|
11
|
-
.option('-u, --user-id <userId>', 'User ID
|
|
8
|
+
.description('Save an API key manually (for CI; use plazbot login on your machine)')
|
|
9
|
+
.requiredOption('-k, --api-key <apiKey>', 'API key (Settings → Developer)')
|
|
10
|
+
.requiredOption('-w, --workspace <workspaceId>', 'Workspace ID')
|
|
11
|
+
.requiredOption('-z, --zone <zone>', 'Zone where the account lives: LA (Americas) or EU (Europe)')
|
|
12
|
+
.option('-e, --email <email>', 'Account email (optional, shown by whoami)')
|
|
13
|
+
.option('-u, --user-id <userId>', 'User ID (optional, needed by studio and workspace list)')
|
|
14
|
+
.addOption(jsonOption())
|
|
12
15
|
.option('--dev', 'Use development environment', false)
|
|
13
16
|
.action(async (options) => {
|
|
14
17
|
try {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
18
|
+
const zone = parseZone(options.zone);
|
|
19
|
+
if (!zone) {
|
|
20
|
+
throw new CliError(`Invalid zone "${options.zone}".`, 'invalid_zone', 'Use -z LA (Americas) or -z EU (Europe).');
|
|
21
|
+
}
|
|
22
|
+
const apiKey = options.apiKey.trim();
|
|
23
|
+
const workspace = options.workspace.trim();
|
|
24
|
+
if (!apiKey)
|
|
25
|
+
throw new CliError('API key cannot be empty.', 'missing_api_key', 'Pass it with -k, --api-key <apiKey>.');
|
|
26
|
+
if (!workspace)
|
|
27
|
+
throw new CliError('Workspace ID cannot be empty.', 'missing_workspace', 'Pass it with -w, --workspace <workspaceId>.');
|
|
25
28
|
await saveCredentials({
|
|
26
29
|
email: options.email || '',
|
|
27
|
-
apiKey
|
|
28
|
-
workspace
|
|
29
|
-
zone
|
|
30
|
-
userId: options.userId
|
|
30
|
+
apiKey,
|
|
31
|
+
workspace,
|
|
32
|
+
zone,
|
|
33
|
+
userId: options.userId,
|
|
34
|
+
source: 'init',
|
|
31
35
|
});
|
|
32
|
-
|
|
36
|
+
if (isJsonMode()) {
|
|
37
|
+
printJson({ workspace, zone });
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
logger.success('Credentials saved to ~/.plazbot/config.json');
|
|
41
|
+
logger.label('Workspace', workspace);
|
|
42
|
+
logger.label('Zone', zone === 'EU' ? 'Europe (EU)' : 'Americas (LA)');
|
|
33
43
|
if (options.email)
|
|
34
44
|
logger.label('Email', options.email);
|
|
35
|
-
logger.label('Workspace', options.workspace);
|
|
36
|
-
logger.label('Zone', options.zone);
|
|
37
45
|
if (options.userId)
|
|
38
|
-
logger.label('
|
|
39
|
-
|
|
40
|
-
logger.dim('
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
logger.dim('plazbot --help - View all commands');
|
|
46
|
+
logger.label('User ID', options.userId);
|
|
47
|
+
console.log();
|
|
48
|
+
logger.dim('The key is not verified yet. Check it with:');
|
|
49
|
+
console.log(` ${chalk.cyan('plazbot agent list')} ${chalk.gray('List your agents (fails if the key or zone is wrong)')}`);
|
|
50
|
+
console.log(` ${chalk.cyan('plazbot whoami')} ${chalk.gray('Show the active session')}`);
|
|
44
51
|
console.log();
|
|
45
|
-
if (options.dev) {
|
|
46
|
-
logger.warning('Environment: development');
|
|
47
|
-
}
|
|
48
52
|
}
|
|
49
53
|
catch (error) {
|
|
50
|
-
|
|
51
|
-
logger.error(message);
|
|
52
|
-
process.exit(1);
|
|
54
|
+
fail(error);
|
|
53
55
|
}
|
|
54
56
|
});
|
|
55
57
|
addExamples(loginCommand, [
|
|
56
|
-
{ description: 'Save credentials for a
|
|
57
|
-
command: 'plazbot init -
|
|
58
|
-
{ description: 'Save credentials for
|
|
59
|
-
command: 'plazbot init -k <
|
|
60
|
-
{ description: 'Include
|
|
61
|
-
command: 'plazbot init -k <
|
|
62
|
-
|
|
63
|
-
|
|
58
|
+
{ description: 'Save credentials for a workspace in the Americas',
|
|
59
|
+
command: 'plazbot init -k <apiKey> -w wok_AbcDef123 -z LA' },
|
|
60
|
+
{ description: 'Save credentials for a workspace in Europe',
|
|
61
|
+
command: 'plazbot init -k <apiKey> -w wok_AbcDef123 -z EU -e you@company.com' },
|
|
62
|
+
{ description: 'Include the user ID (needed by studio and workspace list)',
|
|
63
|
+
command: 'plazbot init -k <apiKey> -w wok_AbcDef123 -z LA -u usr_AbcDef123' },
|
|
64
|
+
]);
|
|
65
|
+
addNotes(loginCommand, [
|
|
66
|
+
'On your own machine prefer plazbot login (browser, no key to copy).',
|
|
67
|
+
'In CI you can skip the file entirely: set PLAZBOT_API_KEY, PLAZBOT_WORKSPACE_ID and PLAZBOT_ZONE.',
|
|
64
68
|
]);
|
|
@@ -1,26 +1,35 @@
|
|
|
1
1
|
import { Command } from 'commander';
|
|
2
2
|
import { removeCredentials } from '../../utils/credentials.js';
|
|
3
3
|
import { logger } from '../../utils/logger.js';
|
|
4
|
-
import { addExamples } from '../../utils/help.js';
|
|
4
|
+
import { addExamples, addNotes } from '../../utils/help.js';
|
|
5
|
+
import { jsonOption, isJsonMode, printJson, fail } from '../../utils/output.js';
|
|
5
6
|
export const logoutCommand = new Command('logout')
|
|
6
7
|
.alias('finish')
|
|
7
|
-
.description('
|
|
8
|
+
.description('Sign out on this machine (removes ~/.plazbot/config.json)')
|
|
9
|
+
.addOption(jsonOption())
|
|
8
10
|
.option('--dev', 'Use development environment', false)
|
|
9
|
-
.action(async (
|
|
11
|
+
.action(async (_options) => {
|
|
10
12
|
try {
|
|
11
13
|
await removeCredentials();
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
14
|
+
if (isJsonMode()) {
|
|
15
|
+
printJson({ loggedOut: true });
|
|
16
|
+
return;
|
|
15
17
|
}
|
|
18
|
+
logger.success('Signed out');
|
|
19
|
+
logger.dim('The token stays valid until you revoke it in Settings → Developer.');
|
|
20
|
+
if (process.env.PLAZBOT_API_KEY) {
|
|
21
|
+
logger.warning('PLAZBOT_API_KEY is still set in your environment, so commands keep working with it.');
|
|
22
|
+
}
|
|
23
|
+
console.log();
|
|
16
24
|
}
|
|
17
25
|
catch (error) {
|
|
18
|
-
|
|
19
|
-
logger.error(message);
|
|
20
|
-
process.exit(1);
|
|
26
|
+
fail(error);
|
|
21
27
|
}
|
|
22
28
|
});
|
|
23
29
|
addExamples(logoutCommand, [
|
|
24
|
-
{ description: '
|
|
25
|
-
|
|
30
|
+
{ description: 'Sign out on this machine', command: 'plazbot logout' },
|
|
31
|
+
{ description: 'Sign out from a script', command: 'plazbot logout --json' },
|
|
32
|
+
]);
|
|
33
|
+
addNotes(logoutCommand, [
|
|
34
|
+
'Logging out only deletes the local session. Revoke the token in Settings → Developer to invalidate it.',
|
|
26
35
|
]);
|
|
@@ -1,30 +1,54 @@
|
|
|
1
1
|
import { Command } from 'commander';
|
|
2
|
-
import { getStoredCredentials } from '../../utils/credentials.js';
|
|
2
|
+
import { apiBaseUrl, getStoredCredentials } from '../../utils/credentials.js';
|
|
3
3
|
import { logger } from '../../utils/logger.js';
|
|
4
4
|
import { addExamples } from '../../utils/help.js';
|
|
5
|
+
import { jsonOption, isJsonMode, printJson, fail, CliError } from '../../utils/output.js';
|
|
5
6
|
import { section } from '../../utils/ui.js';
|
|
7
|
+
const SOURCE_LABELS = {
|
|
8
|
+
login: 'Browser login (plazbot login)',
|
|
9
|
+
init: 'API key (plazbot init)',
|
|
10
|
+
env: 'Environment variables (PLAZBOT_API_KEY)',
|
|
11
|
+
};
|
|
6
12
|
export const statusCommand = new Command('whoami')
|
|
7
13
|
.alias('status')
|
|
8
|
-
.description('
|
|
14
|
+
.description('Show the active session (account, workspace and zone)')
|
|
15
|
+
.addOption(jsonOption())
|
|
9
16
|
.action(async () => {
|
|
10
17
|
try {
|
|
11
|
-
|
|
18
|
+
let credentials;
|
|
19
|
+
try {
|
|
20
|
+
credentials = await getStoredCredentials();
|
|
21
|
+
}
|
|
22
|
+
catch {
|
|
23
|
+
throw new CliError('You are not signed in.', 'not_signed_in', "Run 'plazbot login' to sign in.");
|
|
24
|
+
}
|
|
25
|
+
const api = apiBaseUrl(credentials.zone);
|
|
26
|
+
if (isJsonMode()) {
|
|
27
|
+
printJson({
|
|
28
|
+
email: credentials.email || null,
|
|
29
|
+
workspace: credentials.workspace,
|
|
30
|
+
workspaceName: credentials.workspaceName || null,
|
|
31
|
+
zone: credentials.zone,
|
|
32
|
+
api,
|
|
33
|
+
source: credentials.source || 'init',
|
|
34
|
+
});
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
12
37
|
console.log(section('Active session'));
|
|
13
38
|
if (credentials.email)
|
|
14
39
|
logger.label('Email', credentials.email);
|
|
15
40
|
logger.label('Workspace', credentials.workspaceName ? `${credentials.workspaceName} (${credentials.workspace})` : credentials.workspace);
|
|
16
|
-
logger.label('Zone', credentials.zone === '
|
|
17
|
-
logger.label('API',
|
|
18
|
-
|
|
19
|
-
logger.label('Origen', 'variables de entorno (PLAZBOT_API_KEY)');
|
|
41
|
+
logger.label('Zone', credentials.zone === 'EU' ? 'Europe (EU)' : 'Americas (LA)');
|
|
42
|
+
logger.label('API', api);
|
|
43
|
+
logger.label('Source', SOURCE_LABELS[credentials.source || 'init'] || credentials.source || 'init');
|
|
20
44
|
console.log();
|
|
21
45
|
}
|
|
22
|
-
catch {
|
|
23
|
-
|
|
24
|
-
process.exit(1);
|
|
46
|
+
catch (error) {
|
|
47
|
+
fail(error);
|
|
25
48
|
}
|
|
26
49
|
});
|
|
27
50
|
addExamples(statusCommand, [
|
|
28
|
-
{ description: 'Show the active workspace, email and zone',
|
|
29
|
-
|
|
51
|
+
{ description: 'Show the active workspace, email and zone', command: 'plazbot whoami' },
|
|
52
|
+
{ description: 'Get the session as JSON', command: 'plazbot whoami --json' },
|
|
53
|
+
{ description: 'Get only the workspace ID', command: "plazbot whoami --json | jq -r '.workspace'" },
|
|
30
54
|
]);
|
|
@@ -4,11 +4,12 @@ import chalk from 'chalk';
|
|
|
4
4
|
import { apiBaseUrl, getStoredCredentials, saveCredentials } from '../../utils/credentials.js';
|
|
5
5
|
import { createSpinner, createTable, theme } from '../../utils/ui.js';
|
|
6
6
|
import { logger } from '../../utils/logger.js';
|
|
7
|
-
import { addExamples } from '../../utils/help.js';
|
|
7
|
+
import { addExamples, addNotes } from '../../utils/help.js';
|
|
8
|
+
import { jsonOption, isJsonMode, printJson, fail, CliError } from '../../utils/output.js';
|
|
8
9
|
async function fetchWorkspaces(dev) {
|
|
9
10
|
const creds = await getStoredCredentials();
|
|
10
11
|
if (!creds.userId) {
|
|
11
|
-
throw new
|
|
12
|
+
throw new CliError('This session has no user attached, so workspaces cannot be listed.', 'missing_user_id', "Sign in again with 'plazbot login'.");
|
|
12
13
|
}
|
|
13
14
|
const res = await axios.get(`${apiBaseUrl(creds.zone, dev)}/api/workspace/workspaceByUserId/${encodeURIComponent(creds.userId)}`, {
|
|
14
15
|
headers: { Authorization: `Bearer ${creds.apiKey}`, 'x-workspace-id': creds.workspace },
|
|
@@ -18,56 +19,89 @@ async function fetchWorkspaces(dev) {
|
|
|
18
19
|
.map((w) => ({ id: w.data.id, name: w.data.name || w.data.id }));
|
|
19
20
|
}
|
|
20
21
|
const listCommand = new Command('list')
|
|
21
|
-
.description('
|
|
22
|
-
.
|
|
23
|
-
.option('--dev', '
|
|
22
|
+
.description('List the workspaces you belong to (same zone as the session)')
|
|
23
|
+
.addOption(jsonOption())
|
|
24
|
+
.option('--dev', 'Use development environment', false)
|
|
24
25
|
.action(async (options) => {
|
|
25
26
|
try {
|
|
26
27
|
const creds = await getStoredCredentials();
|
|
27
|
-
const spinner =
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
28
|
+
const spinner = createSpinner('Loading workspaces...').start();
|
|
29
|
+
let items;
|
|
30
|
+
try {
|
|
31
|
+
items = await fetchWorkspaces(options.dev);
|
|
32
|
+
}
|
|
33
|
+
finally {
|
|
34
|
+
spinner.stop();
|
|
35
|
+
}
|
|
36
|
+
if (isJsonMode()) {
|
|
37
|
+
printJson(items.map(w => ({ ...w, active: w.id === creds.workspace })));
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
if (items.length === 0) {
|
|
41
|
+
logger.dim('No workspaces found for this account.');
|
|
32
42
|
return;
|
|
33
43
|
}
|
|
34
44
|
console.log(createTable(['', 'Workspace', 'ID'], items.map(w => [
|
|
35
45
|
w.id === creds.workspace ? chalk.green('●') : ' ', w.name, theme.muted(w.id),
|
|
36
46
|
])));
|
|
37
|
-
console.log(theme.muted(
|
|
47
|
+
console.log(theme.muted(' Switch with: plazbot workspace use <workspaceId>'));
|
|
38
48
|
}
|
|
39
49
|
catch (error) {
|
|
40
|
-
|
|
41
|
-
process.exit(1);
|
|
50
|
+
fail(error);
|
|
42
51
|
}
|
|
43
52
|
});
|
|
44
53
|
const useCommand = new Command('use')
|
|
45
|
-
.description('
|
|
46
|
-
.argument('<workspaceId>', 'ID
|
|
47
|
-
.
|
|
54
|
+
.description('Switch the active workspace')
|
|
55
|
+
.argument('<workspaceId>', 'Workspace ID (see plazbot workspace list)')
|
|
56
|
+
.addOption(jsonOption())
|
|
57
|
+
.option('--dev', 'Use development environment', false)
|
|
48
58
|
.action(async (workspaceId, options) => {
|
|
49
59
|
try {
|
|
50
60
|
const creds = await getStoredCredentials();
|
|
51
61
|
if (creds.source === 'env') {
|
|
52
|
-
throw new
|
|
62
|
+
throw new CliError('The session comes from environment variables.', 'env_session', 'Change PLAZBOT_WORKSPACE_ID instead.');
|
|
63
|
+
}
|
|
64
|
+
const spinner = createSpinner('Checking access...').start();
|
|
65
|
+
let items;
|
|
66
|
+
try {
|
|
67
|
+
items = await fetchWorkspaces(options.dev);
|
|
68
|
+
}
|
|
69
|
+
finally {
|
|
70
|
+
spinner.stop();
|
|
71
|
+
}
|
|
72
|
+
const target = items.find(w => w.id === workspaceId.trim());
|
|
73
|
+
if (!target) {
|
|
74
|
+
throw new CliError(`You do not have access to workspace ${workspaceId}.`, 'workspace_not_found', "See your workspaces with 'plazbot workspace list'.");
|
|
53
75
|
}
|
|
54
|
-
const items = await fetchWorkspaces(options.dev);
|
|
55
|
-
const target = items.find(w => w.id === workspaceId);
|
|
56
|
-
if (!target)
|
|
57
|
-
throw new Error(`No tienes acceso al workspace ${workspaceId}.`);
|
|
58
76
|
await saveCredentials({ ...creds, workspace: target.id, workspaceName: target.name });
|
|
59
|
-
|
|
77
|
+
if (isJsonMode()) {
|
|
78
|
+
printJson({ id: target.id, name: target.name, active: true });
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
logger.success(`Active workspace: ${target.name} ${theme.muted(`(${target.id})`)}`);
|
|
82
|
+
console.log();
|
|
60
83
|
}
|
|
61
84
|
catch (error) {
|
|
62
|
-
|
|
63
|
-
process.exit(1);
|
|
85
|
+
fail(error);
|
|
64
86
|
}
|
|
65
87
|
});
|
|
66
88
|
export const workspaceCommand = new Command('workspace')
|
|
67
|
-
.description('
|
|
89
|
+
.description('List and switch workspaces')
|
|
68
90
|
.addCommand(listCommand)
|
|
69
91
|
.addCommand(useCommand);
|
|
70
92
|
addExamples(workspaceCommand, [
|
|
71
|
-
{ description: '
|
|
72
|
-
{ description: '
|
|
93
|
+
{ description: 'List your workspaces', command: 'plazbot workspace list' },
|
|
94
|
+
{ description: 'Switch the active workspace', command: 'plazbot workspace use wok_AbcDef123' },
|
|
95
|
+
{ description: 'List workspaces as JSON', command: 'plazbot workspace list --json' },
|
|
96
|
+
]);
|
|
97
|
+
addExamples(listCommand, [
|
|
98
|
+
{ description: 'List your workspaces (● marks the active one)', command: 'plazbot workspace list' },
|
|
99
|
+
{ description: 'Get them as JSON', command: 'plazbot workspace list --json' },
|
|
100
|
+
]);
|
|
101
|
+
addExamples(useCommand, [
|
|
102
|
+
{ description: 'Switch the active workspace', command: 'plazbot workspace use wok_AbcDef123' },
|
|
103
|
+
{ description: 'Switch from a script', command: 'plazbot workspace use wok_AbcDef123 --json' },
|
|
104
|
+
]);
|
|
105
|
+
addNotes(workspaceCommand, [
|
|
106
|
+
'Only workspaces in the zone of the current session are listed. For another zone, run plazbot login --zone EU (or LA).',
|
|
73
107
|
]);
|