@ghostystudio/cli 0.88.0 → 0.90.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/dist/index.js +33 -5
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1175,7 +1175,7 @@ async function postLong(path2, body, timeoutMs = 9e5) {
|
|
|
1175
1175
|
const req = httpsRequest(`${base}${path2}`, {
|
|
1176
1176
|
method: "POST",
|
|
1177
1177
|
timeout: timeoutMs,
|
|
1178
|
-
headers: { authorization: `Bearer ${token}`, "user-agent": `ghosty-cli/${"0.
|
|
1178
|
+
headers: { authorization: `Bearer ${token}`, "user-agent": `ghosty-cli/${"0.90.0"}`, "content-type": "application/json", "content-length": Buffer.byteLength(data) }
|
|
1179
1179
|
}, (res) => {
|
|
1180
1180
|
let buf = "";
|
|
1181
1181
|
res.on("data", (c) => buf += c);
|
|
@@ -1217,7 +1217,7 @@ async function request(path2, opts = {}, retried = false) {
|
|
|
1217
1217
|
method: opts.method ?? (opts.body !== void 0 || opts.raw !== void 0 ? "POST" : "GET"),
|
|
1218
1218
|
headers: {
|
|
1219
1219
|
authorization: `Bearer ${token}`,
|
|
1220
|
-
"user-agent": `ghosty-cli/${"0.
|
|
1220
|
+
"user-agent": `ghosty-cli/${"0.90.0"}`,
|
|
1221
1221
|
"accept-language": lang(),
|
|
1222
1222
|
...opts.body !== void 0 ? { "content-type": "application/json" } : {},
|
|
1223
1223
|
...opts.headers
|
|
@@ -11278,7 +11278,7 @@ async function call(path2, v, init = {}) {
|
|
|
11278
11278
|
"x-ghosty-ts": ts,
|
|
11279
11279
|
"x-ghosty-sig": sig,
|
|
11280
11280
|
"content-type": "application/json",
|
|
11281
|
-
"user-agent": `ghosty-cli/${"0.
|
|
11281
|
+
"user-agent": `ghosty-cli/${"0.90.0"}`
|
|
11282
11282
|
},
|
|
11283
11283
|
body: method === "GET" ? void 0 : raw
|
|
11284
11284
|
});
|
|
@@ -12126,6 +12126,7 @@ function skipReason(r) {
|
|
|
12126
12126
|
channel_off: ["WhatsApp channel off for this agent", "canal de WhatsApp apagado en este agente"],
|
|
12127
12127
|
no_quota: ["out of balance", "sin saldo"],
|
|
12128
12128
|
own_number: ["sent by another of our agent numbers (bot loop guard)", "lo mand\xF3 otro n\xFAmero nuestro con agente (guarda de bucle)"],
|
|
12129
|
+
contact_off: ["the agent is turned off for this contact (whatsapp contacts --off)", "el agente est\xE1 apagado para este contacto (whatsapp contacts --off)"],
|
|
12129
12130
|
known_contact: ["contact wrote before --new-only was turned on (only new contacts get the agent)", "el contacto ya escrib\xEDa antes de --new-only (el agente s\xF3lo contesta a contactos nuevos)"],
|
|
12130
12131
|
partner_token: ["partner did not issue a turn token", "el partner no dio token de turno"],
|
|
12131
12132
|
partner_busy: ["partner at its concurrent-turn limit", "el partner lleg\xF3 a su tope de turnos a la vez"]
|
|
@@ -12630,6 +12631,7 @@ async function channelsCmd(kind, sub, id, ref, v) {
|
|
|
12630
12631
|
if (!id) throw usage(t("Missing agent id.", "Falta el id del agente."), t("Example", "Ejemplo") + ": ghosty channels whatsapp ls <agent-id>");
|
|
12631
12632
|
if (sub === "link" || sub === "unlink") return linkCmd(sub, id, v);
|
|
12632
12633
|
if (sub === "history") return historyCmd(id, v);
|
|
12634
|
+
if (sub === "contacts") return contactsCmd(id, v);
|
|
12633
12635
|
if (sub === "integrations" && v.orphans) return linksCmd(id, "waba", true);
|
|
12634
12636
|
if (sub === "integrations") return integrationsCmd(id, v.email);
|
|
12635
12637
|
if (sub === "import" || sub === "status" || sub === "pause" || sub === "pair") return waCmd2(sub, id, v);
|
|
@@ -12997,6 +12999,24 @@ ${t(`Cards appear on the team's board (no "new lead" alerts).`, "Las tarjetas ap
|
|
|
12997
12999
|
}
|
|
12998
13000
|
out({ ...sum, conversations: done }, () => `${lavender("\u2713")} ${t(`${sum.newCards} new card(s), ${sum.updatedCards} updated, ${sum.messages} message(s), ${sum.orders} order(s)`, `${sum.newCards} tarjeta(s) nueva(s), ${sum.updatedCards} actualizada(s), ${sum.messages} mensaje(s), ${sum.orders} pedido(s)`)}${files(sum)}${sum.suppressed ? dim(t(` \xB7 ${sum.suppressed} bot draft(s) the customer never saw, skipped`, ` \xB7 se omitieron ${sum.suppressed} borrador(es) del bot que el cliente nunca vio`)) : ""}${pausedLine(sum, id)}`);
|
|
12999
13001
|
}
|
|
13002
|
+
async function contactsCmd(id, v) {
|
|
13003
|
+
if (!id || !v.integration) throw usage(t("Missing agent id or --integration.", "Falta el id del agente o --integration."), t("Example", "Ejemplo") + ": ghosty channels whatsapp contacts <agent-id> --integration <id> [--new-only on|off] [--mute PHONE] [--allow PHONE] [--unmute PHONE] [--seed]");
|
|
13004
|
+
if (v["new-only"] !== void 0 && v["new-only"] !== "on" && v["new-only"] !== "off") throw usage(t("--new-only takes on or off.", "--new-only acepta on u off."));
|
|
13005
|
+
if ([v.mute, v.unmute, v.allow].filter((x) => x !== void 0).length > 1) throw usage(t("Use only one of --mute, --allow or --unmute.", "Usa s\xF3lo uno de --mute, --allow o --unmute."));
|
|
13006
|
+
const path2 = `/api/v2/agents/${enc11(id)}/whatsapp/contacts`;
|
|
13007
|
+
const contact = v.mute ?? v.allow ?? v.unmute;
|
|
13008
|
+
const write = v["new-only"] !== void 0 || contact !== void 0 || v.seed;
|
|
13009
|
+
const r = write ? await api(path2, { method: "POST", body: { number: v.integration, ...v["new-only"] !== void 0 ? { newOnly: v["new-only"] === "on" } : {}, ...contact !== void 0 ? v.allow !== void 0 ? { contact, always: true } : { contact, off: !!v.mute } : {}, ...v.seed ? { seed: true } : {} } }) : await api(`${path2}?number=${enc11(v.integration)}`);
|
|
13010
|
+
return out(r, () => {
|
|
13011
|
+
const lines = [
|
|
13012
|
+
`${t("New contacts only", "S\xF3lo contactos nuevos")}: ${r.newOnly ? lavender(t("on", "encendido")) : t("off", "apagado")}${r.newSince ? dim(` (${t("since", "desde")} ${r.newSince})`) : ""}`,
|
|
13013
|
+
`${t("Known contacts", "Contactos conocidos")}: ${r.known}${r.seededAt ? dim(` (${t("brought from Formmy", "tra\xEDdos de Formmy")} ${r.seededAt})`) : dim(t(" (still waiting for the WhatsApp history)", " (todav\xEDa esperando el historial de WhatsApp)"))}`,
|
|
13014
|
+
`${t("Always answers", "Siempre le contesta a")}: ${r.always?.length ? r.always.map((o) => o.name ? `${o.name} ${o.key}` : o.key).join(", ") : dim("\u2014")}`,
|
|
13015
|
+
`${t("Never answers", "Nunca le contesta a")}: ${r.off.length ? r.off.map((o) => o.name ? `${o.name} ${o.key}` : o.key).join(", ") : dim("\u2014")}`
|
|
13016
|
+
];
|
|
13017
|
+
return lines.join("\n");
|
|
13018
|
+
});
|
|
13019
|
+
}
|
|
13000
13020
|
|
|
13001
13021
|
// src/commands/board.ts
|
|
13002
13022
|
init_api();
|
|
@@ -13670,6 +13690,7 @@ var HELPS_ES = {
|
|
|
13670
13690
|
["--cached", "groups ls: no le pide a WhatsApp la lista en vivo (m\xE1s r\xE1pido; puede faltar alg\xFAn grupo nuevo)"],
|
|
13671
13691
|
["--ads-only on|off", "link: s\xF3lo las conversaciones que vienen de un anuncio abren tarjeta (tambi\xE9n solo, para cambiarlo en un n\xFAmero ya ligado)"],
|
|
13672
13692
|
["--new-only on|off", "link: el agente s\xF3lo contesta a contactos que escriben por primera vez desde ahora; los de antes quedan en el hilo para ti (tambi\xE9n solo)"],
|
|
13693
|
+
["contacts <id> --integration ID", "s\xF3lo contactos nuevos y contactos sin agente: --new-only on|off, --mute TEL (el agente nunca le contesta a ese n\xFAmero), --allow TEL (el agente le contesta aunque sea contacto conocido), --unmute TEL (vuelve a la regla general), --seed (vuelve a traer los contactos conocidos de WhatsApp)"],
|
|
13673
13694
|
["--board NAME|agent", "link: este n\xFAmero llena su propio tablero de ventas (nombre, id o main) en vez del del agente; las tools del CRM del agente trabajan ese tablero en los turnos de este n\xFAmero. agent = vuelve al del agente. Tambi\xE9n solo, en un n\xFAmero ya ligado"],
|
|
13674
13695
|
["--list", "history --dry-run: CU\xC1LES conversaciones (tel\xE9fono, nombre, primer mensaje, mensajes, si vino de anuncio)"],
|
|
13675
13696
|
["--only-ads / --phones a,b", "history: importa (o lista) s\xF3lo las de anuncio y/o esos tel\xE9fonos"],
|
|
@@ -14562,6 +14583,7 @@ HELPS.channels = {
|
|
|
14562
14583
|
["--cached", "groups ls: don't ask WhatsApp for the live list (faster; may miss new groups)"],
|
|
14563
14584
|
["--ads-only on|off", "link: only conversations that come from an ad open a card (also alone, to change it on a linked number)"],
|
|
14564
14585
|
["--new-only on|off", "link: the agent answers only contacts writing for the first time from now on; earlier contacts stay in the thread for you (also alone)"],
|
|
14586
|
+
["contacts <id> --integration ID", "new contacts only and contacts without the agent: --new-only on|off, --mute PHONE (the agent never answers that number), --allow PHONE (the agent answers that number even if it's a known contact), --unmute PHONE (back to the general rule), --seed (bring the known contacts from WhatsApp again)"],
|
|
14565
14587
|
["--board NAME|agent", "link: this number fills its own sales board (name, id or main) instead of the agent's; the agent's CRM tools work that board on this number's turns. agent = back to the agent's board. Also alone, on a linked number"],
|
|
14566
14588
|
["--list", "history --dry-run: WHICH conversations (phone, name, first message, messages, from an ad)"],
|
|
14567
14589
|
["--only-ads / --phones a,b", "history: import (or list) only the ones from an ad and/or those phones"],
|
|
@@ -17043,6 +17065,7 @@ ${bold("Configure an agent")}
|
|
|
17043
17065
|
channels messenger on|off <id> <page> Answer a page with this agent, or stop (off keeps logging to the board) [--take --dry-run --yes]
|
|
17044
17066
|
channels mteams ls|connect|zip|on|off|rm <id> [bot] Microsoft Teams bot (Azure Bot in the client's tenant) [--app-id --tenant --secret|GHOSTY_MTEAMS_SECRET --name --out]
|
|
17045
17067
|
channels whatsapp link|unlink <id> --integration ID --answer on|off Bring a WhatsApp Business number from Formmy/EasyBits to this agent, or send it back [--forward] [--ads-only on|off] [--new-only on|off] [--board NAME|agent] [--dry-run]
|
|
17068
|
+
channels whatsapp contacts <id> --integration ID New contacts only (the agent skips the people you already talk to) and contacts without the agent [--new-only on|off] [--mute PHONE] [--allow PHONE] [--unmute PHONE] [--seed]
|
|
17046
17069
|
channels whatsapp history <id> --integration ID [--days 7] Bring its recent cards, messages, orders and files from Formmy (no duplicates; Formmy keeps files 7 days) [--media] [--dry-run [--list]] [--only-ads] [--phones a,b] [--column NAME]
|
|
17047
17070
|
channels wa import <id> --from easybits:ID | --from-file F | --from-dir DIR --own-number yes|no Move a personal WhatsApp session here, no QR [--dry-run] [--replace] [--no-connect]
|
|
17048
17071
|
channels wa pair <id> --phone N Pair a personal WhatsApp by code (no QR)
|
|
@@ -17261,6 +17284,7 @@ ${bold("Configurar un agente")}
|
|
|
17261
17284
|
channels messenger on|off <id> <p\xE1gina> Que este agente conteste una p\xE1gina, o que deje de hacerlo (off sigue registrando en el tablero) [--take --dry-run --yes]
|
|
17262
17285
|
channels mteams ls|connect|zip|on|off|rm <id> [bot] Bot de Microsoft Teams (Azure Bot en el tenant del cliente) [--app-id --tenant --secret|GHOSTY_MTEAMS_SECRET --name --out]
|
|
17263
17286
|
channels whatsapp link|unlink <id> --integration ID --answer on|off Trae un n\xFAmero de WhatsApp Business de Formmy/EasyBits a este agente, o devu\xE9lvelo [--forward] [--ads-only on|off] [--new-only on|off] [--board NOMBRE|agent] [--dry-run]
|
|
17287
|
+
channels whatsapp contacts <id> --integration ID S\xF3lo contactos nuevos (el agente no le contesta a tu gente de siempre) y contactos sin agente [--new-only on|off] [--mute TEL] [--allow TEL] [--unmute TEL] [--seed]
|
|
17264
17288
|
channels whatsapp history <id> --integration ID [--days 7] Trae de Formmy sus tarjetas, mensajes, pedidos y archivos recientes (sin duplicar; Formmy guarda los archivos 7 d\xEDas) [--media] [--dry-run [--list]] [--only-ads] [--phones a,b] [--column NOMBRE]
|
|
17265
17289
|
channels wa import <id> --from easybits:ID | --from-file F | --from-dir DIR --own-number yes|no Mueve aqu\xED una sesi\xF3n de WhatsApp personal, sin QR [--dry-run] [--replace] [--no-connect]
|
|
17266
17290
|
channels wa pair <id> --phone N Vincula un WhatsApp personal con c\xF3digo (sin QR)
|
|
@@ -17644,6 +17668,10 @@ async function main() {
|
|
|
17644
17668
|
draft: { type: "boolean" },
|
|
17645
17669
|
"ads-only": { type: "string" },
|
|
17646
17670
|
"new-only": { type: "string" },
|
|
17671
|
+
mute: { type: "string" },
|
|
17672
|
+
unmute: { type: "string" },
|
|
17673
|
+
allow: { type: "string" },
|
|
17674
|
+
seed: { type: "boolean" },
|
|
17647
17675
|
"partner-tenant": { type: "string" },
|
|
17648
17676
|
ref: { type: "string", multiple: true },
|
|
17649
17677
|
"style-ref": { type: "string", multiple: true },
|
|
@@ -17686,7 +17714,7 @@ async function main() {
|
|
|
17686
17714
|
const tokens = splitTokens(pos, v);
|
|
17687
17715
|
globals.token = tokens.session;
|
|
17688
17716
|
globals.profile = v.profile;
|
|
17689
|
-
if (v.version) return out({ version: "0.
|
|
17717
|
+
if (v.version) return out({ version: "0.90.0" }, () => "0.90.0");
|
|
17690
17718
|
for (const n of normalizeArgs(pos, v)) if (!globals.json) info(dim(n));
|
|
17691
17719
|
const context = (await readConfig()).workspace;
|
|
17692
17720
|
if (!explicitToken()?.startsWith("gat_")) {
|
|
@@ -17889,7 +17917,7 @@ async function main() {
|
|
|
17889
17917
|
throw unknown(cmd, cmd, COMMANDS, "ghosty --help");
|
|
17890
17918
|
}
|
|
17891
17919
|
}
|
|
17892
|
-
var notice = updateNotice("0.
|
|
17920
|
+
var notice = updateNotice("0.90.0").catch(() => null);
|
|
17893
17921
|
main().then(
|
|
17894
17922
|
async () => {
|
|
17895
17923
|
const n = process.stderr.isTTY ? await notice : null;
|
package/package.json
CHANGED