Режим !active
Перенесено из репозитория формата — docs/spec/SPECIFICATION_RU.md, SYNX 3.7.4. Правки вносятся там.
3.1 Что это такое
По умолчанию .synx файл — это статичные данные. Просто ключи и значения, как JSON.
Но если в первой строке файла написать !active, файл превращается в живой конфиг — включаются:
- Функции (
:random,:calc,:envи др.) - Ограничения (
[min:3],[type:int]и др.)
!active
порт:env PORT
приветствие:random
- Привет!
- Здорово!Без !active — маркеры :random, :calc и квадратные скобки [] полностью игнорируются. Парсер читает файл как обычный текст:
// Нет !active — функции НЕ работают
порт:env PORT // ключ = "порт:env", значение = "PORT" (просто строка)
приветствие:random // ключ = "приветствие:random", значение = {} (объект)💡 Это сделано для безопасности: статичный файл никогда не выполнит код, не полезет в переменные окружения и не запустит команды.
3.2 Полный список функций (:)
Функции записываются через двоеточие сразу после имени ключа: ключ:функция значение.
:random — случайный выбор
Выбирает один элемент из списка при каждом парсинге.
Равные шансы (без процентов):
!active
боевой_клич:random
- Время побеждать!
- Ва-ха-ха!
- За Синдикат!Каждый элемент имеет шанс 33.3%.
Взвешенный рандом (с процентами):
!active
// Проценты указываются после :random через пробел
// Порядок процентов соответствует порядку элементов
награда:random 70 20 10
- Обычный сундук
- Редкий сундук
- Легендарный сундукЗдесь:
- «Обычный сундук» выпадает с шансом 70%
- «Редкий сундук» — 20%
- «Легендарный сундук» — 10%
Правила процентов:
| Ситуация | Поведение |
|---|---|
| Процентов нет | Все элементы равновероятны |
| Сумма = 100 | Используются как есть |
| Сумма ≠ 100 | Автоматически нормализуются (пропорции сохраняются) |
| Процентов меньше, чем элементов | Остаток делится поровну между элементами без процента |
| Процентов больше, чем элементов | Лишние проценты игнорируются |
Пример нормализации:
!active
// 2 + 1 = 3, нормализация: ~66.7% и ~33.3%
тип:random 2 1
- Воин
- МагПример неполных процентов:
!active
// Первому — 80%, оставшиеся 20% делятся на два: по 10%
дроп:random 80
- Ничего
- Меч
- Щит:calc — вычисление выражения
Вычисляет арифметическое выражение. Может ссылаться на другие ключи по имени.
!active
цена 100
налог:calc цена * 0.2
итого:calc цена + налогРезультат:
цена 100
налог 20 // < программа получит это значение
итого 120 // < программа получит это значениеЕсли брать файл .json
{
"цена": 100,
"налог": 20,
"итого": 120
}Поддерживаемые операции: +, -, *, /, % (остаток), (, ).
⚠️ Только арифметика. Никакого произвольного кода. Парсер использует безопасный вычислитель, не
eval().
:env — переменная окружения
Подставляет значение переменной окружения системы.
!active
порт:env PORT
домашняя_папка:env HOMEЕсли переменная не найдена — значение будет null.
С дефолтом (через :default):
!active
порт:env:default:8080 PORTЕсли PORT не задан в системе → вернётся 8080.
Текст остаётся текстом. Значение переменной приводится как любой литерал (8080 → int). Значения, которые лишь похожи на числа — 64-битные id, коды с ведущими нулями, — сохраняют текст с подсказкой (string) или ограничением [type:string]; то же правило действует для запасного значения :default:
!active
discord_app_id[type:string]:env DISCORD_APP_ID
индекс(string):env:default:007 ZIP
api_key[type:string]:secret:env API_KEYС 3.7.4 текст сохраняет и
[type:string]. Раньше это делал только(string): значение сначала приводилось к числу, и[type:string]отвергал его сCONSTRAINT_ERR. Значение:secretудовлетворяет[type:string].
:alias — ссылка на другой ключ
Копирует значение другого ключа. Не дублирует данные — ссылается.
!active
главный_админ alex@mail.com
почта_для_жалоб:alias главный_админРезультат:
{
"главный_админ": "[email protected]",
"почта_для_жалоб": "[email protected]"
}:secret — скрытое значение
Значение читается программой, но не выводится в логи, при freeze, при сериализации в JSON. Защита от случайной утечки.
!active
api_key:secret sk-1234567890abcdef
db_password:secret P@ssw0rd!При console.log(data), print(data), JSON.stringify(data) — покажет "[SECRET]".
Чтобы получить реальное значение, используйте метод .reveal():
// JavaScript / TypeScript
const key = data.api_key; // SynxSecret объект
console.log(String(key)); // "[SECRET]"
console.log(JSON.stringify(key)); // '"[SECRET]"'
console.log(key.reveal()); // "sk-1234567890abcdef" ← реальное значение# Python
key = data['api_key'] # SynxSecret объект
print(key) # [SECRET]
print(key.reveal()) # sk-1234567890abcdef ← реальное значениеС 3.7.2 маска держится и для
util.inspect/console.logцелого объекта, spread иObject.entries(TypeScript), для{:?}(Rust) и для данных, которые получают WASM-плагины маркеров.
⚠️ Важно: Никогда не логируйте результат
.reveal(). Этот метод предназначен только для передачи значения в API, подключения к БД и т.д.
:default — значение по умолчанию
Задаёт fallback, если основное значение пустое или не найдено. Чаще всего комбинируется с :env.
!active
// Если переменная PORT не задана — будет 3000
порт:env:default:3000 PORT
// Просто значение по умолчанию (если значение = null или пусто)
тема:default dark:unique — убрать дубликаты из списка
Оставляет только уникальные элементы.
!active
теги:unique
- экшн
- рпг
- экшн
- симулятор
- рпгРезультат: ["экшн", "рпг", "симулятор"]
:include — подключить другой файл
Вставляет содержимое другого .synx файла в текущий. Путь относительный от текущего файла.
!active
// Подтянуть настройки базы данных из отдельного файла
database:include ./db.synxГде db.synx:
host localhost
port 5432
name mydbРезультат:
{
"database": {
"host": "localhost",
"port": 5432,
"name": "mydb"
}
}:geo — значение по геолокации / региону
Выбирает значение на основе региона пользователя (определяется по IP или системной локали).
!active
валюта:geo
- RU RUB
- US USD
- EU EURЭта функция требует поддержки в рантайме. Парсер передаёт текущий регион движку.
:template — интерполяция строк
Подставляет значения из объекта в строку с использованием {placeholders}. Поддерживает точечную нотацию для доступа к вложенным полям.
!active
приветствие:template Привет, {имя}!
имя Иван
сообщение:template Сервер {server.host}:{server.port}
server
host localhost
port 8080Результат:
{
"приветствие": "Привет, Иван!",
"сообщение": "Сервер localhost:8080"
}:split — разделение строки на массив
Преобразует строку в массив, разделяя по указанному разделителю. Поддерживает ключевые слова: space, pipe, dash, dot, semi, tab.
!active
теги:split space
Python Django Flask
координаты:split pipe
10|20|30
части:split dash
section-one-two-threeРезультат:
{
"теги": ["Python", "Django", "Flask"],
"координаты": ["10", "20", "30"],
"части": ["section", "one", "two", "three"]
}Если значение выглядит как число, оно автоматически приводится к числовому типу.
:join — объединение массива в строку
Преобразует массив в строку, соединяя элементы указанным разделителем. Поддерживает те же ключевые слова: space, pipe, dash, dot, semi, tab.
!active
фраза:join space
- Hello
- World
- 2024
путь:join dot
- app
- modules
- configРезультат:
{
"фраза": "Hello World 2024",
"путь": "app.modules.config"
}:ref — разрешение и цепочка
Разрешает ключ по имени и передаёт значение следующим маркерам в цепочке. Похож на :alias, но предназначен для цепочек с :calc и другими преобразованиями.
!active
базовая_ставка 100
итого:ref:calc:*2 базовая_ставкаРезультат: итого = 200. Сокращение :ref:calc:*2 базовая_ставка разрешает базовая_ставка → 100, затем вычисляет 100 * 2.
:i18n — интернационализация
Выбирает перевод на основе текущей локали. Дочерние ключи — коды языков; движок выбирает тот, что совпадает с options.lang (по умолчанию en).
!active
приветствие:i18n
en Hello
ru Привет
de HalloПлюрализация — добавьте имя поля-счётчика: :i18n:count_field
!active
метка_предметов:i18n:количество
en
one {count} item
other {count} items
ru
one {count} предмет
few {count} предмета
many {count} предметов
other {count} предметовКатегории множественного числа по CLDR (en: one/other, ru: one/few/many/other). {count} подставляется значением указанного поля.
:clamp — числовое ограничение диапазона
Ограничивает числовое значение в диапазоне min–max.
!active
громкость:clamp:0:100 150
# → 100
яркость:clamp:0:255 -10
# → 0Ошибка, если MIN > MAX.
:round — числовое округление
Округляет число до N знаков после запятой.
!active
цена:round:2 19.999
# → 20.00
пи:round:4 3.14159265
# → 3.1416
целое:round:0 42.7
# → 43По умолчанию: 0 знаков (округление до целого).
:format — форматирование в стиле printf
Форматирует значение по шаблону printf.
!active
цена:format:%.2f 19.9
# → "19.90"
код:format:%04d 42
# → "0042"Поддерживаемые шаблоны: %.Nf (дробное), %d (целое), %0Nd (с нулями). Макс. ширина/точность: 4096/1024.
:map — таблица подстановок
Подставляет значение из таблицы поиска. Дочерние элементы — пары значение_поиска результат.
!active
метки_статусов
200 OK
404 Not Found
500 Internal Server Error
результат:map:метки_статусов
- 200
- 404
- 500Результат: ["OK", "Not Found", "Internal Server Error"]. Если совпадений нет — возвращает null.
:once — сгенерировать один раз, кэшировать
Генерирует значение при первом парсинге и сохраняет его в файле .synx.lock для последующих чтений.
!active
instance_id:once:uuid
# → "550e8400-e29b-41d4-a716-446655440000" (стабильно между парсингами)
created_at:once:timestamp
# → "2026-04-01T12:00:00Z" (замораживается при первом парсинге)Типы: uuid, timestamp, random.
:version — сравнение версий
Сравнивает значение с ограничением семантической версии. Возвращает булево.
!active
app_ok:version:>=:1.0.0 1.2.3
# → true
engine_ok:version:>=:2.0.0 1.9.5
# → falseОператоры: >=, <=, >, <, ==, !=. Разбирает semver (x.y.z…).
:watch — чтение внешнего файла
Читает внешний JSON или SYNX файл при парсинге и подставляет его содержимое как значение.
!active
все_флаги:watch ./flags.synx
db_host:watch:database.host ./infra.jsonНеобязательный путь ключа после :watch: извлекает конкретное вложенное значение. Макс. глубина: 16, макс. размер: 10 MiB. Защита путей (path-jail).
:fallback — резервный файл
Если основной файл отсутствует, используется резервный путь.
!active
config:fallback:./defaults.synx ./overrides.synxТакже применяется, если значение null или пустое.
:spam — ограничение частоты
Ограничивает количество обращений к значению за временное окно.
!active
api_endpoint:spam:5:60 https://api.example.com/data
# Максимум 5 обращений за 60 секундОкно по умолчанию: 1 секунда. Счётчик живёт в памяти процесса и сбрасывается при перезапуске.
:prompt — метка для LLM
Форматирует поддерево как именованный block-fence для LLM.
!active
config_block:prompt:AppConfig
app_name MyCoolApp
version 2.1.0Выход: AppConfig (SYNX):\n\``synx\n...\n````
:vision — метаданные изображения (сквозной)
Помечает значение как ссылку на изображение для моделей компьютерного зрения. Движок не трансформирует — приложения определяют по метаданным.
!active
диаграмма:vision ./docs/architecture.png:audio — метаданные аудио (сквозной)
Помечает значение как ссылку на аудио. Движок не трансформирует — приложения определяют по метаданным.
!active
запись:audio ./meetings/standup.mp3:import — псевдоним для :include
Идентичен :include. Используйте тот, что читается лучше.
!active
бд:import ./config/db.synx:inherit — наследование объектов (mixin)
Наследует все поля из одного или нескольких родительских объектов. Дочерние поля имеют приоритет.
!active
база
host localhost
port 8080
debug false
продакшн:inherit база
host prod.example.com
debug falseРезультат: продакшн = { "host": "prod.example.com", "port": 8080, "debug": false }. Родители объединяются слева направо, затем дочерние поля перезаписывают. Разрешается на предварительном проходе до других маркеров.
3.3 Сводная таблица функций
| Функция | Описание | Пример |
|---|---|---|
:random | Случайный элемент из списка | фраза:random |
:random N N N | Взвешенный рандом (проценты) | дроп:random 70 20 10 |
:calc | Арифметическое вычисление | итого:calc цена * 1.2 |
:env | Переменная окружения | порт:env PORT |
:alias | Ссылка на другой ключ | копия:alias оригинал |
:secret | Скрытое от логов значение | пароль:secret abc123 |
:default | Значение по умолчанию | тема:default dark |
:default:X | Fallback (в комбинации) | порт:env:default:8080 PORT |
:unique | Дедупликация списка | теги:unique |
:include | Подключить внешний файл | бд:include ./db.synx |
:import | Псевдоним для :include | бд:import ./db.synx |
:geo | Значение по региону | валюта:geo |
:template | Интерполяция строк | приветствие:template Привет, {имя}! |
:split | Разделение строки на массив | теги:split space |
:join | Объединение массива в строку | фраза:join space |
:ref | Разрешение и цепочка | итого:ref:calc:*2 базовая_ставка |
:i18n | Перевод по локали | приветствие:i18n |
:clamp | Числовое ограничение | громкость:clamp:0:100 150 |
:round | Числовое округление | цена:round:2 19.999 |
:format | Форматирование printf | цена:format:%.2f 19.9 |
:map | Таблица подстановок | результат:map:метки_статусов |
:once | Сгенерировать, кэшировать | id:once:uuid |
:version | Сравнение версий | ok:version:>=:1.0.0 1.2.3 |
:watch | Чтение внешнего файла | флаги:watch ./flags.synx |
:fallback | Резервный файл | cfg:fallback:./default.synx ./custom.synx |
:spam | Ограничение частоты | api:spam:5:60 endpoint |
:prompt | Метка для LLM | ctx:prompt:system Ваш промпт |
:vision | Метаданные изображения | img:vision ./photo.png |
:audio | Метаданные аудио | snd:audio ./clip.mp3 |
:inherit | Наследование объектов | прод:inherit база |
Комбинирование функций — через цепочку ::
!active
порт:env:default:8080 PORT3.4 Ограничения ([]) — валидация данных
Ограничения записываются в квадратных скобках между ключом и функцией (или значением). Они работают только в режиме !active.
Общий синтаксис:
ключ[ограничение1:значение, ограничение2:значение]:функция значениеmin / max — минимум и максимум
Для чисел — ограничивает диапазон значения.
Для строк — ограничивает длину (количество символов).
!active
// Строка от 3 до 30 символов
имя_приложения[min:3, max:30] TotalWario
// Число от 1 до 100
громкость[min:1, max:100] 75
// Только минимум
пароль[min:8] мойпароль123required — обязательное поле
Парсер выкинет ошибку, если значение пустое или отсутствует.
!active
api_key[required]:env API_KEY
имя[required, min:1] Wariopattern — регулярное выражение
Значение должно соответствовать regex-шаблону.
!active
код_страны[pattern:^[A-Z]{2}$] RU
телефон[pattern:^\+\d{10,15}$] +79991234567enum — допустимые значения
Значение должно быть одним из перечисленных.
!active
тема[enum:light|dark|auto] dark
регион[enum:EU|US|RU|AS] RUreadonly — только для чтения
Значение нельзя изменить через API / горячую перезагрузку конфига. Только ручное редактирование файла.
!active
версия[readonly] 2.0.03.5 Сводная таблица ограничений
| Ограничение | Описание | Синтаксис |
|---|---|---|
min | Минимум (длина в символах или значение) | [min:3] |
max | Максимум (длина в символах или значение) | [max:100] |
type | Тип данных | [type:int] |
required | Обязательное поле | [required] |
pattern | Regex-валидация | [pattern:^\d+$] |
enum | Список допустимых значений | [enum:a|b|c] |
readonly | Запрет на изменение | [readonly] |
Длина строки — число Unicode-символов (скалярных значений): у мир и 東京都 она 3, у 😀 — 1. До 3.7.4 движок на Rust считал байты UTF-8.
Нарушенное ограничение заменяет значение строкой CONSTRAINT_ERR: …. Кроме того, ограничения собираются по имени поля со всего документа — побеждает самое строгое объявление — и проверяются у каждого поля с этим именем, когда все маркеры уже разрешены. pattern, где один квантификатор вложен в другой (^(a+)+$), пропускается, а не выполняется, чтобы враждебный документ не мог подвесить парсер.
Ограничения можно комбинировать через запятую:
!active
пароль[required, min:8, max:64, type:string] MyP@ssw0rd3.6 Директивы
Директивы — строки верхнего уровня, начинающиеся с ! или #!. Они управляют режимом документа и метаданными. Директива должна стоять перед любыми парами ключ-значение.
| Директива | Описание |
|---|---|
!active | Включить маркеры, ограничения и валидацию (см. §3.1) |
!lock | Пометить документ как только для чтения (флаг метаданных) |
!include | Включить другой SYNX-файл на уровне корня документа |
!tool | Перестроить вывод как конверт вызова инструмента (имя + параметры) |
!schema | Экспортировать JSON Schema Draft 2020-12 из структуры документа |
!llm | Аннотировать документ для LLM (только метаданные) |
!lock — только для чтения
Устанавливает флаг locked в результате парсинга. Дерево данных не меняется — это рекомендация для инструментов.
!lock
имя Алиса
роль администратор!include — включение на уровне документа
Включает другой SYNX-файл и объединяет его содержимое на уровне корня. Необязательный псевдоним назначает включённое дерево именованному ключу.
!include ./db.synx
!include ./auth.synx auth_config
имя МоёПриложениеМаксимальная глубина: 16. Защита путей запрещает .. выход.
!tool — конверт вызова инструмента
Перестраивает вывод: первый ключ становится именем инструмента, его дочерние элементы — параметрами.
!tool
web_search
query rust async
lang en
results 10Выход:
{
"tool": "web_search",
"params": {
"query": "rust async",
"lang": "en",
"results": 10
}
}!schema — экспорт JSON Schema
Заставляет парсер генерировать объект JSON Schema Draft 2020-12 на основе ключей и ограничений документа.
!schema
имя[required, type:string]
порт[type:int, min:1, max:65535]!llm — метаданные LLM
Директива-метаданные для LLM-инструментов. Не меняет дерево данных.
!llm
persona Ассистент
role Вы — полезный ассистент по программированию
tone профессиональный и лаконичный