Retry a failed portrait from the notice with the same scene builder.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -13,26 +13,26 @@
|
||||
|
||||
## Задачи
|
||||
|
||||
- [ ] `EventDef.action`: `none` | `generateImage`. `generateImage` без `personId` на `Notice` —
|
||||
- [x] `EventDef.action`: `none` | `generateImage`. `generateImage` без `personId` на `Notice` —
|
||||
не рисовать, не 500
|
||||
- [ ] Ваниль `GenerationFailed`: error, pause, `generateImage`. Эмит из сервиса портретов при
|
||||
- [x] Ваниль `GenerationFailed`: error, pause, `generateImage`. Эмит из сервиса портретов при
|
||||
неуспехе Swarm (тот же personId и kind). Утро и звонок остаются `none`
|
||||
- [ ] UI: на модале/тосте с action — кнопка; вызов существующего портретного HTTP (или узкого
|
||||
- [x] UI: на модале/тосте с action — кнопка; вызов существующего портретного HTTP (или узкого
|
||||
`POST .../notices/{id}/generate`, если так проще связать права). Kind по умолчанию `full`.
|
||||
Строки через `t(...)`
|
||||
- [ ] Хозяин только. Гость кнопку не активирует. Успех не снимает паузу сам — нужен dismiss
|
||||
- [ ] [`protocol.md`](../../protocol.md) — HTTP действия, тем же коммитом. Сокет не бампить
|
||||
- [x] Хозяин только. Гость кнопку не активирует. Успех не снимает паузу сам — нужен dismiss
|
||||
- [x] [`protocol.md`](../../protocol.md) — HTTP действия, тем же коммитом. Сокет не бампить
|
||||
повторно, если кадр 64 уже несёт action/personId; иначе добавить поля в том же смысле,
|
||||
что 64, без лишнего +1 если укладка уже есть
|
||||
|
||||
## Тесты, без которых фаза не закрыта
|
||||
|
||||
- [ ] Каталог: `GenerationFailed` с `generateImage`; `DayStarted` без кнопки
|
||||
- [ ] Неуспех генерации ставит pausing notice с personId; успех — не ставит
|
||||
- [ ] Хостовый: хозяин с кнопки получает PNG (или тот же outcome, что карточка); гость 403
|
||||
- [ ] Промпт этой генерации содержит сцену узла человека (как 66), не пустой коридор без людей
|
||||
- [ ] Notice без personId и с `generateImage` не дергает Swarm
|
||||
- [ ] Клиентский: кнопка есть только при action; info-тост дня кнопки не имеет
|
||||
- [x] Каталог: `GenerationFailed` с `generateImage`; `DayStarted` без кнопки
|
||||
- [x] Неуспех генерации ставит pausing notice с personId; успех — не ставит
|
||||
- [x] Хостовый: хозяин с кнопки получает PNG (или тот же outcome, что карточка); гость 403
|
||||
- [x] Промпт этой генерации содержит сцену узла человека (как 66), не пустой коридор без людей
|
||||
- [x] Notice без personId и с `generateImage` не дергает Swarm
|
||||
- [x] Клиентский: кнопка есть только при action; info-тост дня кнопки не имеет
|
||||
|
||||
## Критерий готовности
|
||||
|
||||
|
||||
+22
-4
@@ -814,6 +814,20 @@ Owner-only close of a pausing notice. `204` even when that id is already gone. G
|
||||
sticky warning/error. Socket dismiss (`0x08`) is the live intent; this HTTP route is the
|
||||
same right check for clients that are not on the socket.
|
||||
|
||||
### `POST /api/schools/{id}/notices/{noticeId}/generate`
|
||||
|
||||
Owner-only portrait from a sticky notice whose `action` is `generateImage`. Uses the same
|
||||
`GetPortraitBuildInput` assembly as the person card (scene included). Kind is the one stored
|
||||
on the notice when Swarm failed, or `full`. Success is the same `201` body as
|
||||
`POST /api/schools/{id}/people/{personId}/portrait`; Swarm down is the same `503` / `502` /
|
||||
`504`. The notice stays on the board — a PNG does not dismiss it or start the clock.
|
||||
|
||||
| Status | `code` | When |
|
||||
| --- | --- | --- |
|
||||
| `400` | `notice-cannot-generate` | No person on the notice, or action is not `generateImage`. Swarm is not called. |
|
||||
| `403` | `not-owner` | Guest. |
|
||||
| `404` | `unknown-school` / `unknown-notice` | Missing school or that id is not a sticky notice. |
|
||||
|
||||
## Dev endpoints
|
||||
|
||||
These exist only when `HSchool:AllowSaveReload` is true (headless AppHost tests). They are never
|
||||
@@ -868,9 +882,11 @@ read the `World`. Unknown `{id}` is `404` `unknown-school`.
|
||||
### `POST /api/dev/schools/{id}/notices`
|
||||
|
||||
Posts a catalog `EventDef` onto that school's board without going through Swarm. Body:
|
||||
`{ "defName": "GenerationFailed", "personId": 0 }`. Success is `{ "id", "defName", "pause" }`.
|
||||
`{ "defName": "GenerationFailed", "personId": 0, "person": "a0.p0", "kind": "full" }`.
|
||||
`person` is the roster id to put on the notice (empty/omitted = nobody in frame). `kind` is
|
||||
the portrait kind to retry (`avatar` / `custom` / `full`). Success is `{ "id", "defName", "pause" }`.
|
||||
Unknown `{id}` is `404` `unknown-school`. Unknown def or a full sticky queue is `409`
|
||||
`notice-rejected`. Tests use this; portraits emit `generationFailed` in a later phase.
|
||||
`notice-rejected`. Tests use this; a live Swarm failure posts `GenerationFailed` itself.
|
||||
|
||||
## WebSocket message ids
|
||||
|
||||
@@ -1100,8 +1116,9 @@ on this frame; the client builds «говорит с Машей о футбол
|
||||
One school event for every connection that has that school open. Not glued to the clock frame.
|
||||
Info is not written to the save and is not resent on OpenSchool. Warning/error with `pause=1`
|
||||
stop the clock, stay in the save (at most eight), and are sent again on Open. The ninth sticky
|
||||
notice is not emitted. `personId` is `0` when nobody is in frame (the generate-image button is a
|
||||
later phase).
|
||||
notice is not emitted. `personId` is `0` when nobody is in frame. `action` is the catalog value
|
||||
(`none` or `generateImage`); the generate button is owner-only HTTP, not a new socket id.
|
||||
Layout extra after the v10 personId field; protocol version stays 10.
|
||||
|
||||
| Offset | Type | Field |
|
||||
| --- | --- | --- |
|
||||
@@ -1112,6 +1129,7 @@ later phase).
|
||||
| … | `u8` | `1` pause (clocks stop until dismiss + Play), `0` clocks keep running |
|
||||
| … | `u32` | `ttlMs`; `0` stays until dismiss |
|
||||
| … | `u32` | `personId`; `0` = none |
|
||||
| … | string | `action`; `none` or `generateImage` |
|
||||
|
||||
## Guarantees and limits
|
||||
|
||||
|
||||
Reference in New Issue
Block a user