consolidate provider ACP methods onto inventory (#8710)
Signed-off-by: Bradley Axen <baxen@squareup.com>
This commit is contained in:
@@ -10,7 +10,7 @@ export async function getProviderInventory(
|
||||
): Promise<ProviderInventoryEntryDto[]> {
|
||||
const client = await getClient();
|
||||
const t0 = performance.now();
|
||||
const response = await client.goose.GooseProvidersInventory({ providerIds });
|
||||
const response = await client.goose.GooseProvidersList({ providerIds });
|
||||
perfLog(
|
||||
`[perf:inventory] getProviderInventory done in ${(performance.now() - t0).toFixed(1)}ms (n=${response.entries.length})`,
|
||||
);
|
||||
|
||||
@@ -20,16 +20,25 @@ export interface AcpSessionInfo {
|
||||
}
|
||||
|
||||
const DEPRECATED_PROVIDER_IDS = new Set(["claude-code", "codex", "gemini-cli"]);
|
||||
const DEFAULT_PROVIDER: AcpProvider = {
|
||||
id: "goose",
|
||||
label: "Goose (Default)",
|
||||
};
|
||||
|
||||
export async function listProviders(): Promise<AcpProvider[]> {
|
||||
const client = await getClient();
|
||||
const result = await client.goose.GooseProvidersList({});
|
||||
// biome-ignore lint/suspicious/noExplicitAny: ACP SDK types don't expose providers field
|
||||
return (result as any).providers
|
||||
.filter(
|
||||
(p: { id: string; label: string }) => !DEPRECATED_PROVIDER_IDS.has(p.id),
|
||||
)
|
||||
.map((p: { id: string; label: string }) => ({ id: p.id, label: p.label }));
|
||||
const result = await client.goose.GooseProvidersList({
|
||||
providerIds: [],
|
||||
});
|
||||
|
||||
const providers = result.entries
|
||||
.filter((entry) => !DEPRECATED_PROVIDER_IDS.has(entry.providerId))
|
||||
.map((entry) => ({
|
||||
id: entry.providerId,
|
||||
label: entry.providerName,
|
||||
}));
|
||||
|
||||
return [DEFAULT_PROVIDER, ...providers];
|
||||
}
|
||||
|
||||
export async function listSessions(): Promise<AcpSessionInfo[]> {
|
||||
|
||||
@@ -126,8 +126,6 @@ export function buildInitScript(options?: {
|
||||
return jsonRpcResult(message.id, { stopReason: "end_turn" });
|
||||
}
|
||||
case "_goose/providers/list":
|
||||
return jsonRpcResult(message.id, { providers: [] });
|
||||
case "_goose/providers/inventory":
|
||||
return jsonRpcResult(message.id, { entries: [] });
|
||||
case "_goose/providers/inventory/refresh":
|
||||
return jsonRpcResult(message.id, { started: [], skipped: [] });
|
||||
|
||||
@@ -34,10 +34,6 @@ import type {
|
||||
ExportSourceResponse,
|
||||
GetExtensionsRequest,
|
||||
GetExtensionsResponse,
|
||||
GetProviderDetailsRequest,
|
||||
GetProviderDetailsResponse,
|
||||
GetProviderInventoryRequest,
|
||||
GetProviderInventoryResponse,
|
||||
GetSessionExtensionsRequest,
|
||||
GetSessionExtensionsResponse,
|
||||
GetToolsRequest,
|
||||
@@ -76,8 +72,6 @@ import {
|
||||
zExportSessionResponse,
|
||||
zExportSourceResponse,
|
||||
zGetExtensionsResponse,
|
||||
zGetProviderDetailsResponse,
|
||||
zGetProviderInventoryResponse,
|
||||
zGetSessionExtensionsResponse,
|
||||
zGetToolsResponse,
|
||||
zImportSessionResponse,
|
||||
@@ -144,22 +138,6 @@ export class GooseExtClient {
|
||||
return zListProvidersResponse.parse(raw) as ListProvidersResponse;
|
||||
}
|
||||
|
||||
async GooseProvidersDetails(
|
||||
params: GetProviderDetailsRequest,
|
||||
): Promise<GetProviderDetailsResponse> {
|
||||
const raw = await this.conn.extMethod("_goose/providers/details", params);
|
||||
return zGetProviderDetailsResponse.parse(raw) as GetProviderDetailsResponse;
|
||||
}
|
||||
|
||||
async GooseProvidersInventory(
|
||||
params: GetProviderInventoryRequest,
|
||||
): Promise<GetProviderInventoryResponse> {
|
||||
const raw = await this.conn.extMethod("_goose/providers/inventory", params);
|
||||
return zGetProviderInventoryResponse.parse(
|
||||
raw,
|
||||
) as GetProviderInventoryResponse;
|
||||
}
|
||||
|
||||
async GooseProvidersInventoryRefresh(
|
||||
params: RefreshProviderInventoryRequest,
|
||||
): Promise<RefreshProviderInventoryResponse> {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// This file is auto-generated by @hey-api/openapi-ts
|
||||
|
||||
export type { AddExtensionRequest, ArchiveSessionRequest, CheckSecretRequest, CheckSecretResponse, CreateSourceRequest, CreateSourceResponse, DeleteSessionRequest, DeleteSourceRequest, DictationConfigRequest, DictationConfigResponse, DictationDownloadProgress, DictationLocalModelStatus, DictationModelCancelRequest, DictationModelDeleteRequest, DictationModelDownloadProgressRequest, DictationModelDownloadProgressResponse, DictationModelDownloadRequest, DictationModelOption, DictationModelSelectRequest, DictationModelsListRequest, DictationModelsListResponse, DictationProviderStatusEntry, DictationTranscribeRequest, DictationTranscribeResponse, EmptyResponse, ExportSessionRequest, ExportSessionResponse, ExportSourceRequest, ExportSourceResponse, ExtRequest, ExtResponse, GetExtensionsRequest, GetExtensionsResponse, GetProviderDetailsRequest, GetProviderDetailsResponse, GetProviderInventoryRequest, GetProviderInventoryResponse, GetSessionExtensionsRequest, GetSessionExtensionsResponse, GetToolsRequest, GetToolsResponse, ImportSessionRequest, ImportSessionResponse, ImportSourcesRequest, ImportSourcesResponse, ListProvidersRequest, ListProvidersResponse, ListSourcesRequest, ListSourcesResponse, ModelEntry, ProviderConfigKey, ProviderDetailEntry, ProviderInventoryEntryDto, ProviderInventoryModelDto, ProviderListEntry, ReadConfigRequest, ReadConfigResponse, ReadResourceRequest, ReadResourceResponse, RefreshProviderInventoryRequest, RefreshProviderInventoryResponse, RefreshProviderInventorySkipDto, RefreshProviderInventorySkipReasonDto, RemoveConfigRequest, RemoveExtensionRequest, RemoveSecretRequest, SourceEntry, SourceType, UnarchiveSessionRequest, UpdateSourceRequest, UpdateSourceResponse, UpdateWorkingDirRequest, UpsertConfigRequest, UpsertSecretRequest } from './types.gen.js';
|
||||
export type { AddExtensionRequest, ArchiveSessionRequest, CheckSecretRequest, CheckSecretResponse, CreateSourceRequest, CreateSourceResponse, DeleteSessionRequest, DeleteSourceRequest, DictationConfigRequest, DictationConfigResponse, DictationDownloadProgress, DictationLocalModelStatus, DictationModelCancelRequest, DictationModelDeleteRequest, DictationModelDownloadProgressRequest, DictationModelDownloadProgressResponse, DictationModelDownloadRequest, DictationModelOption, DictationModelSelectRequest, DictationModelsListRequest, DictationModelsListResponse, DictationProviderStatusEntry, DictationTranscribeRequest, DictationTranscribeResponse, EmptyResponse, ExportSessionRequest, ExportSessionResponse, ExportSourceRequest, ExportSourceResponse, ExtRequest, ExtResponse, GetExtensionsRequest, GetExtensionsResponse, GetSessionExtensionsRequest, GetSessionExtensionsResponse, GetToolsRequest, GetToolsResponse, ImportSessionRequest, ImportSessionResponse, ImportSourcesRequest, ImportSourcesResponse, ListProvidersRequest, ListProvidersResponse, ListSourcesRequest, ListSourcesResponse, ProviderConfigKey, ProviderInventoryEntryDto, ProviderInventoryModelDto, ReadConfigRequest, ReadConfigResponse, ReadResourceRequest, ReadResourceResponse, RefreshProviderInventoryRequest, RefreshProviderInventoryResponse, RefreshProviderInventorySkipDto, RefreshProviderInventorySkipReasonDto, RemoveConfigRequest, RemoveExtensionRequest, RemoveSecretRequest, SourceEntry, SourceType, UnarchiveSessionRequest, UpdateSourceRequest, UpdateSourceResponse, UpdateWorkingDirRequest, UpsertConfigRequest, UpsertSecretRequest } from './types.gen.js';
|
||||
|
||||
export const GOOSE_EXT_METHODS = [
|
||||
{
|
||||
@@ -48,16 +48,6 @@ export const GOOSE_EXT_METHODS = [
|
||||
requestType: "ListProvidersRequest",
|
||||
responseType: "ListProvidersResponse",
|
||||
},
|
||||
{
|
||||
method: "_goose/providers/details",
|
||||
requestType: "GetProviderDetailsRequest",
|
||||
responseType: "GetProviderDetailsResponse",
|
||||
},
|
||||
{
|
||||
method: "_goose/providers/inventory",
|
||||
requestType: "GetProviderInventoryRequest",
|
||||
responseType: "GetProviderInventoryResponse",
|
||||
},
|
||||
{
|
||||
method: "_goose/providers/inventory/refresh",
|
||||
requestType: "RefreshProviderInventoryRequest",
|
||||
|
||||
@@ -105,69 +105,9 @@ export type GetSessionExtensionsResponse = {
|
||||
};
|
||||
|
||||
/**
|
||||
* List providers available through goose, including the config-default sentinel.
|
||||
* List providers with setup metadata and the current model inventory snapshot.
|
||||
*/
|
||||
export type ListProvidersRequest = {
|
||||
[key: string]: unknown;
|
||||
};
|
||||
|
||||
/**
|
||||
* Provider list response.
|
||||
*/
|
||||
export type ListProvidersResponse = {
|
||||
providers: Array<ProviderListEntry>;
|
||||
};
|
||||
|
||||
export type ProviderListEntry = {
|
||||
id: string;
|
||||
label: string;
|
||||
};
|
||||
|
||||
/**
|
||||
* List providers with full metadata (config keys, setup steps, etc.).
|
||||
*/
|
||||
export type GetProviderDetailsRequest = {
|
||||
[key: string]: unknown;
|
||||
};
|
||||
|
||||
/**
|
||||
* Provider details response.
|
||||
*/
|
||||
export type GetProviderDetailsResponse = {
|
||||
providers: Array<ProviderDetailEntry>;
|
||||
};
|
||||
|
||||
export type ProviderDetailEntry = {
|
||||
name: string;
|
||||
displayName: string;
|
||||
description: string;
|
||||
defaultModel: string;
|
||||
isConfigured: boolean;
|
||||
providerType: string;
|
||||
configKeys: Array<ProviderConfigKey>;
|
||||
setupSteps?: Array<string>;
|
||||
knownModels?: Array<ModelEntry>;
|
||||
};
|
||||
|
||||
export type ProviderConfigKey = {
|
||||
name: string;
|
||||
required: boolean;
|
||||
secret: boolean;
|
||||
default?: string | null;
|
||||
oauthFlow?: boolean;
|
||||
deviceCodeFlow?: boolean;
|
||||
primary?: boolean;
|
||||
};
|
||||
|
||||
export type ModelEntry = {
|
||||
name: string;
|
||||
contextLimit: number;
|
||||
};
|
||||
|
||||
/**
|
||||
* Read per-provider inventory. Always returns immediately from stored state.
|
||||
*/
|
||||
export type GetProviderInventoryRequest = {
|
||||
/**
|
||||
* Only return entries for these providers. Empty means all.
|
||||
*/
|
||||
@@ -175,9 +115,9 @@ export type GetProviderInventoryRequest = {
|
||||
};
|
||||
|
||||
/**
|
||||
* Provider inventory response.
|
||||
* Provider list response.
|
||||
*/
|
||||
export type GetProviderInventoryResponse = {
|
||||
export type ListProvidersResponse = {
|
||||
entries: Array<ProviderInventoryEntryDto>;
|
||||
};
|
||||
|
||||
@@ -193,10 +133,30 @@ export type ProviderInventoryEntryDto = {
|
||||
* Human-readable provider name.
|
||||
*/
|
||||
providerName: string;
|
||||
/**
|
||||
* Description of the provider's capabilities.
|
||||
*/
|
||||
description: string;
|
||||
/**
|
||||
* The default/recommended model for this provider.
|
||||
*/
|
||||
defaultModel: string;
|
||||
/**
|
||||
* Whether Goose has enough configuration to use this provider.
|
||||
*/
|
||||
configured: boolean;
|
||||
/**
|
||||
* Provider classification such as `Preferred`, `Builtin`, `Declarative`, or `Custom`.
|
||||
*/
|
||||
providerType: string;
|
||||
/**
|
||||
* Required configuration keys and setup metadata.
|
||||
*/
|
||||
configKeys: Array<ProviderConfigKey>;
|
||||
/**
|
||||
* Step-by-step setup instructions, when present.
|
||||
*/
|
||||
setupSteps: Array<string>;
|
||||
/**
|
||||
* Whether this provider supports background inventory refresh.
|
||||
*/
|
||||
@@ -231,6 +191,16 @@ export type ProviderInventoryEntryDto = {
|
||||
modelSelectionHint?: string | null;
|
||||
};
|
||||
|
||||
export type ProviderConfigKey = {
|
||||
name: string;
|
||||
required: boolean;
|
||||
secret: boolean;
|
||||
default?: string | null;
|
||||
oauthFlow?: boolean;
|
||||
deviceCodeFlow?: boolean;
|
||||
primary?: boolean;
|
||||
};
|
||||
|
||||
/**
|
||||
* A single model in provider inventory.
|
||||
*/
|
||||
@@ -648,14 +618,14 @@ export type DictationModelSelectRequest = {
|
||||
export type ExtRequest = {
|
||||
id: string;
|
||||
method: string;
|
||||
params?: AddExtensionRequest | RemoveExtensionRequest | GetToolsRequest | ReadResourceRequest | UpdateWorkingDirRequest | DeleteSessionRequest | GetExtensionsRequest | GetSessionExtensionsRequest | ListProvidersRequest | GetProviderDetailsRequest | GetProviderInventoryRequest | RefreshProviderInventoryRequest | ReadConfigRequest | UpsertConfigRequest | RemoveConfigRequest | CheckSecretRequest | UpsertSecretRequest | RemoveSecretRequest | ExportSessionRequest | ImportSessionRequest | ArchiveSessionRequest | UnarchiveSessionRequest | CreateSourceRequest | ListSourcesRequest | UpdateSourceRequest | DeleteSourceRequest | ExportSourceRequest | ImportSourcesRequest | DictationTranscribeRequest | DictationConfigRequest | DictationModelsListRequest | DictationModelDownloadRequest | DictationModelDownloadProgressRequest | DictationModelCancelRequest | DictationModelDeleteRequest | DictationModelSelectRequest | {
|
||||
params?: AddExtensionRequest | RemoveExtensionRequest | GetToolsRequest | ReadResourceRequest | UpdateWorkingDirRequest | DeleteSessionRequest | GetExtensionsRequest | GetSessionExtensionsRequest | ListProvidersRequest | RefreshProviderInventoryRequest | ReadConfigRequest | UpsertConfigRequest | RemoveConfigRequest | CheckSecretRequest | UpsertSecretRequest | RemoveSecretRequest | ExportSessionRequest | ImportSessionRequest | ArchiveSessionRequest | UnarchiveSessionRequest | CreateSourceRequest | ListSourcesRequest | UpdateSourceRequest | DeleteSourceRequest | ExportSourceRequest | ImportSourcesRequest | DictationTranscribeRequest | DictationConfigRequest | DictationModelsListRequest | DictationModelDownloadRequest | DictationModelDownloadProgressRequest | DictationModelCancelRequest | DictationModelDeleteRequest | DictationModelSelectRequest | {
|
||||
[key: string]: unknown;
|
||||
} | null;
|
||||
};
|
||||
|
||||
export type ExtResponse = {
|
||||
id: string;
|
||||
result?: EmptyResponse | GetToolsResponse | ReadResourceResponse | GetExtensionsResponse | GetSessionExtensionsResponse | ListProvidersResponse | GetProviderDetailsResponse | GetProviderInventoryResponse | RefreshProviderInventoryResponse | ReadConfigResponse | CheckSecretResponse | ExportSessionResponse | ImportSessionResponse | CreateSourceResponse | ListSourcesResponse | UpdateSourceResponse | ExportSourceResponse | ImportSourcesResponse | DictationTranscribeResponse | DictationConfigResponse | DictationModelsListResponse | DictationModelDownloadProgressResponse | unknown;
|
||||
result?: EmptyResponse | GetToolsResponse | ReadResourceResponse | GetExtensionsResponse | GetSessionExtensionsResponse | ListProvidersResponse | RefreshProviderInventoryResponse | ReadConfigResponse | CheckSecretResponse | ExportSessionResponse | ImportSessionResponse | CreateSourceResponse | ListSourcesResponse | UpdateSourceResponse | ExportSourceResponse | ImportSourcesResponse | DictationTranscribeResponse | DictationConfigResponse | DictationModelsListResponse | DictationModelDownloadProgressResponse | unknown;
|
||||
} | {
|
||||
error: {
|
||||
code: number;
|
||||
|
||||
@@ -90,27 +90,12 @@ export const zGetSessionExtensionsResponse = z.object({
|
||||
});
|
||||
|
||||
/**
|
||||
* List providers available through goose, including the config-default sentinel.
|
||||
* List providers with setup metadata and the current model inventory snapshot.
|
||||
*/
|
||||
export const zListProvidersRequest = z.record(z.unknown());
|
||||
|
||||
export const zProviderListEntry = z.object({
|
||||
id: z.string(),
|
||||
label: z.string()
|
||||
export const zListProvidersRequest = z.object({
|
||||
providerIds: z.array(z.string()).optional().default([])
|
||||
});
|
||||
|
||||
/**
|
||||
* Provider list response.
|
||||
*/
|
||||
export const zListProvidersResponse = z.object({
|
||||
providers: z.array(zProviderListEntry)
|
||||
});
|
||||
|
||||
/**
|
||||
* List providers with full metadata (config keys, setup steps, etc.).
|
||||
*/
|
||||
export const zGetProviderDetailsRequest = z.record(z.unknown());
|
||||
|
||||
export const zProviderConfigKey = z.object({
|
||||
name: z.string(),
|
||||
required: z.boolean(),
|
||||
@@ -124,37 +109,6 @@ export const zProviderConfigKey = z.object({
|
||||
primary: z.boolean().optional().default(false)
|
||||
});
|
||||
|
||||
export const zModelEntry = z.object({
|
||||
name: z.string(),
|
||||
contextLimit: z.number().int().gte(0)
|
||||
});
|
||||
|
||||
export const zProviderDetailEntry = z.object({
|
||||
name: z.string(),
|
||||
displayName: z.string(),
|
||||
description: z.string(),
|
||||
defaultModel: z.string(),
|
||||
isConfigured: z.boolean(),
|
||||
providerType: z.string(),
|
||||
configKeys: z.array(zProviderConfigKey),
|
||||
setupSteps: z.array(z.string()).optional().default([]),
|
||||
knownModels: z.array(zModelEntry).optional().default([])
|
||||
});
|
||||
|
||||
/**
|
||||
* Provider details response.
|
||||
*/
|
||||
export const zGetProviderDetailsResponse = z.object({
|
||||
providers: z.array(zProviderDetailEntry)
|
||||
});
|
||||
|
||||
/**
|
||||
* Read per-provider inventory. Always returns immediately from stored state.
|
||||
*/
|
||||
export const zGetProviderInventoryRequest = z.object({
|
||||
providerIds: z.array(z.string()).optional().default([])
|
||||
});
|
||||
|
||||
/**
|
||||
* A single model in provider inventory.
|
||||
*/
|
||||
@@ -182,7 +136,12 @@ export const zProviderInventoryModelDto = z.object({
|
||||
export const zProviderInventoryEntryDto = z.object({
|
||||
providerId: z.string(),
|
||||
providerName: z.string(),
|
||||
description: z.string(),
|
||||
defaultModel: z.string(),
|
||||
configured: z.boolean(),
|
||||
providerType: z.string(),
|
||||
configKeys: z.array(zProviderConfigKey),
|
||||
setupSteps: z.array(z.string()),
|
||||
supportsRefresh: z.boolean(),
|
||||
refreshing: z.boolean(),
|
||||
models: z.array(zProviderInventoryModelDto),
|
||||
@@ -206,9 +165,9 @@ export const zProviderInventoryEntryDto = z.object({
|
||||
});
|
||||
|
||||
/**
|
||||
* Provider inventory response.
|
||||
* Provider list response.
|
||||
*/
|
||||
export const zGetProviderInventoryResponse = z.object({
|
||||
export const zListProvidersResponse = z.object({
|
||||
entries: z.array(zProviderInventoryEntryDto)
|
||||
});
|
||||
|
||||
@@ -626,8 +585,6 @@ export const zExtRequest = z.object({
|
||||
zGetExtensionsRequest,
|
||||
zGetSessionExtensionsRequest,
|
||||
zListProvidersRequest,
|
||||
zGetProviderDetailsRequest,
|
||||
zGetProviderInventoryRequest,
|
||||
zRefreshProviderInventoryRequest,
|
||||
zReadConfigRequest,
|
||||
zUpsertConfigRequest,
|
||||
@@ -672,8 +629,6 @@ export const zExtResponse = z.union([
|
||||
zGetExtensionsResponse,
|
||||
zGetSessionExtensionsResponse,
|
||||
zListProvidersResponse,
|
||||
zGetProviderDetailsResponse,
|
||||
zGetProviderInventoryResponse,
|
||||
zRefreshProviderInventoryResponse,
|
||||
zReadConfigResponse,
|
||||
zCheckSecretResponse,
|
||||
|
||||
+25
-18
@@ -1,6 +1,6 @@
|
||||
import React, { useState, useEffect, useCallback } from "react";
|
||||
import { Box, Text, useInput, useStdout } from "ink";
|
||||
import type { GooseClient, ProviderDetailEntry } from "@aaif/goose-sdk";
|
||||
import type { GooseClient, ProviderInventoryEntryDto } from "@aaif/goose-sdk";
|
||||
import {
|
||||
CRANBERRY,
|
||||
TEAL,
|
||||
@@ -38,7 +38,7 @@ interface ConfigureProps {
|
||||
|
||||
interface ModelSelectorProps {
|
||||
client: GooseClient;
|
||||
provider: ProviderDetailEntry;
|
||||
provider: ProviderInventoryEntryDto;
|
||||
height: number;
|
||||
onSelect: (model: string) => void;
|
||||
onBack: () => void;
|
||||
@@ -74,7 +74,7 @@ const ModelSelector = React.memo(function ModelSelector({
|
||||
setLoading(true);
|
||||
setError(null);
|
||||
const resp = await client.goose.GooseProvidersModels({
|
||||
providerName: provider.name,
|
||||
providerName: provider.providerId,
|
||||
});
|
||||
if (!cancelled) {
|
||||
setModels(resp.models);
|
||||
@@ -96,7 +96,7 @@ const ModelSelector = React.memo(function ModelSelector({
|
||||
cancelled = true;
|
||||
clearTimeout(timeoutId);
|
||||
};
|
||||
}, [client, provider.name, provider.defaultModel]);
|
||||
}, [client, provider.providerId, provider.defaultModel]);
|
||||
|
||||
const filtered = (() => {
|
||||
if (!searchQuery) return models;
|
||||
@@ -190,7 +190,7 @@ const ModelSelector = React.memo(function ModelSelector({
|
||||
<Text color={TEXT_PRIMARY} bold>◆ Select model ◆</Text>
|
||||
</Box>
|
||||
<Box justifyContent="center" marginBottom={2}>
|
||||
<Text color={TEXT_DIM}>Loading models for {provider.displayName}…</Text>
|
||||
<Text color={TEXT_DIM}>Loading models for {provider.providerName}…</Text>
|
||||
</Box>
|
||||
<Box justifyContent="center" flexGrow={1} alignItems="center">
|
||||
<Spinner idx={0} />
|
||||
@@ -235,7 +235,7 @@ const ModelSelector = React.memo(function ModelSelector({
|
||||
<Text color={TEXT_PRIMARY} bold>◆ Enter model name ◆</Text>
|
||||
</Box>
|
||||
<Box justifyContent="center" marginBottom={2}>
|
||||
<Text color={TEXT_DIM}>Type a model identifier for {provider.displayName}</Text>
|
||||
<Text color={TEXT_DIM}>Type a model identifier for {provider.providerName}</Text>
|
||||
</Box>
|
||||
|
||||
<Box justifyContent="center">
|
||||
@@ -270,7 +270,7 @@ const ModelSelector = React.memo(function ModelSelector({
|
||||
<Text color={TEXT_PRIMARY} bold>◆ Select model ◆</Text>
|
||||
</Box>
|
||||
<Box justifyContent="center" marginBottom={2}>
|
||||
<Text color={TEXT_DIM}>Choose a model for {provider.displayName}</Text>
|
||||
<Text color={TEXT_DIM}>Choose a model for {provider.providerName}</Text>
|
||||
</Box>
|
||||
|
||||
{/* Search Bar */}
|
||||
@@ -359,8 +359,8 @@ export default function ConfigureScreen({
|
||||
initialIntent,
|
||||
}: ConfigureProps) {
|
||||
const [phase, setPhase] = useState<Phase>("loading");
|
||||
const [providers, setProviders] = useState<ProviderDetailEntry[]>([]);
|
||||
const [selectedProvider, setSelectedProvider] = useState<ProviderDetailEntry | null>(null);
|
||||
const [providers, setProviders] = useState<ProviderInventoryEntryDto[]>([]);
|
||||
const [selectedProvider, setSelectedProvider] = useState<ProviderInventoryEntryDto | null>(null);
|
||||
const [errorMsg, setErrorMsg] = useState("");
|
||||
const [spinIdx, setSpinIdx] = useState(0);
|
||||
const [fetchKey, setFetchKey] = useState(0);
|
||||
@@ -378,13 +378,13 @@ export default function ConfigureScreen({
|
||||
|
||||
(async () => {
|
||||
try {
|
||||
const resp = await client.goose.GooseProvidersDetails({});
|
||||
const resp = await client.goose.GooseProvidersList({ providerIds: [] });
|
||||
if (cancelled) return;
|
||||
const sorted = [...resp.providers].sort((a, b) => {
|
||||
const sorted = [...resp.entries].sort((a, b) => {
|
||||
const aP = a.providerType === "Preferred" ? 0 : 1;
|
||||
const bP = b.providerType === "Preferred" ? 0 : 1;
|
||||
if (aP !== bP) return aP - bP;
|
||||
return a.displayName.localeCompare(b.displayName);
|
||||
return a.providerName.localeCompare(b.providerName);
|
||||
});
|
||||
setProviders(sorted);
|
||||
|
||||
@@ -392,7 +392,7 @@ export default function ConfigureScreen({
|
||||
try {
|
||||
const cfg = await client.goose.GooseConfigRead({ key: "GOOSE_PROVIDER" });
|
||||
if (cancelled) return;
|
||||
const current = sorted.find((p) => p.name === cfg.value);
|
||||
const current = sorted.find((p) => p.providerId === cfg.value);
|
||||
if (current) {
|
||||
setSelectedProvider(current);
|
||||
setPendingConfigValues({});
|
||||
@@ -419,7 +419,11 @@ export default function ConfigureScreen({
|
||||
}, [client, fetchKey, initialIntent]);
|
||||
|
||||
const applyProviderModel = useCallback(
|
||||
async (provider: ProviderDetailEntry, model: string, configValues: Record<string, string>) => {
|
||||
async (
|
||||
provider: ProviderInventoryEntryDto,
|
||||
model: string,
|
||||
configValues: Record<string, string>,
|
||||
) => {
|
||||
setPhase("saving");
|
||||
try {
|
||||
for (const [key, value] of Object.entries(configValues)) {
|
||||
@@ -430,11 +434,14 @@ export default function ConfigureScreen({
|
||||
await client.goose.GooseConfigUpsert({ key, value });
|
||||
}
|
||||
}
|
||||
await client.goose.GooseConfigUpsert({ key: "GOOSE_PROVIDER", value: provider.name });
|
||||
await client.goose.GooseConfigUpsert({
|
||||
key: "GOOSE_PROVIDER",
|
||||
value: provider.providerId,
|
||||
});
|
||||
await client.goose.GooseConfigUpsert({ key: "GOOSE_MODEL", value: model });
|
||||
await client.goose.GooseSessionProviderUpdate({
|
||||
sessionId,
|
||||
provider: provider.name,
|
||||
provider: provider.providerId,
|
||||
model,
|
||||
});
|
||||
onComplete();
|
||||
@@ -449,12 +456,12 @@ export default function ConfigureScreen({
|
||||
const [pendingConfigValues, setPendingConfigValues] = useState<Record<string, string>>({});
|
||||
|
||||
const handleProviderSelected = useCallback(
|
||||
(provider: ProviderDetailEntry) => {
|
||||
(provider: ProviderInventoryEntryDto) => {
|
||||
const keys = provider.configKeys.filter(
|
||||
(k) => k.required && !k.oauthFlow && !k.deviceCodeFlow,
|
||||
);
|
||||
setSelectedProvider(provider);
|
||||
if (keys.length > 0 && !provider.isConfigured) {
|
||||
if (keys.length > 0 && !provider.configured) {
|
||||
setPhase("configure");
|
||||
} else {
|
||||
setPendingConfigValues({});
|
||||
|
||||
+26
-22
@@ -1,7 +1,7 @@
|
||||
import React, { useState, useEffect, useCallback } from "react";
|
||||
import { Box, Text, useInput, useStdout } from "ink";
|
||||
import { TextInput, PasswordInput } from '@inkjs/ui';
|
||||
import type { GooseClient, ProviderDetailEntry } from "@aaif/goose-sdk";
|
||||
import type { GooseClient, ProviderInventoryEntryDto } from "@aaif/goose-sdk";
|
||||
import {
|
||||
CRANBERRY,
|
||||
TEAL,
|
||||
@@ -30,9 +30,9 @@ interface OnboardingProps {
|
||||
}
|
||||
|
||||
export interface ProviderSelectorProps {
|
||||
providers: ProviderDetailEntry[];
|
||||
providers: ProviderInventoryEntryDto[];
|
||||
height: number;
|
||||
onSelect: (provider: ProviderDetailEntry) => void;
|
||||
onSelect: (provider: ProviderInventoryEntryDto) => void;
|
||||
title?: string;
|
||||
subtitle?: string;
|
||||
onBack?: () => void;
|
||||
@@ -49,8 +49,8 @@ export const ProviderSelector = React.memo(function ProviderSelector({ providers
|
||||
const q = searchQuery.toLowerCase();
|
||||
return providers.filter(
|
||||
(p) =>
|
||||
p.displayName.toLowerCase().includes(q) ||
|
||||
p.name.toLowerCase().includes(q),
|
||||
p.providerName.toLowerCase().includes(q) ||
|
||||
p.providerId.toLowerCase().includes(q),
|
||||
);
|
||||
})();
|
||||
|
||||
@@ -151,7 +151,11 @@ export const ProviderSelector = React.memo(function ProviderSelector({ providers
|
||||
});
|
||||
|
||||
// Create grid of provider cards
|
||||
const renderProviderCard = (provider: ProviderDetailEntry, _index: number, isSelected: boolean) => {
|
||||
const renderProviderCard = (
|
||||
provider: ProviderInventoryEntryDto,
|
||||
_index: number,
|
||||
isSelected: boolean,
|
||||
) => {
|
||||
const cardBorder = isSelected ? "double" : "single";
|
||||
const cardBorderColor = isSelected ? GOLD : RULE_COLOR;
|
||||
const textColor = isSelected ? TEXT_PRIMARY : TEXT_SECONDARY;
|
||||
@@ -166,7 +170,7 @@ export const ProviderSelector = React.memo(function ProviderSelector({ providers
|
||||
|
||||
return (
|
||||
<Box
|
||||
key={provider.name}
|
||||
key={provider.providerId}
|
||||
width={cardWidth}
|
||||
height={cardHeight}
|
||||
borderStyle={cardBorder}
|
||||
@@ -178,14 +182,14 @@ export const ProviderSelector = React.memo(function ProviderSelector({ providers
|
||||
<Box justifyContent="space-between" alignItems="center">
|
||||
<Box width={titleWidth} flexShrink={1}>
|
||||
<Text color={textColor} bold={isSelected} wrap="truncate">
|
||||
{provider.displayName}
|
||||
{provider.providerName}
|
||||
</Text>
|
||||
</Box>
|
||||
<Box flexShrink={0}>
|
||||
{provider.providerType === "Preferred" && (
|
||||
<Text color={TEAL}>★</Text>
|
||||
)}
|
||||
{provider.isConfigured && (
|
||||
{provider.configured && (
|
||||
<Text color={TEAL}>✓</Text>
|
||||
)}
|
||||
</Box>
|
||||
@@ -194,7 +198,7 @@ export const ProviderSelector = React.memo(function ProviderSelector({ providers
|
||||
<Box marginTop={1} flexDirection="column" flexGrow={1}>
|
||||
<Box width={contentWidth}>
|
||||
<Text color={TEXT_DIM} wrap="truncate">
|
||||
{provider.name}
|
||||
{provider.providerId}
|
||||
</Text>
|
||||
</Box>
|
||||
{provider.description && (
|
||||
@@ -306,7 +310,7 @@ export const ProviderSelector = React.memo(function ProviderSelector({ providers
|
||||
});
|
||||
|
||||
export interface ProviderConfiguratorProps {
|
||||
provider: ProviderDetailEntry;
|
||||
provider: ProviderInventoryEntryDto;
|
||||
height: number;
|
||||
onComplete: (values: Record<string, string>) => void;
|
||||
onBack: () => void;
|
||||
@@ -383,7 +387,7 @@ export const ProviderConfigurator = React.memo(function ProviderConfigurator({ p
|
||||
{/* Header */}
|
||||
<Box justifyContent="center" marginBottom={1}>
|
||||
<Text color={TEXT_PRIMARY} bold>
|
||||
◆ Configure {provider.displayName} ◆
|
||||
◆ Configure {provider.providerName} ◆
|
||||
</Text>
|
||||
</Box>
|
||||
{provider.description && (
|
||||
@@ -473,7 +477,7 @@ export const ProviderConfigurator = React.memo(function ProviderConfigurator({ p
|
||||
});
|
||||
|
||||
interface SuccessScreenProps {
|
||||
provider: ProviderDetailEntry | null;
|
||||
provider: ProviderInventoryEntryDto | null;
|
||||
height: number;
|
||||
}
|
||||
|
||||
@@ -501,7 +505,7 @@ const SuccessScreen = React.memo(function SuccessScreen({ provider, height }: Su
|
||||
{provider && (
|
||||
<Box marginTop={1}>
|
||||
<Text color={TEXT_SECONDARY}>
|
||||
Connected to {provider.displayName}
|
||||
Connected to {provider.providerName}
|
||||
</Text>
|
||||
</Box>
|
||||
)}
|
||||
@@ -517,9 +521,9 @@ export default function Onboarding({
|
||||
onComplete,
|
||||
}: OnboardingProps) {
|
||||
const [phase, setPhase] = useState<Phase>("loading");
|
||||
const [providers, setProviders] = useState<ProviderDetailEntry[]>([]);
|
||||
const [providers, setProviders] = useState<ProviderInventoryEntryDto[]>([]);
|
||||
const [selectedProvider, setSelectedProvider] =
|
||||
useState<ProviderDetailEntry | null>(null);
|
||||
useState<ProviderInventoryEntryDto | null>(null);
|
||||
const [errorMsg, setErrorMsg] = useState("");
|
||||
const [spinIdx, setSpinIdx] = useState(0);
|
||||
const [fetchKey, setFetchKey] = useState(0);
|
||||
@@ -535,12 +539,12 @@ export default function Onboarding({
|
||||
useEffect(() => {
|
||||
(async () => {
|
||||
try {
|
||||
const resp = await client.goose.GooseProvidersDetails({});
|
||||
const sorted = [...resp.providers].sort((a, b) => {
|
||||
const resp = await client.goose.GooseProvidersList({ providerIds: [] });
|
||||
const sorted = [...resp.entries].sort((a, b) => {
|
||||
const aP = a.providerType === "Preferred" ? 0 : 1;
|
||||
const bP = b.providerType === "Preferred" ? 0 : 1;
|
||||
if (aP !== bP) return aP - bP;
|
||||
return a.displayName.localeCompare(b.displayName);
|
||||
return a.providerName.localeCompare(b.providerName);
|
||||
});
|
||||
setProviders(sorted);
|
||||
setPhase("select_provider");
|
||||
@@ -552,7 +556,7 @@ export default function Onboarding({
|
||||
}, [client, fetchKey]);
|
||||
|
||||
const saveProvider = useCallback(
|
||||
async (provider: ProviderDetailEntry, values: Record<string, string>) => {
|
||||
async (provider: ProviderInventoryEntryDto, values: Record<string, string>) => {
|
||||
setPhase("saving");
|
||||
try {
|
||||
for (const [key, value] of Object.entries(values)) {
|
||||
@@ -565,7 +569,7 @@ export default function Onboarding({
|
||||
}
|
||||
await client.goose.GooseConfigUpsert({
|
||||
key: "GOOSE_PROVIDER",
|
||||
value: provider.name,
|
||||
value: provider.providerId,
|
||||
});
|
||||
await client.goose.GooseConfigUpsert({
|
||||
key: "GOOSE_MODEL",
|
||||
@@ -582,7 +586,7 @@ export default function Onboarding({
|
||||
);
|
||||
|
||||
const confirmProvider = useCallback(
|
||||
(provider: ProviderDetailEntry) => {
|
||||
(provider: ProviderInventoryEntryDto) => {
|
||||
const keys = provider.configKeys.filter(
|
||||
(k) => k.required && !k.oauthFlow && !k.deviceCodeFlow,
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user