plazbot-cli 0.3.3 → 0.3.6
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/dist/studio/components/App.js +38 -31
- package/dist/studio/components/ChatLog.js +49 -21
- package/dist/studio/components/ConnectCard.js +85 -0
- package/dist/studio/components/Footer.js +1 -1
- package/dist/studio/components/Input.js +143 -11
- package/dist/studio/connect/api.js +66 -0
- package/dist/studio/connect/polling.js +76 -0
- package/dist/studio/connect/types.js +72 -0
- package/dist/studio/runRepl.js +6 -37
- package/dist/studio/state/store.js +13 -12
- package/package.json +1 -1
- package/src/studio/components/App.tsx +41 -33
- package/src/studio/components/ChatLog.tsx +58 -32
- package/src/studio/components/{WhatsappConnectCard.tsx → ConnectCard.tsx} +54 -22
- package/src/studio/components/Footer.tsx +1 -1
- package/src/studio/components/Input.tsx +159 -15
- package/src/studio/{whatsapp → connect}/api.ts +11 -9
- package/src/studio/{whatsapp → connect}/polling.ts +26 -25
- package/src/studio/connect/types.ts +141 -0
- package/src/studio/runRepl.tsx +6 -37
- package/src/studio/state/store.ts +26 -20
- package/dist/studio/components/WhatsappConnectCard.js +0 -57
- package/src/studio/whatsapp/types.ts +0 -80
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
import { jsxs as _jsxs, jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
-
import { Box, Text } from 'ink';
|
|
3
|
-
import Spinner from 'ink-spinner';
|
|
4
|
-
import { WA_POLL_MAX_ATTEMPTS } from '../whatsapp/types.js';
|
|
5
|
-
function formatExpiry(iso) {
|
|
6
|
-
if (!iso)
|
|
7
|
-
return '';
|
|
8
|
-
const d = new Date(iso);
|
|
9
|
-
if (Number.isNaN(d.getTime()))
|
|
10
|
-
return '';
|
|
11
|
-
return d.toLocaleString('en-US', {
|
|
12
|
-
day: 'numeric',
|
|
13
|
-
month: 'short',
|
|
14
|
-
hour: '2-digit',
|
|
15
|
-
minute: '2-digit',
|
|
16
|
-
});
|
|
17
|
-
}
|
|
18
|
-
/**
|
|
19
|
-
* Wraps a URL in an OSC 8 hyperlink escape sequence. Terminals that don't
|
|
20
|
-
* support it just print the visible text — but iTerm2, kitty, Wezterm,
|
|
21
|
-
* Alacritty (recent), and modern VS Code/Hyper terminals do.
|
|
22
|
-
*/
|
|
23
|
-
function osc8(url, label) {
|
|
24
|
-
return `\u001b]8;;${url}\u001b\\${label}\u001b]8;;\u001b\\`;
|
|
25
|
-
}
|
|
26
|
-
export function WhatsappConnectCard({ state }) {
|
|
27
|
-
const { linkData, status, connectedNumber, errorMessage, attempt } = state;
|
|
28
|
-
const shortUrl = linkData.shortUrl || '';
|
|
29
|
-
const expiry = formatExpiry(linkData.expiresAt);
|
|
30
|
-
const typeLabel = linkData.linkType === 'whatsapp_business' ? 'WhatsApp Business' : 'WhatsApp Cloud API';
|
|
31
|
-
// Header glyph + color per status.
|
|
32
|
-
let headerIcon = '●';
|
|
33
|
-
let headerColor = 'green';
|
|
34
|
-
let headerText = 'Connect your WhatsApp';
|
|
35
|
-
if (status === 'connected') {
|
|
36
|
-
headerIcon = '✓';
|
|
37
|
-
headerColor = 'green';
|
|
38
|
-
headerText = 'WhatsApp connected';
|
|
39
|
-
}
|
|
40
|
-
else if (status === 'error') {
|
|
41
|
-
headerIcon = '✖';
|
|
42
|
-
headerColor = 'red';
|
|
43
|
-
headerText = 'Could not activate the number';
|
|
44
|
-
}
|
|
45
|
-
else if (status === 'timeout') {
|
|
46
|
-
headerIcon = '○';
|
|
47
|
-
headerColor = 'yellow';
|
|
48
|
-
headerText = 'No connection detected';
|
|
49
|
-
}
|
|
50
|
-
else if (status === 'cancelled') {
|
|
51
|
-
headerIcon = '○';
|
|
52
|
-
headerColor = 'yellow';
|
|
53
|
-
headerText = 'Connection cancelled';
|
|
54
|
-
}
|
|
55
|
-
const showLink = status !== 'connected' && status !== 'cancelled' && !!shortUrl;
|
|
56
|
-
return (_jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: status === 'error' ? 'red' : status === 'connected' ? 'green' : 'gray', paddingX: 1, marginY: 1, marginLeft: 2, children: [_jsxs(Box, { children: [_jsxs(Text, { bold: true, color: headerColor, children: [headerIcon, " "] }), _jsx(Text, { bold: true, children: headerText }), status !== 'connected' && status !== 'error' && status !== 'cancelled' ? (_jsxs(_Fragment, { children: [_jsx(Text, { dimColor: true, children: " " }), _jsxs(Text, { dimColor: true, children: ["\u00B7 ", typeLabel] })] })) : null] }), showLink ? (_jsxs(Box, { marginTop: 1, flexDirection: "column", children: [_jsxs(Box, { children: [_jsx(Text, { dimColor: true, children: "link: " }), _jsx(Text, { color: "cyan", underline: true, children: osc8(shortUrl, shortUrl) })] }), expiry ? (_jsx(Box, { children: _jsxs(Text, { dimColor: true, children: ["expires: ", expiry] }) })) : null, _jsx(Box, { marginTop: 1, children: _jsx(Text, { dimColor: true, children: "Open the link from a phone with WhatsApp installed. We'll keep watching for the new number." }) })] })) : null, _jsxs(Box, { marginTop: 1, children: [status === 'waiting' ? (_jsxs(_Fragment, { children: [_jsx(Text, { color: "yellow", children: _jsx(Spinner, { type: "dots" }) }), _jsx(Text, { dimColor: true, children: " Waiting for connection\u2026 " }), _jsxs(Text, { dimColor: true, children: ["(", attempt, "/", WA_POLL_MAX_ATTEMPTS, ")"] }), _jsx(Text, { dimColor: true, children: " \u00B7 press Esc to cancel" })] })) : null, status === 'activating' ? (_jsxs(_Fragment, { children: [_jsx(Text, { color: "yellow", children: _jsx(Spinner, { type: "dots" }) }), _jsx(Text, { dimColor: true, children: " Number detected, activating\u2026" })] })) : null, status === 'connected' ? (_jsxs(Text, { color: "green", children: ["Number ", connectedNumber || '(connected)', " activated successfully."] })) : null, status === 'timeout' ? (_jsx(Text, { dimColor: true, children: "We didn't detect the connection within 5 minutes. Ask the agent to try again." })) : null, status === 'cancelled' ? (_jsx(Text, { dimColor: true, children: "Polling cancelled by user." })) : null, status === 'error' ? (_jsx(Text, { color: "red", children: errorMessage || 'An error occurred while activating the integration.' })) : null] })] }));
|
|
57
|
-
}
|
|
@@ -1,80 +0,0 @@
|
|
|
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
|
-
}
|