@ghostystudio/cli 0.71.0 → 0.74.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 +11 -0
- package/dist/index.js +241 -22
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -121,6 +121,9 @@ ghosty connectors ls|connect|disconnect [id] [--q TEXT] [--from-env VAR] [--no-
|
|
|
121
121
|
ghosty support open --title T --body TEXT · support ls | show <id> | reply <id> --body TEXT # ask Ghosty for help; answered by email
|
|
122
122
|
ghosty browser logout # revoke your terminal agents' browser tokens and disconnect Ghosty for Chrome
|
|
123
123
|
ghosty audit ls [--workspace SLUG] [--agent ID] [--actor EMAIL] [--action A] [--since 24h] [--limit N] # who changed what
|
|
124
|
+
ghosty factory rooms connect owner/name --room R --create # set up the factory for a repo from the terminal
|
|
125
|
+
ghosty factory run "…" --repo owner/name [--wait] # hand a request to the Software Factory from the terminal
|
|
126
|
+
ghosty factory runs watch|approve|changes|merge|card <run> # wait for it and decide it without opening Teams
|
|
124
127
|
ghosty factory runs ls|show|why|stats|rename [--workspace SLUG] [--room R] [--status S] [show --timing] [why --refresh] # Software Factory runs
|
|
125
128
|
ghosty docs
|
|
126
129
|
|
|
@@ -137,6 +140,14 @@ Every command has its own help with examples: `ghosty <command> --help` or `ghos
|
|
|
137
140
|
|
|
138
141
|
Exit codes: `0` ok · `1` API error · `2` usage error · `3` not signed in.
|
|
139
142
|
|
|
143
|
+
### Changes in 0.73.0
|
|
144
|
+
|
|
145
|
+
- `factory rooms ls|connect|disconnect`: set up the factory for a repo without opening Teams. `connect owner/repo --room R --create` creates the room, connects the repo (only if your GitHub App sees it) and tells you how ready it is for agents.
|
|
146
|
+
|
|
147
|
+
### Changes in 0.72.0
|
|
148
|
+
|
|
149
|
+
- `factory run "…" --repo owner/name [--wait]`: hand a request to the Software Factory from the terminal (it posts «@plan …» in the repo's room under your name). `--wait` and `runs watch <run>` return when the run needs you and print the next command; `runs approve <run> --plan-version N`, `runs changes <run> --note "…"`, `runs merge <run>` and `runs card <run>` decide it without opening Teams.
|
|
150
|
+
|
|
140
151
|
### Changes in 0.71.0
|
|
141
152
|
|
|
142
153
|
- `channels mteams ls|connect|zip|on|off|rm`: your agent as a Microsoft Teams bot through an Azure Bot in the client's tenant (no app store). `ls` now shows the bot's last problem (token rejected, send failed, app uninstalled), also in `--json` as `lastError`/`lastErrorAt`.
|
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.74.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.74.0"}`,
|
|
1221
1221
|
"accept-language": lang(),
|
|
1222
1222
|
...opts.body !== void 0 ? { "content-type": "application/json" } : {},
|
|
1223
1223
|
...opts.headers
|
|
@@ -11193,7 +11193,7 @@ async function call(path, v, init = {}) {
|
|
|
11193
11193
|
"x-ghosty-ts": ts,
|
|
11194
11194
|
"x-ghosty-sig": sig,
|
|
11195
11195
|
"content-type": "application/json",
|
|
11196
|
-
"user-agent": `ghosty-cli/${"0.
|
|
11196
|
+
"user-agent": `ghosty-cli/${"0.74.0"}`
|
|
11197
11197
|
},
|
|
11198
11198
|
body: method === "GET" ? void 0 : raw
|
|
11199
11199
|
});
|
|
@@ -13558,26 +13558,39 @@ var HELPS_ES = {
|
|
|
13558
13558
|
]
|
|
13559
13559
|
},
|
|
13560
13560
|
factory: {
|
|
13561
|
-
summary: "
|
|
13562
|
-
replace: [['"Title"', '"T\xEDtulo"']],
|
|
13561
|
+
summary: "P\xEDdele cosas a la Software Factory de un espacio desde la terminal y decide sin abrir Teams (firmar el plan, mergear el PR): la f\xE1brica como complemento de tu agente de c\xF3digo. Tambi\xE9n sus pedidos (viven en su Teams): listarlos con tiempo y costo, ver uno (plan vigente, PR, preview, \xFAltimos eventos, qu\xE9 rol trabaja), ver en qu\xE9 se fue su tiempo y su dinero y por qu\xE9 se ator\xF3 o fall\xF3, los totales del espacio y corregir el t\xEDtulo de un pedido.",
|
|
13562
|
+
replace: [['"Title"', '"T\xEDtulo"'], [`"What, why and how we know it's done"`, '"Qu\xE9, por qu\xE9 y c\xF3mo se sabe que qued\xF3"']],
|
|
13563
13563
|
flags: [
|
|
13564
13564
|
["--workspace SLUG", "el espacio (default: el de ghosty use)"],
|
|
13565
|
-
["--
|
|
13565
|
+
["--repo OWNER/REPO", "run: el repo; va al room que lo tiene conectado. stats: s\xF3lo ese repo"],
|
|
13566
|
+
["--wait", "run: espera a que el pedido te necesite (firmar el plan, decidir, mergear el PR) o termine; imprime el siguiente comando"],
|
|
13567
|
+
["--timeout S", "run --wait / watch: segundos de espera (default 1800); exit 1 si se acaba"],
|
|
13568
|
+
["--thread ID", "watch: el hilo que te dio run, antes de que @plan cree el pedido"],
|
|
13569
|
+
["--plan-version N", "approve: la versi\xF3n del plan que le\xEDste (runs show <pedido> --full); una m\xE1s nueva se rechaza"],
|
|
13570
|
+
["--note T", "changes: qu\xE9 cambiar del plan (o por qu\xE9 replanear tras un escalado). approve tras un escalado: qu\xE9 debe arreglar @build"],
|
|
13571
|
+
["--check-scope T", "approve/changes: lo \xFAnico que @check revisa en la siguiente vuelta (lo propone runs advise); lo nuevo va como nota, no como hallazgo"],
|
|
13572
|
+
["--skip-preview", "merge: mergea sin la preview que ped\xEDa el plan (queda en bit\xE1cora)"],
|
|
13573
|
+
["--create", "rooms connect: crea el room si no existe"],
|
|
13574
|
+
["--private", "rooms connect --create: el room nuevo es privado (s\xF3lo t\xFA, y a quien agregues)"],
|
|
13575
|
+
["--room R", "rooms connect/disconnect: el room (slug o nombre). run: ese room en vez de buscarlo por --repo. ls: s\xF3lo los pedidos de ese room (#slug o nombre)"],
|
|
13566
13576
|
["--status S", "ls: s\xF3lo esa etapa (planning, building, checking, pr_review, merged\u2026)"],
|
|
13567
13577
|
["--limit N", "ls: cu\xE1ntos (default 30)"],
|
|
13568
|
-
["--full", "show: imprime el plan vigente"],
|
|
13578
|
+
["--full", "show: imprime el plan vigente. rooms ls: tambi\xE9n los rooms sin repo"],
|
|
13569
13579
|
["--timing", "show: cada turno de cada rol (cr\xEDtico, @plan, @build, @check) con minutos, minutos en tools, modelo y USD; el reloj del pedido partido en trabajando, esperando a una persona (plan o PR por aprobar) y lo dem\xE1s (CI, colas); y los comandos de 60 s o m\xE1s"],
|
|
13570
13580
|
["--refresh", "why: rehace el an\xE1lisis (se guarda la primera vez)"],
|
|
13571
13581
|
["--since 30d", "stats: cu\xE1nto hacia atr\xE1s (d\xEDas, default 30)"],
|
|
13572
|
-
["--repo OWNER/REPO", "stats: s\xF3lo ese repo (due\xF1o/repo)"],
|
|
13573
13582
|
["-n, --dry-run", "rename: ense\xF1a el cambio, no cambia nada"],
|
|
13574
|
-
["--yes", "rename: se salta la confirmaci\xF3n (obligatorio sin terminal)"]
|
|
13583
|
+
["--yes", "rename, approve, changes, merge: se salta la confirmaci\xF3n (obligatorio sin terminal)"]
|
|
13575
13584
|
],
|
|
13576
13585
|
notes: [
|
|
13586
|
+
"rooms connect revisa que TU instalaci\xF3n de la GitHub App vea el repo (si no, te da la liga para darle acceso) y dice qu\xE9 tan listo est\xE1 para agentes (niveles 1\u20133 y lo que falta). Cualquier miembro puede conectar; desconectar, quien lo conect\xF3 o el due\xF1o. Queda en bit\xE1cora (factory.room_connect / factory.room_disconnect).",
|
|
13587
|
+
"run publica \xAB@plan <tu texto>\xBB en el room A TU NOMBRE, como si lo escribieras en Teams: el mismo plan, firmas y tarjeta. Escr\xEDbelo como ticket: el objetivo, por qu\xE9 y c\xF3mo se sabe que qued\xF3. Cualquier miembro puede pedir, firmar, pedir cambios y mergear; todo queda en bit\xE1cora (factory.run, factory.run_approve\u2026).",
|
|
13588
|
+
"card baja la tarjeta viva del pedido al final de su hilo; la anterior queda como huella quieta con liga a la viva. Los roles tambi\xE9n pueden (factory_card).",
|
|
13577
13589
|
"Leer pide ser miembro del espacio; renombrar, ser due\xF1o, admin o staff de Ghosty, y queda en bit\xE1cora (factory.run_rename). La tarjeta del room toma el t\xEDtulo nuevo en su siguiente refresco.",
|
|
13578
13590
|
"Qui\xE9n es @plan o @build: ghosty agents ls --handle plan --workspace SLUG.",
|
|
13579
13591
|
"stats: pedidos, % mezclados, mediana de minutos hasta el PR y hasta el merge, vueltas @check\u2192@build y CI rojo por pedido, y costo por pedido y por PR mezclado. El costo incluye el primer turno de @plan en el hilo, antes de que naciera el pedido.",
|
|
13580
13592
|
"--timing lee la transcripci\xF3n de cada rol: los motores sin una (ACP) salen con minutos y costo, pero sin comandos. Tambi\xE9n lista los atascos: un comando abierto 8+ min, el mismo comando 4 veces, el mismo error 3 veces, ir y venir entre dos acciones, o apt install dentro de una caja.",
|
|
13593
|
+
"advise: con un pedido ESCALADO, qu\xE9 hacer \u2014que @build lo arregle o rehacer el plan\u2014 con la nota para @build punto por punto (cada uno cita el hallazgo o el paso del plan que lo justifica) y qu\xE9 debe revisar @check. Compara los hallazgos de @check contra el plan firmado. No aplica nada: imprime el comando exacto de approve/changes. show dice por qu\xE9 se escal\xF3.",
|
|
13581
13594
|
"why: si el pedido no fue sano (atascos, @build de m\xE1s de 30 min, vueltas, CI rojo, escalado), una categor\xEDa (missing_service, unresolved_build_or_tests, fixed_strategy\u2026), el paso cr\xEDtico con su evidencia y qu\xE9 cambiar la pr\xF3xima vez. Primero cruza los criterios del plan aprobado con la evidencia: aprobado sin la preview que ped\xEDa un criterio, mezclado sin preview, smoke rojo sobre el commit mezclado o criterio de CI con CI none \u2192 approved_unmet_criterion, arriba de cualquier atasco. Un pedido sano no llama al modelo. Cuando un pedido cierra sin ser sano, el room recibe este resumen en su hilo.",
|
|
13582
13595
|
"Mientras un rol trabaja, si se atora el room recibe un \u23F3 en el hilo y al rol se le dice qu\xE9 revisar; desde la segunda vez en el mismo pedido, quien lo pidi\xF3 recibe un push."
|
|
13583
13596
|
]
|
|
@@ -14460,8 +14473,18 @@ HELPS.audit = {
|
|
|
14460
14473
|
learn: `${REF}#bitacora`
|
|
14461
14474
|
};
|
|
14462
14475
|
HELPS.factory = {
|
|
14463
|
-
summary: "
|
|
14476
|
+
summary: "Hand requests to a workspace's Software Factory from the terminal and decide them (approve the plan, merge the PR) without opening Teams \u2014 the factory as a sidekick for your coding agent. Also its runs (they live in its Teams): list them with time and cost, see one (current plan, PR, preview, latest events, which role is working), see where its time and money went and why it got stuck or failed, totals for the workspace, and fix a run's title.",
|
|
14464
14477
|
usage: [
|
|
14478
|
+
"ghosty factory rooms ls [--full] [--workspace SLUG]",
|
|
14479
|
+
"ghosty factory rooms connect OWNER/REPO --room R [--create] [--private] [--workspace SLUG]",
|
|
14480
|
+
"ghosty factory rooms disconnect OWNER/REPO --room R [--yes]",
|
|
14481
|
+
`ghosty factory run "What, why and how we know it's done" --repo OWNER/REPO [--room R] [--wait] [--timeout 1800] [--workspace SLUG]`,
|
|
14482
|
+
"ghosty factory runs watch <run> | --thread <id> [--timeout 1800] [--workspace SLUG]",
|
|
14483
|
+
'ghosty factory runs approve <run> --plan-version N [--note "\u2026"] [--check-scope "\u2026"] [--yes]',
|
|
14484
|
+
"ghosty factory runs advise <run> [--workspace SLUG]",
|
|
14485
|
+
'ghosty factory runs changes <run> --note "\u2026" [--yes]',
|
|
14486
|
+
"ghosty factory runs merge <run> [--skip-preview] [--yes]",
|
|
14487
|
+
"ghosty factory runs card <run>",
|
|
14465
14488
|
"ghosty factory runs ls [--workspace SLUG] [--room R] [--status S] [--limit 30]",
|
|
14466
14489
|
"ghosty factory runs show <run> [--workspace SLUG] [--full]",
|
|
14467
14490
|
"ghosty factory runs show <run> --timing [--workspace SLUG]",
|
|
@@ -14471,19 +14494,28 @@ HELPS.factory = {
|
|
|
14471
14494
|
],
|
|
14472
14495
|
flags: [
|
|
14473
14496
|
["--workspace SLUG", "the workspace (default: the one from ghosty use)"],
|
|
14474
|
-
["--
|
|
14497
|
+
["--repo OWNER/REPO", "run: the repo; it goes to the room connected to it. stats: only that repo"],
|
|
14498
|
+
["--wait", "run: wait until the run needs you (plan to approve, a decision, PR to merge) or ends; prints the next command"],
|
|
14499
|
+
["--timeout S", "run --wait / watch: seconds to wait (default 1800); exit 1 when it runs out"],
|
|
14500
|
+
["--thread ID", "watch: the thread run gave you, before @plan has created the run"],
|
|
14501
|
+
["--plan-version N", "approve: the plan version you read (runs show <run> --full); a newer one is rejected"],
|
|
14502
|
+
["--note T", "changes: what to change in the plan (or why to replan after an escalation). approve after an escalation: what @build must fix"],
|
|
14503
|
+
["--check-scope T", "approve/changes: the only thing @check reviews on the next loop (runs advise proposes it); anything new goes as a note, not a finding"],
|
|
14504
|
+
["--skip-preview", "merge: merge without the preview the plan asked for (logged)"],
|
|
14505
|
+
["--create", "rooms connect: create the room if it doesn't exist"],
|
|
14506
|
+
["--private", "rooms connect --create: make the new room private (only you, then whoever you add)"],
|
|
14507
|
+
["--room R", "rooms connect/disconnect: the room (slug or name). run: that room instead of finding it by --repo. ls: only that room's runs (#slug or name)"],
|
|
14475
14508
|
["--status S", "ls: only that stage (planning, building, checking, pr_review, merged\u2026)"],
|
|
14476
14509
|
["--limit N", "ls: how many (default 30)"],
|
|
14477
|
-
["--full", "show: print the current plan"],
|
|
14510
|
+
["--full", "show: print the current plan. rooms ls: also rooms without a repo"],
|
|
14478
14511
|
["--timing", "show: each turn of each role (critic, @plan, @build, @check) with minutes, minutes in tools, model and USD; the run's clock split into working, waiting for a person (plan or PR to approve) and the rest (CI, queues); and the commands that took 60 s or more"],
|
|
14479
14512
|
["--refresh", "why: redo the analysis (it's saved the first time)"],
|
|
14480
14513
|
["--since 30d", "stats: how far back (days, default 30)"],
|
|
14481
|
-
["--repo OWNER/REPO", "stats: only that repo"],
|
|
14482
14514
|
["-n, --dry-run", "rename: show the change, change nothing"],
|
|
14483
|
-
["--yes", "rename: skip the confirmation (required without a terminal)"]
|
|
14515
|
+
["--yes", "rename, approve, changes, merge: skip the confirmation (required without a terminal)"]
|
|
14484
14516
|
],
|
|
14485
|
-
examples: ["ghosty factory runs ls --workspace business --room mailmask", "ghosty factory runs show 15 --workspace business", "ghosty factory runs show 13 --timing --workspace mercadito-verde", "ghosty factory runs why 13 --workspace mercadito-verde", "ghosty factory runs stats --since 7d --workspace mercadito-verde", 'ghosty factory runs rename 15 "Docs del CLI al d\xEDa" --workspace business --dry-run'],
|
|
14486
|
-
notes: ["Reading needs membership in the workspace; rename needs owner, admin or Ghosty staff, and is logged (factory.run_rename). The room's card picks the new title up on its next refresh.", "Who is @plan or @build: ghosty agents ls --handle plan --workspace SLUG.", "stats: runs, % merged, median minutes to PR and to merge, @check\u2192@build loops and red CI per run, and cost per run and per merged PR. The cost counts @plan's first turn in the thread, before the run existed.", "--timing reads each role's transcript: engines without one (ACP) show minutes and cost but no commands. It also lists stuck patterns: a command open 8+ min, the same command 4 times, the same error 3 times, going back and forth, or apt install inside a box.", "why: if the run wasn't healthy (stuck patterns, @build over 30 min, loops, red CI, escalated), a category (missing_service, unresolved_build_or_tests, fixed_strategy\u2026), the critical step with its evidence and what to change next time. First it checks the approved plan's criteria against the evidence: approved without the preview a criterion asked for, merged without preview, smoke failed on the merged commit, or a CI criterion with CI none \u2192 approved_unmet_criterion, above any stuck pattern. A healthy run doesn't call the model. When a run closes unhealthy, the room gets this summary in its thread.", "While a role works, if it gets stuck the room gets a \u23F3 message in the thread and the role is told what to check; from the second time in the same run, whoever asked gets a push."],
|
|
14517
|
+
examples: ["ghosty factory rooms connect blissito/ghosty-studio --room studio --create --workspace business", 'ghosty factory run "Add a COLLABORATOR role: invited by room, lands in the room, no personal agent. Done when an invite to #factory logs in straight there" --repo blissito/ghosty-studio --wait --workspace business', "ghosty factory runs approve 31 --plan-version 2 --workspace business", "ghosty factory runs watch 31 --workspace business", "ghosty factory runs merge 31 --workspace business", "ghosty factory runs ls --workspace business --room mailmask", "ghosty factory runs show 15 --workspace business", "ghosty factory runs show 13 --timing --workspace mercadito-verde", "ghosty factory runs why 13 --workspace mercadito-verde", "ghosty factory runs advise 115 --workspace business", "ghosty factory runs stats --since 7d --workspace mercadito-verde", 'ghosty factory runs rename 15 "Docs del CLI al d\xEDa" --workspace business --dry-run'],
|
|
14518
|
+
notes: ["rooms connect checks that YOUR GitHub App installation sees the repo (if not, it gives you the link to grant access) and tells you how ready the repo is for agents (levels 1\u20133 and what's missing). Any member can connect; only whoever connected it, or the owner, can disconnect. Logged as factory.room_connect / factory.room_disconnect.", "run posts \xAB@plan <your text>\xBB in the room under YOUR name, like typing it in Teams: the same plan, approvals and card. Write it like a ticket: the goal, why, and how you'll know it's done. Any member can run, approve, ask for changes and merge; each one is logged (factory.run, factory.run_approve\u2026).", "card brings the run's live card down to the bottom of its thread; the old one stays as a still footprint linking to the live one. The roles can do it too (factory_card).", "Reading needs membership in the workspace; rename needs owner, admin or Ghosty staff, and is logged (factory.run_rename). The room's card picks the new title up on its next refresh.", "Who is @plan or @build: ghosty agents ls --handle plan --workspace SLUG.", "stats: runs, % merged, median minutes to PR and to merge, @check\u2192@build loops and red CI per run, and cost per run and per merged PR. The cost counts @plan's first turn in the thread, before the run existed.", "--timing reads each role's transcript: engines without one (ACP) show minutes and cost but no commands. It also lists stuck patterns: a command open 8+ min, the same command 4 times, the same error 3 times, going back and forth, or apt install inside a box.", "why: if the run wasn't healthy (stuck patterns, @build over 30 min, loops, red CI, escalated), a category (missing_service, unresolved_build_or_tests, fixed_strategy\u2026), the critical step with its evidence and what to change next time. First it checks the approved plan's criteria against the evidence: approved without the preview a criterion asked for, merged without preview, smoke failed on the merged commit, or a CI criterion with CI none \u2192 approved_unmet_criterion, above any stuck pattern. A healthy run doesn't call the model. When a run closes unhealthy, the room gets this summary in its thread.", "advise: for an ESCALATED run, what to do \u2014 let @build fix it or redo the plan \u2014 with the note for @build point by point (each one cites the finding or plan step behind it) and what @check should review. It compares @check's findings against the signed plan. Nothing is applied: it prints the exact approve/changes command. show tells you why it was escalated.", "While a role works, if it gets stuck the room gets a \u23F3 message in the thread and the role is told what to check; from the second time in the same run, whoever asked gets a push."],
|
|
14487
14519
|
learn: `${REF}#fabrica`
|
|
14488
14520
|
};
|
|
14489
14521
|
function helpText(cmd) {
|
|
@@ -15488,11 +15520,134 @@ var money = (n) => n === null || n === void 0 ? "\u2014" : `$${n.toFixed(2)}`;
|
|
|
15488
15520
|
var mins = (n) => n === null || n === void 0 ? "\u2014" : n >= 120 ? `${(n / 60).toFixed(1)} h` : `${n} min`;
|
|
15489
15521
|
var hhmm = (iso) => new Date(iso).toLocaleTimeString("es-MX", { hour: "2-digit", minute: "2-digit", hour12: false });
|
|
15490
15522
|
var short3 = (s2) => (s2 ?? "").slice(0, 16).replace("T", " ");
|
|
15523
|
+
async function roomsCmd(ws, verb, repo, v) {
|
|
15524
|
+
const path = `/api/v2/workspaces/${enc16(ws)}/factory/rooms`;
|
|
15525
|
+
if (!verb || verb === "ls" || verb === "list") {
|
|
15526
|
+
const r2 = await api(path);
|
|
15527
|
+
const rows = r2.rooms.filter((x) => x.repos.length || v.full).map((x) => ({ room: `#${x.slug}`, repos: x.repos.join(", ") || dim("\u2014"), factory: x.factory ? lavender(t("yes", "s\xED")) : dim("\u2014"), private: x.private ? t("yes", "s\xED") : "" }));
|
|
15528
|
+
return out(
|
|
15529
|
+
r2,
|
|
15530
|
+
() => [
|
|
15531
|
+
rows.length ? table(rows, ["room", "repos", "factory", "private"]) : dim(t(`No room in ${r2.workspace} has a repo yet.`, `Ning\xFAn room de ${r2.workspace} tiene repo todav\xEDa.`)),
|
|
15532
|
+
...r2.factoryInstalled ? [] : [red(t("The Software Factory isn't installed in this workspace: rooms with repos won't get @plan/@build/@check until the owner installs it in Teams \u2192 /factory.", "La Software Factory no est\xE1 instalada en este espacio: los rooms con repo no tendr\xE1n @plan/@build/@check hasta que el due\xF1o la instale en Teams \u2192 /factory."))],
|
|
15533
|
+
dim(t(`Connect one: ghosty factory rooms connect owner/repo --room R [--create] --workspace ${r2.workspace}`, `Conecta uno: ghosty factory rooms connect due\xF1o/repo --room R [--create] --workspace ${r2.workspace}`))
|
|
15534
|
+
].join("\n")
|
|
15535
|
+
);
|
|
15536
|
+
}
|
|
15537
|
+
if (verb !== "connect" && verb !== "disconnect") throw usage(t(`Unknown rooms subcommand: ${verb}.`, `Subcomando de rooms desconocido: ${verb}.`), "ghosty factory rooms ls | connect <owner/repo> --room R [--create] [--private] | disconnect <owner/repo> --room R --yes");
|
|
15538
|
+
if (!repo) throw usage(t("Missing the repo.", "Falta el repo."), `ghosty factory rooms ${verb} owner/repo --room R --workspace ${ws}`);
|
|
15539
|
+
if (!v.room) throw usage(t("Which room?", "\xBFQu\xE9 room?"), t("Add --room NAME (with --create it's made if missing).", "Agrega --room NOMBRE (con --create se crea si no existe)."));
|
|
15540
|
+
if (verb === "disconnect") {
|
|
15541
|
+
const retry = `ghosty factory rooms disconnect ${repo} --room ${v.room} --workspace ${ws}`;
|
|
15542
|
+
requireYesIfHeadless(v.yes, retry);
|
|
15543
|
+
await confirm(t(`Disconnect ${repo} from #${v.room}?`, `\xBFDesconectar ${repo} de #${v.room}?`), { yes: v.yes, retry });
|
|
15544
|
+
const r2 = await api(path, { body: { action: "disconnect", repo, room: v.room } });
|
|
15545
|
+
return out(r2, () => `${lavender("\u2713")} ${t(`${repo} is no longer connected to #${r2.room}.`, `${repo} ya no est\xE1 conectado a #${r2.room}.`)}`);
|
|
15546
|
+
}
|
|
15547
|
+
const r = await api(path, { body: { action: "connect", repo, room: v.room, ...v.create ? { create: true } : {}, ...v.private ? { private: true } : {} } });
|
|
15548
|
+
const rd = r.readiness;
|
|
15549
|
+
return out(
|
|
15550
|
+
r,
|
|
15551
|
+
() => [
|
|
15552
|
+
`${lavender("\u2713")} ${r.created ? t(`Created #${r.room} and connected ${r.repo}`, `Cre\xE9 #${r.room} y le conect\xE9 ${r.repo}`) : t(`Connected ${r.repo} to #${r.room}`, `Conect\xE9 ${r.repo} a #${r.room}`)}`,
|
|
15553
|
+
` ${dim(r.url)}`,
|
|
15554
|
+
r.factoryInstalled ? ` ${t("factory", "f\xE1brica")}: ${lavender(t("on", "activa"))}${r.ciLabel ? dim(` \xB7 CI ${r.ciLabel}`) : ""}` : ` ${red(t("The Software Factory isn't installed in this workspace (Teams \u2192 /factory).", "La Software Factory no est\xE1 instalada en este espacio (Teams \u2192 /factory)."))}`,
|
|
15555
|
+
rd ? ` ${t("ready for agents", "listo para agentes")}: ${t("level", "nivel")} ${rd.level}/3 (${rd.passed}/${rd.total})${rd.missing.length ? dim(` \xB7 ${t("missing", "falta")}: ${rd.missing.join(", ")}`) : ""}` : "",
|
|
15556
|
+
"",
|
|
15557
|
+
dim(t(`Next: ghosty factory run "\u2026" --repo ${r.repo} --wait --workspace ${r.workspace}`, `Siguiente: ghosty factory run "\u2026" --repo ${r.repo} --wait --workspace ${r.workspace}`))
|
|
15558
|
+
].filter((l) => l !== "").join("\n")
|
|
15559
|
+
);
|
|
15560
|
+
}
|
|
15561
|
+
var sleep3 = (ms) => new Promise((ok) => setTimeout(ok, ms));
|
|
15562
|
+
var STOPS = /* @__PURE__ */ new Set(["plan_review", "escalated", "pr_review", "done", "cancelled"]);
|
|
15563
|
+
var STAGE = {
|
|
15564
|
+
planning: ["@plan is writing the plan", "@plan est\xE1 escribiendo el plan"],
|
|
15565
|
+
plan_review: ["plan ready, waiting for your approval", "plan listo, espera tu firma"],
|
|
15566
|
+
building: ["@build is building", "@build est\xE1 construyendo"],
|
|
15567
|
+
checking: ["@check is reviewing the PR", "@check est\xE1 revisando el PR"],
|
|
15568
|
+
pr_review: ["PR ready, waiting for your merge", "PR listo, espera tu merge"],
|
|
15569
|
+
escalated: ["needs a decision", "necesita una decisi\xF3n"],
|
|
15570
|
+
done: ["merged", "mergeado"],
|
|
15571
|
+
cancelled: ["cancelled", "cancelado"]
|
|
15572
|
+
};
|
|
15573
|
+
var stage = (s2) => t(...STAGE[s2] ?? [s2, s2]);
|
|
15574
|
+
function nextStep(r, ws) {
|
|
15575
|
+
const w = `--workspace ${ws}`;
|
|
15576
|
+
if (r.status === "plan_review")
|
|
15577
|
+
return t(
|
|
15578
|
+
`Read it: ghosty factory runs show ${r.id} --full ${w}
|
|
15579
|
+
Approve: ghosty factory runs approve ${r.id} --plan-version ${r.planVersion} ${w}
|
|
15580
|
+
Or ask for changes: ghosty factory runs changes ${r.id} --note "\u2026" ${w}`,
|
|
15581
|
+
`L\xE9elo: ghosty factory runs show ${r.id} --full ${w}
|
|
15582
|
+
Firma: ghosty factory runs approve ${r.id} --plan-version ${r.planVersion} ${w}
|
|
15583
|
+
O pide cambios: ghosty factory runs changes ${r.id} --note "\u2026" ${w}`
|
|
15584
|
+
);
|
|
15585
|
+
if (r.status === "escalated")
|
|
15586
|
+
return t(
|
|
15587
|
+
`Another loop: ghosty factory runs approve ${r.id} ${w}
|
|
15588
|
+
Replan: ghosty factory runs changes ${r.id} --note "\u2026" ${w}`,
|
|
15589
|
+
`Otra vuelta: ghosty factory runs approve ${r.id} ${w}
|
|
15590
|
+
Replanear: ghosty factory runs changes ${r.id} --note "\u2026" ${w}`
|
|
15591
|
+
);
|
|
15592
|
+
if (r.status === "pr_review") return t(`Merge: ghosty factory runs merge ${r.id} ${w}`, `Mergea: ghosty factory runs merge ${r.id} ${w}`);
|
|
15593
|
+
return null;
|
|
15594
|
+
}
|
|
15595
|
+
async function waitRun(base, ws, from, timeoutS) {
|
|
15596
|
+
const deadline = Date.now() + timeoutS * 1e3;
|
|
15597
|
+
let runId = from.runId ?? null;
|
|
15598
|
+
let last = "";
|
|
15599
|
+
while (Date.now() < deadline) {
|
|
15600
|
+
if (!runId && from.thread) runId = (await api(`${base}?thread=${from.thread}`)).run?.id ?? null;
|
|
15601
|
+
if (runId) {
|
|
15602
|
+
const { run } = await api(`${base}/${runId}`);
|
|
15603
|
+
if (run.status !== last && !globals.json) console.log(`${dim(hhmm((/* @__PURE__ */ new Date()).toISOString()))} #${run.id} ${stage(run.status)}`);
|
|
15604
|
+
last = run.status;
|
|
15605
|
+
if (STOPS.has(run.status)) return { run, done: true };
|
|
15606
|
+
} else if (!last && !globals.json) {
|
|
15607
|
+
console.log(`${dim(hhmm((/* @__PURE__ */ new Date()).toISOString()))} ${stage("planning")}`);
|
|
15608
|
+
last = "planning";
|
|
15609
|
+
}
|
|
15610
|
+
await sleep3(5e3);
|
|
15611
|
+
}
|
|
15612
|
+
return { run: runId ? (await api(`${base}/${runId}`)).run : null, done: false };
|
|
15613
|
+
}
|
|
15614
|
+
function waitResult(ws, r, timeoutS, url) {
|
|
15615
|
+
const step = r.run ? nextStep(r.run, ws) : null;
|
|
15616
|
+
out(
|
|
15617
|
+
{ workspace: ws, ...r, next: step },
|
|
15618
|
+
() => [
|
|
15619
|
+
r.run ? `${bold(`#${r.run.id} ${r.run.title}`)} ${dim("\xB7")} ${stage(r.run.status)}${r.run.pr ? `
|
|
15620
|
+
PR: ${r.run.pr}` : ""}` : "",
|
|
15621
|
+
r.done ? step ? `
|
|
15622
|
+
${step}` : "" : dim(t(`Timed out after ${timeoutS}s; keep watching with ghosty factory runs watch ${r.run?.id ?? "<run>"} --workspace ${ws}${url ? ` or at ${url}` : ""}`, `Pasaron ${timeoutS} s; sigue esperando con ghosty factory runs watch ${r.run?.id ?? "<pedido>"} --workspace ${ws}${url ? ` o en ${url}` : ""}`))
|
|
15623
|
+
].filter(Boolean).join("\n")
|
|
15624
|
+
);
|
|
15625
|
+
if (!r.done) process.exitCode = 1;
|
|
15626
|
+
}
|
|
15627
|
+
function timeoutOf(v) {
|
|
15628
|
+
const s2 = Number(v.timeout ?? 1800);
|
|
15629
|
+
if (!Number.isFinite(s2) || s2 <= 0) throw usage(t(`Invalid --timeout: ${v.timeout}.`, `--timeout inv\xE1lido: ${v.timeout}.`), t("Seconds, e.g. --timeout 1800", "Segundos, p. ej. --timeout 1800"));
|
|
15630
|
+
return s2;
|
|
15631
|
+
}
|
|
15491
15632
|
async function factoryCmd(sub, verb, ref, title, v, context) {
|
|
15492
|
-
if (sub !== "runs") throw usage(t(`Unknown factory subcommand: ${sub ?? "(none)"}.`, `Subcomando de factory desconocido: ${sub ?? "(ninguno)"}.`),
|
|
15633
|
+
if (sub !== "runs" && sub !== "run" && sub !== "rooms") throw usage(t(`Unknown factory subcommand: ${sub ?? "(none)"}.`, `Subcomando de factory desconocido: ${sub ?? "(ninguno)"}.`), 'ghosty factory run "\u2026" | rooms ls|connect|disconnect | runs ls|show|why|advise|stats|rename|watch|approve|changes|merge|card \u2026');
|
|
15493
15634
|
const ws = v.workspace ?? context;
|
|
15494
15635
|
if (!ws) throw usage(t("Which workspace?", "\xBFQu\xE9 espacio?"), t("Add --workspace SLUG (or set one with ghosty use SLUG).", "Agrega --workspace SLUG (o fija uno con ghosty use SLUG)."));
|
|
15636
|
+
if (sub === "rooms") return roomsCmd(ws, verb, ref, v);
|
|
15495
15637
|
const base = `/api/v2/workspaces/${enc16(ws)}/factory/runs`;
|
|
15638
|
+
if (sub === "run") {
|
|
15639
|
+
const text = verb?.trim();
|
|
15640
|
+
if (!text) throw usage(t("Missing the request.", "Falta el pedido."), `ghosty factory run "\u2026" --repo owner/name [--room R] [--wait] --workspace ${ws}`);
|
|
15641
|
+
if (!v.repo && !v.room) throw usage(t("Which repo?", "\xBFQu\xE9 repo?"), t("Add --repo owner/name (or --room R).", "Agrega --repo owner/nombre (o --room R)."));
|
|
15642
|
+
const timeoutS = timeoutOf(v);
|
|
15643
|
+
const r = await api(base, { method: "POST", body: { text, ...v.repo ? { repo: v.repo } : {}, ...v.room ? { room: v.room } : {} } });
|
|
15644
|
+
const head = `${lavender("\u2713")} ${t(`Sent to @plan in #${r.room}`, `Enviado a @plan en #${r.room}`)} ${dim(`(${t("thread", "hilo")} ${r.threadId})`)}
|
|
15645
|
+
${dim(r.url)}`;
|
|
15646
|
+
if (!v.wait) return out(r, () => `${head}
|
|
15647
|
+
${dim(t(`Wait for the plan: ghosty factory runs watch --thread ${r.threadId} --workspace ${ws}`, `Espera el plan: ghosty factory runs watch --thread ${r.threadId} --workspace ${ws}`))}`);
|
|
15648
|
+
if (!globals.json) console.log(head);
|
|
15649
|
+
return waitResult(ws, await waitRun(base, ws, { thread: r.threadId }, timeoutS), timeoutS, r.url);
|
|
15650
|
+
}
|
|
15496
15651
|
if (!verb || verb === "ls" || verb === "list") {
|
|
15497
15652
|
const qs = new URLSearchParams({ ...v.room ? { room: v.room } : {}, ...v.status ? { status: v.status } : {}, ...v.limit ? { limit: v.limit } : {} });
|
|
15498
15653
|
const r = await api(`${base}?${qs}`);
|
|
@@ -15515,6 +15670,12 @@ ${dim(`${t("Detail", "Detalle")}: ghosty factory runs show <run> --workspace ${r
|
|
|
15515
15670
|
].join("\n");
|
|
15516
15671
|
});
|
|
15517
15672
|
}
|
|
15673
|
+
if (verb === "watch") {
|
|
15674
|
+
const timeoutS = timeoutOf(v);
|
|
15675
|
+
const thread = Number(v.thread);
|
|
15676
|
+
if (!ref && !(thread > 0)) throw usage(t("Missing run.", "Falta el pedido."), `ghosty factory runs watch <run> | --thread <id> --workspace ${ws}`);
|
|
15677
|
+
return waitResult(ws, await waitRun(base, ws, ref ? { runId: Number(ref.replace(/^#/, "")) } : { thread }, timeoutS), timeoutS);
|
|
15678
|
+
}
|
|
15518
15679
|
if (!ref) throw usage(t("Missing run.", "Falta el pedido."), `ghosty factory runs ${verb} <run> --workspace ${ws}`);
|
|
15519
15680
|
const path = `${base}/${enc16(ref.replace(/^#/, ""))}`;
|
|
15520
15681
|
if (verb === "show" && v.timing) {
|
|
@@ -15567,6 +15728,26 @@ ${dim(`${t("Detail", "Detalle")}: ghosty factory runs show <run> --workspace ${r
|
|
|
15567
15728
|
].join("\n");
|
|
15568
15729
|
});
|
|
15569
15730
|
}
|
|
15731
|
+
if (verb === "advise") {
|
|
15732
|
+
const id = Number(ref.replace(/^#/, ""));
|
|
15733
|
+
const { advice: a, workspace } = await api(`${path}/advise`, { body: {} });
|
|
15734
|
+
const apply = a.decision === "fix" ? `ghosty factory runs approve ${id} --note ${JSON.stringify(a.note)}${a.checkScope ? ` --check-scope ${JSON.stringify(a.checkScope)}` : ""} --workspace ${workspace}` : `ghosty factory runs changes ${id} --note ${JSON.stringify(a.note)} --workspace ${workspace}`;
|
|
15735
|
+
return out({ workspace, advice: a, apply }, () => {
|
|
15736
|
+
const conf = { high: t("high", "alta"), medium: t("medium", "media"), low: t("low", "baja") }[a.confidence] ?? a.confidence;
|
|
15737
|
+
return [
|
|
15738
|
+
`${bold(`#${id}`)} ${bold(a.decision === "fix" ? t("Let @build fix it", "Que @build lo arregle") : t("Redo the plan", "Rehacer el plan"))} ${dim(`\xB7 ${t("confidence", "confianza")} ${conf} \xB7 ${a.model}`)}`,
|
|
15739
|
+
a.why,
|
|
15740
|
+
"",
|
|
15741
|
+
bold(a.decision === "fix" ? t("Note for @build", "Nota para @build") : t("What to change in the plan", "Qu\xE9 cambiar en el plan")),
|
|
15742
|
+
...a.buildNote.map((p, i) => ` ${i + 1}. ${p.point}
|
|
15743
|
+
${dim(p.cites)}`),
|
|
15744
|
+
...a.checkScope && a.decision === "fix" ? ["", bold(t("@check reviews only", "@check revisa s\xF3lo")), ` ${a.checkScope}`] : [],
|
|
15745
|
+
"",
|
|
15746
|
+
dim(t("Nothing was applied. To apply it (edit the note first if you want):", "No se aplic\xF3 nada. Para aplicarla (edita la nota antes si quieres):")),
|
|
15747
|
+
` ${apply}`
|
|
15748
|
+
].join("\n");
|
|
15749
|
+
});
|
|
15750
|
+
}
|
|
15570
15751
|
if (verb === "show") {
|
|
15571
15752
|
const { run: r } = await api(path);
|
|
15572
15753
|
const lines = [
|
|
@@ -15576,6 +15757,11 @@ ${dim(`${t("Detail", "Detalle")}: ghosty factory runs show <run> --workspace ${r
|
|
|
15576
15757
|
`${t("plan", "plan")}: v${r.planVersion}${r.plan ? ` ${r.plan.decision ?? t("pending", "pendiente")}${r.plan.decidedBy ? ` ${t("by", "por")} ${r.plan.decidedBy}` : ""}` : ""} \xB7 ${t("loops", "vueltas")}: ${r.loops} \xB7 ${t("requested by", "pidi\xF3")} ${r.requestedBy}`,
|
|
15577
15758
|
...r.plans.map((p) => dim(` v${p.version} ${p.decision ?? "\u2014"}: ${p.title ?? ""}`)),
|
|
15578
15759
|
`${t("running", "trabajando")}: ${r.running.length ? r.running.map((x) => `@${x.role} ${dim(`(${x.turn}, ${short3(x.since)})`)}`).join(", ") : dim(t("nobody", "nadie"))}`,
|
|
15760
|
+
...r.escalation ? [
|
|
15761
|
+
bold(red(r.escalation.blocked ? t("@check stopped it: needs something @build can't do", "@check lo fren\xF3: falta algo que @build no puede dar") : t(`@check stopped it after ${r.escalation.loops} loops`, `@check lo fren\xF3 tras ${r.escalation.loops} vueltas`))),
|
|
15762
|
+
r.escalation.findings,
|
|
15763
|
+
dim(t(`What to do: ghosty factory runs advise ${r.id} --workspace ${ws}`, `Qu\xE9 hacer: ghosty factory runs advise ${r.id} --workspace ${ws}`))
|
|
15764
|
+
] : [],
|
|
15579
15765
|
bold(t("Latest events", "\xDAltimos eventos")),
|
|
15580
15766
|
...r.events.map((e) => ` ${dim(short3(e.at))} ${e.type}${e.actor ? ` ${dim(e.actor)}` : ""}`),
|
|
15581
15767
|
...v.full && r.plan ? ["", bold(t("Current plan", "Plan vigente")), r.plan.markdown] : [dim(t("--full prints the current plan.", "--full imprime el plan vigente."))]
|
|
@@ -15594,7 +15780,31 @@ ${dim(t("Dry run: nothing changed.", "Simulacro: no se cambi\xF3 nada."))}`);
|
|
|
15594
15780
|
const r = await api(path, { body: { title } });
|
|
15595
15781
|
return out(r, () => `${lavender("\u2713")} ${line2} ${dim(t("(logged; the room card picks it up on its next refresh)", "(queda en bit\xE1cora; la tarjeta del room lo toma en su siguiente refresco)"))}`);
|
|
15596
15782
|
}
|
|
15597
|
-
|
|
15783
|
+
if (verb === "approve" || verb === "changes" || verb === "merge" || verb === "card") {
|
|
15784
|
+
const id = Number(ref.replace(/^#/, ""));
|
|
15785
|
+
const note = v.note?.trim() ?? title?.trim();
|
|
15786
|
+
const scope = verb === "approve" || verb === "changes" ? v["check-scope"]?.trim() : void 0;
|
|
15787
|
+
if (verb === "changes" && !note) throw usage(t("Say what to change.", "Di qu\xE9 cambiar."), `ghosty factory runs changes ${id} --note "\u2026" --workspace ${ws}`);
|
|
15788
|
+
const retry = `ghosty factory runs ${verb} ${id}${v["plan-version"] ? ` --plan-version ${v["plan-version"]}` : ""}${note ? ` --note ${JSON.stringify(note)}` : ""}${scope ? ` --check-scope ${JSON.stringify(scope)}` : ""} --workspace ${ws}`;
|
|
15789
|
+
if (verb !== "card") {
|
|
15790
|
+
requireYesIfHeadless(v.yes, retry);
|
|
15791
|
+
const cur = (await api(`${base}/${id}`)).run;
|
|
15792
|
+
const what = { approve: t(`Approve #${id} (plan v${cur.planVersion})`, `\xBFFirmar el #${id} (plan v${cur.planVersion})`), changes: t(`Ask for changes on #${id}`, `\xBFPedir cambios en el #${id}`), merge: t(`Merge the PR of #${id} (${cur.pr ?? "\u2014"})`, `\xBFMergear el PR del #${id} (${cur.pr ?? "\u2014"})`) }[verb];
|
|
15793
|
+
await confirm(`${what}?`, { yes: v.yes, retry });
|
|
15794
|
+
}
|
|
15795
|
+
const r = await api(`${base}/${id}/act`, {
|
|
15796
|
+
body: { action: verb, ...v["plan-version"] ? { version: Number(v["plan-version"]) } : {}, ...note ? { note } : {}, ...scope ? { checkScope: scope } : {}, ...v["skip-preview"] ? { skipPreview: true } : {} }
|
|
15797
|
+
});
|
|
15798
|
+
const msg = {
|
|
15799
|
+
approve: t(`#${id} approved: ${stage(r.status)}.`, `#${id} firmado: ${stage(r.status)}.`),
|
|
15800
|
+
changes: t(`#${id}: changes sent to @plan.`, `#${id}: cambios enviados a @plan.`),
|
|
15801
|
+
merge: r.queued ? t(`#${id}: merge queued, it goes in when CI passes.`, `#${id}: merge en cola, entra cuando pase el CI.`) : t(`#${id} merged.`, `#${id} mergeado.`),
|
|
15802
|
+
card: t(`#${id}: the card is at the bottom of its thread again.`, `#${id}: la tarjeta volvi\xF3 al final de su hilo.`)
|
|
15803
|
+
}[verb];
|
|
15804
|
+
return out(r, () => `${lavender("\u2713")} ${msg}${verb === "approve" || verb === "changes" ? `
|
|
15805
|
+
${dim(t(`Follow it: ghosty factory runs watch ${id} --workspace ${ws}`, `S\xEDguelo: ghosty factory runs watch ${id} --workspace ${ws}`))}` : ""}`);
|
|
15806
|
+
}
|
|
15807
|
+
throw usage(t(`Unknown runs subcommand: ${verb}.`, `Subcomando de runs desconocido: ${verb}.`), 'ghosty factory runs ls | show <run> [--timing] | why <run> [--refresh] | advise <run> | stats [--since 30d] | rename <run> "title" | watch <run> | approve <run> --plan-version N [--note "\u2026"] [--check-scope "\u2026"] | changes <run> --note "\u2026" | merge <run> | card <run>');
|
|
15598
15808
|
}
|
|
15599
15809
|
async function agentsByHandle(handle, workspace) {
|
|
15600
15810
|
const qs = new URLSearchParams({ handle, ...workspace ? { workspace } : {} });
|
|
@@ -15971,7 +16181,9 @@ ${bold("Workspaces")} ${dim("(changing them: Ghosty staff)")}
|
|
|
15971
16181
|
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]
|
|
15972
16182
|
settings ls|set|unset <KEY> [value] Platform switches (staff): who answers /c without an account, native subagents\u2026 [+id/-id edits a list]
|
|
15973
16183
|
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]
|
|
15974
|
-
factory
|
|
16184
|
+
factory rooms ls|connect|disconnect Set up the factory for a repo without opening Teams: create a room and connect the repo to it [connect owner/repo --room R --create]
|
|
16185
|
+
factory run "\u2026" --repo o/n [--wait] Hand a request to the Software Factory from the terminal (@plan plans, @build builds, @check reviews); --wait returns when you have to decide [runs watch|approve|changes|merge|card <run>]
|
|
16186
|
+
factory runs ls|show|why|advise|stats|rename A workspace's Software Factory runs: list (time and cost), detail (plan, PR, preview, who is working), where the time and money went, why it got stuck or failed, what to do when it's escalated, totals, fix a title [--workspace SLUG] [--room R] [--status S] [show --timing] [why --refresh] [stats --since 30d --repo R]
|
|
15975
16187
|
|
|
15976
16188
|
${bold("Agents")}
|
|
15977
16189
|
agents ls List your agents [--engine E] [--ids: only ids, for xargs] \xB7 --user EMAIL --app all|android|ios|desktop: as their app sees it (staff)
|
|
@@ -16167,7 +16379,9 @@ ${bold("Espacios")} ${dim("(cambiarlos: staff de Ghosty)")}
|
|
|
16167
16379
|
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]
|
|
16168
16380
|
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]
|
|
16169
16381
|
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]
|
|
16170
|
-
factory
|
|
16382
|
+
factory rooms ls|connect|disconnect Deja lista la f\xE1brica de un repo sin abrir Teams: crea un room y con\xE9ctale el repo [connect due\xF1o/repo --room R --create]
|
|
16383
|
+
factory run "\u2026" --repo o/n [--wait] P\xEDdele algo a la Software Factory desde la terminal (@plan planea, @build construye, @check revisa); --wait regresa cuando te toca decidir [runs watch|approve|changes|merge|card <pedido>]
|
|
16384
|
+
factory runs ls|show|why|advise|stats|rename Los pedidos de la Software Factory de un espacio: lista (tiempo y costo), detalle (plan, PR, preview, qui\xE9n trabaja), en qu\xE9 se fue el tiempo y el dinero, por qu\xE9 se ator\xF3 o fall\xF3, qu\xE9 hacer si se escal\xF3, totales, corregir un t\xEDtulo [--workspace SLUG] [--room R] [--status S] [show --timing] [why --refresh] [stats --since 30d --repo R]
|
|
16171
16385
|
|
|
16172
16386
|
${bold("Agentes")}
|
|
16173
16387
|
agents ls Lista tus agentes [--engine E] [--ids: s\xF3lo ids, para xargs] \xB7 --user CORREO --app all|android|ios|desktop: como lo ve su app (staff)
|
|
@@ -16579,6 +16793,11 @@ async function main() {
|
|
|
16579
16793
|
teams: { type: "string" },
|
|
16580
16794
|
wait: { type: "boolean" },
|
|
16581
16795
|
timeout: { type: "string" },
|
|
16796
|
+
"plan-version": { type: "string" },
|
|
16797
|
+
"check-scope": { type: "string" },
|
|
16798
|
+
thread: { type: "string" },
|
|
16799
|
+
private: { type: "boolean" },
|
|
16800
|
+
"skip-preview": { type: "boolean" },
|
|
16582
16801
|
owner: { type: "string" },
|
|
16583
16802
|
cursor: { type: "string" },
|
|
16584
16803
|
user: { type: "string" },
|
|
@@ -16626,7 +16845,7 @@ async function main() {
|
|
|
16626
16845
|
const tokens = splitTokens(pos, v);
|
|
16627
16846
|
globals.token = tokens.session;
|
|
16628
16847
|
globals.profile = v.profile;
|
|
16629
|
-
if (v.version) return out({ version: "0.
|
|
16848
|
+
if (v.version) return out({ version: "0.74.0" }, () => "0.74.0");
|
|
16630
16849
|
for (const n of normalizeArgs(pos, v)) if (!globals.json) info(dim(n));
|
|
16631
16850
|
const context = (await readConfig()).workspace;
|
|
16632
16851
|
if (!explicitToken()?.startsWith("gat_")) {
|
|
@@ -16819,7 +17038,7 @@ async function main() {
|
|
|
16819
17038
|
throw unknown(cmd, cmd, COMMANDS, "ghosty --help");
|
|
16820
17039
|
}
|
|
16821
17040
|
}
|
|
16822
|
-
var notice = updateNotice("0.
|
|
17041
|
+
var notice = updateNotice("0.74.0").catch(() => null);
|
|
16823
17042
|
main().then(
|
|
16824
17043
|
async () => {
|
|
16825
17044
|
const n = await notice;
|
package/package.json
CHANGED