Add Kiro CLI to ACP provider catalog

Adds Kiro CLI as an opt-in ACP provider catalog entry, plus a generic ACP extension-notification sink so unknown notifications no longer fail JSON-RPC dispatch.
This commit is contained in:
Mingyang Sun
2026-05-19 03:23:57 +00:00
committed by GitHub
parent 383b380d8a
commit 9ef7230417
5 changed files with 46 additions and 2 deletions
@@ -1,4 +1,4 @@
import { Bot } from "lucide-react-native";
import { Bot, PackagePlus } from "lucide-react-native";
import { ClaudeIcon } from "@/components/icons/claude-icon";
import { CodexIcon } from "@/components/icons/codex-icon";
import { CopilotIcon } from "@/components/icons/copilot-icon";
@@ -9,6 +9,7 @@ const PROVIDER_ICONS: Record<string, typeof Bot> = {
claude: ClaudeIcon as unknown as typeof Bot,
codex: CodexIcon as unknown as typeof Bot,
copilot: CopilotIcon as unknown as typeof Bot,
kiro: PackagePlus,
opencode: OpenCodeIcon as unknown as typeof Bot,
pi: PiIcon as unknown as typeof Bot,
};
@@ -240,6 +240,15 @@ const CATALOG_DATA = [
installLink: "https://kilo.ai/docs/code-with-ai/platforms/cli",
command: ["kilo", "acp"],
},
{
id: "kiro",
title: "Kiro CLI",
description: "Amazon's AI coding agent with native ACP support",
version: "manual",
iconId: null,
installLink: "https://kiro.dev/docs/cli/acp/",
command: ["kiro-cli", "acp"],
},
{
id: "kimi",
title: "Kimi CLI",
@@ -26,7 +26,7 @@ describe("ACP provider catalog", () => {
});
it("bundles SVG icons for catalog entries that declare an icon", () => {
const entriesWithIcons = ACP_PROVIDER_CATALOG.filter((entry) => entry.id !== "hermes");
const entriesWithIcons = ACP_PROVIDER_CATALOG.filter((entry) => entry.iconSvg !== null);
expect(entriesWithIcons.length).toBeGreaterThan(0);
for (const entry of entriesWithIcons) {
@@ -39,6 +39,7 @@ describe("ACP provider catalog", () => {
expect(findProvider("cursor").command).toEqual(["cursor-agent", "acp"]);
expect(findProvider("goose").command).toEqual(["goose", "acp"]);
expect(findProvider("junie").command).toEqual(["junie", "--acp", "true"]);
expect(findProvider("kiro").command).toEqual(["kiro-cli", "acp"]);
expect(findProvider("poolside").command).toEqual(["pool", "acp"]);
});
@@ -1438,6 +1438,26 @@ describe("ACPAgentSession slash commands", () => {
});
describe("ACPAgentSession", () => {
test("accepts ACP extension notifications without failing the JSON-RPC connection", async () => {
const logger = createTestLogger();
const trace = vi.spyOn(logger, "trace");
const session = createSessionWithConfig({ provider: "kiro" }, logger);
await expect(
session.extNotification("_kiro.dev/session/initialized", {
sessionId: "session-1",
}),
).resolves.toBeUndefined();
expect(trace).toHaveBeenCalledWith(
expect.objectContaining({
provider: "kiro",
method: "_kiro.dev/session/initialized",
sessionId: "session-1",
}),
"provider.acp.extension_notification",
);
});
test("emits assistant and reasoning chunks as deltas while user chunks stay accumulated", async () => {
const session = createSession();
const events: Array<{ type: string; item?: { type: string; text?: string } }> = [];
@@ -1667,6 +1667,19 @@ export class ACPAgentSession implements AgentSession, ACPClient {
}
}
async extNotification(method: string, params: Record<string, unknown>): Promise<void> {
this.logger.trace(
{
agentId: this.agentId,
provider: this.provider,
sessionId: typeof params.sessionId === "string" ? params.sessionId : undefined,
method,
rawEvent: params,
},
"provider.acp.extension_notification",
);
}
async readTextFile(params: ReadTextFileRequest): Promise<{ content: string }> {
const raw = await fs.readFile(params.path, "utf8");
if (!params.line && !params.limit) {