@ykurilov/agent-chat-flows 0.63.2 → 0.64.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/CHANGELOG.md +12 -0
- package/dist/{chunk-KGWXTWBZ.js → chunk-22FWN7NU.js} +2 -2
- package/dist/{chunk-H3AN5YUN.js → chunk-3K72EVAT.js} +2 -2
- package/dist/{chunk-LT4QELAZ.js → chunk-5RDY7QBA.js} +34 -9
- package/dist/chunk-5RDY7QBA.js.map +1 -0
- package/dist/format.js +4 -2
- package/dist/index.js +65 -5
- package/dist/index.js.map +1 -1
- package/dist/react.js +28 -3
- package/dist/react.js.map +1 -1
- package/dist/types/format/index.d.ts +1 -0
- package/dist/types/format/parse-duration.d.ts +5 -0
- package/dist/types/labels/test-chat.d.ts +8 -0
- package/dist/types/react/flow-editor-skin.d.ts +6 -0
- package/dist/types/react/test-chat/use-flow-test-chat.d.ts +12 -0
- package/dist/types/runtime/flow-types.d.ts +27 -6
- package/dist/types/runtime/index.d.ts +1 -1
- package/dist/types/runtime/test-clock.d.ts +7 -4
- package/package.json +4 -4
- package/dist/chunk-LT4QELAZ.js.map +0 -1
- /package/dist/{chunk-KGWXTWBZ.js.map → chunk-22FWN7NU.js.map} +0 -0
- /package/dist/{chunk-H3AN5YUN.js.map → chunk-3K72EVAT.js.map} +0 -0
package/dist/react.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/react/flow-labels.ts","../src/labels/client-card.ts","../src/labels/editor.ts","../src/labels/migrate.ts","../src/labels/test-chat.ts","../src/labels/index.ts","../src/react/editor/flow-editor.tsx","../src/react/editor/editor-model.ts","../src/react/editor/exit-text.ts","../src/react/editor/board-space.ts","../src/react/editor/flow-board.tsx","../src/react/editor/board-styles.ts","../src/react/editor/schedule-model.ts","../src/react/editor/flow-simulation.ts","../src/react/editor/side-task-model.ts","../src/react/editor/use-flow-editor.ts","../src/react/client-card/use-client-card.ts","../src/react/client-card/client-card-panel.tsx","../src/react/test-chat/flow-test-chat.tsx","../src/react/test-chat/use-flow-test-chat.ts"],"sourcesContent":["import { createContext, createElement, useContext } from \"react\";\nimport type { ReactNode } from \"react\";\nimport { russianFlowLabels, type FlowLabels } from \"../labels/index\";\n\nconst FlowLabelsContext = createContext<FlowLabels>(russianFlowLabels);\n\n/** Надписи экранов сценария; по умолчанию русские (`russianFlowLabels`). */\nexport function FlowLabelsProvider({ labels, children }: { labels: FlowLabels; children: ReactNode }) {\n return createElement(FlowLabelsContext.Provider, { value: labels }, children);\n}\n\nexport function useFlowLabels(): FlowLabels {\n return useContext(FlowLabelsContext);\n}\n","/** Надписи экрана карточки клиента. */\nexport interface ClientCardLabels {\n title: string;\n empty: string;\n /** «обновлено 12.10.2026». */\n updatedAt: (date: string) => string;\n stale: string;\n /** Название строки свободного факта («ведёт блог») в списке. */\n fact: string;\n forgetField: string;\n forgetAll: string;\n forgetAllConfirm: string;\n confirm: string;\n cancel: string;\n loading: string;\n failed: string;\n retry: string;\n}\n\nexport const russianClientCardLabels: ClientCardLabels = {\n title: \"Что агент знает о вас\",\n empty: \"Агент пока ничего о вас не запомнил.\",\n updatedAt: (date) => `обновлено ${date}`,\n stale: \"может быть уже не так\",\n fact: \"Факт\",\n forgetField: \"Стереть\",\n forgetAll: \"Стереть всё\",\n forgetAllConfirm: \"Стереть всё, что агент знает о вас? Вернуть не получится.\",\n confirm: \"Стереть\",\n cancel: \"Отмена\",\n loading: \"Загружаем…\",\n failed: \"Не получилось загрузить. Попробуйте ещё раз\",\n retry: \"Повторить\",\n};\n\nexport const englishClientCardLabels: ClientCardLabels = {\n title: \"What the agent knows about you\",\n empty: \"The agent has not remembered anything about you yet.\",\n updatedAt: (date) => `updated ${date}`,\n stale: \"may be out of date\",\n fact: \"Fact\",\n forgetField: \"Erase\",\n forgetAll: \"Erase everything\",\n forgetAllConfirm: \"Erase everything the agent knows about you? This cannot be undone.\",\n confirm: \"Erase\",\n cancel: \"Cancel\",\n loading: \"Loading…\",\n failed: \"Could not load. Try again\",\n retry: \"Retry\",\n};\n","import type { FlowConditionType, FlowDataOp, FlowEventType, FlowFieldType, FlowTimerSpan, FlowTimerUnit } from \"../format/flow-format\";\n\n/** Надписи редактора сценария: доска, шапка, панели, прогон, окно JSON. */\nexport interface FlowEditorLabels {\n conditionKinds: Record<FlowConditionType, string>;\n /** Подсказка к виду условия в легенде. */\n conditionKindHints: Record<FlowConditionType, string>;\n returnKind: string;\n returnTarget: string;\n ops: Record<FlowDataOp, string>;\n events: Record<FlowEventType, string>;\n timerSpans: Record<FlowTimerSpan | \"time_of_day\", string>;\n units: Record<FlowTimerUnit, string>;\n fieldTypes: Record<FlowFieldType, string>;\n /** Значения поля «да/нет» в условиях и подписях. */\n yes: string;\n no: string;\n /** «1 день», «3 дня», «5 дней». */\n days: (count: number) => string;\n /** Подпись условия «наступил день N программы» на доске: «с дня 3». */\n programDay: (day: number) => string;\n\n header: {\n state: string;\n card: string;\n check: string;\n run: string;\n json: string;\n save: string;\n saved: string;\n unsaved: string;\n /** Сохранение отклонено: приложение отказало или упало. */\n saveFailed: string;\n saveFailedHint: string;\n /** Плашка «только просмотр»: сценарий сейчас правит не человек. */\n readOnly: string;\n readOnlyHint: string;\n migrate: string;\n /** Меню «⋯» шапки на узком экране: подпись кнопки. */\n more: string;\n };\n board: {\n anyState: string;\n start: string;\n final: string;\n noSideQuestions: string;\n noTarget: string;\n /** Условие словами, у которого ещё нет текста. */\n emptyCondition: string;\n /** Название нового состояния. */\n newState: string;\n zoomIn: string;\n zoomOut: string;\n fit: string;\n /** «2 ошибки», «1 замечание». */\n errors: (count: number) => string;\n warnings: (count: number) => string;\n /** Подпись касаний на карточке ноды: «касания 15 мин · 1 ч». */\n nudges: string;\n noNudges: string;\n /** Срок своих касаний на карточке: «в день входа», «первые 2 дн.». */\n nudgesDays: (days: number) => string;\n /** Кнопки места на доске: легенда, мини-карта, панель «Сценарий», полный экран. */\n space: {\n legend: string;\n showMinimap: string;\n hideMinimap: string;\n showInspector: string;\n hideInspector: string;\n enterFullscreen: string;\n exitFullscreen: string;\n /** Подпись области редактора в полном экране. */\n fullscreenRegion: string;\n };\n };\n overview: {\n title: string;\n common: string;\n commonHint: string;\n states: string;\n exits: string;\n finals: string;\n lists: string;\n help: string;\n /** Находки без места: весь сценарий, «Дни и время». */\n flowIssues: string;\n afterEnd: string;\n afterEndModes: Record<\"reply\" | \"silent\", string>;\n afterEndHints: Record<\"reply\" | \"silent\", string>;\n };\n schedule: {\n title: string;\n on: string;\n hint: string;\n dayStart: string;\n dayStartHint: string;\n lengthDays: string;\n lengthDaysNone: string;\n nightFrom: string;\n nightFromHint: string;\n lateStart: string;\n lateStartHint: string;\n deadlineState: string;\n deadlineNone: string;\n farewell: string;\n farewellText: string;\n farewellTextHint: string;\n firstMessages: string;\n maxPerDay: string;\n maxPerDayHint: string;\n morning: string;\n skipMorning: string;\n nudges: string;\n nudgesHint: string;\n dayFrame: string;\n dayFrameHint: string;\n softFrom: string;\n hardAt: string;\n hardText: string;\n hardTextHint: string;\n more: string;\n };\n nudges: {\n afterSilence: string;\n addStep: string;\n dailyAt: string;\n addTime: string;\n giveUpAfter: string;\n never: string;\n remove: string;\n on: string;\n };\n sideTasks: {\n title: string;\n hint: string;\n builtIn: string;\n text: string;\n when: string;\n field: string;\n noField: string;\n fromApp: string;\n maxAttempts: string;\n perConversation: string;\n add: string;\n newTask: string;\n delete: string;\n };\n statePanel: {\n title: string;\n name: string;\n instructions: string;\n instructionsHint: string;\n firstMessage: string;\n learn: string;\n tools: string;\n toolsHint: string;\n noTools: string;\n tags: string;\n makeStart: string;\n isStart: string;\n noSideQuestions: string;\n exits: string;\n addExit: string;\n more: string;\n deleteState: string;\n /** «Длится»: выход по времени в ноде. */\n duration: string;\n durationHint: string;\n durationNone: string;\n durationUnits: Record<\"h\" | \"d\" | \"program_day\", string>;\n durationTo: string;\n nudges: string;\n nudgesModes: Record<\"inherit\" | \"own\" | \"off\", string>;\n nudgesHint: string;\n /** Сколько действуют свои касания: всё время в ноде или N дней с дня входа. */\n nudgesDays: string;\n nudgesDaysModes: Record<\"always\" | \"days\", string>;\n nudgesDaysHint: string;\n };\n exitCard: {\n when: string;\n field: string;\n op: string;\n value: string;\n event: string;\n eventName: string;\n timer: string;\n amount: string;\n at: string;\n to: string;\n moveUp: string;\n moveDown: string;\n delete: string;\n };\n anyStatePanel: {\n title: string;\n hint: string;\n except: string;\n };\n cardPanel: {\n title: string;\n clientCard: string;\n chatNotes: string;\n chatNotesHint: string;\n empty: string;\n name: string;\n about: string;\n type: string;\n options: string;\n optionsHint: string;\n refreshAfter: string;\n /** «через 6 мес.». */\n refreshAfterMonths: (months: number) => string;\n pace: string;\n /** «раз в 5 сообщений». */\n paceEvery: (messages: number) => string;\n paceHint: string;\n addField: string;\n newField: string;\n /** Добавить поле из словаря приложения (`catalog.fields`). */\n fromApp: string;\n };\n checkPanel: {\n title: string;\n clean: string;\n errors: string;\n warnings: string;\n goTo: string;\n /** Проверки приложения упали. */\n appCheckFailed: string;\n };\n runPanel: {\n title: string;\n hint: string;\n current: string;\n whatHappened: string;\n nothing: string;\n known: string;\n notYet: string;\n nextQuestion: string;\n path: string;\n back: string;\n restart: string;\n finish: string;\n /** «Прогон · шаг 3». */\n step: (step: number) => string;\n /** Цель выбора «ничего из этого». */\n stay: string;\n /** Выбор, который сейчас не сработает: нет цели или «назад» некуда. */\n wontFire: string;\n /** Шаг пути, когда ничего не сработало. */\n nothingHappened: string;\n noStart: string;\n };\n jsonDialog: {\n title: string;\n copy: string;\n copied: string;\n download: string;\n load: string;\n close: string;\n };\n}\n\nexport const russianFlowEditorLabels: FlowEditorLabels = {\n conditionKinds: { judge: \"Словами\", data: \"Данные\", event: \"Событие\", timer: \"Таймер\" },\n conditionKindHints: {\n judge: \"Словами — решает агент, проверяет судья\",\n data: \"По данным — поле заполнено, значение равно…\",\n event: \"Событие — кнопка, инструмент, сигнал приложения\",\n timer: \"Таймер — по часам\",\n },\n returnKind: \"Назад\",\n returnTarget: \"назад, где был\",\n ops: { filled: \"заполнено\", eq: \"=\", ne: \"≠\", gt: \">\", lt: \"<\", contains: \"содержит\" },\n events: { message: \"Пришло сообщение\", button: \"Нажата кнопка\", tool: \"Вызван инструмент\", app: \"Событие приложения\" },\n timerSpans: {\n in_state: \"Время в этом состоянии\",\n silence: \"Тишина человека\",\n since_start: \"Прошло с начала чата\",\n time_of_day: \"Наступило время суток\",\n },\n units: { min: \"мин\", h: \"ч\", d: \"дн.\" },\n fieldTypes: { text: \"Текст\", number: \"Число\", choice: \"Выбор\", boolean: \"Да/нет\" },\n yes: \"да\",\n no: \"нет\",\n days: (count) => {\n const tens = count % 100;\n const ones = count % 10;\n const word = tens >= 11 && tens <= 14 ? \"дней\" : ones === 1 ? \"день\" : ones >= 2 && ones <= 4 ? \"дня\" : \"дней\";\n return `${count} ${word}`;\n },\n programDay: (day) => `с дня ${day}`,\n\n header: {\n state: \"Состояние\",\n card: \"Карточка и заметки\",\n check: \"Проверить граф\",\n run: \"Прогон\",\n json: \"JSON\",\n save: \"Сохранить\",\n saved: \"Сохранено\",\n unsaved: \"Есть несохранённые правки\",\n saveFailed: \"Не сохранено\",\n saveFailedHint: \"Сохранение отклонено. Что не так — в «Проверить граф» и на нодах.\",\n readOnly: \"Только просмотр\",\n readOnlyHint: \"Сценарий сейчас правит агент. Смотреть и прогонять можно, править нельзя.\",\n migrate: \"Перевести чаты\",\n more: \"Ещё действия\",\n },\n board: {\n anyState: \"Из любого состояния\",\n start: \"Сценарий начинается здесь\",\n final: \"Конец\",\n noSideQuestions: \"Без вопросов о человеке\",\n noTarget: \"куда — не выбрано\",\n emptyCondition: \"условие не написано\",\n newState: \"Новое состояние\",\n zoomIn: \"Крупнее\",\n zoomOut: \"Мельче\",\n fit: \"Весь граф\",\n errors: (count) => `Ошибок: ${count}`,\n warnings: (count) => `Замечаний: ${count}`,\n nudges: \"касания\",\n noNudges: \"без касаний\",\n nudgesDays: (days) => (days === 1 ? \"в день входа\" : `первые ${days} дн.`),\n space: {\n legend: \"Легенда\",\n showMinimap: \"Показать мини-карту\",\n hideMinimap: \"Скрыть мини-карту\",\n showInspector: \"Показать панель «Сценарий»\",\n hideInspector: \"Скрыть панель «Сценарий»\",\n enterFullscreen: \"На весь экран\",\n exitFullscreen: \"Выйти из полного экрана\",\n fullscreenRegion: \"Редактор сценария на весь экран\",\n },\n },\n overview: {\n title: \"Сценарий\",\n common: \"Общее для всех состояний\",\n commonHint: \"Роль, тон, цены, условия, ссылки — то, что верно в любом состоянии.\",\n states: \"Состояний\",\n exits: \"Условий выхода\",\n finals: \"Конечных\",\n lists: \"Списки\",\n help: \"Как пользоваться\",\n flowIssues: \"Весь сценарий\",\n afterEnd: \"После конца разговора\",\n afterEndModes: { reply: \"Отвечать\", silent: \"Не отвечать\" },\n afterEndHints: {\n reply: \"Агент отвечает по общей части: знает, что программа закончилась, не ведёт по шагам и не продаёт повторно.\",\n silent: \"Агент молчит, сообщение получает приложение.\",\n },\n },\n schedule: {\n title: \"Дни и время\",\n on: \"Сценарий по дням\",\n hint: \"Дни, ночь, общий срок и сообщения первым. Номер дня агент видит в каждом ходе.\",\n dayStart: \"Начало дня\",\n dayStartHint: \"В это время — утреннее сообщение.\",\n lengthDays: \"Сколько дней\",\n lengthDaysNone: \"без срока\",\n nightFrom: \"Ночь с\",\n nightFromHint: \"Ночью агент первым не пишет. Пусто — как в настройках приложения.\",\n lateStart: \"Поздний старт, ч\",\n lateStartHint: \"Пришёл меньше чем за столько часов до ночи — первый день завтра. 0 — день прихода первый.\",\n deadlineState: \"Срок вышел — перейти в\",\n deadlineNone: \"сразу закончить\",\n farewell: \"Попрощаться, когда срок вышел\",\n farewellText: \"Готовый текст прощания\",\n farewellTextHint: \"Пусто — прощание напишет агент.\",\n firstMessages: \"Сообщения первым\",\n maxPerDay: \"Не больше в день\",\n maxPerDayHint: \"Пусто — как в настройках приложения.\",\n morning: \"Утреннее сообщение\",\n skipMorning: \"Не писать утром, если человек писал за, мин\",\n nudges: \"Касания по умолчанию\",\n nudgesHint: \"Агент пишет в той же ноде, когда человек молчит. У ноды можно задать свои.\",\n dayFrame: \"Рамки дня\",\n dayFrameHint: \"По числу сообщений человека за день.\",\n softFrom: \"Сворачивать с сообщения №\",\n hardAt: \"Закончить день на сообщении №\",\n hardText: \"Ответ, когда день закончен\",\n hardTextHint: \"Уходит слово в слово, без модели.\",\n more: \"Дополнительно\",\n },\n nudges: {\n afterSilence: \"Молчит — написать через\",\n addStep: \"Добавить срок\",\n dailyAt: \"Потом каждый день в\",\n addTime: \"Добавить время\",\n giveUpAfter: \"Молчит столько — разговор окончен\",\n never: \"никогда\",\n remove: \"Убрать\",\n on: \"Касания по умолчанию\",\n },\n sideTasks: {\n title: \"Попутные задачи\",\n hint: \"Агент делает их между делом, в темпе вопросов о человеке. Не больше заданных попыток.\",\n builtIn: \"«Узнать город» — встроенная задача: есть всегда, когда заданы «Дни и время».\",\n text: \"Что сделать\",\n when: \"Когда уместно\",\n field: \"Решена, когда известно поле\",\n noField: \"—\",\n fromApp: \"Поля приложения\",\n maxAttempts: \"Попыток\",\n perConversation: \"Заново в каждом разговоре\",\n add: \"Добавить задачу\",\n newTask: \"\",\n delete: \"Удалить задачу\",\n },\n statePanel: {\n title: \"Состояние\",\n name: \"Название\",\n instructions: \"Что агент здесь делает\",\n instructionsHint: \"Первая строка — цель, её видно на доске. Дальше — как себя вести.\",\n firstMessage: \"Первое сообщение\",\n learn: \"Узнать в этом состоянии\",\n tools: \"Инструменты\",\n toolsHint: \"Агенту здесь доступны только отмеченные.\",\n noTools: \"В сценарии пока нет инструментов.\",\n tags: \"Метки\",\n makeStart: \"Начинать отсюда\",\n isStart: \"Сценарий начинается здесь\",\n noSideQuestions: \"Не спрашивать здесь о человеке между делом\",\n exits: \"Когда выходить и куда\",\n addExit: \"Добавить условие\",\n more: \"Дополнительно\",\n deleteState: \"Удалить состояние\",\n duration: \"Длится\",\n durationHint: \"Потом переход «Куда». Дни — дни сценария: новый день начинается в начале дня. «До дня программы» — до начала этого дня, когда бы человек ни пришёл в ноду.\",\n durationNone: \"не ограничено\",\n durationUnits: { h: \"часов\", d: \"дней\", program_day: \"до дня программы\" },\n durationTo: \"Потом — куда\",\n nudges: \"Касания\",\n nudgesModes: { inherit: \"Как у сценария\", own: \"Свои\", off: \"Выкл\" },\n nudgesHint: \"Агент пишет здесь сам, когда человек молчит.\",\n nudgesDays: \"Свои касания действуют\",\n nudgesDaysModes: { always: \"всё время в ноде\", days: \"дн., считая день входа\" },\n nudgesDaysHint: \"Потом — касания сценария: утреннее и общий ряд с начала.\",\n },\n exitCard: {\n when: \"Когда\",\n field: \"Поле\",\n op: \"Как сравнить\",\n value: \"Значение\",\n event: \"Событие\",\n eventName: \"Что именно\",\n timer: \"Откуда считать\",\n amount: \"Сколько\",\n at: \"Во сколько\",\n to: \"Куда\",\n moveUp: \"Выше\",\n moveDown: \"Ниже\",\n delete: \"Удалить условие\",\n },\n anyStatePanel: {\n title: \"Общие переходы\",\n hint: \"Работают из любого состояния. Свои условия состояния проверяются раньше.\",\n except: \"Не действуют ещё и здесь\",\n },\n cardPanel: {\n title: \"Карточка и заметки\",\n clientCard: \"Карточка клиента\",\n chatNotes: \"Заметки этого чата\",\n chatNotesHint: \"Живут весь чат, в следующем чате не помнятся.\",\n empty: \"Карточка клиента и заметки пока пусты.\",\n name: \"Название\",\n about: \"Что это и когда уместно спросить\",\n type: \"Тип\",\n options: \"Варианты\",\n optionsHint: \"Варианты через запятую\",\n refreshAfter: \"Может устареть\",\n refreshAfterMonths: (months) => `через ${months} мес.`,\n pace: \"Вопрос о человеке — раз в\",\n paceEvery: (messages) => `раз в ${messages} сообщений`,\n paceHint: \"Сначала пытается понять из слов, спрашивает — если не вышло. Не спрашивает, если человек раздражён или торопится.\",\n addField: \"Добавить поле\",\n newField: \"Новое поле\",\n fromApp: \"Поле приложения…\",\n },\n checkPanel: {\n title: \"Проверка\",\n clean: \"Проблем не нашлось.\",\n errors: \"Ошибки\",\n warnings: \"Замечания\",\n goTo: \"Открыть\",\n appCheckFailed: \"Проверки приложения не сработали — их находок здесь нет\",\n },\n runPanel: {\n title: \"Прогон\",\n hint: \"Прогон: выбирайте справа, что произошло\",\n current: \"Где сейчас агент\",\n whatHappened: \"Что произошло?\",\n nothing: \"Ничего из этого\",\n known: \"Что агент знает\",\n notYet: \"Пока нет\",\n nextQuestion: \"Следующий вопрос о человеке\",\n path: \"Пройденный путь\",\n back: \"Шаг назад\",\n restart: \"Сначала\",\n finish: \"Закончить прогон\",\n step: (step) => `Прогон · шаг ${step}`,\n stay: \"остаться здесь\",\n wontFire: \"сейчас не сработает\",\n nothingHappened: \"ничего не сработало\",\n noStart: \"Нет стартового состояния: отметьте, где начинается сценарий\",\n },\n jsonDialog: {\n title: \"Граф в формате JSON\",\n copy: \"Копировать\",\n copied: \"Скопировано\",\n download: \"Скачать\",\n load: \"Загрузить\",\n close: \"Закрыть\",\n },\n};\n\nexport const englishFlowEditorLabels: FlowEditorLabels = {\n conditionKinds: { judge: \"In words\", data: \"Data\", event: \"Event\", timer: \"Timer\" },\n conditionKindHints: {\n judge: \"In words — the agent decides, the judge checks\",\n data: \"By data — a field is filled, a value equals…\",\n event: \"Event — a button, a tool, an app signal\",\n timer: \"Timer — by the clock\",\n },\n returnKind: \"Back\",\n returnTarget: \"back where it was\",\n ops: { filled: \"is filled\", eq: \"=\", ne: \"≠\", gt: \">\", lt: \"<\", contains: \"contains\" },\n events: { message: \"Message arrived\", button: \"Button pressed\", tool: \"Tool called\", app: \"App event\" },\n timerSpans: {\n in_state: \"Time in this state\",\n silence: \"Person is silent\",\n since_start: \"Since the chat started\",\n time_of_day: \"Time of day reached\",\n },\n units: { min: \"min\", h: \"h\", d: \"d\" },\n fieldTypes: { text: \"Text\", number: \"Number\", choice: \"Choice\", boolean: \"Yes/no\" },\n yes: \"yes\",\n no: \"no\",\n days: (count) => `${count} ${count === 1 ? \"day\" : \"days\"}`,\n programDay: (day) => `from day ${day}`,\n\n header: {\n state: \"State\",\n card: \"Card and notes\",\n check: \"Check the graph\",\n run: \"Dry run\",\n json: \"JSON\",\n save: \"Save\",\n saved: \"Saved\",\n unsaved: \"Unsaved changes\",\n saveFailed: \"Not saved\",\n saveFailedHint: \"Saving was rejected. See what is wrong in “Check flow” and on the nodes.\",\n readOnly: \"View only\",\n readOnlyHint: \"An agent is editing this flow right now. You can look and run it, but not edit.\",\n migrate: \"Move chats\",\n more: \"More actions\",\n },\n board: {\n anyState: \"From any state\",\n start: \"The flow starts here\",\n final: \"End\",\n noSideQuestions: \"No questions about the person\",\n noTarget: \"target not chosen\",\n emptyCondition: \"condition not written\",\n newState: \"New state\",\n zoomIn: \"Zoom in\",\n zoomOut: \"Zoom out\",\n fit: \"Whole graph\",\n errors: (count) => `Errors: ${count}`,\n warnings: (count) => `Warnings: ${count}`,\n nudges: \"nudges\",\n noNudges: \"no nudges\",\n nudgesDays: (days) => (days === 1 ? \"on the entry day\" : `for the first ${days} days`),\n space: {\n legend: \"Legend\",\n showMinimap: \"Show the minimap\",\n hideMinimap: \"Hide the minimap\",\n showInspector: \"Show the flow panel\",\n hideInspector: \"Hide the flow panel\",\n enterFullscreen: \"Full screen\",\n exitFullscreen: \"Exit full screen\",\n fullscreenRegion: \"Flow editor, full screen\",\n },\n },\n overview: {\n title: \"Flow\",\n common: \"Common to all states\",\n commonHint: \"Role, tone, prices, terms, links — whatever holds in every state.\",\n states: \"States\",\n exits: \"Exit conditions\",\n finals: \"Final\",\n lists: \"Lists\",\n help: \"How to use\",\n flowIssues: \"Whole flow\",\n afterEnd: \"After the conversation ends\",\n afterEndModes: { reply: \"Reply\", silent: \"Stay silent\" },\n afterEndHints: {\n reply: \"The agent replies from the common part: it knows the program is over, does not lead through steps or sell again.\",\n silent: \"The agent stays silent; the app receives the message.\",\n },\n },\n schedule: {\n title: \"Days and time\",\n on: \"Day-by-day flow\",\n hint: \"Days, night, total length and first messages. The agent sees the day number on every turn.\",\n dayStart: \"Day starts at\",\n dayStartHint: \"The morning message goes out at this time.\",\n lengthDays: \"How many days\",\n lengthDaysNone: \"no limit\",\n nightFrom: \"Night from\",\n nightFromHint: \"At night the agent never writes first. Empty — as in the app settings.\",\n lateStart: \"Late start, h\",\n lateStartHint: \"Arrived less than this many hours before night — day one is tomorrow. 0 — the arrival day is day one.\",\n deadlineState: \"Time is up — go to\",\n deadlineNone: \"end right away\",\n farewell: \"Say goodbye when time is up\",\n farewellText: \"Ready-made goodbye\",\n farewellTextHint: \"Empty — the agent writes the goodbye.\",\n firstMessages: \"Writing first\",\n maxPerDay: \"At most per day\",\n maxPerDayHint: \"Empty — as in the app settings.\",\n morning: \"Morning message\",\n skipMorning: \"Skip the morning if the person wrote within, min\",\n nudges: \"Default nudges\",\n nudgesHint: \"The agent writes in the same state while the person is silent. A state can have its own.\",\n dayFrame: \"Daily limits\",\n dayFrameHint: \"By the number of the person's messages per day.\",\n softFrom: \"Wrap up from message #\",\n hardAt: \"End the day at message #\",\n hardText: \"Reply when the day is over\",\n hardTextHint: \"Sent word for word, without the model.\",\n more: \"More\",\n },\n nudges: {\n afterSilence: \"Silent — write after\",\n addStep: \"Add a delay\",\n dailyAt: \"Then every day at\",\n addTime: \"Add a time\",\n giveUpAfter: \"Silent this long — conversation over\",\n never: \"never\",\n remove: \"Remove\",\n on: \"Default nudges\",\n },\n sideTasks: {\n title: \"Side tasks\",\n hint: \"The agent does them in passing, at the pace of questions about the person. No more than the given attempts.\",\n builtIn: \"“Find out the city” is built in: always on when “Days and time” are set.\",\n text: \"What to do\",\n when: \"When it fits\",\n field: \"Done when this field is known\",\n noField: \"—\",\n fromApp: \"App fields\",\n maxAttempts: \"Attempts\",\n perConversation: \"Anew in every conversation\",\n add: \"Add a task\",\n newTask: \"\",\n delete: \"Delete the task\",\n },\n statePanel: {\n title: \"State\",\n name: \"Name\",\n instructions: \"What the agent does here\",\n instructionsHint: \"The first line is the goal, shown on the board. Then — how to behave.\",\n firstMessage: \"First message\",\n learn: \"Learn in this state\",\n tools: \"Tools\",\n toolsHint: \"Only the checked tools are available here.\",\n noTools: \"The flow has no tools yet.\",\n tags: \"Tags\",\n makeStart: \"Start here\",\n isStart: \"The flow starts here\",\n noSideQuestions: \"No side questions about the person here\",\n exits: \"When to leave and where to\",\n addExit: \"Add a condition\",\n more: \"More\",\n deleteState: \"Delete the state\",\n duration: \"Lasts\",\n durationHint: \"Then goes to “Go to”. Days are flow days: a new day begins at the day start. “Until program day” lasts until that day starts, whenever the person entered the node.\",\n durationNone: \"no limit\",\n durationUnits: { h: \"hours\", d: \"days\", program_day: \"until program day\" },\n durationTo: \"Then go to\",\n nudges: \"Nudges\",\n nudgesModes: { inherit: \"As in the flow\", own: \"Own\", off: \"Off\" },\n nudgesHint: \"The agent writes here by itself while the person is silent.\",\n nudgesDays: \"Own nudges apply\",\n nudgesDaysModes: { always: \"the whole time in the state\", days: \"days, counting the entry day\" },\n nudgesDaysHint: \"Then the flow's nudges: the morning message and the common series from the start.\",\n },\n exitCard: {\n when: \"When\",\n field: \"Field\",\n op: \"Compare\",\n value: \"Value\",\n event: \"Event\",\n eventName: \"Which one\",\n timer: \"Count from\",\n amount: \"How long\",\n at: \"At\",\n to: \"Go to\",\n moveUp: \"Up\",\n moveDown: \"Down\",\n delete: \"Delete the condition\",\n },\n anyStatePanel: {\n title: \"Common transitions\",\n hint: \"Work from any state. The state's own conditions are checked first.\",\n except: \"Also not active here\",\n },\n cardPanel: {\n title: \"Card and notes\",\n clientCard: \"Client card\",\n chatNotes: \"Notes of this chat\",\n chatNotesHint: \"Live for the whole chat and are not remembered in the next one.\",\n empty: \"The client card and notes are empty so far.\",\n name: \"Name\",\n about: \"What it is and when to ask\",\n type: \"Type\",\n options: \"Options\",\n optionsHint: \"Options separated by commas\",\n refreshAfter: \"May go stale\",\n refreshAfterMonths: (months) => `in ${months} mo.`,\n pace: \"A question about the person — once per\",\n paceEvery: (messages) => `once per ${messages} messages`,\n paceHint: \"First tries to understand from what was said and asks only if that fails. Does not ask when the person is annoyed or in a hurry.\",\n addField: \"Add a field\",\n newField: \"New field\",\n fromApp: \"App field…\",\n },\n checkPanel: {\n title: \"Check\",\n clean: \"No problems found.\",\n errors: \"Errors\",\n warnings: \"Warnings\",\n goTo: \"Open\",\n appCheckFailed: \"The app's checks failed — their findings are missing here\",\n },\n runPanel: {\n title: \"Dry run\",\n hint: \"Dry run: choose on the right what happened\",\n current: \"Where the agent is\",\n whatHappened: \"What happened?\",\n nothing: \"None of these\",\n known: \"What the agent knows\",\n notYet: \"Not yet\",\n nextQuestion: \"Next question about the person\",\n path: \"Path so far\",\n back: \"Step back\",\n restart: \"Restart\",\n finish: \"Finish the dry run\",\n step: (step) => `Dry run · step ${step}`,\n stay: \"stay here\",\n wontFire: \"won't fire now\",\n nothingHappened: \"nothing fired\",\n noStart: \"No start state: mark where the flow begins\",\n },\n jsonDialog: {\n title: \"The graph as JSON\",\n copy: \"Copy\",\n copied: \"Copied\",\n download: \"Download\",\n load: \"Load\",\n close: \"Close\",\n },\n};\n","/** Надписи окна перевода чатов на новую версию сценария. */\nexport interface FlowMigrateLabels {\n title: string;\n hint: string;\n version: string;\n state: string;\n chats: string;\n removed: string;\n target: string;\n chooseTarget: string;\n migrate: string;\n /** «Переведено чатов: 12». */\n moved: (count: number) => string;\n nothingToMigrate: string;\n close: string;\n failed: string;\n}\n\nexport const russianFlowMigrateLabels: FlowMigrateLabels = {\n title: \"Перевести чаты на новую версию\",\n hint: \"Чаты продолжат с того же состояния. Закончившиеся разговоры и тестовые чаты остаются на своей версии. Для удалённых состояний выберите, куда перевести.\",\n version: \"Версия\",\n state: \"Состояние\",\n chats: \"Чатов\",\n removed: \"удалено в новой версии\",\n target: \"Куда\",\n chooseTarget: \"Выберите состояние\",\n migrate: \"Перевести\",\n moved: (count) => `Переведено чатов: ${count}`,\n nothingToMigrate: \"Переводить нечего: идущие чаты уже на этой версии.\",\n close: \"Закрыть\",\n failed: \"Не получилось перевести. Попробуйте ещё раз\",\n};\n\nexport const englishFlowMigrateLabels: FlowMigrateLabels = {\n title: \"Move chats to the new version\",\n hint: \"Chats continue from the same state. Finished conversations and test chats stay on their version. For removed states choose where to move them.\",\n version: \"Version\",\n state: \"State\",\n chats: \"Chats\",\n removed: \"removed in the new version\",\n target: \"Move to\",\n chooseTarget: \"Choose a state\",\n migrate: \"Move\",\n moved: (count) => `Chats moved: ${count}`,\n nothingToMigrate: \"Nothing to move: ongoing chats are already on this version.\",\n close: \"Close\",\n failed: \"Could not move the chats. Try again\",\n};\n","/** Надписи тестового чата редактора: живой разговор по сценарию с перемоткой часов. */\nexport interface FlowTestChatLabels {\n title: string;\n state: string;\n /** «+20 мин». */\n advance: (label: string) => string;\n clock: string;\n /** Часы чата не сдвинуты. */\n noOffset: string;\n /** Единицы сдвига: «3 ч 20 мин». */\n units: { day: string; hour: string; minute: string };\n reset: string;\n close: string;\n /** Тестовый чат не открылся или часы не перемотались. */\n failed: string;\n /** Перемотка к началу следующего дня сценария. */\n nextDay: string;\n /** «День 2 из 3», «День 2». */\n day: (day: number, totalDays?: number) => string;\n /** Вечер позднего старта: первый день ещё не начался. */\n beforeFirstDay: string;\n}\n\nexport const russianFlowTestChatLabels: FlowTestChatLabels = {\n title: \"Тестовый чат\",\n state: \"Сейчас в состоянии\",\n advance: (label) => `+${label}`,\n clock: \"Часы чата\",\n noOffset: \"как сейчас\",\n units: { day: \"д\", hour: \"ч\", minute: \"мин\" },\n reset: \"Начать заново\",\n close: \"Закрыть\",\n failed: \"Не получилось — попробуйте ещё раз\",\n nextDay: \"К началу следующего дня\",\n day: (day, totalDays) => (totalDays === undefined ? `День ${day}` : `День ${day} из ${totalDays}`),\n beforeFirstDay: \"До первого дня\",\n};\n\nexport const englishFlowTestChatLabels: FlowTestChatLabels = {\n title: \"Test chat\",\n state: \"Current state\",\n advance: (label) => `+${label}`,\n clock: \"Chat clock\",\n noOffset: \"now\",\n units: { day: \"d\", hour: \"h\", minute: \"min\" },\n reset: \"Start over\",\n close: \"Close\",\n failed: \"Something went wrong — try again\",\n nextDay: \"To the start of the next day\",\n day: (day, totalDays) => (totalDays === undefined ? `Day ${day}` : `Day ${day} of ${totalDays}`),\n beforeFirstDay: \"Before day one\",\n};\n","import { englishClientCardLabels, russianClientCardLabels, type ClientCardLabels } from \"./client-card\";\nimport { englishFlowEditorLabels, russianFlowEditorLabels, type FlowEditorLabels } from \"./editor\";\nimport { englishFlowMigrateLabels, russianFlowMigrateLabels, type FlowMigrateLabels } from \"./migrate\";\nimport { englishFlowTestChatLabels, russianFlowTestChatLabels, type FlowTestChatLabels } from \"./test-chat\";\n\n/** Все надписи экранов сценария: по словарю на экран. */\nexport interface FlowLabels {\n editor: FlowEditorLabels;\n clientCard: ClientCardLabels;\n migrate: FlowMigrateLabels;\n testChat: FlowTestChatLabels;\n}\n\nexport const russianFlowLabels: FlowLabels = {\n editor: russianFlowEditorLabels,\n clientCard: russianClientCardLabels,\n migrate: russianFlowMigrateLabels,\n testChat: russianFlowTestChatLabels,\n};\n\nexport const englishFlowLabels: FlowLabels = {\n editor: englishFlowEditorLabels,\n clientCard: englishClientCardLabels,\n migrate: englishFlowMigrateLabels,\n testChat: englishFlowTestChatLabels,\n};\n\nexport type { ClientCardLabels, FlowEditorLabels, FlowMigrateLabels, FlowTestChatLabels };\n","import { useMemo, useState, type CSSProperties, type ReactNode } from \"react\";\nimport {\n FLOW_OPS_BY_FIELD_TYPE,\n FLOW_DATA_OPS,\n RETURN_TARGET,\n type AgentFlow,\n type FlowExit,\n type FlowField,\n type FlowIssue,\n type FlowNudges,\n type FlowState,\n} from \"../../format/flow-format\";\nimport { catalogEventLabel, catalogEventNames } from \"../../format/catalog-events\";\nimport { fieldById, isFinal, stateById } from \"../../engine/flow-graph\";\nimport { isFieldStale } from \"../../engine/side-questions\";\nimport type { FlowEditorLabels } from \"../../labels/editor\";\nimport { useFlowLabels } from \"../flow-labels\";\nimport type { FlowEditorSkin, FlowStateLinkView, FlowTargetOption } from \"../flow-editor-skin\";\nimport {\n addExit,\n addField,\n freeSpot,\n moveExit,\n moveField,\n normalizeCondition,\n removeExit,\n removeField,\n setExcept,\n setStart,\n updateExit,\n updateField,\n updateState,\n type ExitOwner,\n type FieldList,\n} from \"./editor-model\";\nimport { conditionText, edgeKind, stateGoal, targetTitle } from \"./exit-text\";\nimport { useBoardSpace, useFullscreenBehavior, type FlowBoardSpaceProps } from \"./board-space\";\nimport { FlowBoard } from \"./flow-board\";\nimport {\n durationOf,\n nudgesMode,\n setAfterEnd,\n setDuration,\n setScheduleOn,\n setStateNudges,\n setStateNudgesDays,\n stateNudgesDays,\n updateSchedule,\n updateScheduleNudges,\n updateStateNudges,\n} from \"./schedule-model\";\nimport { addCatalogField, addSideTask, catalogFieldsToAdd, removeSideTask, setSideTaskField, updateSideTask } from \"./side-task-model\";\nimport { nextQuestionField, simulationChoices } from \"./flow-simulation\";\nimport { useFlowEditor, type FlowEditorController, type UseFlowEditorOptions } from \"./use-flow-editor\";\n\nexport interface FlowEditorProps extends UseFlowEditorOptions, FlowBoardSpaceProps {\n /** Части экрана: `tandemFlowEditorSkin` из `@ykurilov/agent-chat-skin-tandem/flows` или свои по договору. */\n skin: FlowEditorSkin;\n /** Класс и стиль корня редактора. По умолчанию он занимает высоту родителя, но не меньше разумной (на телефоне тоже). */\n className?: string;\n style?: CSSProperties;\n}\n\n/** Редактор сценария: доска, панели, проверка, прогон, JSON. Управляемый: сценарий хранит приложение. */\nexport function FlowEditor({ skin, className, style, header: headerMode, legend, minimap, inspector, fullscreen, storageKey, ...options }: FlowEditorProps) {\n const editor = useFlowEditor(options);\n const labels = useFlowLabels().editor;\n const { flow } = editor;\n const space = useBoardSpace(\n {\n ...(headerMode !== undefined ? { header: headerMode } : {}),\n ...(legend !== undefined ? { legend } : {}),\n ...(minimap !== undefined ? { minimap } : {}),\n ...(inspector !== undefined ? { inspector } : {}),\n ...(fullscreen !== undefined ? { fullscreen } : {}),\n ...(storageKey !== undefined ? { storageKey } : {}),\n },\n editor,\n );\n const [root, setRoot] = useState<HTMLDivElement | null>(null);\n const { setFullscreen } = space;\n const onTab = useFullscreenBehavior(space.fullscreen, () => setFullscreen(false), editor.dialog !== null, root);\n\n const header = (\n <skin.FlowHeader\n name={flow.name}\n onRename={(name) => editor.edit((current) => ({ ...current, name }))}\n mode={editor.mode}\n onModeChange={editor.setMode}\n issues={editor.issueCount}\n onAddState={() => editor.addState(freeSpot(flow))}\n onOpenCard={() => editor.select({ kind: \"card\" })}\n onOpenJson={editor.openJson}\n {...(options.onSave && !editor.readOnly ? { onSave: () => void editor.save() } : {})}\n saving={editor.saving}\n dirty={editor.dirty}\n saveFailed={editor.saveFailed}\n readOnly={editor.readOnly}\n {...(editor.migrate && !editor.readOnly ? { onOpenMigrate: editor.migrate.open } : {})}\n {...(space.header === \"compact\" ? { compact: true } : {})}\n {...(space.fullscreenAllowed ? { fullscreen: { active: space.fullscreen, onToggle: () => setFullscreen(!space.fullscreen) } } : {})}\n />\n );\n\n // Обёртка стоит всегда, чтобы доска не пересоздавалась при выходе на весь экран; в обычном виде она не влияет на вёрстку.\n return (\n <div\n ref={setRoot}\n data-flow-fullscreen={space.fullscreen ? \"\" : undefined}\n {...(space.fullscreen ? { role: \"dialog\", \"aria-modal\": true, \"aria-label\": labels.board.space.fullscreenRegion, onKeyDown: onTab } : {})}\n style={space.fullscreen ? FULLSCREEN_STYLE : { display: \"contents\" }}\n >\n <skin.FlowEditorFrame\n header={header}\n board={<FlowBoard editor={editor} skin={skin} space={space} />}\n panel={space.inspectorOpen ? <EditorPanel editor={editor} skin={skin} labels={labels} /> : null}\n dialog={<EditorDialog editor={editor} skin={skin} />}\n {...(space.header === \"compact\" ? { compact: true } : {})}\n // Свои класс и стиль приложения рассчитаны на место в странице; на весь экран редактор занимает окно.\n {...(space.fullscreen ? { style: { height: \"100%\", minHeight: 0 } } : { ...(className !== undefined ? { className } : {}), ...(style !== undefined ? { style } : {}) })}\n />\n </div>\n );\n}\n\nconst FULLSCREEN_STYLE: CSSProperties = {\n position: \"fixed\",\n inset: 0,\n zIndex: 2000,\n height: \"100dvh\",\n overflow: \"auto\",\n background: \"var(--canvas, Canvas)\",\n color: \"var(--foreground, CanvasText)\",\n};\n\nfunction stateLinks(editor: FlowEditorController): FlowStateLinkView[] {\n return editor.flow.states.map((state) => ({\n stateId: state.id,\n title: state.title || state.id,\n start: editor.flow.start === state.id,\n final: isFinal(state),\n onSelect: () => editor.select({ kind: \"state\", stateId: state.id }),\n }));\n}\n\nfunction targetOptions(flow: AgentFlow, labels: FlowEditorLabels, withReturn: boolean): FlowTargetOption[] {\n const states = flow.states.map((state) => ({ value: state.id, title: state.title || state.id }));\n return withReturn ? [...states, { value: RETURN_TARGET, title: labels.returnTarget }] : states;\n}\n\nfunction ExitCards({ editor, skin, labels, owner }: { editor: FlowEditorController; skin: FlowEditorSkin; labels: FlowEditorLabels; owner: ExitOwner }) {\n const { flow, catalog } = editor;\n const state = owner === null ? undefined : stateById(flow, owner);\n // Выход «Длится» правится в своём разделе панели ноды, если у скина он есть.\n const durationExitId = state && skin.FlowStateTiming ? durationOf(state)?.exitId : undefined;\n const exits: FlowExit[] = (owner === null ? flow.anyState.exits : (state?.exits ?? [])).filter((exit) => exit.id !== durationExitId);\n const fields: FlowField[] = [...flow.clientCard, ...flow.chatNotes];\n const eventNames = {\n button: [...new Set([...catalogEventNames(catalog), ...catalog.widgets])],\n tool: [...catalog.tools],\n app: catalogEventNames(catalog),\n };\n const eventLabels: Record<string, string> = {};\n for (const name of eventNames.app) {\n const label = catalogEventLabel(catalog, name);\n if (label) eventLabels[name] = label;\n }\n const targets = targetOptions(flow, labels, owner !== null);\n return (\n <>\n {exits.map((exit, index) => {\n const fieldType = exit.when.type === \"data\" ? fieldById(flow, exit.when.field)?.field.type : undefined;\n return (\n <skin.FlowExitCard\n key={exit.id}\n exitId={exit.id}\n when={exit.when}\n to={exit.to}\n fields={fields}\n ops={fieldType ? [...FLOW_OPS_BY_FIELD_TYPE[fieldType]] : [...FLOW_DATA_OPS]}\n eventNames={eventNames}\n eventLabels={eventLabels}\n targets={targets}\n issues={editor.issues.filter((issue) => issue.place.exitId === exit.id)}\n canMoveUp={index > 0}\n canMoveDown={index < exits.length - 1}\n onChange={(next) =>\n editor.edit((current) => updateExit(current, owner, exit.id, { when: normalizeCondition(current, exit.when, next.when), to: next.to }))\n }\n onMoveUp={() => editor.edit((current) => moveExit(current, owner, exit.id, -1))}\n onMoveDown={() => editor.edit((current) => moveExit(current, owner, exit.id, 1))}\n onDelete={() => editor.edit((current) => removeExit(current, owner, exit.id))}\n />\n );\n })}\n </>\n );\n}\n\nfunction FieldRows({ editor, skin, list }: { editor: FlowEditorController; skin: FlowEditorSkin; list: FieldList }) {\n const fields: FlowField[] = editor.flow[list];\n return (\n <>\n {fields.map((field, index) => (\n <skin.FlowFieldRow\n key={field.id}\n field={field}\n list={list}\n canMoveUp={index > 0}\n canMoveDown={index < fields.length - 1}\n issues={editor.issues.filter((issue) => issue.place.fieldId === field.id)}\n onChange={(patch) => editor.edit((current) => updateField(current, list, field.id, patch))}\n onMoveUp={() => editor.edit((current) => moveField(current, list, field.id, -1))}\n onMoveDown={() => editor.edit((current) => moveField(current, list, field.id, 1))}\n onDelete={() => editor.edit((current) => removeField(current, list, field.id))}\n />\n ))}\n </>\n );\n}\n\nfunction EditorPanel({ editor, skin, labels }: { editor: FlowEditorController; skin: FlowEditorSkin; labels: FlowEditorLabels }): ReactNode {\n const panel = <EditablePanel editor={editor} skin={skin} labels={labels} />;\n // Только просмотр: поля и кнопки панели правок выключены сразу, а не молча возвращают прежнее значение.\n if (!editor.readOnly || editor.mode !== \"edit\") return panel;\n return (\n <fieldset disabled data-flow-read-only=\"\" className=\"m-0 flex min-h-0 min-w-0 flex-1 flex-col border-0 p-0\">\n {panel}\n </fieldset>\n );\n}\n\nfunction EditablePanel({ editor, skin, labels }: { editor: FlowEditorController; skin: FlowEditorSkin; labels: FlowEditorLabels }): ReactNode {\n const { flow, selection } = editor;\n\n if (editor.mode === \"check\") {\n return <skin.FlowCheckPanel issues={editor.issues.map((issue) => ({ ...issue, onGo: () => editor.goToIssue(issue) }))} />;\n }\n if (editor.mode === \"run\" && editor.simulation) return <RunPanel editor={editor} skin={skin} labels={labels} />;\n\n if (selection.kind === \"state\") {\n const state = stateById(flow, selection.stateId)!;\n return (\n <skin.FlowStatePanel\n key={state.id}\n stateId={state.id}\n title={state.title}\n instructions={state.instructions}\n firstMessage={state.firstMessage}\n learn={state.learn}\n tools={state.tools}\n tags={state.tags}\n start={flow.start === state.id}\n noSideQuestions={state.noSideQuestions}\n fields={[...flow.clientCard, ...flow.chatNotes]}\n catalogTools={[...new Set([...flow.tools, ...editor.catalog.tools])]}\n exits={<ExitCards editor={editor} skin={skin} labels={labels} owner={state.id} />}\n timing={<StateTiming editor={editor} skin={skin} labels={labels} state={state} />}\n issues={editor.issues.filter((issue) => issue.place.stateId === state.id && !issue.place.exitId)}\n onChange={(patch) =>\n editor.edit((current) => {\n const next = updateState(current, state.id, patch);\n // Инструмент, отмеченный в состоянии, попадает и в список инструментов сценария.\n const missing = (patch.tools ?? []).filter((tool) => !next.tools.includes(tool));\n return missing.length ? { ...next, tools: [...next.tools, ...missing] } : next;\n })\n }\n onMakeStart={() => editor.edit((current) => setStart(current, state.id))}\n onAddExit={(kind) => {\n const made = addExit(flow, state.id, kind);\n editor.edit(() => made.flow);\n editor.select({ kind: \"state\", stateId: state.id, exitId: made.exitId });\n }}\n onDelete={() => {\n editor.removeState(state.id);\n editor.select({ kind: \"overview\" });\n }}\n />\n );\n }\n if (selection.kind === \"any\") {\n return (\n <skin.FlowAnyStatePanel\n except={flow.anyState.except}\n states={stateLinks(editor)}\n onExceptChange={(except) => editor.edit((current) => setExcept(current, except))}\n exits={<ExitCards editor={editor} skin={skin} labels={labels} owner={null} />}\n onAddExit={(kind) => editor.edit((current) => addExit(current, null, kind).flow)}\n />\n );\n }\n if (selection.kind === \"card\") {\n return (\n <skin.FlowCardPanel\n clientCard={<FieldRows editor={editor} skin={skin} list=\"clientCard\" />}\n chatNotes={<FieldRows editor={editor} skin={skin} list=\"chatNotes\" />}\n empty={flow.clientCard.length === 0 && flow.chatNotes.length === 0}\n sideQuestionEveryMessages={flow.pace.sideQuestionEveryMessages}\n onPaceChange={(messages) =>\n editor.edit((current) => ({ ...current, pace: { sideQuestionEveryMessages: Math.max(1, Math.round(messages) || 1) } }))\n }\n onAddField={(list) => editor.edit((current) => addField(current, list, labels.cardPanel.newField).flow)}\n appFields={catalogFieldsToAdd(flow, editor.catalog).map((field) => ({ id: field.id, title: field.title }))}\n onAddAppField={(list, fieldId) => {\n const field = editor.catalog.fields?.find((candidate) => candidate.id === fieldId);\n if (field) editor.edit((current) => addCatalogField(current, list, field));\n }}\n />\n );\n }\n return (\n <skin.FlowOverviewPanel\n name={flow.name}\n common={flow.common}\n onCommonChange={(common) => editor.edit((current) => ({ ...current, common }))}\n counts={{\n states: flow.states.length,\n exits: flow.anyState.exits.length + flow.states.reduce((sum, state) => sum + state.exits.length, 0),\n finals: flow.states.filter(isFinal).length,\n }}\n states={stateLinks(editor)}\n issues={editor.issueCount}\n sections={\n <>\n <ScheduleSection editor={editor} skin={skin} labels={labels} />\n <SideTasksSection editor={editor} skin={skin} focused={selection.kind === \"overview\" ? selection.sideTaskId : undefined} />\n </>\n }\n />\n );\n}\n\n/** Находки по «Дням и времени»: их коды из `checkFlow`. */\nconst SCHEDULE_ISSUES = new Set([\"night_before_day_start\", \"unknown_deadline_state\", \"day_frame_soft_after_hard\"]);\nconst isScheduleIssue = (issue: FlowIssue) => SCHEDULE_ISSUES.has(issue.code) || (issue.code === \"empty_nudges\" && !issue.place.stateId);\n\nfunction NudgesEditor({ skin, nudges, optional, onChange }: { skin: FlowEditorSkin; nudges: FlowNudges | null; optional: boolean; onChange(nudges: FlowNudges | null): void }) {\n if (!skin.FlowNudgesEditor) return null;\n return <skin.FlowNudgesEditor nudges={nudges} optional={optional} onChange={onChange} />;\n}\n\nfunction ScheduleSection({ editor, skin, labels }: { editor: FlowEditorController; skin: FlowEditorSkin; labels: FlowEditorLabels }): ReactNode {\n if (!skin.FlowScheduleSection) return null;\n const { flow } = editor;\n return (\n <skin.FlowScheduleSection\n schedule={flow.schedule ?? null}\n afterEnd={flow.afterEnd ?? \"reply\"}\n states={targetOptions(flow, labels, false)}\n issues={editor.issues.filter(isScheduleIssue)}\n nudges={\n <NudgesEditor\n skin={skin}\n nudges={flow.schedule?.nudges ?? null}\n optional\n onChange={(nudges) => editor.edit((current) => updateScheduleNudges(current, nudges))}\n />\n }\n onToggle={(on) => editor.edit((current) => setScheduleOn(current, on))}\n onChange={(patch) => editor.edit((current) => updateSchedule(current, patch))}\n onAfterEndChange={(mode) => editor.edit((current) => setAfterEnd(current, mode))}\n />\n );\n}\n\nfunction SideTasksSection({ editor, skin, focused }: { editor: FlowEditorController; skin: FlowEditorSkin; focused: string | undefined }): ReactNode {\n const labels = useFlowLabels().editor;\n if (!skin.FlowSideTasksSection) return null;\n const { flow, catalog } = editor;\n return (\n <skin.FlowSideTasksSection\n tasks={(flow.sideTasks ?? []).map((task) => ({\n ...task,\n issues: editor.issues.filter((issue) => issue.place.sideTaskId === task.id),\n focused: task.id === focused,\n }))}\n fields={[\n ...[...flow.clientCard, ...flow.chatNotes].map((field) => ({ id: field.id, title: field.name || field.id, fromApp: false })),\n ...catalogFieldsToAdd(flow, catalog).map((field) => ({ id: field.id, title: field.title, fromApp: true })),\n ]}\n builtInCity={flow.schedule !== undefined}\n onAdd={() => editor.edit((current) => addSideTask(current, labels.sideTasks.newTask).flow)}\n onChange={(sideTaskId, patch) => editor.edit((current) => updateSideTask(current, sideTaskId, patch))}\n onFieldChange={(sideTaskId, fieldId) => editor.edit((current) => setSideTaskField(current, sideTaskId, fieldId, catalog))}\n onDelete={(sideTaskId) => editor.edit((current) => removeSideTask(current, sideTaskId))}\n />\n );\n}\n\nfunction StateTiming({ editor, skin, labels, state }: { editor: FlowEditorController; skin: FlowEditorSkin; labels: FlowEditorLabels; state: FlowState }): ReactNode {\n if (!skin.FlowStateTiming) return null;\n const { flow } = editor;\n const duration = durationOf(state);\n const mode = nudgesMode(state);\n const own = state.nudges && state.nudges !== \"off\" ? state.nudges : null;\n return (\n <skin.FlowStateTiming\n duration={duration && { amount: duration.amount, unit: duration.unit, to: duration.to }}\n daysAvailable={flow.schedule !== undefined || (duration !== null && duration.unit !== \"h\")}\n targets={targetOptions(flow, labels, true)}\n issues={duration ? editor.issues.filter((issue) => issue.place.exitId === duration.exitId) : []}\n onDurationChange={(value) => editor.edit((current) => setDuration(current, state.id, value))}\n onDurationTargetChange={(to) => {\n if (!duration) return;\n editor.edit((current) => {\n const exit = stateById(current, state.id)?.exits.find((candidate) => candidate.id === duration.exitId);\n return exit ? updateExit(current, state.id, exit.id, { when: exit.when, to }) : current;\n });\n }}\n nudgesMode={mode}\n onNudgesModeChange={(next) => editor.edit((current) => setStateNudges(current, state.id, next))}\n nudgesDays={stateNudgesDays(state)}\n onNudgesDaysChange={(days) => editor.edit((current) => setStateNudgesDays(current, state.id, days))}\n nudges={\n own && (\n <NudgesEditor\n skin={skin}\n nudges={own}\n optional={false}\n onChange={(nudges) => editor.edit((current) => (nudges ? updateStateNudges(current, state.id, nudges) : setStateNudges(current, state.id, \"off\")))}\n />\n )\n }\n />\n );\n}\n\nfunction RunPanel({ editor, skin, labels }: { editor: FlowEditorController; skin: FlowEditorSkin; labels: FlowEditorLabels }) {\n const { flow } = editor;\n const sim = editor.simulation!;\n const state = stateById(flow, sim.run.state);\n const choices = useMemo(() => simulationChoices(flow, sim), [flow, sim]);\n const question = nextQuestionField(flow, sim);\n const exitById = (exitId: string) => [...flow.anyState.exits, ...flow.states.flatMap((candidate) => candidate.exits)].find((exit) => exit.id === exitId);\n\n const knownRow = (field: FlowField, value: unknown, stale: boolean) => ({\n fieldId: field.id,\n name: field.name || field.id,\n value: value === undefined || value === null || value === \"\" ? null : String(value),\n stale,\n onChange: (text: string) => editor.simulate.setKnown(field.id, text),\n });\n const known = [\n ...flow.clientCard.map((field) => {\n const entry = sim.card[field.id];\n return knownRow(field, entry?.value, entry !== undefined && isFieldStale(field, entry.updatedAt, sim.now));\n }),\n ...flow.chatNotes.map((field) => knownRow(field, sim.run.notes[field.id], false)),\n ];\n\n return (\n <skin.FlowRunPanel\n current={{ stateId: sim.run.state, title: state?.title || sim.run.state, goal: stateGoal(state?.instructions ?? \"\") }}\n choices={choices.map((choice) => {\n const exit = exitById(choice.exitId)!;\n return {\n exitId: choice.exitId,\n kind: edgeKind(exit),\n text: conditionText(flow, exit.when, labels, editor.catalog),\n target: choice.target ? targetTitle(flow, choice.target, labels) : null,\n onChoose: () => editor.simulate.choose(choice.exitId),\n };\n })}\n onNothing={editor.simulate.nothing}\n known={known}\n nextQuestion={question ? (fieldById(flow, question)?.field.name ?? question) : null}\n path={sim.steps.map((step) => {\n const exit = step.exitId ? exitById(step.exitId) : undefined;\n return {\n stateId: step.stateId,\n title: stateById(flow, step.stateId)?.title || step.stateId,\n via: step.nothing ? labels.runPanel.nothingHappened : exit ? conditionText(flow, exit.when, labels, editor.catalog) : null,\n };\n })}\n canGoBack={sim.previous !== null}\n onBack={editor.simulate.back}\n onRestart={editor.simulate.restart}\n onFinish={() => editor.setMode(\"edit\")}\n />\n );\n}\n\nfunction download(name: string, text: string) {\n const url = URL.createObjectURL(new Blob([text], { type: \"application/json\" }));\n const link = document.createElement(\"a\");\n link.href = url;\n link.download = name;\n link.click();\n setTimeout(() => URL.revokeObjectURL(url), 0);\n}\n\nfunction EditorDialog({ editor, skin }: { editor: FlowEditorController; skin: FlowEditorSkin }): ReactNode {\n const labels = useFlowLabels().editor;\n if (editor.dialog === \"json\") {\n return (\n <skin.FlowJsonDialog\n json={editor.json}\n errors={editor.jsonErrors}\n onCopy={() => void navigator.clipboard?.writeText(editor.json)}\n onDownload={() => download(`${editor.flow.id}.json`, editor.json)}\n onLoad={(text) => void editor.loadJson(text)}\n onClose={editor.closeDialog}\n {...(editor.readOnly ? { readOnly: true } : {})}\n />\n );\n }\n if (editor.dialog === \"migrate\" && editor.migrate) {\n const migrate = editor.migrate;\n return (\n <skin.FlowMigrateDialog\n rows={migrate.rows.map((row) => ({ ...row, onTargetChange: (stateId: string) => migrate.setTarget(row.stateId, stateId) }))}\n targets={targetOptions(editor.flow, labels, false)}\n busy={migrate.busy}\n failed={migrate.failed}\n moved={migrate.moved}\n canMigrate={migrate.canMigrate}\n onMigrate={() => void migrate.run()}\n onClose={editor.closeDialog}\n />\n );\n }\n return null;\n}\n","import { fieldById } from \"../../engine/flow-graph\";\nimport { compactFlow } from \"../../format/compact-flow\";\nimport { parseFlow } from \"../../format/parse-flow\";\nimport {\n FLOW_OPS_BY_FIELD_TYPE,\n type AgentFlow,\n type ClientCardField,\n type FlowCondition,\n type FlowConditionType,\n type FlowExit,\n type FlowField,\n type FlowPoint,\n type FlowState,\n} from \"../../format/flow-format\";\n\n// Правки сценария в редакторе: чистые функции, каждая возвращает новый `AgentFlow`. Доска, панели и прогон зовут только их.\n\n/** Чьё условие: id состояния или `null` — общие переходы «Из любого состояния». */\nexport type ExitOwner = string | null;\n\nexport type FieldList = \"clientCard\" | \"chatNotes\";\n\nexport type StatePatch = Partial<Pick<FlowState, \"title\" | \"instructions\" | \"firstMessage\" | \"learn\" | \"tools\" | \"tags\" | \"noSideQuestions\">>;\n\n/** Свободный id вида `state_3`: не занят ни одним из `taken`. */\nfunction freeId(prefix: string, taken: Iterable<string>): string {\n const used = new Set(taken);\n let index = 1;\n while (used.has(`${prefix}_${index}`)) index += 1;\n return `${prefix}_${index}`;\n}\n\nfunction allExits(flow: AgentFlow): FlowExit[] {\n return [...flow.anyState.exits, ...flow.states.flatMap((state) => state.exits)];\n}\n\nfunction allFields(flow: AgentFlow): FlowField[] {\n return [...flow.clientCard, ...flow.chatNotes];\n}\n\nfunction editState(flow: AgentFlow, stateId: string, edit: (state: FlowState) => FlowState): AgentFlow {\n return { ...flow, states: flow.states.map((state) => (state.id === stateId ? edit(state) : state)) };\n}\n\nfunction editExits(flow: AgentFlow, owner: ExitOwner, edit: (exits: FlowExit[]) => FlowExit[]): AgentFlow {\n if (owner === null) return { ...flow, anyState: { ...flow.anyState, exits: edit(flow.anyState.exits) } };\n return editState(flow, owner, (state) => ({ ...state, exits: edit(state.exits) }));\n}\n\nfunction exitsOf(flow: AgentFlow, owner: ExitOwner): FlowExit[] {\n if (owner === null) return flow.anyState.exits;\n return flow.states.find((state) => state.id === owner)?.exits ?? [];\n}\n\n/** Переставляет элемент на `delta` позиций; за край — тот же массив. */\nfunction shift<T>(items: T[], index: number, delta: number): T[] {\n const target = index + delta;\n if (index < 0 || target < 0 || target >= items.length) return items;\n const next = [...items];\n const [item] = next.splice(index, 1);\n next.splice(target, 0, item!);\n return next;\n}\n\nexport function addState(flow: AgentFlow, input: { title: string; at?: FlowPoint }): { flow: AgentFlow; stateId: string } {\n const stateId = freeId(\"state\", flow.states.map((state) => state.id));\n const state: FlowState = {\n id: stateId,\n kind: \"state\",\n title: input.title,\n instructions: \"\",\n firstMessage: null,\n learn: [],\n noSideQuestions: false,\n tools: [],\n tags: [],\n exits: [],\n };\n return {\n stateId,\n flow: {\n ...flow,\n start: flow.states.length === 0 ? stateId : flow.start,\n states: [...flow.states, state],\n layout: input.at ? { ...flow.layout, [stateId]: input.at } : flow.layout,\n },\n };\n}\n\n/** Удаляет состояние: ведущие в него условия остаются без цели, из старта и исключений оно уходит. */\nexport function removeState(flow: AgentFlow, stateId: string): AgentFlow {\n const unlink = (exits: FlowExit[]) => exits.map((exit) => (exit.to === stateId ? { ...exit, to: null } : exit));\n const { [stateId]: _removed, ...layout } = flow.layout;\n return {\n ...flow,\n start: flow.start === stateId ? null : flow.start,\n states: flow.states.filter((state) => state.id !== stateId).map((state) => ({ ...state, exits: unlink(state.exits) })),\n anyState: { except: flow.anyState.except.filter((id) => id !== stateId), exits: unlink(flow.anyState.exits) },\n layout,\n };\n}\n\nexport function updateState(flow: AgentFlow, stateId: string, patch: StatePatch): AgentFlow {\n return editState(flow, stateId, (state) => ({ ...state, ...patch }));\n}\n\nexport function setStart(flow: AgentFlow, stateId: string): AgentFlow {\n return { ...flow, start: stateId };\n}\n\nexport function setExcept(flow: AgentFlow, except: string[]): AgentFlow {\n return { ...flow, anyState: { ...flow.anyState, except } };\n}\n\n/** Условие нового вида со значениями по умолчанию; по данным — первое поле карточки или заметок. */\nexport function defaultCondition(kind: FlowConditionType, flow: AgentFlow): FlowCondition {\n switch (kind) {\n case \"judge\":\n return { type: \"judge\", text: \"\" };\n case \"data\":\n // Поля ещё нет — id-заглушка: формат её примет, проверка графа покажет «поля нет».\n return { type: \"data\", field: allFields(flow)[0]?.id ?? \"field\", op: \"filled\" };\n case \"event\":\n return { type: \"event\", event: \"message\" };\n case \"timer\":\n return { type: \"timer\", from: \"in_state\", amount: 1, unit: \"h\" };\n }\n}\n\n/**\n * Условие после правки в карточке. Скин меняет одно поле, а целым и годным условие делает редактор: другой вид —\n * значения по умолчанию; другое поле — сравнение, подходящее его типу; число из поля ввода — числом; таймер «время\n * суток» ↔ «сколько прошло» — со своими значениями.\n */\nexport function normalizeCondition(flow: AgentFlow, previous: FlowCondition, next: FlowCondition): FlowCondition {\n if (next.type !== previous.type) return defaultCondition(next.type, flow);\n if (next.type === \"data\") {\n const type = fieldById(flow, next.field)?.field.type;\n if (type === undefined) return next;\n if (!FLOW_OPS_BY_FIELD_TYPE[type].includes(next.op)) return { type: \"data\", field: next.field, op: \"filled\" };\n if (next.op === \"filled\") return { type: \"data\", field: next.field, op: \"filled\" };\n if (type === \"boolean\") return { type: \"data\", field: next.field, op: next.op, value: next.value !== false && next.value !== \"false\" };\n if (type === \"number\" && typeof next.value === \"string\" && next.value.trim() !== \"\" && Number.isFinite(Number(next.value))) {\n return { ...next, value: Number(next.value) };\n }\n return { ...next, value: next.value ?? \"\" };\n }\n if (next.type === \"timer\") {\n if (next.from === \"time_of_day\") return { type: \"timer\", from: \"time_of_day\", at: \"at\" in next && next.at ? next.at : \"10:00\" };\n // Дни переносятся между «длится N дней» и «до дня N программы».\n const days = \"days\" in next && next.days ? next.days : \"day\" in next && next.day ? next.day : 1;\n if (next.from === \"state_days\") return { type: \"timer\", from: \"state_days\", days };\n if (next.from === \"program_day\") return { type: \"timer\", from: \"program_day\", day: days };\n const span = next as Partial<typeof next>;\n return { type: \"timer\", from: next.from, amount: span.amount ?? 1, unit: span.unit ?? \"h\" };\n }\n if (next.type === \"event\" && next.event === \"message\") return { type: \"event\", event: \"message\" };\n return next;\n}\n\nexport function addExit(flow: AgentFlow, owner: ExitOwner, kind: FlowConditionType): { flow: AgentFlow; exitId: string } {\n const exitId = freeId(owner ?? \"any\", allExits(flow).map((exit) => exit.id));\n const exit: FlowExit = { id: exitId, when: defaultCondition(kind, flow), to: null };\n return { exitId, flow: editExits(flow, owner, (exits) => [...exits, exit]) };\n}\n\nexport function updateExit(flow: AgentFlow, owner: ExitOwner, exitId: string, next: { when: FlowCondition; to: string | null }): AgentFlow {\n return editExits(flow, owner, (exits) => exits.map((exit) => (exit.id === exitId ? { ...exit, ...next } : exit)));\n}\n\n/** Стрелка с доски: условие ведёт в `to`. */\nexport function connectExit(flow: AgentFlow, owner: ExitOwner, exitId: string, to: string): AgentFlow {\n return editExits(flow, owner, (exits) => exits.map((exit) => (exit.id === exitId ? { ...exit, to } : exit)));\n}\n\nexport function moveExit(flow: AgentFlow, owner: ExitOwner, exitId: string, delta: number): AgentFlow {\n const exits = exitsOf(flow, owner);\n const moved = shift(exits, exits.findIndex((exit) => exit.id === exitId), delta);\n return moved === exits ? flow : editExits(flow, owner, () => moved);\n}\n\nexport function removeExit(flow: AgentFlow, owner: ExitOwner, exitId: string): AgentFlow {\n return editExits(flow, owner, (exits) => exits.filter((exit) => exit.id !== exitId));\n}\n\nexport function addField(flow: AgentFlow, list: FieldList, name: string): { flow: AgentFlow; fieldId: string } {\n const fieldId = freeId(\"field\", allFields(flow).map((field) => field.id));\n const base: FlowField = { id: fieldId, name, about: \"\", type: \"text\", options: [] };\n if (list === \"clientCard\") {\n return { fieldId, flow: { ...flow, clientCard: [...flow.clientCard, { ...base, refreshAfterMonths: null }] } };\n }\n return { fieldId, flow: { ...flow, chatNotes: [...flow.chatNotes, base] } };\n}\n\nexport function updateField(flow: AgentFlow, list: FieldList, fieldId: string, patch: Partial<ClientCardField>): AgentFlow {\n if (list === \"clientCard\") {\n return { ...flow, clientCard: flow.clientCard.map((field) => (field.id === fieldId ? { ...field, ...patch } : field)) };\n }\n const { refreshAfterMonths: _cardOnly, ...notePatch } = patch;\n return { ...flow, chatNotes: flow.chatNotes.map((field) => (field.id === fieldId ? { ...field, ...notePatch } : field)) };\n}\n\nexport function moveField(flow: AgentFlow, list: FieldList, fieldId: string, delta: number): AgentFlow {\n const fields: FlowField[] = flow[list];\n const moved = shift(fields, fields.findIndex((field) => field.id === fieldId), delta);\n return moved === fields ? flow : { ...flow, [list]: moved };\n}\n\n/** Удаляет поле и его «узнать здесь». Условия по нему остаются: их покажет проверка графа. */\nexport function removeField(flow: AgentFlow, list: FieldList, fieldId: string): AgentFlow {\n const fields: FlowField[] = flow[list];\n return {\n ...flow,\n [list]: fields.filter((field) => field.id !== fieldId),\n states: flow.states.map((state) => (state.learn.includes(fieldId) ? { ...state, learn: state.learn.filter((id) => id !== fieldId) } : state)),\n };\n}\n\n/** Где поставить новое состояние без места: под всеми узлами доски. */\nexport function freeSpot(flow: AgentFlow): FlowPoint {\n const points = Object.values(flow.layout);\n if (points.length === 0) return { x: 80, y: 80 };\n return { x: Math.min(...points.map((point) => point.x)), y: Math.max(...points.map((point) => point.y)) + 240 };\n}\n\n/** Место узла на доске; `ANY_STATE_LAYOUT_KEY` — узел общих переходов. */\nexport function placeNode(flow: AgentFlow, nodeId: string, at: FlowPoint): AgentFlow {\n return { ...flow, layout: { ...flow.layout, [nodeId]: { x: Math.round(at.x), y: Math.round(at.y) } } };\n}\n\n/** JSON сценария для окна JSON и скачивания: без значений по умолчанию, как в файлах примеров. */\nexport function flowToJson(flow: AgentFlow): string {\n return `${JSON.stringify(keepJudgeText(compactFlow(flow)), null, 2)}\\n`;\n}\n\nfunction sortKeys(value: unknown): unknown {\n if (Array.isArray(value)) return value.map(sortKeys);\n if (value && typeof value === \"object\") {\n return Object.fromEntries(\n Object.entries(value)\n .sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0))\n .map(([key, inner]) => [key, sortKeys(inner)]),\n );\n }\n return value;\n}\n\n/** Отпечаток сценария для сравнения: тот же `compactFlow`, что у JSON доски, но порядок ключей не важен. */\nexport function flowFingerprint(flow: AgentFlow): string {\n return JSON.stringify(sortKeys(keepJudgeText(compactFlow(flow))));\n}\n\n/**\n * Один ли это сценарий: сравнение так же, как считает «Сохранено» доска (пустые поля не в счёт). Порядок ключей не важен:\n * сценарий из jsonb приходит с другим порядком. Порядок состояний, условий и полей — важен.\n */\nexport function sameFlow(a: AgentFlow, b: AgentFlow): boolean {\n return flowFingerprint(a) === flowFingerprint(b);\n}\n\ntype JsonExit = { when?: { type?: string; text?: string } };\ntype JsonState = { exits?: JsonExit[] };\n\n/**\n * `compactFlow` убирает пустые строки, в том числе текст ещё не написанного условия словами, а без `text` такое условие\n * `parseFlow` не принимает. Возвращаем пустой текст, чтобы недописанный сценарий сохранялся и загружался обратно.\n */\nfunction keepJudgeText(json: Record<string, unknown>): Record<string, unknown> {\n const fix = (exits: JsonExit[] | undefined) =>\n exits?.forEach((exit) => {\n if (exit.when?.type === \"judge\" && exit.when.text === undefined) exit.when.text = \"\";\n });\n (json.states as JsonState[]).forEach((state) => fix(state.exits));\n fix((json.anyState as { exits?: JsonExit[] } | undefined)?.exits);\n return json;\n}\n\nexport type LoadFlowResult = { ok: true; flow: AgentFlow } | { ok: false; errors: string[] };\n\n/** Загрузка JSON в редактор: та же `parseFlow`, что на сервере. Ошибки — строками «место: что не так». */\nexport function loadFlowJson(text: string): LoadFlowResult {\n let input: unknown;\n try {\n input = JSON.parse(text);\n } catch (error) {\n return { ok: false, errors: [`JSON: ${error instanceof Error ? error.message : String(error)}`] };\n }\n const result = parseFlow(input);\n if (result.ok) return result;\n return { ok: false, errors: result.errors.map((error) => (error.path ? `${error.path}: ${error.message}` : error.message)) };\n}\n","import { RETURN_TARGET, type AgentFlow, type FlowCatalog, type FlowCondition, type FlowExit } from \"../../format/flow-format\";\nimport { catalogEventLabel } from \"../../format/catalog-events\";\nimport { fieldById } from \"../../engine/flow-graph\";\nimport type { FlowEditorLabels } from \"../../labels/editor\";\nimport type { FlowEdgeKind } from \"../flow-editor-skin\";\n\n/** Подпись условия для доски, прогона и проверки: «Понятны тема курса и продажи», «Тишина человека 3 ч». С каталогом — подписи событий. */\nexport function conditionText(flow: AgentFlow, when: FlowCondition, labels: FlowEditorLabels, catalog?: Pick<FlowCatalog, \"events\">): string {\n switch (when.type) {\n case \"judge\":\n return when.text.trim() || labels.board.emptyCondition;\n case \"data\": {\n const name = fieldById(flow, when.field)?.field.name || when.field;\n const op = labels.ops[when.op];\n if (typeof when.value === \"boolean\") return `${name} ${op} ${when.value ? labels.yes : labels.no}`;\n return when.op === \"filled\" || when.value === undefined ? `${name} ${op}` : `${name} ${op} ${when.value}`;\n }\n case \"event\":\n if (when.event === \"message\" || !when.name) return labels.events[when.event];\n return `${labels.events[when.event]} «${(when.event !== \"tool\" && catalogEventLabel(catalog, when.name)) || when.name}»`;\n case \"timer\":\n if (when.from === \"time_of_day\") return `${labels.timerSpans.time_of_day} ${when.at}`;\n if (when.from === \"state_days\") return `${labels.statePanel.duration} ${labels.days(when.days)}`;\n if (when.from === \"program_day\") return labels.programDay(when.day);\n return `${labels.timerSpans[when.from]} ${when.amount} ${labels.units[when.unit]}`;\n }\n}\n\n/** Вид стрелки: «назад» рисуется отдельно от вида условия. */\nexport function edgeKind(exit: FlowExit): FlowEdgeKind {\n return exit.to === RETURN_TARGET ? \"return\" : exit.when.type;\n}\n\n/** Название цели: состояние, «назад, где был» или `null`, если цель не выбрана или пропала. */\nexport function targetTitle(flow: AgentFlow, to: string | null, labels: FlowEditorLabels): string | null {\n if (to === null) return null;\n if (to === RETURN_TARGET) return labels.returnTarget;\n const state = flow.states.find((candidate) => candidate.id === to);\n return state ? state.title || state.id : null;\n}\n\n/** Цель состояния на доске: первая строка инструкции. */\nexport function stateGoal(instructions: string): string {\n return instructions.split(\"\\n\").find((line) => line.trim() !== \"\")?.trim() ?? \"\";\n}\n","import { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport type { FlowEditorMode } from \"../flow-editor-skin\";\nimport type { FlowSelection } from \"./use-flow-editor\";\n\n// Место на экране: что на доске свёрнуто, открыта ли правая панель, развёрнут ли весь редактор. Состояние «свёрнуто»\n// запоминается в localStorage браузера (общее для всех сценариев приложения), на сервере и без localStorage — по умолчанию.\n\n/** Шапка доски: `full` — логотип, название и кнопки; `compact` — одна узкая строка кнопок (название у приложения своё). */\nexport type FlowHeaderMode = \"full\" | \"compact\";\n/** Легенда «Условия выхода»: свёрнута в кнопку, открыта или убрана совсем. */\nexport type FlowLegendMode = \"collapsed\" | \"open\" | \"hidden\";\n/** Мини-карта: открыта, свёрнута в кнопку или убрана совсем. */\nexport type FlowMinimapMode = \"open\" | \"collapsed\" | \"hidden\";\n/** Панель «Сценарий»: `open` — открыта, сворачивается кнопкой; `collapsible` — свёрнута, пока ничего не выбрано, выбор раскрывает. */\nexport type FlowInspectorMode = \"open\" | \"collapsible\";\n\nexport interface FlowBoardSpaceProps {\n header?: FlowHeaderMode;\n legend?: FlowLegendMode;\n minimap?: FlowMinimapMode;\n inspector?: FlowInspectorMode;\n /** Кнопка «На весь экран» в шапке. По умолчанию есть. */\n fullscreen?: boolean;\n /** Ключ в localStorage для запомненного. По умолчанию общий `agent-chat-flow-board`; `null` — не запоминать. */\n storageKey?: string | null;\n}\n\nexport const DEFAULT_SPACE_STORAGE_KEY = \"agent-chat-flow-board\";\n\ninterface Remembered {\n legend?: boolean;\n minimap?: boolean;\n inspector?: boolean;\n}\n\nfunction readRemembered(key: string | null | undefined): Remembered {\n if (!key || typeof window === \"undefined\") return {};\n try {\n const parsed: unknown = JSON.parse(window.localStorage.getItem(key) ?? \"null\");\n if (typeof parsed !== \"object\" || parsed === null) return {};\n const result: Remembered = {};\n for (const name of [\"legend\", \"minimap\", \"inspector\"] as const) {\n const value = (parsed as Record<string, unknown>)[name];\n if (typeof value === \"boolean\") result[name] = value;\n }\n return result;\n } catch {\n return {};\n }\n}\n\nfunction writeRemembered(key: string | null | undefined, value: Remembered) {\n if (!key || typeof window === \"undefined\") return;\n try {\n window.localStorage.setItem(key, JSON.stringify(value));\n } catch {\n // Хранилище закрыто или переполнено — просто не запоминаем.\n }\n}\n\nconst selectionKey = (selection: FlowSelection) => {\n if (selection.kind === \"state\") return `state:${selection.stateId}:${selection.exitId ?? \"\"}`;\n if (selection.kind === \"any\") return `any:${selection.exitId ?? \"\"}`;\n return selection.kind === \"overview\" ? `overview:${selection.sideTaskId ?? \"\"}` : selection.kind;\n};\n\nexport interface BoardSpace {\n header: FlowHeaderMode;\n legendHidden: boolean;\n legendOpen: boolean;\n toggleLegend(): void;\n minimapHidden: boolean;\n minimapOpen: boolean;\n toggleMinimap(): void;\n inspectorOpen: boolean;\n /** Кнопка сворачивания панели нужна только в обычной правке: проверка и прогон держат панель открытой. */\n inspectorToggleable: boolean;\n toggleInspector(): void;\n fullscreenAllowed: boolean;\n fullscreen: boolean;\n setFullscreen(on: boolean): void;\n}\n\nexport function useBoardSpace(\n props: FlowBoardSpaceProps,\n editor: { selection: FlowSelection; mode: FlowEditorMode },\n): BoardSpace {\n const { header = \"full\", legend = \"collapsed\", minimap = \"open\", inspector = \"open\", fullscreen: fullscreenAllowed = true } = props;\n const storageKey = props.storageKey === undefined ? DEFAULT_SPACE_STORAGE_KEY : props.storageKey;\n\n const [remembered, setRemembered] = useState<Remembered>({});\n // Читаем после первого показа: на сервере и при гидратации экран тот же, что по умолчанию.\n useEffect(() => setRemembered(readRemembered(storageKey)), [storageKey]);\n // Пишем в хранилище из эффекта, а не из функции setState (она может вызываться дважды).\n const unsaved = useRef(false);\n useEffect(() => {\n if (!unsaved.current) return;\n unsaved.current = false;\n writeRemembered(storageKey, remembered);\n }, [remembered, storageKey]);\n const remember = useCallback((name: keyof Remembered, value: boolean) => {\n unsaved.current = true;\n setRemembered((current) => ({ ...current, [name]: value }));\n }, []);\n\n const legendOpen = legend === \"hidden\" ? false : (remembered.legend ?? legend === \"open\");\n const minimapOpen = minimap === \"hidden\" ? false : (remembered.minimap ?? minimap === \"open\");\n\n // «collapsible»: панель следует за выбором и не запоминается, «open»: запоминается выбор человека.\n const selected = editor.selection.kind !== \"overview\" || editor.selection.sideTaskId !== undefined;\n const key = selectionKey(editor.selection);\n const [followed, setFollowed] = useState(selected);\n const [previousKey, setPreviousKey] = useState(key);\n if (key !== previousKey) {\n setPreviousKey(key);\n setFollowed(selected);\n }\n // Проверка и прогон живут в панели: в них она открыта всегда.\n const needed = editor.mode !== \"edit\";\n const inspectorOpen = needed || (inspector === \"collapsible\" ? followed : (remembered.inspector ?? true));\n\n const [fullscreen, setFullscreen] = useState(false);\n // Приложение выключило полный экран на лету — внутреннее состояние не должно вернуться при включении.\n useEffect(() => {\n if (!fullscreenAllowed) setFullscreen(false);\n }, [fullscreenAllowed]);\n\n return useMemo(\n () => ({\n header,\n legendHidden: legend === \"hidden\",\n legendOpen,\n toggleLegend: () => remember(\"legend\", !legendOpen),\n minimapHidden: minimap === \"hidden\",\n minimapOpen,\n toggleMinimap: () => remember(\"minimap\", !minimapOpen),\n inspectorOpen,\n inspectorToggleable: !needed,\n toggleInspector: () => {\n if (needed) return;\n if (inspector === \"collapsible\") setFollowed(!inspectorOpen);\n else remember(\"inspector\", !inspectorOpen);\n },\n fullscreenAllowed,\n fullscreen: fullscreenAllowed && fullscreen,\n setFullscreen,\n }),\n [header, legend, legendOpen, minimap, minimapOpen, inspector, inspectorOpen, needed, fullscreenAllowed, fullscreen, remember],\n );\n}\n\nconst FOCUSABLE = 'a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex=\"-1\"])';\n\n/**\n * Полный экран: Esc выходит (если не открыто окно поверх), страница под редактором не прокручивается, Tab ходит по кругу\n * внутри. Возвращает ссылку-обработчик клавиш для корня.\n */\nexport function useFullscreenBehavior(active: boolean, onExit: () => void, blocked: boolean, root: HTMLElement | null) {\n useEffect(() => {\n if (!active) return;\n const previous = document.body.style.overflow;\n document.body.style.overflow = \"hidden\";\n return () => {\n document.body.style.overflow = previous;\n };\n }, [active]);\n\n useEffect(() => {\n if (!active) return;\n const onKey = (event: KeyboardEvent) => {\n if (event.key !== \"Escape\" || event.defaultPrevented || blocked) return;\n // Esc в поле ввода только снимает фокус; выход — Esc вне поля.\n const target = event.target;\n if (target instanceof HTMLElement && root?.contains(target) && target.matches('input, textarea, select, [contenteditable]:not([contenteditable=\"false\"])')) {\n event.preventDefault();\n target.blur();\n return;\n }\n event.preventDefault();\n onExit();\n // Кнопка в шапке остаётся на месте: фокус возвращается на неё.\n root?.querySelector<HTMLElement>(\"[data-flow-fullscreen-toggle]\")?.focus();\n };\n document.addEventListener(\"keydown\", onKey);\n return () => document.removeEventListener(\"keydown\", onKey);\n }, [active, blocked, onExit, root]);\n\n return useCallback(\n (event: { key: string; shiftKey: boolean; target: EventTarget; preventDefault(): void }) => {\n // События React всплывают и через портал (окно JSON в body): чужой Tab не трогаем.\n if (!active || event.key !== \"Tab\" || !root || !(event.target instanceof Node) || !root.contains(event.target)) return;\n const items = [...root.querySelectorAll<HTMLElement>(FOCUSABLE)].filter((item) => item.getClientRects().length > 0);\n const first = items[0];\n const last = items[items.length - 1];\n if (!first || !last) return;\n const current = document.activeElement;\n if (event.shiftKey && (current === first || !root.contains(current))) {\n event.preventDefault();\n last.focus();\n } else if (!event.shiftKey && (current === last || !root.contains(current))) {\n event.preventDefault();\n first.focus();\n }\n },\n [active, root],\n );\n}\n","import {\n Background,\n BackgroundVariant,\n getBezierPath,\n Handle,\n MiniMap,\n Panel,\n Position,\n ReactFlow,\n ReactFlowProvider,\n applyNodeChanges,\n useReactFlow,\n useStore,\n type Connection,\n type Edge,\n type EdgeProps,\n type FinalConnectionState,\n type Node,\n type NodeChange,\n type NodeProps,\n} from \"@xyflow/react\";\nimport { createContext, useCallback, useContext, useEffect, useMemo, useState, type ReactNode } from \"react\";\nimport { ANY_STATE_LAYOUT_KEY, RETURN_TARGET, type AgentFlow, type FlowCatalog, type FlowExit, type FlowIssue, type FlowPoint } from \"../../format/flow-format\";\nimport { activeExits, isFinal, stateById } from \"../../engine/flow-graph\";\nimport type { FlowEditorLabels } from \"../../labels/editor\";\nimport { useFlowLabels } from \"../flow-labels\";\nimport type {\n FlowAnyStateNodeProps,\n FlowEdgeKind,\n FlowEdgeProps,\n FlowEditorSkin,\n FlowExitRowView,\n FlowIssueCount,\n FlowStateNodeProps,\n FlowBoardToggleProps,\n} from \"../flow-editor-skin\";\nimport type { BoardSpace } from \"./board-space\";\nimport { FLOW_BOARD_CSS } from \"./board-styles\";\nimport { addExit, connectExit, placeNode, type ExitOwner } from \"./editor-model\";\nimport { conditionText, edgeKind, stateGoal, targetTitle } from \"./exit-text\";\nimport { stateTimingText } from \"./schedule-model\";\nimport { simulationChoices } from \"./flow-simulation\";\nimport type { FlowEditorController } from \"./use-flow-editor\";\n\n// Доска: узлы и стрелки `@xyflow/react`, нарисованные частями скина. Здесь — только раскладка, ручки, пути стрелок и\n// жесты; что показать в узле, считает этот модуль из сценария, правки уходят в `useFlowEditor`.\n\n/** Ручка «новое условие» у каждого узла: потянуть — появится условие словами. */\nexport const NEW_EXIT_HANDLE = \"@new\";\nconst INPUT_HANDLE = \"in\";\n\nconst LEGEND_KINDS: FlowEdgeKind[] = [\"judge\", \"data\", \"event\", \"timer\", \"return\"];\n\ntype StateNodeData = { view: Omit<FlowStateNodeProps, \"renderInputHandle\" | \"renderExitHandle\">; draggable: boolean };\ntype AnyNodeData = { view: Omit<FlowAnyStateNodeProps, \"renderExitHandle\">; draggable: boolean };\ntype FlowEdgeData = Omit<FlowEdgeProps, \"edgeId\" | \"path\" | \"labelX\" | \"labelY\">;\n\ntype StateNode = Node<StateNodeData, \"state\">;\ntype AnyNode = Node<AnyNodeData, \"any\">;\ntype BoardNode = StateNode | AnyNode;\ntype BoardEdge = Edge<FlowEdgeData, \"flow\">;\n\nconst SkinContext = createContext<FlowEditorSkin | null>(null);\n\nfunction useSkin(): FlowEditorSkin {\n const skin = useContext(SkinContext);\n if (!skin) throw new Error(\"FlowBoard renders only inside FlowEditor.\");\n return skin;\n}\n\nfunction exitHandle(exitId: string, connectable: boolean): ReactNode {\n return <Handle type=\"source\" position={Position.Right} id={exitId} isConnectable={connectable} />;\n}\n\nfunction StateNodeView({ data }: NodeProps<StateNode>) {\n const skin = useSkin();\n return (\n <>\n <skin.FlowStateNode\n {...data.view}\n renderInputHandle={() => <Handle type=\"target\" position={Position.Left} id={INPUT_HANDLE} isConnectable={data.draggable} />}\n renderExitHandle={(exitId) => exitHandle(exitId, data.draggable)}\n />\n {data.draggable ? <Handle type=\"source\" position={Position.Right} id={NEW_EXIT_HANDLE} className=\"flow-board__new-exit\" /> : null}\n </>\n );\n}\n\nfunction AnyNodeView({ data }: NodeProps<AnyNode>) {\n const skin = useSkin();\n return (\n <>\n <skin.FlowAnyStateNode {...data.view} renderExitHandle={(exitId) => exitHandle(exitId, data.draggable)} />\n {data.draggable ? <Handle type=\"source\" position={Position.Right} id={NEW_EXIT_HANDLE} className=\"flow-board__new-exit\" /> : null}\n </>\n );\n}\n\nfunction EdgeView({ id, sourceX, sourceY, targetX, targetY, sourcePosition, targetPosition, data }: EdgeProps<BoardEdge>) {\n const skin = useSkin();\n const [path, labelX, labelY] = getBezierPath({ sourceX, sourceY, sourcePosition, targetX, targetY, targetPosition });\n if (!data) return null;\n return <skin.FlowEdge {...data} edgeId={id} path={path} labelX={labelX} labelY={labelY} />;\n}\n\nconst nodeTypes = { state: StateNodeView, any: AnyNodeView };\nconst edgeTypes = { flow: EdgeView };\n\n/** Место узла: из `layout`, а без него — сетка по порядку состояний. */\nfunction nodePosition(flow: AgentFlow, nodeId: string, index: number): FlowPoint {\n const saved = flow.layout[nodeId];\n if (saved) return saved;\n if (nodeId === ANY_STATE_LAYOUT_KEY) return { x: 40, y: -220 };\n return { x: 40 + (index % 4) * 330, y: 40 + Math.floor(index / 4) * 260 };\n}\n\nfunction countFor(issues: FlowIssue[], match: (issue: FlowIssue) => boolean): FlowIssueCount {\n const found = issues.filter(match);\n return { errors: found.filter((issue) => issue.level === \"error\").length, warnings: found.filter((issue) => issue.level === \"warning\").length };\n}\n\nfunction exitRows(flow: AgentFlow, catalog: FlowCatalog, exits: FlowExit[], issues: FlowIssue[], labels: FlowEditorLabels): FlowExitRowView[] {\n return exits.map((exit) => ({\n exitId: exit.id,\n kind: edgeKind(exit),\n text: conditionText(flow, exit.when, labels, catalog),\n target: targetTitle(flow, exit.to, labels),\n issues: countFor(issues, (issue) => issue.place.exitId === exit.id),\n }));\n}\n\nconst ownerOf = (nodeId: string): ExitOwner => (nodeId === ANY_STATE_LAYOUT_KEY ? null : nodeId);\n\n/** Что подсветить в прогоне: где агент, где был, куда можно пойти, по каким стрелкам прошли. */\nfunction runMarks(editor: FlowEditorController) {\n const sim = editor.simulation;\n if (editor.mode !== \"run\" || !sim) return null;\n const visited = new Set(sim.steps.map((step) => step.stateId));\n const next = new Set(simulationChoices(editor.flow, sim).flatMap((choice) => (choice.target ? [choice.target] : [])));\n const traversed = new Set(sim.steps.flatMap((step) => (step.exitId ? [step.exitId] : [])));\n const state = stateById(editor.flow, sim.run.state);\n const live = new Set(state ? activeExits(editor.flow, state).map(({ exit }) => exit.id) : []);\n return { current: sim.run.state, visited, next, traversed, live };\n}\n\nfunction useBoardModel(editor: FlowEditorController) {\n const labels = useFlowLabels().editor;\n const { flow, catalog, issues, selection, mode, select, readOnly } = editor;\n return useMemo(() => {\n const marks = runMarks(editor);\n // Выбирать ноду и стрелку можно вне прогона; двигать и соединять — ещё и не в режиме «только просмотр».\n const selectable = mode !== \"run\";\n const editable = selectable && !readOnly;\n const selectedExit = selection.kind === \"state\" || selection.kind === \"any\" ? selection.exitId : undefined;\n\n const nodes: BoardNode[] = flow.states.map((state, index) => ({\n id: state.id,\n type: \"state\",\n position: nodePosition(flow, state.id, index),\n draggable: editable,\n data: {\n draggable: editable,\n view: {\n stateId: state.id,\n title: state.title || state.id,\n goal: stateGoal(state.instructions),\n exits: exitRows(flow, catalog, state.exits, issues, labels),\n tags: state.tags,\n start: flow.start === state.id,\n final: isFinal(state),\n noSideQuestions: state.noSideQuestions,\n timing: stateTimingText(flow, state, labels),\n selected: selection.kind === \"state\" && selection.stateId === state.id,\n dimmed: marks !== null && !marks.visited.has(state.id) && !marks.next.has(state.id),\n run: marks === null ? null : marks.current === state.id ? \"current\" : marks.visited.has(state.id) ? \"visited\" : null,\n issues: countFor(issues, (issue) => issue.place.stateId === state.id),\n onSelect: () => selectable && select({ kind: \"state\", stateId: state.id }),\n },\n },\n }));\n if (flow.anyState.exits.length > 0 || flow.anyState.except.length > 0 || flow.layout[ANY_STATE_LAYOUT_KEY]) {\n nodes.push({\n id: ANY_STATE_LAYOUT_KEY,\n type: \"any\",\n position: nodePosition(flow, ANY_STATE_LAYOUT_KEY, 0),\n draggable: editable,\n data: {\n draggable: editable,\n view: {\n except: flow.anyState.except.map((id) => stateById(flow, id)?.title ?? id),\n exits: exitRows(flow, catalog, flow.anyState.exits, issues, labels),\n selected: selection.kind === \"any\",\n dimmed: marks !== null,\n issues: countFor(issues, (issue) => !issue.place.stateId && flow.anyState.exits.some((exit) => exit.id === issue.place.exitId)),\n onSelect: () => selectable && select({ kind: \"any\" }),\n },\n },\n });\n }\n\n const owners: Array<{ nodeId: string; exits: FlowExit[] }> = [\n { nodeId: ANY_STATE_LAYOUT_KEY, exits: flow.anyState.exits },\n ...flow.states.map((state) => ({ nodeId: state.id, exits: state.exits })),\n ];\n const edges: BoardEdge[] = owners.flatMap(({ nodeId, exits }) =>\n exits\n .filter((exit) => exit.to !== null && exit.to !== RETURN_TARGET && stateById(flow, exit.to))\n .map((exit) => ({\n id: `${nodeId}:${exit.id}`,\n type: \"flow\" as const,\n source: nodeId,\n sourceHandle: exit.id,\n target: exit.to!,\n targetHandle: INPUT_HANDLE,\n data: {\n kind: edgeKind(exit),\n label: conditionText(flow, exit.when, labels, catalog),\n selected: selectedExit === exit.id,\n dimmed: marks !== null && !marks.traversed.has(exit.id) && !(marks.live.has(exit.id) && nodeId === marks.current),\n traversed: marks?.traversed.has(exit.id) ?? false,\n onSelect: () =>\n selectable && select(nodeId === ANY_STATE_LAYOUT_KEY ? { kind: \"any\", exitId: exit.id } : { kind: \"state\", stateId: nodeId, exitId: exit.id }),\n },\n })),\n );\n return { nodes, edges };\n // `editor` целиком меняется на каждом рендере; от прогона берём `simulation` и `mode`.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [flow, catalog, issues, selection, mode, readOnly, editor.simulation, labels, select]);\n}\n\n/** Кнопка места на доске: у скина своя (`FlowBoardToggle`), без неё — простая на токенах `--flow-board-*`. */\nfunction BoardToggle(props: FlowBoardToggleProps) {\n const skin = useSkin();\n if (skin.FlowBoardToggle) return <skin.FlowBoardToggle {...props} />;\n return (\n <button\n type=\"button\"\n aria-label={props.label}\n title={props.label}\n aria-expanded={props.expanded}\n data-flow-board-toggle={props.kind}\n onClick={props.onClick}\n style={{\n font: \"inherit\",\n fontSize: 12,\n padding: \"6px 10px\",\n borderRadius: 8,\n cursor: \"pointer\",\n color: \"inherit\",\n background: \"var(--flow-board-handle-fill, #fff)\",\n border: \"1px solid var(--flow-board-handle, currentColor)\",\n }}\n >\n {props.showText ? props.label : props.kind === \"legend\" ? \"?\" : props.expanded ? \"×\" : \"+\"}\n </button>\n );\n}\n\n/** Кнопки масштаба скина: ведут доску через `useReactFlow`. */\nfunction ZoomControls() {\n const skin = useSkin();\n const { zoomIn, zoomOut, fitView } = useReactFlow();\n const zoom = useStore((store) => store.transform[2]);\n return (\n <skin.FlowZoomControls\n zoom={zoom}\n onZoomIn={() => void zoomIn({ duration: 150 })}\n onZoomOut={() => void zoomOut({ duration: 150 })}\n onFit={() => void fitView({ duration: 200, padding: 0.15 })}\n />\n );\n}\n\nfunction clientPoint(event: MouseEvent | TouchEvent): { x: number; y: number } | null {\n if (\"changedTouches\" in event) {\n const touch = event.changedTouches[0];\n return touch ? { x: touch.clientX, y: touch.clientY } : null;\n }\n return { x: event.clientX, y: event.clientY };\n}\n\nconst ignoreNodeClick = () => {};\n\nfunction Board({ editor, space }: { editor: FlowEditorController; space: BoardSpace }) {\n const spaceLabels = useFlowLabels().editor.board.space;\n const skin = useSkin();\n const model = useBoardModel(editor);\n const { screenToFlowPosition } = useReactFlow();\n const [nodes, setNodes] = useState<BoardNode[]>(model.nodes);\n\n // Узлы из сценария, но размеры (их меряет доска) и место во время перетаскивания — свои.\n useEffect(() => {\n setNodes((previous) => {\n const byId = new Map(previous.map((node) => [node.id, node]));\n return model.nodes.map((node) => {\n const old = byId.get(node.id);\n if (!old) return node;\n return { ...node, measured: old.measured, ...(old.dragging ? { position: old.position, dragging: true } : {}) } as BoardNode;\n });\n });\n }, [model.nodes]);\n\n const onNodesChange = useCallback((changes: NodeChange<BoardNode>[]) => setNodes((current) => applyNodeChanges(changes, current)), []);\n\n const { edit, connect, connectToNewState, select } = editor;\n\n const onConnect = useCallback(\n (connection: Connection) => {\n const owner = ownerOf(connection.source);\n if (connection.target === ANY_STATE_LAYOUT_KEY) return;\n if (connection.sourceHandle === NEW_EXIT_HANDLE || !connection.sourceHandle) {\n edit((flow) => {\n const made = addExit(flow, owner, \"judge\");\n return connectExit(made.flow, owner, made.exitId, connection.target);\n });\n return;\n }\n connect(owner, connection.sourceHandle, connection.target);\n },\n [connect, edit],\n );\n\n const onConnectEnd = useCallback(\n (event: MouseEvent | TouchEvent, state: FinalConnectionState) => {\n if (state.isValid || !state.fromNode || !state.fromHandle) return;\n const owner = ownerOf(state.fromNode.id);\n const exitId = state.fromHandle.id === NEW_EXIT_HANDLE ? null : (state.fromHandle.id ?? null);\n // Отпустили на узле мимо ручки — всё равно соединяем с ним.\n if (state.toNode && state.toNode.id !== ANY_STATE_LAYOUT_KEY) {\n onConnect({ source: state.fromNode.id, sourceHandle: exitId ?? NEW_EXIT_HANDLE, target: state.toNode.id, targetHandle: INPUT_HANDLE });\n return;\n }\n const point = clientPoint(event);\n if (!point) return;\n const at = screenToFlowPosition(point);\n connectToNewState(owner, exitId, { x: Math.round(at.x), y: Math.round(at.y - 40) });\n },\n [connectToNewState, onConnect, screenToFlowPosition],\n );\n\n const onNodeDragStop = useCallback(\n (_event: unknown, node: BoardNode) => edit((flow) => placeNode(flow, node.id, node.position)),\n [edit],\n );\n\n const selectable = editor.mode !== \"run\";\n const editable = selectable && !editor.readOnly;\n return (\n <ReactFlow<BoardNode, BoardEdge>\n nodes={nodes}\n edges={model.edges}\n nodeTypes={nodeTypes}\n edgeTypes={edgeTypes}\n onNodesChange={onNodesChange}\n onConnect={onConnect}\n onConnectEnd={onConnectEnd}\n onNodeDragStop={onNodeDragStop}\n // Без перетаскивания и связей (только просмотр) доска отключает клики по узлам, если нет обработчика: нужен хотя бы пустой.\n onNodeClick={ignoreNodeClick}\n onPaneClick={() => selectable && select({ kind: \"overview\" })}\n nodesConnectable={editable}\n elementsSelectable={false}\n deleteKeyCode={null}\n selectionKeyCode={null}\n multiSelectionKeyCode={null}\n fitView\n fitViewOptions={{ padding: 0.15 }}\n minZoom={0.2}\n maxZoom={2}\n proOptions={{ hideAttribution: true }}\n >\n <Background variant={BackgroundVariant.Dots} gap={22} size={1.2} />\n {!space.legendHidden && (\n <Panel position=\"bottom-left\" className=\"flow-board__legend\">\n <div className=\"flow-board__legend-stack\" style={{ display: \"flex\", flexDirection: \"column\", alignItems: \"flex-start\", gap: 8 }}>\n {space.legendOpen && <skin.FlowLegend kinds={LEGEND_KINDS} />}\n <BoardToggle kind=\"legend\" label={spaceLabels.legend} expanded={space.legendOpen} showText onClick={space.toggleLegend} />\n </div>\n </Panel>\n )}\n {space.inspectorToggleable && (\n <Panel position=\"top-right\">\n <BoardToggle\n kind=\"inspector\"\n label={space.inspectorOpen ? spaceLabels.hideInspector : spaceLabels.showInspector}\n expanded={space.inspectorOpen}\n onClick={space.toggleInspector}\n />\n </Panel>\n )}\n <Panel position=\"bottom-right\">\n <div style={{ display: \"flex\", alignItems: \"center\", gap: 8 }}>\n {!space.minimapHidden && (\n <span className=\"flow-board__minimap-toggle\" style={{ display: \"contents\" }}>\n <BoardToggle\n kind=\"minimap\"\n label={space.minimapOpen ? spaceLabels.hideMinimap : spaceLabels.showMinimap}\n expanded={space.minimapOpen}\n onClick={space.toggleMinimap}\n />\n </span>\n )}\n <ZoomControls />\n </div>\n </Panel>\n {space.minimapOpen && <MiniMap className=\"flow-board__minimap\" pannable zoomable position=\"bottom-right\" style={{ marginBottom: 76 }} />}\n </ReactFlow>\n );\n}\n\n/** Доска редактора. Свой `ReactFlowProvider`: другой сценарий — доска заново и «весь граф» в экран. */\nexport function FlowBoard({ editor, skin, space }: { editor: FlowEditorController; skin: FlowEditorSkin; space: BoardSpace }) {\n return (\n <SkinContext.Provider value={skin}>\n <style>{FLOW_BOARD_CSS}</style>\n <ReactFlowProvider key={editor.flow.id}>\n <Board editor={editor} space={space} />\n </ReactFlowProvider>\n </SkinContext.Provider>\n );\n}\n","// Стили, без которых доска `@xyflow/react` не работает: слои, места узлов и ручек, мини-карта, панели. Взяты из\n// `@xyflow/react/dist/base.css` (MIT) и урезаны. Цвета — переменные `--flow-board-*`: их задаёт скин, а здесь только\n// нейтральные запасные значения. Стиль вставляется рядом с доской, приложению ничего импортировать не нужно.\n\nexport const FLOW_BOARD_CSS = `\n.react-flow { direction: ltr; position: relative; width: 100%; height: 100%; overflow: hidden; z-index: 0; }\n.react-flow__container, .react-flow__edgelabel-renderer, .react-flow__viewport-portal {\n position: absolute; width: 100%; height: 100%; top: 0; left: 0;\n}\n.react-flow__pane { z-index: 1; touch-action: none; }\n.react-flow__pane.draggable { cursor: grab; }\n.react-flow__pane.dragging { cursor: grabbing; }\n.react-flow__viewport { transform-origin: 0 0; z-index: 2; pointer-events: none; }\n.react-flow__renderer { z-index: 4; }\n.react-flow__background { pointer-events: none; z-index: -1; }\n.react-flow__background-pattern.dots { fill: var(--flow-board-dots, rgba(128, 128, 128, 0.35)); }\n.react-flow .react-flow__edges { position: absolute; }\n.react-flow .react-flow__edges svg { overflow: visible; position: absolute; pointer-events: none; }\n.react-flow__edge { pointer-events: visibleStroke; }\n.react-flow__edge.inactive { pointer-events: none; }\n.react-flow__edge:focus, .react-flow__edge:focus-visible { outline: none; }\n.react-flow__connection { pointer-events: none; }\n.react-flow__connection-path { stroke: var(--flow-board-connection, currentColor); stroke-width: 2; fill: none; stroke-dasharray: 4 4; }\nsvg.react-flow__connectionline { z-index: 1001; overflow: visible; position: absolute; }\n.react-flow__nodes { pointer-events: none; transform-origin: 0 0; }\n.react-flow__node {\n position: absolute; user-select: none; pointer-events: all; transform-origin: 0 0; box-sizing: border-box; cursor: default;\n}\n.react-flow__node.draggable { cursor: grab; }\n.react-flow__node.draggable.dragging { cursor: grabbing; }\n.react-flow__node:focus, .react-flow__node:focus-visible { outline: none; }\n.react-flow__handle {\n position: absolute; pointer-events: none; width: 10px; height: 10px; min-width: 5px; min-height: 5px; border-radius: 999px;\n background: var(--flow-board-handle-fill, #fff); border: 1.5px solid var(--flow-board-handle, currentColor);\n}\n.react-flow__handle.connectingfrom, .react-flow__handle.connectionindicator { pointer-events: all; cursor: crosshair; }\n.react-flow__handle-left { top: 50%; left: 0; transform: translate(-50%, -50%); }\n.react-flow__handle-right { top: 50%; right: 0; transform: translate(50%, -50%); }\n.react-flow__handle-top { top: 0; left: 50%; transform: translate(-50%, -50%); }\n.react-flow__handle-bottom { top: auto; bottom: 0; left: 50%; transform: translate(-50%, 50%); }\n.react-flow__panel { position: absolute; z-index: 5; margin: 16px; }\n.react-flow__panel.top { top: 0; }\n.react-flow__panel.bottom { bottom: 0; }\n.react-flow__panel.left { left: 0; }\n.react-flow__panel.right { right: 0; }\n.react-flow__panel.top.center, .react-flow__panel.bottom.center { left: 50%; transform: translateX(-16px) translateX(-50%); }\n.react-flow__minimap { background: var(--flow-board-minimap, #fff); border-radius: 12px; overflow: hidden; }\n.react-flow__minimap-svg { display: block; }\n.react-flow__minimap-mask { fill: var(--flow-board-minimap-mask, rgba(128, 128, 128, 0.15)); }\n.react-flow__minimap-node { fill: var(--flow-board-minimap-node, rgba(128, 128, 128, 0.35)); }\n.flow-board__new-exit.react-flow__handle {\n top: auto; bottom: 10px; right: 0; transform: translate(50%, 0); opacity: 0.55;\n}\n.flow-board__new-exit.react-flow__handle:hover { opacity: 1; }\n@media (max-width: 860px) {\n .flow-board__legend, .flow-board__minimap, .flow-board__minimap-toggle { display: none !important; }\n}\n`;\n","import {\n DEFAULT_LATE_START_HOURS,\n type AgentFlow,\n type FlowAfterEnd,\n type FlowCondition,\n type FlowDuration,\n type FlowExit,\n type FlowNudges,\n type FlowSchedule,\n type FlowState,\n} from \"../../format/flow-format\";\nimport type { FlowEditorLabels } from \"../../labels/editor\";\nimport { addExit, updateExit } from \"./editor-model\";\n\n// Правки «Дней и времени», продолжительности и касаний ноды: чистые функции, каждая возвращает новый `AgentFlow`.\n\n/** «Дни и время» при включении: день с 9:00, порог позднего старта по умолчанию, без прощания. */\nexport const DEFAULT_SCHEDULE: FlowSchedule = { dayStart: \"09:00\", lateStartHours: DEFAULT_LATE_START_HOURS, farewellOnDeadline: false };\n\n/** Свои касания ноды без общего образца: 15 мин · 1 ч · 4 ч тишины. */\nexport const DEFAULT_NUDGES: FlowNudges = {\n afterSilence: [\n { amount: 15, unit: \"min\" },\n { amount: 1, unit: \"h\" },\n { amount: 4, unit: \"h\" },\n ],\n};\n\n/** Без ключей со значением `undefined`; пустой объект — `undefined`. */\nfunction compact<T extends object>(value: T): T | undefined {\n const entries = Object.entries(value).filter(([, item]) => item !== undefined && item !== \"\");\n return entries.length === 0 ? undefined : (Object.fromEntries(entries) as T);\n}\n\nfunction withOptional<T extends object, K extends keyof T>(target: T, key: K, value: T[K] | undefined): T {\n const { [key]: _old, ...rest } = target;\n return (value === undefined ? rest : { ...rest, [key]: value }) as T;\n}\n\nexport function setScheduleOn(flow: AgentFlow, on: boolean): AgentFlow {\n if (on) return flow.schedule ? flow : { ...flow, schedule: { ...DEFAULT_SCHEDULE } };\n return withOptional(flow, \"schedule\", undefined);\n}\n\nexport type SchedulePatch = { [K in keyof FlowSchedule]?: FlowSchedule[K] | undefined };\n\n/** Правка «Дней и времени»: `undefined` и пустая строка убирают поле, пустые вложенные разделы — целиком. */\nexport function updateSchedule(flow: AgentFlow, patch: SchedulePatch): AgentFlow {\n let schedule: FlowSchedule = flow.schedule ?? { ...DEFAULT_SCHEDULE };\n for (const [key, raw] of Object.entries(patch) as Array<[keyof FlowSchedule, unknown]>) {\n const value = raw !== null && typeof raw === \"object\" && !Array.isArray(raw) && key !== \"nudges\" ? compact(raw) : raw === \"\" ? undefined : raw;\n schedule = withOptional(schedule, key, value as never);\n }\n return { ...flow, schedule };\n}\n\nexport function setAfterEnd(flow: AgentFlow, mode: FlowAfterEnd): AgentFlow {\n return { ...flow, afterEnd: mode };\n}\n\n// ---------- «Длится» ----------\n\nexport type DurationUnit = \"h\" | \"d\" | \"program_day\";\n\n/**\n * Продолжительность ноды: выход «длится N дней сценария» (`state_days`), «до дня N программы» (`program_day`, `amount` —\n * номер дня) или «N часов в этом состоянии».\n */\nexport interface StateDuration {\n exitId: string;\n amount: number;\n unit: DurationUnit;\n to: string | null;\n}\n\nfunction durationExit(exit: FlowExit): StateDuration | null {\n const { when } = exit;\n if (when.type !== \"timer\") return null;\n if (when.from === \"state_days\") return { exitId: exit.id, amount: when.days, unit: \"d\", to: exit.to };\n if (when.from === \"program_day\") return { exitId: exit.id, amount: when.day, unit: \"program_day\", to: exit.to };\n if (when.from === \"in_state\" && when.unit === \"h\") return { exitId: exit.id, amount: when.amount, unit: \"h\", to: exit.to };\n return null;\n}\n\n/** Первый выход-продолжительность ноды; минуты «в этом состоянии» — обычный таймер, не «Длится». */\nexport function durationOf(state: FlowState): StateDuration | null {\n for (const exit of state.exits) {\n const found = durationExit(exit);\n if (found) return found;\n }\n return null;\n}\n\n/** «Длится»: дни — `state_days`, день программы — `program_day`, часы — `in_state`. Правится тот же выход; `null` — выход убирается. */\nexport function setDuration(flow: AgentFlow, stateId: string, value: { amount: number; unit: DurationUnit } | null): AgentFlow {\n const state = flow.states.find((candidate) => candidate.id === stateId);\n if (!state) return flow;\n const current = durationOf(state);\n if (value === null) {\n if (!current) return flow;\n return { ...flow, states: flow.states.map((candidate) => (candidate.id === stateId ? { ...candidate, exits: candidate.exits.filter((exit) => exit.id !== current.exitId) } : candidate)) };\n }\n const amount = Math.max(1, Math.round(value.amount) || 1);\n const when: FlowCondition =\n value.unit === \"d\"\n ? { type: \"timer\", from: \"state_days\", days: amount }\n : value.unit === \"program_day\"\n ? { type: \"timer\", from: \"program_day\", day: amount }\n : { type: \"timer\", from: \"in_state\", amount, unit: \"h\" };\n if (current) return updateExit(flow, stateId, current.exitId, { when, to: current.to });\n const made = addExit(flow, stateId, \"timer\");\n return updateExit(made.flow, stateId, made.exitId, { when, to: null });\n}\n\n// ---------- Касания ----------\n\nexport type NudgesMode = \"inherit\" | \"own\" | \"off\";\n\nexport function nudgesMode(state: FlowState): NudgesMode {\n if (state.nudges === \"off\") return \"off\";\n return state.nudges ? \"own\" : \"inherit\";\n}\n\n/** Касания ноды: как у сценария (поля нет), свои (образец — общие или 15 мин · 1 ч · 4 ч), выкл. */\nexport function setStateNudges(flow: AgentFlow, stateId: string, mode: NudgesMode): AgentFlow {\n return {\n ...flow,\n states: flow.states.map((state) => {\n if (state.id !== stateId || nudgesMode(state) === mode) return state;\n if (mode === \"inherit\") return withOptional(state, \"nudges\", undefined);\n if (mode === \"off\") return { ...state, nudges: \"off\" };\n return { ...state, nudges: structuredClone(flow.schedule?.nudges ?? DEFAULT_NUDGES) };\n }),\n };\n}\n\n/** Своё расписание касаний ноды: пустые части убираются, срок в днях остаётся. */\nexport function updateStateNudges(flow: AgentFlow, stateId: string, nudges: FlowNudges): AgentFlow {\n return {\n ...flow,\n states: flow.states.map((state) => {\n if (state.id !== stateId) return state;\n const days = state.nudges && state.nudges !== \"off\" ? state.nudges.days : undefined;\n return { ...state, nudges: { ...cleanNudges(nudges), ...(days !== undefined && { days }) } };\n }),\n };\n}\n\n/** Сколько дней действуют свои касания ноды, считая день входа; `null` — всё время в ноде. */\nexport function setStateNudgesDays(flow: AgentFlow, stateId: string, days: number | null): AgentFlow {\n return {\n ...flow,\n states: flow.states.map((state) => {\n if (state.id !== stateId || !state.nudges || state.nudges === \"off\") return state;\n const { days: _days, ...rest } = state.nudges;\n return { ...state, nudges: days === null ? rest : { ...rest, days: Math.max(1, Math.round(days) || 1) } };\n }),\n };\n}\n\n/** Срок своих касаний ноды в днях; всё время в ноде или касания не свои — `null`. */\nexport function stateNudgesDays(state: FlowState): number | null {\n return state.nudges && state.nudges !== \"off\" ? (state.nudges.days ?? null) : null;\n}\n\n/** Касания по умолчанию в «Днях и времени»; `null` — без общих касаний. */\nexport function updateScheduleNudges(flow: AgentFlow, nudges: FlowNudges | null): AgentFlow {\n return updateSchedule(flow, { nudges: nudges === null ? undefined : cleanNudges(nudges) });\n}\n\nfunction cleanNudges(nudges: FlowNudges): FlowNudges {\n let clean: FlowNudges = { afterSilence: nudges.afterSilence };\n if (nudges.dailyAt?.length) clean = { ...clean, dailyAt: nudges.dailyAt };\n if (nudges.giveUpAfter) clean = { ...clean, giveUpAfter: nudges.giveUpAfter };\n return clean;\n}\n\n// ---------- Подписи ----------\n\n/** «15 мин», «4 ч», «3 дн.». */\nexport function durationText(duration: FlowDuration, labels: FlowEditorLabels): string {\n return `${duration.amount} ${labels.units[duration.unit]}`;\n}\n\n/** Подпись «Длится» и касаний на карточке ноды: «1 день · касания 15 мин · 1 ч · 4 ч». Ничего своего — пусто. */\nexport function stateTimingText(flow: AgentFlow, state: FlowState, labels: FlowEditorLabels): string {\n const parts: string[] = [];\n const duration = durationOf(state);\n if (duration) {\n parts.push(duration.unit === \"d\" ? labels.days(duration.amount) : duration.unit === \"program_day\" ? labels.programDay(duration.amount) : `${duration.amount} ${labels.units.h}`);\n }\n if (state.nudges === \"off\") parts.push(labels.board.noNudges);\n else if (state.nudges) {\n const steps = state.nudges.afterSilence.map((step) => durationText(step, labels));\n const daily = state.nudges.dailyAt ?? [];\n const days = state.nudges.days === undefined ? \"\" : ` ${labels.board.nudgesDays(state.nudges.days)}`;\n if (steps.length + daily.length > 0) parts.push(`${labels.board.nudges} ${[...steps, ...daily].join(\" · \")}${days}`);\n }\n return parts.join(\" · \");\n}\n","import { FLOW_OPS_BY_FIELD_TYPE, type AgentFlow, type DataCondition, type FlowExit, type FlowField } from \"../../format/flow-format\";\nimport type { FlowRun } from \"../../engine/flow-run\";\nimport { nextTransition, type FlowEvent } from \"../../engine/next-transition\";\nimport { activeExits, fieldById, stateById } from \"../../engine/flow-graph\";\nimport { applyTransition, noteAgentAnswer, noteHumanMessage, noteSideQuestion, startRun } from \"../../engine/run-updates\";\nimport { sideQuestion } from \"../../engine/side-questions\";\nimport { timerDueAt } from \"../../engine/timers\";\n\n// Прогон в редакторе: автор выбирает, что произошло, а решает движок — тот же `nextTransition`, что в рабочем чате.\n// Часы прогона свои: каждый шаг — минута разговора, таймер перематывает к своему сроку.\n\nconst STEP_MS = 60_000;\n\n/** Шаг пути прогона: куда пришли и по какому условию; `nothing` — «ничего из этого», агент остался. */\nexport interface SimulationStep {\n stateId: string;\n exitId: string | null;\n nothing: boolean;\n}\n\nexport interface Simulation {\n run: FlowRun;\n /** Карточка клиента в прогоне: id поля → значение и когда записано. */\n card: Record<string, { value: unknown; updatedAt: number }>;\n now: number;\n timeZone: string;\n steps: SimulationStep[];\n /** Прогон до последнего шага — для «шаг назад». */\n previous: Simulation | null;\n}\n\n/** Выбор «что произошло»: условие и куда приведёт движок (`null` — не сработает). */\nexport interface SimulationChoice {\n exitId: string;\n own: boolean;\n target: string | null;\n}\n\nexport function startSimulation(flow: AgentFlow, options: { now: number; timeZone: string }): Simulation {\n // Агент начинает разговор первым: от этого считается тишина человека.\n const run = noteAgentAnswer(startRun(flow, options.now), options.now);\n return { run, card: {}, now: options.now, timeZone: options.timeZone, steps: [{ stateId: run.state, exitId: null, nothing: false }], previous: null };\n}\n\nexport function simulationChoices(flow: AgentFlow, sim: Simulation): SimulationChoice[] {\n const state = stateById(flow, sim.run.state);\n if (!state) return [];\n return activeExits(flow, state).map(({ exit, own }) => {\n const after = chooseExit(flow, sim, exit.id);\n return { exitId: exit.id, own, target: after.steps.length > sim.steps.length ? after.run.state : null };\n });\n}\n\nfunction findExit(flow: AgentFlow, exitId: string): FlowExit | undefined {\n return [...flow.states.flatMap((state) => state.exits), ...flow.anyState.exits].find((exit) => exit.id === exitId);\n}\n\n/** Значение, при котором условие по данным выполнено. Уже подходящее не трогаем. */\nfunction fittingValue(condition: DataCondition, field: FlowField): unknown {\n const expected = condition.value;\n switch (condition.op) {\n case \"eq\":\n case \"contains\":\n return expected;\n case \"gt\":\n return typeof expected === \"number\" ? expected + 1 : expected;\n case \"lt\":\n return typeof expected === \"number\" ? expected - 1 : expected;\n case \"filled\":\n if (field.type === \"number\") return 1;\n return field.type === \"choice\" && field.options.length > 0 ? field.options[0] : \"✓\";\n }\n}\n\nfunction writeValue(flow: AgentFlow, sim: Simulation, fieldId: string, value: unknown): Simulation {\n const found = fieldById(flow, fieldId);\n if (!found) return sim;\n if (found.place === \"notes\") return { ...sim, run: { ...sim.run, notes: { ...sim.run.notes, [fieldId]: value } } };\n return { ...sim, card: { ...sim.card, [fieldId]: { value, updatedAt: sim.now } } };\n}\n\nfunction cardValues(sim: Simulation): Record<string, unknown> {\n return Object.fromEntries(Object.entries(sim.card).map(([id, entry]) => [id, entry.value]));\n}\n\n/**\n * Шаг: человек написал (кроме таймера), движок ищет переход по событию, агент ответил. Если между делом был вопрос о\n * человеке — он задан, следующий по темпу сценария.\n */\nfunction step(flow: AgentFlow, before: Simulation, prepare: (sim: Simulation) => { sim: Simulation; event: FlowEvent | null; human: boolean }): Simulation {\n const asked = sideQuestion(flow, before.run, { card: before.card, now: before.now });\n const prepared = prepare({ ...before, now: before.now + STEP_MS });\n const sim = prepared.sim;\n let run = prepared.human ? noteHumanMessage(sim.run, sim.now) : sim.run;\n const transition = prepared.event ? nextTransition(flow, run, prepared.event, sim.now) : null;\n const steps = [...sim.steps];\n if (transition) {\n run = applyTransition(flow, run, transition);\n steps.push({ stateId: transition.to, exitId: transition.exitId, nothing: false });\n } else if (prepared.event === null) {\n steps.push({ stateId: run.state, exitId: null, nothing: true });\n } else {\n // Условие не сработало (нет цели, «назад» некуда): прогон не меняется.\n return before;\n }\n run = noteAgentAnswer(run, sim.now);\n if (asked && asked.reason !== \"learn\") run = noteSideQuestion(run);\n return { ...sim, run, steps, previous: before };\n}\n\n/** Автор выбрал условие: собираем событие, на которое оно срабатывает, и отдаём движку. */\nexport function chooseExit(flow: AgentFlow, sim: Simulation, exitId: string): Simulation {\n const exit = findExit(flow, exitId);\n if (!exit) return sim;\n const when = exit.when;\n return step(flow, sim, (current) => {\n switch (when.type) {\n case \"judge\":\n return { sim: current, human: true, event: { type: \"verdict\", exitId, probability: 1, decidedBy: \"judge\" } };\n case \"event\":\n return {\n sim: current,\n human: when.event === \"message\",\n event: { type: \"event\", event: when.event, ...(when.name === undefined ? {} : { name: when.name }) },\n };\n case \"timer\": {\n const due = timerDueAt(when, current.run, current.timeZone);\n // Часы прогона идут только вперёд: срок в прошлом — срабатывает сейчас.\n const now = due === null ? current.now : Math.max(current.now - STEP_MS, due);\n return { sim: { ...current, now }, human: false, event: { type: \"timer\", exitId, timeZone: current.timeZone } };\n }\n case \"data\": {\n const found = fieldById(flow, when.field);\n if (!found || !FLOW_OPS_BY_FIELD_TYPE[found.field.type].includes(when.op)) {\n return { sim: current, human: true, event: { type: \"data\", field: when.field, card: cardValues(current) } };\n }\n const filled = writeValue(flow, current, when.field, fittingValue(when, found.field));\n return { sim: filled, human: true, event: { type: \"data\", field: when.field, card: cardValues(filled) } };\n }\n }\n });\n}\n\n/** «Ничего из этого»: человек написал, агент ответил, остались в том же состоянии. */\nexport function chooseNothing(flow: AgentFlow, sim: Simulation): Simulation {\n return step(flow, sim, (current) => ({ sim: current, human: true, event: null }));\n}\n\n/**\n * Автор вписал, что агент знает о человеке. Число — для числовых полей; пусто — поле забыто. Если от этого сработало\n * условие по данным — переход, как в рабочем чате.\n */\nexport function setKnownValue(flow: AgentFlow, sim: Simulation, fieldId: string, text: string): Simulation {\n const found = fieldById(flow, fieldId);\n if (!found) return sim;\n const trimmed = text.trim();\n const value = trimmed === \"\" ? undefined : found.field.type === \"number\" && Number.isFinite(Number(trimmed)) ? Number(trimmed) : trimmed;\n let written = writeValue(flow, sim, fieldId, value);\n if (value === undefined) {\n written =\n found.place === \"notes\"\n ? { ...written, run: { ...written.run, notes: withoutKey(written.run.notes, fieldId) } }\n : { ...written, card: withoutKey(written.card, fieldId) };\n return written;\n }\n const transition = nextTransition(flow, written.run, { type: \"data\", field: fieldId, card: cardValues(written) }, written.now);\n if (!transition) return written;\n return {\n ...written,\n run: noteAgentAnswer(applyTransition(flow, written.run, transition), written.now),\n steps: [...written.steps, { stateId: transition.to, exitId: transition.exitId, nothing: false }],\n previous: sim,\n };\n}\n\nfunction withoutKey<T>(record: Record<string, T>, key: string): Record<string, T> {\n const { [key]: _removed, ...rest } = record;\n return rest;\n}\n\n/** id поля, о котором агент спросит сейчас; `null` — ни о чём. */\nexport function nextQuestionField(flow: AgentFlow, sim: Simulation): string | null {\n return sideQuestion(flow, sim.run, { card: sim.card, now: sim.now })?.fieldId ?? null;\n}\n\nexport function stepBack(sim: Simulation): Simulation {\n return sim.previous ?? sim;\n}\n","import { fieldById } from \"../../engine/flow-graph\";\nimport {\n DEFAULT_SIDE_TASK_MAX_ATTEMPTS,\n type AgentFlow,\n type ClientCardField,\n type FlowCatalog,\n type FlowCatalogField,\n type FlowField,\n type FlowSideTask,\n} from \"../../format/flow-format\";\nimport type { FieldList } from \"./editor-model\";\n\n// Правки попутных задач и полей из словаря приложения (`catalog.fields`): чистые функции, каждая возвращает новый `AgentFlow`.\n\nfunction freeTaskId(flow: AgentFlow): string {\n const used = new Set((flow.sideTasks ?? []).map((task) => task.id));\n let index = 1;\n while (used.has(`task_${index}`)) index += 1;\n return `task_${index}`;\n}\n\nfunction withTasks(flow: AgentFlow, tasks: FlowSideTask[]): AgentFlow {\n if (tasks.length > 0) return { ...flow, sideTasks: tasks };\n const { sideTasks: _empty, ...rest } = flow;\n return rest;\n}\n\nexport function addSideTask(flow: AgentFlow, text: string): { flow: AgentFlow; sideTaskId: string } {\n const sideTaskId = freeTaskId(flow);\n const task: FlowSideTask = { id: sideTaskId, text, maxAttempts: DEFAULT_SIDE_TASK_MAX_ATTEMPTS, perConversation: false };\n return { sideTaskId, flow: withTasks(flow, [...(flow.sideTasks ?? []), task]) };\n}\n\nexport type SideTaskPatch = { [K in keyof FlowSideTask]?: FlowSideTask[K] | undefined };\n\n/** Правка задачи: пустые «когда» и «поле» убираются, попыток — хотя бы одна. */\nexport function updateSideTask(flow: AgentFlow, sideTaskId: string, patch: SideTaskPatch): AgentFlow {\n return withTasks(\n flow,\n (flow.sideTasks ?? []).map((task) => {\n if (task.id !== sideTaskId) return task;\n const next: Record<string, unknown> = { ...task, ...patch };\n for (const key of [\"when\", \"field\"] as const) if (next[key] === undefined || next[key] === \"\") delete next[key];\n if (patch.maxAttempts !== undefined) next.maxAttempts = Math.max(1, Math.round(patch.maxAttempts) || 1);\n return next as unknown as FlowSideTask;\n }),\n );\n}\n\nexport function removeSideTask(flow: AgentFlow, sideTaskId: string): AgentFlow {\n return withTasks(flow, (flow.sideTasks ?? []).filter((task) => task.id !== sideTaskId));\n}\n\n/** Поля словаря приложения, которых ещё нет ни в карточке, ни в заметках. */\nexport function catalogFieldsToAdd(flow: AgentFlow, catalog: FlowCatalog): FlowCatalogField[] {\n return (catalog.fields ?? []).filter((field) => !fieldById(flow, field.id));\n}\n\n/** Поле словаря приложения в карточку или заметки: id, название, тип и варианты — как у приложения. Уже есть — без правок. */\nexport function addCatalogField(flow: AgentFlow, list: FieldList, field: FlowCatalogField): AgentFlow {\n if (fieldById(flow, field.id)) return flow;\n const base: FlowField = { id: field.id, name: field.title, about: \"\", type: field.type, options: field.type === \"choice\" ? [...(field.options ?? [])] : [] };\n if (list === \"clientCard\") {\n const card: ClientCardField = { ...base, refreshAfterMonths: null };\n return { ...flow, clientCard: [...flow.clientCard, card] };\n }\n return { ...flow, chatNotes: [...flow.chatNotes, base] };\n}\n\n/** Поле, по которому задача решена. Поле из словаря приложения, которого нет в сценарии, попадает в карточку. */\nexport function setSideTaskField(flow: AgentFlow, sideTaskId: string, fieldId: string | null, catalog: FlowCatalog): AgentFlow {\n const fromApp = fieldId === null ? undefined : catalog.fields?.find((field) => field.id === fieldId);\n const withField = fromApp ? addCatalogField(flow, \"clientCard\", fromApp) : flow;\n return updateSideTask(withField, sideTaskId, { field: fieldId ?? undefined });\n}\n","import { useCallback, useMemo, useRef, useState } from \"react\";\nimport { checkFlow } from \"../../check/check-flow\";\nimport type { AgentFlow, FlowCatalog, FlowIssue, FlowPoint } from \"../../format/flow-format\";\nimport type { StateMap } from \"../../engine/migrate-run\";\nimport type { ChatsInState } from \"../../store/flow-store\";\nimport type { FlowEditorMode, FlowIssueCount } from \"../flow-editor-skin\";\nimport { useFlowLabels } from \"../flow-labels\";\nimport { appIssues, type FlowAppChecks, type FlowAppIssue } from \"../../check/app-checks\";\nimport {\n addExit,\n addState as addStateTo,\n connectExit,\n flowFingerprint,\n flowToJson,\n loadFlowJson,\n removeState as removeStateFrom,\n type ExitOwner,\n} from \"./editor-model\";\nimport {\n chooseExit,\n chooseNothing,\n setKnownValue,\n startSimulation,\n stepBack,\n type Simulation,\n} from \"./flow-simulation\";\n\n/** Что открыто в панели справа. */\nexport type FlowSelection =\n | { kind: \"overview\"; sideTaskId?: string }\n | { kind: \"state\"; stateId: string; exitId?: string }\n | { kind: \"any\"; exitId?: string }\n | { kind: \"card\" };\n\nexport type FlowDialog = \"json\" | \"migrate\" | null;\n\n/**\n * Перевод идущих чатов на текущую версию. Данные и действие даёт приложение — редактор не знает, где сервер:\n * `chatsByState` — чаты на прежних версиях (`flow.chatsByState`), `migrate` — перевод с картой удалённых состояний\n * (`flow.migrateChats`). Отбор чатов в обоих вызовах один и тот же: окно показывает ровно тех, кого переведёт.\n */\nexport interface FlowMigration {\n chatsByState(): Promise<ChatsInState[]>;\n migrate(map: StateMap): Promise<{ moved: number }>;\n /** Название состояния прежней версии; нет — берём из текущей или показываем id. */\n stateTitle?(versionId: string, stateId: string): string | undefined;\n}\n\n/**\n * Ответ `onSave`. Ничего (`void`) и `{ ok: true }` — сохранено. `{ ok: false, issues }` — приложение отказало без\n * исключения: шапка не пишет «Сохранено», `issues` встают у нод и выходов, как находки «Проверить граф».\n */\nexport type FlowSaveResult = void | { ok: true } | { ok: false; issues?: ReadonlyArray<Pick<FlowAppIssue, \"path\" | \"message\">> };\n\nexport interface UseFlowEditorOptions {\n value: AgentFlow;\n onChange(flow: AgentFlow): void;\n /** Сохранить сценарий. Отказ — `{ ok: false, issues }` или исключение (оно не уходит в консоль необработанным). */\n onSave?(flow: AgentFlow): FlowSaveResult | Promise<FlowSaveResult>;\n /**\n * Только просмотр: доску нельзя менять (двигать, соединять, удалять, править панели), нельзя сохранять и загружать\n * JSON. Смотреть, проверять граф, прогонять и открывать JSON можно. Нужно, пока сценарий правит внешний агент.\n */\n readOnly?: boolean;\n /**\n * Сценарий, который сейчас сохранён у приложения (на сервере). Если задан, «Сохранено» и доступность кнопки сохранения\n * считаются от него, а не от `value` при показе доски: вернулись на вкладку с несохранённой правкой — доска честно\n * скажет «Не сохранено». После успешного `onSave` доска считает сохранённым отправленное, пока не придёт новый\n * `savedValue`. Без него сохранённым считается `value` при показе доски.\n */\n savedValue?: AgentFlow;\n /** Что объявило приложение: инструменты, события и кнопки, виджеты. */\n catalog: FlowCatalog;\n migration?: FlowMigration;\n /** Пояс человека для таймеров «время суток» в прогоне; по умолчанию — пояс браузера. */\n timeZone?: string;\n now?(): number;\n /**\n * Свои проверки приложения в «Проверить сценарий»: `(flow) => [{ path: \"states[2]\", message }]`. Находки идут после\n * встроенных, клик ведёт на место. Те же проверки приложение передаёт в `checkFlow(flow, catalog, { checks })`.\n */\n checks?: FlowAppChecks;\n}\n\nexport interface FlowMigrateRow extends ChatsInState {\n stateTitle: string;\n removed: boolean;\n target: string | null;\n}\n\nexport interface FlowMigrateController {\n rows: FlowMigrateRow[];\n busy: boolean;\n failed: boolean;\n moved: number | null;\n canMigrate: boolean;\n open(): void;\n setTarget(stateId: string, target: string): void;\n run(): Promise<void>;\n}\n\nfunction countIssues(issues: FlowIssue[]): FlowIssueCount {\n return {\n errors: issues.filter((issue) => issue.level === \"error\").length,\n warnings: issues.filter((issue) => issue.level === \"warning\").length,\n };\n}\n\n/** Проверки приложения; упали — редактор работает дальше, а находка говорит об этом. */\nfunction runAppChecks(flow: AgentFlow, checks: FlowAppChecks | undefined, failed: string): FlowIssue[] {\n if (!checks) return [];\n try {\n return appIssues(flow, checks(flow));\n } catch (error) {\n console.error(\"[flow] app checks failed\", error);\n return [{ level: \"warning\", code: \"app_check_failed\", message: failed, place: {} }];\n }\n}\n\nconst NO_ISSUES: FlowIssue[] = [];\n\nconst browserTimeZone = () => Intl.DateTimeFormat().resolvedOptions().timeZone || \"UTC\";\n\n/** Логика редактора сценария: правки, выбор, проверка, прогон, JSON, сохранение, перевод чатов. Скин только рисует. */\nexport function useFlowEditor(options: UseFlowEditorOptions) {\n const { value: flow, onChange, catalog } = options;\n const labels = useFlowLabels().editor;\n const latest = useRef(options);\n latest.current = options;\n\n const [selection, setSelection] = useState<FlowSelection>({ kind: \"overview\" });\n const [mode, setModeState] = useState<FlowEditorMode>(\"edit\");\n const [dialog, setDialog] = useState<FlowDialog>(null);\n const [jsonErrors, setJsonErrors] = useState<string[]>([]);\n const [simulation, setSimulation] = useState<Simulation | null>(null);\n const [saving, setSaving] = useState(false);\n const [mountedPrint] = useState(() => flowFingerprint(flow));\n const savedPrint = useMemo(() => (options.savedValue ? flowFingerprint(options.savedValue) : undefined), [options.savedValue]);\n // Отправленное через `onSave` считается сохранённым, пока приложение не прислало другой `savedValue`.\n const [sent, setSent] = useState<{ print: string; base: string | undefined } | null>(null);\n const savedJson = sent && sent.base === savedPrint ? sent.print : (savedPrint ?? mountedPrint);\n // Отказ в сохранении держится, пока сценарий тот же: любая правка снимает его.\n const [rejection, setRejection] = useState<{ flow: AgentFlow; issues: FlowIssue[] } | null>(null);\n const readOnly = options.readOnly === true;\n\n const checks = options.checks;\n const saveFailed = rejection !== null && rejection.flow === flow;\n const rejectedIssues = saveFailed ? rejection.issues : NO_ISSUES;\n const issues = useMemo(\n () => [...checkFlow(flow, catalog), ...runAppChecks(flow, checks, labels.checkPanel.appCheckFailed), ...rejectedIssues],\n [flow, catalog, checks, labels, rejectedIssues],\n );\n const issueCount = useMemo(() => countIssues(issues), [issues]);\n const json = useMemo(() => flowToJson(flow), [flow]);\n const print = useMemo(() => flowFingerprint(flow), [flow]);\n const dirty = print !== savedJson;\n\n // Выбранное состояние удалили — панель возвращается к обзору.\n const visibleSelection: FlowSelection =\n selection.kind === \"state\" && !flow.states.some((state) => state.id === selection.stateId) ? { kind: \"overview\" } : selection;\n\n const edit = useCallback((change: (flow: AgentFlow) => AgentFlow) => {\n if (latest.current.readOnly) return;\n onChange(change(latest.current.value));\n }, [onChange]);\n\n const select = useCallback((next: FlowSelection) => {\n setSelection(next);\n setModeState((current) => (current === \"check\" ? \"edit\" : current));\n }, []);\n\n const addState = useCallback(\n (at?: FlowPoint): string => {\n if (latest.current.readOnly) return \"\";\n const made = addStateTo(latest.current.value, { title: labels.board.newState, ...(at ? { at } : {}) });\n onChange(made.flow);\n setSelection({ kind: \"state\", stateId: made.stateId });\n return made.stateId;\n },\n [labels, onChange],\n );\n\n const connect = useCallback(\n (owner: ExitOwner, exitId: string, to: string) => {\n if (!latest.current.readOnly) onChange(connectExit(latest.current.value, owner, exitId, to));\n },\n [onChange],\n );\n\n /** Стрелку отпустили на пустом месте: новое состояние там же. Из узла без условия — новое условие словами. */\n const connectToNewState = useCallback(\n (owner: ExitOwner, exitId: string | null, at: FlowPoint) => {\n if (latest.current.readOnly) return;\n const made = addStateTo(latest.current.value, { title: labels.board.newState, at });\n let next = made.flow;\n let fromExit = exitId;\n if (fromExit === null) {\n const added = addExit(next, owner, \"judge\");\n next = added.flow;\n fromExit = added.exitId;\n }\n onChange(connectExit(next, owner, fromExit, made.stateId));\n setSelection({ kind: \"state\", stateId: made.stateId });\n },\n [labels, onChange],\n );\n\n const removeState = useCallback(\n (stateId: string) => {\n if (!latest.current.readOnly) onChange(removeStateFrom(latest.current.value, stateId));\n },\n [onChange],\n );\n\n const restartSimulation = useCallback(() => {\n const current = latest.current;\n setSimulation(startSimulation(current.value, { now: current.now?.() ?? Date.now(), timeZone: current.timeZone ?? browserTimeZone() }));\n }, []);\n\n const setMode = useCallback(\n (next: FlowEditorMode) => {\n if (next === \"run\") {\n const current = latest.current.value;\n if (!current.states.some((state) => state.id === current.start)) {\n setModeState(\"check\");\n return;\n }\n restartSimulation();\n } else {\n setSimulation(null);\n }\n setModeState(next);\n },\n [restartSimulation],\n );\n\n const goToIssue = useCallback((issue: FlowIssue) => {\n const { stateId, exitId, fieldId, sideTaskId } = issue.place;\n if (stateId && flow.states.some((state) => state.id === stateId)) setSelection({ kind: \"state\", stateId, ...(exitId ? { exitId } : {}) });\n else if (exitId && flow.anyState.exits.some((exit) => exit.id === exitId)) setSelection({ kind: \"any\", exitId });\n else if (sideTaskId) setSelection({ kind: \"overview\", sideTaskId });\n else if (fieldId) setSelection({ kind: \"card\" });\n else setSelection({ kind: \"overview\" });\n setModeState(\"edit\");\n }, [flow]);\n\n const simulate = useMemo(() => {\n const change = (step: (sim: Simulation) => Simulation) => setSimulation((sim) => (sim ? step(sim) : sim));\n return {\n choose: (exitId: string) => change((sim) => chooseExit(latest.current.value, sim, exitId)),\n nothing: () => change((sim) => chooseNothing(latest.current.value, sim)),\n back: () => change(stepBack),\n restart: restartSimulation,\n setKnown: (fieldId: string, text: string) => change((sim) => setKnownValue(latest.current.value, sim, fieldId, text)),\n };\n }, [restartSimulation]);\n\n const openJson = useCallback(() => {\n setJsonErrors([]);\n setDialog(\"json\");\n }, []);\n\n const closeDialog = useCallback(() => setDialog(null), []);\n\n const loadJson = useCallback(\n (text: string): boolean => {\n if (latest.current.readOnly) return false;\n const loaded = loadFlowJson(text);\n if (!loaded.ok) {\n setJsonErrors(loaded.errors);\n return false;\n }\n setJsonErrors([]);\n setSelection({ kind: \"overview\" });\n setSimulation(null);\n setModeState(\"edit\");\n setDialog(null);\n onChange(loaded.flow);\n return true;\n },\n [onChange],\n );\n\n const save = useCallback(async () => {\n const { onSave, value, readOnly: viewOnly } = latest.current;\n if (!onSave || viewOnly) return;\n setSaving(true);\n try {\n const result = await onSave(value);\n if (result && !result.ok) {\n setRejection({ flow: value, issues: appIssues(value, (result.issues ?? []).map((issue) => ({ ...issue, code: \"save_rejected\" }))) });\n return;\n }\n setRejection(null);\n setSent({ print: flowFingerprint(value), base: latest.current.savedValue ? flowFingerprint(latest.current.savedValue) : undefined });\n } catch (error) {\n // Исключение из `onSave` — тот же отказ, только без списка: шапка говорит «Не сохранено», консоль не засоряем.\n console.warn(\"[flow] onSave failed\", error);\n setRejection({ flow: value, issues: [] });\n } finally {\n setSaving(false);\n }\n }, []);\n\n const migrate = useMigrateController(flow, options.migration, () => setDialog(\"migrate\"));\n\n return {\n flow,\n catalog,\n issues,\n issueCount,\n selection: visibleSelection,\n select,\n mode,\n setMode,\n goToIssue,\n edit,\n addState,\n connect,\n connectToNewState,\n removeState,\n simulation,\n simulate,\n dialog,\n openJson,\n closeDialog,\n json,\n jsonErrors,\n loadJson,\n save,\n saving,\n saveFailed,\n dirty,\n readOnly,\n migrate,\n };\n}\n\nexport type FlowEditorController = ReturnType<typeof useFlowEditor>;\n\n/** Окно перевода чатов: строки «версия → состояние → чатов», цели для удалённых состояний, перевод. */\nfunction useMigrateController(flow: AgentFlow, migration: FlowMigration | undefined, show: () => void): FlowMigrateController | null {\n const [chats, setChats] = useState<ChatsInState[]>([]);\n const [targets, setTargets] = useState<Record<string, string>>({});\n const [busy, setBusy] = useState(false);\n const [failed, setFailed] = useState(false);\n const [moved, setMoved] = useState<number | null>(null);\n\n const rows = useMemo<FlowMigrateRow[]>(\n () =>\n chats.map((entry) => {\n const current = flow.states.find((state) => state.id === entry.stateId);\n return {\n ...entry,\n stateTitle: migration?.stateTitle?.(entry.versionId, entry.stateId) ?? current?.title ?? entry.stateId,\n removed: !current,\n target: current ? null : (targets[entry.stateId] ?? null),\n };\n }),\n [chats, flow, migration, targets],\n );\n\n const canMigrate = !busy && rows.length > 0 && rows.every((row) => !row.removed || row.chats === 0 || row.target !== null);\n\n const open = useCallback(() => {\n if (!migration) return;\n show();\n setMoved(null);\n setFailed(false);\n setBusy(true);\n migration\n .chatsByState()\n .then(setChats, () => setFailed(true))\n .finally(() => setBusy(false));\n }, [migration, show]);\n\n const setTarget = useCallback((stateId: string, target: string) => setTargets((current) => ({ ...current, [stateId]: target })), []);\n\n const run = useCallback(async () => {\n if (!migration) return;\n const map: StateMap = Object.fromEntries(rows.filter((row) => row.removed && row.target).map((row) => [row.stateId, row.target!]));\n setBusy(true);\n setFailed(false);\n try {\n const result = await migration.migrate(map);\n setMoved(result.moved);\n // Счётчик — заново с сервера: чаты, которые перевод пропустил (их держала другая копия), остаются в окне.\n setChats(await migration.chatsByState().catch(() => []));\n } catch {\n setFailed(true);\n } finally {\n setBusy(false);\n }\n }, [migration, rows]);\n\n if (!migration) return null;\n return { rows, busy, failed, moved, canMigrate, open, setTarget, run };\n}\n","import { useCallback, useEffect, useRef, useState } from \"react\";\nimport { isFieldStale } from \"../../engine/side-questions\";\nimport type { ClientCardField } from \"../../format/flow-format\";\nimport { fieldValueText } from \"../../prompt/client-card-block\";\nimport { FACT_PREFIX } from \"../../runtime/client-facts\";\nimport type { ClientCardEntry } from \"../../store/flow-store\";\nimport { useFlowLabels } from \"../flow-labels\";\nimport type { ClientCardFieldView, ClientCardLoadState, ClientCardPanelProps } from \"../client-card-skin\";\n\nexport interface UseClientCardOptions {\n /** Поля карточки сценариев приложения: порядок = что важнее, имена видит человек. Чужих полей здесь может не быть — их покажет `id`. */\n fields: Array<Pick<ClientCardField, \"id\" | \"name\" | \"refreshAfterMonths\">>;\n /** Карточка человека с сервера: `flow.readClientCard(ownerId)` за HTTP-ручкой приложения. */\n read(): Promise<ClientCardEntry[]>;\n /** Стереть поле или `\"all\"`: `flow.forgetClientCard(ownerId, fieldId)`. */\n forget(fieldId: string | \"all\"): Promise<void>;\n /** Как назвать свободный факт о человеке («ведёт блог») в списке; по умолчанию — `useFlowLabels().clientCard.fact`. */\n factName?: string;\n /** Часы; для тестов. */\n now?: () => number;\n /** Пояс для даты записи; нет — пояс браузера. */\n timeZone?: string;\n}\n\n/** Слой поведения экрана карточки: грузит, готовит строки для скина, стирает поле или всё. Скин только рисует. */\nexport function useClientCard(options: UseClientCardOptions): ClientCardPanelProps {\n const latest = useRef(options);\n latest.current = options;\n const [state, setState] = useState<ClientCardLoadState>(\"loading\");\n const [entries, setEntries] = useState<ClientCardEntry[]>([]);\n const [busy, setBusy] = useState<ReadonlySet<string>>(new Set());\n const [forgettingAll, setForgettingAll] = useState(false);\n const alive = useRef(true);\n\n const load = useCallback(async () => {\n setState(\"loading\");\n try {\n const loaded = await latest.current.read();\n if (!alive.current) return;\n setEntries(loaded);\n setState(\"ready\");\n } catch {\n if (alive.current) setState(\"failed\");\n }\n }, []);\n\n useEffect(() => {\n alive.current = true;\n void load();\n return () => {\n alive.current = false;\n };\n }, [load]);\n\n const forgetField = async (fieldId: string) => {\n setBusy((current) => new Set(current).add(fieldId));\n try {\n await latest.current.forget(fieldId);\n if (alive.current) setEntries((current) => current.filter((entry) => entry.fieldId !== fieldId));\n } catch {\n if (alive.current) setState(\"failed\");\n } finally {\n if (alive.current)\n setBusy((current) => {\n const next = new Set(current);\n next.delete(fieldId);\n return next;\n });\n }\n };\n\n const forgetAll = async () => {\n setForgettingAll(true);\n try {\n await latest.current.forget(\"all\");\n if (alive.current) setEntries([]);\n } catch {\n if (alive.current) setState(\"failed\");\n } finally {\n if (alive.current) setForgettingAll(false);\n }\n };\n\n const labels = useFlowLabels().clientCard;\n const { fields, now = Date.now, timeZone, factName = labels.fact } = options;\n const dateFormat = new Intl.DateTimeFormat(\"ru-RU\", { day: \"2-digit\", month: \"2-digit\", year: \"numeric\", ...(timeZone && { timeZone }) });\n const position = (fieldId: string) => {\n const index = fields.findIndex((field) => field.id === fieldId);\n return index === -1 ? Number.MAX_SAFE_INTEGER : index;\n };\n const views: ClientCardFieldView[] = [...entries]\n .sort((left, right) => position(left.fieldId) - position(right.fieldId) || left.fieldId.localeCompare(right.fieldId))\n .map((entry) => {\n const field = fields.find((item) => item.id === entry.fieldId);\n const updatedAt = Date.parse(entry.updatedAt);\n return {\n fieldId: entry.fieldId,\n name: field?.name ?? (entry.fieldId.startsWith(FACT_PREFIX) ? factName : entry.fieldId),\n value: fieldValueText(entry.value),\n updatedAt: dateFormat.format(updatedAt),\n stale: field ? isFieldStale(field, updatedAt, now()) : false,\n busy: busy.has(entry.fieldId),\n onForget: () => void forgetField(entry.fieldId),\n };\n });\n\n return { state, fields: views, forgettingAll, onForgetAll: () => void forgetAll(), onRetry: () => void load() };\n}\n","import type { ClientCardSkin } from \"../client-card-skin\";\nimport { useClientCard, type UseClientCardOptions } from \"./use-client-card\";\n\nexport interface ClientCardScreenProps extends UseClientCardOptions {\n /** Части экрана: `tandemClientCardSkin` из `@ykurilov/agent-chat-skin-tandem/client-card` или свои по договору. */\n skin: ClientCardSkin;\n}\n\n/** Экран «Что агент знает о вас»: рядом с экраном памяти, если приложение его подключило. Надписи — `useFlowLabels().clientCard`. */\nexport function ClientCardPanel({ skin, ...options }: ClientCardScreenProps) {\n return <skin.ClientCardPanel {...useClientCard(options)} />;\n}\n","import { createContext, useContext, useMemo, type ReactNode } from \"react\";\nimport type { FlowDayInfo } from \"../../engine/flow-days\";\nimport { stateById } from \"../../engine/flow-graph\";\nimport { russianFlowTestChatLabels, type FlowTestChatLabels } from \"../../labels/test-chat\";\nimport { FlowEditor, type FlowEditorProps } from \"../editor/flow-editor\";\nimport { useFlowLabels } from \"../flow-labels\";\nimport type { FlowEditorFrameProps, FlowEditorSkin, FlowHeaderProps, FlowStateNodeProps } from \"../flow-editor-skin\";\nimport { useFlowTestChat, type FlowTestChatConnection, type FlowTestChatController } from \"./use-flow-test-chat\";\n\nconst MINUTE = 60_000;\nconst HOUR = 60 * MINUTE;\nconst DAY = 24 * HOUR;\n\n/** Варианты перемотки по умолчанию: 20 минут, 3 часа, сутки. */\nexport const DEFAULT_ADVANCE_STEPS: readonly number[] = [20 * MINUTE, 3 * HOUR, DAY];\n\n/** Длительность словами: «1 д 3 ч 20 мин». */\nexport function formatDuration(ms: number, units: FlowTestChatLabels[\"units\"]): string {\n const minutes = Math.round(ms / MINUTE);\n const parts: Array<[number, string]> = [\n [Math.floor(minutes / (24 * 60)), units.day],\n [Math.floor(minutes / 60) % 24, units.hour],\n [minutes % 60, units.minute],\n ];\n return parts\n .filter(([amount]) => amount > 0)\n .map(([amount, unit]) => `${amount} ${unit}`)\n .join(\" \");\n}\n\n/** Сдвиг часов тестового чата готовой строкой: «как сейчас», «+3 ч 20 мин». */\nexport function formatClockOffset(ms: number, labels: FlowTestChatLabels = russianFlowTestChatLabels): string {\n const { noOffset, units } = labels;\n const text = formatDuration(ms, units);\n return text ? `+${text}` : noOffset;\n}\n\n/** Строка дня тестового чата: «День 2 из 3 · 14:20» по часам чата в поясе человека; дней нет — `null`. */\nexport function formatDayLine(day: FlowDayInfo | null | undefined, at: number, timeZone: string, labels: FlowTestChatLabels = russianFlowTestChatLabels): string | null {\n if (!day) return null;\n const time = new Intl.DateTimeFormat(\"ru-RU\", { timeZone, hour: \"2-digit\", minute: \"2-digit\", hourCycle: \"h23\" }).format(at);\n return `${day.day === 0 ? labels.beforeFirstDay : labels.day(day.day, day.totalDays)} · ${time}`;\n}\n\nconst browserTimeZone = () => Intl.DateTimeFormat().resolvedOptions().timeZone || \"UTC\";\n\nexport interface FlowTestChatProps extends FlowEditorProps {\n testChat: FlowTestChatConnection;\n /** Варианты перемотки, мс. По умолчанию `DEFAULT_ADVANCE_STEPS`. */\n advanceSteps?: readonly number[];\n}\n\ninterface TestChatView {\n controller: FlowTestChatController;\n /** Рамка тестового чата вместо панели редактора; `null` — тестовый чат закрыт. */\n panel: ReactNode | null;\n}\n\nconst TestChatContext = createContext<TestChatView | null>(null);\n\nfunction useTestChatView(): TestChatView {\n const view = useContext(TestChatContext);\n if (!view) throw new Error(\"Test chat parts render only inside FlowTestChat.\");\n return view;\n}\n\n/**\n * Скин редактора с тестовым чатом поверх скина приложения: в шапке кнопка теста, справа вместо панели — чат, на доске\n * подсвечено место чата. Обёртки постоянные на скин: доска не пересоздаёт узлы.\n */\nfunction withTestChat(skin: FlowEditorSkin): FlowEditorSkin {\n function Header(props: FlowHeaderProps) {\n const { controller } = useTestChatView();\n return <skin.FlowHeader {...props} onOpenTestChat={controller.open} />;\n }\n function Frame(props: FlowEditorFrameProps) {\n const { panel } = useTestChatView();\n return <skin.FlowEditorFrame {...props} panel={panel ?? props.panel} />;\n }\n function StateNode(props: FlowStateNodeProps) {\n const { controller } = useTestChatView();\n if (!controller.opened || controller.stateId === null) return <skin.FlowStateNode {...props} />;\n const run = controller.stateId === props.stateId ? \"current\" : controller.visited.has(props.stateId) ? \"visited\" : null;\n return <skin.FlowStateNode {...props} run={run} dimmed={false} />;\n }\n return { ...skin, FlowHeader: Header, FlowEditorFrame: Frame, FlowStateNode: StateNode };\n}\n\n/**\n * Редактор сценария с тестовым чатом: автор пишет агенту рядом с доской, видит текущее состояние и перематывает часы\n * чата, чтобы проверить таймеры без ожидания. Сервер и экран чата даёт приложение (`testChat`).\n */\nexport function FlowTestChat({ testChat, advanceSteps = DEFAULT_ADVANCE_STEPS, skin, ...editor }: FlowTestChatProps) {\n const labels = useFlowLabels().testChat;\n const controller = useFlowTestChat(testChat, editor.value);\n const testSkin = useMemo(() => withTestChat(skin), [skin]);\n\n const state = controller.stateId === null ? undefined : stateById(editor.value, controller.stateId);\n const panel = controller.opened ? (\n <skin.FlowTestChatFrame\n stateTitle={state?.title || controller.stateId || \"\"}\n clock={formatClockOffset(controller.timeOffset, labels)}\n advanceSteps={advanceSteps.map((ms) => ({ label: formatDuration(ms, labels.units), ms }))}\n onAdvance={controller.advance}\n day={formatDayLine(controller.day, (editor.now?.() ?? Date.now()) + controller.timeOffset, editor.timeZone ?? browserTimeZone(), labels)}\n {...(controller.nextDay && editor.value.schedule ? { onNextDay: controller.nextDay } : {})}\n busy={controller.busy}\n failed={controller.failed}\n onReset={controller.reset}\n onClose={controller.close}\n >\n {controller.chatId === null ? null : testChat.renderChat(controller.chatId)}\n </skin.FlowTestChatFrame>\n ) : null;\n\n return (\n <TestChatContext.Provider value={{ controller, panel }}>\n <FlowEditor skin={testSkin} {...editor} />\n </TestChatContext.Provider>\n );\n}\n","import { useCallback, useEffect, useRef, useState, type ReactNode } from \"react\";\nimport type { FlowDayInfo } from \"../../engine/flow-days\";\nimport type { FlowRun } from \"../../engine/flow-run\";\nimport type { AgentFlow } from \"../../format/flow-format\";\n\n/** Как часто тестовый чат перечитывает место, пока открыт, мс. */\nconst RUN_POLL_MS = 1000;\n\n/** Что тестовому чату нужно от приложения: сервер и экран чата. Редактор не знает, где сервер. */\nexport interface FlowTestChatConnection {\n /** Новый тестовый чат по сценарию из редактора: сервер создаёт его с `flowTestChatData()`. */\n start(flow: AgentFlow): Promise<{ chatId: string }>;\n /** Промотать часы чата: на сервере `flow.advanceTestClock`. */\n advance(chatId: string, ms: number): Promise<{ timeOffset: number }>;\n /**\n * Промотать часы к началу следующего дня сценария: на сервере `flow.advanceTestClock({ chatId, to: \"next_day_start\" })`.\n * Нет — кнопки «К началу следующего дня» нет.\n */\n advanceToNextDay?(chatId: string): Promise<{ timeOffset: number }>;\n /** Место чата: на сервере `flow.readRun`. В браузер посетителя место не уходит, доска читает его отдельно. */\n readRun(chatId: string): Promise<(Pick<FlowRun, \"state\" | \"path\"> & { day?: FlowDayInfo }) | null>;\n /** Экран чата приложения: `<AgentChat api=… chatId={chatId} skin=… />`. */\n renderChat(chatId: string): ReactNode;\n}\n\nexport interface FlowTestChatController {\n opened: boolean;\n chatId: string | null;\n /** Сдвиг часов чата, мс. */\n timeOffset: number;\n busy: boolean;\n failed: boolean;\n /** Где чат на доске; пока ходов нет — старт сценария. */\n stateId: string | null;\n /** Пройденные состояния, без текущего. */\n visited: ReadonlySet<string>;\n /** День сценария чата; `null` — у сценария нет «Дней и времени» или ходов ещё не было. */\n day: FlowDayInfo | null;\n open(): void;\n close(): void;\n reset(): void;\n advance(ms: number): void;\n /** К началу следующего дня сценария; `null` — приложение не дало `advanceToNextDay`. */\n nextDay: (() => void) | null;\n}\n\ntype BoardRun = { state: string; visited: ReadonlySet<string>; day: FlowDayInfo | null };\n\n/** Место чата с сервера: только то, что нужно доске. */\nfunction runOf(run: Awaited<ReturnType<FlowTestChatConnection[\"readRun\"]>>): BoardRun | null {\n if (!run || typeof run.state !== \"string\") return null;\n const visited = new Set((run.path ?? []).flatMap((step) => (typeof step.state === \"string\" && step.state !== run.state ? [step.state] : [])));\n return { state: run.state, visited, day: run.day ?? null };\n}\n\nconst sameDay = (left: FlowDayInfo | null, right: FlowDayInfo | null) =>\n left === right || (left !== null && right !== null && left.day === right.day && left.totalDays === right.totalDays && left.dayStartedAt === right.dayStartedAt);\n\nconst sameRun = (left: BoardRun | null, right: BoardRun | null) =>\n left === right || (left !== null && right !== null && left.state === right.state && sameDay(left.day, right.day) && left.visited.size === right.visited.size && [...left.visited].every((id) => right.visited.has(id)));\n\nconst NOTHING_VISITED: ReadonlySet<string> = new Set();\n\n/** Логика тестового чата редактора: открыть, перемотать, начать заново, подсветка состояния. */\nexport function useFlowTestChat(connection: FlowTestChatConnection, flow: AgentFlow): FlowTestChatController {\n const [opened, setOpened] = useState(false);\n const [chatId, setChatId] = useState<string | null>(null);\n const [timeOffset, setTimeOffset] = useState(0);\n const [busy, setBusy] = useState(false);\n const [failed, setFailed] = useState(false);\n const [run, setRun] = useState<BoardRun | null>(null);\n const latest = useRef({ connection, flow, chatId });\n latest.current = { connection, flow, chatId };\n\n const refresh = useCallback(async (id: string) => {\n try {\n const next = runOf(await latest.current.connection.readRun(id));\n if (latest.current.chatId === id) setRun((current) => (sameRun(current, next) ? current : next));\n } catch (error) {\n console.error(\"[flow] test chat: run not read\", error);\n }\n }, []);\n\n // Пока панель открыта, место перечитывается: ходы чата и таймеры двигают его на сервере.\n useEffect(() => {\n if (!opened || chatId === null) return;\n void refresh(chatId);\n const timer = setInterval(() => void refresh(chatId), RUN_POLL_MS);\n return () => clearInterval(timer);\n }, [opened, chatId, refresh]);\n\n const work = useCallback(async (job: () => Promise<void>) => {\n setBusy(true);\n setFailed(false);\n try {\n await job();\n } catch (error) {\n console.error(\"[flow] test chat:\", error);\n setFailed(true);\n } finally {\n setBusy(false);\n }\n }, []);\n\n const start = useCallback(\n () =>\n work(async () => {\n const { chatId: next } = await latest.current.connection.start(latest.current.flow);\n setRun(null);\n setChatId(next);\n setTimeOffset(0);\n }),\n [work],\n );\n\n /** Перемотка часов чата: сервер сдвигает часы и ждёт ход, который она вызвала; место перечитывается сразу. */\n const shift = (move: (chatId: string) => Promise<{ timeOffset: number }>) => {\n const current = latest.current.chatId;\n if (current === null) return;\n void work(async () => {\n const { timeOffset: next } = await move(current);\n setTimeOffset(next);\n await refresh(current);\n });\n };\n\n return {\n opened,\n chatId,\n timeOffset,\n busy,\n failed,\n stateId: chatId === null ? null : (run?.state ?? flow.start),\n visited: run?.visited ?? NOTHING_VISITED,\n day: chatId === null ? null : (run?.day ?? null),\n open() {\n setOpened(true);\n if (latest.current.chatId === null) void start();\n },\n close: () => setOpened(false),\n reset: () => void start(),\n advance: (ms) => shift((id) => latest.current.connection.advance(id, ms)),\n nextDay: connection.advanceToNextDay ? () => shift((id) => latest.current.connection.advanceToNextDay!(id)) : null,\n };\n}\n"],"mappings":"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","names":["step","useMemo","useState","state","exit","createContext","useCallback","useContext","useEffect","useMemo","useState","step","createContext","useContext","step","useMemo","useState","useEffect","useCallback","useCallback","useMemo","useRef","useState","useRef","useState","useMemo","useCallback","addState","removeState","step","Fragment","jsx","jsxs","useState","useMemo","step","useCallback","useEffect","useRef","useState","useRef","useState","useCallback","useEffect","jsx","createContext","useContext","useMemo","useCallback","useEffect","useRef","useState","step","shift","jsx","browserTimeZone","createContext","useContext","useMemo"]}
|
|
1
|
+
{"version":3,"sources":["../src/react/flow-labels.ts","../src/labels/client-card.ts","../src/labels/editor.ts","../src/labels/migrate.ts","../src/labels/test-chat.ts","../src/labels/index.ts","../src/react/editor/flow-editor.tsx","../src/react/editor/editor-model.ts","../src/react/editor/exit-text.ts","../src/react/editor/board-space.ts","../src/react/editor/flow-board.tsx","../src/react/editor/board-styles.ts","../src/react/editor/schedule-model.ts","../src/react/editor/flow-simulation.ts","../src/react/editor/side-task-model.ts","../src/react/editor/use-flow-editor.ts","../src/react/client-card/use-client-card.ts","../src/react/client-card/client-card-panel.tsx","../src/react/test-chat/flow-test-chat.tsx","../src/react/test-chat/use-flow-test-chat.ts"],"sourcesContent":["import { createContext, createElement, useContext } from \"react\";\nimport type { ReactNode } from \"react\";\nimport { russianFlowLabels, type FlowLabels } from \"../labels/index\";\n\nconst FlowLabelsContext = createContext<FlowLabels>(russianFlowLabels);\n\n/** Надписи экранов сценария; по умолчанию русские (`russianFlowLabels`). */\nexport function FlowLabelsProvider({ labels, children }: { labels: FlowLabels; children: ReactNode }) {\n return createElement(FlowLabelsContext.Provider, { value: labels }, children);\n}\n\nexport function useFlowLabels(): FlowLabels {\n return useContext(FlowLabelsContext);\n}\n","/** Надписи экрана карточки клиента. */\nexport interface ClientCardLabels {\n title: string;\n empty: string;\n /** «обновлено 12.10.2026». */\n updatedAt: (date: string) => string;\n stale: string;\n /** Название строки свободного факта («ведёт блог») в списке. */\n fact: string;\n forgetField: string;\n forgetAll: string;\n forgetAllConfirm: string;\n confirm: string;\n cancel: string;\n loading: string;\n failed: string;\n retry: string;\n}\n\nexport const russianClientCardLabels: ClientCardLabels = {\n title: \"Что агент знает о вас\",\n empty: \"Агент пока ничего о вас не запомнил.\",\n updatedAt: (date) => `обновлено ${date}`,\n stale: \"может быть уже не так\",\n fact: \"Факт\",\n forgetField: \"Стереть\",\n forgetAll: \"Стереть всё\",\n forgetAllConfirm: \"Стереть всё, что агент знает о вас? Вернуть не получится.\",\n confirm: \"Стереть\",\n cancel: \"Отмена\",\n loading: \"Загружаем…\",\n failed: \"Не получилось загрузить. Попробуйте ещё раз\",\n retry: \"Повторить\",\n};\n\nexport const englishClientCardLabels: ClientCardLabels = {\n title: \"What the agent knows about you\",\n empty: \"The agent has not remembered anything about you yet.\",\n updatedAt: (date) => `updated ${date}`,\n stale: \"may be out of date\",\n fact: \"Fact\",\n forgetField: \"Erase\",\n forgetAll: \"Erase everything\",\n forgetAllConfirm: \"Erase everything the agent knows about you? This cannot be undone.\",\n confirm: \"Erase\",\n cancel: \"Cancel\",\n loading: \"Loading…\",\n failed: \"Could not load. Try again\",\n retry: \"Retry\",\n};\n","import type { FlowConditionType, FlowDataOp, FlowEventType, FlowFieldType, FlowTimerSpan, FlowTimerUnit } from \"../format/flow-format\";\n\n/** Надписи редактора сценария: доска, шапка, панели, прогон, окно JSON. */\nexport interface FlowEditorLabels {\n conditionKinds: Record<FlowConditionType, string>;\n /** Подсказка к виду условия в легенде. */\n conditionKindHints: Record<FlowConditionType, string>;\n returnKind: string;\n returnTarget: string;\n ops: Record<FlowDataOp, string>;\n events: Record<FlowEventType, string>;\n timerSpans: Record<FlowTimerSpan | \"time_of_day\", string>;\n units: Record<FlowTimerUnit, string>;\n fieldTypes: Record<FlowFieldType, string>;\n /** Значения поля «да/нет» в условиях и подписях. */\n yes: string;\n no: string;\n /** «1 день», «3 дня», «5 дней». */\n days: (count: number) => string;\n /** Подпись условия «наступил день N программы» на доске: «с дня 3». */\n programDay: (day: number) => string;\n\n header: {\n state: string;\n card: string;\n check: string;\n run: string;\n json: string;\n save: string;\n saved: string;\n unsaved: string;\n /** Сохранение отклонено: приложение отказало или упало. */\n saveFailed: string;\n saveFailedHint: string;\n /** Плашка «только просмотр»: сценарий сейчас правит не человек. */\n readOnly: string;\n readOnlyHint: string;\n migrate: string;\n /** Меню «⋯» шапки на узком экране: подпись кнопки. */\n more: string;\n };\n board: {\n anyState: string;\n start: string;\n final: string;\n noSideQuestions: string;\n noTarget: string;\n /** Условие словами, у которого ещё нет текста. */\n emptyCondition: string;\n /** Название нового состояния. */\n newState: string;\n zoomIn: string;\n zoomOut: string;\n fit: string;\n /** «2 ошибки», «1 замечание». */\n errors: (count: number) => string;\n warnings: (count: number) => string;\n /** Подпись касаний на карточке ноды: «касания 15 мин · 1 ч». */\n nudges: string;\n noNudges: string;\n /** Срок своих касаний на карточке: «в день входа», «первые 2 дн.». */\n nudgesDays: (days: number) => string;\n /** Кнопки места на доске: легенда, мини-карта, панель «Сценарий», полный экран. */\n space: {\n legend: string;\n showMinimap: string;\n hideMinimap: string;\n showInspector: string;\n hideInspector: string;\n enterFullscreen: string;\n exitFullscreen: string;\n /** Подпись области редактора в полном экране. */\n fullscreenRegion: string;\n };\n };\n overview: {\n title: string;\n common: string;\n commonHint: string;\n states: string;\n exits: string;\n finals: string;\n lists: string;\n help: string;\n /** Находки без места: весь сценарий, «Дни и время». */\n flowIssues: string;\n afterEnd: string;\n afterEndModes: Record<\"reply\" | \"silent\", string>;\n afterEndHints: Record<\"reply\" | \"silent\", string>;\n };\n schedule: {\n title: string;\n on: string;\n hint: string;\n dayStart: string;\n dayStartHint: string;\n lengthDays: string;\n lengthDaysNone: string;\n nightFrom: string;\n nightFromHint: string;\n lateStart: string;\n lateStartHint: string;\n deadlineState: string;\n deadlineNone: string;\n farewell: string;\n farewellText: string;\n farewellTextHint: string;\n firstMessages: string;\n maxPerDay: string;\n maxPerDayHint: string;\n morning: string;\n skipMorning: string;\n nudges: string;\n nudgesHint: string;\n dayFrame: string;\n dayFrameHint: string;\n softFrom: string;\n hardAt: string;\n hardText: string;\n hardTextHint: string;\n more: string;\n };\n nudges: {\n afterSilence: string;\n addStep: string;\n dailyAt: string;\n addTime: string;\n giveUpAfter: string;\n never: string;\n remove: string;\n on: string;\n };\n sideTasks: {\n title: string;\n hint: string;\n builtIn: string;\n text: string;\n when: string;\n field: string;\n noField: string;\n fromApp: string;\n maxAttempts: string;\n perConversation: string;\n add: string;\n newTask: string;\n delete: string;\n };\n statePanel: {\n title: string;\n name: string;\n instructions: string;\n instructionsHint: string;\n firstMessage: string;\n learn: string;\n tools: string;\n toolsHint: string;\n noTools: string;\n tags: string;\n makeStart: string;\n isStart: string;\n noSideQuestions: string;\n exits: string;\n addExit: string;\n more: string;\n deleteState: string;\n /** «Длится»: выход по времени в ноде. */\n duration: string;\n durationHint: string;\n durationNone: string;\n durationUnits: Record<\"h\" | \"d\" | \"program_day\", string>;\n durationTo: string;\n nudges: string;\n nudgesModes: Record<\"inherit\" | \"own\" | \"off\", string>;\n nudgesHint: string;\n /** Сколько действуют свои касания: всё время в ноде или N дней с дня входа. */\n nudgesDays: string;\n nudgesDaysModes: Record<\"always\" | \"days\", string>;\n nudgesDaysHint: string;\n };\n exitCard: {\n when: string;\n field: string;\n op: string;\n value: string;\n event: string;\n eventName: string;\n timer: string;\n amount: string;\n at: string;\n to: string;\n moveUp: string;\n moveDown: string;\n delete: string;\n };\n anyStatePanel: {\n title: string;\n hint: string;\n except: string;\n };\n cardPanel: {\n title: string;\n clientCard: string;\n chatNotes: string;\n chatNotesHint: string;\n empty: string;\n name: string;\n about: string;\n type: string;\n options: string;\n optionsHint: string;\n refreshAfter: string;\n /** «через 6 мес.». */\n refreshAfterMonths: (months: number) => string;\n pace: string;\n /** «раз в 5 сообщений». */\n paceEvery: (messages: number) => string;\n paceHint: string;\n addField: string;\n newField: string;\n /** Добавить поле из словаря приложения (`catalog.fields`). */\n fromApp: string;\n };\n checkPanel: {\n title: string;\n clean: string;\n errors: string;\n warnings: string;\n goTo: string;\n /** Проверки приложения упали. */\n appCheckFailed: string;\n };\n runPanel: {\n title: string;\n hint: string;\n current: string;\n whatHappened: string;\n nothing: string;\n known: string;\n notYet: string;\n nextQuestion: string;\n path: string;\n back: string;\n restart: string;\n finish: string;\n /** «Прогон · шаг 3». */\n step: (step: number) => string;\n /** Цель выбора «ничего из этого». */\n stay: string;\n /** Выбор, который сейчас не сработает: нет цели или «назад» некуда. */\n wontFire: string;\n /** Шаг пути, когда ничего не сработало. */\n nothingHappened: string;\n noStart: string;\n };\n jsonDialog: {\n title: string;\n copy: string;\n copied: string;\n download: string;\n load: string;\n close: string;\n };\n}\n\nexport const russianFlowEditorLabels: FlowEditorLabels = {\n conditionKinds: { judge: \"Словами\", data: \"Данные\", event: \"Событие\", timer: \"Таймер\" },\n conditionKindHints: {\n judge: \"Словами — решает агент, проверяет судья\",\n data: \"По данным — поле заполнено, значение равно…\",\n event: \"Событие — кнопка, инструмент, сигнал приложения\",\n timer: \"Таймер — по часам\",\n },\n returnKind: \"Назад\",\n returnTarget: \"назад, где был\",\n ops: { filled: \"заполнено\", eq: \"=\", ne: \"≠\", gt: \">\", lt: \"<\", contains: \"содержит\" },\n events: { message: \"Пришло сообщение\", button: \"Нажата кнопка\", tool: \"Вызван инструмент\", app: \"Событие приложения\" },\n timerSpans: {\n in_state: \"Время в этом состоянии\",\n silence: \"Тишина человека\",\n since_start: \"Прошло с начала чата\",\n time_of_day: \"Наступило время суток\",\n },\n units: { min: \"мин\", h: \"ч\", d: \"дн.\" },\n fieldTypes: { text: \"Текст\", number: \"Число\", choice: \"Выбор\", boolean: \"Да/нет\" },\n yes: \"да\",\n no: \"нет\",\n days: (count) => {\n const tens = count % 100;\n const ones = count % 10;\n const word = tens >= 11 && tens <= 14 ? \"дней\" : ones === 1 ? \"день\" : ones >= 2 && ones <= 4 ? \"дня\" : \"дней\";\n return `${count} ${word}`;\n },\n programDay: (day) => `с дня ${day}`,\n\n header: {\n state: \"Состояние\",\n card: \"Карточка и заметки\",\n check: \"Проверить граф\",\n run: \"Прогон\",\n json: \"JSON\",\n save: \"Сохранить\",\n saved: \"Сохранено\",\n unsaved: \"Есть несохранённые правки\",\n saveFailed: \"Не сохранено\",\n saveFailedHint: \"Сохранение отклонено. Что не так — в «Проверить граф» и на нодах.\",\n readOnly: \"Только просмотр\",\n readOnlyHint: \"Сценарий сейчас правит агент. Смотреть и прогонять можно, править нельзя.\",\n migrate: \"Перевести чаты\",\n more: \"Ещё действия\",\n },\n board: {\n anyState: \"Из любого состояния\",\n start: \"Сценарий начинается здесь\",\n final: \"Конец\",\n noSideQuestions: \"Без вопросов о человеке\",\n noTarget: \"куда — не выбрано\",\n emptyCondition: \"условие не написано\",\n newState: \"Новое состояние\",\n zoomIn: \"Крупнее\",\n zoomOut: \"Мельче\",\n fit: \"Весь граф\",\n errors: (count) => `Ошибок: ${count}`,\n warnings: (count) => `Замечаний: ${count}`,\n nudges: \"касания\",\n noNudges: \"без касаний\",\n nudgesDays: (days) => (days === 1 ? \"в день входа\" : `первые ${days} дн.`),\n space: {\n legend: \"Легенда\",\n showMinimap: \"Показать мини-карту\",\n hideMinimap: \"Скрыть мини-карту\",\n showInspector: \"Показать панель «Сценарий»\",\n hideInspector: \"Скрыть панель «Сценарий»\",\n enterFullscreen: \"На весь экран\",\n exitFullscreen: \"Выйти из полного экрана\",\n fullscreenRegion: \"Редактор сценария на весь экран\",\n },\n },\n overview: {\n title: \"Сценарий\",\n common: \"Общее для всех состояний\",\n commonHint: \"Роль, тон, цены, условия, ссылки — то, что верно в любом состоянии.\",\n states: \"Состояний\",\n exits: \"Условий выхода\",\n finals: \"Конечных\",\n lists: \"Списки\",\n help: \"Как пользоваться\",\n flowIssues: \"Весь сценарий\",\n afterEnd: \"После конца разговора\",\n afterEndModes: { reply: \"Отвечать\", silent: \"Не отвечать\" },\n afterEndHints: {\n reply: \"Агент отвечает по общей части: знает, что программа закончилась, не ведёт по шагам и не продаёт повторно.\",\n silent: \"Агент молчит, сообщение получает приложение.\",\n },\n },\n schedule: {\n title: \"Дни и время\",\n on: \"Сценарий по дням\",\n hint: \"Дни, ночь, общий срок и сообщения первым. Номер дня агент видит в каждом ходе.\",\n dayStart: \"Начало дня\",\n dayStartHint: \"В это время — утреннее сообщение.\",\n lengthDays: \"Сколько дней\",\n lengthDaysNone: \"без срока\",\n nightFrom: \"Ночь с\",\n nightFromHint: \"Ночью агент первым не пишет. Пусто — как в настройках приложения.\",\n lateStart: \"Поздний старт, ч\",\n lateStartHint: \"Пришёл меньше чем за столько часов до ночи — первый день завтра. 0 — день прихода первый.\",\n deadlineState: \"Срок вышел — перейти в\",\n deadlineNone: \"сразу закончить\",\n farewell: \"Попрощаться, когда срок вышел\",\n farewellText: \"Готовый текст прощания\",\n farewellTextHint: \"Пусто — прощание напишет агент.\",\n firstMessages: \"Сообщения первым\",\n maxPerDay: \"Не больше в день\",\n maxPerDayHint: \"Пусто — как в настройках приложения.\",\n morning: \"Утреннее сообщение\",\n skipMorning: \"Не писать утром, если человек писал за, мин\",\n nudges: \"Касания по умолчанию\",\n nudgesHint: \"Агент пишет в той же ноде, когда человек молчит. У ноды можно задать свои.\",\n dayFrame: \"Рамки дня\",\n dayFrameHint: \"По числу сообщений человека за день.\",\n softFrom: \"Сворачивать с сообщения №\",\n hardAt: \"Закончить день на сообщении №\",\n hardText: \"Ответ, когда день закончен\",\n hardTextHint: \"Уходит слово в слово, без модели.\",\n more: \"Дополнительно\",\n },\n nudges: {\n afterSilence: \"Молчит — написать через\",\n addStep: \"Добавить срок\",\n dailyAt: \"Потом каждый день в\",\n addTime: \"Добавить время\",\n giveUpAfter: \"Молчит столько — разговор окончен\",\n never: \"никогда\",\n remove: \"Убрать\",\n on: \"Касания по умолчанию\",\n },\n sideTasks: {\n title: \"Попутные задачи\",\n hint: \"Агент делает их между делом, в темпе вопросов о человеке. Не больше заданных попыток.\",\n builtIn: \"«Узнать город» — встроенная задача: есть всегда, когда заданы «Дни и время».\",\n text: \"Что сделать\",\n when: \"Когда уместно\",\n field: \"Решена, когда известно поле\",\n noField: \"—\",\n fromApp: \"Поля приложения\",\n maxAttempts: \"Попыток\",\n perConversation: \"Заново в каждом разговоре\",\n add: \"Добавить задачу\",\n newTask: \"\",\n delete: \"Удалить задачу\",\n },\n statePanel: {\n title: \"Состояние\",\n name: \"Название\",\n instructions: \"Что агент здесь делает\",\n instructionsHint: \"Первая строка — цель, её видно на доске. Дальше — как себя вести.\",\n firstMessage: \"Первое сообщение\",\n learn: \"Узнать в этом состоянии\",\n tools: \"Инструменты\",\n toolsHint: \"Агенту здесь доступны только отмеченные.\",\n noTools: \"В сценарии пока нет инструментов.\",\n tags: \"Метки\",\n makeStart: \"Начинать отсюда\",\n isStart: \"Сценарий начинается здесь\",\n noSideQuestions: \"Не спрашивать здесь о человеке между делом\",\n exits: \"Когда выходить и куда\",\n addExit: \"Добавить условие\",\n more: \"Дополнительно\",\n deleteState: \"Удалить состояние\",\n duration: \"Длится\",\n durationHint: \"Потом переход «Куда». Дни — дни сценария: новый день начинается в начале дня. «До дня программы» — до начала этого дня, когда бы человек ни пришёл в ноду.\",\n durationNone: \"не ограничено\",\n durationUnits: { h: \"часов\", d: \"дней\", program_day: \"до дня программы\" },\n durationTo: \"Потом — куда\",\n nudges: \"Касания\",\n nudgesModes: { inherit: \"Как у сценария\", own: \"Свои\", off: \"Выкл\" },\n nudgesHint: \"Агент пишет здесь сам, когда человек молчит.\",\n nudgesDays: \"Свои касания действуют\",\n nudgesDaysModes: { always: \"всё время в ноде\", days: \"дн., считая день входа\" },\n nudgesDaysHint: \"Потом — касания сценария: утреннее и общий ряд с начала.\",\n },\n exitCard: {\n when: \"Когда\",\n field: \"Поле\",\n op: \"Как сравнить\",\n value: \"Значение\",\n event: \"Событие\",\n eventName: \"Что именно\",\n timer: \"Откуда считать\",\n amount: \"Сколько\",\n at: \"Во сколько\",\n to: \"Куда\",\n moveUp: \"Выше\",\n moveDown: \"Ниже\",\n delete: \"Удалить условие\",\n },\n anyStatePanel: {\n title: \"Общие переходы\",\n hint: \"Работают из любого состояния. Свои условия состояния проверяются раньше.\",\n except: \"Не действуют ещё и здесь\",\n },\n cardPanel: {\n title: \"Карточка и заметки\",\n clientCard: \"Карточка клиента\",\n chatNotes: \"Заметки этого чата\",\n chatNotesHint: \"Живут весь чат, в следующем чате не помнятся.\",\n empty: \"Карточка клиента и заметки пока пусты.\",\n name: \"Название\",\n about: \"Что это и когда уместно спросить\",\n type: \"Тип\",\n options: \"Варианты\",\n optionsHint: \"Варианты через запятую\",\n refreshAfter: \"Может устареть\",\n refreshAfterMonths: (months) => `через ${months} мес.`,\n pace: \"Вопрос о человеке — раз в\",\n paceEvery: (messages) => `раз в ${messages} сообщений`,\n paceHint: \"Сначала пытается понять из слов, спрашивает — если не вышло. Не спрашивает, если человек раздражён или торопится.\",\n addField: \"Добавить поле\",\n newField: \"Новое поле\",\n fromApp: \"Поле приложения…\",\n },\n checkPanel: {\n title: \"Проверка\",\n clean: \"Проблем не нашлось.\",\n errors: \"Ошибки\",\n warnings: \"Замечания\",\n goTo: \"Открыть\",\n appCheckFailed: \"Проверки приложения не сработали — их находок здесь нет\",\n },\n runPanel: {\n title: \"Прогон\",\n hint: \"Прогон: выбирайте справа, что произошло\",\n current: \"Где сейчас агент\",\n whatHappened: \"Что произошло?\",\n nothing: \"Ничего из этого\",\n known: \"Что агент знает\",\n notYet: \"Пока нет\",\n nextQuestion: \"Следующий вопрос о человеке\",\n path: \"Пройденный путь\",\n back: \"Шаг назад\",\n restart: \"Сначала\",\n finish: \"Закончить прогон\",\n step: (step) => `Прогон · шаг ${step}`,\n stay: \"остаться здесь\",\n wontFire: \"сейчас не сработает\",\n nothingHappened: \"ничего не сработало\",\n noStart: \"Нет стартового состояния: отметьте, где начинается сценарий\",\n },\n jsonDialog: {\n title: \"Граф в формате JSON\",\n copy: \"Копировать\",\n copied: \"Скопировано\",\n download: \"Скачать\",\n load: \"Загрузить\",\n close: \"Закрыть\",\n },\n};\n\nexport const englishFlowEditorLabels: FlowEditorLabels = {\n conditionKinds: { judge: \"In words\", data: \"Data\", event: \"Event\", timer: \"Timer\" },\n conditionKindHints: {\n judge: \"In words — the agent decides, the judge checks\",\n data: \"By data — a field is filled, a value equals…\",\n event: \"Event — a button, a tool, an app signal\",\n timer: \"Timer — by the clock\",\n },\n returnKind: \"Back\",\n returnTarget: \"back where it was\",\n ops: { filled: \"is filled\", eq: \"=\", ne: \"≠\", gt: \">\", lt: \"<\", contains: \"contains\" },\n events: { message: \"Message arrived\", button: \"Button pressed\", tool: \"Tool called\", app: \"App event\" },\n timerSpans: {\n in_state: \"Time in this state\",\n silence: \"Person is silent\",\n since_start: \"Since the chat started\",\n time_of_day: \"Time of day reached\",\n },\n units: { min: \"min\", h: \"h\", d: \"d\" },\n fieldTypes: { text: \"Text\", number: \"Number\", choice: \"Choice\", boolean: \"Yes/no\" },\n yes: \"yes\",\n no: \"no\",\n days: (count) => `${count} ${count === 1 ? \"day\" : \"days\"}`,\n programDay: (day) => `from day ${day}`,\n\n header: {\n state: \"State\",\n card: \"Card and notes\",\n check: \"Check the graph\",\n run: \"Dry run\",\n json: \"JSON\",\n save: \"Save\",\n saved: \"Saved\",\n unsaved: \"Unsaved changes\",\n saveFailed: \"Not saved\",\n saveFailedHint: \"Saving was rejected. See what is wrong in “Check flow” and on the nodes.\",\n readOnly: \"View only\",\n readOnlyHint: \"An agent is editing this flow right now. You can look and run it, but not edit.\",\n migrate: \"Move chats\",\n more: \"More actions\",\n },\n board: {\n anyState: \"From any state\",\n start: \"The flow starts here\",\n final: \"End\",\n noSideQuestions: \"No questions about the person\",\n noTarget: \"target not chosen\",\n emptyCondition: \"condition not written\",\n newState: \"New state\",\n zoomIn: \"Zoom in\",\n zoomOut: \"Zoom out\",\n fit: \"Whole graph\",\n errors: (count) => `Errors: ${count}`,\n warnings: (count) => `Warnings: ${count}`,\n nudges: \"nudges\",\n noNudges: \"no nudges\",\n nudgesDays: (days) => (days === 1 ? \"on the entry day\" : `for the first ${days} days`),\n space: {\n legend: \"Legend\",\n showMinimap: \"Show the minimap\",\n hideMinimap: \"Hide the minimap\",\n showInspector: \"Show the flow panel\",\n hideInspector: \"Hide the flow panel\",\n enterFullscreen: \"Full screen\",\n exitFullscreen: \"Exit full screen\",\n fullscreenRegion: \"Flow editor, full screen\",\n },\n },\n overview: {\n title: \"Flow\",\n common: \"Common to all states\",\n commonHint: \"Role, tone, prices, terms, links — whatever holds in every state.\",\n states: \"States\",\n exits: \"Exit conditions\",\n finals: \"Final\",\n lists: \"Lists\",\n help: \"How to use\",\n flowIssues: \"Whole flow\",\n afterEnd: \"After the conversation ends\",\n afterEndModes: { reply: \"Reply\", silent: \"Stay silent\" },\n afterEndHints: {\n reply: \"The agent replies from the common part: it knows the program is over, does not lead through steps or sell again.\",\n silent: \"The agent stays silent; the app receives the message.\",\n },\n },\n schedule: {\n title: \"Days and time\",\n on: \"Day-by-day flow\",\n hint: \"Days, night, total length and first messages. The agent sees the day number on every turn.\",\n dayStart: \"Day starts at\",\n dayStartHint: \"The morning message goes out at this time.\",\n lengthDays: \"How many days\",\n lengthDaysNone: \"no limit\",\n nightFrom: \"Night from\",\n nightFromHint: \"At night the agent never writes first. Empty — as in the app settings.\",\n lateStart: \"Late start, h\",\n lateStartHint: \"Arrived less than this many hours before night — day one is tomorrow. 0 — the arrival day is day one.\",\n deadlineState: \"Time is up — go to\",\n deadlineNone: \"end right away\",\n farewell: \"Say goodbye when time is up\",\n farewellText: \"Ready-made goodbye\",\n farewellTextHint: \"Empty — the agent writes the goodbye.\",\n firstMessages: \"Writing first\",\n maxPerDay: \"At most per day\",\n maxPerDayHint: \"Empty — as in the app settings.\",\n morning: \"Morning message\",\n skipMorning: \"Skip the morning if the person wrote within, min\",\n nudges: \"Default nudges\",\n nudgesHint: \"The agent writes in the same state while the person is silent. A state can have its own.\",\n dayFrame: \"Daily limits\",\n dayFrameHint: \"By the number of the person's messages per day.\",\n softFrom: \"Wrap up from message #\",\n hardAt: \"End the day at message #\",\n hardText: \"Reply when the day is over\",\n hardTextHint: \"Sent word for word, without the model.\",\n more: \"More\",\n },\n nudges: {\n afterSilence: \"Silent — write after\",\n addStep: \"Add a delay\",\n dailyAt: \"Then every day at\",\n addTime: \"Add a time\",\n giveUpAfter: \"Silent this long — conversation over\",\n never: \"never\",\n remove: \"Remove\",\n on: \"Default nudges\",\n },\n sideTasks: {\n title: \"Side tasks\",\n hint: \"The agent does them in passing, at the pace of questions about the person. No more than the given attempts.\",\n builtIn: \"“Find out the city” is built in: always on when “Days and time” are set.\",\n text: \"What to do\",\n when: \"When it fits\",\n field: \"Done when this field is known\",\n noField: \"—\",\n fromApp: \"App fields\",\n maxAttempts: \"Attempts\",\n perConversation: \"Anew in every conversation\",\n add: \"Add a task\",\n newTask: \"\",\n delete: \"Delete the task\",\n },\n statePanel: {\n title: \"State\",\n name: \"Name\",\n instructions: \"What the agent does here\",\n instructionsHint: \"The first line is the goal, shown on the board. Then — how to behave.\",\n firstMessage: \"First message\",\n learn: \"Learn in this state\",\n tools: \"Tools\",\n toolsHint: \"Only the checked tools are available here.\",\n noTools: \"The flow has no tools yet.\",\n tags: \"Tags\",\n makeStart: \"Start here\",\n isStart: \"The flow starts here\",\n noSideQuestions: \"No side questions about the person here\",\n exits: \"When to leave and where to\",\n addExit: \"Add a condition\",\n more: \"More\",\n deleteState: \"Delete the state\",\n duration: \"Lasts\",\n durationHint: \"Then goes to “Go to”. Days are flow days: a new day begins at the day start. “Until program day” lasts until that day starts, whenever the person entered the node.\",\n durationNone: \"no limit\",\n durationUnits: { h: \"hours\", d: \"days\", program_day: \"until program day\" },\n durationTo: \"Then go to\",\n nudges: \"Nudges\",\n nudgesModes: { inherit: \"As in the flow\", own: \"Own\", off: \"Off\" },\n nudgesHint: \"The agent writes here by itself while the person is silent.\",\n nudgesDays: \"Own nudges apply\",\n nudgesDaysModes: { always: \"the whole time in the state\", days: \"days, counting the entry day\" },\n nudgesDaysHint: \"Then the flow's nudges: the morning message and the common series from the start.\",\n },\n exitCard: {\n when: \"When\",\n field: \"Field\",\n op: \"Compare\",\n value: \"Value\",\n event: \"Event\",\n eventName: \"Which one\",\n timer: \"Count from\",\n amount: \"How long\",\n at: \"At\",\n to: \"Go to\",\n moveUp: \"Up\",\n moveDown: \"Down\",\n delete: \"Delete the condition\",\n },\n anyStatePanel: {\n title: \"Common transitions\",\n hint: \"Work from any state. The state's own conditions are checked first.\",\n except: \"Also not active here\",\n },\n cardPanel: {\n title: \"Card and notes\",\n clientCard: \"Client card\",\n chatNotes: \"Notes of this chat\",\n chatNotesHint: \"Live for the whole chat and are not remembered in the next one.\",\n empty: \"The client card and notes are empty so far.\",\n name: \"Name\",\n about: \"What it is and when to ask\",\n type: \"Type\",\n options: \"Options\",\n optionsHint: \"Options separated by commas\",\n refreshAfter: \"May go stale\",\n refreshAfterMonths: (months) => `in ${months} mo.`,\n pace: \"A question about the person — once per\",\n paceEvery: (messages) => `once per ${messages} messages`,\n paceHint: \"First tries to understand from what was said and asks only if that fails. Does not ask when the person is annoyed or in a hurry.\",\n addField: \"Add a field\",\n newField: \"New field\",\n fromApp: \"App field…\",\n },\n checkPanel: {\n title: \"Check\",\n clean: \"No problems found.\",\n errors: \"Errors\",\n warnings: \"Warnings\",\n goTo: \"Open\",\n appCheckFailed: \"The app's checks failed — their findings are missing here\",\n },\n runPanel: {\n title: \"Dry run\",\n hint: \"Dry run: choose on the right what happened\",\n current: \"Where the agent is\",\n whatHappened: \"What happened?\",\n nothing: \"None of these\",\n known: \"What the agent knows\",\n notYet: \"Not yet\",\n nextQuestion: \"Next question about the person\",\n path: \"Path so far\",\n back: \"Step back\",\n restart: \"Restart\",\n finish: \"Finish the dry run\",\n step: (step) => `Dry run · step ${step}`,\n stay: \"stay here\",\n wontFire: \"won't fire now\",\n nothingHappened: \"nothing fired\",\n noStart: \"No start state: mark where the flow begins\",\n },\n jsonDialog: {\n title: \"The graph as JSON\",\n copy: \"Copy\",\n copied: \"Copied\",\n download: \"Download\",\n load: \"Load\",\n close: \"Close\",\n },\n};\n","/** Надписи окна перевода чатов на новую версию сценария. */\nexport interface FlowMigrateLabels {\n title: string;\n hint: string;\n version: string;\n state: string;\n chats: string;\n removed: string;\n target: string;\n chooseTarget: string;\n migrate: string;\n /** «Переведено чатов: 12». */\n moved: (count: number) => string;\n nothingToMigrate: string;\n close: string;\n failed: string;\n}\n\nexport const russianFlowMigrateLabels: FlowMigrateLabels = {\n title: \"Перевести чаты на новую версию\",\n hint: \"Чаты продолжат с того же состояния. Закончившиеся разговоры и тестовые чаты остаются на своей версии. Для удалённых состояний выберите, куда перевести.\",\n version: \"Версия\",\n state: \"Состояние\",\n chats: \"Чатов\",\n removed: \"удалено в новой версии\",\n target: \"Куда\",\n chooseTarget: \"Выберите состояние\",\n migrate: \"Перевести\",\n moved: (count) => `Переведено чатов: ${count}`,\n nothingToMigrate: \"Переводить нечего: идущие чаты уже на этой версии.\",\n close: \"Закрыть\",\n failed: \"Не получилось перевести. Попробуйте ещё раз\",\n};\n\nexport const englishFlowMigrateLabels: FlowMigrateLabels = {\n title: \"Move chats to the new version\",\n hint: \"Chats continue from the same state. Finished conversations and test chats stay on their version. For removed states choose where to move them.\",\n version: \"Version\",\n state: \"State\",\n chats: \"Chats\",\n removed: \"removed in the new version\",\n target: \"Move to\",\n chooseTarget: \"Choose a state\",\n migrate: \"Move\",\n moved: (count) => `Chats moved: ${count}`,\n nothingToMigrate: \"Nothing to move: ongoing chats are already on this version.\",\n close: \"Close\",\n failed: \"Could not move the chats. Try again\",\n};\n","/** Надписи тестового чата редактора: живой разговор по сценарию с перемоткой часов. */\nexport interface FlowTestChatLabels {\n title: string;\n state: string;\n /** «+20 мин». */\n advance: (label: string) => string;\n clock: string;\n /** Часы чата не сдвинуты. */\n noOffset: string;\n /** Единицы сдвига: «3 ч 20 мин». */\n units: { day: string; hour: string; minute: string };\n reset: string;\n close: string;\n /** Тестовый чат не открылся или часы не перемотались. */\n failed: string;\n /** Перемотка к началу следующего дня сценария. */\n nextDay: string;\n /** Перемотка к моменту, когда сценарий сам напишет первым. */\n nextFirstMessage: string;\n /** Впереди сценарий сам ничего не напишет: перематывать к напоминанию не к чему. */\n nothingScheduled: string;\n /** Поле «своё время»: подпись, пример и подсказка на непонятное. */\n customTime: string;\n customTimePlaceholder: string;\n customTimeInvalid: string;\n /** «День 2 из 3», «День 2». */\n day: (day: number, totalDays?: number) => string;\n /** Вечер позднего старта: первый день ещё не начался. */\n beforeFirstDay: string;\n}\n\nexport const russianFlowTestChatLabels: FlowTestChatLabels = {\n title: \"Тестовый чат\",\n state: \"Сейчас в состоянии\",\n advance: (label) => `+${label}`,\n clock: \"Часы чата\",\n noOffset: \"как сейчас\",\n units: { day: \"д\", hour: \"ч\", minute: \"мин\" },\n reset: \"Начать заново\",\n close: \"Закрыть\",\n failed: \"Не получилось — попробуйте ещё раз\",\n nextDay: \"К началу следующего дня\",\n nextFirstMessage: \"К следующему напоминанию\",\n nothingScheduled: \"Впереди сценарий сам ничего не напишет\",\n customTime: \"Своё время\",\n customTimePlaceholder: \"15 мин, 1 ч 30 мин, 2 дня\",\n customTimeInvalid: \"Не понял время — например, «1 ч 30 мин» или «2 дня»\",\n day: (day, totalDays) => (totalDays === undefined ? `День ${day}` : `День ${day} из ${totalDays}`),\n beforeFirstDay: \"До первого дня\",\n};\n\nexport const englishFlowTestChatLabels: FlowTestChatLabels = {\n title: \"Test chat\",\n state: \"Current state\",\n advance: (label) => `+${label}`,\n clock: \"Chat clock\",\n noOffset: \"now\",\n units: { day: \"d\", hour: \"h\", minute: \"min\" },\n reset: \"Start over\",\n close: \"Close\",\n failed: \"Something went wrong — try again\",\n nextDay: \"To the start of the next day\",\n nextFirstMessage: \"To the next reminder\",\n nothingScheduled: \"The flow won't write first from here on\",\n customTime: \"Custom time\",\n customTimePlaceholder: \"15 min, 1h 30m, 2 days\",\n customTimeInvalid: \"Couldn't read the time — try “1h 30m” or “2 days”\",\n day: (day, totalDays) => (totalDays === undefined ? `Day ${day}` : `Day ${day} of ${totalDays}`),\n beforeFirstDay: \"Before day one\",\n};\n","import { englishClientCardLabels, russianClientCardLabels, type ClientCardLabels } from \"./client-card\";\nimport { englishFlowEditorLabels, russianFlowEditorLabels, type FlowEditorLabels } from \"./editor\";\nimport { englishFlowMigrateLabels, russianFlowMigrateLabels, type FlowMigrateLabels } from \"./migrate\";\nimport { englishFlowTestChatLabels, russianFlowTestChatLabels, type FlowTestChatLabels } from \"./test-chat\";\n\n/** Все надписи экранов сценария: по словарю на экран. */\nexport interface FlowLabels {\n editor: FlowEditorLabels;\n clientCard: ClientCardLabels;\n migrate: FlowMigrateLabels;\n testChat: FlowTestChatLabels;\n}\n\nexport const russianFlowLabels: FlowLabels = {\n editor: russianFlowEditorLabels,\n clientCard: russianClientCardLabels,\n migrate: russianFlowMigrateLabels,\n testChat: russianFlowTestChatLabels,\n};\n\nexport const englishFlowLabels: FlowLabels = {\n editor: englishFlowEditorLabels,\n clientCard: englishClientCardLabels,\n migrate: englishFlowMigrateLabels,\n testChat: englishFlowTestChatLabels,\n};\n\nexport type { ClientCardLabels, FlowEditorLabels, FlowMigrateLabels, FlowTestChatLabels };\n","import { useMemo, useState, type CSSProperties, type ReactNode } from \"react\";\nimport {\n FLOW_OPS_BY_FIELD_TYPE,\n FLOW_DATA_OPS,\n RETURN_TARGET,\n type AgentFlow,\n type FlowExit,\n type FlowField,\n type FlowIssue,\n type FlowNudges,\n type FlowState,\n} from \"../../format/flow-format\";\nimport { catalogEventLabel, catalogEventNames } from \"../../format/catalog-events\";\nimport { fieldById, isFinal, stateById } from \"../../engine/flow-graph\";\nimport { isFieldStale } from \"../../engine/side-questions\";\nimport type { FlowEditorLabels } from \"../../labels/editor\";\nimport { useFlowLabels } from \"../flow-labels\";\nimport type { FlowEditorSkin, FlowStateLinkView, FlowTargetOption } from \"../flow-editor-skin\";\nimport {\n addExit,\n addField,\n freeSpot,\n moveExit,\n moveField,\n normalizeCondition,\n removeExit,\n removeField,\n setExcept,\n setStart,\n updateExit,\n updateField,\n updateState,\n type ExitOwner,\n type FieldList,\n} from \"./editor-model\";\nimport { conditionText, edgeKind, stateGoal, targetTitle } from \"./exit-text\";\nimport { useBoardSpace, useFullscreenBehavior, type FlowBoardSpaceProps } from \"./board-space\";\nimport { FlowBoard } from \"./flow-board\";\nimport {\n durationOf,\n nudgesMode,\n setAfterEnd,\n setDuration,\n setScheduleOn,\n setStateNudges,\n setStateNudgesDays,\n stateNudgesDays,\n updateSchedule,\n updateScheduleNudges,\n updateStateNudges,\n} from \"./schedule-model\";\nimport { addCatalogField, addSideTask, catalogFieldsToAdd, removeSideTask, setSideTaskField, updateSideTask } from \"./side-task-model\";\nimport { nextQuestionField, simulationChoices } from \"./flow-simulation\";\nimport { useFlowEditor, type FlowEditorController, type UseFlowEditorOptions } from \"./use-flow-editor\";\n\nexport interface FlowEditorProps extends UseFlowEditorOptions, FlowBoardSpaceProps {\n /** Части экрана: `tandemFlowEditorSkin` из `@ykurilov/agent-chat-skin-tandem/flows` или свои по договору. */\n skin: FlowEditorSkin;\n /** Класс и стиль корня редактора. По умолчанию он занимает высоту родителя, но не меньше разумной (на телефоне тоже). */\n className?: string;\n style?: CSSProperties;\n}\n\n/** Редактор сценария: доска, панели, проверка, прогон, JSON. Управляемый: сценарий хранит приложение. */\nexport function FlowEditor({ skin, className, style, header: headerMode, legend, minimap, inspector, fullscreen, storageKey, ...options }: FlowEditorProps) {\n const editor = useFlowEditor(options);\n const labels = useFlowLabels().editor;\n const { flow } = editor;\n const space = useBoardSpace(\n {\n ...(headerMode !== undefined ? { header: headerMode } : {}),\n ...(legend !== undefined ? { legend } : {}),\n ...(minimap !== undefined ? { minimap } : {}),\n ...(inspector !== undefined ? { inspector } : {}),\n ...(fullscreen !== undefined ? { fullscreen } : {}),\n ...(storageKey !== undefined ? { storageKey } : {}),\n },\n editor,\n );\n const [root, setRoot] = useState<HTMLDivElement | null>(null);\n const { setFullscreen } = space;\n const onTab = useFullscreenBehavior(space.fullscreen, () => setFullscreen(false), editor.dialog !== null, root);\n\n const header = (\n <skin.FlowHeader\n name={flow.name}\n onRename={(name) => editor.edit((current) => ({ ...current, name }))}\n mode={editor.mode}\n onModeChange={editor.setMode}\n issues={editor.issueCount}\n onAddState={() => editor.addState(freeSpot(flow))}\n onOpenCard={() => editor.select({ kind: \"card\" })}\n onOpenJson={editor.openJson}\n {...(options.onSave && !editor.readOnly ? { onSave: () => void editor.save() } : {})}\n saving={editor.saving}\n dirty={editor.dirty}\n saveFailed={editor.saveFailed}\n readOnly={editor.readOnly}\n {...(editor.migrate && !editor.readOnly ? { onOpenMigrate: editor.migrate.open } : {})}\n {...(space.header === \"compact\" ? { compact: true } : {})}\n {...(space.fullscreenAllowed ? { fullscreen: { active: space.fullscreen, onToggle: () => setFullscreen(!space.fullscreen) } } : {})}\n />\n );\n\n // Обёртка стоит всегда, чтобы доска не пересоздавалась при выходе на весь экран; в обычном виде она не влияет на вёрстку.\n return (\n <div\n ref={setRoot}\n data-flow-fullscreen={space.fullscreen ? \"\" : undefined}\n {...(space.fullscreen ? { role: \"dialog\", \"aria-modal\": true, \"aria-label\": labels.board.space.fullscreenRegion, onKeyDown: onTab } : {})}\n style={space.fullscreen ? FULLSCREEN_STYLE : { display: \"contents\" }}\n >\n <skin.FlowEditorFrame\n header={header}\n board={<FlowBoard editor={editor} skin={skin} space={space} />}\n panel={space.inspectorOpen ? <EditorPanel editor={editor} skin={skin} labels={labels} /> : null}\n dialog={<EditorDialog editor={editor} skin={skin} />}\n {...(space.header === \"compact\" ? { compact: true } : {})}\n // Свои класс и стиль приложения рассчитаны на место в странице; на весь экран редактор занимает окно.\n {...(space.fullscreen ? { style: { height: \"100%\", minHeight: 0 } } : { ...(className !== undefined ? { className } : {}), ...(style !== undefined ? { style } : {}) })}\n />\n </div>\n );\n}\n\nconst FULLSCREEN_STYLE: CSSProperties = {\n position: \"fixed\",\n inset: 0,\n zIndex: 2000,\n height: \"100dvh\",\n overflow: \"auto\",\n background: \"var(--canvas, Canvas)\",\n color: \"var(--foreground, CanvasText)\",\n};\n\nfunction stateLinks(editor: FlowEditorController): FlowStateLinkView[] {\n return editor.flow.states.map((state) => ({\n stateId: state.id,\n title: state.title || state.id,\n start: editor.flow.start === state.id,\n final: isFinal(state),\n onSelect: () => editor.select({ kind: \"state\", stateId: state.id }),\n }));\n}\n\nfunction targetOptions(flow: AgentFlow, labels: FlowEditorLabels, withReturn: boolean): FlowTargetOption[] {\n const states = flow.states.map((state) => ({ value: state.id, title: state.title || state.id }));\n return withReturn ? [...states, { value: RETURN_TARGET, title: labels.returnTarget }] : states;\n}\n\nfunction ExitCards({ editor, skin, labels, owner }: { editor: FlowEditorController; skin: FlowEditorSkin; labels: FlowEditorLabels; owner: ExitOwner }) {\n const { flow, catalog } = editor;\n const state = owner === null ? undefined : stateById(flow, owner);\n // Выход «Длится» правится в своём разделе панели ноды, если у скина он есть.\n const durationExitId = state && skin.FlowStateTiming ? durationOf(state)?.exitId : undefined;\n const exits: FlowExit[] = (owner === null ? flow.anyState.exits : (state?.exits ?? [])).filter((exit) => exit.id !== durationExitId);\n const fields: FlowField[] = [...flow.clientCard, ...flow.chatNotes];\n const eventNames = {\n button: [...new Set([...catalogEventNames(catalog), ...catalog.widgets])],\n tool: [...catalog.tools],\n app: catalogEventNames(catalog),\n };\n const eventLabels: Record<string, string> = {};\n for (const name of eventNames.app) {\n const label = catalogEventLabel(catalog, name);\n if (label) eventLabels[name] = label;\n }\n const targets = targetOptions(flow, labels, owner !== null);\n return (\n <>\n {exits.map((exit, index) => {\n const fieldType = exit.when.type === \"data\" ? fieldById(flow, exit.when.field)?.field.type : undefined;\n return (\n <skin.FlowExitCard\n key={exit.id}\n exitId={exit.id}\n when={exit.when}\n to={exit.to}\n fields={fields}\n ops={fieldType ? [...FLOW_OPS_BY_FIELD_TYPE[fieldType]] : [...FLOW_DATA_OPS]}\n eventNames={eventNames}\n eventLabels={eventLabels}\n targets={targets}\n issues={editor.issues.filter((issue) => issue.place.exitId === exit.id)}\n canMoveUp={index > 0}\n canMoveDown={index < exits.length - 1}\n onChange={(next) =>\n editor.edit((current) => updateExit(current, owner, exit.id, { when: normalizeCondition(current, exit.when, next.when), to: next.to }))\n }\n onMoveUp={() => editor.edit((current) => moveExit(current, owner, exit.id, -1))}\n onMoveDown={() => editor.edit((current) => moveExit(current, owner, exit.id, 1))}\n onDelete={() => editor.edit((current) => removeExit(current, owner, exit.id))}\n />\n );\n })}\n </>\n );\n}\n\nfunction FieldRows({ editor, skin, list }: { editor: FlowEditorController; skin: FlowEditorSkin; list: FieldList }) {\n const fields: FlowField[] = editor.flow[list];\n return (\n <>\n {fields.map((field, index) => (\n <skin.FlowFieldRow\n key={field.id}\n field={field}\n list={list}\n canMoveUp={index > 0}\n canMoveDown={index < fields.length - 1}\n issues={editor.issues.filter((issue) => issue.place.fieldId === field.id)}\n onChange={(patch) => editor.edit((current) => updateField(current, list, field.id, patch))}\n onMoveUp={() => editor.edit((current) => moveField(current, list, field.id, -1))}\n onMoveDown={() => editor.edit((current) => moveField(current, list, field.id, 1))}\n onDelete={() => editor.edit((current) => removeField(current, list, field.id))}\n />\n ))}\n </>\n );\n}\n\nfunction EditorPanel({ editor, skin, labels }: { editor: FlowEditorController; skin: FlowEditorSkin; labels: FlowEditorLabels }): ReactNode {\n const panel = <EditablePanel editor={editor} skin={skin} labels={labels} />;\n // Только просмотр: поля и кнопки панели правок выключены сразу, а не молча возвращают прежнее значение.\n if (!editor.readOnly || editor.mode !== \"edit\") return panel;\n return (\n <fieldset disabled data-flow-read-only=\"\" className=\"m-0 flex min-h-0 min-w-0 flex-1 flex-col border-0 p-0\">\n {panel}\n </fieldset>\n );\n}\n\nfunction EditablePanel({ editor, skin, labels }: { editor: FlowEditorController; skin: FlowEditorSkin; labels: FlowEditorLabels }): ReactNode {\n const { flow, selection } = editor;\n\n if (editor.mode === \"check\") {\n return <skin.FlowCheckPanel issues={editor.issues.map((issue) => ({ ...issue, onGo: () => editor.goToIssue(issue) }))} />;\n }\n if (editor.mode === \"run\" && editor.simulation) return <RunPanel editor={editor} skin={skin} labels={labels} />;\n\n if (selection.kind === \"state\") {\n const state = stateById(flow, selection.stateId)!;\n return (\n <skin.FlowStatePanel\n key={state.id}\n stateId={state.id}\n title={state.title}\n instructions={state.instructions}\n firstMessage={state.firstMessage}\n learn={state.learn}\n tools={state.tools}\n tags={state.tags}\n start={flow.start === state.id}\n noSideQuestions={state.noSideQuestions}\n fields={[...flow.clientCard, ...flow.chatNotes]}\n catalogTools={[...new Set([...flow.tools, ...editor.catalog.tools])]}\n exits={<ExitCards editor={editor} skin={skin} labels={labels} owner={state.id} />}\n timing={<StateTiming editor={editor} skin={skin} labels={labels} state={state} />}\n issues={editor.issues.filter((issue) => issue.place.stateId === state.id && !issue.place.exitId)}\n onChange={(patch) =>\n editor.edit((current) => {\n const next = updateState(current, state.id, patch);\n // Инструмент, отмеченный в состоянии, попадает и в список инструментов сценария.\n const missing = (patch.tools ?? []).filter((tool) => !next.tools.includes(tool));\n return missing.length ? { ...next, tools: [...next.tools, ...missing] } : next;\n })\n }\n onMakeStart={() => editor.edit((current) => setStart(current, state.id))}\n onAddExit={(kind) => {\n const made = addExit(flow, state.id, kind);\n editor.edit(() => made.flow);\n editor.select({ kind: \"state\", stateId: state.id, exitId: made.exitId });\n }}\n onDelete={() => {\n editor.removeState(state.id);\n editor.select({ kind: \"overview\" });\n }}\n />\n );\n }\n if (selection.kind === \"any\") {\n return (\n <skin.FlowAnyStatePanel\n except={flow.anyState.except}\n states={stateLinks(editor)}\n onExceptChange={(except) => editor.edit((current) => setExcept(current, except))}\n exits={<ExitCards editor={editor} skin={skin} labels={labels} owner={null} />}\n onAddExit={(kind) => editor.edit((current) => addExit(current, null, kind).flow)}\n />\n );\n }\n if (selection.kind === \"card\") {\n return (\n <skin.FlowCardPanel\n clientCard={<FieldRows editor={editor} skin={skin} list=\"clientCard\" />}\n chatNotes={<FieldRows editor={editor} skin={skin} list=\"chatNotes\" />}\n empty={flow.clientCard.length === 0 && flow.chatNotes.length === 0}\n sideQuestionEveryMessages={flow.pace.sideQuestionEveryMessages}\n onPaceChange={(messages) =>\n editor.edit((current) => ({ ...current, pace: { sideQuestionEveryMessages: Math.max(1, Math.round(messages) || 1) } }))\n }\n onAddField={(list) => editor.edit((current) => addField(current, list, labels.cardPanel.newField).flow)}\n appFields={catalogFieldsToAdd(flow, editor.catalog).map((field) => ({ id: field.id, title: field.title }))}\n onAddAppField={(list, fieldId) => {\n const field = editor.catalog.fields?.find((candidate) => candidate.id === fieldId);\n if (field) editor.edit((current) => addCatalogField(current, list, field));\n }}\n />\n );\n }\n return (\n <skin.FlowOverviewPanel\n name={flow.name}\n common={flow.common}\n onCommonChange={(common) => editor.edit((current) => ({ ...current, common }))}\n counts={{\n states: flow.states.length,\n exits: flow.anyState.exits.length + flow.states.reduce((sum, state) => sum + state.exits.length, 0),\n finals: flow.states.filter(isFinal).length,\n }}\n states={stateLinks(editor)}\n issues={editor.issueCount}\n sections={\n <>\n <ScheduleSection editor={editor} skin={skin} labels={labels} />\n <SideTasksSection editor={editor} skin={skin} focused={selection.kind === \"overview\" ? selection.sideTaskId : undefined} />\n </>\n }\n />\n );\n}\n\n/** Находки по «Дням и времени»: их коды из `checkFlow`. */\nconst SCHEDULE_ISSUES = new Set([\"night_before_day_start\", \"unknown_deadline_state\", \"day_frame_soft_after_hard\"]);\nconst isScheduleIssue = (issue: FlowIssue) => SCHEDULE_ISSUES.has(issue.code) || (issue.code === \"empty_nudges\" && !issue.place.stateId);\n\nfunction NudgesEditor({ skin, nudges, optional, onChange }: { skin: FlowEditorSkin; nudges: FlowNudges | null; optional: boolean; onChange(nudges: FlowNudges | null): void }) {\n if (!skin.FlowNudgesEditor) return null;\n return <skin.FlowNudgesEditor nudges={nudges} optional={optional} onChange={onChange} />;\n}\n\nfunction ScheduleSection({ editor, skin, labels }: { editor: FlowEditorController; skin: FlowEditorSkin; labels: FlowEditorLabels }): ReactNode {\n if (!skin.FlowScheduleSection) return null;\n const { flow } = editor;\n return (\n <skin.FlowScheduleSection\n schedule={flow.schedule ?? null}\n afterEnd={flow.afterEnd ?? \"reply\"}\n states={targetOptions(flow, labels, false)}\n issues={editor.issues.filter(isScheduleIssue)}\n nudges={\n <NudgesEditor\n skin={skin}\n nudges={flow.schedule?.nudges ?? null}\n optional\n onChange={(nudges) => editor.edit((current) => updateScheduleNudges(current, nudges))}\n />\n }\n onToggle={(on) => editor.edit((current) => setScheduleOn(current, on))}\n onChange={(patch) => editor.edit((current) => updateSchedule(current, patch))}\n onAfterEndChange={(mode) => editor.edit((current) => setAfterEnd(current, mode))}\n />\n );\n}\n\nfunction SideTasksSection({ editor, skin, focused }: { editor: FlowEditorController; skin: FlowEditorSkin; focused: string | undefined }): ReactNode {\n const labels = useFlowLabels().editor;\n if (!skin.FlowSideTasksSection) return null;\n const { flow, catalog } = editor;\n return (\n <skin.FlowSideTasksSection\n tasks={(flow.sideTasks ?? []).map((task) => ({\n ...task,\n issues: editor.issues.filter((issue) => issue.place.sideTaskId === task.id),\n focused: task.id === focused,\n }))}\n fields={[\n ...[...flow.clientCard, ...flow.chatNotes].map((field) => ({ id: field.id, title: field.name || field.id, fromApp: false })),\n ...catalogFieldsToAdd(flow, catalog).map((field) => ({ id: field.id, title: field.title, fromApp: true })),\n ]}\n builtInCity={flow.schedule !== undefined}\n onAdd={() => editor.edit((current) => addSideTask(current, labels.sideTasks.newTask).flow)}\n onChange={(sideTaskId, patch) => editor.edit((current) => updateSideTask(current, sideTaskId, patch))}\n onFieldChange={(sideTaskId, fieldId) => editor.edit((current) => setSideTaskField(current, sideTaskId, fieldId, catalog))}\n onDelete={(sideTaskId) => editor.edit((current) => removeSideTask(current, sideTaskId))}\n />\n );\n}\n\nfunction StateTiming({ editor, skin, labels, state }: { editor: FlowEditorController; skin: FlowEditorSkin; labels: FlowEditorLabels; state: FlowState }): ReactNode {\n if (!skin.FlowStateTiming) return null;\n const { flow } = editor;\n const duration = durationOf(state);\n const mode = nudgesMode(state);\n const own = state.nudges && state.nudges !== \"off\" ? state.nudges : null;\n return (\n <skin.FlowStateTiming\n duration={duration && { amount: duration.amount, unit: duration.unit, to: duration.to }}\n daysAvailable={flow.schedule !== undefined || (duration !== null && duration.unit !== \"h\")}\n targets={targetOptions(flow, labels, true)}\n issues={duration ? editor.issues.filter((issue) => issue.place.exitId === duration.exitId) : []}\n onDurationChange={(value) => editor.edit((current) => setDuration(current, state.id, value))}\n onDurationTargetChange={(to) => {\n if (!duration) return;\n editor.edit((current) => {\n const exit = stateById(current, state.id)?.exits.find((candidate) => candidate.id === duration.exitId);\n return exit ? updateExit(current, state.id, exit.id, { when: exit.when, to }) : current;\n });\n }}\n nudgesMode={mode}\n onNudgesModeChange={(next) => editor.edit((current) => setStateNudges(current, state.id, next))}\n nudgesDays={stateNudgesDays(state)}\n onNudgesDaysChange={(days) => editor.edit((current) => setStateNudgesDays(current, state.id, days))}\n nudges={\n own && (\n <NudgesEditor\n skin={skin}\n nudges={own}\n optional={false}\n onChange={(nudges) => editor.edit((current) => (nudges ? updateStateNudges(current, state.id, nudges) : setStateNudges(current, state.id, \"off\")))}\n />\n )\n }\n />\n );\n}\n\nfunction RunPanel({ editor, skin, labels }: { editor: FlowEditorController; skin: FlowEditorSkin; labels: FlowEditorLabels }) {\n const { flow } = editor;\n const sim = editor.simulation!;\n const state = stateById(flow, sim.run.state);\n const choices = useMemo(() => simulationChoices(flow, sim), [flow, sim]);\n const question = nextQuestionField(flow, sim);\n const exitById = (exitId: string) => [...flow.anyState.exits, ...flow.states.flatMap((candidate) => candidate.exits)].find((exit) => exit.id === exitId);\n\n const knownRow = (field: FlowField, value: unknown, stale: boolean) => ({\n fieldId: field.id,\n name: field.name || field.id,\n value: value === undefined || value === null || value === \"\" ? null : String(value),\n stale,\n onChange: (text: string) => editor.simulate.setKnown(field.id, text),\n });\n const known = [\n ...flow.clientCard.map((field) => {\n const entry = sim.card[field.id];\n return knownRow(field, entry?.value, entry !== undefined && isFieldStale(field, entry.updatedAt, sim.now));\n }),\n ...flow.chatNotes.map((field) => knownRow(field, sim.run.notes[field.id], false)),\n ];\n\n return (\n <skin.FlowRunPanel\n current={{ stateId: sim.run.state, title: state?.title || sim.run.state, goal: stateGoal(state?.instructions ?? \"\") }}\n choices={choices.map((choice) => {\n const exit = exitById(choice.exitId)!;\n return {\n exitId: choice.exitId,\n kind: edgeKind(exit),\n text: conditionText(flow, exit.when, labels, editor.catalog),\n target: choice.target ? targetTitle(flow, choice.target, labels) : null,\n onChoose: () => editor.simulate.choose(choice.exitId),\n };\n })}\n onNothing={editor.simulate.nothing}\n known={known}\n nextQuestion={question ? (fieldById(flow, question)?.field.name ?? question) : null}\n path={sim.steps.map((step) => {\n const exit = step.exitId ? exitById(step.exitId) : undefined;\n return {\n stateId: step.stateId,\n title: stateById(flow, step.stateId)?.title || step.stateId,\n via: step.nothing ? labels.runPanel.nothingHappened : exit ? conditionText(flow, exit.when, labels, editor.catalog) : null,\n };\n })}\n canGoBack={sim.previous !== null}\n onBack={editor.simulate.back}\n onRestart={editor.simulate.restart}\n onFinish={() => editor.setMode(\"edit\")}\n />\n );\n}\n\nfunction download(name: string, text: string) {\n const url = URL.createObjectURL(new Blob([text], { type: \"application/json\" }));\n const link = document.createElement(\"a\");\n link.href = url;\n link.download = name;\n link.click();\n setTimeout(() => URL.revokeObjectURL(url), 0);\n}\n\nfunction EditorDialog({ editor, skin }: { editor: FlowEditorController; skin: FlowEditorSkin }): ReactNode {\n const labels = useFlowLabels().editor;\n if (editor.dialog === \"json\") {\n return (\n <skin.FlowJsonDialog\n json={editor.json}\n errors={editor.jsonErrors}\n onCopy={() => void navigator.clipboard?.writeText(editor.json)}\n onDownload={() => download(`${editor.flow.id}.json`, editor.json)}\n onLoad={(text) => void editor.loadJson(text)}\n onClose={editor.closeDialog}\n {...(editor.readOnly ? { readOnly: true } : {})}\n />\n );\n }\n if (editor.dialog === \"migrate\" && editor.migrate) {\n const migrate = editor.migrate;\n return (\n <skin.FlowMigrateDialog\n rows={migrate.rows.map((row) => ({ ...row, onTargetChange: (stateId: string) => migrate.setTarget(row.stateId, stateId) }))}\n targets={targetOptions(editor.flow, labels, false)}\n busy={migrate.busy}\n failed={migrate.failed}\n moved={migrate.moved}\n canMigrate={migrate.canMigrate}\n onMigrate={() => void migrate.run()}\n onClose={editor.closeDialog}\n />\n );\n }\n return null;\n}\n","import { fieldById } from \"../../engine/flow-graph\";\nimport { compactFlow } from \"../../format/compact-flow\";\nimport { parseFlow } from \"../../format/parse-flow\";\nimport {\n FLOW_OPS_BY_FIELD_TYPE,\n type AgentFlow,\n type ClientCardField,\n type FlowCondition,\n type FlowConditionType,\n type FlowExit,\n type FlowField,\n type FlowPoint,\n type FlowState,\n} from \"../../format/flow-format\";\n\n// Правки сценария в редакторе: чистые функции, каждая возвращает новый `AgentFlow`. Доска, панели и прогон зовут только их.\n\n/** Чьё условие: id состояния или `null` — общие переходы «Из любого состояния». */\nexport type ExitOwner = string | null;\n\nexport type FieldList = \"clientCard\" | \"chatNotes\";\n\nexport type StatePatch = Partial<Pick<FlowState, \"title\" | \"instructions\" | \"firstMessage\" | \"learn\" | \"tools\" | \"tags\" | \"noSideQuestions\">>;\n\n/** Свободный id вида `state_3`: не занят ни одним из `taken`. */\nfunction freeId(prefix: string, taken: Iterable<string>): string {\n const used = new Set(taken);\n let index = 1;\n while (used.has(`${prefix}_${index}`)) index += 1;\n return `${prefix}_${index}`;\n}\n\nfunction allExits(flow: AgentFlow): FlowExit[] {\n return [...flow.anyState.exits, ...flow.states.flatMap((state) => state.exits)];\n}\n\nfunction allFields(flow: AgentFlow): FlowField[] {\n return [...flow.clientCard, ...flow.chatNotes];\n}\n\nfunction editState(flow: AgentFlow, stateId: string, edit: (state: FlowState) => FlowState): AgentFlow {\n return { ...flow, states: flow.states.map((state) => (state.id === stateId ? edit(state) : state)) };\n}\n\nfunction editExits(flow: AgentFlow, owner: ExitOwner, edit: (exits: FlowExit[]) => FlowExit[]): AgentFlow {\n if (owner === null) return { ...flow, anyState: { ...flow.anyState, exits: edit(flow.anyState.exits) } };\n return editState(flow, owner, (state) => ({ ...state, exits: edit(state.exits) }));\n}\n\nfunction exitsOf(flow: AgentFlow, owner: ExitOwner): FlowExit[] {\n if (owner === null) return flow.anyState.exits;\n return flow.states.find((state) => state.id === owner)?.exits ?? [];\n}\n\n/** Переставляет элемент на `delta` позиций; за край — тот же массив. */\nfunction shift<T>(items: T[], index: number, delta: number): T[] {\n const target = index + delta;\n if (index < 0 || target < 0 || target >= items.length) return items;\n const next = [...items];\n const [item] = next.splice(index, 1);\n next.splice(target, 0, item!);\n return next;\n}\n\nexport function addState(flow: AgentFlow, input: { title: string; at?: FlowPoint }): { flow: AgentFlow; stateId: string } {\n const stateId = freeId(\"state\", flow.states.map((state) => state.id));\n const state: FlowState = {\n id: stateId,\n kind: \"state\",\n title: input.title,\n instructions: \"\",\n firstMessage: null,\n learn: [],\n noSideQuestions: false,\n tools: [],\n tags: [],\n exits: [],\n };\n return {\n stateId,\n flow: {\n ...flow,\n start: flow.states.length === 0 ? stateId : flow.start,\n states: [...flow.states, state],\n layout: input.at ? { ...flow.layout, [stateId]: input.at } : flow.layout,\n },\n };\n}\n\n/** Удаляет состояние: ведущие в него условия остаются без цели, из старта и исключений оно уходит. */\nexport function removeState(flow: AgentFlow, stateId: string): AgentFlow {\n const unlink = (exits: FlowExit[]) => exits.map((exit) => (exit.to === stateId ? { ...exit, to: null } : exit));\n const { [stateId]: _removed, ...layout } = flow.layout;\n return {\n ...flow,\n start: flow.start === stateId ? null : flow.start,\n states: flow.states.filter((state) => state.id !== stateId).map((state) => ({ ...state, exits: unlink(state.exits) })),\n anyState: { except: flow.anyState.except.filter((id) => id !== stateId), exits: unlink(flow.anyState.exits) },\n layout,\n };\n}\n\nexport function updateState(flow: AgentFlow, stateId: string, patch: StatePatch): AgentFlow {\n return editState(flow, stateId, (state) => ({ ...state, ...patch }));\n}\n\nexport function setStart(flow: AgentFlow, stateId: string): AgentFlow {\n return { ...flow, start: stateId };\n}\n\nexport function setExcept(flow: AgentFlow, except: string[]): AgentFlow {\n return { ...flow, anyState: { ...flow.anyState, except } };\n}\n\n/** Условие нового вида со значениями по умолчанию; по данным — первое поле карточки или заметок. */\nexport function defaultCondition(kind: FlowConditionType, flow: AgentFlow): FlowCondition {\n switch (kind) {\n case \"judge\":\n return { type: \"judge\", text: \"\" };\n case \"data\":\n // Поля ещё нет — id-заглушка: формат её примет, проверка графа покажет «поля нет».\n return { type: \"data\", field: allFields(flow)[0]?.id ?? \"field\", op: \"filled\" };\n case \"event\":\n return { type: \"event\", event: \"message\" };\n case \"timer\":\n return { type: \"timer\", from: \"in_state\", amount: 1, unit: \"h\" };\n }\n}\n\n/**\n * Условие после правки в карточке. Скин меняет одно поле, а целым и годным условие делает редактор: другой вид —\n * значения по умолчанию; другое поле — сравнение, подходящее его типу; число из поля ввода — числом; таймер «время\n * суток» ↔ «сколько прошло» — со своими значениями.\n */\nexport function normalizeCondition(flow: AgentFlow, previous: FlowCondition, next: FlowCondition): FlowCondition {\n if (next.type !== previous.type) return defaultCondition(next.type, flow);\n if (next.type === \"data\") {\n const type = fieldById(flow, next.field)?.field.type;\n if (type === undefined) return next;\n if (!FLOW_OPS_BY_FIELD_TYPE[type].includes(next.op)) return { type: \"data\", field: next.field, op: \"filled\" };\n if (next.op === \"filled\") return { type: \"data\", field: next.field, op: \"filled\" };\n if (type === \"boolean\") return { type: \"data\", field: next.field, op: next.op, value: next.value !== false && next.value !== \"false\" };\n if (type === \"number\" && typeof next.value === \"string\" && next.value.trim() !== \"\" && Number.isFinite(Number(next.value))) {\n return { ...next, value: Number(next.value) };\n }\n return { ...next, value: next.value ?? \"\" };\n }\n if (next.type === \"timer\") {\n if (next.from === \"time_of_day\") return { type: \"timer\", from: \"time_of_day\", at: \"at\" in next && next.at ? next.at : \"10:00\" };\n // Дни переносятся между «длится N дней» и «до дня N программы».\n const days = \"days\" in next && next.days ? next.days : \"day\" in next && next.day ? next.day : 1;\n if (next.from === \"state_days\") return { type: \"timer\", from: \"state_days\", days };\n if (next.from === \"program_day\") return { type: \"timer\", from: \"program_day\", day: days };\n const span = next as Partial<typeof next>;\n return { type: \"timer\", from: next.from, amount: span.amount ?? 1, unit: span.unit ?? \"h\" };\n }\n if (next.type === \"event\" && next.event === \"message\") return { type: \"event\", event: \"message\" };\n return next;\n}\n\nexport function addExit(flow: AgentFlow, owner: ExitOwner, kind: FlowConditionType): { flow: AgentFlow; exitId: string } {\n const exitId = freeId(owner ?? \"any\", allExits(flow).map((exit) => exit.id));\n const exit: FlowExit = { id: exitId, when: defaultCondition(kind, flow), to: null };\n return { exitId, flow: editExits(flow, owner, (exits) => [...exits, exit]) };\n}\n\nexport function updateExit(flow: AgentFlow, owner: ExitOwner, exitId: string, next: { when: FlowCondition; to: string | null }): AgentFlow {\n return editExits(flow, owner, (exits) => exits.map((exit) => (exit.id === exitId ? { ...exit, ...next } : exit)));\n}\n\n/** Стрелка с доски: условие ведёт в `to`. */\nexport function connectExit(flow: AgentFlow, owner: ExitOwner, exitId: string, to: string): AgentFlow {\n return editExits(flow, owner, (exits) => exits.map((exit) => (exit.id === exitId ? { ...exit, to } : exit)));\n}\n\nexport function moveExit(flow: AgentFlow, owner: ExitOwner, exitId: string, delta: number): AgentFlow {\n const exits = exitsOf(flow, owner);\n const moved = shift(exits, exits.findIndex((exit) => exit.id === exitId), delta);\n return moved === exits ? flow : editExits(flow, owner, () => moved);\n}\n\nexport function removeExit(flow: AgentFlow, owner: ExitOwner, exitId: string): AgentFlow {\n return editExits(flow, owner, (exits) => exits.filter((exit) => exit.id !== exitId));\n}\n\nexport function addField(flow: AgentFlow, list: FieldList, name: string): { flow: AgentFlow; fieldId: string } {\n const fieldId = freeId(\"field\", allFields(flow).map((field) => field.id));\n const base: FlowField = { id: fieldId, name, about: \"\", type: \"text\", options: [] };\n if (list === \"clientCard\") {\n return { fieldId, flow: { ...flow, clientCard: [...flow.clientCard, { ...base, refreshAfterMonths: null }] } };\n }\n return { fieldId, flow: { ...flow, chatNotes: [...flow.chatNotes, base] } };\n}\n\nexport function updateField(flow: AgentFlow, list: FieldList, fieldId: string, patch: Partial<ClientCardField>): AgentFlow {\n if (list === \"clientCard\") {\n return { ...flow, clientCard: flow.clientCard.map((field) => (field.id === fieldId ? { ...field, ...patch } : field)) };\n }\n const { refreshAfterMonths: _cardOnly, ...notePatch } = patch;\n return { ...flow, chatNotes: flow.chatNotes.map((field) => (field.id === fieldId ? { ...field, ...notePatch } : field)) };\n}\n\nexport function moveField(flow: AgentFlow, list: FieldList, fieldId: string, delta: number): AgentFlow {\n const fields: FlowField[] = flow[list];\n const moved = shift(fields, fields.findIndex((field) => field.id === fieldId), delta);\n return moved === fields ? flow : { ...flow, [list]: moved };\n}\n\n/** Удаляет поле и его «узнать здесь». Условия по нему остаются: их покажет проверка графа. */\nexport function removeField(flow: AgentFlow, list: FieldList, fieldId: string): AgentFlow {\n const fields: FlowField[] = flow[list];\n return {\n ...flow,\n [list]: fields.filter((field) => field.id !== fieldId),\n states: flow.states.map((state) => (state.learn.includes(fieldId) ? { ...state, learn: state.learn.filter((id) => id !== fieldId) } : state)),\n };\n}\n\n/** Где поставить новое состояние без места: под всеми узлами доски. */\nexport function freeSpot(flow: AgentFlow): FlowPoint {\n const points = Object.values(flow.layout);\n if (points.length === 0) return { x: 80, y: 80 };\n return { x: Math.min(...points.map((point) => point.x)), y: Math.max(...points.map((point) => point.y)) + 240 };\n}\n\n/** Место узла на доске; `ANY_STATE_LAYOUT_KEY` — узел общих переходов. */\nexport function placeNode(flow: AgentFlow, nodeId: string, at: FlowPoint): AgentFlow {\n return { ...flow, layout: { ...flow.layout, [nodeId]: { x: Math.round(at.x), y: Math.round(at.y) } } };\n}\n\n/** JSON сценария для окна JSON и скачивания: без значений по умолчанию, как в файлах примеров. */\nexport function flowToJson(flow: AgentFlow): string {\n return `${JSON.stringify(keepJudgeText(compactFlow(flow)), null, 2)}\\n`;\n}\n\nfunction sortKeys(value: unknown): unknown {\n if (Array.isArray(value)) return value.map(sortKeys);\n if (value && typeof value === \"object\") {\n return Object.fromEntries(\n Object.entries(value)\n .sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0))\n .map(([key, inner]) => [key, sortKeys(inner)]),\n );\n }\n return value;\n}\n\n/** Отпечаток сценария для сравнения: тот же `compactFlow`, что у JSON доски, но порядок ключей не важен. */\nexport function flowFingerprint(flow: AgentFlow): string {\n return JSON.stringify(sortKeys(keepJudgeText(compactFlow(flow))));\n}\n\n/**\n * Один ли это сценарий: сравнение так же, как считает «Сохранено» доска (пустые поля не в счёт). Порядок ключей не важен:\n * сценарий из jsonb приходит с другим порядком. Порядок состояний, условий и полей — важен.\n */\nexport function sameFlow(a: AgentFlow, b: AgentFlow): boolean {\n return flowFingerprint(a) === flowFingerprint(b);\n}\n\ntype JsonExit = { when?: { type?: string; text?: string } };\ntype JsonState = { exits?: JsonExit[] };\n\n/**\n * `compactFlow` убирает пустые строки, в том числе текст ещё не написанного условия словами, а без `text` такое условие\n * `parseFlow` не принимает. Возвращаем пустой текст, чтобы недописанный сценарий сохранялся и загружался обратно.\n */\nfunction keepJudgeText(json: Record<string, unknown>): Record<string, unknown> {\n const fix = (exits: JsonExit[] | undefined) =>\n exits?.forEach((exit) => {\n if (exit.when?.type === \"judge\" && exit.when.text === undefined) exit.when.text = \"\";\n });\n (json.states as JsonState[]).forEach((state) => fix(state.exits));\n fix((json.anyState as { exits?: JsonExit[] } | undefined)?.exits);\n return json;\n}\n\nexport type LoadFlowResult = { ok: true; flow: AgentFlow } | { ok: false; errors: string[] };\n\n/** Загрузка JSON в редактор: та же `parseFlow`, что на сервере. Ошибки — строками «место: что не так». */\nexport function loadFlowJson(text: string): LoadFlowResult {\n let input: unknown;\n try {\n input = JSON.parse(text);\n } catch (error) {\n return { ok: false, errors: [`JSON: ${error instanceof Error ? error.message : String(error)}`] };\n }\n const result = parseFlow(input);\n if (result.ok) return result;\n return { ok: false, errors: result.errors.map((error) => (error.path ? `${error.path}: ${error.message}` : error.message)) };\n}\n","import { RETURN_TARGET, type AgentFlow, type FlowCatalog, type FlowCondition, type FlowExit } from \"../../format/flow-format\";\nimport { catalogEventLabel } from \"../../format/catalog-events\";\nimport { fieldById } from \"../../engine/flow-graph\";\nimport type { FlowEditorLabels } from \"../../labels/editor\";\nimport type { FlowEdgeKind } from \"../flow-editor-skin\";\n\n/** Подпись условия для доски, прогона и проверки: «Понятны тема курса и продажи», «Тишина человека 3 ч». С каталогом — подписи событий. */\nexport function conditionText(flow: AgentFlow, when: FlowCondition, labels: FlowEditorLabels, catalog?: Pick<FlowCatalog, \"events\">): string {\n switch (when.type) {\n case \"judge\":\n return when.text.trim() || labels.board.emptyCondition;\n case \"data\": {\n const name = fieldById(flow, when.field)?.field.name || when.field;\n const op = labels.ops[when.op];\n if (typeof when.value === \"boolean\") return `${name} ${op} ${when.value ? labels.yes : labels.no}`;\n return when.op === \"filled\" || when.value === undefined ? `${name} ${op}` : `${name} ${op} ${when.value}`;\n }\n case \"event\":\n if (when.event === \"message\" || !when.name) return labels.events[when.event];\n return `${labels.events[when.event]} «${(when.event !== \"tool\" && catalogEventLabel(catalog, when.name)) || when.name}»`;\n case \"timer\":\n if (when.from === \"time_of_day\") return `${labels.timerSpans.time_of_day} ${when.at}`;\n if (when.from === \"state_days\") return `${labels.statePanel.duration} ${labels.days(when.days)}`;\n if (when.from === \"program_day\") return labels.programDay(when.day);\n return `${labels.timerSpans[when.from]} ${when.amount} ${labels.units[when.unit]}`;\n }\n}\n\n/** Вид стрелки: «назад» рисуется отдельно от вида условия. */\nexport function edgeKind(exit: FlowExit): FlowEdgeKind {\n return exit.to === RETURN_TARGET ? \"return\" : exit.when.type;\n}\n\n/** Название цели: состояние, «назад, где был» или `null`, если цель не выбрана или пропала. */\nexport function targetTitle(flow: AgentFlow, to: string | null, labels: FlowEditorLabels): string | null {\n if (to === null) return null;\n if (to === RETURN_TARGET) return labels.returnTarget;\n const state = flow.states.find((candidate) => candidate.id === to);\n return state ? state.title || state.id : null;\n}\n\n/** Цель состояния на доске: первая строка инструкции. */\nexport function stateGoal(instructions: string): string {\n return instructions.split(\"\\n\").find((line) => line.trim() !== \"\")?.trim() ?? \"\";\n}\n","import { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport type { FlowEditorMode } from \"../flow-editor-skin\";\nimport type { FlowSelection } from \"./use-flow-editor\";\n\n// Место на экране: что на доске свёрнуто, открыта ли правая панель, развёрнут ли весь редактор. Состояние «свёрнуто»\n// запоминается в localStorage браузера (общее для всех сценариев приложения), на сервере и без localStorage — по умолчанию.\n\n/** Шапка доски: `full` — логотип, название и кнопки; `compact` — одна узкая строка кнопок (название у приложения своё). */\nexport type FlowHeaderMode = \"full\" | \"compact\";\n/** Легенда «Условия выхода»: свёрнута в кнопку, открыта или убрана совсем. */\nexport type FlowLegendMode = \"collapsed\" | \"open\" | \"hidden\";\n/** Мини-карта: открыта, свёрнута в кнопку или убрана совсем. */\nexport type FlowMinimapMode = \"open\" | \"collapsed\" | \"hidden\";\n/** Панель «Сценарий»: `open` — открыта, сворачивается кнопкой; `collapsible` — свёрнута, пока ничего не выбрано, выбор раскрывает. */\nexport type FlowInspectorMode = \"open\" | \"collapsible\";\n\nexport interface FlowBoardSpaceProps {\n header?: FlowHeaderMode;\n legend?: FlowLegendMode;\n minimap?: FlowMinimapMode;\n inspector?: FlowInspectorMode;\n /** Кнопка «На весь экран» в шапке. По умолчанию есть. */\n fullscreen?: boolean;\n /** Ключ в localStorage для запомненного. По умолчанию общий `agent-chat-flow-board`; `null` — не запоминать. */\n storageKey?: string | null;\n}\n\nexport const DEFAULT_SPACE_STORAGE_KEY = \"agent-chat-flow-board\";\n\ninterface Remembered {\n legend?: boolean;\n minimap?: boolean;\n inspector?: boolean;\n}\n\nfunction readRemembered(key: string | null | undefined): Remembered {\n if (!key || typeof window === \"undefined\") return {};\n try {\n const parsed: unknown = JSON.parse(window.localStorage.getItem(key) ?? \"null\");\n if (typeof parsed !== \"object\" || parsed === null) return {};\n const result: Remembered = {};\n for (const name of [\"legend\", \"minimap\", \"inspector\"] as const) {\n const value = (parsed as Record<string, unknown>)[name];\n if (typeof value === \"boolean\") result[name] = value;\n }\n return result;\n } catch {\n return {};\n }\n}\n\nfunction writeRemembered(key: string | null | undefined, value: Remembered) {\n if (!key || typeof window === \"undefined\") return;\n try {\n window.localStorage.setItem(key, JSON.stringify(value));\n } catch {\n // Хранилище закрыто или переполнено — просто не запоминаем.\n }\n}\n\nconst selectionKey = (selection: FlowSelection) => {\n if (selection.kind === \"state\") return `state:${selection.stateId}:${selection.exitId ?? \"\"}`;\n if (selection.kind === \"any\") return `any:${selection.exitId ?? \"\"}`;\n return selection.kind === \"overview\" ? `overview:${selection.sideTaskId ?? \"\"}` : selection.kind;\n};\n\nexport interface BoardSpace {\n header: FlowHeaderMode;\n legendHidden: boolean;\n legendOpen: boolean;\n toggleLegend(): void;\n minimapHidden: boolean;\n minimapOpen: boolean;\n toggleMinimap(): void;\n inspectorOpen: boolean;\n /** Кнопка сворачивания панели нужна только в обычной правке: проверка и прогон держат панель открытой. */\n inspectorToggleable: boolean;\n toggleInspector(): void;\n fullscreenAllowed: boolean;\n fullscreen: boolean;\n setFullscreen(on: boolean): void;\n}\n\nexport function useBoardSpace(\n props: FlowBoardSpaceProps,\n editor: { selection: FlowSelection; mode: FlowEditorMode },\n): BoardSpace {\n const { header = \"full\", legend = \"collapsed\", minimap = \"open\", inspector = \"open\", fullscreen: fullscreenAllowed = true } = props;\n const storageKey = props.storageKey === undefined ? DEFAULT_SPACE_STORAGE_KEY : props.storageKey;\n\n const [remembered, setRemembered] = useState<Remembered>({});\n // Читаем после первого показа: на сервере и при гидратации экран тот же, что по умолчанию.\n useEffect(() => setRemembered(readRemembered(storageKey)), [storageKey]);\n // Пишем в хранилище из эффекта, а не из функции setState (она может вызываться дважды).\n const unsaved = useRef(false);\n useEffect(() => {\n if (!unsaved.current) return;\n unsaved.current = false;\n writeRemembered(storageKey, remembered);\n }, [remembered, storageKey]);\n const remember = useCallback((name: keyof Remembered, value: boolean) => {\n unsaved.current = true;\n setRemembered((current) => ({ ...current, [name]: value }));\n }, []);\n\n const legendOpen = legend === \"hidden\" ? false : (remembered.legend ?? legend === \"open\");\n const minimapOpen = minimap === \"hidden\" ? false : (remembered.minimap ?? minimap === \"open\");\n\n // «collapsible»: панель следует за выбором и не запоминается, «open»: запоминается выбор человека.\n const selected = editor.selection.kind !== \"overview\" || editor.selection.sideTaskId !== undefined;\n const key = selectionKey(editor.selection);\n const [followed, setFollowed] = useState(selected);\n const [previousKey, setPreviousKey] = useState(key);\n if (key !== previousKey) {\n setPreviousKey(key);\n setFollowed(selected);\n }\n // Проверка и прогон живут в панели: в них она открыта всегда.\n const needed = editor.mode !== \"edit\";\n const inspectorOpen = needed || (inspector === \"collapsible\" ? followed : (remembered.inspector ?? true));\n\n const [fullscreen, setFullscreen] = useState(false);\n // Приложение выключило полный экран на лету — внутреннее состояние не должно вернуться при включении.\n useEffect(() => {\n if (!fullscreenAllowed) setFullscreen(false);\n }, [fullscreenAllowed]);\n\n return useMemo(\n () => ({\n header,\n legendHidden: legend === \"hidden\",\n legendOpen,\n toggleLegend: () => remember(\"legend\", !legendOpen),\n minimapHidden: minimap === \"hidden\",\n minimapOpen,\n toggleMinimap: () => remember(\"minimap\", !minimapOpen),\n inspectorOpen,\n inspectorToggleable: !needed,\n toggleInspector: () => {\n if (needed) return;\n if (inspector === \"collapsible\") setFollowed(!inspectorOpen);\n else remember(\"inspector\", !inspectorOpen);\n },\n fullscreenAllowed,\n fullscreen: fullscreenAllowed && fullscreen,\n setFullscreen,\n }),\n [header, legend, legendOpen, minimap, minimapOpen, inspector, inspectorOpen, needed, fullscreenAllowed, fullscreen, remember],\n );\n}\n\nconst FOCUSABLE = 'a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex=\"-1\"])';\n\n/**\n * Полный экран: Esc выходит (если не открыто окно поверх), страница под редактором не прокручивается, Tab ходит по кругу\n * внутри. Возвращает ссылку-обработчик клавиш для корня.\n */\nexport function useFullscreenBehavior(active: boolean, onExit: () => void, blocked: boolean, root: HTMLElement | null) {\n useEffect(() => {\n if (!active) return;\n const previous = document.body.style.overflow;\n document.body.style.overflow = \"hidden\";\n return () => {\n document.body.style.overflow = previous;\n };\n }, [active]);\n\n useEffect(() => {\n if (!active) return;\n const onKey = (event: KeyboardEvent) => {\n if (event.key !== \"Escape\" || event.defaultPrevented || blocked) return;\n // Esc в поле ввода только снимает фокус; выход — Esc вне поля.\n const target = event.target;\n if (target instanceof HTMLElement && root?.contains(target) && target.matches('input, textarea, select, [contenteditable]:not([contenteditable=\"false\"])')) {\n event.preventDefault();\n target.blur();\n return;\n }\n event.preventDefault();\n onExit();\n // Кнопка в шапке остаётся на месте: фокус возвращается на неё.\n root?.querySelector<HTMLElement>(\"[data-flow-fullscreen-toggle]\")?.focus();\n };\n document.addEventListener(\"keydown\", onKey);\n return () => document.removeEventListener(\"keydown\", onKey);\n }, [active, blocked, onExit, root]);\n\n return useCallback(\n (event: { key: string; shiftKey: boolean; target: EventTarget; preventDefault(): void }) => {\n // События React всплывают и через портал (окно JSON в body): чужой Tab не трогаем.\n if (!active || event.key !== \"Tab\" || !root || !(event.target instanceof Node) || !root.contains(event.target)) return;\n const items = [...root.querySelectorAll<HTMLElement>(FOCUSABLE)].filter((item) => item.getClientRects().length > 0);\n const first = items[0];\n const last = items[items.length - 1];\n if (!first || !last) return;\n const current = document.activeElement;\n if (event.shiftKey && (current === first || !root.contains(current))) {\n event.preventDefault();\n last.focus();\n } else if (!event.shiftKey && (current === last || !root.contains(current))) {\n event.preventDefault();\n first.focus();\n }\n },\n [active, root],\n );\n}\n","import {\n Background,\n BackgroundVariant,\n getBezierPath,\n Handle,\n MiniMap,\n Panel,\n Position,\n ReactFlow,\n ReactFlowProvider,\n applyNodeChanges,\n useReactFlow,\n useStore,\n type Connection,\n type Edge,\n type EdgeProps,\n type FinalConnectionState,\n type Node,\n type NodeChange,\n type NodeProps,\n} from \"@xyflow/react\";\nimport { createContext, useCallback, useContext, useEffect, useMemo, useState, type ReactNode } from \"react\";\nimport { ANY_STATE_LAYOUT_KEY, RETURN_TARGET, type AgentFlow, type FlowCatalog, type FlowExit, type FlowIssue, type FlowPoint } from \"../../format/flow-format\";\nimport { activeExits, isFinal, stateById } from \"../../engine/flow-graph\";\nimport type { FlowEditorLabels } from \"../../labels/editor\";\nimport { useFlowLabels } from \"../flow-labels\";\nimport type {\n FlowAnyStateNodeProps,\n FlowEdgeKind,\n FlowEdgeProps,\n FlowEditorSkin,\n FlowExitRowView,\n FlowIssueCount,\n FlowStateNodeProps,\n FlowBoardToggleProps,\n} from \"../flow-editor-skin\";\nimport type { BoardSpace } from \"./board-space\";\nimport { FLOW_BOARD_CSS } from \"./board-styles\";\nimport { addExit, connectExit, placeNode, type ExitOwner } from \"./editor-model\";\nimport { conditionText, edgeKind, stateGoal, targetTitle } from \"./exit-text\";\nimport { stateTimingText } from \"./schedule-model\";\nimport { simulationChoices } from \"./flow-simulation\";\nimport type { FlowEditorController } from \"./use-flow-editor\";\n\n// Доска: узлы и стрелки `@xyflow/react`, нарисованные частями скина. Здесь — только раскладка, ручки, пути стрелок и\n// жесты; что показать в узле, считает этот модуль из сценария, правки уходят в `useFlowEditor`.\n\n/** Ручка «новое условие» у каждого узла: потянуть — появится условие словами. */\nexport const NEW_EXIT_HANDLE = \"@new\";\nconst INPUT_HANDLE = \"in\";\n\nconst LEGEND_KINDS: FlowEdgeKind[] = [\"judge\", \"data\", \"event\", \"timer\", \"return\"];\n\ntype StateNodeData = { view: Omit<FlowStateNodeProps, \"renderInputHandle\" | \"renderExitHandle\">; draggable: boolean };\ntype AnyNodeData = { view: Omit<FlowAnyStateNodeProps, \"renderExitHandle\">; draggable: boolean };\ntype FlowEdgeData = Omit<FlowEdgeProps, \"edgeId\" | \"path\" | \"labelX\" | \"labelY\">;\n\ntype StateNode = Node<StateNodeData, \"state\">;\ntype AnyNode = Node<AnyNodeData, \"any\">;\ntype BoardNode = StateNode | AnyNode;\ntype BoardEdge = Edge<FlowEdgeData, \"flow\">;\n\nconst SkinContext = createContext<FlowEditorSkin | null>(null);\n\nfunction useSkin(): FlowEditorSkin {\n const skin = useContext(SkinContext);\n if (!skin) throw new Error(\"FlowBoard renders only inside FlowEditor.\");\n return skin;\n}\n\nfunction exitHandle(exitId: string, connectable: boolean): ReactNode {\n return <Handle type=\"source\" position={Position.Right} id={exitId} isConnectable={connectable} />;\n}\n\nfunction StateNodeView({ data }: NodeProps<StateNode>) {\n const skin = useSkin();\n return (\n <>\n <skin.FlowStateNode\n {...data.view}\n renderInputHandle={() => <Handle type=\"target\" position={Position.Left} id={INPUT_HANDLE} isConnectable={data.draggable} />}\n renderExitHandle={(exitId) => exitHandle(exitId, data.draggable)}\n />\n {data.draggable ? <Handle type=\"source\" position={Position.Right} id={NEW_EXIT_HANDLE} className=\"flow-board__new-exit\" /> : null}\n </>\n );\n}\n\nfunction AnyNodeView({ data }: NodeProps<AnyNode>) {\n const skin = useSkin();\n return (\n <>\n <skin.FlowAnyStateNode {...data.view} renderExitHandle={(exitId) => exitHandle(exitId, data.draggable)} />\n {data.draggable ? <Handle type=\"source\" position={Position.Right} id={NEW_EXIT_HANDLE} className=\"flow-board__new-exit\" /> : null}\n </>\n );\n}\n\nfunction EdgeView({ id, sourceX, sourceY, targetX, targetY, sourcePosition, targetPosition, data }: EdgeProps<BoardEdge>) {\n const skin = useSkin();\n const [path, labelX, labelY] = getBezierPath({ sourceX, sourceY, sourcePosition, targetX, targetY, targetPosition });\n if (!data) return null;\n return <skin.FlowEdge {...data} edgeId={id} path={path} labelX={labelX} labelY={labelY} />;\n}\n\nconst nodeTypes = { state: StateNodeView, any: AnyNodeView };\nconst edgeTypes = { flow: EdgeView };\n\n/** Место узла: из `layout`, а без него — сетка по порядку состояний. */\nfunction nodePosition(flow: AgentFlow, nodeId: string, index: number): FlowPoint {\n const saved = flow.layout[nodeId];\n if (saved) return saved;\n if (nodeId === ANY_STATE_LAYOUT_KEY) return { x: 40, y: -220 };\n return { x: 40 + (index % 4) * 330, y: 40 + Math.floor(index / 4) * 260 };\n}\n\nfunction countFor(issues: FlowIssue[], match: (issue: FlowIssue) => boolean): FlowIssueCount {\n const found = issues.filter(match);\n return { errors: found.filter((issue) => issue.level === \"error\").length, warnings: found.filter((issue) => issue.level === \"warning\").length };\n}\n\nfunction exitRows(flow: AgentFlow, catalog: FlowCatalog, exits: FlowExit[], issues: FlowIssue[], labels: FlowEditorLabels): FlowExitRowView[] {\n return exits.map((exit) => ({\n exitId: exit.id,\n kind: edgeKind(exit),\n text: conditionText(flow, exit.when, labels, catalog),\n target: targetTitle(flow, exit.to, labels),\n issues: countFor(issues, (issue) => issue.place.exitId === exit.id),\n }));\n}\n\nconst ownerOf = (nodeId: string): ExitOwner => (nodeId === ANY_STATE_LAYOUT_KEY ? null : nodeId);\n\n/** Что подсветить в прогоне: где агент, где был, куда можно пойти, по каким стрелкам прошли. */\nfunction runMarks(editor: FlowEditorController) {\n const sim = editor.simulation;\n if (editor.mode !== \"run\" || !sim) return null;\n const visited = new Set(sim.steps.map((step) => step.stateId));\n const next = new Set(simulationChoices(editor.flow, sim).flatMap((choice) => (choice.target ? [choice.target] : [])));\n const traversed = new Set(sim.steps.flatMap((step) => (step.exitId ? [step.exitId] : [])));\n const state = stateById(editor.flow, sim.run.state);\n const live = new Set(state ? activeExits(editor.flow, state).map(({ exit }) => exit.id) : []);\n return { current: sim.run.state, visited, next, traversed, live };\n}\n\nfunction useBoardModel(editor: FlowEditorController) {\n const labels = useFlowLabels().editor;\n const { flow, catalog, issues, selection, mode, select, readOnly } = editor;\n return useMemo(() => {\n const marks = runMarks(editor);\n // Выбирать ноду и стрелку можно вне прогона; двигать и соединять — ещё и не в режиме «только просмотр».\n const selectable = mode !== \"run\";\n const editable = selectable && !readOnly;\n const selectedExit = selection.kind === \"state\" || selection.kind === \"any\" ? selection.exitId : undefined;\n\n const nodes: BoardNode[] = flow.states.map((state, index) => ({\n id: state.id,\n type: \"state\",\n position: nodePosition(flow, state.id, index),\n draggable: editable,\n data: {\n draggable: editable,\n view: {\n stateId: state.id,\n title: state.title || state.id,\n goal: stateGoal(state.instructions),\n exits: exitRows(flow, catalog, state.exits, issues, labels),\n tags: state.tags,\n start: flow.start === state.id,\n final: isFinal(state),\n noSideQuestions: state.noSideQuestions,\n timing: stateTimingText(flow, state, labels),\n selected: selection.kind === \"state\" && selection.stateId === state.id,\n dimmed: marks !== null && !marks.visited.has(state.id) && !marks.next.has(state.id),\n run: marks === null ? null : marks.current === state.id ? \"current\" : marks.visited.has(state.id) ? \"visited\" : null,\n issues: countFor(issues, (issue) => issue.place.stateId === state.id),\n onSelect: () => selectable && select({ kind: \"state\", stateId: state.id }),\n },\n },\n }));\n if (flow.anyState.exits.length > 0 || flow.anyState.except.length > 0 || flow.layout[ANY_STATE_LAYOUT_KEY]) {\n nodes.push({\n id: ANY_STATE_LAYOUT_KEY,\n type: \"any\",\n position: nodePosition(flow, ANY_STATE_LAYOUT_KEY, 0),\n draggable: editable,\n data: {\n draggable: editable,\n view: {\n except: flow.anyState.except.map((id) => stateById(flow, id)?.title ?? id),\n exits: exitRows(flow, catalog, flow.anyState.exits, issues, labels),\n selected: selection.kind === \"any\",\n dimmed: marks !== null,\n issues: countFor(issues, (issue) => !issue.place.stateId && flow.anyState.exits.some((exit) => exit.id === issue.place.exitId)),\n onSelect: () => selectable && select({ kind: \"any\" }),\n },\n },\n });\n }\n\n const owners: Array<{ nodeId: string; exits: FlowExit[] }> = [\n { nodeId: ANY_STATE_LAYOUT_KEY, exits: flow.anyState.exits },\n ...flow.states.map((state) => ({ nodeId: state.id, exits: state.exits })),\n ];\n const edges: BoardEdge[] = owners.flatMap(({ nodeId, exits }) =>\n exits\n .filter((exit) => exit.to !== null && exit.to !== RETURN_TARGET && stateById(flow, exit.to))\n .map((exit) => ({\n id: `${nodeId}:${exit.id}`,\n type: \"flow\" as const,\n source: nodeId,\n sourceHandle: exit.id,\n target: exit.to!,\n targetHandle: INPUT_HANDLE,\n data: {\n kind: edgeKind(exit),\n label: conditionText(flow, exit.when, labels, catalog),\n selected: selectedExit === exit.id,\n dimmed: marks !== null && !marks.traversed.has(exit.id) && !(marks.live.has(exit.id) && nodeId === marks.current),\n traversed: marks?.traversed.has(exit.id) ?? false,\n onSelect: () =>\n selectable && select(nodeId === ANY_STATE_LAYOUT_KEY ? { kind: \"any\", exitId: exit.id } : { kind: \"state\", stateId: nodeId, exitId: exit.id }),\n },\n })),\n );\n return { nodes, edges };\n // `editor` целиком меняется на каждом рендере; от прогона берём `simulation` и `mode`.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [flow, catalog, issues, selection, mode, readOnly, editor.simulation, labels, select]);\n}\n\n/** Кнопка места на доске: у скина своя (`FlowBoardToggle`), без неё — простая на токенах `--flow-board-*`. */\nfunction BoardToggle(props: FlowBoardToggleProps) {\n const skin = useSkin();\n if (skin.FlowBoardToggle) return <skin.FlowBoardToggle {...props} />;\n return (\n <button\n type=\"button\"\n aria-label={props.label}\n title={props.label}\n aria-expanded={props.expanded}\n data-flow-board-toggle={props.kind}\n onClick={props.onClick}\n style={{\n font: \"inherit\",\n fontSize: 12,\n padding: \"6px 10px\",\n borderRadius: 8,\n cursor: \"pointer\",\n color: \"inherit\",\n background: \"var(--flow-board-handle-fill, #fff)\",\n border: \"1px solid var(--flow-board-handle, currentColor)\",\n }}\n >\n {props.showText ? props.label : props.kind === \"legend\" ? \"?\" : props.expanded ? \"×\" : \"+\"}\n </button>\n );\n}\n\n/** Кнопки масштаба скина: ведут доску через `useReactFlow`. */\nfunction ZoomControls() {\n const skin = useSkin();\n const { zoomIn, zoomOut, fitView } = useReactFlow();\n const zoom = useStore((store) => store.transform[2]);\n return (\n <skin.FlowZoomControls\n zoom={zoom}\n onZoomIn={() => void zoomIn({ duration: 150 })}\n onZoomOut={() => void zoomOut({ duration: 150 })}\n onFit={() => void fitView({ duration: 200, padding: 0.15 })}\n />\n );\n}\n\nfunction clientPoint(event: MouseEvent | TouchEvent): { x: number; y: number } | null {\n if (\"changedTouches\" in event) {\n const touch = event.changedTouches[0];\n return touch ? { x: touch.clientX, y: touch.clientY } : null;\n }\n return { x: event.clientX, y: event.clientY };\n}\n\nconst ignoreNodeClick = () => {};\n\nfunction Board({ editor, space }: { editor: FlowEditorController; space: BoardSpace }) {\n const spaceLabels = useFlowLabels().editor.board.space;\n const skin = useSkin();\n const model = useBoardModel(editor);\n const { screenToFlowPosition } = useReactFlow();\n const [nodes, setNodes] = useState<BoardNode[]>(model.nodes);\n\n // Узлы из сценария, но размеры (их меряет доска) и место во время перетаскивания — свои.\n useEffect(() => {\n setNodes((previous) => {\n const byId = new Map(previous.map((node) => [node.id, node]));\n return model.nodes.map((node) => {\n const old = byId.get(node.id);\n if (!old) return node;\n return { ...node, measured: old.measured, ...(old.dragging ? { position: old.position, dragging: true } : {}) } as BoardNode;\n });\n });\n }, [model.nodes]);\n\n const onNodesChange = useCallback((changes: NodeChange<BoardNode>[]) => setNodes((current) => applyNodeChanges(changes, current)), []);\n\n const { edit, connect, connectToNewState, select } = editor;\n\n const onConnect = useCallback(\n (connection: Connection) => {\n const owner = ownerOf(connection.source);\n if (connection.target === ANY_STATE_LAYOUT_KEY) return;\n if (connection.sourceHandle === NEW_EXIT_HANDLE || !connection.sourceHandle) {\n edit((flow) => {\n const made = addExit(flow, owner, \"judge\");\n return connectExit(made.flow, owner, made.exitId, connection.target);\n });\n return;\n }\n connect(owner, connection.sourceHandle, connection.target);\n },\n [connect, edit],\n );\n\n const onConnectEnd = useCallback(\n (event: MouseEvent | TouchEvent, state: FinalConnectionState) => {\n if (state.isValid || !state.fromNode || !state.fromHandle) return;\n const owner = ownerOf(state.fromNode.id);\n const exitId = state.fromHandle.id === NEW_EXIT_HANDLE ? null : (state.fromHandle.id ?? null);\n // Отпустили на узле мимо ручки — всё равно соединяем с ним.\n if (state.toNode && state.toNode.id !== ANY_STATE_LAYOUT_KEY) {\n onConnect({ source: state.fromNode.id, sourceHandle: exitId ?? NEW_EXIT_HANDLE, target: state.toNode.id, targetHandle: INPUT_HANDLE });\n return;\n }\n const point = clientPoint(event);\n if (!point) return;\n const at = screenToFlowPosition(point);\n connectToNewState(owner, exitId, { x: Math.round(at.x), y: Math.round(at.y - 40) });\n },\n [connectToNewState, onConnect, screenToFlowPosition],\n );\n\n const onNodeDragStop = useCallback(\n (_event: unknown, node: BoardNode) => edit((flow) => placeNode(flow, node.id, node.position)),\n [edit],\n );\n\n const selectable = editor.mode !== \"run\";\n const editable = selectable && !editor.readOnly;\n return (\n <ReactFlow<BoardNode, BoardEdge>\n nodes={nodes}\n edges={model.edges}\n nodeTypes={nodeTypes}\n edgeTypes={edgeTypes}\n onNodesChange={onNodesChange}\n onConnect={onConnect}\n onConnectEnd={onConnectEnd}\n onNodeDragStop={onNodeDragStop}\n // Без перетаскивания и связей (только просмотр) доска отключает клики по узлам, если нет обработчика: нужен хотя бы пустой.\n onNodeClick={ignoreNodeClick}\n onPaneClick={() => selectable && select({ kind: \"overview\" })}\n nodesConnectable={editable}\n elementsSelectable={false}\n deleteKeyCode={null}\n selectionKeyCode={null}\n multiSelectionKeyCode={null}\n fitView\n fitViewOptions={{ padding: 0.15 }}\n minZoom={0.2}\n maxZoom={2}\n proOptions={{ hideAttribution: true }}\n >\n <Background variant={BackgroundVariant.Dots} gap={22} size={1.2} />\n {!space.legendHidden && (\n <Panel position=\"bottom-left\" className=\"flow-board__legend\">\n <div className=\"flow-board__legend-stack\" style={{ display: \"flex\", flexDirection: \"column\", alignItems: \"flex-start\", gap: 8 }}>\n {space.legendOpen && <skin.FlowLegend kinds={LEGEND_KINDS} />}\n <BoardToggle kind=\"legend\" label={spaceLabels.legend} expanded={space.legendOpen} showText onClick={space.toggleLegend} />\n </div>\n </Panel>\n )}\n {space.inspectorToggleable && (\n <Panel position=\"top-right\">\n <BoardToggle\n kind=\"inspector\"\n label={space.inspectorOpen ? spaceLabels.hideInspector : spaceLabels.showInspector}\n expanded={space.inspectorOpen}\n onClick={space.toggleInspector}\n />\n </Panel>\n )}\n <Panel position=\"bottom-right\">\n <div style={{ display: \"flex\", alignItems: \"center\", gap: 8 }}>\n {!space.minimapHidden && (\n <span className=\"flow-board__minimap-toggle\" style={{ display: \"contents\" }}>\n <BoardToggle\n kind=\"minimap\"\n label={space.minimapOpen ? spaceLabels.hideMinimap : spaceLabels.showMinimap}\n expanded={space.minimapOpen}\n onClick={space.toggleMinimap}\n />\n </span>\n )}\n <ZoomControls />\n </div>\n </Panel>\n {space.minimapOpen && <MiniMap className=\"flow-board__minimap\" pannable zoomable position=\"bottom-right\" style={{ marginBottom: 76 }} />}\n </ReactFlow>\n );\n}\n\n/** Доска редактора. Свой `ReactFlowProvider`: другой сценарий — доска заново и «весь граф» в экран. */\nexport function FlowBoard({ editor, skin, space }: { editor: FlowEditorController; skin: FlowEditorSkin; space: BoardSpace }) {\n return (\n <SkinContext.Provider value={skin}>\n <style>{FLOW_BOARD_CSS}</style>\n <ReactFlowProvider key={editor.flow.id}>\n <Board editor={editor} space={space} />\n </ReactFlowProvider>\n </SkinContext.Provider>\n );\n}\n","// Стили, без которых доска `@xyflow/react` не работает: слои, места узлов и ручек, мини-карта, панели. Взяты из\n// `@xyflow/react/dist/base.css` (MIT) и урезаны. Цвета — переменные `--flow-board-*`: их задаёт скин, а здесь только\n// нейтральные запасные значения. Стиль вставляется рядом с доской, приложению ничего импортировать не нужно.\n\nexport const FLOW_BOARD_CSS = `\n.react-flow { direction: ltr; position: relative; width: 100%; height: 100%; overflow: hidden; z-index: 0; }\n.react-flow__container, .react-flow__edgelabel-renderer, .react-flow__viewport-portal {\n position: absolute; width: 100%; height: 100%; top: 0; left: 0;\n}\n.react-flow__pane { z-index: 1; touch-action: none; }\n.react-flow__pane.draggable { cursor: grab; }\n.react-flow__pane.dragging { cursor: grabbing; }\n.react-flow__viewport { transform-origin: 0 0; z-index: 2; pointer-events: none; }\n.react-flow__renderer { z-index: 4; }\n.react-flow__background { pointer-events: none; z-index: -1; }\n.react-flow__background-pattern.dots { fill: var(--flow-board-dots, rgba(128, 128, 128, 0.35)); }\n.react-flow .react-flow__edges { position: absolute; }\n.react-flow .react-flow__edges svg { overflow: visible; position: absolute; pointer-events: none; }\n.react-flow__edge { pointer-events: visibleStroke; }\n.react-flow__edge.inactive { pointer-events: none; }\n.react-flow__edge:focus, .react-flow__edge:focus-visible { outline: none; }\n.react-flow__connection { pointer-events: none; }\n.react-flow__connection-path { stroke: var(--flow-board-connection, currentColor); stroke-width: 2; fill: none; stroke-dasharray: 4 4; }\nsvg.react-flow__connectionline { z-index: 1001; overflow: visible; position: absolute; }\n.react-flow__nodes { pointer-events: none; transform-origin: 0 0; }\n.react-flow__node {\n position: absolute; user-select: none; pointer-events: all; transform-origin: 0 0; box-sizing: border-box; cursor: default;\n}\n.react-flow__node.draggable { cursor: grab; }\n.react-flow__node.draggable.dragging { cursor: grabbing; }\n.react-flow__node:focus, .react-flow__node:focus-visible { outline: none; }\n.react-flow__handle {\n position: absolute; pointer-events: none; width: 10px; height: 10px; min-width: 5px; min-height: 5px; border-radius: 999px;\n background: var(--flow-board-handle-fill, #fff); border: 1.5px solid var(--flow-board-handle, currentColor);\n}\n.react-flow__handle.connectingfrom, .react-flow__handle.connectionindicator { pointer-events: all; cursor: crosshair; }\n.react-flow__handle-left { top: 50%; left: 0; transform: translate(-50%, -50%); }\n.react-flow__handle-right { top: 50%; right: 0; transform: translate(50%, -50%); }\n.react-flow__handle-top { top: 0; left: 50%; transform: translate(-50%, -50%); }\n.react-flow__handle-bottom { top: auto; bottom: 0; left: 50%; transform: translate(-50%, 50%); }\n.react-flow__panel { position: absolute; z-index: 5; margin: 16px; }\n.react-flow__panel.top { top: 0; }\n.react-flow__panel.bottom { bottom: 0; }\n.react-flow__panel.left { left: 0; }\n.react-flow__panel.right { right: 0; }\n.react-flow__panel.top.center, .react-flow__panel.bottom.center { left: 50%; transform: translateX(-16px) translateX(-50%); }\n.react-flow__minimap { background: var(--flow-board-minimap, #fff); border-radius: 12px; overflow: hidden; }\n.react-flow__minimap-svg { display: block; }\n.react-flow__minimap-mask { fill: var(--flow-board-minimap-mask, rgba(128, 128, 128, 0.15)); }\n.react-flow__minimap-node { fill: var(--flow-board-minimap-node, rgba(128, 128, 128, 0.35)); }\n.flow-board__new-exit.react-flow__handle {\n top: auto; bottom: 10px; right: 0; transform: translate(50%, 0); opacity: 0.55;\n}\n.flow-board__new-exit.react-flow__handle:hover { opacity: 1; }\n@media (max-width: 860px) {\n .flow-board__legend, .flow-board__minimap, .flow-board__minimap-toggle { display: none !important; }\n}\n`;\n","import {\n DEFAULT_LATE_START_HOURS,\n type AgentFlow,\n type FlowAfterEnd,\n type FlowCondition,\n type FlowDuration,\n type FlowExit,\n type FlowNudges,\n type FlowSchedule,\n type FlowState,\n} from \"../../format/flow-format\";\nimport type { FlowEditorLabels } from \"../../labels/editor\";\nimport { addExit, updateExit } from \"./editor-model\";\n\n// Правки «Дней и времени», продолжительности и касаний ноды: чистые функции, каждая возвращает новый `AgentFlow`.\n\n/** «Дни и время» при включении: день с 9:00, порог позднего старта по умолчанию, без прощания. */\nexport const DEFAULT_SCHEDULE: FlowSchedule = { dayStart: \"09:00\", lateStartHours: DEFAULT_LATE_START_HOURS, farewellOnDeadline: false };\n\n/** Свои касания ноды без общего образца: 15 мин · 1 ч · 4 ч тишины. */\nexport const DEFAULT_NUDGES: FlowNudges = {\n afterSilence: [\n { amount: 15, unit: \"min\" },\n { amount: 1, unit: \"h\" },\n { amount: 4, unit: \"h\" },\n ],\n};\n\n/** Без ключей со значением `undefined`; пустой объект — `undefined`. */\nfunction compact<T extends object>(value: T): T | undefined {\n const entries = Object.entries(value).filter(([, item]) => item !== undefined && item !== \"\");\n return entries.length === 0 ? undefined : (Object.fromEntries(entries) as T);\n}\n\nfunction withOptional<T extends object, K extends keyof T>(target: T, key: K, value: T[K] | undefined): T {\n const { [key]: _old, ...rest } = target;\n return (value === undefined ? rest : { ...rest, [key]: value }) as T;\n}\n\nexport function setScheduleOn(flow: AgentFlow, on: boolean): AgentFlow {\n if (on) return flow.schedule ? flow : { ...flow, schedule: { ...DEFAULT_SCHEDULE } };\n return withOptional(flow, \"schedule\", undefined);\n}\n\nexport type SchedulePatch = { [K in keyof FlowSchedule]?: FlowSchedule[K] | undefined };\n\n/** Правка «Дней и времени»: `undefined` и пустая строка убирают поле, пустые вложенные разделы — целиком. */\nexport function updateSchedule(flow: AgentFlow, patch: SchedulePatch): AgentFlow {\n let schedule: FlowSchedule = flow.schedule ?? { ...DEFAULT_SCHEDULE };\n for (const [key, raw] of Object.entries(patch) as Array<[keyof FlowSchedule, unknown]>) {\n const value = raw !== null && typeof raw === \"object\" && !Array.isArray(raw) && key !== \"nudges\" ? compact(raw) : raw === \"\" ? undefined : raw;\n schedule = withOptional(schedule, key, value as never);\n }\n return { ...flow, schedule };\n}\n\nexport function setAfterEnd(flow: AgentFlow, mode: FlowAfterEnd): AgentFlow {\n return { ...flow, afterEnd: mode };\n}\n\n// ---------- «Длится» ----------\n\nexport type DurationUnit = \"h\" | \"d\" | \"program_day\";\n\n/**\n * Продолжительность ноды: выход «длится N дней сценария» (`state_days`), «до дня N программы» (`program_day`, `amount` —\n * номер дня) или «N часов в этом состоянии».\n */\nexport interface StateDuration {\n exitId: string;\n amount: number;\n unit: DurationUnit;\n to: string | null;\n}\n\nfunction durationExit(exit: FlowExit): StateDuration | null {\n const { when } = exit;\n if (when.type !== \"timer\") return null;\n if (when.from === \"state_days\") return { exitId: exit.id, amount: when.days, unit: \"d\", to: exit.to };\n if (when.from === \"program_day\") return { exitId: exit.id, amount: when.day, unit: \"program_day\", to: exit.to };\n if (when.from === \"in_state\" && when.unit === \"h\") return { exitId: exit.id, amount: when.amount, unit: \"h\", to: exit.to };\n return null;\n}\n\n/** Первый выход-продолжительность ноды; минуты «в этом состоянии» — обычный таймер, не «Длится». */\nexport function durationOf(state: FlowState): StateDuration | null {\n for (const exit of state.exits) {\n const found = durationExit(exit);\n if (found) return found;\n }\n return null;\n}\n\n/** «Длится»: дни — `state_days`, день программы — `program_day`, часы — `in_state`. Правится тот же выход; `null` — выход убирается. */\nexport function setDuration(flow: AgentFlow, stateId: string, value: { amount: number; unit: DurationUnit } | null): AgentFlow {\n const state = flow.states.find((candidate) => candidate.id === stateId);\n if (!state) return flow;\n const current = durationOf(state);\n if (value === null) {\n if (!current) return flow;\n return { ...flow, states: flow.states.map((candidate) => (candidate.id === stateId ? { ...candidate, exits: candidate.exits.filter((exit) => exit.id !== current.exitId) } : candidate)) };\n }\n const amount = Math.max(1, Math.round(value.amount) || 1);\n const when: FlowCondition =\n value.unit === \"d\"\n ? { type: \"timer\", from: \"state_days\", days: amount }\n : value.unit === \"program_day\"\n ? { type: \"timer\", from: \"program_day\", day: amount }\n : { type: \"timer\", from: \"in_state\", amount, unit: \"h\" };\n if (current) return updateExit(flow, stateId, current.exitId, { when, to: current.to });\n const made = addExit(flow, stateId, \"timer\");\n return updateExit(made.flow, stateId, made.exitId, { when, to: null });\n}\n\n// ---------- Касания ----------\n\nexport type NudgesMode = \"inherit\" | \"own\" | \"off\";\n\nexport function nudgesMode(state: FlowState): NudgesMode {\n if (state.nudges === \"off\") return \"off\";\n return state.nudges ? \"own\" : \"inherit\";\n}\n\n/** Касания ноды: как у сценария (поля нет), свои (образец — общие или 15 мин · 1 ч · 4 ч), выкл. */\nexport function setStateNudges(flow: AgentFlow, stateId: string, mode: NudgesMode): AgentFlow {\n return {\n ...flow,\n states: flow.states.map((state) => {\n if (state.id !== stateId || nudgesMode(state) === mode) return state;\n if (mode === \"inherit\") return withOptional(state, \"nudges\", undefined);\n if (mode === \"off\") return { ...state, nudges: \"off\" };\n return { ...state, nudges: structuredClone(flow.schedule?.nudges ?? DEFAULT_NUDGES) };\n }),\n };\n}\n\n/** Своё расписание касаний ноды: пустые части убираются, срок в днях остаётся. */\nexport function updateStateNudges(flow: AgentFlow, stateId: string, nudges: FlowNudges): AgentFlow {\n return {\n ...flow,\n states: flow.states.map((state) => {\n if (state.id !== stateId) return state;\n const days = state.nudges && state.nudges !== \"off\" ? state.nudges.days : undefined;\n return { ...state, nudges: { ...cleanNudges(nudges), ...(days !== undefined && { days }) } };\n }),\n };\n}\n\n/** Сколько дней действуют свои касания ноды, считая день входа; `null` — всё время в ноде. */\nexport function setStateNudgesDays(flow: AgentFlow, stateId: string, days: number | null): AgentFlow {\n return {\n ...flow,\n states: flow.states.map((state) => {\n if (state.id !== stateId || !state.nudges || state.nudges === \"off\") return state;\n const { days: _days, ...rest } = state.nudges;\n return { ...state, nudges: days === null ? rest : { ...rest, days: Math.max(1, Math.round(days) || 1) } };\n }),\n };\n}\n\n/** Срок своих касаний ноды в днях; всё время в ноде или касания не свои — `null`. */\nexport function stateNudgesDays(state: FlowState): number | null {\n return state.nudges && state.nudges !== \"off\" ? (state.nudges.days ?? null) : null;\n}\n\n/** Касания по умолчанию в «Днях и времени»; `null` — без общих касаний. */\nexport function updateScheduleNudges(flow: AgentFlow, nudges: FlowNudges | null): AgentFlow {\n return updateSchedule(flow, { nudges: nudges === null ? undefined : cleanNudges(nudges) });\n}\n\nfunction cleanNudges(nudges: FlowNudges): FlowNudges {\n let clean: FlowNudges = { afterSilence: nudges.afterSilence };\n if (nudges.dailyAt?.length) clean = { ...clean, dailyAt: nudges.dailyAt };\n if (nudges.giveUpAfter) clean = { ...clean, giveUpAfter: nudges.giveUpAfter };\n return clean;\n}\n\n// ---------- Подписи ----------\n\n/** «15 мин», «4 ч», «3 дн.». */\nexport function durationText(duration: FlowDuration, labels: FlowEditorLabels): string {\n return `${duration.amount} ${labels.units[duration.unit]}`;\n}\n\n/** Подпись «Длится» и касаний на карточке ноды: «1 день · касания 15 мин · 1 ч · 4 ч». Ничего своего — пусто. */\nexport function stateTimingText(flow: AgentFlow, state: FlowState, labels: FlowEditorLabels): string {\n const parts: string[] = [];\n const duration = durationOf(state);\n if (duration) {\n parts.push(duration.unit === \"d\" ? labels.days(duration.amount) : duration.unit === \"program_day\" ? labels.programDay(duration.amount) : `${duration.amount} ${labels.units.h}`);\n }\n if (state.nudges === \"off\") parts.push(labels.board.noNudges);\n else if (state.nudges) {\n const steps = state.nudges.afterSilence.map((step) => durationText(step, labels));\n const daily = state.nudges.dailyAt ?? [];\n const days = state.nudges.days === undefined ? \"\" : ` ${labels.board.nudgesDays(state.nudges.days)}`;\n if (steps.length + daily.length > 0) parts.push(`${labels.board.nudges} ${[...steps, ...daily].join(\" · \")}${days}`);\n }\n return parts.join(\" · \");\n}\n","import { FLOW_OPS_BY_FIELD_TYPE, type AgentFlow, type DataCondition, type FlowExit, type FlowField } from \"../../format/flow-format\";\nimport type { FlowRun } from \"../../engine/flow-run\";\nimport { nextTransition, type FlowEvent } from \"../../engine/next-transition\";\nimport { activeExits, fieldById, stateById } from \"../../engine/flow-graph\";\nimport { applyTransition, noteAgentAnswer, noteHumanMessage, noteSideQuestion, startRun } from \"../../engine/run-updates\";\nimport { sideQuestion } from \"../../engine/side-questions\";\nimport { timerDueAt } from \"../../engine/timers\";\n\n// Прогон в редакторе: автор выбирает, что произошло, а решает движок — тот же `nextTransition`, что в рабочем чате.\n// Часы прогона свои: каждый шаг — минута разговора, таймер перематывает к своему сроку.\n\nconst STEP_MS = 60_000;\n\n/** Шаг пути прогона: куда пришли и по какому условию; `nothing` — «ничего из этого», агент остался. */\nexport interface SimulationStep {\n stateId: string;\n exitId: string | null;\n nothing: boolean;\n}\n\nexport interface Simulation {\n run: FlowRun;\n /** Карточка клиента в прогоне: id поля → значение и когда записано. */\n card: Record<string, { value: unknown; updatedAt: number }>;\n now: number;\n timeZone: string;\n steps: SimulationStep[];\n /** Прогон до последнего шага — для «шаг назад». */\n previous: Simulation | null;\n}\n\n/** Выбор «что произошло»: условие и куда приведёт движок (`null` — не сработает). */\nexport interface SimulationChoice {\n exitId: string;\n own: boolean;\n target: string | null;\n}\n\nexport function startSimulation(flow: AgentFlow, options: { now: number; timeZone: string }): Simulation {\n // Агент начинает разговор первым: от этого считается тишина человека.\n const run = noteAgentAnswer(startRun(flow, options.now), options.now);\n return { run, card: {}, now: options.now, timeZone: options.timeZone, steps: [{ stateId: run.state, exitId: null, nothing: false }], previous: null };\n}\n\nexport function simulationChoices(flow: AgentFlow, sim: Simulation): SimulationChoice[] {\n const state = stateById(flow, sim.run.state);\n if (!state) return [];\n return activeExits(flow, state).map(({ exit, own }) => {\n const after = chooseExit(flow, sim, exit.id);\n return { exitId: exit.id, own, target: after.steps.length > sim.steps.length ? after.run.state : null };\n });\n}\n\nfunction findExit(flow: AgentFlow, exitId: string): FlowExit | undefined {\n return [...flow.states.flatMap((state) => state.exits), ...flow.anyState.exits].find((exit) => exit.id === exitId);\n}\n\n/** Значение, при котором условие по данным выполнено. Уже подходящее не трогаем. */\nfunction fittingValue(condition: DataCondition, field: FlowField): unknown {\n const expected = condition.value;\n switch (condition.op) {\n case \"eq\":\n case \"contains\":\n return expected;\n case \"gt\":\n return typeof expected === \"number\" ? expected + 1 : expected;\n case \"lt\":\n return typeof expected === \"number\" ? expected - 1 : expected;\n case \"filled\":\n if (field.type === \"number\") return 1;\n return field.type === \"choice\" && field.options.length > 0 ? field.options[0] : \"✓\";\n }\n}\n\nfunction writeValue(flow: AgentFlow, sim: Simulation, fieldId: string, value: unknown): Simulation {\n const found = fieldById(flow, fieldId);\n if (!found) return sim;\n if (found.place === \"notes\") return { ...sim, run: { ...sim.run, notes: { ...sim.run.notes, [fieldId]: value } } };\n return { ...sim, card: { ...sim.card, [fieldId]: { value, updatedAt: sim.now } } };\n}\n\nfunction cardValues(sim: Simulation): Record<string, unknown> {\n return Object.fromEntries(Object.entries(sim.card).map(([id, entry]) => [id, entry.value]));\n}\n\n/**\n * Шаг: человек написал (кроме таймера), движок ищет переход по событию, агент ответил. Если между делом был вопрос о\n * человеке — он задан, следующий по темпу сценария.\n */\nfunction step(flow: AgentFlow, before: Simulation, prepare: (sim: Simulation) => { sim: Simulation; event: FlowEvent | null; human: boolean }): Simulation {\n const asked = sideQuestion(flow, before.run, { card: before.card, now: before.now });\n const prepared = prepare({ ...before, now: before.now + STEP_MS });\n const sim = prepared.sim;\n let run = prepared.human ? noteHumanMessage(sim.run, sim.now) : sim.run;\n const transition = prepared.event ? nextTransition(flow, run, prepared.event, sim.now) : null;\n const steps = [...sim.steps];\n if (transition) {\n run = applyTransition(flow, run, transition);\n steps.push({ stateId: transition.to, exitId: transition.exitId, nothing: false });\n } else if (prepared.event === null) {\n steps.push({ stateId: run.state, exitId: null, nothing: true });\n } else {\n // Условие не сработало (нет цели, «назад» некуда): прогон не меняется.\n return before;\n }\n run = noteAgentAnswer(run, sim.now);\n if (asked && asked.reason !== \"learn\") run = noteSideQuestion(run);\n return { ...sim, run, steps, previous: before };\n}\n\n/** Автор выбрал условие: собираем событие, на которое оно срабатывает, и отдаём движку. */\nexport function chooseExit(flow: AgentFlow, sim: Simulation, exitId: string): Simulation {\n const exit = findExit(flow, exitId);\n if (!exit) return sim;\n const when = exit.when;\n return step(flow, sim, (current) => {\n switch (when.type) {\n case \"judge\":\n return { sim: current, human: true, event: { type: \"verdict\", exitId, probability: 1, decidedBy: \"judge\" } };\n case \"event\":\n return {\n sim: current,\n human: when.event === \"message\",\n event: { type: \"event\", event: when.event, ...(when.name === undefined ? {} : { name: when.name }) },\n };\n case \"timer\": {\n const due = timerDueAt(when, current.run, current.timeZone);\n // Часы прогона идут только вперёд: срок в прошлом — срабатывает сейчас.\n const now = due === null ? current.now : Math.max(current.now - STEP_MS, due);\n return { sim: { ...current, now }, human: false, event: { type: \"timer\", exitId, timeZone: current.timeZone } };\n }\n case \"data\": {\n const found = fieldById(flow, when.field);\n if (!found || !FLOW_OPS_BY_FIELD_TYPE[found.field.type].includes(when.op)) {\n return { sim: current, human: true, event: { type: \"data\", field: when.field, card: cardValues(current) } };\n }\n const filled = writeValue(flow, current, when.field, fittingValue(when, found.field));\n return { sim: filled, human: true, event: { type: \"data\", field: when.field, card: cardValues(filled) } };\n }\n }\n });\n}\n\n/** «Ничего из этого»: человек написал, агент ответил, остались в том же состоянии. */\nexport function chooseNothing(flow: AgentFlow, sim: Simulation): Simulation {\n return step(flow, sim, (current) => ({ sim: current, human: true, event: null }));\n}\n\n/**\n * Автор вписал, что агент знает о человеке. Число — для числовых полей; пусто — поле забыто. Если от этого сработало\n * условие по данным — переход, как в рабочем чате.\n */\nexport function setKnownValue(flow: AgentFlow, sim: Simulation, fieldId: string, text: string): Simulation {\n const found = fieldById(flow, fieldId);\n if (!found) return sim;\n const trimmed = text.trim();\n const value = trimmed === \"\" ? undefined : found.field.type === \"number\" && Number.isFinite(Number(trimmed)) ? Number(trimmed) : trimmed;\n let written = writeValue(flow, sim, fieldId, value);\n if (value === undefined) {\n written =\n found.place === \"notes\"\n ? { ...written, run: { ...written.run, notes: withoutKey(written.run.notes, fieldId) } }\n : { ...written, card: withoutKey(written.card, fieldId) };\n return written;\n }\n const transition = nextTransition(flow, written.run, { type: \"data\", field: fieldId, card: cardValues(written) }, written.now);\n if (!transition) return written;\n return {\n ...written,\n run: noteAgentAnswer(applyTransition(flow, written.run, transition), written.now),\n steps: [...written.steps, { stateId: transition.to, exitId: transition.exitId, nothing: false }],\n previous: sim,\n };\n}\n\nfunction withoutKey<T>(record: Record<string, T>, key: string): Record<string, T> {\n const { [key]: _removed, ...rest } = record;\n return rest;\n}\n\n/** id поля, о котором агент спросит сейчас; `null` — ни о чём. */\nexport function nextQuestionField(flow: AgentFlow, sim: Simulation): string | null {\n return sideQuestion(flow, sim.run, { card: sim.card, now: sim.now })?.fieldId ?? null;\n}\n\nexport function stepBack(sim: Simulation): Simulation {\n return sim.previous ?? sim;\n}\n","import { fieldById } from \"../../engine/flow-graph\";\nimport {\n DEFAULT_SIDE_TASK_MAX_ATTEMPTS,\n type AgentFlow,\n type ClientCardField,\n type FlowCatalog,\n type FlowCatalogField,\n type FlowField,\n type FlowSideTask,\n} from \"../../format/flow-format\";\nimport type { FieldList } from \"./editor-model\";\n\n// Правки попутных задач и полей из словаря приложения (`catalog.fields`): чистые функции, каждая возвращает новый `AgentFlow`.\n\nfunction freeTaskId(flow: AgentFlow): string {\n const used = new Set((flow.sideTasks ?? []).map((task) => task.id));\n let index = 1;\n while (used.has(`task_${index}`)) index += 1;\n return `task_${index}`;\n}\n\nfunction withTasks(flow: AgentFlow, tasks: FlowSideTask[]): AgentFlow {\n if (tasks.length > 0) return { ...flow, sideTasks: tasks };\n const { sideTasks: _empty, ...rest } = flow;\n return rest;\n}\n\nexport function addSideTask(flow: AgentFlow, text: string): { flow: AgentFlow; sideTaskId: string } {\n const sideTaskId = freeTaskId(flow);\n const task: FlowSideTask = { id: sideTaskId, text, maxAttempts: DEFAULT_SIDE_TASK_MAX_ATTEMPTS, perConversation: false };\n return { sideTaskId, flow: withTasks(flow, [...(flow.sideTasks ?? []), task]) };\n}\n\nexport type SideTaskPatch = { [K in keyof FlowSideTask]?: FlowSideTask[K] | undefined };\n\n/** Правка задачи: пустые «когда» и «поле» убираются, попыток — хотя бы одна. */\nexport function updateSideTask(flow: AgentFlow, sideTaskId: string, patch: SideTaskPatch): AgentFlow {\n return withTasks(\n flow,\n (flow.sideTasks ?? []).map((task) => {\n if (task.id !== sideTaskId) return task;\n const next: Record<string, unknown> = { ...task, ...patch };\n for (const key of [\"when\", \"field\"] as const) if (next[key] === undefined || next[key] === \"\") delete next[key];\n if (patch.maxAttempts !== undefined) next.maxAttempts = Math.max(1, Math.round(patch.maxAttempts) || 1);\n return next as unknown as FlowSideTask;\n }),\n );\n}\n\nexport function removeSideTask(flow: AgentFlow, sideTaskId: string): AgentFlow {\n return withTasks(flow, (flow.sideTasks ?? []).filter((task) => task.id !== sideTaskId));\n}\n\n/** Поля словаря приложения, которых ещё нет ни в карточке, ни в заметках. */\nexport function catalogFieldsToAdd(flow: AgentFlow, catalog: FlowCatalog): FlowCatalogField[] {\n return (catalog.fields ?? []).filter((field) => !fieldById(flow, field.id));\n}\n\n/** Поле словаря приложения в карточку или заметки: id, название, тип и варианты — как у приложения. Уже есть — без правок. */\nexport function addCatalogField(flow: AgentFlow, list: FieldList, field: FlowCatalogField): AgentFlow {\n if (fieldById(flow, field.id)) return flow;\n const base: FlowField = { id: field.id, name: field.title, about: \"\", type: field.type, options: field.type === \"choice\" ? [...(field.options ?? [])] : [] };\n if (list === \"clientCard\") {\n const card: ClientCardField = { ...base, refreshAfterMonths: null };\n return { ...flow, clientCard: [...flow.clientCard, card] };\n }\n return { ...flow, chatNotes: [...flow.chatNotes, base] };\n}\n\n/** Поле, по которому задача решена. Поле из словаря приложения, которого нет в сценарии, попадает в карточку. */\nexport function setSideTaskField(flow: AgentFlow, sideTaskId: string, fieldId: string | null, catalog: FlowCatalog): AgentFlow {\n const fromApp = fieldId === null ? undefined : catalog.fields?.find((field) => field.id === fieldId);\n const withField = fromApp ? addCatalogField(flow, \"clientCard\", fromApp) : flow;\n return updateSideTask(withField, sideTaskId, { field: fieldId ?? undefined });\n}\n","import { useCallback, useMemo, useRef, useState } from \"react\";\nimport { checkFlow } from \"../../check/check-flow\";\nimport type { AgentFlow, FlowCatalog, FlowIssue, FlowPoint } from \"../../format/flow-format\";\nimport type { StateMap } from \"../../engine/migrate-run\";\nimport type { ChatsInState } from \"../../store/flow-store\";\nimport type { FlowEditorMode, FlowIssueCount } from \"../flow-editor-skin\";\nimport { useFlowLabels } from \"../flow-labels\";\nimport { appIssues, type FlowAppChecks, type FlowAppIssue } from \"../../check/app-checks\";\nimport {\n addExit,\n addState as addStateTo,\n connectExit,\n flowFingerprint,\n flowToJson,\n loadFlowJson,\n removeState as removeStateFrom,\n type ExitOwner,\n} from \"./editor-model\";\nimport {\n chooseExit,\n chooseNothing,\n setKnownValue,\n startSimulation,\n stepBack,\n type Simulation,\n} from \"./flow-simulation\";\n\n/** Что открыто в панели справа. */\nexport type FlowSelection =\n | { kind: \"overview\"; sideTaskId?: string }\n | { kind: \"state\"; stateId: string; exitId?: string }\n | { kind: \"any\"; exitId?: string }\n | { kind: \"card\" };\n\nexport type FlowDialog = \"json\" | \"migrate\" | null;\n\n/**\n * Перевод идущих чатов на текущую версию. Данные и действие даёт приложение — редактор не знает, где сервер:\n * `chatsByState` — чаты на прежних версиях (`flow.chatsByState`), `migrate` — перевод с картой удалённых состояний\n * (`flow.migrateChats`). Отбор чатов в обоих вызовах один и тот же: окно показывает ровно тех, кого переведёт.\n */\nexport interface FlowMigration {\n chatsByState(): Promise<ChatsInState[]>;\n migrate(map: StateMap): Promise<{ moved: number }>;\n /** Название состояния прежней версии; нет — берём из текущей или показываем id. */\n stateTitle?(versionId: string, stateId: string): string | undefined;\n}\n\n/**\n * Ответ `onSave`. Ничего (`void`) и `{ ok: true }` — сохранено. `{ ok: false, issues }` — приложение отказало без\n * исключения: шапка не пишет «Сохранено», `issues` встают у нод и выходов, как находки «Проверить граф».\n */\nexport type FlowSaveResult = void | { ok: true } | { ok: false; issues?: ReadonlyArray<Pick<FlowAppIssue, \"path\" | \"message\">> };\n\nexport interface UseFlowEditorOptions {\n value: AgentFlow;\n onChange(flow: AgentFlow): void;\n /** Сохранить сценарий. Отказ — `{ ok: false, issues }` или исключение (оно не уходит в консоль необработанным). */\n onSave?(flow: AgentFlow): FlowSaveResult | Promise<FlowSaveResult>;\n /**\n * Только просмотр: доску нельзя менять (двигать, соединять, удалять, править панели), нельзя сохранять и загружать\n * JSON. Смотреть, проверять граф, прогонять и открывать JSON можно. Нужно, пока сценарий правит внешний агент.\n */\n readOnly?: boolean;\n /**\n * Сценарий, который сейчас сохранён у приложения (на сервере). Если задан, «Сохранено» и доступность кнопки сохранения\n * считаются от него, а не от `value` при показе доски: вернулись на вкладку с несохранённой правкой — доска честно\n * скажет «Не сохранено». После успешного `onSave` доска считает сохранённым отправленное, пока не придёт новый\n * `savedValue`. Без него сохранённым считается `value` при показе доски.\n */\n savedValue?: AgentFlow;\n /** Что объявило приложение: инструменты, события и кнопки, виджеты. */\n catalog: FlowCatalog;\n migration?: FlowMigration;\n /** Пояс человека для таймеров «время суток» в прогоне; по умолчанию — пояс браузера. */\n timeZone?: string;\n now?(): number;\n /**\n * Свои проверки приложения в «Проверить сценарий»: `(flow) => [{ path: \"states[2]\", message }]`. Находки идут после\n * встроенных, клик ведёт на место. Те же проверки приложение передаёт в `checkFlow(flow, catalog, { checks })`.\n */\n checks?: FlowAppChecks;\n}\n\nexport interface FlowMigrateRow extends ChatsInState {\n stateTitle: string;\n removed: boolean;\n target: string | null;\n}\n\nexport interface FlowMigrateController {\n rows: FlowMigrateRow[];\n busy: boolean;\n failed: boolean;\n moved: number | null;\n canMigrate: boolean;\n open(): void;\n setTarget(stateId: string, target: string): void;\n run(): Promise<void>;\n}\n\nfunction countIssues(issues: FlowIssue[]): FlowIssueCount {\n return {\n errors: issues.filter((issue) => issue.level === \"error\").length,\n warnings: issues.filter((issue) => issue.level === \"warning\").length,\n };\n}\n\n/** Проверки приложения; упали — редактор работает дальше, а находка говорит об этом. */\nfunction runAppChecks(flow: AgentFlow, checks: FlowAppChecks | undefined, failed: string): FlowIssue[] {\n if (!checks) return [];\n try {\n return appIssues(flow, checks(flow));\n } catch (error) {\n console.error(\"[flow] app checks failed\", error);\n return [{ level: \"warning\", code: \"app_check_failed\", message: failed, place: {} }];\n }\n}\n\nconst NO_ISSUES: FlowIssue[] = [];\n\nconst browserTimeZone = () => Intl.DateTimeFormat().resolvedOptions().timeZone || \"UTC\";\n\n/** Логика редактора сценария: правки, выбор, проверка, прогон, JSON, сохранение, перевод чатов. Скин только рисует. */\nexport function useFlowEditor(options: UseFlowEditorOptions) {\n const { value: flow, onChange, catalog } = options;\n const labels = useFlowLabels().editor;\n const latest = useRef(options);\n latest.current = options;\n\n const [selection, setSelection] = useState<FlowSelection>({ kind: \"overview\" });\n const [mode, setModeState] = useState<FlowEditorMode>(\"edit\");\n const [dialog, setDialog] = useState<FlowDialog>(null);\n const [jsonErrors, setJsonErrors] = useState<string[]>([]);\n const [simulation, setSimulation] = useState<Simulation | null>(null);\n const [saving, setSaving] = useState(false);\n const [mountedPrint] = useState(() => flowFingerprint(flow));\n const savedPrint = useMemo(() => (options.savedValue ? flowFingerprint(options.savedValue) : undefined), [options.savedValue]);\n // Отправленное через `onSave` считается сохранённым, пока приложение не прислало другой `savedValue`.\n const [sent, setSent] = useState<{ print: string; base: string | undefined } | null>(null);\n const savedJson = sent && sent.base === savedPrint ? sent.print : (savedPrint ?? mountedPrint);\n // Отказ в сохранении держится, пока сценарий тот же: любая правка снимает его.\n const [rejection, setRejection] = useState<{ flow: AgentFlow; issues: FlowIssue[] } | null>(null);\n const readOnly = options.readOnly === true;\n\n const checks = options.checks;\n const saveFailed = rejection !== null && rejection.flow === flow;\n const rejectedIssues = saveFailed ? rejection.issues : NO_ISSUES;\n const issues = useMemo(\n () => [...checkFlow(flow, catalog), ...runAppChecks(flow, checks, labels.checkPanel.appCheckFailed), ...rejectedIssues],\n [flow, catalog, checks, labels, rejectedIssues],\n );\n const issueCount = useMemo(() => countIssues(issues), [issues]);\n const json = useMemo(() => flowToJson(flow), [flow]);\n const print = useMemo(() => flowFingerprint(flow), [flow]);\n const dirty = print !== savedJson;\n\n // Выбранное состояние удалили — панель возвращается к обзору.\n const visibleSelection: FlowSelection =\n selection.kind === \"state\" && !flow.states.some((state) => state.id === selection.stateId) ? { kind: \"overview\" } : selection;\n\n const edit = useCallback((change: (flow: AgentFlow) => AgentFlow) => {\n if (latest.current.readOnly) return;\n onChange(change(latest.current.value));\n }, [onChange]);\n\n const select = useCallback((next: FlowSelection) => {\n setSelection(next);\n setModeState((current) => (current === \"check\" ? \"edit\" : current));\n }, []);\n\n const addState = useCallback(\n (at?: FlowPoint): string => {\n if (latest.current.readOnly) return \"\";\n const made = addStateTo(latest.current.value, { title: labels.board.newState, ...(at ? { at } : {}) });\n onChange(made.flow);\n setSelection({ kind: \"state\", stateId: made.stateId });\n return made.stateId;\n },\n [labels, onChange],\n );\n\n const connect = useCallback(\n (owner: ExitOwner, exitId: string, to: string) => {\n if (!latest.current.readOnly) onChange(connectExit(latest.current.value, owner, exitId, to));\n },\n [onChange],\n );\n\n /** Стрелку отпустили на пустом месте: новое состояние там же. Из узла без условия — новое условие словами. */\n const connectToNewState = useCallback(\n (owner: ExitOwner, exitId: string | null, at: FlowPoint) => {\n if (latest.current.readOnly) return;\n const made = addStateTo(latest.current.value, { title: labels.board.newState, at });\n let next = made.flow;\n let fromExit = exitId;\n if (fromExit === null) {\n const added = addExit(next, owner, \"judge\");\n next = added.flow;\n fromExit = added.exitId;\n }\n onChange(connectExit(next, owner, fromExit, made.stateId));\n setSelection({ kind: \"state\", stateId: made.stateId });\n },\n [labels, onChange],\n );\n\n const removeState = useCallback(\n (stateId: string) => {\n if (!latest.current.readOnly) onChange(removeStateFrom(latest.current.value, stateId));\n },\n [onChange],\n );\n\n const restartSimulation = useCallback(() => {\n const current = latest.current;\n setSimulation(startSimulation(current.value, { now: current.now?.() ?? Date.now(), timeZone: current.timeZone ?? browserTimeZone() }));\n }, []);\n\n const setMode = useCallback(\n (next: FlowEditorMode) => {\n if (next === \"run\") {\n const current = latest.current.value;\n if (!current.states.some((state) => state.id === current.start)) {\n setModeState(\"check\");\n return;\n }\n restartSimulation();\n } else {\n setSimulation(null);\n }\n setModeState(next);\n },\n [restartSimulation],\n );\n\n const goToIssue = useCallback((issue: FlowIssue) => {\n const { stateId, exitId, fieldId, sideTaskId } = issue.place;\n if (stateId && flow.states.some((state) => state.id === stateId)) setSelection({ kind: \"state\", stateId, ...(exitId ? { exitId } : {}) });\n else if (exitId && flow.anyState.exits.some((exit) => exit.id === exitId)) setSelection({ kind: \"any\", exitId });\n else if (sideTaskId) setSelection({ kind: \"overview\", sideTaskId });\n else if (fieldId) setSelection({ kind: \"card\" });\n else setSelection({ kind: \"overview\" });\n setModeState(\"edit\");\n }, [flow]);\n\n const simulate = useMemo(() => {\n const change = (step: (sim: Simulation) => Simulation) => setSimulation((sim) => (sim ? step(sim) : sim));\n return {\n choose: (exitId: string) => change((sim) => chooseExit(latest.current.value, sim, exitId)),\n nothing: () => change((sim) => chooseNothing(latest.current.value, sim)),\n back: () => change(stepBack),\n restart: restartSimulation,\n setKnown: (fieldId: string, text: string) => change((sim) => setKnownValue(latest.current.value, sim, fieldId, text)),\n };\n }, [restartSimulation]);\n\n const openJson = useCallback(() => {\n setJsonErrors([]);\n setDialog(\"json\");\n }, []);\n\n const closeDialog = useCallback(() => setDialog(null), []);\n\n const loadJson = useCallback(\n (text: string): boolean => {\n if (latest.current.readOnly) return false;\n const loaded = loadFlowJson(text);\n if (!loaded.ok) {\n setJsonErrors(loaded.errors);\n return false;\n }\n setJsonErrors([]);\n setSelection({ kind: \"overview\" });\n setSimulation(null);\n setModeState(\"edit\");\n setDialog(null);\n onChange(loaded.flow);\n return true;\n },\n [onChange],\n );\n\n const save = useCallback(async () => {\n const { onSave, value, readOnly: viewOnly } = latest.current;\n if (!onSave || viewOnly) return;\n setSaving(true);\n try {\n const result = await onSave(value);\n if (result && !result.ok) {\n setRejection({ flow: value, issues: appIssues(value, (result.issues ?? []).map((issue) => ({ ...issue, code: \"save_rejected\" }))) });\n return;\n }\n setRejection(null);\n setSent({ print: flowFingerprint(value), base: latest.current.savedValue ? flowFingerprint(latest.current.savedValue) : undefined });\n } catch (error) {\n // Исключение из `onSave` — тот же отказ, только без списка: шапка говорит «Не сохранено», консоль не засоряем.\n console.warn(\"[flow] onSave failed\", error);\n setRejection({ flow: value, issues: [] });\n } finally {\n setSaving(false);\n }\n }, []);\n\n const migrate = useMigrateController(flow, options.migration, () => setDialog(\"migrate\"));\n\n return {\n flow,\n catalog,\n issues,\n issueCount,\n selection: visibleSelection,\n select,\n mode,\n setMode,\n goToIssue,\n edit,\n addState,\n connect,\n connectToNewState,\n removeState,\n simulation,\n simulate,\n dialog,\n openJson,\n closeDialog,\n json,\n jsonErrors,\n loadJson,\n save,\n saving,\n saveFailed,\n dirty,\n readOnly,\n migrate,\n };\n}\n\nexport type FlowEditorController = ReturnType<typeof useFlowEditor>;\n\n/** Окно перевода чатов: строки «версия → состояние → чатов», цели для удалённых состояний, перевод. */\nfunction useMigrateController(flow: AgentFlow, migration: FlowMigration | undefined, show: () => void): FlowMigrateController | null {\n const [chats, setChats] = useState<ChatsInState[]>([]);\n const [targets, setTargets] = useState<Record<string, string>>({});\n const [busy, setBusy] = useState(false);\n const [failed, setFailed] = useState(false);\n const [moved, setMoved] = useState<number | null>(null);\n\n const rows = useMemo<FlowMigrateRow[]>(\n () =>\n chats.map((entry) => {\n const current = flow.states.find((state) => state.id === entry.stateId);\n return {\n ...entry,\n stateTitle: migration?.stateTitle?.(entry.versionId, entry.stateId) ?? current?.title ?? entry.stateId,\n removed: !current,\n target: current ? null : (targets[entry.stateId] ?? null),\n };\n }),\n [chats, flow, migration, targets],\n );\n\n const canMigrate = !busy && rows.length > 0 && rows.every((row) => !row.removed || row.chats === 0 || row.target !== null);\n\n const open = useCallback(() => {\n if (!migration) return;\n show();\n setMoved(null);\n setFailed(false);\n setBusy(true);\n migration\n .chatsByState()\n .then(setChats, () => setFailed(true))\n .finally(() => setBusy(false));\n }, [migration, show]);\n\n const setTarget = useCallback((stateId: string, target: string) => setTargets((current) => ({ ...current, [stateId]: target })), []);\n\n const run = useCallback(async () => {\n if (!migration) return;\n const map: StateMap = Object.fromEntries(rows.filter((row) => row.removed && row.target).map((row) => [row.stateId, row.target!]));\n setBusy(true);\n setFailed(false);\n try {\n const result = await migration.migrate(map);\n setMoved(result.moved);\n // Счётчик — заново с сервера: чаты, которые перевод пропустил (их держала другая копия), остаются в окне.\n setChats(await migration.chatsByState().catch(() => []));\n } catch {\n setFailed(true);\n } finally {\n setBusy(false);\n }\n }, [migration, rows]);\n\n if (!migration) return null;\n return { rows, busy, failed, moved, canMigrate, open, setTarget, run };\n}\n","import { useCallback, useEffect, useRef, useState } from \"react\";\nimport { isFieldStale } from \"../../engine/side-questions\";\nimport type { ClientCardField } from \"../../format/flow-format\";\nimport { fieldValueText } from \"../../prompt/client-card-block\";\nimport { FACT_PREFIX } from \"../../runtime/client-facts\";\nimport type { ClientCardEntry } from \"../../store/flow-store\";\nimport { useFlowLabels } from \"../flow-labels\";\nimport type { ClientCardFieldView, ClientCardLoadState, ClientCardPanelProps } from \"../client-card-skin\";\n\nexport interface UseClientCardOptions {\n /** Поля карточки сценариев приложения: порядок = что важнее, имена видит человек. Чужих полей здесь может не быть — их покажет `id`. */\n fields: Array<Pick<ClientCardField, \"id\" | \"name\" | \"refreshAfterMonths\">>;\n /** Карточка человека с сервера: `flow.readClientCard(ownerId)` за HTTP-ручкой приложения. */\n read(): Promise<ClientCardEntry[]>;\n /** Стереть поле или `\"all\"`: `flow.forgetClientCard(ownerId, fieldId)`. */\n forget(fieldId: string | \"all\"): Promise<void>;\n /** Как назвать свободный факт о человеке («ведёт блог») в списке; по умолчанию — `useFlowLabels().clientCard.fact`. */\n factName?: string;\n /** Часы; для тестов. */\n now?: () => number;\n /** Пояс для даты записи; нет — пояс браузера. */\n timeZone?: string;\n}\n\n/** Слой поведения экрана карточки: грузит, готовит строки для скина, стирает поле или всё. Скин только рисует. */\nexport function useClientCard(options: UseClientCardOptions): ClientCardPanelProps {\n const latest = useRef(options);\n latest.current = options;\n const [state, setState] = useState<ClientCardLoadState>(\"loading\");\n const [entries, setEntries] = useState<ClientCardEntry[]>([]);\n const [busy, setBusy] = useState<ReadonlySet<string>>(new Set());\n const [forgettingAll, setForgettingAll] = useState(false);\n const alive = useRef(true);\n\n const load = useCallback(async () => {\n setState(\"loading\");\n try {\n const loaded = await latest.current.read();\n if (!alive.current) return;\n setEntries(loaded);\n setState(\"ready\");\n } catch {\n if (alive.current) setState(\"failed\");\n }\n }, []);\n\n useEffect(() => {\n alive.current = true;\n void load();\n return () => {\n alive.current = false;\n };\n }, [load]);\n\n const forgetField = async (fieldId: string) => {\n setBusy((current) => new Set(current).add(fieldId));\n try {\n await latest.current.forget(fieldId);\n if (alive.current) setEntries((current) => current.filter((entry) => entry.fieldId !== fieldId));\n } catch {\n if (alive.current) setState(\"failed\");\n } finally {\n if (alive.current)\n setBusy((current) => {\n const next = new Set(current);\n next.delete(fieldId);\n return next;\n });\n }\n };\n\n const forgetAll = async () => {\n setForgettingAll(true);\n try {\n await latest.current.forget(\"all\");\n if (alive.current) setEntries([]);\n } catch {\n if (alive.current) setState(\"failed\");\n } finally {\n if (alive.current) setForgettingAll(false);\n }\n };\n\n const labels = useFlowLabels().clientCard;\n const { fields, now = Date.now, timeZone, factName = labels.fact } = options;\n const dateFormat = new Intl.DateTimeFormat(\"ru-RU\", { day: \"2-digit\", month: \"2-digit\", year: \"numeric\", ...(timeZone && { timeZone }) });\n const position = (fieldId: string) => {\n const index = fields.findIndex((field) => field.id === fieldId);\n return index === -1 ? Number.MAX_SAFE_INTEGER : index;\n };\n const views: ClientCardFieldView[] = [...entries]\n .sort((left, right) => position(left.fieldId) - position(right.fieldId) || left.fieldId.localeCompare(right.fieldId))\n .map((entry) => {\n const field = fields.find((item) => item.id === entry.fieldId);\n const updatedAt = Date.parse(entry.updatedAt);\n return {\n fieldId: entry.fieldId,\n name: field?.name ?? (entry.fieldId.startsWith(FACT_PREFIX) ? factName : entry.fieldId),\n value: fieldValueText(entry.value),\n updatedAt: dateFormat.format(updatedAt),\n stale: field ? isFieldStale(field, updatedAt, now()) : false,\n busy: busy.has(entry.fieldId),\n onForget: () => void forgetField(entry.fieldId),\n };\n });\n\n return { state, fields: views, forgettingAll, onForgetAll: () => void forgetAll(), onRetry: () => void load() };\n}\n","import type { ClientCardSkin } from \"../client-card-skin\";\nimport { useClientCard, type UseClientCardOptions } from \"./use-client-card\";\n\nexport interface ClientCardScreenProps extends UseClientCardOptions {\n /** Части экрана: `tandemClientCardSkin` из `@ykurilov/agent-chat-skin-tandem/client-card` или свои по договору. */\n skin: ClientCardSkin;\n}\n\n/** Экран «Что агент знает о вас»: рядом с экраном памяти, если приложение его подключило. Надписи — `useFlowLabels().clientCard`. */\nexport function ClientCardPanel({ skin, ...options }: ClientCardScreenProps) {\n return <skin.ClientCardPanel {...useClientCard(options)} />;\n}\n","import { createContext, useContext, useMemo, type ReactNode } from \"react\";\nimport type { FlowDayInfo } from \"../../engine/flow-days\";\nimport { stateById } from \"../../engine/flow-graph\";\nimport { parseDuration } from \"../../format/parse-duration\";\nimport { russianFlowTestChatLabels, type FlowTestChatLabels } from \"../../labels/test-chat\";\nimport { FlowEditor, type FlowEditorProps } from \"../editor/flow-editor\";\nimport { useFlowLabels } from \"../flow-labels\";\nimport type { FlowEditorFrameProps, FlowEditorSkin, FlowHeaderProps, FlowStateNodeProps } from \"../flow-editor-skin\";\nimport { useFlowTestChat, type FlowTestChatConnection, type FlowTestChatController } from \"./use-flow-test-chat\";\n\nconst MINUTE = 60_000;\nconst HOUR = 60 * MINUTE;\nconst DAY = 24 * HOUR;\n\n/** Варианты перемотки по умолчанию: 20 минут, 3 часа, сутки. */\nexport const DEFAULT_ADVANCE_STEPS: readonly number[] = [20 * MINUTE, 3 * HOUR, DAY];\n\n/** Длительность словами: «1 д 3 ч 20 мин». */\nexport function formatDuration(ms: number, units: FlowTestChatLabels[\"units\"]): string {\n const minutes = Math.round(ms / MINUTE);\n const parts: Array<[number, string]> = [\n [Math.floor(minutes / (24 * 60)), units.day],\n [Math.floor(minutes / 60) % 24, units.hour],\n [minutes % 60, units.minute],\n ];\n return parts\n .filter(([amount]) => amount > 0)\n .map(([amount, unit]) => `${amount} ${unit}`)\n .join(\" \");\n}\n\n/** Сдвиг часов тестового чата готовой строкой: «как сейчас», «+3 ч 20 мин». */\nexport function formatClockOffset(ms: number, labels: FlowTestChatLabels = russianFlowTestChatLabels): string {\n const { noOffset, units } = labels;\n const text = formatDuration(ms, units);\n return text ? `+${text}` : noOffset;\n}\n\n/** Строка дня тестового чата: «День 2 из 3 · 14:20» по часам чата в поясе человека; дней нет — `null`. */\nexport function formatDayLine(day: FlowDayInfo | null | undefined, at: number, timeZone: string, labels: FlowTestChatLabels = russianFlowTestChatLabels): string | null {\n if (!day) return null;\n const time = new Intl.DateTimeFormat(\"ru-RU\", { timeZone, hour: \"2-digit\", minute: \"2-digit\", hourCycle: \"h23\" }).format(at);\n return `${day.day === 0 ? labels.beforeFirstDay : labels.day(day.day, day.totalDays)} · ${time}`;\n}\n\nconst browserTimeZone = () => Intl.DateTimeFormat().resolvedOptions().timeZone || \"UTC\";\n\nexport interface FlowTestChatProps extends FlowEditorProps {\n testChat: FlowTestChatConnection;\n /** Варианты перемотки, мс. По умолчанию `DEFAULT_ADVANCE_STEPS`. */\n advanceSteps?: readonly number[];\n}\n\ninterface TestChatView {\n controller: FlowTestChatController;\n /** Рамка тестового чата вместо панели редактора; `null` — тестовый чат закрыт. */\n panel: ReactNode | null;\n}\n\nconst TestChatContext = createContext<TestChatView | null>(null);\n\nfunction useTestChatView(): TestChatView {\n const view = useContext(TestChatContext);\n if (!view) throw new Error(\"Test chat parts render only inside FlowTestChat.\");\n return view;\n}\n\n/**\n * Скин редактора с тестовым чатом поверх скина приложения: в шапке кнопка теста, справа вместо панели — чат, на доске\n * подсвечено место чата. Обёртки постоянные на скин: доска не пересоздаёт узлы.\n */\nfunction withTestChat(skin: FlowEditorSkin): FlowEditorSkin {\n function Header(props: FlowHeaderProps) {\n const { controller } = useTestChatView();\n return <skin.FlowHeader {...props} onOpenTestChat={controller.open} />;\n }\n function Frame(props: FlowEditorFrameProps) {\n const { panel } = useTestChatView();\n return <skin.FlowEditorFrame {...props} panel={panel ?? props.panel} />;\n }\n function StateNode(props: FlowStateNodeProps) {\n const { controller } = useTestChatView();\n if (!controller.opened || controller.stateId === null) return <skin.FlowStateNode {...props} />;\n const run = controller.stateId === props.stateId ? \"current\" : controller.visited.has(props.stateId) ? \"visited\" : null;\n return <skin.FlowStateNode {...props} run={run} dimmed={false} />;\n }\n return { ...skin, FlowHeader: Header, FlowEditorFrame: Frame, FlowStateNode: StateNode };\n}\n\n/**\n * Редактор сценария с тестовым чатом: автор пишет агенту рядом с доской, видит текущее состояние и перематывает часы\n * чата, чтобы проверить таймеры без ожидания. Сервер и экран чата даёт приложение (`testChat`).\n */\nexport function FlowTestChat({ testChat, advanceSteps = DEFAULT_ADVANCE_STEPS, skin, ...editor }: FlowTestChatProps) {\n const labels = useFlowLabels().testChat;\n const controller = useFlowTestChat(testChat, editor.value);\n const testSkin = useMemo(() => withTestChat(skin), [skin]);\n\n const state = controller.stateId === null ? undefined : stateById(editor.value, controller.stateId);\n const panel = controller.opened ? (\n <skin.FlowTestChatFrame\n stateTitle={state?.title || controller.stateId || \"\"}\n clock={formatClockOffset(controller.timeOffset, labels)}\n advanceSteps={advanceSteps.map((ms) => ({ label: formatDuration(ms, labels.units), ms }))}\n onAdvance={controller.advance}\n day={formatDayLine(controller.day, (editor.now?.() ?? Date.now()) + controller.timeOffset, editor.timeZone ?? browserTimeZone(), labels)}\n {...(controller.nextDay && editor.value.schedule ? { onNextDay: controller.nextDay } : {})}\n {...(controller.nextFirstMessage && { onNextFirstMessage: controller.nextFirstMessage, nothingScheduled: controller.nothingScheduled })}\n onAdvanceText={(text) => {\n const ms = parseDuration(text);\n if (ms !== undefined) controller.advance(ms);\n return ms !== undefined;\n }}\n busy={controller.busy}\n failed={controller.failed}\n onReset={controller.reset}\n onClose={controller.close}\n >\n {controller.chatId === null ? null : testChat.renderChat(controller.chatId)}\n </skin.FlowTestChatFrame>\n ) : null;\n\n return (\n <TestChatContext.Provider value={{ controller, panel }}>\n <FlowEditor skin={testSkin} {...editor} />\n </TestChatContext.Provider>\n );\n}\n","import { useCallback, useEffect, useRef, useState, type ReactNode } from \"react\";\nimport type { FlowDayInfo } from \"../../engine/flow-days\";\nimport type { FlowRun } from \"../../engine/flow-run\";\nimport type { AgentFlow } from \"../../format/flow-format\";\n\n/** Как часто тестовый чат перечитывает место, пока открыт, мс. */\nconst RUN_POLL_MS = 1000;\n\n/** Что тестовому чату нужно от приложения: сервер и экран чата. Редактор не знает, где сервер. */\nexport interface FlowTestChatConnection {\n /** Новый тестовый чат по сценарию из редактора: сервер создаёт его с `flowTestChatData()`. */\n start(flow: AgentFlow): Promise<{ chatId: string }>;\n /** Промотать часы чата: на сервере `flow.advanceTestClock`. */\n advance(chatId: string, ms: number): Promise<{ timeOffset: number }>;\n /**\n * Промотать часы к началу следующего дня сценария: на сервере `flow.advanceTestClock({ chatId, to: \"next_day_start\" })`.\n * Нет — кнопки «К началу следующего дня» нет.\n */\n advanceToNextDay?(chatId: string): Promise<{ timeOffset: number }>;\n /**\n * Промотать часы ровно к моменту, когда сценарий сам напишет первым: на сервере\n * `flow.advanceTestClock({ chatId, to: \"next_first_message\" })`. Впереди ничего — ошибка с `code: \"nothing_scheduled\"`\n * (у `FlowTestClockError`; через сеть передайте код). Нет — кнопки «К следующему напоминанию» нет.\n */\n advanceToNextFirstMessage?(chatId: string): Promise<{ timeOffset: number }>;\n /** Место чата: на сервере `flow.readRun`. В браузер посетителя место не уходит, доска читает его отдельно. */\n readRun(chatId: string): Promise<(Pick<FlowRun, \"state\" | \"path\"> & { day?: FlowDayInfo }) | null>;\n /** Экран чата приложения: `<AgentChat api=… chatId={chatId} skin=… />`. */\n renderChat(chatId: string): ReactNode;\n}\n\nexport interface FlowTestChatController {\n opened: boolean;\n chatId: string | null;\n /** Сдвиг часов чата, мс. */\n timeOffset: number;\n busy: boolean;\n failed: boolean;\n /** Где чат на доске; пока ходов нет — старт сценария. */\n stateId: string | null;\n /** Пройденные состояния, без текущего. */\n visited: ReadonlySet<string>;\n /** День сценария чата; `null` — у сценария нет «Дней и времени» или ходов ещё не было. */\n day: FlowDayInfo | null;\n open(): void;\n close(): void;\n reset(): void;\n advance(ms: number): void;\n /** К началу следующего дня сценария; `null` — приложение не дало `advanceToNextDay`. */\n nextDay: (() => void) | null;\n /** К следующему сообщению сценария; `null` — приложение не дало `advanceToNextFirstMessage`. */\n nextFirstMessage: (() => void) | null;\n /** Последняя перемотка к напоминанию: впереди сценарий сам ничего не напишет. */\n nothingScheduled: boolean;\n}\n\ntype BoardRun = { state: string; visited: ReadonlySet<string>; day: FlowDayInfo | null };\n\n/** Место чата с сервера: только то, что нужно доске. */\nfunction runOf(run: Awaited<ReturnType<FlowTestChatConnection[\"readRun\"]>>): BoardRun | null {\n if (!run || typeof run.state !== \"string\") return null;\n const visited = new Set((run.path ?? []).flatMap((step) => (typeof step.state === \"string\" && step.state !== run.state ? [step.state] : [])));\n return { state: run.state, visited, day: run.day ?? null };\n}\n\nconst sameDay = (left: FlowDayInfo | null, right: FlowDayInfo | null) =>\n left === right || (left !== null && right !== null && left.day === right.day && left.totalDays === right.totalDays && left.dayStartedAt === right.dayStartedAt);\n\nconst sameRun = (left: BoardRun | null, right: BoardRun | null) =>\n left === right || (left !== null && right !== null && left.state === right.state && sameDay(left.day, right.day) && left.visited.size === right.visited.size && [...left.visited].every((id) => right.visited.has(id)));\n\nconst NOTHING_VISITED: ReadonlySet<string> = new Set();\n\n/** Логика тестового чата редактора: открыть, перемотать, начать заново, подсветка состояния. */\nexport function useFlowTestChat(connection: FlowTestChatConnection, flow: AgentFlow): FlowTestChatController {\n const [opened, setOpened] = useState(false);\n const [chatId, setChatId] = useState<string | null>(null);\n const [timeOffset, setTimeOffset] = useState(0);\n const [busy, setBusy] = useState(false);\n const [failed, setFailed] = useState(false);\n const [nothingScheduled, setNothingScheduled] = useState(false);\n const [run, setRun] = useState<BoardRun | null>(null);\n const latest = useRef({ connection, flow, chatId });\n latest.current = { connection, flow, chatId };\n\n const refresh = useCallback(async (id: string) => {\n try {\n const next = runOf(await latest.current.connection.readRun(id));\n if (latest.current.chatId === id) setRun((current) => (sameRun(current, next) ? current : next));\n } catch (error) {\n console.error(\"[flow] test chat: run not read\", error);\n }\n }, []);\n\n // Пока панель открыта, место перечитывается: ходы чата и таймеры двигают его на сервере.\n useEffect(() => {\n if (!opened || chatId === null) return;\n void refresh(chatId);\n const timer = setInterval(() => void refresh(chatId), RUN_POLL_MS);\n return () => clearInterval(timer);\n }, [opened, chatId, refresh]);\n\n const work = useCallback(async (job: () => Promise<void>) => {\n setBusy(true);\n setFailed(false);\n setNothingScheduled(false);\n try {\n await job();\n } catch (error) {\n if ((error as { code?: unknown } | null)?.code === \"nothing_scheduled\") {\n setNothingScheduled(true);\n return;\n }\n console.error(\"[flow] test chat:\", error);\n setFailed(true);\n } finally {\n setBusy(false);\n }\n }, []);\n\n const start = useCallback(\n () =>\n work(async () => {\n const { chatId: next } = await latest.current.connection.start(latest.current.flow);\n setRun(null);\n setChatId(next);\n setTimeOffset(0);\n }),\n [work],\n );\n\n /** Перемотка часов чата: сервер сдвигает часы и ждёт ход, который она вызвала; место перечитывается сразу. */\n const shift = (move: (chatId: string) => Promise<{ timeOffset: number }>) => {\n const current = latest.current.chatId;\n if (current === null) return;\n void work(async () => {\n const { timeOffset: next } = await move(current);\n setTimeOffset(next);\n await refresh(current);\n });\n };\n\n return {\n opened,\n chatId,\n timeOffset,\n busy,\n failed,\n nothingScheduled,\n stateId: chatId === null ? null : (run?.state ?? flow.start),\n visited: run?.visited ?? NOTHING_VISITED,\n day: chatId === null ? null : (run?.day ?? null),\n open() {\n setOpened(true);\n if (latest.current.chatId === null) void start();\n },\n close: () => setOpened(false),\n reset: () => void start(),\n advance: (ms) => shift((id) => latest.current.connection.advance(id, ms)),\n nextDay: connection.advanceToNextDay ? () => shift((id) => latest.current.connection.advanceToNextDay!(id)) : null,\n nextFirstMessage: connection.advanceToNextFirstMessage ? () => shift((id) => latest.current.connection.advanceToNextFirstMessage!(id)) : null,\n };\n}\n"],"mappings":"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","names":["step","useMemo","useState","state","exit","createContext","useCallback","useContext","useEffect","useMemo","useState","step","createContext","useContext","step","useMemo","useState","useEffect","useCallback","useCallback","useMemo","useRef","useState","useRef","useState","useMemo","useCallback","addState","removeState","step","Fragment","jsx","jsxs","useState","useMemo","step","useCallback","useEffect","useRef","useState","useRef","useState","useCallback","useEffect","jsx","createContext","useContext","useMemo","useCallback","useEffect","useRef","useState","step","shift","jsx","browserTimeZone","createContext","useContext","useMemo"]}
|