Skip to Content
Интеграция с IDEСпецификация IDE Companion

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

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

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

I. Интерфейс связи

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

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

Плагин ДОЛЖЕН запускать локальный HTTP-сервер, который реализует Model Context Protocol (MCP).

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

2. Механизм обнаружения: Port File

Для подключения Qwen Code необходимо определить, в каком экземпляре IDE он запущен, и какой порт использует ваш сервер. Плагин ОБЯЗАН обеспечить это, создавая так называемый “discovery file”.

  • Как CLI находит файл: CLI определяет Process ID (PID) родительского процесса IDE, проходя по дереву процессов. Затем он ищет discovery файл, имя которого содержит этот PID.

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

  • Соглашение об именовании файла: Имя файла критично и ДОЛЖНО соответствовать шаблону: qwen-code-ide-server-${PID}-${PORT}.json

    • ${PID}: Process ID родительского процесса IDE. Плагин должен определить этот PID и включить его в имя файла.
    • ${PORT}: Порт, на котором слушает ваш MCP сервер.
  • Содержимое файла и проверка workspace: Файл ОБЯЗАН содержать JSON объект следующей структуры:

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

  • Разрешение конфликтов через переменные окружения (рекомендуется): Для наиболее надёжной работы ваш плагин РЕКОМЕНДУЕТСЯ одновременно создавать discovery файл и устанавливать переменную окружения QWEN_CODE_IDE_SERVER_PORT в интегрированном терминале. Файл служит основным механизмом обнаружения, но переменная окружения играет ключевую роль при разрешении конфликтов. Если пользователь открыл несколько окон IDE для одного и того же workspace, CLI использует переменную QWEN_CODE_IDE_SERVER_PORT, чтобы определить и подключиться к серверу нужного окна.

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

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

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

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

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

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

    interface IdeContext { workspaceState?: { openFiles?: File[]; isTrusted?: boolean; }; } interface File { // Абсолютный путь к файлу path: string; // Временная метка последнего фокуса (для сортировки) 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. Интерфейс сравнения (Diffing Interface)

Чтобы включить интерактивные изменения кода, плагин МОЖЕТ предоставлять интерфейс сравнения. Это позволяет CLI запрашивать у IDE открытие представления diff, показывающего предложенные изменения в файле. Затем пользователь может просмотреть, отредактировать, а в конечном итоге принять или отклонить эти изменения непосредственно в IDE.

Инструмент openDiff

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

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

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

    interface OpenDiffRequest { // Абсолютный путь к файлу, по которому будет показан diff. 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-просмотре (например, нажимает кнопку “Apply” или “Save”), плагин ОБЯЗАН отправить уведомление ide/diffAccepted в CLI.

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

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

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

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

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

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

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

Плагин ДОЛЖЕН правильно управлять своими ресурсами и файлом обнаружения в соответствии с жизненным циклом IDE.

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