@ghostystudio/cli 0.58.1 → 0.60.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 +10 -0
- package/dist/index.js +64 -16
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -31,6 +31,7 @@ ghosty agents set <id> [--name] [--engine] [--model] [--prompt | --prompt-file F
|
|
|
31
31
|
ghosty agents set <id> --prompt-base <base-id> --prompt-overlay overlay.json [--dry-run] # prompt = another agent's + edits, kept in sync
|
|
32
32
|
ghosty agents share|unshare <id> <email> [--role editor|admin] # share without handing it over · agents shares <id> lists them
|
|
33
33
|
ghosty agents teams ls|on|off|rm <id> [workspace] [--handle x] # which Teams workspaces it answers in, and its @handle there
|
|
34
|
+
ghosty agents archive|restore <id> # archive: stops answering, deleted after 7 days unless restored
|
|
34
35
|
ghosty agents rm <id> [--from-workspace] [--yes] # --from-workspace: turn it off in Teams first
|
|
35
36
|
ghosty agents set <id> [--tool wa:tool=off,…] [--bag NAME|none] [--avatar URL|FILE]
|
|
36
37
|
ghosty agents restart <id>
|
|
@@ -109,6 +110,15 @@ Every command has its own help with examples: `ghosty <command> --help` or `ghos
|
|
|
109
110
|
|
|
110
111
|
Exit codes: `0` ok · `1` API error · `2` usage error · `3` not signed in.
|
|
111
112
|
|
|
113
|
+
### Changes in 0.60.0
|
|
114
|
+
|
|
115
|
+
- `agents archive <id>` / `agents restore <id>`: archive an agent (it stops answering on every channel and leaves the lists; deleted automatically after 7 days) or bring it back as it was. `agents ls --archived` lists archived agents and when they get deleted.
|
|
116
|
+
|
|
117
|
+
### Changes in 0.59.0
|
|
118
|
+
|
|
119
|
+
- `spaces archive <workspace>` / `spaces restore <workspace>`: archive a workspace (same as Settings → Archive: it leaves `/app` and `spaces ls`; agents and data stay) or bring it back. Owner or staff; dry run first, archiving asks you to type the slug; logged as `workspace.archive` / `workspace.restore`.
|
|
120
|
+
- `spaces ls` no longer lists archived workspaces you are a member of (same as `/app`).
|
|
121
|
+
|
|
112
122
|
### Changes in 0.58.1
|
|
113
123
|
|
|
114
124
|
- `agents docs add|replace --file` sends the file type from its extension. Before, the server stored every CLI upload as `application/octet-stream`, and a PDF reached WhatsApp customers as `.bin`.
|
package/dist/index.js
CHANGED
|
@@ -8169,7 +8169,17 @@ var SERVER_MESSAGES = [
|
|
|
8169
8169
|
["s\xF3lo el due\xF1o del agente maneja su widget web", "only the agent's owner manages its web widget"],
|
|
8170
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
8171
|
["el widget web s\xF3lo corre con Claude o MiniGhosty (ghosty-lite): son los que a\xEDslan a cada visitante", "the web widget only runs on Claude or MiniGhosty (ghosty-lite): they isolate 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)"]
|
|
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)"],
|
|
8173
|
+
// — Espacios (`workspaces.server.ts`: crear y archivar)
|
|
8174
|
+
["Ahora mismo no tenemos sitio para espacios nuevos. Te apuntamos en la lista y te avisamos en cuanto se libere \u2014 normalmente es cuesti\xF3n de horas.", "We have no room for new workspaces right now. You're on the list and we'll let you know as soon as there is \u2014 usually within hours."],
|
|
8175
|
+
["Para archivar escribe el nombre exacto: {}", "To archive, type the exact name: {}"],
|
|
8176
|
+
['correo inv\xE1lido: "{}"', 'invalid email: "{}"'],
|
|
8177
|
+
['el workspace "{}" ya existe', 'workspace "{}" already exists'],
|
|
8178
|
+
["slug inv\xE1lido (2-40, min\xFAsculas/n\xFAmeros/guiones, no reservado)", "invalid slug (2-40, lowercase/numbers/hyphens, not reserved)"],
|
|
8179
|
+
["{} rebot\xF3 antes y dejamos de escribirle. Hay que revisar esa direcci\xF3n.", "{} bounced before and we stopped writing to it. Check that address."],
|
|
8180
|
+
["{} tiene que confirmar su correo antes de crear un espacio, y no pudimos mandarte la liga ahora mismo. P\xEDdela otra vez desde /verify-email.", "{} must confirm their email before creating a workspace, and we couldn't send the link right now. Ask for it again from /verify-email."],
|
|
8181
|
+
["{} tiene que confirmar su correo antes de crear un espacio. Acabamos de mandarte la liga; \xE1brela y vuelve a intentarlo.", "{} must confirm their email before creating a workspace. We just sent you the link; open it and try again."],
|
|
8182
|
+
["{} ya tiene {} workspace(s) y su plan ({}) permite {}.", "{} already has {} workspace(s) and their plan ({}) allows {}."]
|
|
8173
8183
|
];
|
|
8174
8184
|
|
|
8175
8185
|
// src/i18n.ts
|
|
@@ -8468,7 +8478,7 @@ async function postLong(path, body, timeoutMs = 9e5) {
|
|
|
8468
8478
|
const req = httpsRequest(`${base}${path}`, {
|
|
8469
8479
|
method: "POST",
|
|
8470
8480
|
timeout: timeoutMs,
|
|
8471
|
-
headers: { authorization: `Bearer ${token}`, "user-agent": `ghosty-cli/${"0.
|
|
8481
|
+
headers: { authorization: `Bearer ${token}`, "user-agent": `ghosty-cli/${"0.60.0"}`, "content-type": "application/json", "content-length": Buffer.byteLength(data) }
|
|
8472
8482
|
}, (res) => {
|
|
8473
8483
|
let buf = "";
|
|
8474
8484
|
res.on("data", (c) => buf += c);
|
|
@@ -8510,7 +8520,7 @@ async function request(path, opts = {}, retried = false) {
|
|
|
8510
8520
|
method: opts.method ?? (opts.body !== void 0 || opts.raw !== void 0 ? "POST" : "GET"),
|
|
8511
8521
|
headers: {
|
|
8512
8522
|
authorization: `Bearer ${token}`,
|
|
8513
|
-
"user-agent": `ghosty-cli/${"0.
|
|
8523
|
+
"user-agent": `ghosty-cli/${"0.60.0"}`,
|
|
8514
8524
|
"accept-language": lang(),
|
|
8515
8525
|
...opts.body !== void 0 ? { "content-type": "application/json" } : {},
|
|
8516
8526
|
...opts.headers
|
|
@@ -9070,6 +9080,11 @@ var need = (v, what, example) => {
|
|
|
9070
9080
|
return v;
|
|
9071
9081
|
};
|
|
9072
9082
|
async function agentsLs(workspace, f = {}) {
|
|
9083
|
+
if (f.archived) {
|
|
9084
|
+
const r2 = await api("/api/v2/me/agents/archived");
|
|
9085
|
+
if (f.ids) return void process.stdout.write(r2.agents.map((a) => a.id).join("\n") + (r2.agents.length ? "\n" : ""));
|
|
9086
|
+
return out(r2.agents, () => table(r2.agents.map((a) => ({ id: a.id, name: a.name, engine: a.engine, archivedAt: a.archivedAt, purgeAt: a.purgeAt })), ["id", "name", "engine", "archivedAt", "purgeAt"]));
|
|
9087
|
+
}
|
|
9073
9088
|
if (f.sponsor || f.owner) {
|
|
9074
9089
|
const q = new URLSearchParams({ ...f.sponsor ? { sponsor: f.sponsor } : {}, ...f.owner ? { owner: f.owner } : {}, ...f.engine ? { engine: f.engine } : {}, ...workspace && !f.all ? { workspace } : {} });
|
|
9075
9090
|
const s2 = await api(`/api/v2/agents?${q}`);
|
|
@@ -9344,6 +9359,15 @@ async function agentsRm(id, v = {}) {
|
|
|
9344
9359
|
const r = await api(agentPath(id, from ? "?fromWorkspace=1" : ""), { method: "DELETE" });
|
|
9345
9360
|
out(r, () => `${lavender("\u2713")} ${t("Deleted", "Borrado")} ${id}.${r?.unbound?.length ? dim(t(` Turned off in Teams: ${r.unbound.join(", ")}.`, ` Desactivado en Teams: ${r.unbound.join(", ")}.`)) : ""}`);
|
|
9346
9361
|
}
|
|
9362
|
+
async function agentsArchive(id, archive) {
|
|
9363
|
+
id = need(id, "agent id", `ghosty agents ${archive ? "archive" : "restore"} <agent-id>`);
|
|
9364
|
+
const r = await api(agentPath(id, "/archive"), { method: "POST", body: { archive } });
|
|
9365
|
+
const day3 = r.purgeAt ? r.purgeAt.slice(0, 10) : "";
|
|
9366
|
+
out(
|
|
9367
|
+
r,
|
|
9368
|
+
() => !r.changed ? dim(archive ? t(`Already archived (deleted on ${day3}).`, `Ya estaba archivado (se borra el ${day3}).`) : t("It wasn't archived.", "No estaba archivado.")) : archive ? `${lavender("\u2713")} ${t(`Archived ${id}. It no longer answers anywhere; deleted on ${day3} unless you restore it (ghosty agents restore ${id}).`, `Archivado ${id}. Ya no contesta en ning\xFAn canal; se borra el ${day3} si no lo restauras (ghosty agents restore ${id}).`)}` : `${lavender("\u2713")} ${t(`Restored ${id}.`, `Restaurado ${id}.`)}${r.teams.length || r.whatsapp ? dim(t(` Back on: ${[...r.teams.length ? [`Teams (${r.teams.length})`] : [], ...r.whatsapp ? ["WhatsApp"] : []].join(", ")}.`, ` De vuelta: ${[...r.teams.length ? [`Teams (${r.teams.length})`] : [], ...r.whatsapp ? ["WhatsApp"] : []].join(", ")}.`)) : ""}`
|
|
9369
|
+
);
|
|
9370
|
+
}
|
|
9347
9371
|
async function setAvatar(id, src) {
|
|
9348
9372
|
if (/^https:\/\//.test(src)) return api(agentPath(id, "/avatar"), { method: "PUT", body: { url: src } });
|
|
9349
9373
|
const bytes = await readFile3(src).catch(() => {
|
|
@@ -10408,7 +10432,7 @@ async function call(path, v, init = {}) {
|
|
|
10408
10432
|
"x-ghosty-ts": ts,
|
|
10409
10433
|
"x-ghosty-sig": sig,
|
|
10410
10434
|
"content-type": "application/json",
|
|
10411
|
-
"user-agent": `ghosty-cli/${"0.
|
|
10435
|
+
"user-agent": `ghosty-cli/${"0.60.0"}`
|
|
10412
10436
|
},
|
|
10413
10437
|
body: method === "GET" ? void 0 : raw
|
|
10414
10438
|
});
|
|
@@ -12080,6 +12104,8 @@ var HELPS_ES = {
|
|
|
12080
12104
|
["# 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"],
|
|
12081
12105
|
["# turn it on there (or change its @handle)", "# lo prende ah\xED (o le cambia el @handle)"],
|
|
12082
12106
|
["# pause it there; it keeps its @handle", "# lo pausa ah\xED; conserva su @handle"],
|
|
12107
|
+
["# archive: stops answering everywhere, hidden, deleted after 7 days unless restored", "# archivar: deja de contestar en todos lados, se oculta y se borra a los 7 d\xEDas si no lo restauras"],
|
|
12108
|
+
["# archived agents and when they get deleted", "# los archivados y cu\xE1ndo se borran"],
|
|
12083
12109
|
["# remove it from there; the agent stays", "# lo quita de ah\xED; el agente sigue"],
|
|
12084
12110
|
["# web widget: chat bubble on your site, only on those domains", "# widget web: burbuja de chat en tu sitio, s\xF3lo en esos dominios"],
|
|
12085
12111
|
["# state + the <script> to paste", "# su estado + el <script> para pegar"]
|
|
@@ -12514,7 +12540,7 @@ var HELPS_ES = {
|
|
|
12514
12540
|
]
|
|
12515
12541
|
},
|
|
12516
12542
|
spaces: {
|
|
12517
|
-
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, cambiar de due\xF1o. Cada cambio queda en la bit\xE1cora del espacio.",
|
|
12543
|
+
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, cambiar de due\xF1o \u2014 y, due\xF1o o staff, archivarlo o restaurarlo. Cada cambio queda en la bit\xE1cora del espacio.",
|
|
12518
12544
|
flags: [
|
|
12519
12545
|
["--user EMAIL", "ls (staff): los espacios de esa persona"],
|
|
12520
12546
|
["--combo C", "set (staff): teams | sales | both \u2014 sin Ventas sus tableros existen pero nadie los ve; create: distinto de teams, s\xF3lo staff"],
|
|
@@ -12529,7 +12555,7 @@ var HELPS_ES = {
|
|
|
12529
12555
|
["-n, --dry-run", "ense\xF1a qu\xE9 cambia, no cambia nada"],
|
|
12530
12556
|
["--yes", "s\xE1ltate la confirmaci\xF3n (obligatorio sin terminal)"]
|
|
12531
12557
|
],
|
|
12532
|
-
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.", "transfer se lleva los agentes con el espacio
|
|
12558
|
+
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.", "archive hace lo mismo que Ajustes \u2192 Archivar: el espacio sale de /app y de spaces ls, sus agentes y datos se quedan; pide escribir el slug. Deshacer: ghosty spaces restore <slug>. Queda en bit\xE1cora como workspace.archive / workspace.restore.", "transfer se lleva los agentes con el espacio: las cajas ACP se mudan al due\xF1o nuevo con su /data, las del pool se reciclan (el due\xF1o va horneado en la caja); sin --copy-keys la simulaci\xF3n dice qu\xE9 llaves le faltan al nuevo \u2014 esos agentes dejar\xEDan de contestar."]
|
|
12533
12559
|
},
|
|
12534
12560
|
staff: {
|
|
12535
12561
|
summary: "Staff de Ghosty asignado a CUENTAS cliente (admin delegado que act\xFAa como s\xED mismo): ve y opera con su propia sesi\xF3n los agentes (con y sin espacio), documentos, bases y tableros de esa cuenta. Sin llaves, cobro, traspasos ni borrados. S\xF3lo el staff de Ghosty asigna; el cliente s\xF3lo ve \xABTu ejecutivo de Ghosty\xBB. Cada cambio y cada escritura quedan en la bit\xE1cora.",
|
|
@@ -12629,6 +12655,8 @@ var HELPS = {
|
|
|
12629
12655
|
"ghosty agents embed <agent-id> [--copy '{json}'|none] [--copy-file texts.json] # what it says while it works",
|
|
12630
12656
|
"ghosty agents embed <agent-id> theme # export the theme as JSON (edit it, apply it back with --style-file)",
|
|
12631
12657
|
"ghosty agents embed <agent-id> --out src/components/GhostyChat.tsx [--force] # your own React component, token and theme baked in",
|
|
12658
|
+
"ghosty agents archive|restore <agent-id> # archive: stops answering everywhere, hidden, deleted after 7 days unless restored",
|
|
12659
|
+
"ghosty agents ls --archived # archived agents and when they get deleted",
|
|
12632
12660
|
"ghosty agents rm <agent-id> [--from-workspace] [--yes]"
|
|
12633
12661
|
],
|
|
12634
12662
|
flags: [
|
|
@@ -13247,8 +13275,8 @@ HELPS.novedades = {
|
|
|
13247
13275
|
learn: `${REF}#soporte`
|
|
13248
13276
|
};
|
|
13249
13277
|
HELPS.spaces = {
|
|
13250
|
-
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, change its owner. Each change is logged in the workspace's audit.",
|
|
13251
|
-
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 | --model-cap 0.25|1|4|none | --house-claude on|off [--dry-run]", "ghosty spaces renew <workspace> --until YYYY-MM-DD [--note TEXT] [--dry-run] [--yes]", "ghosty spaces rename <old> <new> [--dry-run] [--yes]", "ghosty spaces transfer <workspace> --to EMAIL [--keep-as admin|member|none] [--copy-keys] [--dry-run] [--yes]", "ghosty spaces log <workspace> [--since 30d] [--action workspace] [--limit N]"],
|
|
13278
|
+
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, change its owner \u2014 and, owner or staff, archive or restore it. Each change is logged in the workspace's audit.",
|
|
13279
|
+
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 | --model-cap 0.25|1|4|none | --house-claude on|off [--dry-run]", "ghosty spaces renew <workspace> --until YYYY-MM-DD [--note TEXT] [--dry-run] [--yes]", "ghosty spaces rename <old> <new> [--dry-run] [--yes]", "ghosty spaces archive|restore <workspace> [--dry-run] [--yes]", "ghosty spaces transfer <workspace> --to EMAIL [--keep-as admin|member|none] [--copy-keys] [--dry-run] [--yes]", "ghosty spaces log <workspace> [--since 30d] [--action workspace] [--limit N]"],
|
|
13252
13280
|
flags: [
|
|
13253
13281
|
["--user EMAIL", "ls (staff): that person's workspaces"],
|
|
13254
13282
|
["--combo C", "set (staff): teams | sales | both \u2014 without Sales its boards exist but nobody sees them; create: other than teams, staff only"],
|
|
@@ -13263,8 +13291,8 @@ HELPS.spaces = {
|
|
|
13263
13291
|
["-n, --dry-run", "show what changes, change nothing"],
|
|
13264
13292
|
["--yes", "skip the confirmation (required without a terminal)"]
|
|
13265
13293
|
],
|
|
13266
|
-
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 set mailmask --model-cap 4 --house-claude on", 'ghosty spaces renew descti --until 2026-11-01 --note "pag\xF3 octubre"', "ghosty spaces rename totequim siiqtec --dry-run", "ghosty spaces transfer siiqtec --to siiqtec@gmail.com --keep-as admin --copy-keys --dry-run", "ghosty spaces log siiqtec --since 30d"],
|
|
13267
|
-
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.", "transfer moves the agents with the workspace
|
|
13294
|
+
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 set mailmask --model-cap 4 --house-claude on", 'ghosty spaces renew descti --until 2026-11-01 --note "pag\xF3 octubre"', "ghosty spaces rename totequim siiqtec --dry-run", "ghosty spaces archive box-xfer-test --dry-run", "ghosty spaces transfer siiqtec --to siiqtec@gmail.com --keep-as admin --copy-keys --dry-run", "ghosty spaces log siiqtec --since 30d"],
|
|
13295
|
+
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.", "archive does what Settings \u2192 Archive does: the workspace leaves /app and spaces ls, its agents and data stay; it asks you to type the slug. Undo: ghosty spaces restore <slug>. Logged as workspace.archive / workspace.restore.", "transfer moves the agents with the workspace: ACP boxes move to the new owner with their /data, pool boxes are recycled (the owner is baked into the box); without --copy-keys the dry run lists which keys the new owner lacks \u2014 those agents would stop answering."],
|
|
13268
13296
|
learn: `${REF}#espacios`
|
|
13269
13297
|
};
|
|
13270
13298
|
HELPS.workspaces = HELPS.spaces;
|
|
@@ -13844,7 +13872,7 @@ ${bagsText(r)}`);
|
|
|
13844
13872
|
}
|
|
13845
13873
|
}
|
|
13846
13874
|
async function spacesCmd(sub, slug, arg, v, context) {
|
|
13847
|
-
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 | --model-cap 0.25|1|4|none | --house-claude on|off \xB7 renew <workspace> --until 2026-11-01 [--note TEXT] \xB7 rename <old> <new> [--dry-run] \xB7 transfer <workspace> --to EMAIL [--keep-as admin|member|none] [--copy-keys] [--dry-run] \xB7 log <workspace> [--since 30d] [--action workspace]";
|
|
13875
|
+
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 | --model-cap 0.25|1|4|none | --house-claude on|off \xB7 renew <workspace> --until 2026-11-01 [--note TEXT] \xB7 rename <old> <new> [--dry-run] \xB7 archive|restore <workspace> [--dry-run] \xB7 transfer <workspace> --to EMAIL [--keep-as admin|member|none] [--copy-keys] [--dry-run] \xB7 log <workspace> [--since 30d] [--action workspace]";
|
|
13848
13876
|
if (!sub || sub === "ls" || sub === "list") {
|
|
13849
13877
|
const r = await api(`/api/v2/workspaces${v.user ? `?user=${enc10(v.user)}` : ""}`);
|
|
13850
13878
|
const rows = r.workspaces.map((w) => ({ workspace: w.slug, role: w.role ?? "", plan: w.plan, combo: w.combo, owner: w.owner ?? "", paid: w.paidUntil ?? "" }));
|
|
@@ -13927,6 +13955,22 @@ ${t("Rename?", "\xBFRenombrar?")}`, { yes: v.yes, expect: plan.from, retry: `gho
|
|
|
13927
13955
|
const r = await api(path, { method: "POST", body: { to: arg } });
|
|
13928
13956
|
return out(r, () => `${lavender("\u2713")} ${t(`Renamed: ${r.from} \u2192 ${r.to}. Undo: ghosty spaces rename ${r.to} ${r.from}`, `Renombrado: ${r.from} \u2192 ${r.to}. Deshacer: ghosty spaces rename ${r.to} ${r.from}`)}`);
|
|
13929
13957
|
}
|
|
13958
|
+
if (sub === "archive" || sub === "restore") {
|
|
13959
|
+
slug = needSpace(slug, `ghosty spaces ${sub} <workspace> --dry-run`);
|
|
13960
|
+
const archive = sub === "archive";
|
|
13961
|
+
const path = wsPath(slug, "/archive");
|
|
13962
|
+
const plan = await api(path, { method: "POST", body: { archive, dryRun: true } });
|
|
13963
|
+
const line2 = `${plan.slug}: ${plan.from} \u2192 ${bold(plan.to)} ${dim(t(`(${plan.agents} agent(s); they and their data stay as they are)`, `(${plan.agents} agente(s); ellos y sus datos se quedan igual)`))}`;
|
|
13964
|
+
if (!plan.changed) return out(plan, () => dim(t(`Nothing to do: ${plan.slug} is already ${plan.from}.`, `Nada que hacer: ${plan.slug} ya est\xE1 ${plan.from}.`)));
|
|
13965
|
+
if (v["dry-run"]) return out(plan, () => `${line2}
|
|
13966
|
+
${dim(t("Dry run: nothing changed.", "Simulaci\xF3n: no cambi\xF3 nada."))}`);
|
|
13967
|
+
const retry = `ghosty spaces ${sub} ${slug}`;
|
|
13968
|
+
requireYesIfHeadless(v.yes, retry);
|
|
13969
|
+
await confirm(`${line2}
|
|
13970
|
+
${archive ? t("Archive it?", "\xBFArchivarlo?") : t("Restore it?", "\xBFRestaurarlo?")}`, { yes: v.yes, retry, ...archive ? { expect: plan.slug } : {} });
|
|
13971
|
+
const r = await api(path, { method: "POST", body: { archive } });
|
|
13972
|
+
return out(r, () => archive ? `${lavender("\u2713")} ${t(`Archived: ${r.slug}. Undo: ghosty spaces restore ${r.slug}`, `Archivado: ${r.slug}. Deshacer: ghosty spaces restore ${r.slug}`)}` : `${lavender("\u2713")} ${t(`Restored: ${r.slug}.`, `Restaurado: ${r.slug}.`)}`);
|
|
13973
|
+
}
|
|
13930
13974
|
if (sub === "transfer") {
|
|
13931
13975
|
slug = needSpace(slug ?? context, "ghosty spaces transfer <workspace> --to EMAIL --dry-run");
|
|
13932
13976
|
const toEmail = v.to ?? arg;
|
|
@@ -14641,7 +14685,8 @@ ${bold("Workspaces")} ${dim("(changing them: Ghosty staff)")}
|
|
|
14641
14685
|
spaces set <workspace> --combo sales teams | sales | both (without Sales its boards are invisible) [--model-cap 0.25|1|4|none: most expensive model] [--house-claude on|off]
|
|
14642
14686
|
spaces renew <workspace> --until DATE Move \xABpaid until\xBB (logged) [--note] [--dry-run]
|
|
14643
14687
|
spaces rename <old> <new> Change its slug only [--dry-run]
|
|
14644
|
-
spaces
|
|
14688
|
+
spaces archive|restore <workspace> Archive it (out of /app and spaces ls; agents and data stay) or bring it back (owner or staff) [--dry-run]
|
|
14689
|
+
spaces transfer <workspace> --to EMAIL New owner; agents go with it (ACP boxes move with their /data, pool boxes are recycled) [--keep-as admin|member|none] [--copy-keys] [--dry-run]
|
|
14645
14690
|
spaces log <workspace> Its log: transfers, staff in/out, renewals (owner or staff) [--since 30d] [--action workspace]
|
|
14646
14691
|
staff ls [staff-email] [client-email] Ghosty staff assigned to client accounts (staff) [--all: also revoked]
|
|
14647
14692
|
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]
|
|
@@ -14808,7 +14853,8 @@ ${bold("Espacios")} ${dim("(cambiarlos: staff de Ghosty)")}
|
|
|
14808
14853
|
spaces set <espacio> --combo sales teams | sales | both (sin Ventas sus tableros no se ven) [--model-cap 0.25|1|4|none: el modelo m\xE1s caro] [--house-claude on|off]
|
|
14809
14854
|
spaces renew <espacio> --until FECHA Mueve \xABpagado hasta\xBB (queda en bit\xE1cora) [--note] [--dry-run]
|
|
14810
14855
|
spaces rename <viejo> <nuevo> Cambia s\xF3lo su slug [--dry-run]
|
|
14811
|
-
spaces
|
|
14856
|
+
spaces archive|restore <espacio> Arch\xEDvalo (sale de /app y de spaces ls; agentes y datos se quedan) o tr\xE1elo de vuelta (due\xF1o o staff) [--dry-run]
|
|
14857
|
+
spaces transfer <espacio> --to CORREO Due\xF1o nuevo; los agentes se van con \xE9l (las cajas ACP se mudan con su /data, las del pool se reciclan) [--keep-as admin|member|none] [--copy-keys] [--dry-run]
|
|
14812
14858
|
spaces log <espacio> Su bit\xE1cora: traspasos, staff que entra o sale, renovaciones (due\xF1o o staff) [--since 30d] [--action workspace]
|
|
14813
14859
|
staff ls [correo-staff] [correo-cliente] Staff de Ghosty asignado a cuentas cliente (staff) [--all: tambi\xE9n revocadas]
|
|
14814
14860
|
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]
|
|
@@ -15172,6 +15218,7 @@ async function main() {
|
|
|
15172
15218
|
avatar: { type: "string" },
|
|
15173
15219
|
tool: { type: "string" },
|
|
15174
15220
|
"from-workspace": { type: "boolean" },
|
|
15221
|
+
archived: { type: "boolean" },
|
|
15175
15222
|
"quota-hits": { type: "boolean" },
|
|
15176
15223
|
by: { type: "string" },
|
|
15177
15224
|
models: { type: "boolean" },
|
|
@@ -15221,7 +15268,7 @@ async function main() {
|
|
|
15221
15268
|
const tokens = splitTokens(pos, v);
|
|
15222
15269
|
globals.token = tokens.session;
|
|
15223
15270
|
globals.profile = v.profile;
|
|
15224
|
-
if (v.version) return out({ version: "0.
|
|
15271
|
+
if (v.version) return out({ version: "0.60.0" }, () => "0.60.0");
|
|
15225
15272
|
for (const n of normalizeArgs(pos, v)) if (!globals.json) info(dim(n));
|
|
15226
15273
|
const context = (await readConfig()).workspace;
|
|
15227
15274
|
if (!explicitToken()?.startsWith("gat_")) {
|
|
@@ -15270,7 +15317,7 @@ async function main() {
|
|
|
15270
15317
|
case "agents":
|
|
15271
15318
|
if ((sub === "ls" || sub === "list" || !sub) && v.user && v.app !== void 0) return appAgentsOf(v.user, v.app);
|
|
15272
15319
|
if ((sub === "ls" || sub === "list" || !sub) && v.handle) return agentsByHandle(v.handle, v.workspace ?? context);
|
|
15273
|
-
if (sub === "ls" || sub === "list" || !sub) return agentsLs(v.all ? void 0 : v.workspace ?? context, { sponsor: v.sponsor, owner: v.owner, engine: v.engine, ids: v.ids, all: v.all });
|
|
15320
|
+
if (sub === "ls" || sub === "list" || !sub) return agentsLs(v.all ? void 0 : v.workspace ?? context, { sponsor: v.sponsor, owner: v.owner, engine: v.engine, ids: v.ids, all: v.all, archived: v.archived });
|
|
15274
15321
|
if (sub === "create" || sub === "new") {
|
|
15275
15322
|
if (v.workspace === "none") delete v.workspace;
|
|
15276
15323
|
else if (!v.workspace && context) {
|
|
@@ -15284,6 +15331,7 @@ async function main() {
|
|
|
15284
15331
|
if (sub === "teams") return agentsTeams(a1, a2, pos[4], v);
|
|
15285
15332
|
if (sub === "set") return agentsSet(a1, v);
|
|
15286
15333
|
if (sub === "rm" || sub === "delete") return agentsRm(a1, v);
|
|
15334
|
+
if (sub === "archive" || sub === "restore") return agentsArchive(a1, sub === "archive");
|
|
15287
15335
|
if (sub === "doctor" && v.user) return userDoctor(v.user, a1, v);
|
|
15288
15336
|
if (sub === "doctor") return agentsDoctor(a1, v);
|
|
15289
15337
|
if (sub === "docs" || sub === "documents") return agentDocsCmd(a1, a2, pos.slice(4).filter((x) => x !== void 0), v);
|
|
@@ -15387,7 +15435,7 @@ async function main() {
|
|
|
15387
15435
|
throw unknown(cmd, cmd, COMMANDS, "ghosty --help");
|
|
15388
15436
|
}
|
|
15389
15437
|
}
|
|
15390
|
-
var notice = updateNotice("0.
|
|
15438
|
+
var notice = updateNotice("0.60.0").catch(() => null);
|
|
15391
15439
|
main().then(
|
|
15392
15440
|
async () => {
|
|
15393
15441
|
const n = await notice;
|
package/package.json
CHANGED