feat: move goose2 provider catalog behind ACP layer (#9030)
Signed-off-by: Kalvin Chau <kalvin@block.xyz> Signed-off-by: Matt Toohey <contact@matttoohey.com> Co-authored-by: Matt Toohey <contact@matttoohey.com>
This commit is contained in:
@@ -0,0 +1,29 @@
|
||||
import { beforeEach, describe, expect, it } from "vitest";
|
||||
import { useProviderCatalogStore } from "@/features/providers/stores/providerCatalogStore";
|
||||
import { discoverAcpProvidersFromEntries } from "../acp";
|
||||
|
||||
describe("discoverAcpProvidersFromEntries", () => {
|
||||
beforeEach(() => {
|
||||
useProviderCatalogStore.getState().reset();
|
||||
});
|
||||
|
||||
it("preserves agent inventory entries when the setup catalog has not loaded", () => {
|
||||
expect(
|
||||
discoverAcpProvidersFromEntries([
|
||||
{
|
||||
providerId: "codex-acp",
|
||||
providerName: "Codex",
|
||||
category: "agent",
|
||||
},
|
||||
{
|
||||
providerId: "openai",
|
||||
providerName: "OpenAI",
|
||||
category: "model",
|
||||
},
|
||||
]),
|
||||
).toEqual([
|
||||
{ id: "goose", label: "Goose" },
|
||||
{ id: "codex-acp", label: "Codex" },
|
||||
]);
|
||||
});
|
||||
});
|
||||
@@ -44,7 +44,7 @@ export async function discoverAcpProviders(): Promise<AcpProvider[]> {
|
||||
* avoiding a duplicate `_goose/providers/list` RPC.
|
||||
*/
|
||||
export function discoverAcpProvidersFromEntries(
|
||||
entries: Array<{ providerId: string; providerName: string }>,
|
||||
entries: Parameters<typeof directAcp.buildProviderListFromEntries>[0],
|
||||
): AcpProvider[] {
|
||||
return resolveProvidersCatalog(
|
||||
directAcp.buildProviderListFromEntries(entries),
|
||||
@@ -60,13 +60,14 @@ function resolveProvidersCatalog(providers: AcpProvider[]): AcpProvider[] {
|
||||
provider.id,
|
||||
provider.label,
|
||||
);
|
||||
if (!catalogId || seen.has(catalogId)) {
|
||||
const resolvedId = catalogId ?? provider.id;
|
||||
if (seen.has(resolvedId)) {
|
||||
return null;
|
||||
}
|
||||
seen.add(catalogId);
|
||||
seen.add(resolvedId);
|
||||
return {
|
||||
id: catalogId,
|
||||
label: getCatalogEntry(catalogId)?.displayName ?? provider.label,
|
||||
id: resolvedId,
|
||||
label: getCatalogEntry(resolvedId)?.displayName ?? provider.label,
|
||||
};
|
||||
})
|
||||
.filter((provider): provider is AcpProvider => provider !== null);
|
||||
|
||||
@@ -5,6 +5,7 @@ import type {
|
||||
PromptResponse,
|
||||
SessionInfo,
|
||||
} from "@agentclientprotocol/sdk";
|
||||
import type { ProviderInventoryEntryDto } from "@aaif/goose-sdk";
|
||||
import { getClient } from "./acpConnection";
|
||||
import { perfLog } from "@/shared/lib/perfLog";
|
||||
|
||||
@@ -46,12 +47,15 @@ export const DEFAULT_PROVIDER: AcpProvider = {
|
||||
* already-fetched entries at startup).
|
||||
*/
|
||||
export function buildProviderListFromEntries(
|
||||
entries: Array<{ providerId: string; providerName: string }>,
|
||||
entries: Array<
|
||||
Pick<ProviderInventoryEntryDto, "providerId" | "providerName" | "category">
|
||||
>,
|
||||
): AcpProvider[] {
|
||||
return [
|
||||
DEFAULT_PROVIDER,
|
||||
...entries
|
||||
.filter((entry) => !DEPRECATED_PROVIDER_IDS.has(entry.providerId))
|
||||
.filter((entry) => entry.category === "agent")
|
||||
.map((entry) => ({ id: entry.providerId, label: entry.providerName })),
|
||||
];
|
||||
}
|
||||
|
||||
@@ -332,6 +332,9 @@
|
||||
"useTemplateDescription": "Start with endpoint and model defaults for a known provider."
|
||||
}
|
||||
},
|
||||
"catalog": {
|
||||
"loading": "Loading provider catalog..."
|
||||
},
|
||||
"disconnect": "Disconnect",
|
||||
"models": {
|
||||
"description": "AI models power your agents. Goose requires one to work, but some agents bring their own.",
|
||||
|
||||
@@ -332,6 +332,9 @@
|
||||
"useTemplateDescription": "Comienza con valores predeterminados de endpoint y modelos para un proveedor conocido."
|
||||
}
|
||||
},
|
||||
"catalog": {
|
||||
"loading": "Cargando catálogo de proveedores..."
|
||||
},
|
||||
"disconnect": "Desconectar",
|
||||
"models": {
|
||||
"description": "Necesitas al menos un proveedor de modelos para usar el agente Goose. Algunos agentes pueden traer sus propias conexiones de modelo.",
|
||||
|
||||
@@ -1,26 +1,15 @@
|
||||
export type ProviderCategory = "agent" | "model";
|
||||
import type {
|
||||
ProviderSetupCatalogEntryDto,
|
||||
ProviderSetupCategoryDto,
|
||||
ProviderSetupFieldDto,
|
||||
ProviderSetupMethodDto,
|
||||
ProviderSetupGroupDto,
|
||||
} from "@aaif/goose-sdk";
|
||||
|
||||
export type ProviderSetupMethod =
|
||||
| "none"
|
||||
| "single_api_key"
|
||||
| "config_fields"
|
||||
| "host_with_oauth_fallback"
|
||||
| "oauth_browser"
|
||||
| "oauth_device_code"
|
||||
| "cloud_credentials"
|
||||
| "local"
|
||||
| "cli_auth";
|
||||
|
||||
export type ProviderTier = "promoted" | "standard" | "advanced";
|
||||
|
||||
export interface ProviderField {
|
||||
key: string;
|
||||
label: string;
|
||||
secret: boolean;
|
||||
required: boolean;
|
||||
placeholder?: string;
|
||||
defaultValue?: string;
|
||||
}
|
||||
export type ProviderCategory = ProviderSetupCategoryDto;
|
||||
export type ProviderSetupMethod = ProviderSetupMethodDto;
|
||||
export type ProviderGroup = ProviderSetupGroupDto;
|
||||
export type ProviderField = ProviderSetupFieldDto;
|
||||
|
||||
export interface ProviderFieldValue {
|
||||
key: string;
|
||||
@@ -30,23 +19,30 @@ export interface ProviderFieldValue {
|
||||
required: boolean;
|
||||
}
|
||||
|
||||
export interface ProviderCatalogEntry {
|
||||
export type ProviderCatalogEntry = Omit<
|
||||
ProviderSetupCatalogEntryDto,
|
||||
| "providerId"
|
||||
| "name"
|
||||
| "nativeConnectQuery"
|
||||
| "binaryName"
|
||||
| "docUrl"
|
||||
| "showOnlyWhenInstalled"
|
||||
| "supportsInstall"
|
||||
| "supportsAuth"
|
||||
| "supportsAuthStatus"
|
||||
> & {
|
||||
id: string;
|
||||
displayName: string;
|
||||
category: ProviderCategory;
|
||||
description: string;
|
||||
setupMethod: ProviderSetupMethod;
|
||||
nativeConnectQuery?: string;
|
||||
envVar?: string;
|
||||
fields?: ProviderField[];
|
||||
binaryName?: string;
|
||||
installCommand?: string;
|
||||
authCommand?: string;
|
||||
authStatusCommand?: string;
|
||||
docsUrl?: string;
|
||||
tier: ProviderTier;
|
||||
showOnlyWhenInstalled?: boolean;
|
||||
}
|
||||
nativeConnectQuery?: NonNullable<
|
||||
ProviderSetupCatalogEntryDto["nativeConnectQuery"]
|
||||
>;
|
||||
binaryName?: NonNullable<ProviderSetupCatalogEntryDto["binaryName"]>;
|
||||
docsUrl?: NonNullable<ProviderSetupCatalogEntryDto["docUrl"]>;
|
||||
showOnlyWhenInstalled?: ProviderSetupCatalogEntryDto["showOnlyWhenInstalled"];
|
||||
supportsInstall?: ProviderSetupCatalogEntryDto["supportsInstall"];
|
||||
supportsAuth?: ProviderSetupCatalogEntryDto["supportsAuth"];
|
||||
supportsAuthStatus?: ProviderSetupCatalogEntryDto["supportsAuthStatus"];
|
||||
};
|
||||
|
||||
export type ProviderSetupStatus =
|
||||
| "built_in"
|
||||
|
||||
Reference in New Issue
Block a user