y83 code / инструмент

Prompts

Библиотека заготовок промптов — текстов задач на один ход с полями. Каждая заготовка отвечает на два вопроса, заданных в AGENTS.md:

раздел реестра
AI и агенты
код
1 247 строк в 4 файлах
документ
14-prompts.md
Раздел: AI & Agents
Идентификатор: prompts · Экран: ui/prompts/ (PromptsScreen, PromptsViewModel, PromptFormScreen)
Снимок: 2026-10-11

1. Зачем и что это

  • Done when — критерий готовности, обязательные поля;
  • Контекст — что именно нужно сделать.

Заготовка — не шаблон копипасты, а структурированный объект с валидацией: пока обязательное поле не заполнено, вставка в чат заблокирована.

Библиотека — файл на backend ~/.y83-ws/prompts.json. Локальной копии в приложении нет намеренно: экран показывает ошибку и кнопку «Обновить», если бэкенд недоступен. Тот же файл правят MCP-инструменты prompt_list / prompt_get / prompt_save.

Смысловая граница проекта: всегда применимое правило живёт в AGENTS.md, процедура — в скилле, формулировка задачи — в заготовке (docs/tech/prompts-library.md).

2. Как попасть

Хаб инструментов → секция AI & Agents → карточка «Prompts».

Откуда ещёПуть
Меню треда Codexменю композера → «Prompts…» (сразу после «Skills…»)
Чатта же точка входа композера
Хаб (второй путь)AI & Agents → Prompts — из хаба кнопка копирует текст в буфер

Разница поведения зафиксирована в AGENTS.md: из чата кнопка вставляет текст в поле ввода (экран закрывается), из хаба — копирует в буфер обмена.

Откуда ещёПуть
Мостapp_navigate с screen: "prompts"

3. Экран: элементы и действия

Список (PromptsScreen.kt, 400+ строк)

ЭлементЧто делаетГде в коде
Иконка поискаПоказывает поле «Поиск заготовок»searchOpen
Иконка AddНовая заготовкаPromptFormScreen(editing = false)
Иконка MoreVertМеню: обновить, копировать JSON, импорт из буфераActionMenu
Поле поискаФильтр по названию/тегам/телуOutlinedTextField
Ряд чипов теговФильтр по тегу, первый чип — «все»LazyRow + SelectChip
Секция «Встроенные»Заготовки с builtin = trueprompts_built_in
Строка заготовкиЗвезда ★ у закреплённых, название, строка-превью, счётчик N×, стрелкаPromptRow
Полоса статусаСообщения сохранения/ошибки, закреплена под шапкойToggleStatusStrip
Карточка ошибкиТекст ошибки бэкенда + «Обновить»PromptsErrorCard

Форма (PromptFormScreen.kt)

Два режима — «Заполнить» и «Правка».

ЭлементЧто делает
Поля формыПо одному на каждое fields; обязательные помечены required
ПредпросмотрЖивой рендер renderPrompt с числом символов в заголовке секции
Строка «Заполни: …»Список незаполненных обязательных полей
Кнопка «Вставить в чат» / «Копировать»Переключается в зависимости от готовности
Поле «Название»Только в режиме правки
Поле «Теги через запятую»Только в режиме правки
Поле «Тело (цель, контекст, ограничения, done when)»Только в режиме правки
Секция «Поля» + «Добавить поле»Список редакторов полей
Кнопки «Создать» / «Сохранить», «Дублировать», «Удалить»Только в режиме правки
Карточка «Не сохранено»Список проблем валидации (ProblemsCard)
Диалог удаленияПодтверждение с предупреждением, что заготовку можно вернуть

Редактор поля (FieldEditor): ключ, подпись, значение по умолчанию, чекбоксы required и multiline, кнопка удаления поля.

4. Возможности подробно

Структура заготовки

PromptItemDto (data/api/PromptDtos.kt:21):

