feat(ai-chat): per-role autoStart toggle + custom launchMessage (#149) #156

Merged
vvzvlad merged 2 commits from feat/ai-role-autostart into develop 2026-06-24 12:43:43 +03:00

Закрывает #149.

Что

Карточки агентных ролей всегда авто-отправляли захардкоженное "Take a look at the current document". Сделал настраиваемым на уровне роли:

  • autoStart (bool, default true) — отправлять ли сообщение при выборе роли.
  • launchMessage (nullable text) — текст авто-старта; пусто → дефолт. При autoStart=false — только привязать роль, ничего не слать (первое ручное сообщение всё равно несёт roleId).

Существующие роли: autoStart=true/launchMessage=null → поведение в точности как раньше.

Full-stack

  • Миграция 20260624T120000 (аддитивная): auto_start boolean NOT NULL DEFAULT true + launch_message text; down дропает обе. db.d.ts поправлен руками.
  • DTO: autoStart (@IsBoolean), launchMessage (trim @Transform, @MaxLength 2000).
  • repo/service: проброс + нормализация (undefined=не менять, ""→null, autoStart ?? true). Оба поля — в picker-view для рядовых участников (им нужно решить, слать ли авто-сообщение); instructions/modelConfig остаются admin-only.
  • Клиент: типы IAiRole, форма роли (Switch + Textarea, ре-гидрация на edit), handleRolePick ветвится по autoStart; i18n en-US + ru-RU.

По ревью (мой review-агент, NEEDS CHANGES — закрыто)

  • Реальный баг: залипающий rolePickedNoSend при «New chat» после пика роли с autoStart=false (тред не ремоунтится, карточки не возвращались) → render-phase one-shot reset при пустом role-less состоянии.
  • Симметрия нормализации launchMessage create/update.
  • Контроль доступа подтверждён корректным: новые поля в picker-view, instructions/modelConfig — только админам (есть тест-контракт).

Проверка

Сервер: 68 role-тестов (dto/service/repo) зелёные, tsc --noEmit чисто. Клиент: tsc --noEmit чисто, role-тесты зелёные.

🤖 Generated with Claude Code

Закрывает #149. ## Что Карточки агентных ролей всегда авто-отправляли захардкоженное `"Take a look at the current document"`. Сделал настраиваемым на уровне роли: - **`autoStart`** (bool, default true) — отправлять ли сообщение при выборе роли. - **`launchMessage`** (nullable text) — текст авто-старта; пусто → дефолт. При `autoStart=false` — только привязать роль, ничего не слать (первое ручное сообщение всё равно несёт `roleId`). Существующие роли: `autoStart=true`/`launchMessage=null` → поведение в точности как раньше. ## Full-stack - Миграция `20260624T120000` (аддитивная): `auto_start boolean NOT NULL DEFAULT true` + `launch_message text`; `down` дропает обе. `db.d.ts` поправлен руками. - DTO: `autoStart` (`@IsBoolean`), `launchMessage` (trim `@Transform`, `@MaxLength 2000`). - repo/service: проброс + нормализация (`undefined`=не менять, `""`→null, `autoStart ?? true`). Оба поля — в **picker-view** для рядовых участников (им нужно решить, слать ли авто-сообщение); `instructions`/`modelConfig` остаются **admin-only**. - Клиент: типы `IAiRole`, форма роли (`Switch` + `Textarea`, ре-гидрация на edit), `handleRolePick` ветвится по `autoStart`; i18n en-US + ru-RU. ## По ревью (мой review-агент, NEEDS CHANGES — закрыто) - **Реальный баг:** залипающий `rolePickedNoSend` при «New chat» после пика роли с `autoStart=false` (тред не ремоунтится, карточки не возвращались) → render-phase one-shot reset при пустом role-less состоянии. - Симметрия нормализации `launchMessage` create/update. - Контроль доступа подтверждён корректным: новые поля в picker-view, `instructions`/`modelConfig` — только админам (есть тест-контракт). ## Проверка Сервер: 68 role-тестов (dto/service/repo) зелёные, `tsc --noEmit` чисто. Клиент: `tsc --noEmit` чисто, role-тесты зелёные. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Ghost added 1 commit 2026-06-24 06:29:14 +03:00
Agent role cards always auto-sent a hardcoded "Take a look at the current
document" on pick. Make it configurable per role:
- autoStart (bool, default true): whether picking the role auto-sends a message.
- launchMessage (nullable text): the text sent on auto-start; empty -> the
  built-in default. autoStart=false -> bind the role and send nothing (the user
  types the first message, which still carries the roleId).
Existing roles default to autoStart=true / launchMessage=null => identical old
behavior.

Full-stack:
- migration 20260624T120000 adds `auto_start boolean NOT NULL DEFAULT true` +
  `launch_message text` (additive; down drops both); db.d.ts updated by hand.
- DTO: autoStart (@IsBoolean) + launchMessage (trim @Transform, @MaxLength 2000).
- repo/service: thread + normalize (undefined=unchanged, ""=>null, autoStart??true).
  Both fields exposed in the picker-view for ordinary members (they decide
  whether/what to auto-send); instructions/modelConfig stay ADMIN-ONLY.
- client: IAiRole types, role form (Switch + Textarea, re-hydrated on edit),
  handleRolePick branches on autoStart; i18n en-US + ru-RU.

Review follow-ups folded in: reset the `rolePickedNoSend` flag when the thread
returns to an empty role-less state (the "New chat after autoStart=false pick"
stuck-UI bug — render-phase one-shot reset); made create/update launchMessage
normalization symmetric (raw value, server normalizes ""→null).

Server: 68 role tests pass, tsc clean. Client: tsc clean, role tests pass.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Ghost added 1 commit 2026-06-24 12:42:35 +03:00
Review of #156 (Request changes) flagged the new CLIENT logic as untested. Extract
the decision logic from chat-thread.tsx into pure, unit-testable helpers and cover
both branches the reviewer called out:

- `roleLaunchMessage(role, default)` — the three-way handleRolePick behavior:
  autoStart=false -> null (send nothing); autoStart=true + custom -> trimmed
  message; autoStart=true + empty/null/whitespace -> default fallback.
- `shouldResetRolePicked(chatId, roleId, flag)` — the #149 render-phase reset; the
  regression test asserts the stuck-flag case (New chat after an autoStart=false
  pick -> cards return) that the pre-fix code never handled, and that a still-bound
  role keeps the cards hidden.

chat-thread.tsx now calls these helpers (behavior unchanged). 9 new pure tests.

Also folded the review's cosmetic suggestion: `x ? x : null` -> `x || null` in
ai-agent-roles.repo.ts (identical for string|null|undefined).

Client tsc clean; role-launch + role-cards green; repo spec green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
vvzvlad merged commit b321bbafc4 into develop 2026-06-24 12:43:43 +03:00
vvzvlad deleted branch feat/ai-role-autostart 2026-06-24 12:59:08 +03:00
Sign in to join this conversation.
No Reviewers
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: vvzvlad/gitmost#156