@ghostystudio/cli 0.83.0 → 0.84.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 +4 -0
- package/dist/index.js +28 -9
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -146,6 +146,10 @@ Every command has its own help with examples: `ghosty <command> --help` or `ghos
|
|
|
146
146
|
|
|
147
147
|
Exit codes: `0` ok · `1` API error · `2` usage error · `3` not signed in.
|
|
148
148
|
|
|
149
|
+
### Changes in 0.84.0
|
|
150
|
+
|
|
151
|
+
- `coupons create|set` take `--from` (the lent plan starts then), `--redeem-by` (last moment to redeem) and `--convert-promo` (Stripe promotion code offered in /c/uso when the lent plan is about to end). New `coupons show <CODE>` (staff): who redeemed it, their plan window and who converted to a paid plan. Codes are accent- and case-insensitive.
|
|
152
|
+
|
|
149
153
|
### Changes in 0.83.0
|
|
150
154
|
|
|
151
155
|
- `spaces plan <workspace> trial|pro|empresarial [--courtesy] [--until YYYY-MM-DD] [--note] [--dry-run]` (staff): change a workspace's plan without opening /admin/tenants, with the same rules. The dry run shows plan, model cap, tokens (used/included, hard cap or not) and «paid until» before → after. Never charges Stripe nor emails the customer; `--courtesy` records it as a no-charge courtesy in the plan note and the audit (`workspace.plan`).
|
package/dist/index.js
CHANGED
|
@@ -1175,7 +1175,7 @@ async function postLong(path, body, timeoutMs = 9e5) {
|
|
|
1175
1175
|
const req = httpsRequest(`${base}${path}`, {
|
|
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.84.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(path, 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.84.0"}`,
|
|
1221
1221
|
"accept-language": lang(),
|
|
1222
1222
|
...opts.body !== void 0 ? { "content-type": "application/json" } : {},
|
|
1223
1223
|
...opts.headers
|
|
@@ -11237,7 +11237,7 @@ async function call(path, v, init = {}) {
|
|
|
11237
11237
|
"x-ghosty-ts": ts,
|
|
11238
11238
|
"x-ghosty-sig": sig,
|
|
11239
11239
|
"content-type": "application/json",
|
|
11240
|
-
"user-agent": `ghosty-cli/${"0.
|
|
11240
|
+
"user-agent": `ghosty-cli/${"0.84.0"}`
|
|
11241
11241
|
},
|
|
11242
11242
|
body: method === "GET" ? void 0 : raw
|
|
11243
11243
|
});
|
|
@@ -16281,7 +16281,10 @@ function couponRow(c) {
|
|
|
16281
16281
|
code: c.code,
|
|
16282
16282
|
credit: `$${c.creditMxn}`,
|
|
16283
16283
|
plan: c.plan ?? "",
|
|
16284
|
+
from: c.planFrom ? c.planFrom.slice(0, 10) : "",
|
|
16284
16285
|
until: c.until ? c.until.slice(0, 10) : "",
|
|
16286
|
+
redeem: c.redeemBy ? c.redeemBy.slice(0, 10) : "",
|
|
16287
|
+
promo: c.convertPromo ?? "",
|
|
16285
16288
|
used: `${c.redemptions}/${c.maxRedemptions ?? "\u221E"}`,
|
|
16286
16289
|
state: c.active ? t("active", "activo") : t("draft", "borrador"),
|
|
16287
16290
|
only: c.eligibility ?? "",
|
|
@@ -16289,11 +16292,17 @@ function couponRow(c) {
|
|
|
16289
16292
|
note: c.note ?? ""
|
|
16290
16293
|
};
|
|
16291
16294
|
}
|
|
16295
|
+
function redemptionRow(x) {
|
|
16296
|
+
return { email: x.email, redeemed: x.redeemedAt.slice(0, 10), plan: x.plan ?? "", from: x.from?.slice(0, 10) ?? "", until: x.until?.slice(0, 10) ?? "", status: x.status ?? "", converted: x.converted ?? "\u2014" };
|
|
16297
|
+
}
|
|
16292
16298
|
function bodyOf(v) {
|
|
16293
16299
|
const b = {};
|
|
16294
16300
|
if (v.credit !== void 0) b.creditMxn = Number(v.credit);
|
|
16295
16301
|
if (v.plan !== void 0) b.plan = v.plan === "none" ? null : v.plan;
|
|
16296
16302
|
if (v.until !== void 0) b.until = v.until;
|
|
16303
|
+
if (v.from !== void 0) b.planFrom = v.from;
|
|
16304
|
+
if (v["redeem-by"] !== void 0) b.redeemBy = v["redeem-by"];
|
|
16305
|
+
if (v["convert-promo"] !== void 0) b.convertPromo = v["convert-promo"];
|
|
16297
16306
|
if (v.max !== void 0) b.maxRedemptions = v.max === "none" ? null : Number(v.max);
|
|
16298
16307
|
if (v.on) b.active = true;
|
|
16299
16308
|
if (v.off) b.active = false;
|
|
@@ -16306,7 +16315,7 @@ async function couponsCmd(sub, code, v) {
|
|
|
16306
16315
|
const one = (c) => `${lavender("\u2713")} ${c.code} $${c.creditMxn}${c.plan ? ` + ${c.plan} \u2192 ${c.until?.slice(0, 10)}` : ""} ${c.active ? t("active", "activo") : dim(t("draft", "borrador"))}`;
|
|
16307
16316
|
if (!sub || sub === "ls" || sub === "list") {
|
|
16308
16317
|
const r = await api("/api/v2/support/coupons");
|
|
16309
|
-
return out(r, () => r.coupons.length ? table(r.coupons.map(couponRow), ["code", "credit", "plan", "until", "used", "state", "only", "agent", "note"]) : dim(t("No coupons.", "Sin cupones.")));
|
|
16318
|
+
return out(r, () => r.coupons.length ? table(r.coupons.map(couponRow), ["code", "credit", "plan", "from", "until", "redeem", "promo", "used", "state", "only", "agent", "note"]) : dim(t("No coupons.", "Sin cupones.")));
|
|
16310
16319
|
}
|
|
16311
16320
|
if (!code) throw usage(t("Missing the coupon code.", "Falta el c\xF3digo del cup\xF3n."), `ghosty coupons ${sub} <CODE>`);
|
|
16312
16321
|
if (sub === "create") {
|
|
@@ -16317,11 +16326,17 @@ async function couponsCmd(sub, code, v) {
|
|
|
16317
16326
|
const r = await api(`/api/v2/support/coupons/${encodeURIComponent(code)}`, { method: "PATCH", body: bodyOf(v) });
|
|
16318
16327
|
return out(r, () => one(r.coupon));
|
|
16319
16328
|
}
|
|
16329
|
+
if (sub === "show") {
|
|
16330
|
+
const r = await api(`/api/v2/support/coupons/${encodeURIComponent(code)}`);
|
|
16331
|
+
return out(r, () => `${one(r.coupon)}
|
|
16332
|
+
${r.redemptions.length ? table(r.redemptions.map(redemptionRow), ["email", "redeemed", "plan", "from", "until", "status", "converted"]) : dim(t("Nobody redeemed it yet.", "Nadie lo ha canjeado."))}
|
|
16333
|
+
${dim(t(`${r.converted}/${r.redemptions.length} converted to a paid plan`, `${r.converted}/${r.redemptions.length} ya pagan un plan`))}`);
|
|
16334
|
+
}
|
|
16320
16335
|
if (sub === "redeem") {
|
|
16321
16336
|
const r = await api("/api/v2/me/coupons", { method: "POST", body: { code } });
|
|
16322
16337
|
return out(r, () => `${lavender("\u2713")} ${r.message}`);
|
|
16323
16338
|
}
|
|
16324
|
-
throw usage(t(`Unknown coupons subcommand: ${sub}.`, `Subcomando de coupons desconocido: ${sub}.`), "ghosty coupons ls|create|set|redeem <CODE>");
|
|
16339
|
+
throw usage(t(`Unknown coupons subcommand: ${sub}.`, `Subcomando de coupons desconocido: ${sub}.`), "ghosty coupons ls|create|set|show|redeem <CODE>");
|
|
16325
16340
|
}
|
|
16326
16341
|
|
|
16327
16342
|
// src/commands/ads.ts
|
|
@@ -16667,7 +16682,8 @@ ${bold("Workspaces")} ${dim("(changing them: Ghosty staff)")}
|
|
|
16667
16682
|
staff ls [staff-email] [client-email] Ghosty staff assigned to client accounts (staff) [--all: also revoked]
|
|
16668
16683
|
staff assign|unassign <staff> <client> Staff sees and runs that account's agents, documents, databases and boards as themselves (no keys, billing or transfers; logged) [--reason]
|
|
16669
16684
|
settings ls|set|unset <KEY> [value] Platform switches (staff): who answers /c without an account, native subagents\u2026 [+id/-id edits a list]
|
|
16670
|
-
coupons ls|create|set <CODE> Redeemable coupons (staff): balance in cost pesos and an optional lent plan until a date; created as a draft [--credit 50] [--plan pro|power|max --until 2026-11-13] [--max 100] [--eligibility hackathon:<event>: accepted people only] [--agent ID: each account gets its own copy] [--on|--off] [--note]
|
|
16685
|
+
coupons ls|create|set <CODE> Redeemable coupons (staff): balance in cost pesos and an optional lent plan until a date; created as a draft [--credit 50] [--plan pro|power|max --until 2026-11-13] [--max 100] [--eligibility hackathon:<event>: accepted people only] [--agent ID: each account gets its own copy] [--from DATE: the lent plan starts then] [--redeem-by DATE: last day to redeem] [--convert-promo STRIPE_CODE: offered when the plan ends] [--on|--off] [--note]
|
|
16686
|
+
coupons show <CODE> Who redeemed it: plan window (pending/active/ended) and who converted to a paid plan (staff)
|
|
16671
16687
|
coupons redeem <CODE> Redeem a coupon for your account (also /canjear?codigo=CODE)
|
|
16672
16688
|
ads watch [ls|run] Campaign watch (staff): Meta campaigns that stop delivering and ads-only WhatsApp numbers with no leads for 24 h [run --dry-run: what it would alert]
|
|
16673
16689
|
audit ls The audit log: who changed what (agent page, channels, pauses, replies, transfers, "log in as") [--workspace SLUG] [--agent ID] [--actor EMAIL] [--action A] [--since 24h] [--limit N]
|
|
@@ -16875,7 +16891,8 @@ ${bold("Espacios")} ${dim("(cambiarlos: staff de Ghosty)")}
|
|
|
16875
16891
|
staff ls [correo-staff] [correo-cliente] Staff de Ghosty asignado a cuentas cliente (staff) [--all: tambi\xE9n revocadas]
|
|
16876
16892
|
staff assign|unassign <staff> <cliente> El staff ve y opera agentes, documentos, bases y tableros de esa cuenta como s\xED mismo (sin llaves, cobro ni traspasos; queda en bit\xE1cora) [--reason]
|
|
16877
16893
|
settings ls|set|unset <CLAVE> [valor] Perillas de la plataforma (staff): qui\xE9n atiende /c sin cuenta, subagentes nativos\u2026 [+id/-id edita una lista]
|
|
16878
|
-
coupons ls|create|set <C\xD3DIGO> Cupones canjeables (staff): saldo en pesos de costo y un plan prestado opcional hasta una fecha; nacen como borrador [--credit 50] [--plan pro|power|max --until 2026-11-13] [--max 100] [--eligibility hackathon:<evento>: s\xF3lo aceptados] [--agent ID: cada cuenta recibe su copia] [--on|--off] [--note]
|
|
16894
|
+
coupons ls|create|set <C\xD3DIGO> Cupones canjeables (staff): saldo en pesos de costo y un plan prestado opcional hasta una fecha; nacen como borrador [--credit 50] [--plan pro|power|max --until 2026-11-13] [--max 100] [--eligibility hackathon:<evento>: s\xF3lo aceptados] [--agent ID: cada cuenta recibe su copia] [--from FECHA: el plan prestado arranca ah\xED] [--redeem-by FECHA: \xFAltimo d\xEDa para canjear] [--convert-promo C\xD3DIGO_STRIPE: se ofrece al terminar el plan] [--on|--off] [--note]
|
|
16895
|
+
coupons show <C\xD3DIGO> Qui\xE9n lo canje\xF3: ventana del plan (por empezar/activo/termin\xF3) y qui\xE9n ya paga un plan (staff)
|
|
16879
16896
|
coupons redeem <C\xD3DIGO> Canjea un cup\xF3n para tu cuenta (tambi\xE9n /canjear?codigo=C\xD3DIGO)
|
|
16880
16897
|
ads watch [ls|run] Vig\xEDa de campa\xF1as (staff): campa\xF1as de Meta que dejan de entregar y n\xFAmeros \xABs\xF3lo anuncios\xBB sin leads en 24 h [run --dry-run: lo que avisar\xEDa]
|
|
16881
16898
|
audit ls La bit\xE1cora: qui\xE9n cambi\xF3 qu\xE9 (ficha, canales, pausas, respuestas, traspasos, \xABentrar como\xBB) [--workspace SLUG] [--agent ID] [--actor CORREO] [--action A] [--since 24h] [--limit N]
|
|
@@ -17117,6 +17134,8 @@ async function main() {
|
|
|
17117
17134
|
until: { type: "string" },
|
|
17118
17135
|
credit: { type: "string" },
|
|
17119
17136
|
eligibility: { type: "string" },
|
|
17137
|
+
"redeem-by": { type: "string" },
|
|
17138
|
+
"convert-promo": { type: "string" },
|
|
17120
17139
|
title: { type: "string" },
|
|
17121
17140
|
body: { type: "string" },
|
|
17122
17141
|
profile: { type: "string" },
|
|
@@ -17362,7 +17381,7 @@ async function main() {
|
|
|
17362
17381
|
const tokens = splitTokens(pos, v);
|
|
17363
17382
|
globals.token = tokens.session;
|
|
17364
17383
|
globals.profile = v.profile;
|
|
17365
|
-
if (v.version) return out({ version: "0.
|
|
17384
|
+
if (v.version) return out({ version: "0.84.0" }, () => "0.84.0");
|
|
17366
17385
|
for (const n of normalizeArgs(pos, v)) if (!globals.json) info(dim(n));
|
|
17367
17386
|
const context = (await readConfig()).workspace;
|
|
17368
17387
|
if (!explicitToken()?.startsWith("gat_")) {
|
|
@@ -17561,7 +17580,7 @@ async function main() {
|
|
|
17561
17580
|
throw unknown(cmd, cmd, COMMANDS, "ghosty --help");
|
|
17562
17581
|
}
|
|
17563
17582
|
}
|
|
17564
|
-
var notice = updateNotice("0.
|
|
17583
|
+
var notice = updateNotice("0.84.0").catch(() => null);
|
|
17565
17584
|
main().then(
|
|
17566
17585
|
async () => {
|
|
17567
17586
|
const n = await notice;
|
package/package.json
CHANGED