t3-code-android-nightly/packages/contracts/src/acpRegistry.test.ts
Julius Marminge de34391427
feat(orchestrator): introduce new orchestrator (#2829)
Co-authored-by: maria-rcks <maria@kuuro.net>
Co-authored-by: Bilal Bakr <62337003+Bil0000@users.noreply.github.com>
Co-authored-by: shivam <91240327+shivamhwp@users.noreply.github.com>
Co-authored-by: Vitalii Yehorov <vitalyiegorov@gmail.com>
Co-authored-by: Jake Leventhal <jakeleventhal@me.com>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-authored-by: Alex Southwell <saphid@gmail.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Nicholas Wasmiller <derped@mineperial.com>
Co-authored-by: PB <poilmb@gmail.com>
Co-authored-by: Exotic <118054752+extoci@users.noreply.github.com>
Co-authored-by: Yash Singh <saiansh2525@gmail.com>
Co-authored-by: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: Theo Browne <me@t3.gg>
Co-authored-by: Gabriel De Andrade <30420087+gabrielelpidio@users.noreply.github.com>
Co-authored-by: Dara Adedeji <76637177+SunkenInTime@users.noreply.github.com>
Co-authored-by: scratchyone <scratchywon@gmail.com>
Co-authored-by: Dominic Roy <dominic@sdko.org>
Co-authored-by: chukfinley <chuk@chuk.dev>
Co-authored-by: Primož Ajdišek <bigpod@bigpod.si>
Co-authored-by: benthecarman <benthecarman@live.com>
Co-authored-by: NaveDanan <nave0712@gmail.com>
Co-authored-by: aaditagrawal <103925638+aaditagrawal@users.noreply.github.com>
Co-authored-by: Aditya Garud <153842990+yashranaway@users.noreply.github.com>
Co-authored-by: Nick Anisimov <n.anisimov.23@gmail.com>
Co-authored-by: MacKinley Smith <smithmackinley@gmail.com>
Co-authored-by: Yordis Prieto <yordis.prieto@gmail.com>
Co-authored-by: t3-code[bot] <269035359+t3-code[bot]@users.noreply.github.com>
Co-authored-by: AKolenda <akole779@mtroyal.ca>
Co-authored-by: Guillermo Casanova <75276669+Gigioxx@users.noreply.github.com>
Co-authored-by: Otavio Salvador <otavio@ossystems.com.br>
Co-authored-by: Shirish Pothi <183252392+shirishpothi@users.noreply.github.com>
Co-authored-by: Ishaan Kothari <ishaanko.mail@gmail.com>
Co-authored-by: Bob Fowler <bob@rjf.ca>
Co-authored-by: Anton Bezdenezhnykh <gamer392@yandex.ru>
Co-authored-by: ValeraZSD <48602572+ValeraZSD@users.noreply.github.com>
Co-authored-by: Ephraim <ephraim39hr14m@gmail.com>
Co-authored-by: Ryan Ilano <ryanilano@users.noreply.github.com>
Co-authored-by: Alex <me@pixp.cc>
Co-authored-by: maco <gosarmarcel7@gmail.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Tristan Knight <admin@snappeh.com>
Co-authored-by: PR Batch Tester <agent@local.test>
Co-authored-by: oliver <97427849+flamboh@users.noreply.github.com>
Co-authored-by: kamkm <99585688+Kamkmgamer@users.noreply.github.com>
Signed-off-by: Yordis Prieto <yordis.prieto@gmail.com>
2026-10-02 12:22:22 -07:00

180 lines
5.8 KiB
TypeScript

import { describe, expect, it } from "@effect/vitest";
import * as Schema from "effect/Schema";
import {
AcpRegistryImportSessionInput,
AcpRegistryManagedBinaryUninstallInput,
AcpRegistryManagedBinaryUninstallResult,
AcpRegistryOperationError,
AcpRegistryPrepareResult,
AcpRegistryProbeResult,
AcpRegistrySearchAgent,
AcpRegistrySearchInput,
officialAcpRegistryIconUrlForAgentId,
resolveOfficialAcpRegistryIconUrl,
} from "./acpRegistry.ts";
const decodeSearchInput = Schema.decodeUnknownSync(AcpRegistrySearchInput);
const decodeImportSessionInput = Schema.decodeUnknownSync(AcpRegistryImportSessionInput);
const decodePrepareResult = Schema.decodeUnknownSync(AcpRegistryPrepareResult);
const decodeSearchAgent = Schema.decodeUnknownSync(AcpRegistrySearchAgent);
const decodeUninstallInput = Schema.decodeUnknownSync(AcpRegistryManagedBinaryUninstallInput);
const decodeUninstallResult = Schema.decodeUnknownSync(AcpRegistryManagedBinaryUninstallResult);
const decodeProbeResult = Schema.decodeUnknownSync(AcpRegistryProbeResult);
const decodeOperationError = Schema.decodeUnknownSync(AcpRegistryOperationError);
describe("ACP Registry contracts", () => {
it("accepts only official Registry icon URLs and safe agent IDs", () => {
expect(officialAcpRegistryIconUrlForAgentId("antigravity-acp")).toBe(
"https://cdn.agentclientprotocol.com/registry/v1/latest/antigravity-acp.svg",
);
expect(officialAcpRegistryIconUrlForAgentId("../antigravity-acp")).toBeNull();
expect(
resolveOfficialAcpRegistryIconUrl(
"https://cdn.agentclientprotocol.com/registry/v1/latest/pi-acp.svg",
),
).toBe("https://cdn.agentclientprotocol.com/registry/v1/latest/pi-acp.svg");
expect(
resolveOfficialAcpRegistryIconUrl(
"https://cdn.agentclientprotocol.com.evil/registry/v1/latest/pi-acp.svg",
),
).toBeNull();
expect(
resolveOfficialAcpRegistryIconUrl(
"https://user@cdn.agentclientprotocol.com/registry/v1/latest/pi-acp.svg",
),
).toBeNull();
});
it("decodes bounded search and prepare payloads", () => {
expect(decodeSearchInput({ query: " codex " })).toEqual({
query: "codex",
});
expect(
decodePrepareResult({
agentId: "codex-acp",
version: "1.2.0",
distribution: "npx",
prepared: true,
}),
).toMatchObject({ agentId: "codex-acp", distribution: "npx", prepared: true });
});
it("rejects oversized queries and result metadata", () => {
expect(() => decodeSearchInput({ query: "x".repeat(121) })).toThrow();
expect(() =>
decodeSearchAgent({
id: "agent",
name: "Agent",
version: "1.0.0",
description: "x".repeat(1_025),
authors: [],
license: null,
website: null,
repository: null,
icon: null,
distribution: "binary",
integrity: "sha256",
}),
).toThrow();
});
it("decodes managed binary uninstall payloads and rejects unsafe agent IDs", () => {
expect(decodeUninstallInput({ agentId: " example-agent " })).toEqual({
agentId: "example-agent",
});
expect(decodeUninstallResult({ agentId: "example-agent", removed: false })).toEqual({
agentId: "example-agent",
removed: false,
});
expect(() => decodeUninstallInput({ agentId: "../example-agent" })).toThrow();
});
it("decodes bounded native session import metadata", () => {
expect(
decodeImportSessionInput({
instanceId: "acpRegistry_example",
projectId: "project-1",
sessionId: "native-session-1",
title: " Native session ",
updatedAt: " 2026-08-23T00:00:00Z ",
}),
).toEqual({
instanceId: "acpRegistry_example",
projectId: "project-1",
sessionId: "native-session-1",
title: "Native session",
updatedAt: "2026-08-23T00:00:00Z",
});
expect(() =>
decodeImportSessionInput({
instanceId: "acpRegistry_example",
projectId: "project-1",
sessionId: "native-session-1",
title: "x".repeat(1_025),
}),
).toThrow();
});
it("decodes valid probe metadata and rejects oversized or invalid payloads", () => {
const authMethod = {
id: "oauth",
name: "Browser login",
description: null,
type: "agent",
};
expect(
decodeProbeResult({
instanceId: "acpRegistry_example",
ready: true,
icon: null,
authMethods: [authMethod],
models: [{ id: "default", name: "Default", description: "Agent-selected model" }],
currentModelId: "default",
configOptions: [],
}),
).toMatchObject({ ready: true, currentModelId: "default" });
expect(() =>
decodeProbeResult({
instanceId: "acpRegistry_example",
ready: true,
icon: null,
authMethods: Array.from({ length: 33 }, () => authMethod),
models: [],
currentModelId: null,
}),
).toThrow();
expect(() =>
decodeProbeResult({
instanceId: "acpRegistry_example",
ready: true,
icon: null,
authMethods: [{ ...authMethod, type: "passive" }],
models: [],
currentModelId: null,
}),
).toThrow();
expect(() =>
decodeProbeResult({
instanceId: "acpRegistry_example",
ready: true,
icon: null,
authMethods: [],
models: Array.from({ length: 257 }, () => ({
id: "default",
name: "Default",
description: null,
})),
currentModelId: null,
}),
).toThrow();
expect(() =>
decodeOperationError({
_tag: "AcpRegistryOperationError",
reason: "authentication_failed",
message: "Authentication required.",
authMethods: Array.from({ length: 33 }, () => authMethod),
}),
).toThrow();
});
});