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:
@@ -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 { ClaudeIcon } from "@/components/icons/claude-icon";
|
||||||
import { CodexIcon } from "@/components/icons/codex-icon";
|
import { CodexIcon } from "@/components/icons/codex-icon";
|
||||||
import { CopilotIcon } from "@/components/icons/copilot-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,
|
claude: ClaudeIcon as unknown as typeof Bot,
|
||||||
codex: CodexIcon as unknown as typeof Bot,
|
codex: CodexIcon as unknown as typeof Bot,
|
||||||
copilot: CopilotIcon as unknown as typeof Bot,
|
copilot: CopilotIcon as unknown as typeof Bot,
|
||||||
|
kiro: PackagePlus,
|
||||||
opencode: OpenCodeIcon as unknown as typeof Bot,
|
opencode: OpenCodeIcon as unknown as typeof Bot,
|
||||||
pi: PiIcon 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",
|
installLink: "https://kilo.ai/docs/code-with-ai/platforms/cli",
|
||||||
command: ["kilo", "acp"],
|
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",
|
id: "kimi",
|
||||||
title: "Kimi CLI",
|
title: "Kimi CLI",
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ describe("ACP provider catalog", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("bundles SVG icons for catalog entries that declare an icon", () => {
|
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);
|
expect(entriesWithIcons.length).toBeGreaterThan(0);
|
||||||
for (const entry of entriesWithIcons) {
|
for (const entry of entriesWithIcons) {
|
||||||
@@ -39,6 +39,7 @@ describe("ACP provider catalog", () => {
|
|||||||
expect(findProvider("cursor").command).toEqual(["cursor-agent", "acp"]);
|
expect(findProvider("cursor").command).toEqual(["cursor-agent", "acp"]);
|
||||||
expect(findProvider("goose").command).toEqual(["goose", "acp"]);
|
expect(findProvider("goose").command).toEqual(["goose", "acp"]);
|
||||||
expect(findProvider("junie").command).toEqual(["junie", "--acp", "true"]);
|
expect(findProvider("junie").command).toEqual(["junie", "--acp", "true"]);
|
||||||
|
expect(findProvider("kiro").command).toEqual(["kiro-cli", "acp"]);
|
||||||
expect(findProvider("poolside").command).toEqual(["pool", "acp"]);
|
expect(findProvider("poolside").command).toEqual(["pool", "acp"]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -1438,6 +1438,26 @@ describe("ACPAgentSession slash commands", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe("ACPAgentSession", () => {
|
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 () => {
|
test("emits assistant and reasoning chunks as deltas while user chunks stay accumulated", async () => {
|
||||||
const session = createSession();
|
const session = createSession();
|
||||||
const events: Array<{ type: string; item?: { type: string; text?: string } }> = [];
|
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 }> {
|
async readTextFile(params: ReadTextFileRequest): Promise<{ content: string }> {
|
||||||
const raw = await fs.readFile(params.path, "utf8");
|
const raw = await fs.readFile(params.path, "utf8");
|
||||||
if (!params.line && !params.limit) {
|
if (!params.line && !params.limit) {
|
||||||
|
|||||||
Reference in New Issue
Block a user