@ghostystudio/cli 0.89.0 → 0.91.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.
Files changed (2) hide show
  1. package/dist/index.js +19 -15
  2. 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.89.0"}`, "content-type": "application/json", "content-length": Buffer.byteLength(data) }
1178
+ headers: { authorization: `Bearer ${token}`, "user-agent": `ghosty-cli/${"0.91.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.89.0"}`,
1220
+ "user-agent": `ghosty-cli/${"0.91.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.89.0"}`
11281
+ "user-agent": `ghosty-cli/${"0.91.0"}`
11282
11282
  },
11283
11283
  body: method === "GET" ? void 0 : raw
11284
11284
  });
@@ -13000,18 +13000,20 @@ ${t(`Cards appear on the team's board (no "new lead" alerts).`, "Las tarjetas ap
13000
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)}`);
13001
13001
  }
13002
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] [--unmute PHONE] [--seed]");
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] [--signature \u{1F47E}|off] [--seed]");
13004
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) throw usage(t("Use --mute or --unmute, not both.", "Usa --mute o --unmute, no los dos."));
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
13006
  const path2 = `/api/v2/agents/${enc11(id)}/whatsapp/contacts`;
13007
- const contact = v.mute ?? 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 ? { contact, off: !!v.mute } : {}, ...v.seed ? { seed: true } : {} } }) : await api(`${path2}?number=${enc11(v.integration)}`);
13007
+ const contact = v.mute ?? v.allow ?? v.unmute;
13008
+ const write = v["new-only"] !== void 0 || contact !== void 0 || v.seed || v.signature !== void 0;
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 } : {}, ...v.signature !== void 0 ? { signature: v.signature === "off" ? null : v.signature } : {} } }) : await api(`${path2}?number=${enc11(v.integration)}`);
13010
13010
  return out(r, () => {
13011
13011
  const lines = [
13012
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
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("Contacts without the agent", "Contactos sin agente")}: ${r.off.length ? r.off.map((o) => o.name ? `${o.name} ${o.key}` : o.key).join(", ") : dim("\u2014")}`
13014
+ `${t("Signature", "Firma")}: ${r.signature ? `${r.signature}:` : dim(t("none", "sin firma"))}`,
13015
+ `${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")}`,
13016
+ `${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")}`
13015
13017
  ];
13016
13018
  return lines.join("\n");
13017
13019
  });
@@ -13689,7 +13691,7 @@ var HELPS_ES = {
13689
13691
  ["--cached", "groups ls: no le pide a WhatsApp la lista en vivo (m\xE1s r\xE1pido; puede faltar alg\xFAn grupo nuevo)"],
13690
13692
  ["--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)"],
13691
13693
  ["--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)"],
13692
- ["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), --unmute TEL, --seed (vuelve a traer los contactos conocidos de WhatsApp)"],
13694
+ ["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), --signature \u{1F47E}|off (los mensajes del agente empiezan con \xAB\u{1F47E}:\xBB para que el cliente lo distinga de ti), --seed (vuelve a traer los contactos conocidos de WhatsApp)"],
13693
13695
  ["--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"],
13694
13696
  ["--list", "history --dry-run: CU\xC1LES conversaciones (tel\xE9fono, nombre, primer mensaje, mensajes, si vino de anuncio)"],
13695
13697
  ["--only-ads / --phones a,b", "history: importa (o lista) s\xF3lo las de anuncio y/o esos tel\xE9fonos"],
@@ -14582,7 +14584,7 @@ HELPS.channels = {
14582
14584
  ["--cached", "groups ls: don't ask WhatsApp for the live list (faster; may miss new groups)"],
14583
14585
  ["--ads-only on|off", "link: only conversations that come from an ad open a card (also alone, to change it on a linked number)"],
14584
14586
  ["--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)"],
14585
- ["contacts <id> --integration ID", "new contacts only and contacts without the agent: --new-only on|off, --mute PHONE (the agent never answers that number), --unmute PHONE, --seed (bring the known contacts from WhatsApp again)"],
14587
+ ["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), --signature \u{1F47E}|off (the agent's messages start with \u201C\u{1F47E}:\u201D so customers can tell it from you), --seed (bring the known contacts from WhatsApp again)"],
14586
14588
  ["--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"],
14587
14589
  ["--list", "history --dry-run: WHICH conversations (phone, name, first message, messages, from an ad)"],
14588
14590
  ["--only-ads / --phones a,b", "history: import (or list) only the ones from an ad and/or those phones"],
@@ -17064,7 +17066,7 @@ ${bold("Configure an agent")}
17064
17066
  channels messenger on|off <id> <page> Answer a page with this agent, or stop (off keeps logging to the board) [--take --dry-run --yes]
17065
17067
  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]
17066
17068
  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]
17067
- 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] [--unmute PHONE] [--seed]
17069
+ 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] [--signature \u{1F47E}|off] [--seed]
17068
17070
  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]
17069
17071
  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]
17070
17072
  channels wa pair <id> --phone N Pair a personal WhatsApp by code (no QR)
@@ -17283,7 +17285,7 @@ ${bold("Configurar un agente")}
17283
17285
  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]
17284
17286
  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]
17285
17287
  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]
17286
- 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] [--unmute TEL] [--seed]
17288
+ 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] [--signature \u{1F47E}|off] [--seed]
17287
17289
  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]
17288
17290
  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]
17289
17291
  channels wa pair <id> --phone N Vincula un WhatsApp personal con c\xF3digo (sin QR)
@@ -17669,6 +17671,8 @@ async function main() {
17669
17671
  "new-only": { type: "string" },
17670
17672
  mute: { type: "string" },
17671
17673
  unmute: { type: "string" },
17674
+ allow: { type: "string" },
17675
+ signature: { type: "string" },
17672
17676
  seed: { type: "boolean" },
17673
17677
  "partner-tenant": { type: "string" },
17674
17678
  ref: { type: "string", multiple: true },
@@ -17712,7 +17716,7 @@ async function main() {
17712
17716
  const tokens = splitTokens(pos, v);
17713
17717
  globals.token = tokens.session;
17714
17718
  globals.profile = v.profile;
17715
- if (v.version) return out({ version: "0.89.0" }, () => "0.89.0");
17719
+ if (v.version) return out({ version: "0.91.0" }, () => "0.91.0");
17716
17720
  for (const n of normalizeArgs(pos, v)) if (!globals.json) info(dim(n));
17717
17721
  const context = (await readConfig()).workspace;
17718
17722
  if (!explicitToken()?.startsWith("gat_")) {
@@ -17915,7 +17919,7 @@ async function main() {
17915
17919
  throw unknown(cmd, cmd, COMMANDS, "ghosty --help");
17916
17920
  }
17917
17921
  }
17918
- var notice = updateNotice("0.89.0").catch(() => null);
17922
+ var notice = updateNotice("0.91.0").catch(() => null);
17919
17923
  main().then(
17920
17924
  async () => {
17921
17925
  const n = process.stderr.isTTY ? await notice : null;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ghostystudio/cli",
3
- "version": "0.89.0",
3
+ "version": "0.91.0",
4
4
  "description": "Official Ghosty Studio CLI — configure, test and chat with your agents from the terminal. Built for humans and coding agents.",
5
5
  "type": "module",
6
6
  "bin": {