layero 0.8.17 → 0.8.19

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 CHANGED
@@ -14,7 +14,7 @@ npx layero deploy --json # ships current dir, streams JSON events to stdout
14
14
 
15
15
  `layero deploy` prints `{"event":"ready","url":"https://..."}` on success. Show the URL to the user. That's the whole job.
16
16
 
17
- **If the user has no code yet** and wants a landing page built from scratch, this CLI is the wrong tool. Layero runs a remote MCP server for that — `https://mcp.layero.ru/mcp` (Streamable HTTP), registered as `ru.layero/layero` in the official MCP registry. It builds the page from a two-or-three-question brief and deploys it. Install it with `claude plugin marketplace add LayeroInfra/layero-claude && claude plugin install layero@layero-claude`, `codex mcp add layero --url https://mcp.layero.ru/mcp --transport http`, or one click in Cursor from [land.layero.ru](https://land.layero.ru). Details: [docs.layero.ru/en/plugin/intro](https://docs.layero.ru/en/plugin/intro).
17
+ **If the user has no code yet** and wants a landing page built from scratch, this CLI is the wrong tool. Layero runs a remote MCP server for that — `https://mcp.layero.ru/mcp` (Streamable HTTP), registered as `ru.layero/layero` in the official MCP registry. It builds the page from a two-or-three-question brief and deploys it. Install it with `claude plugin marketplace add LayeroInfra/layero-claude && claude plugin install layero@layero-claude`, `codex mcp add layero --url https://mcp.layero.ru/mcp --bearer-token-env-var LAYERO_TOKEN`, or one click in Cursor from [land.layero.app](https://land.layero.app). Details: [docs.layero.ru/en/plugin/intro](https://docs.layero.ru/en/plugin/intro).
18
18
 
19
19
  ## Install
20
20
 
@@ -3,7 +3,7 @@ import chalk from "chalk";
3
3
  import { ApiClient, ApiError } from "../api.js";
4
4
  import { loadConfig } from "../config.js";
5
5
  import { loadProjectConfig } from "../project-config.js";
6
- import { detectMode } from "../agent.js";
6
+ import { detectMode, LayeroError } from "../agent.js";
7
7
  async function resolveProjectId(api, cwd, override) {
8
8
  if (override) {
9
9
  // Accept slug or id; resolve via list to keep consistent error UX.
@@ -159,6 +159,21 @@ export async function rollbackCmd(opts) {
159
159
  }
160
160
  catch (err) {
161
161
  if (err instanceof ApiError) {
162
+ // 409 «not in a rollback-eligible state» — это НЕ сбой платформы, а
163
+ // ожидаемое ограничение, и подавать его кодом `internal` (то есть
164
+ // «сообщите о проблеме») нельзя: человек читает это в момент, когда у
165
+ // него уже что-то сломалось на проде.
166
+ //
167
+ // Две причины дают один и тот же ответ API. Runtime-проекты (SSR,
168
+ // Streamlit, Gradio) не откатываются вообще: их артефакт лежит в
169
+ // реестре образов, а проверка пригодности требует s3_path. У статики
170
+ // артефакт мог быть вычищен по ретенции. Различить их здесь нечем,
171
+ // поэтому называем оба и даём общий выход — пересборку коммита.
172
+ if (err.status === 409 && err.body.includes("rollback-eligible")) {
173
+ throw new LayeroError("rollback_unsupported", "этот деплой нельзя переактивировать: у него нет раздаваемого артефакта", "runtime-проекты (SSR, Streamlit, Gradio) откатывать пока нельзя, " +
174
+ "а у статики артефакт мог быть вычищен по ретенции — " +
175
+ "пересобери нужный коммит через `layero deploy`");
176
+ }
162
177
  throw new Error(`rollback failed (${err.status}): ${err.body.slice(0, 200)}`);
163
178
  }
164
179
  throw err;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "layero",
3
- "version": "0.8.17",
3
+ "version": "0.8.19",
4
4
  "description": "Layero CLI — publish a local site with one command. No git, no GitHub, agent-friendly (Cursor, Claude Code).",
5
5
  "license": "MIT",
6
6
  "type": "module",