plazbot-cli 0.2.26 → 0.3.2
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/CLAUDE.md +34 -5
- package/README.md +21 -0
- package/dist/cli.js +32 -20
- package/dist/commands/agent/ai-config.js +98 -50
- package/dist/commands/agent/chat.js +80 -74
- package/dist/commands/agent/copy.js +23 -21
- package/dist/commands/agent/create.js +42 -72
- package/dist/commands/agent/delete.js +29 -30
- package/dist/commands/agent/enable-widget.js +30 -26
- package/dist/commands/agent/export.js +90 -77
- package/dist/commands/agent/files.js +68 -60
- package/dist/commands/agent/get.js +101 -87
- package/dist/commands/agent/index.js +53 -39
- package/dist/commands/agent/list.js +26 -24
- package/dist/commands/agent/monitor.js +91 -86
- package/dist/commands/agent/on-message.js +40 -37
- package/dist/commands/agent/set.js +62 -59
- package/dist/commands/agent/templates.js +109 -108
- package/dist/commands/agent/tools.js +64 -65
- package/dist/commands/agent/update.js +28 -27
- package/dist/commands/agent/validate.js +127 -0
- package/dist/commands/agent/wizard.js +152 -159
- package/dist/commands/auth/index.js +7 -10
- package/dist/commands/auth/login.js +50 -37
- package/dist/commands/auth/logout.js +16 -14
- package/dist/commands/auth/status.js +19 -16
- package/dist/commands/portal/add-agent.js +26 -24
- package/dist/commands/portal/add-link.js +21 -17
- package/dist/commands/portal/clear-links.js +17 -15
- package/dist/commands/portal/create.js +25 -21
- package/dist/commands/portal/delete.js +31 -30
- package/dist/commands/portal/get.js +33 -31
- package/dist/commands/portal/index.js +30 -22
- package/dist/commands/portal/list.js +34 -30
- package/dist/commands/portal/update.js +41 -33
- package/dist/commands/whatsapp/broadcast.js +40 -37
- package/dist/commands/whatsapp/channels.js +40 -34
- package/dist/commands/whatsapp/chat.js +33 -32
- package/dist/commands/whatsapp/connect.js +53 -52
- package/dist/commands/whatsapp/delete-webhook.js +19 -17
- package/dist/commands/whatsapp/index.js +35 -25
- package/dist/commands/whatsapp/register-webhook.js +21 -19
- package/dist/commands/whatsapp/send-template.js +39 -31
- package/dist/commands/whatsapp/send.js +27 -23
- package/dist/commands/whatsapp/widget.js +35 -31
- package/dist/commands/workers/deploy.js +49 -44
- package/dist/commands/workers/index.js +28 -18
- package/dist/commands/workers/list.js +43 -35
- package/dist/commands/workers/logs.js +38 -32
- package/dist/commands/workers/remove.js +38 -37
- package/dist/commands/workers/secret.js +63 -58
- package/dist/commands/workers/test.js +44 -36
- package/dist/schemas/agent.config.schema.json +569 -0
- package/dist/studio/api/sseClient.js +97 -0
- package/dist/studio/api/studioApi.js +25 -0
- package/dist/studio/api/types.js +16 -0
- package/dist/studio/components/AgentPanel.js +35 -0
- package/dist/studio/components/App.js +214 -0
- package/dist/studio/components/ChatLog.js +59 -0
- package/dist/studio/components/Footer.js +11 -0
- package/dist/studio/components/Header.js +8 -0
- package/dist/studio/components/Input.js +15 -0
- package/dist/studio/components/Message.js +56 -0
- package/dist/studio/components/Suggestions.js +11 -0
- package/dist/studio/components/ToolCall.js +33 -0
- package/dist/studio/components/WhatsappConnectCard.js +57 -0
- package/dist/studio/index.js +42 -0
- package/dist/studio/render/json.js +16 -0
- package/dist/studio/render/markdown.js +86 -0
- package/dist/studio/render/steps.js +58 -0
- package/dist/studio/runOneShot.js +96 -0
- package/dist/studio/runRepl.js +52 -0
- package/dist/studio/slash/handlers.js +199 -0
- package/dist/studio/slash/parser.js +46 -0
- package/dist/studio/slash/registry.js +16 -0
- package/dist/studio/state/store.js +181 -0
- package/dist/studio/whatsapp/api.js +63 -0
- package/dist/studio/whatsapp/polling.js +77 -0
- package/dist/studio/whatsapp/types.js +31 -0
- package/dist/types/agent.js +1 -2
- package/dist/types/auth.js +1 -2
- package/dist/types/common.js +1 -2
- package/dist/types/message.js +1 -2
- package/dist/types/portal.js +1 -2
- package/dist/types/workers.js +1 -2
- package/dist/utils/agent-errors.js +46 -0
- package/dist/utils/api.js +8 -9
- package/dist/utils/banner.js +33 -34
- package/dist/utils/credentials.js +12 -20
- package/dist/utils/help.js +44 -0
- package/dist/utils/logger.js +13 -19
- package/dist/utils/ui.js +35 -49
- package/package.json +22 -10
- package/src/cli.ts +24 -8
- package/src/commands/agent/ai-config.ts +89 -34
- package/src/commands/agent/chat.ts +49 -37
- package/src/commands/agent/copy.ts +19 -13
- package/src/commands/agent/create.ts +32 -22
- package/src/commands/agent/delete.ts +24 -18
- package/src/commands/agent/enable-widget.ts +31 -23
- package/src/commands/agent/export.ts +72 -51
- package/src/commands/agent/files.ts +51 -39
- package/src/commands/agent/get.ts +86 -66
- package/src/commands/agent/index.ts +36 -18
- package/src/commands/agent/list.ts +22 -16
- package/src/commands/agent/monitor.ts +67 -56
- package/src/commands/agent/on-message.ts +36 -27
- package/src/commands/agent/set.ts +47 -37
- package/src/commands/agent/templates.ts +90 -82
- package/src/commands/agent/tools.ts +53 -47
- package/src/commands/agent/update.ts +28 -20
- package/src/commands/agent/validate.ts +135 -0
- package/src/commands/agent/wizard.ts +114 -114
- package/src/commands/auth/index.ts +3 -3
- package/src/commands/auth/login.ts +44 -29
- package/src/commands/auth/logout.ts +16 -10
- package/src/commands/auth/status.ts +14 -8
- package/src/commands/portal/add-agent.ts +23 -17
- package/src/commands/portal/add-link.ts +17 -9
- package/src/commands/portal/clear-links.ts +13 -7
- package/src/commands/portal/create.ts +20 -12
- package/src/commands/portal/delete.ts +28 -20
- package/src/commands/portal/get.ts +25 -19
- package/src/commands/portal/index.ts +22 -10
- package/src/commands/portal/list.ts +27 -19
- package/src/commands/portal/update.ts +38 -26
- package/src/commands/whatsapp/broadcast.ts +28 -18
- package/src/commands/whatsapp/channels.ts +31 -20
- package/src/commands/whatsapp/chat.ts +20 -12
- package/src/commands/whatsapp/connect.ts +39 -31
- package/src/commands/whatsapp/delete-webhook.ts +15 -9
- package/src/commands/whatsapp/index.ts +24 -10
- package/src/commands/whatsapp/register-webhook.ts +16 -10
- package/src/commands/whatsapp/send-template.ts +33 -21
- package/src/commands/whatsapp/send.ts +23 -15
- package/src/commands/whatsapp/widget.ts +25 -17
- package/src/commands/workers/deploy.ts +34 -22
- package/src/commands/workers/index.ts +21 -7
- package/src/commands/workers/list.ts +31 -19
- package/src/commands/workers/logs.ts +30 -20
- package/src/commands/workers/remove.ts +30 -22
- package/src/commands/workers/secret.ts +46 -34
- package/src/commands/workers/test.ts +34 -22
- package/src/schemas/agent.config.schema.json +569 -0
- package/src/studio/api/sseClient.ts +91 -0
- package/src/studio/api/studioApi.ts +27 -0
- package/src/studio/api/types.ts +96 -0
- package/src/studio/components/App.tsx +266 -0
- package/src/studio/components/ChatLog.tsx +95 -0
- package/src/studio/components/Footer.tsx +38 -0
- package/src/studio/components/Header.tsx +39 -0
- package/src/studio/components/Input.tsx +32 -0
- package/src/studio/components/Message.tsx +87 -0
- package/src/studio/components/Suggestions.tsx +26 -0
- package/src/studio/components/ToolCall.tsx +58 -0
- package/src/studio/components/WhatsappConnectCard.tsx +139 -0
- package/src/studio/index.ts +58 -0
- package/src/studio/render/markdown.ts +93 -0
- package/src/studio/render/steps.ts +57 -0
- package/src/studio/runOneShot.ts +114 -0
- package/src/studio/runRepl.tsx +76 -0
- package/src/studio/slash/handlers.ts +226 -0
- package/src/studio/slash/parser.ts +41 -0
- package/src/studio/slash/registry.ts +54 -0
- package/src/studio/state/store.ts +273 -0
- package/src/studio/whatsapp/api.ts +96 -0
- package/src/studio/whatsapp/polling.ts +93 -0
- package/src/studio/whatsapp/types.ts +80 -0
- package/src/types/agent.ts +1 -1
- package/src/types/auth.ts +4 -3
- package/src/types/portal.ts +1 -1
- package/src/types/workers.ts +1 -1
- package/src/utils/agent-errors.ts +67 -0
- package/src/utils/api.ts +6 -0
- package/src/utils/banner.ts +14 -9
- package/src/utils/credentials.ts +6 -5
- package/src/utils/help.ts +51 -0
- package/tsconfig.json +9 -6
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { activateIntegration, getWorkspaceById, type WorkspaceAuthOpts } from './api.js';
|
|
2
|
+
import {
|
|
3
|
+
findNewWhatsappIntegration,
|
|
4
|
+
WA_POLL_INTERVAL_MS,
|
|
5
|
+
WA_POLL_MAX_ATTEMPTS,
|
|
6
|
+
type WhatsappLinkData,
|
|
7
|
+
} from './types.js';
|
|
8
|
+
|
|
9
|
+
export interface PollingCallbacks {
|
|
10
|
+
onAttempt(attempt: number): void;
|
|
11
|
+
onActivating(integrationId: string, number: string): void;
|
|
12
|
+
onConnected(number: string): void;
|
|
13
|
+
onTimeout(): void;
|
|
14
|
+
onError(message: string): void;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface PollingHandle {
|
|
18
|
+
cancel(): void;
|
|
19
|
+
/** True once the loop has stopped (success, timeout, error, or cancel). */
|
|
20
|
+
readonly stopped: boolean;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Starts the polling loop. Returns a handle to cancel it. The loop:
|
|
25
|
+
* 1. GETs the workspace every WA_POLL_INTERVAL_MS up to WA_POLL_MAX_ATTEMPTS.
|
|
26
|
+
* 2. Looks for a whatsapp integration whose id isn't in `existingIntegrationIds`.
|
|
27
|
+
* 3. When found, calls POST .../activate and reports the result.
|
|
28
|
+
*/
|
|
29
|
+
export function startWhatsappPolling(
|
|
30
|
+
opts: WorkspaceAuthOpts,
|
|
31
|
+
linkData: WhatsappLinkData,
|
|
32
|
+
cb: PollingCallbacks,
|
|
33
|
+
): PollingHandle {
|
|
34
|
+
const knownIds = new Set(linkData.existingIntegrationIds ?? []);
|
|
35
|
+
const controller = new AbortController();
|
|
36
|
+
let attempts = 0;
|
|
37
|
+
let busy = false;
|
|
38
|
+
let stopped = false;
|
|
39
|
+
let timer: ReturnType<typeof setInterval> | null = null;
|
|
40
|
+
|
|
41
|
+
const stop = () => {
|
|
42
|
+
stopped = true;
|
|
43
|
+
if (timer) { clearInterval(timer); timer = null; }
|
|
44
|
+
controller.abort();
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
const tick = async () => {
|
|
48
|
+
if (busy || stopped) return;
|
|
49
|
+
busy = true;
|
|
50
|
+
attempts++;
|
|
51
|
+
cb.onAttempt(attempts);
|
|
52
|
+
try {
|
|
53
|
+
const ws = await getWorkspaceById(opts, controller.signal);
|
|
54
|
+
const newIntegration = findNewWhatsappIntegration(ws?.integrations, knownIds);
|
|
55
|
+
if (newIntegration?.id) {
|
|
56
|
+
const number =
|
|
57
|
+
newIntegration.cellphoneNumberFormat ||
|
|
58
|
+
newIntegration.cellphoneNumber ||
|
|
59
|
+
'';
|
|
60
|
+
cb.onActivating(newIntegration.id, number);
|
|
61
|
+
if (timer) { clearInterval(timer); timer = null; }
|
|
62
|
+
const res = await activateIntegration(opts, newIntegration.id, controller.signal);
|
|
63
|
+
if (res.success !== false) {
|
|
64
|
+
cb.onConnected(number);
|
|
65
|
+
} else {
|
|
66
|
+
cb.onError(res.message || 'Could not activate the integration.');
|
|
67
|
+
}
|
|
68
|
+
stopped = true;
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
} catch (err) {
|
|
72
|
+
if ((err as Error).name === 'AbortError') return;
|
|
73
|
+
// Transient network errors: swallow and keep polling.
|
|
74
|
+
} finally {
|
|
75
|
+
busy = false;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if (attempts >= WA_POLL_MAX_ATTEMPTS) {
|
|
79
|
+
if (timer) { clearInterval(timer); timer = null; }
|
|
80
|
+
stopped = true;
|
|
81
|
+
cb.onTimeout();
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
timer = setInterval(() => { void tick(); }, WA_POLL_INTERVAL_MS);
|
|
86
|
+
// Trigger the first attempt immediately so the user sees activity right away.
|
|
87
|
+
void tick();
|
|
88
|
+
|
|
89
|
+
return {
|
|
90
|
+
cancel() { stop(); },
|
|
91
|
+
get stopped() { return stopped; },
|
|
92
|
+
};
|
|
93
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Types and helpers for the "connect WhatsApp from Agent Studio" flow.
|
|
3
|
+
*
|
|
4
|
+
* The backend tool `connect_whatsapp` emits a `tool_result` chunk with
|
|
5
|
+
* `type: "whatsapp_link"`. When `data.shortUrl` is present we render an
|
|
6
|
+
* inline card with the onboarding link and start polling the workspace
|
|
7
|
+
* until the new integration appears. Baseline of "known" ids comes from
|
|
8
|
+
* the server (`existingIntegrationIds`) to avoid race conditions.
|
|
9
|
+
*
|
|
10
|
+
* Mirror of /Plazbot-Front-v2.0/src/modules/agentStudio/whatsappConnect.ts
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
export interface WhatsappLinkData {
|
|
14
|
+
shortUrl?: string | null;
|
|
15
|
+
/** "whatsapp" (Cloud API) | "whatsapp_business" (Business app / QR) */
|
|
16
|
+
linkType?: string;
|
|
17
|
+
expiresAt?: string;
|
|
18
|
+
isNewLink?: boolean;
|
|
19
|
+
alreadyConnected?: boolean;
|
|
20
|
+
connectedNumbers?: Array<{ id?: string; number?: string; alias?: string }>;
|
|
21
|
+
existingIntegrationIds?: string[];
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export type WaConnectStatus =
|
|
25
|
+
| 'waiting' // card visible, polling active
|
|
26
|
+
| 'activating' // integration detected, activating via API
|
|
27
|
+
| 'connected' // activated successfully
|
|
28
|
+
| 'timeout' // attempts exhausted
|
|
29
|
+
| 'cancelled' // user cancelled
|
|
30
|
+
| 'error'; // activation failed
|
|
31
|
+
|
|
32
|
+
export interface WaConnectState {
|
|
33
|
+
/** Stable id used by the store + card. */
|
|
34
|
+
id: string;
|
|
35
|
+
linkData: WhatsappLinkData;
|
|
36
|
+
status: WaConnectStatus;
|
|
37
|
+
/** Message id this card anchors to in the chat log. */
|
|
38
|
+
anchorMessageId: string;
|
|
39
|
+
connectedNumber?: string;
|
|
40
|
+
errorMessage?: string;
|
|
41
|
+
attempt: number;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/** Minimal shape of an integration item as returned by GET /api/workspace/{id}. */
|
|
45
|
+
export interface WorkspaceIntegrationItem {
|
|
46
|
+
id?: string;
|
|
47
|
+
type?: string;
|
|
48
|
+
cellphoneNumber?: string;
|
|
49
|
+
cellphoneNumberFormat?: string;
|
|
50
|
+
creationDate?: string;
|
|
51
|
+
isActive?: number | boolean;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export const WA_POLL_INTERVAL_MS = 5000;
|
|
55
|
+
export const WA_POLL_MAX_ATTEMPTS = 60; // 5 minutes
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Returns a new whatsapp integration whose id is NOT in the baseline.
|
|
59
|
+
* If multiple are new, picks the most recently created one.
|
|
60
|
+
*/
|
|
61
|
+
export function findNewWhatsappIntegration(
|
|
62
|
+
integrations: WorkspaceIntegrationItem[] | undefined,
|
|
63
|
+
knownIds: Set<string>,
|
|
64
|
+
): WorkspaceIntegrationItem | null {
|
|
65
|
+
if (!integrations?.length) return null;
|
|
66
|
+
|
|
67
|
+
const candidates = integrations.filter(
|
|
68
|
+
(i) =>
|
|
69
|
+
(i.type === 'whatsapp' || i.type === 'whatsapp_business') &&
|
|
70
|
+
!!i.id &&
|
|
71
|
+
!knownIds.has(i.id as string),
|
|
72
|
+
);
|
|
73
|
+
if (!candidates.length) return null;
|
|
74
|
+
|
|
75
|
+
return candidates.reduce((latest, current) => {
|
|
76
|
+
const a = latest.creationDate ? new Date(latest.creationDate).getTime() : 0;
|
|
77
|
+
const b = current.creationDate ? new Date(current.creationDate).getTime() : 0;
|
|
78
|
+
return b > a ? current : latest;
|
|
79
|
+
});
|
|
80
|
+
}
|
package/src/types/agent.ts
CHANGED
package/src/types/auth.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { BaseCommandOptions } from './common';
|
|
1
|
+
import { BaseCommandOptions } from './common.js';
|
|
2
2
|
|
|
3
3
|
export interface LoginOptions extends BaseCommandOptions {
|
|
4
|
-
email
|
|
4
|
+
email?: string;
|
|
5
5
|
apiKey: string;
|
|
6
6
|
workspace: string;
|
|
7
7
|
zone: "LA" | "EU";
|
|
8
|
-
|
|
8
|
+
userId?: string;
|
|
9
|
+
}
|
package/src/types/portal.ts
CHANGED
package/src/types/workers.ts
CHANGED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import type { StoredCredentials } from './credentials.js';
|
|
3
|
+
|
|
4
|
+
interface AxiosLikeError {
|
|
5
|
+
response?: {
|
|
6
|
+
status?: number;
|
|
7
|
+
data?: { message?: string };
|
|
8
|
+
};
|
|
9
|
+
message?: string;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Resuelve un error proveniente del SDK/axios al cargar un agente y devuelve
|
|
14
|
+
* un mensaje legible que oriente al usuario sobre la causa real (404 = ID o
|
|
15
|
+
* workspace/zona incorrectos, 401 = token expirado, etc.).
|
|
16
|
+
*/
|
|
17
|
+
export function describeAgentLoadError(
|
|
18
|
+
error: unknown,
|
|
19
|
+
agentId: string,
|
|
20
|
+
credentials: Pick<StoredCredentials, 'workspace' | 'zone'>,
|
|
21
|
+
context: { dev?: boolean; workspaceOverride?: string; zoneOverride?: string } = {}
|
|
22
|
+
): string {
|
|
23
|
+
const err = error as AxiosLikeError;
|
|
24
|
+
const status = err?.response?.status;
|
|
25
|
+
const workspace = context.workspaceOverride || credentials.workspace;
|
|
26
|
+
const zone = context.zoneOverride || credentials.zone;
|
|
27
|
+
const envHint = context.dev ? ' (env: --dev / localhost:5090)' : '';
|
|
28
|
+
|
|
29
|
+
if (status === 404) {
|
|
30
|
+
return [
|
|
31
|
+
`Agent "${agentId}" was not found in workspace ${workspace} (zone ${zone})${envHint}.`,
|
|
32
|
+
chalk.gray(' Verify the ID and active workspace:'),
|
|
33
|
+
chalk.gray(' plazbot status'),
|
|
34
|
+
chalk.gray(' plazbot agent list'),
|
|
35
|
+
chalk.gray(' If the agent lives in a different zone, re-init with the right one:'),
|
|
36
|
+
chalk.gray(' plazbot init -z LA # or EU'),
|
|
37
|
+
].join('\n');
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
if (status === 401) {
|
|
41
|
+
return [
|
|
42
|
+
'Authentication token rejected (401).',
|
|
43
|
+
chalk.gray(' Re-run: plazbot init -k <jwt> -w <workspace> -z LA|EU'),
|
|
44
|
+
].join('\n');
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (status === 403) {
|
|
48
|
+
return [
|
|
49
|
+
`No permissions to access agent "${agentId}" in workspace ${workspace}.`,
|
|
50
|
+
chalk.gray(' Confirm your user has access to that workspace.'),
|
|
51
|
+
].join('\n');
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
if (status === 429) {
|
|
55
|
+
return 'Rate limit reached. Try again in a few seconds.';
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if (typeof status === 'number' && status >= 500) {
|
|
59
|
+
return [
|
|
60
|
+
`Backend error (HTTP ${status})${envHint}.`,
|
|
61
|
+
chalk.gray(` ${err.response?.data?.message || err.message || ''}`).trimEnd(),
|
|
62
|
+
].join('\n');
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const fallback = err?.response?.data?.message || err?.message || 'Unknown error';
|
|
66
|
+
return fallback;
|
|
67
|
+
}
|
package/src/utils/api.ts
CHANGED
|
@@ -22,8 +22,14 @@ export function createApiClient(options: ApiClientOptions): AxiosInstance {
|
|
|
22
22
|
baseURL,
|
|
23
23
|
headers: {
|
|
24
24
|
'Content-Type': 'application/json',
|
|
25
|
+
// El apiKey almacenado en el CLI ya es un JWT válido. El backend espera
|
|
26
|
+
// Authorization: Bearer en endpoints nuevos (ej. /api/agent/studio).
|
|
27
|
+
// x-api-key se mantiene transitorio para no romper endpoints legacy.
|
|
28
|
+
'Authorization': `Bearer ${options.apiKey}`,
|
|
25
29
|
'x-api-key': options.apiKey,
|
|
26
30
|
'x-workspace-id': options.workspace,
|
|
27
31
|
},
|
|
28
32
|
});
|
|
29
33
|
}
|
|
34
|
+
|
|
35
|
+
export { getBaseUrl };
|
package/src/utils/banner.ts
CHANGED
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
import chalk from 'chalk';
|
|
2
|
-
import {
|
|
2
|
+
import { readFileSync } from 'node:fs';
|
|
3
|
+
import { fileURLToPath } from 'node:url';
|
|
4
|
+
import { dirname, join } from 'node:path';
|
|
5
|
+
import { getStoredCredentials } from './credentials.js';
|
|
3
6
|
|
|
4
|
-
const
|
|
7
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
8
|
+
const pkgPath = join(__dirname, '..', '..', 'package.json');
|
|
9
|
+
const { version: VERSION } = JSON.parse(readFileSync(pkgPath, 'utf-8'));
|
|
5
10
|
|
|
6
11
|
// ASCII art del logo Plazbot (burbujas de chat)
|
|
7
12
|
const logo = [
|
|
@@ -45,27 +50,27 @@ export async function showBanner(): Promise<void> {
|
|
|
45
50
|
const rightColumn: string[] = [];
|
|
46
51
|
|
|
47
52
|
if (credentials) {
|
|
48
|
-
rightColumn.push(chalk.bold.hex('#4CAF50')('
|
|
53
|
+
rightColumn.push(chalk.bold.hex('#4CAF50')('Connected workspace'));
|
|
49
54
|
rightColumn.push(chalk.gray(` ${credentials.workspace || 'N/A'}`));
|
|
50
|
-
rightColumn.push(chalk.gray(` ${credentials.email
|
|
51
|
-
rightColumn.push(chalk.gray(`
|
|
55
|
+
if (credentials.email) rightColumn.push(chalk.gray(` ${credentials.email}`));
|
|
56
|
+
rightColumn.push(chalk.gray(` Zone: ${credentials.zone || 'N/A'}`));
|
|
52
57
|
rightColumn.push('');
|
|
53
58
|
rightColumn.push(chalk.hex('#4CAF50')('─'.repeat(35)));
|
|
54
59
|
rightColumn.push('');
|
|
55
|
-
rightColumn.push(chalk.bold.hex('#4CAF50')('
|
|
60
|
+
rightColumn.push(chalk.bold.hex('#4CAF50')('Quick commands'));
|
|
56
61
|
rightColumn.push(chalk.white(' plazbot agent list'));
|
|
57
62
|
rightColumn.push(chalk.white(' plazbot agent create'));
|
|
58
63
|
rightColumn.push(chalk.white(' plazbot agent chat -a <id>'));
|
|
59
64
|
rightColumn.push(chalk.white(' plazbot whatsapp send-message'));
|
|
60
65
|
} else {
|
|
61
|
-
rightColumn.push(chalk.bold.hex('#FFA726')('
|
|
66
|
+
rightColumn.push(chalk.bold.hex('#FFA726')('Not connected'));
|
|
62
67
|
rightColumn.push('');
|
|
63
|
-
rightColumn.push(chalk.bold.hex('#4CAF50')('
|
|
68
|
+
rightColumn.push(chalk.bold.hex('#4CAF50')('To get started'));
|
|
64
69
|
rightColumn.push(chalk.white(' plazbot init -e <email> -k <key> -w <workspace> -z <zone>'));
|
|
65
70
|
rightColumn.push('');
|
|
66
71
|
rightColumn.push(chalk.hex('#4CAF50')('─'.repeat(35)));
|
|
67
72
|
rightColumn.push('');
|
|
68
|
-
rightColumn.push(chalk.bold.hex('#4CAF50')('
|
|
73
|
+
rightColumn.push(chalk.bold.hex('#4CAF50')('Documentation'));
|
|
69
74
|
rightColumn.push(chalk.gray(' https://docs.plazbot.com'));
|
|
70
75
|
}
|
|
71
76
|
|
package/src/utils/credentials.ts
CHANGED
|
@@ -5,22 +5,23 @@ import os from 'os';
|
|
|
5
5
|
const configDir = path.join(os.homedir(), '.plazbot');
|
|
6
6
|
const configPath = path.join(configDir, 'config.json');
|
|
7
7
|
|
|
8
|
-
interface StoredCredentials {
|
|
9
|
-
email
|
|
8
|
+
export interface StoredCredentials {
|
|
9
|
+
email?: string;
|
|
10
10
|
apiKey: string;
|
|
11
11
|
workspace: string;
|
|
12
12
|
zone: "LA" | "EU";
|
|
13
|
+
userId?: string;
|
|
13
14
|
}
|
|
14
15
|
|
|
15
16
|
export async function getStoredCredentials(): Promise<StoredCredentials> {
|
|
16
17
|
try {
|
|
17
18
|
const configRaw = await fs.readFile(configPath, 'utf-8');
|
|
18
19
|
const config = JSON.parse(configRaw);
|
|
19
|
-
|
|
20
|
+
|
|
20
21
|
if (!config.apiKey || !config.workspace || !config.zone) {
|
|
21
22
|
throw new Error('Credenciales incompletas');
|
|
22
23
|
}
|
|
23
|
-
|
|
24
|
+
|
|
24
25
|
return config;
|
|
25
26
|
} catch (error) {
|
|
26
27
|
throw new Error("No se encontró una sesión activa. Ejecuta 'plazbot init' primero.");
|
|
@@ -34,4 +35,4 @@ export async function saveCredentials(credentials: StoredCredentials): Promise<v
|
|
|
34
35
|
|
|
35
36
|
export async function removeCredentials(): Promise<void> {
|
|
36
37
|
await fs.rm(configPath, { force: true });
|
|
37
|
-
}
|
|
38
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
|
|
4
|
+
export interface HelpExample {
|
|
5
|
+
/** Brief description of what the example does. */
|
|
6
|
+
description: string;
|
|
7
|
+
/** The command line to run (without the `$ ` prefix). */
|
|
8
|
+
command: string;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Appends a colored "Examples" section to a Commander command's --help output.
|
|
13
|
+
*
|
|
14
|
+
* Usage:
|
|
15
|
+
* addExamples(myCommand, [
|
|
16
|
+
* { description: 'List all agents in the current workspace', command: 'plazbot agent list' },
|
|
17
|
+
* { description: 'List as JSON for scripting', command: 'plazbot agent list --json' },
|
|
18
|
+
* ]);
|
|
19
|
+
*
|
|
20
|
+
* Renders as:
|
|
21
|
+
* Examples:
|
|
22
|
+
* # List all agents in the current workspace
|
|
23
|
+
* $ plazbot agent list
|
|
24
|
+
*
|
|
25
|
+
* # List as JSON for scripting
|
|
26
|
+
* $ plazbot agent list --json
|
|
27
|
+
*/
|
|
28
|
+
export function addExamples(cmd: Command, examples: HelpExample[]): Command {
|
|
29
|
+
if (!examples.length) return cmd;
|
|
30
|
+
const lines: string[] = ['', chalk.bold('Examples:')];
|
|
31
|
+
for (const ex of examples) {
|
|
32
|
+
lines.push(' ' + chalk.gray('# ' + ex.description));
|
|
33
|
+
lines.push(' ' + chalk.cyan('$ ') + ex.command);
|
|
34
|
+
lines.push('');
|
|
35
|
+
}
|
|
36
|
+
cmd.addHelpText('after', lines.join('\n'));
|
|
37
|
+
return cmd;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Appends a "Notes" section after Examples. Use for caveats, links, or
|
|
42
|
+
* prerequisites the user should know before running the command.
|
|
43
|
+
*/
|
|
44
|
+
export function addNotes(cmd: Command, notes: string[]): Command {
|
|
45
|
+
if (!notes.length) return cmd;
|
|
46
|
+
const lines: string[] = ['', chalk.bold('Notes:')];
|
|
47
|
+
for (const n of notes) lines.push(' ' + chalk.gray('• ') + n);
|
|
48
|
+
lines.push('');
|
|
49
|
+
cmd.addHelpText('after', lines.join('\n'));
|
|
50
|
+
return cmd;
|
|
51
|
+
}
|
package/tsconfig.json
CHANGED
|
@@ -1,15 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"compilerOptions": {
|
|
3
|
-
"target": "
|
|
4
|
-
"module": "
|
|
3
|
+
"target": "es2022",
|
|
4
|
+
"module": "NodeNext",
|
|
5
|
+
"moduleResolution": "NodeNext",
|
|
6
|
+
"jsx": "react-jsx",
|
|
5
7
|
"outDir": "./dist",
|
|
6
8
|
"rootDir": "./src",
|
|
7
9
|
"strict": true,
|
|
8
10
|
"esModuleInterop": true,
|
|
9
11
|
"skipLibCheck": true,
|
|
10
|
-
"
|
|
11
|
-
"
|
|
12
|
+
"resolveJsonModule": true,
|
|
13
|
+
"isolatedModules": true,
|
|
14
|
+
"forceConsistentCasingInFileNames": true
|
|
12
15
|
},
|
|
13
16
|
"include": ["src/**/*"],
|
|
14
|
-
"exclude": ["node_modules", "**/*.spec.ts"]
|
|
15
|
-
}
|
|
17
|
+
"exclude": ["node_modules", "**/*.spec.ts", "dist"]
|
|
18
|
+
}
|