Skip to Content
Руководство для пользователей

Qwen Code Companion Plugin: Спецификация интерфейса

Последнее обновление: 15 сентября 2025 г.

Этот документ определяет контракт для создания компаньон-плагина, который активирует режим IDE для Qwen Code. Для VS Code эти возможности (встроенное сравнение, осведомленность о контексте) предоставляются официальным расширением (маркетплейс ). Данная спецификация предназначена для участников, желающих реализовать аналогичную функциональность в других редакторах, таких как JetBrains IDE, Sublime Text и т.д.

I. Интерфейс взаимодействия

Qwen Code и плагин IDE обмениваются данными через локальный канал взаимодействия.

1. Транспортный уровень: MCP поверх HTTP

Плагин ОБЯЗАН запустить локальный HTTP-сервер, реализующий Model Context Protocol (MCP).

  • Протокол: Сервер должен быть корректным MCP-сервером. Рекомендуется использовать существующий MCP SDK для вашего языка, если он доступен.
  • Конечная точка: Сервер должен предоставлять одну конечную точку (например, /mcp) для всего MCP-взаимодействия.
  • Порт: Сервер ОБЯЗАН прослушивать динамически назначенный порт (т.е. слушать порт 0).

2. Механизм обнаружения: Блокировочный файл

Чтобы Qwen Code мог подключиться, ему необходимо узнать, какой порт использует ваш сервер. Плагин ОБЯЗАН обеспечить это, создав «блокировочный файл» и установив переменную окружения с портом.

  • Как CLI находит файл: CLI считывает порт из QWEN_CODE_IDE_SERVER_PORT, затем читает ~/.qwen/ide/<PORT>.lock (существуют устаревшие запасные варианты для старых расширений; см. примечание ниже).

  • Расположение файла: Файл должен быть создан в определённом каталоге: ~/.qwen/ide/. Ваш плагин должен создать этот каталог, если он не существует.

  • Соглашение об именовании файлов: Имя файла критически важно и ОБЯЗАНО соответствовать шаблону: <PORT>.lock

    • <PORT>: Порт, на котором работает ваш MCP-сервер.
  • Содержимое файла и проверка рабочей области: Файл ОБЯЗАН содержать JSON-объект следующей структуры:

    { "port": 12345, "workspacePath": "/path/to/project1:/path/to/project2", "authToken": "a-very-secret-token", "ppid": 1234, "ideName": "VS Code" }
    • port (number, required): Порт MCP-сервера.
    • workspacePath (string, required): Список всех открытых корневых путей рабочей области, разделённых разделителем путей, специфичным для ОС (: для Linux/macOS, ; для Windows). CLI использует этот путь, чтобы убедиться, что он запущен в той же папке проекта, которая открыта в IDE. Если текущий рабочий каталог CLI не является подкаталогом workspacePath, соединение будет отклонено. Ваш плагин ОБЯЗАН предоставлять корректные абсолютные пути к корням открытых рабочих областей.
    • authToken (string, required): Секретный токен для защиты соединения. CLI будет включать этот токен в заголовок Authorization: Bearer <token> во всех запросах.
    • ppid (number, required): Идентификатор родительского процесса IDE.
    • ideName (string, required): Удобочитаемое имя IDE (например, VS Code, JetBrains IDE).
  • Аутентификация: Для защиты соединения плагин ОБЯЗАН сгенерировать уникальный секретный токен и включить его в файл обнаружения. Затем CLI будет включать этот токен в заголовок Authorization для всех запросов к MCP-серверу (например, Authorization: Bearer a-very-secret-token). Ваш сервер ОБЯЗАН проверять этот токен при каждом запросе и отклонять любые неавторизованные.

  • Переменные окружения (обязательно): Ваш плагин ОБЯЗАН установить QWEN_CODE_IDE_SERVER_PORT во встроенном терминале, чтобы CLI мог найти соответствующий файл <PORT>.lock.

Примечание об устаревших версиях: Для расширений старше v0.5.1 Qwen Code может использовать запасной вариант — чтение JSON-файлов в системном временном каталоге с именами qwen-code-ide-server-<PID>.json или qwen-code-ide-server-<PORT>.json. Новые интеграции не должны полагаться на эти устаревшие файлы.

II. Интерфейс контекста

Для обеспечения осведомленности о контексте плагин МОЖЕТ предоставлять CLI информацию в реальном времени о действиях пользователя в IDE.

Уведомление ide/contextUpdate