ПолеСмысл
idстабильный идентификатор (латиница)
titleназвание
tagsсписок тегов, по ним фильтр
iconимя иконочной строки
pinnedзакрепление, в списке ★
orderпорядок в списке
usesсчётчик использований, в списке N×
lastUsedAtвремя последнего использования
fieldsполя подстановки
bodyтекст с плейсхолдерами {{ключ}}
builtinвстроенная заготовка

Плейсхолдеры и зарезервированные ключи

Плейсхолдер — {{ключ}}, регексп \{\{([a-z0-9_]+)\}\}. Зарезервированные ключи PromptsRules.RESERVED = ["project", "thread", "model"] подставляет приложение из контекста треда — объявлять их как поля нельзя, но использовать в теле можно.

Рендер и пропуск строк

renderPrompt(item, args) собирает готовый текст:

  1. для каждого поля берётся значение из аргументов, при пустом — default;
  2. обязательное поле с пустым значением попадает в missing;
  3. зарезервированные ключи берутся из аргументов напрямую;
  4. построчная подстановка, и сверх того убираются «дыры»:
  • строка с плейсхолдером, которая после подстановки пуста, выбрасывается;
    • строка, где после подстановки осталось только «Метка:» (подстановка с пустыми значениями совпала с результатом и кончается двоеточием), тоже выбрасывается — незаполненное необязательное поле не должно оставлять хвост;
    • лишние пустые строки не дублируются;
  1. результат — PromptRender(text, missing), ready = missing.isEmpty().

Именно ready решает судьбу главной кнопки: пока есть незаполненные обязательные поля, доступна «Копировать», а не «Вставить в чат».

Валидация (зеркало бэкенда)

promptProblems(doc) возвращает список проблем до отправки — чтобы не ждать 400 от сервера. Формулировки совпадают с бэкендом (backend/internal/prompts). Проверяется:

ПравилоЗначение
MAX_ITEMS200 заготовок на документ
MAX_FIELDS12 полей на заготовку
MAX_BODY_BYTES8000 байт тела
MAX_TITLE_CHARS80 символов названия
id^[a-z0-9][a-z0-9_-]{0,47}$, уникальный, без пробелов
ключ поля^[a-z][a-z0-9_]{0,31}$, уникальный, не зарезервирован
плейсхолдер в телеобъявлен как поле или зарезервирован
обязательное полевстречается в теле
подпись поляне пустая

Счётчик использований

markUsed(id) сначала увеличивает uses локально (мгновенно), потом шлёт markUsed(id) в фон. Это сделано, чтобы вставка текста не ждала сеть — закоммитить вставку важнее, чем обновить счётчик.

Дубликат

duplicateItem берёт id из заголовка с суффиксом «(копия)» через promptSlug(title, taken) (латиница из заголовка, максимум 40 символов, при занятости — -2, -3…), обнуляет uses, снимает закрепление.

Встроенные заготовки

restoreBuiltins() вызывает POST /api/v1/prompts/seed — возвращает в файл встроенные заготовки, которых там нет. Ключевая деталь: правки существующих заготовок не затираются, добавляются только отсутствующие. Если все уже на месте, приходит сообщение «все встроенные уже на месте».

Импорт и экспорт

Через меню «Ещё»:

  • Копировать JSON — весь документ в буфер обмена;
  • Импорт из буфера — читает буфер, парсит как PromptDocDto и заменяет библиотеку целиком (не дополняет). Пустой буфер — предупреждение, не JSON — ошибка, валидный документ с проблемами — показывается первая проблема.

5. Данные: БД, файлы, настройки

ЧтоГде лежитКак меняетсяКто читает
Библиотека~/.y83-ws/prompts.json (backend)PUT /api/v1/promptsэкран, prompt_get, композер чата
Встроенные заготовкиКод backend/internal/prompts/builtin.goPOST /api/v1/prompts/seedМатериализуются в файл один раз

Локального кэша и Room-таблицы нет. Backend при старте, если файла нет, заводит встроенные заготовки сам (NewService: «при отсутствии — заводит встроенные»).

