Skip to main content

Serveur ACP de Copilot CLI

En savoir plus sur le serveur du Protocole Client Agent CLI GitHub Copilot.

Remarque

Le support ACP dans CLI GitHub Copilot est en préversion publique et est susceptible de changer.

Aperçu

Le protocole ACP (Agent Client Protocol) est un protocole qui normalise la communication entre les clients (tels que les Ă©diteurs de code et les IDE) et les agents (par Copilot pour CLIexemple). Pour plus d’informations sur ce protocole, consultez l’introduction officielle.

Cas d’utilisation

  • IntĂ©grations d’IDE : IntĂ©grez la Copilot prise en charge dans n’importe quel Ă©diteur ou environnement de dĂ©veloppement.
  • CI/CD pipelines : Orchestrer des tĂąches de codage agentiques dans des flux de travail automatisĂ©s.
  • Frontends personnalisĂ©s : CrĂ©ez des interfaces spĂ©cialisĂ©es pour des flux de travail de dĂ©veloppement spĂ©cifiques.
  • SystĂšmes multi-agents : Coordonnez-vous Copilot avec d’autres agents IA Ă  l’aide d’un protocole standard.

Démarrage du serveur ACP

          CLI GitHub Copilot peut ĂȘtre dĂ©marrĂ© en tant que serveur ACP Ă  l’aide de l’indicateur `--acp` . Le serveur prend en charge deux modes, `stdio` et `TCP`.

Par dĂ©faut, en fournissant l'indicateur --acp, le mode stdio est dĂ©duit. L’indicateur --stdio peut Ă©galement ĂȘtre fourni pour la dĂ©sambiguation.

copilot --acp --stdio

Mode TCP

Si l’indicateur --port est fourni en combinaison avec l’indicateur --acp , le serveur est dĂ©marrĂ© en mode TCP.

copilot --acp --port 3000

Intégration au serveur ACP

Il existe un Ă©cosystĂšme croissant de bibliothĂšques pour interagir par programmation avec les serveurs ACP. Étant donnĂ© que CLI GitHub Copilot est correctement installĂ© et authentifiĂ©, l'exemple suivant illustre l'utilisation du client typescript pour envoyer une invite unique et afficher la rĂ©ponse IA.

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

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");
  const promptText = "Hello ACP Server!";
  process.stdout.write(`Sending prompt: '${promptText}'\n`);

  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;
});

Lectures complémentaires