# Copilot CLI ACP сервер

Узнайте о GitHub Copilot CLIсервере протокола Agent Client от '.

> \[!NOTE]
> Поддержка ACP в GitHub Copilot CLI системе Публичный предварительный просмотр и может измениться.

## Обзор

Протокол агента-клиента (ACP) — это протокол, который стандартизирует коммуникацию между клиентами (такими как редакторы кода и IDE) и агентами (например Copilot CLI, ). Для получения дополнительной информации об этом протоколе см. [официальное введение](https://agentclientprotocol.com/get-started/introduction).

## Случаи использования

* **Интеграции IDE:** Встраивайте Copilot поддержку в любой редактор или среду разработки.
* **CI/CD pipelines:** Оркестрирование задач агентного кодирования в автоматизированных рабочих процессах.
* **Кастомные фронтенды:** Создавайте специализированные интерфейсы для конкретных рабочих процессов разработчиков.
* **Многоагентные системы:** Координируйте Copilot действия с другими агентами ИИ по стандартному протоколу.

## Запуск сервера ACP

`--acp` Используйте параметр `copilot` команды, чтобы запустить сервер ACP интерфейса командной строки. Можно указать режим транспорта с `--stdio` помощью параметров или `--port` параметров. Если режим транспорта не указан, сервер по умолчанию использует режим stdio.

Режим ACP позволяет сеансам с настроенным поставщиком собственных ключей (BYOK) (`COPILOT_PROVIDER_*` переменными среды) выполняться без GitHub входа, совпадая с поведением /интерактивным `-p`режимом.

### Параметры, применяемые к каждому сеансу

Запрос ACP `session/new` позволяет клиенту задать несколько параметров сеанса, таких как рабочий каталог и серверы MCP. Он не содержит параметров фильтрации инструментов или причин. Чтобы настроить эти параметры, передайте соответствующие параметры при **запуске сервера**. Сервер хранит значения и применяет их в качестве начальной конфигурации для каждого сеанса, который он создает или загружает, для любого клиента, который подключается. Подключающийся клиент не выбирает эти значения, независимо от того, кто запускает сервер.

| Параметр сервера                             | Принятое значение                                      | Влияние на каждый сеанс                                 |
| -------------------------------------------- | ------------------------------------------------------ | ------------------------------------------------------- |
| `--available-tools=TOOL ...`                 | Кавычек, разделенный запятыми список имен инструментов | Сеанс может использовать только перечисленные средства. |
| `--excluded-tools=TOOL ...`                  | Кавычек, разделенный запятыми список имен инструментов | Перечисленные средства удаляются из сеанса.             |
| `--effort=LEVEL`, `--reasoning-effort=LEVEL` |                                                        |                                                         |
| `low`, `medium`, `high`, `xhigh` или `max`   | Задает начальную причину сеанса.                       |                                                         |

Например, эта команда запускает сервер, сеансы которого используют максимальное усилие по поводу и предоставляют только `bash` те и `view` средства:

```bash
copilot --acp --port 3000 --effort=max --available-tools="bash,view"
```

Каждый сеанс подключенного клиента открывается для этого сервера, наследуя эти параметры. Так как значения фиксируются при запуске сервера, клиент не может изменять их на сеанс.`session/new`

### Режим stdio

Режим stdio по умолчанию выводится при запуске сервера ACP. Вы также можете использовать `--stdio` параметр для диамбигуации.

```bash
copilot --acp --stdio
```

### Режим TCP

Если параметр `--port` предоставляется в сочетании с параметром `--acp` , сервер запускается в режиме TCP.

```bash
copilot --acp --port 3000
```

### Выбор между stdio и TCP

Оба режима транспорта несут одни и те же сообщения ACP, закодированные в формате JSON с разделителями новой строки (NDJSON). Они отличаются только тем, как клиент подключается к серверу и как управляется жизненным циклом сервера. Два режима являются взаимоисключающими: передача обоих `--stdio` и `--port` отклонений.

| Аспект                          | Режим stdio                                                                                                                                                 | Режим TCP                                                                                                                                                    |
| ------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| **Как клиент подключается**     | Клиент запускается `copilot --acp` как дочерний процесс и обменивается сообщениями по стандартным входным и выходным данным процесса.                       | Сервер открывает прослушиватель TCP, к которому клиенты подключаются через сетевой сокет. По умолчанию он привязывается к адресу `127.0.0.1`обратного цикла. |
| **Количество клиентов**         | Один клиент — процесс, который породил сервер и владеет каналом.                                                                                            | Прослушиватель принимает подключения сокетов, каждый из которых обрабатывается в качестве собственного подключения агента.                                   |
| **Жизненный цикл**              | Привязан к родительскому процессу. Когда входной поток закрывается , так как родительский выход или закрывает канал, сервер завершает работу автоматически. | Независимо от одного клиента. Сервер продолжает прослушивать порт, пока он не будет остановлен, например с <kbd>помощью CTRL</kbd>+<kbd>C</kbd>.             |
| **Стандартные выходные данные** | Зарезервировано для потока протокола NDJSON, поэтому его нельзя использовать для журналов или другого текста.                                               | Бесплатно для другого использования, так как трафик протокола перемещается по сокету.                                                                        |

Когда следует использовать каждый режим:

* Используйте **режим stdio** , когда редактор, интегрированная среда разработки или скрипты возникают Copilot CLI непосредственно в качестве подпроцесса. Это по умолчанию и рекомендуемая настройка для интеграции интегрированной среды разработки, так как транспорт устанавливается автоматически при запуске процесса и отключается при завершении работы.
* Используйте **режим TCP** , когда клиенту нужно связаться с сервером через сокет вместо канала, например из отдельного процесса или контейнера или при подключении к более длительному серверу на известном порту.

## Пример: интеграция с сервером ACP

В следующем примере используется клиентское приложение, которое взаимодействует Copilot с GitHub Copilot CLIсервером ACP. Он запускает сервер ACP в режиме stdio, открывает сеанс, запрашивает ввод запроса, отправляет его и выводит потоковый ответ.

Существует растущая экосистема библиотек для программного взаимодействия с серверами ACP. В этом примере используется [библиотека ACP TypeScript](https://agentclientprotocol.com/libraries/typescript).

Чтобы запустить этот пример, вам потребуется следующие зависимости:

* [Node.js](https://nodejs.org) версии 18 или более поздней.
* GitHub Copilot CLI, установленный и прошедший проверку подлинности с GitHub помощью поставщика BYOK (см. раздел ["Запуск сервера ACP](#starting-the-acp-server)").
* Пакет `@agentclientprotocol/sdk` , предоставляющий библиотеку ACP TypeScript. Установите его, выполнив команду `npm install @agentclientprotocol/sdk`.

```typescript copy
import * as acp from "@agentclientprotocol/sdk";
import { spawn } from "node:child_process";
import { Readable, Writable } from "node:stream";
import * as readline from "node:readline/promises";

async function main() {
  const executable = process.env.COPILOT_CLI_PATH ?? "copilot";

  // ACP uses standard input/output (stdin/stdout) for transport; we pipe these for the NDJSON stream.
  const copilotProcess = spawn(executable, ["--acp", "--stdio"], {
    stdio: ["pipe", "pipe", "inherit"],
  });

  if (!copilotProcess.stdin || !copilotProcess.stdout) {
    throw new Error("Failed to start Copilot ACP process with piped stdio.");
  }

  // Create ACP streams (NDJSON over stdio)
  const output = Writable.toWeb(copilotProcess.stdin) as WritableStream<Uint8Array>;
  const input = Readable.toWeb(copilotProcess.stdout) as ReadableStream<Uint8Array>;
  const stream = acp.ndJsonStream(output, input);

  const client: acp.Client = {
    async requestPermission(params) {
      // This example should not trigger tool calls; if it does, refuse.
      return { outcome: { outcome: "cancelled" } };
    },

    async sessionUpdate(params) {
      const update = params.update;

      if (update.sessionUpdate === "agent_message_chunk" && update.content.type === "text") {
        process.stdout.write(update.content.text);
      }
    },
  };

  const connection = new acp.ClientSideConnection((_agent) => client, stream);

  await connection.initialize({
    protocolVersion: acp.PROTOCOL_VERSION,
    clientCapabilities: {},
  });

  const sessionResult = await connection.newSession({
    cwd: process.cwd(),
    mcpServers: [],
  });

  process.stdout.write("Session started!\n");

  // Ask the user to enter a prompt instead of using a hard-coded one.
  const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout,
  });
  const promptText = await rl.question("Enter a prompt: ");
  rl.close();

  const promptResult = await connection.prompt({
    sessionId: sessionResult.sessionId,
    prompt: [{ type: "text", text: promptText }],
  });

  process.stdout.write("\n");

  if (promptResult.stopReason !== "end_turn") {
    process.stderr.write(`Prompt finished with stopReason=${promptResult.stopReason}\n`);
  }

  // Best-effort cleanup
  copilotProcess.stdin.end();
  copilotProcess.kill("SIGTERM");
  await new Promise<void>((resolve) => {
    copilotProcess.once("exit", () => resolve());
    setTimeout(() => resolve(), 2000);
  });
}

main().catch((error) => {
  console.error(error);
  process.exitCode = 1;
});
```

Чтобы выполнить пример, выполните следующие действия:

1. Сохраните приведенный выше код в файл с именем `acp-client.ts`.
2. Запустите файл с `npx tsx`файлом, с помощью которого выполняется TypeScript напрямую без отдельного шага сборки:

   ```bash
   npx tsx acp-client.ts
   ```

## Использование команд косой черты

GitHub Copilot CLIВстроенные команды косой черты могут выполняться по ACP. Чтобы вызвать его, отправьте его как обычный запрос, текст которого является командой, переданный в виде одного блока текстового содержимого, например `/context` или `/session info`. Сервер распознает команду и запускает ее напрямую: информационные команды, такие как или `/usage` возвращающие их выходные данные без вызова модели, а команды действий, такие как `/context``/plan` или `/review` запуск соответствующей задачи агента. В любом случае текст команды не отправляется в модель как вопрос.

### Обнаружение доступных команд

Сервер объявляет команды, поддерживаемые с помощью стандартного уведомления сеанса ACP `available_commands_update` . Он отправляется после создания или загрузки сеанса, а также при каждом изменении набора, например при завершении загрузки навыков. Этот объявленный список является авторитетным, всегда текущим набором команд, которые можно запускать по ACP, и клиенты обычно отображают его в меню команд.

Объявленный список содержит следующее:

* **Встроенные команды**, такие как `/compact`, `/context``/usage``/env``/model``/mcp``/plan`, `/review``/research``/session`и .`/rename`
* **Включено, неизменяемые пользователем навыки**, которые отображаются в виде `/SKILL-NAME` команд.

Команды, которые сам клиент регистрирует, не объявляются обратно в него.

### Доступ к списку из клиента

Так как список поступает как уведомление, а не в ответ на запрос, нет метода получения по запросу. Клиент обращается к нему, обрабатывая `session/update` уведомление и реагируя на обновления, тип которых имеет тип `available_commands_update`. Каждая запись имеет значение `name` (без начальной косой черты), а `description`также необязательный элемент `input.hint` , описывающий аргументы команды. Уведомление отправляется повторно всякий раз при изменении набора, поэтому следует рассматривать каждую из них как полную замену любого кэшированного списка.

`sessionUpdate` Следующий обработчик записывает объявленные команды, расширяя `client` объект из примера, показанного ранее.

```typescript copy
// Track the latest advertised commands for the session.
let availableCommands: acp.AvailableCommand[] = [];

const client: acp.Client = {
  async sessionUpdate(params) {
    const update = params.update;

    if (update.sessionUpdate === "available_commands_update") {
      // This notification is a full snapshot—replace any cached list.
      availableCommands = update.availableCommands;
      for (const command of availableCommands) {
        // command.name has no leading slash; invoke it by sending "/<name>" as a prompt.
        console.log(`/${command.name} — ${command.description}`);
      }
      return;
    }

    // ...handle other updates, such as agent_message_chunk
  },

  // ...other client methods, such as requestPermission
};
```

Чтобы выполнить одну из объявленных команд, отправьте его имя в виде запроса в одном блоке текстового содержимого( например, `{ type: "text", text: "/context" }`как описано в [разделе "Использование команд косой черты](#using-slash-commands)".

### Команды, которые нельзя использовать для ACP

Команды косой черты, зависящие от интерактивного интерфейса терминала, не обрабатываются сервером ACP. Сюда входят команды, которые открывают средство выбора, диалоговое окно или полноэкранное представление, например `/diff`, `/resume`, `/theme`, `/settings`, `/login`, `/help`и `/tasks``/undo`. Как правило, если команда не отображается в `available_commands_update` списке, она не будет выполняться по ACP: сервер обрабатывает текст как обычный запрос и пересылает его в модель вместо выполнения.

Так как у клиентов ACP нет интерактивных средства выбора, встроенная команда, которая обычно открывает подменю, возвращает параметры в виде текста. Предоставьте подкоманда явным образом, чтобы получить прямой результат, например, или `/session info` вместо того, `/mcp list` чтобы `/session``/mcp` или самостоятельно.

Полный список команд косой черты см Copilot CLI. в разделе [Справочник команды GitHub Copilot CLI](/ru/copilot/reference/copilot-cli-reference/cli-command-reference#slash-commands-in-the-interactive-interface).

## Дополнительные материалы

* [Официальная документация ACP](https://agentclientprotocol.com/protocol/overview)