6. Backend: REST/роуты

Метод и путьНазначениеОбработчик
GET /api/v1/promptsвесь документprmH.Doc
PUT /api/v1/promptsсохранить документ (с валидацией)prmH.Doc
POST /api/v1/prompts/seedдобавить встроенные заготовкиprmH.Seed
POST /api/v1/prompts/{id}/usedувеличить счётчик использованияprmH.Used

Роуты: backend/internal/api/v1/routes.go:162–165. Логика и валидация — backend/internal/prompts/prompts.go (DefaultPath → ~/.y83-ws/prompts.json).

7. Мост и MCP

ИнструментЧто делает
prompt_list {q, tag}список заготовок с id, заголовком, тегами, полями
prompt_get {id, args}подставить значения в текст; возвращает missing для незаполненных обязательных полей
prompt_save {title, body, fields, id, tags, icon, order, pinned}создать или изменить; валидация на сервере

Метод prompt_get сознательно не генерирует id: незаполненные обязательные поля возвращаются как missing, заполненные — уже в text. Агент может дописать значения сам.

8. Настройки, конфиг, квоты и лимиты

ПараметрЗначениеГде задаётся
Максимум заготовок200PromptsRules.MAX_ITEMS
Максимум полей12PromptsRules.MAX_FIELDS
Максимум тела8000 байтPromptsRules.MAX_BODY_BYTES
Максимум названия80 символовPromptsRules.MAX_TITLE_CHARS
Зарезервированные ключиproject, thread, modelPromptsRules.RESERVED
Длина idдо 48 символовPromptsRules.ID

9. Ловушки и ограничения

  • Импорт заменяет библиотеку целиком. Это не слияние: если в буфере лежит документ из трёх заготовок, после импорта в библиотеке останутся только они.
  • Валидация дублируется на клиенте и сервере. Правила держатся синхронно, но при правке одной стороны вторая об этом не узнает — появится расхождение в формулировке ошибки, а не в её сути.
  • Экран бесполезен без бэкенда. Локальной копии нет намеренно, поэтому при недоступном backend вы увидите только карточку ошибки с кнопкой «Обновить».
  • Счётчик использований обновляется в фоне. Если сеть отвалилась сразу после вставки, uses в файле не вырастет — но в UI уже показан.
  • prompt_get не генерирует значения. Обязательные поля остаются незаполненными, это ожидаемое поведение, а не ошибка.
  • Зарезервированные ключи нельзя объявлять полями, но можно использовать в теле — они подставятся из контекста треда.
  • Название важнее тела для id. promptSlug строит id из латиницы заголовка; русское название без латиницы даст prompt-N.
  • Правки встроенных заготовок стираются? Нет: seed добавляет только отсутствующие, существующие не трогает. Но это не значит, что изменения переживут обновление приложения, если backend их не переживёт — файл один.

10. Источники правды

  • app/src/main/java/com/y83/ws/ui/prompts/PromptsScreen.kt — список, поиск, теги, меню.
  • app/src/main/java/com/y83/ws/ui/prompts/PromptFormScreen.kt — режимы правки и заполнения.
  • app/src/main/java/com/y83/ws/ui/prompts/PromptsViewModel.kt — сохранение, seed, импорт, счётчик.
  • app/src/main/java/com/y83/ws/data/prompts/PromptsRender.kt — рендер, валидация, slug.
  • app/src/main/java/com/y83/ws/data/api/PromptDtos.kt — DTO.
  • app/src/main/java/com/y83/ws/data/repo/PromptsRepository.kt — клиент REST.
  • backend/internal/prompts/prompts.go, builtin.go — файл, валидация, встроенные.
  • backend/internal/api/v1/routes.go:162–165 — роуты.
  • docs/tech/prompts-library.md — границы «правило / процедура / формулировка».

Источник: docs/project/hub/14-prompts.md · AI и агенты · 1 247 строк в 4 файлах. Страница собирается из документации проекта при сборке сайта.