@easybits.cloud/cli 0.20.0 → 0.22.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 +6 -0
- package/dist/index.js +199 -9
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -54,6 +54,9 @@ easybits sandboxes bg kill sb_abc123 exec_123 # the whole process group
|
|
|
54
54
|
easybits sandboxes git clone sb_abc123 --repo https://github.com/you/app.git --dir /data/work/app --git-token '$secret:GITHUB_TOKEN'
|
|
55
55
|
easybits sandboxes git status sb_abc123 --dir /data/work/app
|
|
56
56
|
easybits sandboxes git commit sb_abc123 --dir /data/work/app --all -m "fix: checkout"
|
|
57
|
+
easybits sandboxes codex login sb_abc123 # Codex on YOUR ChatGPT plan: shows a link + code, you sign in, saved to your vault
|
|
58
|
+
easybits sandboxes codex connect sb_def456 # puts that session in another box (installs Codex if missing)
|
|
59
|
+
easybits sandboxes codex save sb_abc123 # saves the renewed session back to the vault
|
|
57
60
|
easybits sandboxes git push sb_abc123 --dir /data/work/app --git-token '$secret:GITHUB_TOKEN'
|
|
58
61
|
easybits sandboxes git pull|checkout|log sb_abc123 --dir /data/work/app …
|
|
59
62
|
easybits sandboxes suspend sb_abc123
|
|
@@ -74,6 +77,7 @@ easybits machines secrets ls sb_abc123
|
|
|
74
77
|
easybits machines secrets set sb_abc123 --dotenv .env.production # - reads stdin
|
|
75
78
|
easybits machines secrets unset sb_abc123 DATABASE_URL
|
|
76
79
|
easybits machines restart shop # restart the app with the current secrets/runspec (no build)
|
|
80
|
+
easybits machines adopt sb_abc123 --name shop-prod --unit app --import-env /app/secrets.env --dry-run # register a box that already runs; its secrets move to the vault
|
|
77
81
|
easybits machines get shop # tier, size, MXN/month, whether it sleeps
|
|
78
82
|
easybits machines tiers # the catalog: sizes and prices in MXN
|
|
79
83
|
easybits machines runspec get shop
|
|
@@ -212,6 +216,8 @@ easybits sites ls # your site-builder sites (/dash/sitios): k
|
|
|
212
216
|
easybits sites create --prompt "Landing for my dental clinic" # web app (TanStack) in its own machine
|
|
213
217
|
easybits sites create --prompt "Task tracker with login" --stack next --json
|
|
214
218
|
easybits sites create --name "Promo" --kind static # CDN website instead of a machine
|
|
219
|
+
easybits sites model my-clinic # engine + model that build it (● = current)
|
|
220
|
+
easybits sites model my-clinic claude-sonnet-5-5 # the model applies to all your sites with that engine
|
|
215
221
|
easybits sites theme get my-clinic # site by name or id
|
|
216
222
|
easybits sites theme set my-clinic --theme dracula # or --colors theme.json (every token)
|
|
217
223
|
easybits websites ls # every static website (also documents and agent-published pages)
|
package/dist/index.js
CHANGED
|
@@ -1754,6 +1754,14 @@ function printGit(op, r) {
|
|
|
1754
1754
|
async function sandboxAt(ctx, i, usage2) {
|
|
1755
1755
|
return (await getClient(ctx)).sandboxes.get(need(ctx, i, "sandbox", usage2));
|
|
1756
1756
|
}
|
|
1757
|
+
var CODEX_USAGE = "easybits sandboxes codex <login|connect|save> <sandbox> [--force] [--no-install]";
|
|
1758
|
+
function parseDeviceAuth(out) {
|
|
1759
|
+
const plain = out.replace(/\x1b\[[0-9;]*m/g, "");
|
|
1760
|
+
return {
|
|
1761
|
+
url: plain.match(/https:\/\/auth\.openai\.com\/\S+/)?.[0],
|
|
1762
|
+
code: plain.match(/\b[A-Z0-9]{4}-[A-Z0-9]{4,6}\b/)?.[0]
|
|
1763
|
+
};
|
|
1764
|
+
}
|
|
1757
1765
|
var FILES_USAGE = "easybits sandboxes files <ls|read|write|rm|mv|mkdir> <sandbox> <path> [local-file|new-path]";
|
|
1758
1766
|
var sandboxes = {
|
|
1759
1767
|
name: "sandboxes",
|
|
@@ -2066,6 +2074,89 @@ var sandboxes = {
|
|
|
2066
2074
|
}
|
|
2067
2075
|
}
|
|
2068
2076
|
},
|
|
2077
|
+
codex: {
|
|
2078
|
+
summary: "Codex on YOUR ChatGPT plan in a box: login once, then connect any box from your vault",
|
|
2079
|
+
usage: CODEX_USAGE,
|
|
2080
|
+
options: {
|
|
2081
|
+
force: { type: "boolean", description: "connect: replace the session the box already has" },
|
|
2082
|
+
"no-install": { type: "boolean", description: "connect/login: don't install Codex if it's missing" }
|
|
2083
|
+
},
|
|
2084
|
+
examples: [
|
|
2085
|
+
"easybits sb codex login sb_abc123 # shows a link + code; you sign in; the session goes to your vault",
|
|
2086
|
+
"easybits sb codex connect sb_def456 # puts that session in another box (installs Codex if missing)",
|
|
2087
|
+
"easybits sb codex save sb_abc123 # saves the box's (renewed) session back to the vault"
|
|
2088
|
+
],
|
|
2089
|
+
async run(ctx) {
|
|
2090
|
+
const action = need(ctx, 0, "login|connect|save", CODEX_USAGE);
|
|
2091
|
+
const id = need(ctx, 1, "sandbox", CODEX_USAGE);
|
|
2092
|
+
const path = `/sandboxes/${encodeURIComponent(id)}`;
|
|
2093
|
+
if (action === "connect") {
|
|
2094
|
+
const r2 = await api(ctx, "POST", `${path}/codex-connect`, {
|
|
2095
|
+
force: bool(ctx, "force"),
|
|
2096
|
+
install: !bool(ctx, "no-install")
|
|
2097
|
+
});
|
|
2098
|
+
return emit(ctx, r2, () => {
|
|
2099
|
+
console.log(
|
|
2100
|
+
r2.session === "kept" ? t("The box already had a Codex session: kept it (use --force to replace it).", "La caja ya ten\xEDa sesi\xF3n de Codex: se conserv\xF3 (usa --force para reemplazarla).") : t("Codex session from your vault is in the box.", "La sesi\xF3n de Codex de tu vault ya est\xE1 en la caja.")
|
|
2101
|
+
);
|
|
2102
|
+
if (r2.codex === "no_npm") console.log(t("Codex isn't installed and the box has no npm: use a node template.", "Codex no est\xE1 instalado y la caja no tiene npm: usa un template node."));
|
|
2103
|
+
console.log(t(`Try it: easybits sb exec ${id} -- codex exec "hola"`, `Pru\xE9balo: easybits sb exec ${id} -- codex exec "hola"`));
|
|
2104
|
+
});
|
|
2105
|
+
}
|
|
2106
|
+
if (action === "save") {
|
|
2107
|
+
const r2 = await api(ctx, "POST", `${path}/codex-save`, {});
|
|
2108
|
+
return emit(
|
|
2109
|
+
ctx,
|
|
2110
|
+
r2,
|
|
2111
|
+
() => console.log(r2.saved ? t("Saved to your vault as CODEX_AUTH.", "Guardada en tu vault como CODEX_AUTH.") : t(`Not saved: ${r2.reason}`, `No se guard\xF3: ${r2.reason}`))
|
|
2112
|
+
);
|
|
2113
|
+
}
|
|
2114
|
+
if (action !== "login") throw usageError(t(`Unknown codex action "${action}".`, `Acci\xF3n de codex desconocida "${action}".`), CODEX_USAGE);
|
|
2115
|
+
const sb = await sandboxAt(ctx, 1, CODEX_USAGE);
|
|
2116
|
+
if (!bool(ctx, "no-install")) {
|
|
2117
|
+
const i = await sb.exec("command -v codex >/dev/null 2>&1 || npm i -g @openai/codex >/dev/null 2>&1; command -v codex", { timeoutSeconds: 240 });
|
|
2118
|
+
if (!i.stdout.trim()) throw new CliError(t("Couldn't install Codex in the box (needs npm: use a node template).", "No se pudo instalar Codex en la caja (necesita npm: usa un template node)."));
|
|
2119
|
+
}
|
|
2120
|
+
const bg = await sb.execBackground("codex login --device-auth");
|
|
2121
|
+
const started = Date.now();
|
|
2122
|
+
let shown = false;
|
|
2123
|
+
for (; ; ) {
|
|
2124
|
+
await new Promise((r2) => setTimeout(r2, 2e3));
|
|
2125
|
+
const st = await sb.bgStatus(bg.execId);
|
|
2126
|
+
const { url, code } = parseDeviceAuth(`${st.stdout ?? ""}
|
|
2127
|
+
${st.stderr ?? ""}`);
|
|
2128
|
+
if (!shown && url && code) {
|
|
2129
|
+
shown = true;
|
|
2130
|
+
if (ctx.json) console.log(JSON.stringify({ url, code, expiresInMinutes: 15 }));
|
|
2131
|
+
else {
|
|
2132
|
+
console.log(t("1. Open: ", "1. Abre: ") + url);
|
|
2133
|
+
console.log(t("2. Code: ", "2. C\xF3digo: ") + code + t(" (15 min)", " (15 min)"));
|
|
2134
|
+
console.log(t("Waiting for you to sign in with your ChatGPT account\u2026", "Esperando a que inicies sesi\xF3n con tu cuenta de ChatGPT\u2026"));
|
|
2135
|
+
}
|
|
2136
|
+
}
|
|
2137
|
+
if (st.status !== "running") {
|
|
2138
|
+
if (st.exitCode !== 0) {
|
|
2139
|
+
const tail = `${st.stderr ?? ""}${st.stdout ?? ""}`.replace(/\x1b\[[0-9;]*m/g, "").trim().split("\n").slice(-3).join(" ");
|
|
2140
|
+
throw new CliError(t(`Codex login failed: ${tail}`, `El login de Codex fall\xF3: ${tail}`));
|
|
2141
|
+
}
|
|
2142
|
+
break;
|
|
2143
|
+
}
|
|
2144
|
+
if (Date.now() - started > 16 * 6e4) {
|
|
2145
|
+
await sb.bgKill(bg.execId).catch(() => void 0);
|
|
2146
|
+
throw new CliError(t("The code expired (15 min). Run it again.", "El c\xF3digo venci\xF3 (15 min). Vuelve a correrlo."));
|
|
2147
|
+
}
|
|
2148
|
+
}
|
|
2149
|
+
const r = await api(ctx, "POST", `${path}/codex-save`, {});
|
|
2150
|
+
return emit(
|
|
2151
|
+
ctx,
|
|
2152
|
+
{ signedIn: true, ...r },
|
|
2153
|
+
() => console.log(t(
|
|
2154
|
+
`Signed in. Session saved to your vault (CODEX_AUTH): connect any other box with easybits sb codex connect <sandbox>`,
|
|
2155
|
+
`Listo. Sesi\xF3n guardada en tu vault (CODEX_AUTH): conecta cualquier otra caja con easybits sb codex connect <sandbox>`
|
|
2156
|
+
))
|
|
2157
|
+
);
|
|
2158
|
+
}
|
|
2159
|
+
},
|
|
2069
2160
|
git: {
|
|
2070
2161
|
summary: "Git inside a sandbox: clone, status, commit, push, pull, checkout, log",
|
|
2071
2162
|
usage: GIT_USAGE,
|
|
@@ -2198,6 +2289,7 @@ var REF_ARGS = {
|
|
|
2198
2289
|
"db query": { index: 0, kind: "db" },
|
|
2199
2290
|
"db photos": { index: 1, kind: "db" },
|
|
2200
2291
|
"sites theme": { index: 1, kind: "site" },
|
|
2292
|
+
"sites model": { index: 0, kind: "site" },
|
|
2201
2293
|
"fleet get": { index: 0, kind: "fleet" },
|
|
2202
2294
|
"fleet capabilities": { index: 0, kind: "fleet" },
|
|
2203
2295
|
"fleet configure": { index: 0, kind: "fleet" },
|
|
@@ -2534,6 +2626,39 @@ var machines = {
|
|
|
2534
2626
|
emit(ctx, m, () => printMachine(m));
|
|
2535
2627
|
}
|
|
2536
2628
|
},
|
|
2629
|
+
adopt: {
|
|
2630
|
+
summary: "Register a box that already runs (e.g. migrated by hand) so its secrets live in the vault",
|
|
2631
|
+
usage: "easybits machines adopt <sandbox-id> --name <name> [--unit <unit>] [--import-env <path-in-box>] [--tier <tier>] [--dry-run]",
|
|
2632
|
+
options: {
|
|
2633
|
+
name: { type: "string", value: "name", description: "Label for the machine" },
|
|
2634
|
+
unit: { type: "string", value: "unit", description: "systemd unit that `machines restart` restarts" },
|
|
2635
|
+
"import-env": { type: "string", value: "path", description: "dotenv file INSIDE the box to copy into the vault (values never leave the server)" },
|
|
2636
|
+
tier: { type: "string", value: "tier", description: "Tier to show for it (default: the host's, or mini)" },
|
|
2637
|
+
"dry-run": { type: "boolean", description: "Show what would happen without writing anything" }
|
|
2638
|
+
},
|
|
2639
|
+
examples: [
|
|
2640
|
+
"easybits machines adopt sb_abc123 --name shop-prod --unit app --import-env /app/secrets.env --dry-run",
|
|
2641
|
+
"easybits machines adopt sb_abc123 --name shop-prod --unit app --import-env /app/secrets.env"
|
|
2642
|
+
],
|
|
2643
|
+
async run(ctx) {
|
|
2644
|
+
const id = need(ctx, 0, "sandbox-id", this.usage);
|
|
2645
|
+
const name = str(ctx, "name");
|
|
2646
|
+
if (!name) throw usageError(t("Give --name <name>.", "Pasa --name <nombre>."), this.usage);
|
|
2647
|
+
const dryRun = bool(ctx, "dry-run");
|
|
2648
|
+
const r = await api(
|
|
2649
|
+
ctx,
|
|
2650
|
+
"POST",
|
|
2651
|
+
"/machines/adopt",
|
|
2652
|
+
{ sandboxId: id, name, unit: str(ctx, "unit"), importEnvFrom: str(ctx, "import-env"), tier: str(ctx, "tier"), dryRun }
|
|
2653
|
+
);
|
|
2654
|
+
emit(ctx, r, () => {
|
|
2655
|
+
console.log(
|
|
2656
|
+
r.dryRun ? t(`Would adopt ${r.sandboxId} as ${r.name} (${r.tier}). Nothing was written.`, `Adoptar\xEDa ${r.sandboxId} como ${r.name} (${r.tier}). No se escribi\xF3 nada.`) : t(`Adopted ${r.sandboxId} as ${r.name}. EasyBits keeps its secrets and restarts it; it never redeploys or releases it.`, `Adoptada ${r.sandboxId} como ${r.name}. EasyBits guarda sus secretos y la reinicia; nunca la redespliega ni la libera.`)
|
|
2657
|
+
);
|
|
2658
|
+
if (r.imported.length) console.log(`${t("Secrets", "Secretos")}: ${r.imported.join(", ")}`);
|
|
2659
|
+
});
|
|
2660
|
+
}
|
|
2661
|
+
},
|
|
2537
2662
|
restart: {
|
|
2538
2663
|
summary: "Restart the app's process with the current secrets and runspec (seconds, no build)",
|
|
2539
2664
|
usage: "easybits machines restart <machine>",
|
|
@@ -2705,7 +2830,10 @@ var machines = {
|
|
|
2705
2830
|
secrets: {
|
|
2706
2831
|
summary: "App env vars stored encrypted in your vault",
|
|
2707
2832
|
usage: SECRETS_USAGE,
|
|
2708
|
-
options: {
|
|
2833
|
+
options: {
|
|
2834
|
+
...ENV_FILE_OPTION,
|
|
2835
|
+
"no-restart": { type: "boolean", description: "Store them without restarting the app (apply later with machines restart)" }
|
|
2836
|
+
},
|
|
2709
2837
|
examples: [
|
|
2710
2838
|
"easybits machines secrets ls sb_abc123",
|
|
2711
2839
|
"easybits machines secrets set sb_abc123 --dotenv .env.production",
|
|
@@ -2726,7 +2854,7 @@ var machines = {
|
|
|
2726
2854
|
const file = str(ctx, "dotenv");
|
|
2727
2855
|
const values = { ...file ? await readEnvFile(file, SECRETS_USAGE) : {}, ...pairs(ctx.args.slice(2), SECRETS_USAGE) };
|
|
2728
2856
|
if (!Object.keys(values).length) throw usageError(t("Give --dotenv <path> (or - for stdin).", "Pasa --dotenv <ruta> (o - para stdin)."), SECRETS_USAGE);
|
|
2729
|
-
const r = await eb.machines.setSecrets(id, values);
|
|
2857
|
+
const r = bool(ctx, "no-restart") ? await api(ctx, "PUT", `/machines/${encodeURIComponent(id)}/secrets?restart=false`, values) : await eb.machines.setSecrets(id, values);
|
|
2730
2858
|
emit(ctx, r, () => console.log(t(`Set ${Object.keys(values).join(", ")}. Injected now: ${r.secretNames.join(", ")}`, `Guardados ${Object.keys(values).join(", ")}. Inyectados ahora: ${r.secretNames.join(", ")}`)));
|
|
2731
2859
|
} else if (action === "unset") {
|
|
2732
2860
|
const name = need(ctx, 2, "NAME", SECRETS_USAGE);
|
|
@@ -2773,9 +2901,10 @@ function createBody(o, usage2) {
|
|
|
2773
2901
|
}
|
|
2774
2902
|
if (!o.prompt && !o.name) throw usageError(t("Give --prompt (what to build) or --name.", "Pasa --prompt (qu\xE9 construir) o --name."), usage2);
|
|
2775
2903
|
const body = { kind };
|
|
2776
|
-
for (const k of ["prompt", "name", "stack", "template"]) if (o[k]) body[k] = o[k];
|
|
2904
|
+
for (const k of ["prompt", "name", "stack", "template", "engine", "model"]) if (o[k]) body[k] = o[k];
|
|
2777
2905
|
return body;
|
|
2778
2906
|
}
|
|
2907
|
+
var MODEL_USAGE = "easybits sites model <site> [<model>] [--engine <id>] [--key <value>]";
|
|
2779
2908
|
var THEME_USAGE = "easybits sites theme <get|set> <site> [--theme <id> | --colors <file.json|->]";
|
|
2780
2909
|
async function readColors(path) {
|
|
2781
2910
|
let text;
|
|
@@ -2798,7 +2927,7 @@ var sites = {
|
|
|
2798
2927
|
aliases: ["site"],
|
|
2799
2928
|
group: "Hosting",
|
|
2800
2929
|
summary: "Your site-builder sites (/dash/sitios): static and web apps",
|
|
2801
|
-
synopsis: "sites <ls|create|theme>",
|
|
2930
|
+
synopsis: "sites <ls|create|model|theme>",
|
|
2802
2931
|
subs: {
|
|
2803
2932
|
ls: {
|
|
2804
2933
|
aliases: ["list"],
|
|
@@ -2821,13 +2950,15 @@ var sites = {
|
|
|
2821
2950
|
create: {
|
|
2822
2951
|
aliases: ["new"],
|
|
2823
2952
|
summary: "Create a site from a prompt; its builder agent picks it up in the editor",
|
|
2824
|
-
usage: "easybits sites create (--prompt <text> | --name <name>) [--kind webapp|static] [--stack <stack>] [--template <key>]",
|
|
2953
|
+
usage: "easybits sites create (--prompt <text> | --name <name>) [--kind webapp|static] [--stack <stack>] [--template <key>] [--engine <id>] [--model <id>]",
|
|
2825
2954
|
options: {
|
|
2826
2955
|
prompt: { type: "string", value: "text", description: "What to build; also names the site if --name is missing" },
|
|
2827
2956
|
name: { type: "string", value: "name", description: "Site name" },
|
|
2828
2957
|
kind: { type: "string", value: "kind", description: "webapp (default: its own machine, published later) or static (CDN website)" },
|
|
2829
2958
|
stack: { type: "string", value: "stack", description: "Web app stack: tanstack (default), next, react-router, remix, nuxt, sveltekit, astro, elysia" },
|
|
2830
|
-
template: { type: "string", value: "key", description: "Starting template (tanstack/react-router): consultorio, despacho, portafolio, lanzamiento" }
|
|
2959
|
+
template: { type: "string", value: "key", description: "Starting template (tanstack/react-router): consultorio, despacho, portafolio, lanzamiento" },
|
|
2960
|
+
engine: { type: "string", value: "id", description: "What builds it: claude (your Claude), easybits (included)\u2026 see sites model" },
|
|
2961
|
+
model: { type: "string", value: "id", description: "Model of that engine; applies to all your sites with that engine" }
|
|
2831
2962
|
},
|
|
2832
2963
|
examples: [
|
|
2833
2964
|
'easybits sites create --prompt "Landing for my dental clinic in Puebla"',
|
|
@@ -2836,7 +2967,7 @@ var sites = {
|
|
|
2836
2967
|
],
|
|
2837
2968
|
async run(ctx) {
|
|
2838
2969
|
const body = createBody(
|
|
2839
|
-
{ prompt: str(ctx, "prompt"), name: str(ctx, "name"), kind: str(ctx, "kind"), stack: str(ctx, "stack"), template: str(ctx, "template") },
|
|
2970
|
+
{ prompt: str(ctx, "prompt"), name: str(ctx, "name"), kind: str(ctx, "kind"), stack: str(ctx, "stack"), template: str(ctx, "template"), engine: str(ctx, "engine"), model: str(ctx, "model") },
|
|
2840
2971
|
this.usage
|
|
2841
2972
|
);
|
|
2842
2973
|
const site = await api(ctx, "POST", "/sites", body);
|
|
@@ -2851,6 +2982,46 @@ var sites = {
|
|
|
2851
2982
|
});
|
|
2852
2983
|
}
|
|
2853
2984
|
},
|
|
2985
|
+
model: {
|
|
2986
|
+
aliases: ["engine"],
|
|
2987
|
+
summary: "See or change what builds a site: engine and model (the model applies to all your sites with that engine)",
|
|
2988
|
+
usage: MODEL_USAGE,
|
|
2989
|
+
options: {
|
|
2990
|
+
engine: { type: "string", value: "id", description: "Switch the site to this engine" },
|
|
2991
|
+
key: { type: "string", value: "value", description: "The engine's key, if your account doesn't have it yet" }
|
|
2992
|
+
},
|
|
2993
|
+
examples: [
|
|
2994
|
+
"easybits sites model my-shop # engines, models and the current one",
|
|
2995
|
+
"easybits sites model my-shop claude-sonnet-5-5",
|
|
2996
|
+
"easybits sites model my-shop --engine easybits"
|
|
2997
|
+
],
|
|
2998
|
+
async run(ctx) {
|
|
2999
|
+
const id = need(ctx, 0, "site", MODEL_USAGE);
|
|
3000
|
+
const model = ctx.args[1];
|
|
3001
|
+
const engine = str(ctx, "engine");
|
|
3002
|
+
if (!model && !engine) {
|
|
3003
|
+
const [{ items }, { items: mine }] = await Promise.all([
|
|
3004
|
+
api(ctx, "GET", "/sites/engines"),
|
|
3005
|
+
api(ctx, "GET", "/sites")
|
|
3006
|
+
]);
|
|
3007
|
+
const site = mine.find((s) => s.id === id);
|
|
3008
|
+
emit(ctx, { site: site ? { id: site.id, engine: site.engine } : null, engines: items }, () => {
|
|
3009
|
+
if (site) console.log(t(`${site.name} builds with: ${site.engine}`, `${site.name} se construye con: ${site.engine}`));
|
|
3010
|
+
table(
|
|
3011
|
+
items.flatMap((e) => e.models.map((m) => ({ engine: e.id, model: m.id, label: m.label, now: m.id === e.currentModel ? "\u25CF" : "", key: e.needsSecret ? t("needs key", "pide llave") : "" }))),
|
|
3012
|
+
[["engine", "ENGINE"], ["model", "MODEL"], ["label", "LABEL"], ["now", "NOW"], ["key", "KEY"]]
|
|
3013
|
+
);
|
|
3014
|
+
});
|
|
3015
|
+
return;
|
|
3016
|
+
}
|
|
3017
|
+
const r = await api(ctx, "POST", `/sites/${encodeURIComponent(id)}/engine`, {
|
|
3018
|
+
...engine ? { engine } : {},
|
|
3019
|
+
...model ? { model } : {},
|
|
3020
|
+
...str(ctx, "key") ? { secretValue: str(ctx, "key") } : {}
|
|
3021
|
+
});
|
|
3022
|
+
emit(ctx, r, () => console.log(t(`Now builds with ${r.label} \xB7 ${r.model ?? "default"} (from the next message, on all your ${r.label} sites).`, `Ahora construye con ${r.label} \xB7 ${r.model ?? "default"} (desde el siguiente mensaje, en todos tus sitios con ${r.label}).`)));
|
|
3023
|
+
}
|
|
3024
|
+
},
|
|
2854
3025
|
theme: {
|
|
2855
3026
|
summary: "Read or change a site's color theme without a model turn (the \xABTema\xBB button)",
|
|
2856
3027
|
usage: THEME_USAGE,
|
|
@@ -4940,7 +5111,7 @@ async function updateNotice(current2) {
|
|
|
4940
5111
|
}
|
|
4941
5112
|
|
|
4942
5113
|
// src/commands/doctor.ts
|
|
4943
|
-
var VERSION = true ? "0.
|
|
5114
|
+
var VERSION = true ? "0.22.0" : "dev";
|
|
4944
5115
|
var doctor2 = {
|
|
4945
5116
|
name: "doctor",
|
|
4946
5117
|
group: "Account",
|
|
@@ -7280,12 +7451,25 @@ var HELP_ES = {
|
|
|
7280
7451
|
"webapp (default: its own machine, published later) or static (CDN website)": "webapp (default: su propia m\xE1quina, se publica despu\xE9s) o static (website en el CDN)",
|
|
7281
7452
|
"Web app stack: tanstack (default), next, react-router, remix, nuxt, sveltekit, astro, elysia": "Stack de la web app: tanstack (default), next, react-router, remix, nuxt, sveltekit, astro, elysia",
|
|
7282
7453
|
"Starting template (tanstack/react-router): consultorio, despacho, portafolio, lanzamiento": "Plantilla de partida (tanstack/react-router): consultorio, despacho, portafolio, lanzamiento",
|
|
7454
|
+
"What builds it: claude (your Claude), easybits (included)\u2026 see sites model": "Qu\xE9 lo construye: claude (tu Claude), easybits (incluido)\u2026 ver sites model",
|
|
7455
|
+
"Model of that engine; applies to all your sites with that engine": "Modelo de ese motor; vale para todos tus sitios con ese motor",
|
|
7456
|
+
"See or change what builds a site: engine and model (the model applies to all your sites with that engine)": "Ve o cambia qu\xE9 construye un sitio: motor y modelo (el modelo vale para todos tus sitios con ese motor)",
|
|
7457
|
+
"Switch the site to this engine": "Cambia el sitio a este motor",
|
|
7458
|
+
"The engine's key, if your account doesn't have it yet": "La llave del motor, si tu cuenta todav\xEDa no la tiene",
|
|
7459
|
+
"engines, models and the current one": "motores, modelos y el actual",
|
|
7283
7460
|
"Read or change a site's color theme without a model turn (the \xABTema\xBB button)": "Lee o cambia el tema de colores de un sitio sin turno del modelo (el bot\xF3n \xABTema\xBB)",
|
|
7284
7461
|
"Palette id: minimal, calido, oceano, noche, dracula, nord, tokyo-night, github-light\u2026": "Id de la paleta: minimal, calido, oceano, noche, dracula, nord, tokyo-night, github-light\u2026",
|
|
7285
7462
|
"JSON with every token as #rrggbb (- reads stdin)": "JSON con cada token en #rrggbb (- lee stdin)",
|
|
7286
7463
|
"edit, then:": "ed\xEDtalo y luego:",
|
|
7287
7464
|
// machines get/restart/redeploy/backups/backup/runspec/rm/tiers
|
|
7288
7465
|
"Show a machine: tier, size, price, status and whether it sleeps": "Muestra una m\xE1quina: tier, tama\xF1o, precio, estado y si duerme",
|
|
7466
|
+
"Register a box that already runs (e.g. migrated by hand) so its secrets live in the vault": "Registra una caja que ya corre (p. ej. migrada a mano) para que sus secretos vivan en el vault",
|
|
7467
|
+
"Label for the machine": "Etiqueta de la m\xE1quina",
|
|
7468
|
+
"systemd unit that `machines restart` restarts": "Unit de systemd que reinicia `machines restart`",
|
|
7469
|
+
"dotenv file INSIDE the box to copy into the vault (values never leave the server)": "Archivo dotenv DENTRO de la caja que se copia al vault (los valores no salen del servidor)",
|
|
7470
|
+
"Tier to show for it (default: the host's, or mini)": "Tier con que se muestra (default: el del host, o mini)",
|
|
7471
|
+
"Show what would happen without writing anything": "Muestra qu\xE9 har\xEDa sin escribir nada",
|
|
7472
|
+
"Store them without restarting the app (apply later with machines restart)": "Los guarda sin reiniciar la app (apl\xEDcalos despu\xE9s con machines restart)",
|
|
7289
7473
|
"Restart the app's process with the current secrets and runspec (seconds, no build)": "Reinicia el proceso de la app con los secretos y el runspec actuales (segundos, sin build)",
|
|
7290
7474
|
"Build a NEW machine from a release: recover a lost one, or change its tier (resize)": "Construye una m\xE1quina NUEVA desde un release: recupera una perdida o cambia su tier (resize)",
|
|
7291
7475
|
"Release to build from (default: the machine's newest)": "Release de d\xF3nde construir (default: el m\xE1s nuevo de la m\xE1quina)",
|
|
@@ -7377,6 +7561,12 @@ var HELP_ES = {
|
|
|
7377
7561
|
"Long-running processes: start one in the background, list, poll its output, kill it": "Procesos largos: arranca uno en segundo plano, enl\xEDstalos, lee su salida, detenlo",
|
|
7378
7562
|
"kill: seconds between SIGTERM and SIGKILL (default 5)": "kill: segundos entre SIGTERM y SIGKILL (default 5)",
|
|
7379
7563
|
"status, exit code, stdout/stderr": "estado, c\xF3digo de salida, stdout/stderr",
|
|
7564
|
+
"Codex on YOUR ChatGPT plan in a box: login once, then connect any box from your vault": "Codex con TU plan de ChatGPT en una caja: inicia sesi\xF3n una vez y conecta cualquier caja desde tu vault",
|
|
7565
|
+
"connect: replace the session the box already has": "connect: reemplaza la sesi\xF3n que ya tenga la caja",
|
|
7566
|
+
"shows a link + code; you sign in; the session goes to your vault": "muestra un link y un c\xF3digo; inicias sesi\xF3n; la sesi\xF3n se guarda en tu vault",
|
|
7567
|
+
"puts that session in another box (installs Codex if missing)": "pone esa sesi\xF3n en otra caja (instala Codex si falta)",
|
|
7568
|
+
"saves the box's (renewed) session back to the vault": "devuelve al vault la sesi\xF3n (renovada) de la caja",
|
|
7569
|
+
"connect/login: don't install Codex if it's missing": "connect/login: no instalar Codex si falta",
|
|
7380
7570
|
"Git inside a sandbox: clone, status, commit, push, pull, checkout, log": "Git dentro de un sandbox: clone, status, commit, push, pull, checkout, log",
|
|
7381
7571
|
"Repo folder inside the sandbox (required)": "Carpeta del repo dentro del sandbox (obligatoria)",
|
|
7382
7572
|
"clone: repo URL (clean; the token goes in --git-token)": "clone: URL del repo (limpia; el token va en --git-token)",
|
|
@@ -7680,7 +7870,7 @@ function normalizeArgs(input) {
|
|
|
7680
7870
|
}
|
|
7681
7871
|
|
|
7682
7872
|
// src/index.ts
|
|
7683
|
-
var VERSION2 = true ? "0.
|
|
7873
|
+
var VERSION2 = true ? "0.22.0" : "dev";
|
|
7684
7874
|
var GLOBAL_OPTIONS = {
|
|
7685
7875
|
json: { type: "boolean" },
|
|
7686
7876
|
token: { type: "string" },
|
package/package.json
CHANGED