@ghostystudio/cli 0.46.0 → 0.47.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 +5 -0
- package/dist/index.js +64 -16
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -103,6 +103,11 @@ Every command has its own help with examples: `ghosty <command> --help` or `ghos
|
|
|
103
103
|
|
|
104
104
|
Exit codes: `0` ok · `1` API error · `2` usage error · `3` not signed in.
|
|
105
105
|
|
|
106
|
+
### Changes in 0.47.0
|
|
107
|
+
|
|
108
|
+
- `agents set --quote` takes VAT rules for the house `cotizar` tool: `iva-incluido=true` (prices already include VAT), `iva.CATEGORY=16` (VAT for that category), `solo-factura=true` (VAT only when the customer asks for an invoice).
|
|
109
|
+
- New `agents set --catalog products.csv|json`: the house `cotizar` tool's catalog (sku, nombre, precio, unidad, categoria). The category comes from here, not from the model.
|
|
110
|
+
|
|
106
111
|
### Changes in 0.46.0
|
|
107
112
|
|
|
108
113
|
- New `staff ls|assign|unassign <staff-email> <client-email>` (Ghosty staff): a staff member assigned to a client account sees and runs its agents (with or without a workspace), documents, databases and boards as themselves — no keys, billing or transfers, every write logged. The client sees «Your Ghosty account manager».
|
package/dist/index.js
CHANGED
|
@@ -8422,7 +8422,7 @@ async function postLong(path, body, timeoutMs = 9e5) {
|
|
|
8422
8422
|
const req = httpsRequest(`${base}${path}`, {
|
|
8423
8423
|
method: "POST",
|
|
8424
8424
|
timeout: timeoutMs,
|
|
8425
|
-
headers: { authorization: `Bearer ${token}`, "user-agent": `ghosty-cli/${"0.
|
|
8425
|
+
headers: { authorization: `Bearer ${token}`, "user-agent": `ghosty-cli/${"0.47.0"}`, "content-type": "application/json", "content-length": Buffer.byteLength(data) }
|
|
8426
8426
|
}, (res) => {
|
|
8427
8427
|
let buf = "";
|
|
8428
8428
|
res.on("data", (c) => buf += c);
|
|
@@ -8464,7 +8464,7 @@ async function request(path, opts = {}, retried = false) {
|
|
|
8464
8464
|
method: opts.method ?? (opts.body !== void 0 || opts.raw !== void 0 ? "POST" : "GET"),
|
|
8465
8465
|
headers: {
|
|
8466
8466
|
authorization: `Bearer ${token}`,
|
|
8467
|
-
"user-agent": `ghosty-cli/${"0.
|
|
8467
|
+
"user-agent": `ghosty-cli/${"0.47.0"}`,
|
|
8468
8468
|
"accept-language": lang(),
|
|
8469
8469
|
...opts.body !== void 0 ? { "content-type": "application/json" } : {},
|
|
8470
8470
|
...opts.headers
|
|
@@ -8764,6 +8764,36 @@ async function agentsGet(id, fields, promptOut) {
|
|
|
8764
8764
|
const q = fields ? `?fields=${enc2(fields)}` : "?full=1";
|
|
8765
8765
|
out(await api(agentPath(id, q)));
|
|
8766
8766
|
}
|
|
8767
|
+
function parseCsv(text) {
|
|
8768
|
+
const rows = [];
|
|
8769
|
+
let row = [], cell = "", q = false;
|
|
8770
|
+
for (let i = 0; i < text.length; i++) {
|
|
8771
|
+
const c = text[i];
|
|
8772
|
+
if (q) {
|
|
8773
|
+
if (c === '"' && text[i + 1] === '"') {
|
|
8774
|
+
cell += '"';
|
|
8775
|
+
i++;
|
|
8776
|
+
} else if (c === '"') q = false;
|
|
8777
|
+
else cell += c;
|
|
8778
|
+
} else if (c === '"') q = true;
|
|
8779
|
+
else if (c === ",") {
|
|
8780
|
+
row.push(cell);
|
|
8781
|
+
cell = "";
|
|
8782
|
+
} else if (c === "\n" || c === "\r") {
|
|
8783
|
+
if (c === "\r" && text[i + 1] === "\n") i++;
|
|
8784
|
+
row.push(cell);
|
|
8785
|
+
cell = "";
|
|
8786
|
+
if (row.some((x) => x.trim())) rows.push(row);
|
|
8787
|
+
row = [];
|
|
8788
|
+
} else cell += c;
|
|
8789
|
+
}
|
|
8790
|
+
row.push(cell);
|
|
8791
|
+
if (row.some((x) => x.trim())) rows.push(row);
|
|
8792
|
+
const [head, ...body] = rows;
|
|
8793
|
+
if (!head) return [];
|
|
8794
|
+
const keys = head.map((h) => h.trim().toLowerCase());
|
|
8795
|
+
return body.map((r) => Object.fromEntries(keys.map((k, i) => [k, k === "precio" ? Number((r[i] ?? "").replace(/[$,\s]/g, "")) : (r[i] ?? "").trim()])));
|
|
8796
|
+
}
|
|
8767
8797
|
async function agentsSet(id, v) {
|
|
8768
8798
|
id = need(id, "agent id", "ghosty agents set <agent-id> --prompt-file PROMPT.md");
|
|
8769
8799
|
const done = [];
|
|
@@ -8864,19 +8894,32 @@ ${dim(t("Dry run: nothing changed.", "Simulacro: no se cambi\xF3 nada."))}`);
|
|
|
8864
8894
|
body.autoStage = v["auto-stage"] === "on";
|
|
8865
8895
|
}
|
|
8866
8896
|
if (v.quote) {
|
|
8867
|
-
const alias = { iva: "ivaPct", vigencia: "vigenciaDias", prefix: "folioPrefijo", prefijo: "folioPrefijo", currency: "moneda", company: "empresa", phone: "telefono", email: "correo", address: "direccion", notes: "notas" };
|
|
8897
|
+
const alias = { iva: "ivaPct", vigencia: "vigenciaDias", prefix: "folioPrefijo", prefijo: "folioPrefijo", currency: "moneda", company: "empresa", phone: "telefono", email: "correo", address: "direccion", notes: "notas", "iva-incluido": "ivaIncluido", "solo-factura": "ivaSoloConFactura" };
|
|
8868
8898
|
const cot = {};
|
|
8869
|
-
|
|
8870
|
-
|
|
8899
|
+
let cats = null;
|
|
8900
|
+
for (const part of v.quote.split(/,(?=\s*[a-zA-Z-]+(?:\.[^=,]+)?=)/)) {
|
|
8901
|
+
const m = /^\s*([a-zA-Z-]+)(?:\.([^=]+))?=(.*)$/.exec(part);
|
|
8871
8902
|
if (!m) throw usage(t(`Bad --quote: ${part}.`, `--quote inv\xE1lido: ${part}.`), "--quote iva=0,prefix=SFI,vigencia=15");
|
|
8872
|
-
const
|
|
8873
|
-
const val =
|
|
8874
|
-
|
|
8903
|
+
const [, rawKey, category, rawVal] = m;
|
|
8904
|
+
const val = rawVal.trim().replace(/^"(.*)"$/, "$1");
|
|
8905
|
+
if (rawKey.toLowerCase() === "iva" && category) {
|
|
8906
|
+
if (!cats) cats = { ...(await api(agentPath(id, "?fields=cotizacion"))).cotizacion?.ivaPorCategoria ?? {} };
|
|
8907
|
+
if (val === "") delete cats[category];
|
|
8908
|
+
else cats[category] = Number(val);
|
|
8909
|
+
continue;
|
|
8910
|
+
}
|
|
8911
|
+
const key = alias[rawKey] ?? rawKey;
|
|
8912
|
+
cot[key] = key === "ivaPct" || key === "vigenciaDias" ? Number(val) : key === "ivaIncluido" || key === "ivaSoloConFactura" ? /^(true|on|yes|si|sí|1)$/i.test(val) : val;
|
|
8875
8913
|
}
|
|
8914
|
+
if (cats) cot.ivaPorCategoria = cats;
|
|
8876
8915
|
body.cotizacion = cot;
|
|
8877
8916
|
}
|
|
8917
|
+
if (v.catalog) {
|
|
8918
|
+
const raw = await readFile3(resolve(v.catalog), "utf8");
|
|
8919
|
+
body.catalogo = v.catalog.toLowerCase().endsWith(".json") ? JSON.parse(raw) : parseCsv(raw);
|
|
8920
|
+
}
|
|
8878
8921
|
if (!Object.keys(body).length && done.length) return out({ id, updated: done }, () => `${lavender("\u2713")} ${t("Updated", "Actualizado")}: ${done.join(" \xB7 ")}`);
|
|
8879
|
-
if (!Object.keys(body).length) throw usage(t("Nothing to change.", "Nada que cambiar."), t("Use", "Usa") + " --name, --engine, --model, --prompt, --prompt-file, --env, --unset-env, --channels, --toolsets, --tool, --connect, --disconnect, --voice, --voice-replies, --auto-stage, --quote, --bag " + t("or", "o") + " --avatar.");
|
|
8922
|
+
if (!Object.keys(body).length) throw usage(t("Nothing to change.", "Nada que cambiar."), t("Use", "Usa") + " --name, --engine, --model, --prompt, --prompt-file, --env, --unset-env, --channels, --toolsets, --tool, --connect, --disconnect, --voice, --voice-replies, --auto-stage, --quote, --catalog, --bag " + t("or", "o") + " --avatar.");
|
|
8880
8923
|
const r = await api(agentPath(id), { method: "PATCH", body });
|
|
8881
8924
|
out(r, () => `${lavender("\u2713")} ${t("Updated", "Actualizado")}: ${[...Object.keys(body), ...done].join(", ")}.`);
|
|
8882
8925
|
}
|
|
@@ -9738,7 +9781,7 @@ async function call(path, v, init = {}) {
|
|
|
9738
9781
|
"x-ghosty-ts": ts,
|
|
9739
9782
|
"x-ghosty-sig": sig,
|
|
9740
9783
|
"content-type": "application/json",
|
|
9741
|
-
"user-agent": `ghosty-cli/${"0.
|
|
9784
|
+
"user-agent": `ghosty-cli/${"0.47.0"}`
|
|
9742
9785
|
},
|
|
9743
9786
|
body: method === "GET" ? void 0 : raw
|
|
9744
9787
|
});
|
|
@@ -11225,7 +11268,8 @@ var HELPS_ES = {
|
|
|
11225
11268
|
["--voice E:ID", "set: voz de las notas de voz: elevenlabs:<voiceId> o kokoro:em_santa|em_alex|ef_dora"],
|
|
11226
11269
|
["--voice-replies M", "set: auto = contesta con nota de voz cuando el cliente manda o pide audio; off = siempre texto"],
|
|
11227
11270
|
["--auto-stage on|off", "set: mueve solo las tarjetas del tablero tras cada turno del cliente (una llamada extra al modelo por turno)"],
|
|
11228
|
-
["--quote k=v,\u2026", "set: config de la tool de casa `cotizar` \u2014 iva (0-100), vigencia (d\xEDas), prefix (folio), moneda, empresa, rfc, telefono, correo, direccion, notas, color. Vac\xEDo lo borra (rfc=). El contador de folio no se toca"],
|
|
11271
|
+
["--quote k=v,\u2026", "set: config de la tool de casa `cotizar` \u2014 iva (0-100), iva-incluido=true (los precios del cat\xE1logo ya traen IVA), iva.CATEGORIA=16 (IVA de esa categor\xEDa del cat\xE1logo; iva.CATEGORIA= la quita), solo-factura=true (IVA s\xF3lo si el cliente pide factura), vigencia (d\xEDas), prefix (folio), moneda, empresa, rfc, telefono, correo, direccion, notas, color. Vac\xEDo lo borra (rfc=). El contador de folio no se toca"],
|
|
11272
|
+
["--catalog ARCHIVO", "set: el cat\xE1logo de la tool de casa `cotizar` desde un CSV (sku,nombre,precio[,unidad,categoria,descripcion]) o una lista JSON; reemplaza al anterior. Su `categoria` decide las reglas de IVA"],
|
|
11229
11273
|
["--verbose", "doctor: lista tambi\xE9n las revisiones que pasaron"],
|
|
11230
11274
|
["--user EMAIL", "doctor (staff de Ghosty): los agentes de esa persona \u2014 doctor, \xFAltimos turnos (estado, segundos, error y \xABfetched\xBB: si su app pidi\xF3 el hilo despu\xE9s de que termin\xF3 el turno), plan/bolsa y cajas (marca duplicadas); queda en bit\xE1cora"],
|
|
11231
11275
|
["--turns N", "doctor --user: cu\xE1ntos turnos recientes por agente (default 8, m\xE1x. 50)"],
|
|
@@ -11664,7 +11708,8 @@ var HELPS = {
|
|
|
11664
11708
|
["--voice E:ID", "set: voice for voice notes: elevenlabs:<voiceId> or kokoro:em_santa|em_alex|ef_dora"],
|
|
11665
11709
|
["--voice-replies M", "set: auto = answer with a voice note when the customer sends or asks for audio; off = always text"],
|
|
11666
11710
|
["--auto-stage on|off", "set: move board cards by itself after each customer turn (one extra model call per turn)"],
|
|
11667
|
-
["--quote k=v,\u2026", "set: config of the house `cotizar` tool \u2014 iva (0-100), vigencia (days), prefix (folio), moneda, empresa, rfc, telefono, correo, direccion, notas, color. Empty value clears it (rfc=). The folio counter is never touched"],
|
|
11711
|
+
["--quote k=v,\u2026", "set: config of the house `cotizar` tool \u2014 iva (0-100), iva-incluido=true (catalog prices already include VAT), iva.CATEGORY=16 (VAT for that catalog category; iva.CATEGORY= removes it), solo-factura=true (VAT only when the customer asks for an invoice), vigencia (days), prefix (folio), moneda, empresa, rfc, telefono, correo, direccion, notas, color. Empty value clears it (rfc=). The folio counter is never touched"],
|
|
11712
|
+
["--catalog FILE", "set: the house `cotizar` tool's catalog from a CSV (sku,nombre,precio[,unidad,categoria,descripcion]) or JSON list; replaces the previous one. Its `categoria` drives the VAT rules"],
|
|
11668
11713
|
["--verbose", "doctor: also list the checks that passed"],
|
|
11669
11714
|
["--user EMAIL", "doctor (Ghosty staff): that person's agents \u2014 doctor, latest turns (state, seconds, error, and \xABfetched\xBB: whether their app asked for the thread after the turn ended), plan/bag and boxes (duplicates flagged); logged"],
|
|
11670
11715
|
["--turns N", "doctor --user: how many recent turns per agent (default 8, max 50)"],
|
|
@@ -13370,7 +13415,8 @@ ${bold("Agents")}
|
|
|
13370
13415
|
[--connect google-drive,\u2026] [--disconnect \u2026] give/remove access to your connectors
|
|
13371
13416
|
[--channels wa=on,teams=off] turn channels on/off (wa = personal WhatsApp)
|
|
13372
13417
|
[--voice elevenlabs:ID | kokoro:em_santa] [--voice-replies auto|off] [--auto-stage on|off]
|
|
13373
|
-
[--quote iva=
|
|
13418
|
+
[--quote iva=16,iva-incluido=true,iva.GRANEL=16,solo-factura=true,prefix=SFI] house cotizar tool config (issuer, VAT rules, folio)
|
|
13419
|
+
[--catalog productos.csv|json] its catalog: sku,nombre,precio[,unidad,categoria]
|
|
13374
13420
|
[--toolsets crm,sales | +crm,-sales] gs tool groups it gets
|
|
13375
13421
|
[--prompt-base AGENT|none --prompt-overlay FILE [--dry-run]] prompt = another agent's + edits, kept in sync
|
|
13376
13422
|
[--tool wa:tool=off,\u2026] [--bag NAME|none] [--avatar URL|FILE] a tool per channel \xB7 its token bag (staff) \xB7 its face in Teams
|
|
@@ -13515,7 +13561,8 @@ ${bold("Agentes")}
|
|
|
13515
13561
|
[--connect google-drive,\u2026] [--disconnect \u2026] dale o qu\xEDtale acceso a tus conectores
|
|
13516
13562
|
[--channels wa=on,teams=off] prende/apaga canales (wa = WhatsApp personal)
|
|
13517
13563
|
[--voice elevenlabs:ID | kokoro:em_santa] [--voice-replies auto|off] [--auto-stage on|off]
|
|
13518
|
-
[--quote iva=
|
|
13564
|
+
[--quote iva=16,iva-incluido=true,iva.GRANEL=16,solo-factura=true,prefix=SFI] config de la tool de casa cotizar (emisor, reglas de IVA, folio)
|
|
13565
|
+
[--catalog productos.csv|json] su cat\xE1logo: sku,nombre,precio[,unidad,categoria]
|
|
13519
13566
|
[--toolsets crm,sales | +crm,-sales] grupos de tools de gs que recibe
|
|
13520
13567
|
[--prompt-base AGENTE|none --prompt-overlay ARCHIVO [--dry-run]] prompt = el de otro agente + ediciones, sincronizado
|
|
13521
13568
|
[--tool wa:tool=off,\u2026] [--bag NOMBRE|none] [--avatar URL|ARCHIVO] una tool por canal \xB7 su bolsa de tokens (staff) \xB7 su cara en Teams
|
|
@@ -13762,6 +13809,7 @@ async function main() {
|
|
|
13762
13809
|
days: { type: "string" },
|
|
13763
13810
|
voice: { type: "string" },
|
|
13764
13811
|
quote: { type: "string" },
|
|
13812
|
+
catalog: { type: "string" },
|
|
13765
13813
|
"voice-replies": { type: "string" },
|
|
13766
13814
|
"auto-stage": { type: "string" },
|
|
13767
13815
|
"from-env": { type: "string" },
|
|
@@ -13850,7 +13898,7 @@ async function main() {
|
|
|
13850
13898
|
const tokens = splitTokens(pos, v);
|
|
13851
13899
|
globals.token = tokens.session;
|
|
13852
13900
|
globals.profile = v.profile;
|
|
13853
|
-
if (v.version) return out({ version: "0.
|
|
13901
|
+
if (v.version) return out({ version: "0.47.0" }, () => "0.47.0");
|
|
13854
13902
|
for (const n of normalizeArgs(pos, v)) if (!globals.json) info(dim(n));
|
|
13855
13903
|
const context = (await readConfig()).workspace;
|
|
13856
13904
|
if (!explicitToken()?.startsWith("gat_")) {
|
|
@@ -14010,7 +14058,7 @@ async function main() {
|
|
|
14010
14058
|
throw unknown(cmd, cmd, COMMANDS, "ghosty --help");
|
|
14011
14059
|
}
|
|
14012
14060
|
}
|
|
14013
|
-
var notice = updateNotice("0.
|
|
14061
|
+
var notice = updateNotice("0.47.0").catch(() => null);
|
|
14014
14062
|
main().then(
|
|
14015
14063
|
async () => {
|
|
14016
14064
|
const n = await notice;
|
package/package.json
CHANGED