@ghostystudio/cli 0.50.0 → 0.52.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 +14 -0
- package/dist/index.js +190 -8
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -38,6 +38,10 @@ ghosty agents box <id> [--check PATH]… [--contains PATH=TEXT]… [--recycle]
|
|
|
38
38
|
ghosty agents demo enable|disable <id>
|
|
39
39
|
ghosty agents demo <id> [--slug NAME] [--expires "YYYY-MM-DDTHH:MM"|no] [--turns N] [--per-ip N]
|
|
40
40
|
[--welcome TEXT] [--starter TEXT] [--chips "a|b|c"] [--sponsor on|off] [--rotate] # public /p/ link, no account needed
|
|
41
|
+
ghosty agents embed enable|disable <id> [--domains a.com,*.b.com] # web widget: chat bubble on your site, only on those domains
|
|
42
|
+
ghosty agents embed <id> [--per-visitor N] [--per-ip N] [--welcome TEXT] [--color #hex] [--rotate] # state + the <script> to paste
|
|
43
|
+
ghosty agents embed <id> [--title T] [--avatar URL] [--icon chat|avatar|ghost] [--position left] [--theme auto] [--bubble-text T] [--auto-open S] [--starters "a|b"] # its look
|
|
44
|
+
ghosty agents embed <id> [--style '{json}'] [--theme-source teams|site --site-url URL] [--style-file theme.json] # its theme · `theme` exports it
|
|
41
45
|
ghosty agents doctor <id> [--verbose] # exits 1 when it finds a problem
|
|
42
46
|
ghosty agents docs ls|grant|revoke <id> [doc] [--write] [--no-deliver]
|
|
43
47
|
ghosty agents docs add <id> --url URL | --file PATH [--description TEXT] [--grant read|write|no]
|
|
@@ -103,6 +107,16 @@ Every command has its own help with examples: `ghosty <command> --help` or `ghos
|
|
|
103
107
|
|
|
104
108
|
Exit codes: `0` ok · `1` API error · `2` usage error · `3` not signed in.
|
|
105
109
|
|
|
110
|
+
### Changes in 0.52.0
|
|
111
|
+
|
|
112
|
+
- `agents embed <id>` customizes the web widget: `--title`, `--subtitle`, `--avatar URL|none`, `--icon chat|avatar|ghost`, `--placeholder`, `--position right|left`, `--offset X[,Y]`, `--theme light|dark|auto`, `--bubble-text`, `--auto-open S|off`, `--starters "a|b"` (up to 4 of yours; Ghosty's never show). The pasted `<script>` doesn't change.
|
|
113
|
+
- Fine style without free CSS: `--style '{json}'|none` (fontFamily from a Google Fonts allow-list, radius 0–24, header/bubble/input/send/launcher colors, titleUppercase, statusDot, sendArrow), shortcuts `--font` and `--radius`.
|
|
114
|
+
- Theme source: `--theme-source teams` (your Ghosty Teams workspace brand, `--workspace SLUG`) or `--theme-source site --site-url URL` (your site's CSS colors), imported as editable values. `agents embed <id> theme` exports it as JSON; `--style-file theme.json` applies it back.
|
|
115
|
+
|
|
116
|
+
### Changes in 0.51.0
|
|
117
|
+
|
|
118
|
+
- `agents embed enable|disable <id> [--domains a.com,*.b.com] [--per-visitor N] [--per-ip N] [--welcome T] [--color #hex] [--rotate]`: the **web widget**, a chat bubble with the agent on your own site (one `<script>`), loading only on the domains you list; each visitor gets an isolated conversation and talks as a customer. Claude engine only. No flags = state + the snippet.
|
|
119
|
+
|
|
106
120
|
### Changes in 0.50.0
|
|
107
121
|
|
|
108
122
|
- `cards pause|resume <id> <card> [--mode 30min|2h|24h|until_tomorrow|permanent]`: the thread's pause menu; resume also lifts "operator only" and doesn't answer by itself. Logged.
|
package/dist/index.js
CHANGED
|
@@ -8164,7 +8164,12 @@ var SERVER_MESSAGES = [
|
|
|
8164
8164
|
["s\xF3lo el due\xF1o de \xAB{}\xBB o el staff de Ghosty leen su bit\xE1cora", "only \xAB{}\xBB's owner or Ghosty staff read its audit log"],
|
|
8165
8165
|
["s\xF3lo aplica a conversaciones de WhatsApp Business", "only applies to WhatsApp Business conversations"],
|
|
8166
8166
|
["ese n\xFAmero ya no est\xE1 conectado", "that number is no longer connected"],
|
|
8167
|
-
["ese n\xFAmero no es de este tablero", "that number isn't on this board"]
|
|
8167
|
+
["ese n\xFAmero no es de este tablero", "that number isn't on this board"],
|
|
8168
|
+
// — Widget web (`agents embed`)
|
|
8169
|
+
["s\xF3lo el due\xF1o del agente maneja su widget web", "only the agent's owner manages its web widget"],
|
|
8170
|
+
["dominio no v\xE1lido: {} (usa ejemplo.com o *.ejemplo.com, sin https:// ni rutas)", "invalid domain: {} (use example.com or *.example.com, no https:// or paths)"],
|
|
8171
|
+
["el widget web s\xF3lo corre con motor claude (es el que a\xEDsla a cada visitante)", "the web widget only runs on the claude engine (it's the one that isolates each visitor)"],
|
|
8172
|
+
["pon al menos un dominio donde va a vivir el widget (--domains ejemplo.com)", "add at least one domain where the widget will live (--domains example.com)"]
|
|
8168
8173
|
];
|
|
8169
8174
|
|
|
8170
8175
|
// src/i18n.ts
|
|
@@ -8463,7 +8468,7 @@ async function postLong(path, body, timeoutMs = 9e5) {
|
|
|
8463
8468
|
const req = httpsRequest(`${base}${path}`, {
|
|
8464
8469
|
method: "POST",
|
|
8465
8470
|
timeout: timeoutMs,
|
|
8466
|
-
headers: { authorization: `Bearer ${token}`, "user-agent": `ghosty-cli/${"0.
|
|
8471
|
+
headers: { authorization: `Bearer ${token}`, "user-agent": `ghosty-cli/${"0.52.0"}`, "content-type": "application/json", "content-length": Buffer.byteLength(data) }
|
|
8467
8472
|
}, (res) => {
|
|
8468
8473
|
let buf = "";
|
|
8469
8474
|
res.on("data", (c) => buf += c);
|
|
@@ -8505,7 +8510,7 @@ async function request(path, opts = {}, retried = false) {
|
|
|
8505
8510
|
method: opts.method ?? (opts.body !== void 0 || opts.raw !== void 0 ? "POST" : "GET"),
|
|
8506
8511
|
headers: {
|
|
8507
8512
|
authorization: `Bearer ${token}`,
|
|
8508
|
-
"user-agent": `ghosty-cli/${"0.
|
|
8513
|
+
"user-agent": `ghosty-cli/${"0.52.0"}`,
|
|
8509
8514
|
"accept-language": lang(),
|
|
8510
8515
|
...opts.body !== void 0 ? { "content-type": "application/json" } : {},
|
|
8511
8516
|
...opts.headers
|
|
@@ -9339,6 +9344,101 @@ async function agentsDemo(id, v) {
|
|
|
9339
9344
|
].join("\n")
|
|
9340
9345
|
);
|
|
9341
9346
|
}
|
|
9347
|
+
function styleSummary(st) {
|
|
9348
|
+
if (!st) return "";
|
|
9349
|
+
return Object.entries(st).filter(([k, x]) => x !== null && !(k === "headerAvatar" && x === true) && !(k === "titleUppercase" && x === false) && !(k === "sendArrow" && x === "up")).map(([k, x]) => `${k}=${x}`).join(" ");
|
|
9350
|
+
}
|
|
9351
|
+
async function agentsEmbed(id, v, action) {
|
|
9352
|
+
id = need(id, "agent id", "ghosty agents embed enable <agent-id> --domains tusitio.com");
|
|
9353
|
+
if (action === "theme") {
|
|
9354
|
+
const e2 = await api(agentPath(id, "/embed"));
|
|
9355
|
+
const theme = { themeSource: e2.themeSource ?? "custom", themeFrom: e2.themeFrom ?? null, siteUrl: e2.siteUrl ?? null, color: e2.color, theme: e2.theme ?? "light", style: e2.style ?? {} };
|
|
9356
|
+
return out(theme, () => JSON.stringify(theme, null, 2));
|
|
9357
|
+
}
|
|
9358
|
+
if (action) throw usage(t(`Unknown: agents embed <id> ${action}`, `No existe: agents embed <id> ${action}`), "ghosty agents embed <id> theme");
|
|
9359
|
+
if (v.on && v.off) throw usage(t("Use enable or disable, not both.", "Usa enable o disable, no los dos."));
|
|
9360
|
+
const body = {};
|
|
9361
|
+
if (v.on) body.enabled = true;
|
|
9362
|
+
if (v.off) body.enabled = false;
|
|
9363
|
+
if (v.domains !== void 0) body.domains = v.domains.split(/[\s,]+/).map((d) => d.trim()).filter(Boolean);
|
|
9364
|
+
if (v["per-visitor"]) body.perVisitorDay = Number(v["per-visitor"]);
|
|
9365
|
+
if (v["per-ip"]) body.perIpDay = Number(v["per-ip"]);
|
|
9366
|
+
if (v.welcome !== void 0) body.welcome = v.welcome || null;
|
|
9367
|
+
if (v.color !== void 0) body.color = v.color;
|
|
9368
|
+
const clear = (x) => x === "" || x.toLowerCase() === "none" ? null : x;
|
|
9369
|
+
if (v.avatar !== void 0) body.avatarUrl = clear(v.avatar);
|
|
9370
|
+
if (v.title !== void 0) body.title = clear(v.title);
|
|
9371
|
+
if (v.subtitle !== void 0) body.subtitle = clear(v.subtitle);
|
|
9372
|
+
if (v.placeholder !== void 0) body.placeholder = clear(v.placeholder);
|
|
9373
|
+
if (v["bubble-text"] !== void 0) body.bubbleText = clear(v["bubble-text"]);
|
|
9374
|
+
if (v.icon !== void 0) body.icon = v.icon;
|
|
9375
|
+
if (v.position !== void 0) body.position = v.position;
|
|
9376
|
+
if (v.theme !== void 0) body.theme = v.theme;
|
|
9377
|
+
if (v.offset !== void 0) {
|
|
9378
|
+
const [x, y] = v.offset.split(/[,x ]+/).map((n) => Number(n));
|
|
9379
|
+
if (!Number.isFinite(x)) throw usage(t("--offset takes px: 20 or 20,40 (side,bottom)", "--offset va en px: 20 o 20,40 (lado,abajo)"));
|
|
9380
|
+
body.offsetX = x;
|
|
9381
|
+
body.offsetY = Number.isFinite(y) ? y : x;
|
|
9382
|
+
}
|
|
9383
|
+
if (v["auto-open"] !== void 0) body.autoOpen = /^(off|no|0|)$/i.test(v["auto-open"]) ? 0 : Number(v["auto-open"]);
|
|
9384
|
+
if (v.starters !== void 0) body.starters = v.starters.split("|").map((x) => x.trim()).filter(Boolean);
|
|
9385
|
+
if (v.style !== void 0) {
|
|
9386
|
+
if (v.style.toLowerCase() === "none") body.style = null;
|
|
9387
|
+
else {
|
|
9388
|
+
try {
|
|
9389
|
+
body.style = JSON.parse(v.style);
|
|
9390
|
+
} catch {
|
|
9391
|
+
throw usage(t(`--style takes JSON: '{"headerBg":"#2d4a2e","radius":0}'`, `--style va en JSON: '{"headerBg":"#2d4a2e","radius":0}'`));
|
|
9392
|
+
}
|
|
9393
|
+
}
|
|
9394
|
+
}
|
|
9395
|
+
if (v["style-file"]) {
|
|
9396
|
+
let j;
|
|
9397
|
+
try {
|
|
9398
|
+
j = JSON.parse(await readFile3(v["style-file"], "utf8"));
|
|
9399
|
+
} catch (err) {
|
|
9400
|
+
throw usage(t(`Could not read ${v["style-file"]} as JSON: ${err.message}`, `No pude leer ${v["style-file"]} como JSON: ${err.message}`));
|
|
9401
|
+
}
|
|
9402
|
+
const isTheme = j && typeof j === "object" && "style" in j;
|
|
9403
|
+
body.style = isTheme ? j.style : j;
|
|
9404
|
+
if (isTheme && typeof j.color === "string" && body.color === void 0) body.color = j.color;
|
|
9405
|
+
if (isTheme && typeof j.theme === "string" && body.theme === void 0) body.theme = j.theme;
|
|
9406
|
+
}
|
|
9407
|
+
if (v["theme-source"] !== void 0) body.themeSource = v["theme-source"];
|
|
9408
|
+
if (v["site-url"] !== void 0) {
|
|
9409
|
+
body.siteUrl = v["site-url"];
|
|
9410
|
+
if (body.themeSource === void 0) body.themeSource = "site";
|
|
9411
|
+
}
|
|
9412
|
+
if (body.themeSource === "teams" && v.workspace) body.teamsWorkspace = v.workspace;
|
|
9413
|
+
if (v.font !== void 0 || v.radius !== void 0) {
|
|
9414
|
+
const st = body.style && typeof body.style === "object" ? body.style : {};
|
|
9415
|
+
if (v.font !== void 0) st.fontFamily = clear(v.font);
|
|
9416
|
+
if (v.radius !== void 0) st.radius = v.radius === "" || v.radius === "none" ? null : Number(v.radius);
|
|
9417
|
+
body.style = st;
|
|
9418
|
+
}
|
|
9419
|
+
if (v.rotate) body.rotate = true;
|
|
9420
|
+
const e = Object.keys(body).length ? await api(agentPath(id, "/embed"), { method: "PUT", body }) : await api(agentPath(id, "/embed"));
|
|
9421
|
+
out(
|
|
9422
|
+
e,
|
|
9423
|
+
() => [
|
|
9424
|
+
`${e.enabled ? lavender(t("\u25CF on", "\u25CF encendido")) : dim(t("\u25CB off", "\u25CB apagado"))} ${t("web widget", "widget web")}`,
|
|
9425
|
+
e.domains.length ? `${t("domains", "dominios")}: ${e.domains.join(", ")}` : red(t("domains: (none \u2014 it loads nowhere; add --domains yoursite.com)", "dominios: (ninguno \u2014 no carga en ning\xFAn lado; agrega --domains tusitio.com)")),
|
|
9426
|
+
...e.engineOk ? [] : [red(t("engine: only claude isolates each visitor; switch with `ghosty agents set <id> --engine claude`", "motor: s\xF3lo claude a\xEDsla a cada visitante; c\xE1mbialo con `ghosty agents set <id> --engine claude`"))],
|
|
9427
|
+
dim(t(`cap ${e.perVisitorDay} messages per visitor per day \xB7 ${e.perIpDay} per IP per day \xB7 color ${e.color}`, `tope ${e.perVisitorDay} mensajes por visitante al d\xEDa \xB7 ${e.perIpDay} por IP al d\xEDa \xB7 color ${e.color}`)),
|
|
9428
|
+
`${t("first message", "primer mensaje")}: ${e.welcome ?? dim(e.welcomeShown ?? t("(default greeting)", "(saludo por defecto)"))}`,
|
|
9429
|
+
`${t("header", "encabezado")}: ${e.title ?? e.agentName ?? ""}${e.subtitle ? ` \xB7 ${e.subtitle}` : ""} ${dim(`${t("avatar", "avatar")} ${e.avatarUrl ?? t("ghost", "fantasma")} \xB7 ${t("icon", "\xEDcono")} ${e.icon ?? "chat"}`)}`,
|
|
9430
|
+
dim(
|
|
9431
|
+
`${t("position", "lado")} ${e.position ?? "right"} (${e.offsetX ?? 20},${e.offsetY ?? 20}px) \xB7 ${t("theme", "tema")} ${e.theme ?? "light"} \xB7 ${t("text on color", "texto sobre el color")} ${e.textColor ?? ""} \xB7 ${t("auto-open", "abrir solo")} ${e.autoOpen ? `${e.autoOpen}s` : "off"}${e.bubbleText ? ` \xB7 ${t("label", "etiqueta")} \xAB${e.bubbleText}\xBB` : ""}${e.placeholder ? ` \xB7 placeholder \xAB${e.placeholder}\xBB` : ""}`
|
|
9432
|
+
),
|
|
9433
|
+
e.starters?.length ? `${t("suggestions", "sugerencias")}: ${e.starters.join(" | ")}` : dim(t("suggestions: (none)", "sugerencias: (ninguna)")),
|
|
9434
|
+
`${t("theme", "tema")}: ${e.themeSource ?? "custom"}${e.themeFrom ? dim(` \xB7 ${e.themeFrom}`) : ""}`,
|
|
9435
|
+
...styleSummary(e.style) ? [dim(`${t("style", "estilo")}: ${styleSummary(e.style)}`)] : [],
|
|
9436
|
+
...e.snippet ? ["", t("Paste before </body> on your site:", "Pega antes de </body> en tu sitio:"), e.snippet, ""] : [],
|
|
9437
|
+
t(`visitors ${e.stats.visitantes} \xB7 messages ${e.stats.mensajes}`, `visitantes ${e.stats.visitantes} \xB7 mensajes ${e.stats.mensajes}`),
|
|
9438
|
+
...e.lastError ? [red(`${t("last failure", "\xFAltima falla")} ${e.lastError.at}: ${serverText(e.lastError.message ?? e.lastError.error ?? "")}`)] : []
|
|
9439
|
+
].join("\n")
|
|
9440
|
+
);
|
|
9441
|
+
}
|
|
9342
9442
|
async function agentsBox(id, v) {
|
|
9343
9443
|
id = need(id, "agent id", "ghosty agents box <agent-id> [--check PATH] [--contains PATH=TEXT] [--recycle]");
|
|
9344
9444
|
if (v.recycle) {
|
|
@@ -9950,7 +10050,7 @@ async function call(path, v, init = {}) {
|
|
|
9950
10050
|
"x-ghosty-ts": ts,
|
|
9951
10051
|
"x-ghosty-sig": sig,
|
|
9952
10052
|
"content-type": "application/json",
|
|
9953
|
-
"user-agent": `ghosty-cli/${"0.
|
|
10053
|
+
"user-agent": `ghosty-cli/${"0.52.0"}`
|
|
9954
10054
|
},
|
|
9955
10055
|
body: method === "GET" ? void 0 : raw
|
|
9956
10056
|
});
|
|
@@ -11555,6 +11655,10 @@ var HELPS_ES = {
|
|
|
11555
11655
|
summary: "Crea, revisa, cambia, diagnostica y borra agentes.",
|
|
11556
11656
|
replace: [
|
|
11557
11657
|
["# the agent as a file; see ghosty apply --help", "# el agente como archivo; ver ghosty apply --help"],
|
|
11658
|
+
["# its look", "# su apariencia"],
|
|
11659
|
+
["# its theme", "# su tema"],
|
|
11660
|
+
["# export the theme as JSON (edit it, apply it back with --style-file)", "# exporta el tema en JSON (ed\xEDtalo y vuelve a aplicarlo con --style-file)"],
|
|
11661
|
+
["--style-file theme.json", "--style-file tema.json"],
|
|
11558
11662
|
["# who is @build in Teams (that workspace, or all of yours)", "# qui\xE9n es @build en Teams (en ese espacio, o en todos los tuyos)"],
|
|
11559
11663
|
["# change one piece of the prompt, on the server's current one", "# cambia un pedazo del prompt, sobre el actual del servidor"],
|
|
11560
11664
|
["# your account: merge copies with the same content", "# tu cuenta: une las copias con el mismo contenido"],
|
|
@@ -11563,7 +11667,9 @@ var HELPS_ES = {
|
|
|
11563
11667
|
["# Teams workspaces you administer: where it answers, is paused, and with which @handle", "# los equipos de Teams que administras: d\xF3nde contesta, d\xF3nde est\xE1 en pausa y con qu\xE9 @handle"],
|
|
11564
11668
|
["# turn it on there (or change its @handle)", "# lo prende ah\xED (o le cambia el @handle)"],
|
|
11565
11669
|
["# pause it there; it keeps its @handle", "# lo pausa ah\xED; conserva su @handle"],
|
|
11566
|
-
["# remove it from there; the agent stays", "# lo quita de ah\xED; el agente sigue"]
|
|
11670
|
+
["# remove it from there; the agent stays", "# lo quita de ah\xED; el agente sigue"],
|
|
11671
|
+
["# web widget: chat bubble on your site, only on those domains", "# widget web: burbuja de chat en tu sitio, s\xF3lo en esos dominios"],
|
|
11672
|
+
["# state + the <script> to paste", "# su estado + el <script> para pegar"]
|
|
11567
11673
|
],
|
|
11568
11674
|
flags: [
|
|
11569
11675
|
["--fields a,b", "get: regresa s\xF3lo estos campos"],
|
|
@@ -11606,6 +11712,22 @@ var HELPS_ES = {
|
|
|
11606
11712
|
['--chips "a|b|c"', "demo: sugerencias, separadas por |"],
|
|
11607
11713
|
["--sponsor on|off", "demo: las copias que la gente se queda corren con TU llave del motor"],
|
|
11608
11714
|
["--rotate", "demo: c\xF3digo nuevo; la liga vieja deja de servir"],
|
|
11715
|
+
["--domains a.com,*.b.com", "embed: d\xF3nde puede cargarse el widget (vac\xEDo = en ning\xFAn lado)"],
|
|
11716
|
+
["--welcome TEXT", "embed: el primer mensaje que ve el visitante (vac\xEDo = \xAB\xA1Hola! \xBFEn qu\xE9 te ayudo?\xBB)"],
|
|
11717
|
+
["--title T / --subtitle T", "embed: nombre en el encabezado del widget (default: el del agente) y un rengl\xF3n chico debajo (\xABResponde en minutos\xBB)"],
|
|
11718
|
+
["--avatar URL|none", "embed: tu imagen (https JPEG/PNG/WebP, se rehospeda en img.ghosty.studio); none = el fantasma del agente"],
|
|
11719
|
+
["--icon chat|avatar|ghost", "embed: qu\xE9 lleva el bot\xF3n flotante"],
|
|
11720
|
+
["--placeholder T", "embed: el texto gris de la caja para escribir"],
|
|
11721
|
+
["--position right|left / --offset X[,Y]", "embed: esquina de la p\xE1gina y separaci\xF3n en px del lado y de abajo (0-200, default 20)"],
|
|
11722
|
+
["--theme light|dark|auto", "embed: tema del panel del chat (auto = el del visitante)"],
|
|
11723
|
+
["--bubble-text T", "embed: etiqueta junto al bot\xF3n (\xAB\xBFDudas?\xBB)"],
|
|
11724
|
+
["--auto-open S|off", "embed: se abre solo a los S segundos (1-120), una vez por visita, nunca en el tel\xE9fono"],
|
|
11725
|
+
['--starters "a|b|c"', 'embed: hasta 4 sugerencias TUYAS ("" las quita; nunca salen las de Ghosty)'],
|
|
11726
|
+
["--style '{json}'|none", "embed: estilo fino, s\xF3lo llaves conocidas: fontFamily, radius, headerBg, headerText, titleUppercase, statusDot, headerAvatar, panelBg, userBubbleBg/Text, agentBubbleBg/Text, inputBg, sendBg, sendIcon, sendArrow (up|right), launcherBg, launcherIcon. PATCH por llave (null resetea una); none resetea todo"],
|
|
11727
|
+
["--font NOMBRE / --radius 0-24", "embed: atajos de style.fontFamily (lista de Google Fonts: Barlow, Inter, Poppins\u2026) y style.radius"],
|
|
11728
|
+
["--theme-source custom|teams|site", "embed: importa el tema de la marca de tu espacio de Ghosty Teams (--workspace SLUG para elegir) o de tu sitio (--site-url); queda editable"],
|
|
11729
|
+
["--site-url URL", "embed: el sitio del que se sacan los colores (implica --theme-source site)"],
|
|
11730
|
+
["--style-file ARCHIVO", "embed: aplica un tema exportado con `agents embed <id> theme` (o s\xF3lo el objeto style)"],
|
|
11609
11731
|
["--check PATH", "box: este archivo debe existir en la m\xE1quina (repetible), p. ej. un archivo que trae la imagen nueva"],
|
|
11610
11732
|
["--contains PATH=TEXT", "box: ese archivo debe contener TEXT (un cambio que no agrega archivos)"],
|
|
11611
11733
|
["--recycle", "box: reemplaza sus m\xE1quinas (nunca a media respuesta); pool: la nueva nace en el siguiente turno; ACP (goose, lite): su caja se recrea ya con la imagen actual"],
|
|
@@ -12065,6 +12187,11 @@ var HELPS = {
|
|
|
12065
12187
|
"ghosty agents box <agent-id> [--check PATH]\u2026 [--contains PATH=TEXT]\u2026 [--recycle]",
|
|
12066
12188
|
"ghosty agents demo enable|disable <agent-id>",
|
|
12067
12189
|
'ghosty agents demo <agent-id> [--slug NAME] [--expires "YYYY-MM-DDTHH:MM"|no] [--turns N] [--per-ip N] [--welcome TEXT] [--starter TEXT] [--chips "a|b|c"] [--sponsor on|off] [--rotate]',
|
|
12190
|
+
"ghosty agents embed enable|disable <agent-id> [--domains a.com,*.b.com] # web widget: chat bubble on your site, only on those domains",
|
|
12191
|
+
"ghosty agents embed <agent-id> [--domains \u2026] [--per-visitor N] [--per-ip N] [--welcome TEXT] [--color #hex] [--rotate] # state + the <script> to paste",
|
|
12192
|
+
'ghosty agents embed <agent-id> [--title T] [--subtitle T] [--avatar URL] [--icon chat|avatar|ghost] [--placeholder T] [--position right|left] [--offset X,Y] [--theme light|dark|auto] [--bubble-text T] [--auto-open S] [--starters "a|b"] # its look',
|
|
12193
|
+
"ghosty agents embed <agent-id> [--theme-source custom|teams|site] [--site-url URL] [--style '{json}'] [--style-file theme.json] [--font NAME] [--radius 0-24] # its theme",
|
|
12194
|
+
"ghosty agents embed <agent-id> theme # export the theme as JSON (edit it, apply it back with --style-file)",
|
|
12068
12195
|
"ghosty agents rm <agent-id> [--from-workspace] [--yes]"
|
|
12069
12196
|
],
|
|
12070
12197
|
flags: [
|
|
@@ -12108,6 +12235,22 @@ var HELPS = {
|
|
|
12108
12235
|
['--chips "a|b|c"', "demo: suggestions, separated by |"],
|
|
12109
12236
|
["--sponsor on|off", "demo: copies people keep run on YOUR engine key"],
|
|
12110
12237
|
["--rotate", "demo: new code; the old link stops working"],
|
|
12238
|
+
["--domains a.com,*.b.com", "embed: where the widget may load (empty = nowhere)"],
|
|
12239
|
+
["--welcome TEXT", "embed: the first message the visitor sees (empty = \xAB\xA1Hola! \xBFEn qu\xE9 te ayudo?\xBB)"],
|
|
12240
|
+
["--title T / --subtitle T", `embed: name in the widget header (default: the agent's name) and a small line under it ("Replies in minutes")`],
|
|
12241
|
+
["--avatar URL|none", "embed: your own image (https JPEG/PNG/WebP, re-hosted on img.ghosty.studio); none = the agent's ghost"],
|
|
12242
|
+
["--icon chat|avatar|ghost", "embed: what the floating button shows"],
|
|
12243
|
+
["--placeholder T", "embed: grey text in the message box"],
|
|
12244
|
+
["--position right|left / --offset X[,Y]", "embed: corner of the page and distance in px from the side and the bottom (0-200, default 20)"],
|
|
12245
|
+
["--theme light|dark|auto", "embed: the chat panel's theme (auto = the visitor's)"],
|
|
12246
|
+
["--bubble-text T", 'embed: label next to the button ("Questions?")'],
|
|
12247
|
+
["--auto-open S|off", "embed: open by itself after S seconds (1-120), once per visit, never on phones"],
|
|
12248
|
+
['--starters "a|b|c"', `embed: up to 4 of YOUR suggestions ("" removes them; Ghosty's are never shown)`],
|
|
12249
|
+
["--style '{json}'|none", "embed: fine style, only known keys: fontFamily, radius, headerBg, headerText, titleUppercase, statusDot, headerAvatar, panelBg, userBubbleBg/Text, agentBubbleBg/Text, inputBg, sendBg, sendIcon, sendArrow (up|right), launcherBg, launcherIcon. Patch per key (null resets one); none resets all"],
|
|
12250
|
+
["--font NAME / --radius 0-24", "embed: shortcuts for style.fontFamily (Google Fonts allow-list: Barlow, Inter, Poppins\u2026) and style.radius"],
|
|
12251
|
+
["--theme-source custom|teams|site", "embed: import the theme from the brand of your Ghosty Teams workspace (--workspace SLUG to pick one) or from your site (--site-url); it stays editable"],
|
|
12252
|
+
["--site-url URL", "embed: the site to take colors from (implies --theme-source site)"],
|
|
12253
|
+
["--style-file FILE", "embed: apply a theme exported with `agents embed <id> theme` (or a plain style object)"],
|
|
12111
12254
|
["--check PATH", "box: this file must exist in the machine (repeatable), e.g. a file the new image brings"],
|
|
12112
12255
|
["--contains PATH=TEXT", "box: that file must contain TEXT (a change that adds no files)"],
|
|
12113
12256
|
["--recycle", "box: replace its machines (not mid-turn); pool: the new one starts on the next turn; ACP (goose, lite): its box is recreated now with the current image"],
|
|
@@ -12143,6 +12286,10 @@ var HELPS = {
|
|
|
12143
12286
|
"ghosty agents set <pia-id> --prompt-base <tania-id> --prompt-overlay capa.json --dry-run --out /tmp/pia.md",
|
|
12144
12287
|
"ghosty agents demo enable <id>",
|
|
12145
12288
|
'ghosty agents demo <id> --slug guardias --expires "2026-10-15T20:00" --starter "Ens\xE9\xF1ame c\xF3mo empezar"',
|
|
12289
|
+
'ghosty agents embed enable <id> --domains "mitienda.com,*.mitienda.mx" --welcome "\xA1Hola! \xBFEn qu\xE9 te ayudo?"',
|
|
12290
|
+
'ghosty agents embed <id> --title "Palmera Legal" --subtitle "Responde en minutos" --position left --bubble-text "\xBFDudas?" --starters "\xBFCu\xE1nto cuesta una consulta?|\xBFD\xF3nde est\xE1n?"',
|
|
12291
|
+
"ghosty agents embed <id> --theme-source site --site-url https://palmeralegal.mx",
|
|
12292
|
+
"ghosty agents embed <id> theme > tema.json \xB7 ghosty agents embed <id> --style-file tema.json",
|
|
12146
12293
|
"ghosty agents box <id> --contains /opt/claude-worker/skills/pdf-doc/render-doc.mjs=pdf-templates",
|
|
12147
12294
|
"ghosty agents set <id> --tool wa:actualizar_identidad=off,teams:actualizar_identidad=on",
|
|
12148
12295
|
'ghosty agents set minighosty --bag "MiniGhosty" --avatar https://www.ghosty.studio/avatars/minighosty.png',
|
|
@@ -12989,6 +13136,10 @@ function normalizeArgs(pos, v) {
|
|
|
12989
13136
|
if (v.expires !== void 0) v.vence = v.expires;
|
|
12990
13137
|
else if (v.vence !== void 0) notes.push(t("`--vence` is now `--expires`.", "`--vence` ahora es `--expires`."));
|
|
12991
13138
|
}
|
|
13139
|
+
if (cmd === "agents" && (sub === "embed" || sub === "widget") && (pos[2] === "enable" || pos[2] === "disable")) {
|
|
13140
|
+
v[pos[2] === "enable" ? "on" : "off"] = true;
|
|
13141
|
+
pos.splice(2, 1);
|
|
13142
|
+
}
|
|
12992
13143
|
if (cmd === "channels" && pos[2] === "groups") {
|
|
12993
13144
|
if (pos[3] === "enable" || pos[3] === "disable") {
|
|
12994
13145
|
v[pos[3] === "enable" ? "on" : "off"] = true;
|
|
@@ -13965,6 +14116,12 @@ ${bold("Agents")}
|
|
|
13965
14116
|
agents box <id> The machine serving it: is it on the new image? [--check PATH]\u2026 [--contains PATH=TEXT]\u2026 [--recycle [--reenv] [--force]]
|
|
13966
14117
|
agents demo enable|disable <id> Turn its public demo link on or off
|
|
13967
14118
|
agents demo <id> Public demo link /p/<slug>: anyone tries it without an account, "Keep it" clones it to theirs
|
|
14119
|
+
agents embed enable|disable <id> Web widget: a chat bubble on YOUR site (one <script>), only on the domains you list [--domains a.com,*.b.com] [--per-visitor N] [--per-ip N] [--welcome T] [--color #hex] [--rotate]
|
|
14120
|
+
look: [--title T] [--subtitle T] [--avatar URL|none] [--icon chat|avatar|ghost] [--placeholder T] [--position right|left] [--offset X[,Y]]
|
|
14121
|
+
[--theme light|dark|auto] [--bubble-text T] [--auto-open SECONDS|off] [--starters "a|b|c"] [--font NAME] [--radius 0-24] [--style '{json}'|none]
|
|
14122
|
+
theme: [--theme-source custom|teams|site] [--workspace SLUG] [--site-url URL] [--style-file theme.json]
|
|
14123
|
+
agents embed <id> theme Export the widget theme as JSON (edit it and apply it back with --style-file)
|
|
14124
|
+
agents embed <id> Its state and the snippet to paste (claude engine only: it isolates each visitor)
|
|
13968
14125
|
[--slug NAME] [--expires "YYYY-MM-DDTHH:MM"|no] [--turns N] [--per-ip N] [--welcome TEXT] [--chips "a|b|c"] [--starter TEXT] [--sponsor on|off] [--rotate]
|
|
13969
14126
|
|
|
13970
14127
|
${bold("Configure an agent")}
|
|
@@ -14121,6 +14278,12 @@ ${bold("Agentes")}
|
|
|
14121
14278
|
agents box <id> La m\xE1quina que lo atiende: \xBFya trae la imagen nueva? [--check RUTA]\u2026 [--contains RUTA=TEXTO]\u2026 [--recycle [--reenv] [--force]]
|
|
14122
14279
|
agents demo enable|disable <id> Prende o apaga su liga p\xFAblica de demo
|
|
14123
14280
|
agents demo <id> Liga p\xFAblica de demo /p/<slug>: cualquiera lo prueba sin cuenta y \xABQued\xE1rmelo\xBB lo clona a la suya
|
|
14281
|
+
agents embed enable|disable <id> Widget web: burbuja de chat en TU sitio (un <script>), s\xF3lo en los dominios que pongas [--domains a.com,*.b.com] [--per-visitor N] [--per-ip N] [--welcome T] [--color #hex] [--rotate]
|
|
14282
|
+
look: [--title T] [--subtitle T] [--avatar URL|none] [--icon chat|avatar|ghost] [--placeholder T] [--position right|left] [--offset X[,Y]]
|
|
14283
|
+
[--theme light|dark|auto] [--bubble-text T] [--auto-open SEGUNDOS|off] [--starters "a|b|c"] [--font NOMBRE] [--radius 0-24] [--style '{json}'|none]
|
|
14284
|
+
tema: [--theme-source custom|teams|site] [--workspace SLUG] [--site-url URL] [--style-file tema.json]
|
|
14285
|
+
agents embed <id> theme Exporta el tema del widget en JSON (ed\xEDtalo y vuelve a aplicarlo con --style-file)
|
|
14286
|
+
agents embed <id> Su estado y el snippet para pegar (s\xF3lo motor claude: a\xEDsla a cada visitante)
|
|
14124
14287
|
[--slug NOMBRE] [--expires "AAAA-MM-DDTHH:MM"|no] [--turns N] [--per-ip N] [--welcome TEXTO] [--chips "a|b|c"] [--starter TEXTO] [--sponsor on|off] [--rotate]
|
|
14125
14288
|
|
|
14126
14289
|
${bold("Configurar un agente")}
|
|
@@ -14214,7 +14377,7 @@ ${bold("C\xF3digos de salida")} 0 bien \xB7 1 error de la API \xB7 2 uso incorr
|
|
|
14214
14377
|
${dim("Nota: `ghosty` puede chocar con otro binario en tu PATH (p. ej. la TUI de Ghosty). Rev\xEDsalo con `which -a ghosty`; corre `npx @ghostystudio/cli` para ir a la segura.")}
|
|
14215
14378
|
${dim("Documentaci\xF3n: https://www.ghosty.studio/docs/cli")}`;
|
|
14216
14379
|
var COMMANDS = ["login", "logout", "whoami", "usage", "use", "apply", "plan", "engines", "bags", "spaces", "workspaces", "staff", "audit", "factory", "demos", "sites", "push", "novedades", "completion", "cards", "agents", "files", "skills", "mcp", "dbs", "turns", "try", "chat", "conversations", "schedule", "partner", "me", "channels", "board", "boards", "credentials", "connectors", "browser", "docs", "help"];
|
|
14217
|
-
var AGENTS_SUBS = ["ls", "create", "get", "set", "export", "doctor", "docs", "share", "unshare", "shares", "teams", "rm", "restart", "demo", "box"];
|
|
14380
|
+
var AGENTS_SUBS = ["ls", "create", "get", "set", "export", "doctor", "docs", "share", "unshare", "shares", "teams", "rm", "restart", "demo", "embed", "box"];
|
|
14218
14381
|
function unknown(what, input, known, helpCmd) {
|
|
14219
14382
|
const s = suggest(input, known);
|
|
14220
14383
|
return usage(t(`Unknown command: ${what}.`, `Comando desconocido: ${what}.`), s ? t(`Did you mean "${s}"? Run: ${helpCmd}`, `\xBFQuisiste decir "${s}"? Corre: ${helpCmd}`) : t(`Run: ${helpCmd}`, `Corre: ${helpCmd}`));
|
|
@@ -14296,10 +14459,28 @@ async function main() {
|
|
|
14296
14459
|
turns: { type: "string" },
|
|
14297
14460
|
vence: { type: "string" },
|
|
14298
14461
|
"per-ip": { type: "string" },
|
|
14462
|
+
"per-visitor": { type: "string" },
|
|
14463
|
+
domains: { type: "string" },
|
|
14464
|
+
color: { type: "string" },
|
|
14299
14465
|
welcome: { type: "string" },
|
|
14300
14466
|
chips: { type: "string" },
|
|
14301
14467
|
starter: { type: "string" },
|
|
14302
14468
|
rotate: { type: "boolean" },
|
|
14469
|
+
subtitle: { type: "string" },
|
|
14470
|
+
placeholder: { type: "string" },
|
|
14471
|
+
position: { type: "string" },
|
|
14472
|
+
offset: { type: "string" },
|
|
14473
|
+
theme: { type: "string" },
|
|
14474
|
+
icon: { type: "string" },
|
|
14475
|
+
"bubble-text": { type: "string" },
|
|
14476
|
+
"auto-open": { type: "string" },
|
|
14477
|
+
starters: { type: "string" },
|
|
14478
|
+
style: { type: "string" },
|
|
14479
|
+
font: { type: "string" },
|
|
14480
|
+
radius: { type: "string" },
|
|
14481
|
+
"style-file": { type: "string" },
|
|
14482
|
+
"theme-source": { type: "string" },
|
|
14483
|
+
"site-url": { type: "string" },
|
|
14303
14484
|
sponsor: { type: "string" },
|
|
14304
14485
|
yes: { type: "boolean", short: "y" },
|
|
14305
14486
|
dir: { type: "string" },
|
|
@@ -14452,7 +14633,7 @@ async function main() {
|
|
|
14452
14633
|
const tokens = splitTokens(pos, v);
|
|
14453
14634
|
globals.token = tokens.session;
|
|
14454
14635
|
globals.profile = v.profile;
|
|
14455
|
-
if (v.version) return out({ version: "0.
|
|
14636
|
+
if (v.version) return out({ version: "0.52.0" }, () => "0.52.0");
|
|
14456
14637
|
for (const n of normalizeArgs(pos, v)) if (!globals.json) info(dim(n));
|
|
14457
14638
|
const context = (await readConfig()).workspace;
|
|
14458
14639
|
if (!explicitToken()?.startsWith("gat_")) {
|
|
@@ -14520,6 +14701,7 @@ async function main() {
|
|
|
14520
14701
|
if (sub === "docs" || sub === "documents") return agentDocsCmd(a1, a2, pos.slice(4).filter((x) => x !== void 0), v);
|
|
14521
14702
|
if (sub === "restart") return agentsRestart(a1);
|
|
14522
14703
|
if (sub === "demo") return agentsDemo(a1, v);
|
|
14704
|
+
if (sub === "embed" || sub === "widget") return agentsEmbed(a1, v, a2);
|
|
14523
14705
|
if (sub === "box") return agentsBox(a1, v);
|
|
14524
14706
|
if (sub === "export") return agentsExport(a1, v);
|
|
14525
14707
|
throw unknown(`agents ${sub}`, sub, AGENTS_SUBS, "ghosty agents --help");
|
|
@@ -14617,7 +14799,7 @@ async function main() {
|
|
|
14617
14799
|
throw unknown(cmd, cmd, COMMANDS, "ghosty --help");
|
|
14618
14800
|
}
|
|
14619
14801
|
}
|
|
14620
|
-
var notice = updateNotice("0.
|
|
14802
|
+
var notice = updateNotice("0.52.0").catch(() => null);
|
|
14621
14803
|
main().then(
|
|
14622
14804
|
async () => {
|
|
14623
14805
|
const n = await notice;
|
package/package.json
CHANGED