Плагин МОЖЕТ отправлять уведомление ide/contextUpdate notification  в CLI всякий раз, когда контекст пользователя меняется.

  • События-триггеры: Это уведомление следует отправлять (с рекомендуемым подавлением 50 мс) при:

    • Открытии, закрытии или фокусировке файла.
    • Изменении позиции курсора или выделения текста пользователя в активном файле.
  • Полезная нагрузка (IdeContext): Параметры уведомления ОБЯЗАНЫ быть объектом IdeContext:

    interface IdeContext { workspaceState?: { openFiles?: File[]; isTrusted?: boolean; }; } interface File { // Абсолютный путь к файлу path: string; // Временная метка последней фокусировки (Unix timestamp) для упорядочивания timestamp: number; // True, если это текущий сфокусированный файл isActive?: boolean; cursor?: { // Номер строки (начиная с 1) line: number; // Номер символа (начиная с 1) character: number; }; // Текст, выделенный пользователем в данный момент selectedText?: string; }

    Примечание: Список openFiles должен включать только файлы, существующие на диске. Виртуальные файлы (например, несохранённые файлы без пути, страницы настроек редактора) ОБЯЗАНЫ быть исключены.

Как CLI использует этот контекст

Получив объект IdeContext, CLI выполняет несколько шагов нормализации и усечения перед отправкой информации модели.

  • Упорядочивание файлов: CLI использует поле timestamp для определения наиболее недавно использованных файлов. Он сортирует список openFiles на основе этого значения. Поэтому ваш плагин ОБЯЗАН предоставлять точную временную метку Unix для момента последней фокусировки файла.
  • Активный файл: CLI считает только самый последний файл (после сортировки) «активным». Он игнорирует флаг isActive во всех остальных файлах и очищает их поля cursor и selectedText. Ваш плагин должен сосредоточиться на установке isActive: true и предоставлении информации о курсоре/выделении только для текущего сфокусированного файла.
  • Усечение: Для управления лимитом токенов CLI усекает как список файлов (до 10 файлов), так и selectedText (до 16 КБ).

Хотя CLI выполняет финальное усечение, настоятельно рекомендуется, чтобы ваш плагин также ограничивал объем отправляемого контекста.

III. Интерфейс сравнения (diff)

Для поддержки интерактивных изменений кода плагин МОЖЕТ предоставлять интерфейс сравнения. Это позволяет CLI запрашивать открытие в IDE представления diff с предлагаемыми изменениями файла. Пользователь может просматривать, редактировать и в итоге принять или отклонить эти изменения непосредственно в IDE.

Инструмент openDiff

Плагин ОБЯЗАН зарегистрировать инструмент openDiff на своём MCP-сервере.

  • Описание: Этот инструмент даёт указание IDE открыть редактируемое представление diff для определённого файла.

  • Запрос (OpenDiffRequest): Инструмент вызывается через запрос tools/call. Поле arguments внутри params запроса ОБЯЗАНО быть объектом OpenDiffRequest.

    interface OpenDiffRequest { // Абсолютный путь к файлу для сравнения. filePath: string; // Предлагаемое новое содержимое файла. newContent: string; }
  • Ответ (CallToolResult): Инструмент ОБЯЗАН немедленно вернуть CallToolResult для подтверждения запроса и сообщения, было ли представление diff успешно открыто.

    • При успехе: Если представление diff успешно открыто, ответ ОБЯЗАН содержать пустое содержимое (т.е. content: []).
    • При ошибке: Если ошибка помешала открытию представления diff, ответ ОБЯЗАН иметь isError: true и включать блок TextContent в массив content с описанием ошибки.

    Фактический результат diff (принятие или отклонение) передается асинхронно через уведомления.

Инструмент closeDiff

Плагин ОБЯЗАН зарегистрировать инструмент closeDiff на своём MCP-сервере.

  • Описание: Этот инструмент даёт указание IDE закрыть открытое представление diff для определённого файла.

  • Запрос (CloseDiffRequest): Инструмент вызывается через запрос tools/call. Поле arguments внутри params запроса ОБЯЗАНО быть объектом CloseDiffRequest.

    interface CloseDiffRequest { // Абсолютный путь к файлу, для которого нужно закрыть представление diff. filePath: string; }
  • Ответ (CallToolResult): Инструмент ОБЯЗАН вернуть CallToolResult.

    • При успехе: Если представление diff успешно закрыто, ответ ОБЯЗАН включать один блок TextContent в массиве content, содержащий финальное содержимое файла перед закрытием.
    • При ошибке: Если ошибка помешала закрытию представления diff, ответ ОБЯЗАН иметь isError: true и включать блок TextContent в массиве content с описанием ошибки.

Уведомление ide/diffAccepted

Когда пользователь принимает изменения в представлении diff (например, нажатием кнопки «Применить» или «Сохранить»), плагин ОБЯЗАН отправить уведомление ide/diffAccepted в CLI.

  • Полезная нагрузка: Параметры уведомления ОБЯЗАНЫ включать путь к файлу и финальное содержимое файла. Содержимое может отличаться от исходного newContent, если пользователь внёс ручные правки в представлении diff.

    { // Абсолютный путь к сравниваемому файлу. filePath: string; // Полное содержимое файла после принятия. content: string; }

Уведомление ide/diffRejected

Когда пользователь отклоняет изменения (например, закрывает представление diff без принятия), плагин ОБЯЗАН отправить уведомление ide/diffRejected в CLI.

  • Полезная нагрузка: Параметры уведомления ОБЯЗАНЫ включать путь к файлу отклонённого diff.

    { // Абсолютный путь к сравниваемому файлу. filePath: string; }

IV. Интерфейс жизненного цикла

Плагин ОБЯЗАН корректно управлять своими ресурсами и файлом обнаружения в соответствии с жизненным циклом IDE.

  • При активации (запуск IDE / включение плагина):
    1. Запустить MCP-сервер.
    2. Создать файл обнаружения.
  • При деактивации (выключение IDE / отключение плагина):
    1. Остановить MCP-сервер.
    2. Удалить файл обнаружения.
Last updated on