800: Пакет/Схемика
- На чём основаны:
Это специальная библиотека, которая делает Схему (детальный чертёж) единственным и главным источником правды для всей программы. Она использует этот единый чертёж для всего: для проверки данных во время работы, для создания подсказок в коде (типы TypeScript), для общения с искусственным интеллектом и для управления логикой программы. Это гарантирует, что правила для данных и подсказки для программиста всегда идеально совпадают.
Схемика — это фундамент, на котором строятся все структуры данных в нашей системе. Её главная задача — сделать Схему (чертёж) центром всего, главным авторитетом, который определяет всё: от проверки данных до того, как «думают» наши умные помощники-агенты.
Философия и основные идеи
Единственный источник правды
Во многих программах возникает беспорядок: подсказки для программиста (типы в TypeScript) говорят одно, а правила проверки данных во время работы программы (JSON-схемы) — другое. Это как если бы у строителей был один чертёж, а у инженера по качеству — другой. Рано или поздно они начнут расходиться, что приведёт к ошибкам.
Схемика решает эту проблему, делая Схему единственным источником правды. Мы создаём чертёж данных всего один раз, и из него автоматически получаем:
- Проверку во время работы: Как инспектор, который следит, чтобы все детали соответствовали чертежу.
- Типы TypeScript: Как подробная инструкция для программиста, которая не даст ему ошибиться.
- Интеграцию с ИИ: Как понятный язык для наших умных агентов, чтобы они точно знали, с какими данными работают.
- Логику программы: Правила, по которым программа действует, основываясь на структуре чертежа.
Такой подход называется разработкой на основе схемы. Он гарантирует, что теория (то, что видит программист) и практика (то, что происходит в работающей программе) всегда совпадают, без необходимости всё перепроверять вручную.
Принцип «Из Схемы»
Главный волшебный инструмент в нашей библиотеке — это механизм «из схемы». Это как специальный сканер, который читает чертёж и мгновенно создаёт для него точные технические инструкции (типы) для программиста.
- Мгновенное создание типов: Мы «вычисляем» типы прямо из готовой JSON-схемы с помощью утилиты
FromSchema. - Безопасность типов: Эти инструкции-типы используются по всей программе. Если чертёж меняется, инструкции обновляются автоматически. Если какой-то код не соответствует новому чертежу, программа просто не соберётся, и ошибка будет найдена сразу.
Реестр Схем
Чтобы не запутаться в большом количестве чертежей, в Схемике есть встроенный каталог, или реестр.
- Плоская структура: Все чертежи хранятся в одном «каталоге» и могут ссылаться друг на друга по имени (
$ref). Это помогает избежать путаницы, когда один чертёж запрятан глубоко внутри другого. - Автоматические ссылки: Система сама находит нужные чертежи по ссылкам, позволяя разработчикам собирать сложные конструкции из простых, многоразовых «кубиков».
Каноническая Схема и смысловое расхождение
Мы используем понятие Канонической Схемы. Это значит, что внутри системы схема может выглядеть немного иначе, чем для программиста, чтобы быть удобнее для работы библиотеки.
Мы допускаем, что инструкция для программиста (тип TypeScript, полученный через FromSchema) и сам чертёж могут немного отличаться по строению, но при этом они всегда означают одно и то же. Например, для проверки данных схема может быть описана как «объединение двух частей» (allOf), но для программиста она будет выглядеть как один цельный объект. Это сделано специально: программисту проще работать, а система всё равно строго следит за правильностью данных.
Скорость и кэширование
Создавать подробные инструкции по чертежам — довольно сложная задача для компьютера. Чтобы ускорить процесс, Схемика использует умное кэширование.
- Кэширование: Готовые инструкции сохраняются в памяти.
- Повторное использование: Когда инструкция нужна снова, система не создаёт её с нуля, а берёт уже готовую из кэша. Это как если бы вы сделали копию документа, чтобы не печатать его каждый раз заново.
Эволюция: от общего к частному
Сначала наша библиотека использовала очень общий, широкий тип для всех схем. Мы предполагали, что у любой схемы может быть любое свойство. Но это оказалось ловушкой.
- Ловушка «общего»: Слишком общий тип не позволял нам уточнять детали. Например, если объект мог быть «или машиной, или самолётом», система не могла понять, что у машины есть колёса, а у самолёта — крылья. Общий тип «глотал» эти важные различия.
- Переход к строгости: Мы перешли к более строгому подходу, где «любая схема» — это набор чётко разделённых типов (
объект,массив,строкаи т.д.). - Решение: Теперь мы полностью отказываемся от общего типа. Любые общие описания должны быть «распакованы» в свои конкретные составляющие.
План развития: безопасная архитектура типов
Манипуляция схемами
Библиотека предоставляет набор удобных инструментов для работы со схемами, таких как Intersection (объединение), Pick (взять часть), Omit (убрать часть) и Union (или/или). Они позволяют разработчикам собирать и изменять структуры данных «на лету», обращаясь со схемами как с обычными деталями конструктора.
Мы активно работаем над тем, чтобы эти инструменты были полностью типобезопасными. Наша цель — чтобы любое изменение в схеме тут же точно отражалось в статических подсказках (типах) для программиста.
Стратегия ToSchema
Двигаясь вперёд, Схемика использует новый подход к изменению схем, который называется ToSchema. Он основан на том, что Схемы и типы TypeScript — это как две стороны одной медали, и можно легко переключаться между ними.
Процесс выглядит так:
- Извлечь (
FromSchema): Мы «поднимаем» схему в мир типов TypeScript (как бы делаем 3D-скан чертежа). - Обработать: В мире типов мы легко выполняем нужные операции (объединяем, вырезаем, добавляем), используя стандартные инструменты TypeScript.
- Воссоздать (
ToSchema): Мы «опускаем» изменённый тип обратно в мир схем (как бы печатаем новый чертёж на 3D-принтере по компьютерной модели).
Schema.Intersection<A, B>(a: A, b: B): ToSchema<FromSchema<A> & FromSchema<B>>
Почему это работает: Схемы — это мост между реальными данными и подсказками для программиста. Поскольку этот мост работает в обе стороны, мы можем уверенно переходить из одного мира в другой. Мы сосредотачиваемся на том, чтобы структура была правильной, и это позволяет нам обращаться со схемами как с чистыми, функциональными блоками, которые можно собирать и изменять с математической точностью.
Цели: новые инструменты и расширяемость
Эта стратегия позволяет нам создавать сложные инструменты, для которых раньше было трудно или невозможно правильно описать типы:
- Intersection и Union: объединение схем с полной точностью типов.
- Pick и Omit: изменение схем объектов с сохранением строгой типизации.
Простота поддержки: Такой подход сильно упрощает добавление новых инструментов. Вместо того, чтобы вручную описывать все возможные варианты изменения схемы, мы просто описываем, как меняется её тип, а система делает всё остальное.
Поддержка частичных схем
Сейчас наши строгие правила требуют, чтобы схемы были полностью описаны (например, у объекта должно быть явно указано type: 'object'). Однако стандарт JSON Schema позволяет создавать «частичные» описания (например, просто перечислить свойства, а тип object будет подразумеваться).
- Текущее ограничение: Наш инструмент
FromSchemaпока не умеет «додумывать» типы для таких частичных схем. Схема, у которой есть только свойства, не считается полноценным объектом, и это ломает создание инструкций-типов. - Временное решение: Пока что мы требуем, чтобы все схемы были полностью завершёнными и явно указывали свой тип.
- Внутреннее состояние: Внутри кода мы используем специальный тип
CouldBePartial, чтобы пометить места, где в будущем может появиться поддержка частичных схем. - Что нас останавливает: Мы не уверены, не сделает ли поддержка частичных схем систему типов TypeScript слишком сложной и медленной.
- Цель на будущее: Если это окажется возможным без сильного падения производительности, мы хотим включить поддержку частичных схем везде.
Заключение
Делая Схему общим языком и для людей (разработчиков), и для машин (агентов), Схемика создаёт надёжный фундамент, необходимый для системы, построенной вокруг ИИ.
Теперь, когда мы определили, как устроены наши данные, можно посмотреть, как они используются для общения с агентами. 001: Агент/Запрос основывается на этих схемах, чтобы определить правила взаимодействия с большими языковыми моделями.