<?xml version="1.0" encoding="UTF-8"?>
<spec xmlns="https://vibevm.org/spec/1">
  <title id="root">Расширения и провайдеры</title>
  <status stage="doc" state="work" audience="user,author"/>
  <p p="1">Пакет может встроиться в сборку: выполнить шаг, преобразовать этап или передать задачу агенту. Эта страница объясняет, как такие встраивания объявляются, как проект их включает и как увидеть, какие из них выполнились и почему.</p>
  <example ref="extensions" p="2"/>
  <section id="points-and-contributions" title="Точки и вклады">
    <p p="3">[Жизненный цикл](../glossary/index.xml#lifecycle) открывает именованные *[точки расширения](../glossary/index.xml#extension-point)*, строки вида `family:name`. Семейство `phase:`, группа точек с общим префиксом, — это девять [фаз](../glossary/index.xml#phase). Семейство `slot:` называет места внутри фазы, куда стек или дисциплина ожидает что-то встроить. Семейство `compile:` — собственный конвейер компилятора стартовой полосы, где пакет может преобразовать текст, который прочитает агент. *[Вклад](../glossary/index.xml#contribution)* привязывает [обработчик](../glossary/index.xml#handler) к точке и объявляется в [манифесте](../glossary/index.xml#manifest) таблицей `[[extension]]`, в пакете или в самом проекте.</p>
    <rule ref="spec://org.vibevm.core/vibevm/common/PROP-054#POINT-GRAMMAR" p="4"/>
    <rule ref="spec://org.vibevm.core/vibevm/common/PROP-054#CONTRIB-GRAMMAR" p="5"/>
    <p p="6">У вклада есть идентификатор, он же ключ, по которому проект выключает или заменяет вклад; один обработчик можно привязать несколько раз под разными идентификаторами с разной конфигурацией.</p>
    <rule ref="spec://org.vibevm.core/vibevm/common/PROP-054#CONTRIB-FIELDS" p="7"/>
  </section>
  <section id="handlers" title="Пять видов обработчиков">
    <table p="8">
      <tr>
        <td>Вид</td>
        <td>Что выполняется</td>
      </tr>
      <tr>
        <td>`builtin`</td>
        <td>обработчик, вкомпилированный в vibe, например журнал</td>
      </tr>
      <tr>
        <td>`script`</td>
        <td>скрипт оболочки или PowerShell, который поставляет пакет; выбирается по платформе</td>
      </tr>
      <tr>
        <td>`binary`</td>
        <td>программа, которую доставляет пакет и собирает vibe при установке</td>
      </tr>
      <tr>
        <td>`native`</td>
        <td>динамическая библиотека, загружаемая в процесс через C ABI, из точной готовой сборки для платформы</td>
      </tr>
      <tr>
        <td>`agent`</td>
        <td>промпт: работа, переданная агенту-хозяину, или настроенному провайдеру модели, когда vibe запускает человек за терминалом</td>
      </tr>
    </table>
    <rule ref="spec://org.vibevm.core/vibevm/common/PROP-054#HANDLER-KINDS" p="9"/>
    <p p="10">Каждый обработчик получает один конверт контекста, версионированный JSON-документ, который называет проект, фазу, произведённые к этому моменту артефакты и конфигурацию вклада, и отвечает конвертом ответа, который может объявить новые артефакты. Конверт — это то, как фазы говорят друг с другом.</p>
    <rule ref="spec://org.vibevm.core/vibevm/common/PROP-054#ENVELOPE-LAW" p="11"/>
    <p p="12">Нативный обработчик — динамическая библиотека ровно с четырьмя символами C; запрос и ответ пересекают эту границу как версионированный JSON, по одному семейству на библиотеку, а крейт `vibe-ext` даёт автору безопасные макросы, чтобы ни один `unsafe` не писался руками. Обработчик с закрытым исходным кодом поставляется готовой сборкой для каждой платформы; точная готовая сборка побеждает, объявленный исходник может собраться вместо неё, а отсутствие — отказ, а не пропуск. Преобразование `compile:` выполняется внутри регенерации полосы, поэтому им может быть только builtin или допущенный нативный обработчик, никогда скрипт, бинарник или агент. Вклад, которому нужен низкоуровневый ярус проходов, говорит об этом флагом `compiler_internals = true`, и ему всё равно нужна активация со стороны хозяина.</p>
    <rule ref="spec://org.vibevm.core/vibevm/common/PROP-054#C-ABI-LAW" p="13"/>
    <rule ref="spec://org.vibevm.core/vibevm/common/PROP-054#ABI-CRATE" p="14"/>
    <rule ref="spec://org.vibevm.core/vibevm/common/PROP-054#PREBUILT-CLOSED" p="15"/>
    <rule ref="spec://org.vibevm.core/vibevm/common/PROP-054#COMPILE-NATIVE-ONLY" p="16"/>
    <rule ref="spec://org.vibevm.core/vibevm/common/PROP-054#COMPILER-INTERNALS-FLAG" p="17"/>
  </section>
  <section id="activation" title="Как включить вклады">
    <p p="18">Установить пакет — значит согласиться на выполнение его вкладов: вклады зависимости в фазы и слоты активны, как только пакет установлен. Манифест потребителя может активировать вклад, который не включается сам, выключить вклад по идентификатору или [переопределить](../glossary/index.xml#override) его конфигурацию. Диалогов согласия во время выполнения нет; вместо них полная прозрачность.</p>
    <rule ref="spec://org.vibevm.core/vibevm/common/PROP-054#HOST-ACTIVATION" p="19"/>
    <rule ref="spec://org.vibevm.core/vibevm/common/PROP-054#OBS-LAW" p="20"/>
    <p p="21">Внутри одной точки вклады выполняются в фиксированном порядке: сначала встроенные привязки действующего пресета, затем вклады пакетов в порядке зависимостей, затем собственные вклады проекта; порядок выводится, а не обсуждается.</p>
    <rule ref="spec://org.vibevm.core/vibevm/common/PROP-054#ORDER-LAW" p="22"/>
  </section>
  <section id="seeing" title="Как увидеть, что выполнилось">
    <p p="23">`vibe extensions` перечисляет каждый объявленный вклад в установленном мире с его точкой, обработчиком и происхождением; `--json` отдаёт то же сканеру. Всё, что вклад может сделать, объявлено, так что сканеру не нужно ничего выполнять, чтобы проверить проект. Каждый прогон перед стартом печатает вклады, которые выполнит, а сам прогон можно проследить проход за проходом флагом `--trace-compile` в `.vibe/trace/`.</p>
    <rule ref="spec://org.vibevm.core/vibevm/common/PROP-054#OBS-REGISTRY" p="24"/>
    <rule ref="spec://org.vibevm.core/vibevm/common/PROP-054#OBS-TRACE" p="25"/>
    <p p="26">`vibe tools` перечисляет бинарники и серверы, которые принесли установленные пакеты; это [реестр](../glossary/index.xml#registry) того, что может назвать вклад вида `binary`.</p>
    <example ref="tools" p="27"/>
  </section>
  <section id="providers" title="Провайдеры">
    <p p="28">Вкладу вида `agent` нужен кто-то, кто выполнит его промпт. Под агентом-хозяином vibe откладывает задачу для этого агента и продолжает, когда объявленные результаты появились. За терминалом vibe может вызвать настроенного провайдера модели, и первый из них — любая конечная точка, совместимая с OpenAI; учётные данные провайдера он читает только тогда, когда несвежий агентный шаг действительно доходит до вызова. Каждая функция, которую улучшает модель, объявляет, выключена ли она, помогает или обязательна, и по умолчанию она выключена.</p>
    <rule ref="spec://org.vibevm.core/vibevm/common/PROP-054#AGENT-PROVIDER-SEAM" p="29"/>
    <rule ref="spec://org.vibevm.core/vibevm/common/PROP-054#LLM-ENHANCEMENT-MODES" p="30"/>
  </section>
  <section id="edge-cases" title="Особые случаи и правила">
    <p p="31">Вклад может нести селектор, который ограничивает его подходящими файлами или целями, так что форматер привязывается к исходникам одного языка, а не ко всему дереву.</p>
    <rule ref="spec://org.vibevm.core/vibevm/common/PROP-054#CONTRIB-SELECTOR" p="32"/>
    <p p="33">Нативный обработчик пересекает границу из C и JSON, а не Rust ABI, так что библиотека, собранная другой версией тулчейна, всё равно загружается.</p>
    <rule ref="spec://org.vibevm.core/vibevm/common/PROP-054#why-c-abi" p="34"/>
    <p p="35">У включённой работы модели есть потолки на прогон по числу вызовов и токенов; шаг, который их превысил бы, останавливается, а не тратит.</p>
    <rule ref="spec://org.vibevm.core/vibevm/common/PROP-054#LLM-BUDGET" p="36"/>
  </section>
</spec>
