@ghostystudio/cli 0.34.0 → 0.36.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 +9 -1
- package/dist/index.js +92 -20
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -18,6 +18,7 @@ ghosty usage # plan and usage this week
|
|
|
18
18
|
ghosty usage --workspace SLUG [--by agent,day] [--days 14] # a workspace's turns and tokens per agent/day (owner or staff)
|
|
19
19
|
ghosty engines ls [--models] # valid --engine / --model values and what each model costs
|
|
20
20
|
ghosty bags ls|create|set|rm <workspace> ["bag"] [--tokens 20M] [--recurring on|off] [--hard-cap on|off] [--note] # token bags (changing: staff)
|
|
21
|
+
ghosty spaces create <slug> [--combo …: staff] [--dry-run] # yours, trial
|
|
21
22
|
ghosty spaces renew <workspace> --until YYYY-MM-DD [--note] [--dry-run] # staff
|
|
22
23
|
ghosty spaces rename <old> <new> [--dry-run] # staff, slug only
|
|
23
24
|
ghosty agents ls [--engine E] [--ids] [--sponsor EMAIL | --owner EMAIL] # --sponsor/--owner: any account (Ghosty staff)
|
|
@@ -58,7 +59,7 @@ ghosty boards ls|create|assign|move-cards|rm <workspace|agent> … [--columns-
|
|
|
58
59
|
ghosty cards ls <id> [--q TEXT] [--limit 20] # recent cards on its sales board
|
|
59
60
|
ghosty cards show <id> <folio|phone|id> [--limit 20] # a card's thread, attachments and whether gs kept a copy
|
|
60
61
|
ghosty cards archive <id> --integration X | --column X | --before 30d [--dry-run]
|
|
61
|
-
ghosty mcp get|set <id> [--file servers.json]
|
|
62
|
+
ghosty mcp get|set <id> [--file servers.json] # http headers accept ${turn.token} (per-turn key)
|
|
62
63
|
|
|
63
64
|
ghosty try <id> "message" [--session] [--reset]
|
|
64
65
|
ghosty try <id> "message" --waba --session PHONE [--media FILE [--as-formmy]] [--history FILE] # real WhatsApp path, nothing sent
|
|
@@ -97,6 +98,12 @@ Every command has its own help with examples: `ghosty <command> --help` or `ghos
|
|
|
97
98
|
|
|
98
99
|
Exit codes: `0` ok · `1` API error · `2` usage error · `3` not signed in.
|
|
99
100
|
|
|
101
|
+
### Changes in 0.35.0
|
|
102
|
+
|
|
103
|
+
- `spaces create <slug> [--dry-run]`: create a workspace of your own from the terminal (trial, same rules as the web form). Then `partner enable <slug>`.
|
|
104
|
+
- `mcp set`: an `http` server's headers accept `${turn.token}`, filled per turn with the `turnToken` that `message-stream`/`turns` receive (one key per end user; the token never reaches the box).
|
|
105
|
+
- `partner --help`: the `gpk_`/`gps_` pair also signs `message-stream` for the normal agents of the partner's workspace.
|
|
106
|
+
|
|
100
107
|
### Changes in 0.33.0
|
|
101
108
|
|
|
102
109
|
- Staff: `agents doctor --user EMAIL` (their agents: doctor, latest turns and whether the app picked up each answer, plan/bag, boxes with duplicates flagged), `usage --images [--plan free] [--by user]` (image charges vs deliveries, real cost vs the table), `conversations show <agent> <conv> --tools` (every tool it ran, secrets masked, and the external domains it named).
|
|
@@ -136,6 +143,7 @@ Exit codes: `0` ok · `1` API error · `2` usage error · `3` not signed in.
|
|
|
136
143
|
- `partner credentials create|rotate --env-file PATH` (mode 600, nothing printed) or `--format env` (pipe to `fly secrets import`). The secret's env var is now `GHOSTY_PARTNER_KEY_SECRET` (`GHOSTY_PARTNER_SECRET` still works).
|
|
137
144
|
- `partner agent apply --prompt-file prompt.md`; `partner try --verbose` prints each tool's arguments and milliseconds.
|
|
138
145
|
- `partner agent get|apply --agent SLUG` and `partner try --agent SLUG`: several agents per partner (e.g. `nik-admin`, `nik-public`). `channels whatsapp link … --partner-tenant <externalId> --partner-agent <slug>`: a business's WhatsApp Business number answered by that partner agent.
|
|
146
|
+
- `partner wa groups ls|create|link|unlink`: WhatsApp groups of a partner agent's own number (e.g. `nik-admin`), each linked to a business.
|
|
139
147
|
- Empty `partner ls|credentials ls|tenants ls` say what to do next. `login --device --profile <client>` explains how to sign in a client's account (they approve the link).
|
|
140
148
|
|
|
141
149
|
### Changes in 0.27.1
|
package/dist/index.js
CHANGED
|
@@ -8065,6 +8065,18 @@ var SERVER_MESSAGES = [
|
|
|
8065
8065
|
["las memorias s\xF3lo se tocan en el chat personal de la persona", "memories can only be changed in the person's personal chat"],
|
|
8066
8066
|
["la persona la ve y la edita en Memorias de su app", "the person sees and edits it in Memories in their app"],
|
|
8067
8067
|
["No pude abrir el chat nuevo: {}", "Couldn't open the new chat: {}"],
|
|
8068
|
+
// — Espacios y turnToken por turno (spaces create, mcp set, message-stream)
|
|
8069
|
+
["combo distinto de teams: s\xF3lo el staff de Ghosty", "a combo other than teams: Ghosty staff only"],
|
|
8070
|
+
['el espacio "{}" ya existe', 'workspace "{}" already exists'],
|
|
8071
|
+
["{} ya tiene {} espacio(s) y su plan permite {}", "{} already owns {} workspace(s) and their plan allows {}"],
|
|
8072
|
+
["no se pudo crear el espacio", "couldn't create the workspace"],
|
|
8073
|
+
["${turn.token} s\xF3lo funciona en motores del pool (claude-worker y similares), no en ACP", "${turn.token} only works on pool engines (claude-worker and similar), not ACP"],
|
|
8074
|
+
["servers[{}]: ${turn.token} s\xF3lo va en headers de un MCP http (url)", "servers[{}]: ${turn.token} only goes in the headers of an http MCP (url)"],
|
|
8075
|
+
["turnToken debe ser un string no vac\xEDo", "turnToken must be a non-empty string"],
|
|
8076
|
+
["turnToken debe tener al menos {} caracteres", "turnToken must be at least {} characters"],
|
|
8077
|
+
["turnToken excede {} caracteres", "turnToken exceeds {} characters"],
|
|
8078
|
+
["turnToken no puede llevar espacios", "turnToken can't contain whitespace"],
|
|
8079
|
+
["turnToken requerido: los MCP de este agente usan ${turn.token}", "turnToken required: this agent's MCP servers use ${turn.token}"],
|
|
8068
8080
|
// — Infra interna (casi nunca llega al CLI, pero por si acaso)
|
|
8069
8081
|
["SESSION_SECRET ausente en producci\xF3n \u2014 las cookies quedar\xEDan firmadas con un valor p\xFAblico. Inyectarlo con ./scripts/set_gs_secret.sh SESSION_SECRET (openssl rand -hex 32).", "SESSION_SECRET missing in production \u2014 cookies would be signed with a public value. Inject it with ./scripts/set_gs_secret.sh SESSION_SECRET (openssl rand -hex 32)."],
|
|
8070
8082
|
["sqld: fetch sin namespace", "sqld: fetch without namespace"],
|
|
@@ -8367,7 +8379,7 @@ async function postLong(path, body, timeoutMs = 9e5) {
|
|
|
8367
8379
|
const req = httpsRequest(`${base}${path}`, {
|
|
8368
8380
|
method: "POST",
|
|
8369
8381
|
timeout: timeoutMs,
|
|
8370
|
-
headers: { authorization: `Bearer ${token}`, "user-agent": `ghosty-cli/${"0.
|
|
8382
|
+
headers: { authorization: `Bearer ${token}`, "user-agent": `ghosty-cli/${"0.36.0"}`, "content-type": "application/json", "content-length": Buffer.byteLength(data) }
|
|
8371
8383
|
}, (res) => {
|
|
8372
8384
|
let buf = "";
|
|
8373
8385
|
res.on("data", (c) => buf += c);
|
|
@@ -8409,7 +8421,7 @@ async function request(path, opts = {}, retried = false) {
|
|
|
8409
8421
|
method: opts.method ?? (opts.body !== void 0 || opts.raw !== void 0 ? "POST" : "GET"),
|
|
8410
8422
|
headers: {
|
|
8411
8423
|
authorization: `Bearer ${token}`,
|
|
8412
|
-
"user-agent": `ghosty-cli/${"0.
|
|
8424
|
+
"user-agent": `ghosty-cli/${"0.36.0"}`,
|
|
8413
8425
|
"accept-language": lang(),
|
|
8414
8426
|
...opts.body !== void 0 ? { "content-type": "application/json" } : {},
|
|
8415
8427
|
...opts.headers
|
|
@@ -9505,6 +9517,12 @@ ${bold("Tenants")} ${dim("(your customers, by externalId \u2014 config only, no
|
|
|
9505
9517
|
partner tenants set <externalId> --config '{"name":"\u2026","timezone":"America/Mexico_City"}'
|
|
9506
9518
|
partner tenants rm <externalId> Deletes its config AND its memory
|
|
9507
9519
|
|
|
9520
|
+
${bold("WhatsApp groups")} ${dim("(the number of a partner agent, e.g. nik-admin, paired by Baileys)")}
|
|
9521
|
+
partner wa groups ls [--agent SLUG] [--invites] Groups, the business each one answers, on/off
|
|
9522
|
+
partner wa groups create --tenant ID --name N --agent SLUG New group for that business, on (max 10/hour)
|
|
9523
|
+
partner wa groups link <jid> --tenant ID --agent SLUG [--off] Link a group the number is already in
|
|
9524
|
+
partner wa groups unlink <jid> [--agent SLUG] Unlink and turn off (the number stays in the group)
|
|
9525
|
+
|
|
9508
9526
|
${bold("Try it")}
|
|
9509
9527
|
partner try <externalId> "message" One turn [--agent SLUG] [--group END_USER_ID] [--turn-token SHORT_LIVED_TOKEN] [--verbose: tool args and ms]
|
|
9510
9528
|
(the turn token goes to YOUR MCP as \${turn.token}; --token also works here)
|
|
@@ -9515,6 +9533,7 @@ ${bold("Options")}
|
|
|
9515
9533
|
|
|
9516
9534
|
${bold("Server credential mode")} GHOSTY_PARTNER_KEY=gpk_\u2026 GHOSTY_PARTNER_KEY_SECRET=gps_\u2026 ghosty partner agent get
|
|
9517
9535
|
${dim("(GHOSTY_PARTNER_SECRET also works; it is NOT the gs server's global secret)")}
|
|
9536
|
+
${dim("The same gpk_/gps_ pair signs POST /api/v2/fleet-agents/<id>/message-stream for the normal agents of this space (claude-worker), with turnToken per end user.")}
|
|
9518
9537
|
${dim("Docs: https://www.ghosty.studio/docs/cli/partners")}`,
|
|
9519
9538
|
`${bold("Uso:")} ghosty partner <comando> [opciones]
|
|
9520
9539
|
|
|
@@ -9537,6 +9556,12 @@ ${bold("Tenants")} ${dim("(tus clientes, por externalId \u2014 s\xF3lo config,
|
|
|
9537
9556
|
partner tenants set <externalId> --config '{"name":"\u2026","timezone":"America/Mexico_City"}'
|
|
9538
9557
|
partner tenants rm <externalId> Borra su config Y su memoria
|
|
9539
9558
|
|
|
9559
|
+
${bold("Grupos de WhatsApp")} ${dim("(el n\xFAmero de un agente de partner, p. ej. nik-admin, pareado por Baileys)")}
|
|
9560
|
+
partner wa groups ls [--agent SLUG] [--invites] Grupos, a qu\xE9 negocio contesta cada uno, prendido/apagado
|
|
9561
|
+
partner wa groups create --tenant ID --name N --agent SLUG Grupo nuevo para ese negocio, prendido (m\xE1x. 10/hora)
|
|
9562
|
+
partner wa groups link <jid> --tenant ID --agent SLUG [--off] Liga un grupo donde ya est\xE1 el n\xFAmero
|
|
9563
|
+
partner wa groups unlink <jid> [--agent SLUG] Lo desliga y lo apaga (el n\xFAmero sigue en el grupo)
|
|
9564
|
+
|
|
9540
9565
|
${bold("Pru\xE9balo")}
|
|
9541
9566
|
partner try <externalId> "mensaje" Un turno [--agent SLUG] [--group END_USER_ID] [--turn-token TOKEN_DE_VIDA_CORTA] [--verbose: args y ms de cada tool]
|
|
9542
9567
|
(el token del turno llega a TU MCP como \${turn.token}; --token tambi\xE9n sirve aqu\xED)
|
|
@@ -9547,6 +9572,7 @@ ${bold("Opciones")}
|
|
|
9547
9572
|
|
|
9548
9573
|
${bold("Modo credencial de servidor")} GHOSTY_PARTNER_KEY=gpk_\u2026 GHOSTY_PARTNER_KEY_SECRET=gps_\u2026 ghosty partner agent get
|
|
9549
9574
|
${dim("(GHOSTY_PARTNER_SECRET tambi\xE9n vale; NO es el secreto global del servidor de gs)")}
|
|
9575
|
+
${dim("El mismo par gpk_/gps_ firma POST /api/v2/fleet-agents/<id>/message-stream de los agentes normales de este espacio (claude-worker), con turnToken por usuario final.")}
|
|
9550
9576
|
${dim("Docs: https://www.ghosty.studio/docs/cli/partners")}`
|
|
9551
9577
|
);
|
|
9552
9578
|
var enc5 = encodeURIComponent;
|
|
@@ -9569,7 +9595,7 @@ async function call(path, v, init = {}) {
|
|
|
9569
9595
|
"x-ghosty-ts": ts,
|
|
9570
9596
|
"x-ghosty-sig": sig,
|
|
9571
9597
|
"content-type": "application/json",
|
|
9572
|
-
"user-agent": `ghosty-cli/${"0.
|
|
9598
|
+
"user-agent": `ghosty-cli/${"0.36.0"}`
|
|
9573
9599
|
},
|
|
9574
9600
|
body: method === "GET" ? void 0 : raw
|
|
9575
9601
|
});
|
|
@@ -9717,7 +9743,38 @@ async function tryCmd(externalId, text, v) {
|
|
|
9717
9743
|
}
|
|
9718
9744
|
if (!globals.json && full) process.stdout.write("\n");
|
|
9719
9745
|
}
|
|
9720
|
-
async function
|
|
9746
|
+
async function waCmd(what, sub, jid, v) {
|
|
9747
|
+
if (what !== "groups") throw usage(t("Try: ghosty partner wa groups ls", "Prueba: ghosty partner wa groups ls"));
|
|
9748
|
+
const base = "/api/v2/partner/wa/groups";
|
|
9749
|
+
if (!sub || sub === "ls" || sub === "list") {
|
|
9750
|
+
const q = new URLSearchParams();
|
|
9751
|
+
if (v.agent) q.set("agent", v.agent);
|
|
9752
|
+
if (v.invites) q.set("invites", "1");
|
|
9753
|
+
const r = await json(`${base}${q.size ? `?${q}` : ""}`, v);
|
|
9754
|
+
return out(
|
|
9755
|
+
r,
|
|
9756
|
+
() => r.groups.length ? table(r.groups.map((g) => ({ name: g.name, jid: g.jid, business: g.externalId ?? dim("\u2014"), agent: g.agent ?? "app", status: g.enabled ? lavender("on") : dim("off"), ...v.invites ? { invite: g.inviteUrl ?? "" } : {} })), ["name", "jid", "business", "agent", "status", ...v.invites ? ["invite"] : []]) : dim(t("No groups. The number has to be paired (ghosty channels wa \u2026) and in at least one group.", "Sin grupos. El n\xFAmero tiene que estar pareado (ghosty channels wa \u2026) y en al menos un grupo."))
|
|
9757
|
+
);
|
|
9758
|
+
}
|
|
9759
|
+
if (sub === "create") {
|
|
9760
|
+
if (!v.tenant || !v.name || !v.agent) throw usage(t("Missing --tenant, --name or --agent.", "Falta --tenant, --name o --agent."), `${t("Example", "Ejemplo")}: ghosty partner wa groups create --tenant org_123 --name "Nik \xB7 Spa Luna" --agent nik-admin`);
|
|
9761
|
+
const r = await json(base, v, { method: "POST", body: { externalId: v.tenant, name: v.name, agent: v.agent } });
|
|
9762
|
+
return out(r, () => `${lavender("\u2713")} ${r.jid}
|
|
9763
|
+
${t("Invite", "Invitaci\xF3n")}: ${r.inviteUrl}`);
|
|
9764
|
+
}
|
|
9765
|
+
if (!jid) throw usage(t("Missing the group jid (\u2026@g.us).", "Falta el jid del grupo (\u2026@g.us)."), `${t("See them", "Velos")}: ghosty partner wa groups ls`);
|
|
9766
|
+
if (sub === "link") {
|
|
9767
|
+
if (!v.tenant || !v.agent) throw usage(t("Missing --tenant or --agent.", "Falta --tenant o --agent."), `${t("Example", "Ejemplo")}: ghosty partner wa groups link ${jid} --tenant org_123 --agent nik-admin`);
|
|
9768
|
+
const r = await json(`${base}/${enc5(jid)}`, v, { method: "PUT", body: { externalId: v.tenant, agent: v.agent, enabled: !v.off } });
|
|
9769
|
+
return out(r, () => `${lavender("\u2713")} ${r.group.name} \u2192 ${r.group.externalId} \xB7 ${r.group.enabled ? t("on (answers everything)", "prendido (contesta todo)") : t("off", "apagado")}`);
|
|
9770
|
+
}
|
|
9771
|
+
if (sub === "unlink" || sub === "rm") {
|
|
9772
|
+
const r = await json(`${base}/${enc5(jid)}${v.agent ? `?agent=${enc5(v.agent)}` : ""}`, v, { method: "DELETE" });
|
|
9773
|
+
return out(r, () => r.unlinked ? `${lavender("\u2713")} ${t("Unlinked and off. The number stays in the group.", "Desligado y apagado. El n\xFAmero sigue en el grupo.")}` : dim(t("It wasn't linked.", "No estaba ligado.")));
|
|
9774
|
+
}
|
|
9775
|
+
throw usage(t(`Unknown wa groups subcommand: ${sub}.`, `Subcomando de wa groups desconocido: ${sub}.`), t("Try", "Prueba") + ": ghosty partner wa groups ls | create | link | unlink");
|
|
9776
|
+
}
|
|
9777
|
+
async function partnerCmd(sub, a1, a2, v, a3) {
|
|
9721
9778
|
switch (sub) {
|
|
9722
9779
|
case void 0:
|
|
9723
9780
|
case "help":
|
|
@@ -9745,6 +9802,8 @@ async function partnerCmd(sub, a1, a2, v) {
|
|
|
9745
9802
|
}
|
|
9746
9803
|
case "try":
|
|
9747
9804
|
return tryCmd(a1, a2, v);
|
|
9805
|
+
case "wa":
|
|
9806
|
+
return waCmd(a1, a2, a3, v);
|
|
9748
9807
|
default:
|
|
9749
9808
|
throw usage(t(`Unknown partner subcommand: ${sub}.`, `Subcomando de partner desconocido: ${sub}.`), t("Run", "Corre") + ": ghosty partner --help");
|
|
9750
9809
|
}
|
|
@@ -10379,7 +10438,7 @@ async function channelsCmd(kind, sub, id, ref, v) {
|
|
|
10379
10438
|
if (sub === "link" || sub === "unlink") return linkCmd(sub, id, v);
|
|
10380
10439
|
if (sub === "history") return historyCmd(id, v);
|
|
10381
10440
|
if (sub === "integrations") return integrationsCmd(id, v.email);
|
|
10382
|
-
if (sub === "import" || sub === "status" || sub === "pause" || sub === "pair") return
|
|
10441
|
+
if (sub === "import" || sub === "status" || sub === "pause" || sub === "pair") return waCmd2(sub, id, v);
|
|
10383
10442
|
if (sub === "enable" && !v["dry-run"]) requireYesIfHeadless(v.yes, `ghosty channels whatsapp enable ${id} ${ref ?? "<number>"}`);
|
|
10384
10443
|
const path = `/api/v2/agents/${enc7(id)}/whatsapp`;
|
|
10385
10444
|
const listing = !sub || sub === "ls" || sub === "list";
|
|
@@ -10493,7 +10552,7 @@ function originText(o) {
|
|
|
10493
10552
|
groups
|
|
10494
10553
|
].join("\n");
|
|
10495
10554
|
}
|
|
10496
|
-
async function
|
|
10555
|
+
async function waCmd2(sub, id, v) {
|
|
10497
10556
|
if (!id) throw usage(t("Missing agent id.", "Falta el id del agente."), t("Example", "Ejemplo") + `: ghosty channels wa ${sub} <agent-id>`);
|
|
10498
10557
|
const base = `/api/v2/agents/${enc7(id)}/wa`;
|
|
10499
10558
|
if (sub === "status") {
|
|
@@ -11151,16 +11210,16 @@ var HELPS_ES = {
|
|
|
11151
11210
|
notes: ["ls dice, de una ya enviada, cu\xE1ntos entreg\xF3 y rechaz\xF3 FCM (del push log, desde el 1-oct).", "--image se publica en img.ghosty.studio (WebP 1200 px). --to vac\xEDo = todos. send sin --at la manda ya (pregunta); --at '' quita la programaci\xF3n.", "--min-version N (versionCode de Android): si la app del tester es m\xE1s vieja, el bot\xF3n dice \xABActualizar\xBB y lanza la actualizaci\xF3n de Play desde la app; '' la quita."]
|
|
11152
11211
|
},
|
|
11153
11212
|
spaces: {
|
|
11154
|
-
summary: "Espacios: lista los tuyos (o, staff, los de cualquiera) y operaciones del staff de Ghosty \u2014 entrar/salir del espacio de un cliente, cambiar su combo, mover \xABpagado hasta\xBB, renombrar su slug. Cada cambio queda en la bit\xE1cora del espacio.",
|
|
11213
|
+
summary: "Espacios: crea uno a tu nombre (prueba), lista los tuyos (o, staff, los de cualquiera) y operaciones del staff de Ghosty \u2014 entrar/salir del espacio de un cliente, cambiar su combo, mover \xABpagado hasta\xBB, renombrar su slug. Cada cambio queda en la bit\xE1cora del espacio.",
|
|
11155
11214
|
flags: [
|
|
11156
11215
|
["--user EMAIL", "ls (staff): los espacios de esa persona"],
|
|
11157
|
-
["--combo C", "set (staff): teams | sales | both \u2014 sin Ventas sus tableros existen pero nadie los ve"],
|
|
11216
|
+
["--combo C", "set (staff): teams | sales | both \u2014 sin Ventas sus tableros existen pero nadie los ve; create: distinto de teams, s\xF3lo staff"],
|
|
11158
11217
|
["--until DATE", "renew: el nuevo \xABpagado hasta\xBB (AAAA-MM-DD)"],
|
|
11159
11218
|
["--note TEXT", "renew: por qu\xE9 (va a la bit\xE1cora)"],
|
|
11160
11219
|
["-n, --dry-run", "ense\xF1a qu\xE9 cambia, no cambia nada"],
|
|
11161
11220
|
["--yes", "s\xE1ltate la confirmaci\xF3n (obligatorio sin terminal)"]
|
|
11162
11221
|
],
|
|
11163
|
-
notes: ["Con suscripci\xF3n de Stripe renew se niega: la fecha la mueve la factura pagada.", "rename cambia s\xF3lo el slug (id y namespace se quedan, as\xED que tablero, Stripe y WhatsApp siguen funcionando); las ligas viejas <slug>.sales dejan de servir."]
|
|
11222
|
+
notes: ["create sigue las reglas de la web: queda a tu nombre, nace como prueba de 30 d\xEDas, tu correo debe estar confirmado y tu plan topa cu\xE1ntos tienes. Sigue: ghosty partner enable <slug>.", "Con suscripci\xF3n de Stripe renew se niega: la fecha la mueve la factura pagada.", "rename cambia s\xF3lo el slug (id y namespace se quedan, as\xED que tablero, Stripe y WhatsApp siguen funcionando); las ligas viejas <slug>.sales dejan de servir."]
|
|
11164
11223
|
}
|
|
11165
11224
|
};
|
|
11166
11225
|
var HELP_ALIASES = { creds: "credentials", board: "cards", conversations: "chat", workspaces: "spaces" };
|
|
@@ -11724,18 +11783,18 @@ HELPS.novedades = {
|
|
|
11724
11783
|
learn: `${REF}#soporte`
|
|
11725
11784
|
};
|
|
11726
11785
|
HELPS.spaces = {
|
|
11727
|
-
summary: "Workspaces: list yours (or, staff, anyone's), and Ghosty staff operations \u2014 join/leave a client's workspace, change its combo, move \xABpaid until\xBB, rename its slug. Each change is logged in the workspace's audit.",
|
|
11728
|
-
usage: ["ghosty spaces ls [--user EMAIL]", "ghosty spaces join|leave <workspace>", "ghosty spaces set <workspace> --combo teams|sales|both [--dry-run]", "ghosty spaces renew <workspace> --until YYYY-MM-DD [--note TEXT] [--dry-run] [--yes]", "ghosty spaces rename <old> <new> [--dry-run] [--yes]"],
|
|
11786
|
+
summary: "Workspaces: create one of your own (trial), list yours (or, staff, anyone's), and Ghosty staff operations \u2014 join/leave a client's workspace, change its combo, move \xABpaid until\xBB, rename its slug. Each change is logged in the workspace's audit.",
|
|
11787
|
+
usage: ["ghosty spaces ls [--user EMAIL]", "ghosty spaces create <slug> [--combo teams|sales|both] [--dry-run]", "ghosty spaces join|leave <workspace>", "ghosty spaces set <workspace> --combo teams|sales|both [--dry-run]", "ghosty spaces renew <workspace> --until YYYY-MM-DD [--note TEXT] [--dry-run] [--yes]", "ghosty spaces rename <old> <new> [--dry-run] [--yes]"],
|
|
11729
11788
|
flags: [
|
|
11730
11789
|
["--user EMAIL", "ls (staff): that person's workspaces"],
|
|
11731
|
-
["--combo C", "set (staff): teams | sales | both \u2014 without Sales its boards exist but nobody sees them"],
|
|
11790
|
+
["--combo C", "set (staff): teams | sales | both \u2014 without Sales its boards exist but nobody sees them; create: other than teams, staff only"],
|
|
11732
11791
|
["--until DATE", "renew: the new \xABpaid until\xBB (YYYY-MM-DD)"],
|
|
11733
11792
|
["--note TEXT", "renew: why (goes into the audit)"],
|
|
11734
11793
|
["-n, --dry-run", "show what changes, change nothing"],
|
|
11735
11794
|
["--yes", "skip the confirmation (required without a terminal)"]
|
|
11736
11795
|
],
|
|
11737
|
-
examples: ["ghosty spaces ls", "ghosty spaces ls --user brenda@siiqtec.com", "ghosty spaces join denik", "ghosty spaces set denik --combo sales --dry-run", 'ghosty spaces renew descti --until 2026-11-01 --note "pag\xF3 octubre"', "ghosty spaces rename totequim siiqtec --dry-run"],
|
|
11738
|
-
notes: ["With a Stripe subscription renew refuses: the paid invoice moves the date.", "rename changes only the slug (id and namespace stay, so board, Stripe and WhatsApp keep working); old <slug>.sales links stop working."],
|
|
11796
|
+
examples: ["ghosty spaces ls", "ghosty spaces create mailmask --dry-run", "ghosty spaces ls --user brenda@siiqtec.com", "ghosty spaces join denik", "ghosty spaces set denik --combo sales --dry-run", 'ghosty spaces renew descti --until 2026-11-01 --note "pag\xF3 octubre"', "ghosty spaces rename totequim siiqtec --dry-run"],
|
|
11797
|
+
notes: ["create follows the same rules as the web: you own it, it starts as a 30-day trial, your email must be confirmed, and your plan caps how many you own. Next: ghosty partner enable <slug>.", "With a Stripe subscription renew refuses: the paid invoice moves the date.", "rename changes only the slug (id and namespace stay, so board, Stripe and WhatsApp keep working); old <slug>.sales links stop working."],
|
|
11739
11798
|
learn: `${REF}#espacios`
|
|
11740
11799
|
};
|
|
11741
11800
|
HELPS.workspaces = HELPS.spaces;
|
|
@@ -12220,12 +12279,21 @@ ${bagsText(r)}`);
|
|
|
12220
12279
|
}
|
|
12221
12280
|
}
|
|
12222
12281
|
async function spacesCmd(sub, slug, arg, v, context) {
|
|
12223
|
-
const ex = "ghosty spaces ls [--user EMAIL] \xB7 join|leave <workspace> \xB7 set <workspace> --combo teams|sales|both \xB7 renew <workspace> --until 2026-11-01 [--note TEXT] \xB7 rename <old> <new> [--dry-run]";
|
|
12282
|
+
const ex = "ghosty spaces ls [--user EMAIL] \xB7 create <slug> [--combo teams|sales|both] [--dry-run] \xB7 join|leave <workspace> \xB7 set <workspace> --combo teams|sales|both \xB7 renew <workspace> --until 2026-11-01 [--note TEXT] \xB7 rename <old> <new> [--dry-run]";
|
|
12224
12283
|
if (!sub || sub === "ls" || sub === "list") {
|
|
12225
12284
|
const r = await api(`/api/v2/workspaces${v.user ? `?user=${enc10(v.user)}` : ""}`);
|
|
12226
12285
|
const rows = r.workspaces.map((w) => ({ workspace: w.slug, role: w.role ?? "", plan: w.plan, combo: w.combo, owner: w.owner ?? "", paid: w.paidUntil ?? "" }));
|
|
12227
12286
|
return out(r, () => rows.length ? `${bold(r.user)}
|
|
12228
12287
|
${table(rows, ["workspace", "role", "plan", "combo", "owner", "paid"])}` : dim(t(`${r.user} has no workspaces.`, `${r.user} no tiene espacios.`)));
|
|
12288
|
+
}
|
|
12289
|
+
if (sub === "create") {
|
|
12290
|
+
slug = needSpace(slug, "ghosty spaces create <slug> [--combo teams|sales|both] [--dry-run]");
|
|
12291
|
+
const r = await api("/api/v2/workspaces", { method: "POST", body: { slug, ...v.combo ? { combo: v.combo } : {}, ...v["dry-run"] ? { dryRun: true } : {} } });
|
|
12292
|
+
const line2 = `${r.workspace} \xB7 ${r.owner} \xB7 ${r.plan} \xB7 ${r.combo}`;
|
|
12293
|
+
if (!r.created) return out(r, () => `${line2}
|
|
12294
|
+
${dim(t("Dry run: nothing created.", "Simulaci\xF3n: no se cre\xF3 nada."))}`);
|
|
12295
|
+
return out(r, () => `${lavender("\u2713")} ${line2}
|
|
12296
|
+
${dim(t(`Next: ghosty use ${r.workspace} \xB7 ghosty partner enable ${r.workspace}`, `Sigue: ghosty use ${r.workspace} \xB7 ghosty partner enable ${r.workspace}`))}`);
|
|
12229
12297
|
}
|
|
12230
12298
|
if (sub === "join" || sub === "leave") {
|
|
12231
12299
|
slug = needSpace(slug, `ghosty spaces ${sub} <workspace>`);
|
|
@@ -12663,6 +12731,7 @@ ${bold("Session")}
|
|
|
12663
12731
|
${bold("Workspaces")} ${dim("(changing them: Ghosty staff)")}
|
|
12664
12732
|
bags ls|create|set|rm <workspace> ["bag"] Token bags its agents spend from [--tokens 20M] [--recurring on|off] [--hard-cap on|off] [--note]
|
|
12665
12733
|
spaces ls Your workspaces (role, plan, combo) [--user EMAIL: someone else's]
|
|
12734
|
+
spaces create <slug> New workspace owned by you (trial) [--combo teams|sales|both: staff] [--dry-run]
|
|
12666
12735
|
spaces join|leave <workspace> Enter or leave a client's workspace as staff (no seat; logged)
|
|
12667
12736
|
spaces set <workspace> --combo sales teams | sales | both (without Sales its boards are invisible)
|
|
12668
12737
|
spaces renew <workspace> --until DATE Move \xABpaid until\xBB (logged) [--note] [--dry-run]
|
|
@@ -12708,7 +12777,7 @@ ${bold("Configure an agent")}
|
|
|
12708
12777
|
skills templates <id> pdf-doc templates it sees: its own and Ghosty's, and which folder wins
|
|
12709
12778
|
dbs ls|tables|query|import|rehost|grant|revoke|rename|rm <id> [db] Databases it uses [--write] [--external-write t1,t2] [--external-rows t:col] [--from easybits:ID --dry-run] [--table T --column C]
|
|
12710
12779
|
dbs photos put <id> <db> --table T --key-column K --dir DIR Loose photos to a catalog (SKU-123.jpg \u2192 its row), permanent links [--column C] [--dry-run]
|
|
12711
|
-
mcp get|set <id> MCP servers [--file servers.json]
|
|
12780
|
+
mcp get|set <id> MCP servers [--file servers.json] (http headers accept \${turn.token})
|
|
12712
12781
|
channels whatsapp ls|enable|disable <id> [number] Which WhatsApp Business numbers it answers [--dry-run]
|
|
12713
12782
|
channels whatsapp integrations <id> Its owner's WhatsApp Business numbers in Formmy (number, who answers today, Integration id)
|
|
12714
12783
|
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] [--dry-run]
|
|
@@ -12791,6 +12860,7 @@ ${bold("Sesi\xF3n")}
|
|
|
12791
12860
|
${bold("Espacios")} ${dim("(cambiarlos: staff de Ghosty)")}
|
|
12792
12861
|
bags ls|create|set|rm <espacio> ["bolsa"] Bolsas de tokens de las que gastan sus agentes [--tokens 20M] [--recurring on|off] [--hard-cap on|off] [--note]
|
|
12793
12862
|
spaces ls Tus espacios (rol, plan, combo) [--user CORREO: los de alguien m\xE1s]
|
|
12863
|
+
spaces create <slug> Espacio nuevo a tu nombre (trial) [--combo teams|sales|both: staff] [--dry-run]
|
|
12794
12864
|
spaces join|leave <espacio> Entra o sal del espacio de un cliente como staff (sin asiento; queda en bit\xE1cora)
|
|
12795
12865
|
spaces set <espacio> --combo sales teams | sales | both (sin Ventas sus tableros no se ven)
|
|
12796
12866
|
spaces renew <espacio> --until FECHA Mueve \xABpagado hasta\xBB (queda en bit\xE1cora) [--note] [--dry-run]
|
|
@@ -12836,7 +12906,7 @@ ${bold("Configurar un agente")}
|
|
|
12836
12906
|
skills templates <id> Plantillas de pdf-doc que ve: las suyas y las de Ghosty, y qu\xE9 carpeta gana
|
|
12837
12907
|
dbs ls|tables|query|import|rehost|grant|revoke|rename|rm <id> [db] Bases de datos que usa [--write] [--external-write t1,t2] [--external-rows t:col] [--from easybits:ID --dry-run] [--table T --column C]
|
|
12838
12908
|
dbs photos put <id> <db> --table T --key-column K --dir DIR Fotos sueltas a un cat\xE1logo (SKU-123.jpg \u2192 su fila), ligas permanentes [--column C] [--dry-run]
|
|
12839
|
-
mcp get|set <id> Servidores MCP [--file servers.json]
|
|
12909
|
+
mcp get|set <id> Servidores MCP [--file servers.json] (headers http admiten \${turn.token})
|
|
12840
12910
|
channels whatsapp ls|enable|disable <id> [n\xFAmero] Qu\xE9 n\xFAmeros de WhatsApp Business contesta [--dry-run]
|
|
12841
12911
|
channels whatsapp integrations <id> Los n\xFAmeros de WhatsApp Business de su due\xF1o en Formmy (n\xFAmero, qui\xE9n contesta hoy, id de la Integration)
|
|
12842
12912
|
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] [--dry-run]
|
|
@@ -13091,6 +13161,8 @@ async function main() {
|
|
|
13091
13161
|
draft: { type: "boolean" },
|
|
13092
13162
|
"ads-only": { type: "string" },
|
|
13093
13163
|
"partner-tenant": { type: "string" },
|
|
13164
|
+
tenant: { type: "string" },
|
|
13165
|
+
invites: { type: "boolean" },
|
|
13094
13166
|
"partner-agent": { type: "string" },
|
|
13095
13167
|
list: { type: "boolean" },
|
|
13096
13168
|
"only-ads": { type: "boolean" },
|
|
@@ -13116,7 +13188,7 @@ async function main() {
|
|
|
13116
13188
|
const tokens = splitTokens(pos, v);
|
|
13117
13189
|
globals.token = tokens.session;
|
|
13118
13190
|
globals.profile = v.profile;
|
|
13119
|
-
if (v.version) return out({ version: "0.
|
|
13191
|
+
if (v.version) return out({ version: "0.36.0" }, () => "0.36.0");
|
|
13120
13192
|
for (const n of normalizeArgs(pos, v)) if (!globals.json) info(dim(n));
|
|
13121
13193
|
const context = (await readConfig()).workspace;
|
|
13122
13194
|
if (!explicitToken()?.startsWith("gat_")) {
|
|
@@ -13229,7 +13301,7 @@ async function main() {
|
|
|
13229
13301
|
case "schedule":
|
|
13230
13302
|
return scheduleCmd(sub, a1, a2, v);
|
|
13231
13303
|
case "partner":
|
|
13232
|
-
return partnerCmd(sub, a1, a2, { ...v, token: tokens.turn });
|
|
13304
|
+
return partnerCmd(sub, a1, a2, { ...v, token: tokens.turn }, pos[4]);
|
|
13233
13305
|
case "usage":
|
|
13234
13306
|
if (v.images) return imageUsage(v);
|
|
13235
13307
|
if (v.boxes && v.by === "template") return fleetBoxes();
|
|
@@ -13265,7 +13337,7 @@ async function main() {
|
|
|
13265
13337
|
throw unknown(cmd, cmd, COMMANDS, "ghosty --help");
|
|
13266
13338
|
}
|
|
13267
13339
|
}
|
|
13268
|
-
var notice = updateNotice("0.
|
|
13340
|
+
var notice = updateNotice("0.36.0").catch(() => null);
|
|
13269
13341
|
main().then(
|
|
13270
13342
|
async () => {
|
|
13271
13343
|
const n = await notice;
|
package/package.json
CHANGED