|
|
@@ -62,7 +62,9 @@ export interface CreateModelRuntimeOptions {
|
|
|
|
modelsPath?: string | null;
|
|
|
|
modelsPath?: string | null;
|
|
|
|
modelsStore?: ModelsStore;
|
|
|
|
modelsStore?: ModelsStore;
|
|
|
|
modelsStorePath?: string;
|
|
|
|
modelsStorePath?: string;
|
|
|
|
|
|
|
|
/** Allow create() to refresh model catalogs over the network. Defaults to false. */
|
|
|
|
allowModelNetwork?: boolean;
|
|
|
|
allowModelNetwork?: boolean;
|
|
|
|
|
|
|
|
/** Timeout for the create-time network model refresh. */
|
|
|
|
modelRefreshTimeoutMs?: number;
|
|
|
|
modelRefreshTimeoutMs?: number;
|
|
|
|
catalogBaseUrl?: string;
|
|
|
|
catalogBaseUrl?: string;
|
|
|
|
}
|
|
|
|
}
|
|
|
@@ -98,7 +100,7 @@ export class ModelRuntime implements Models {
|
|
|
|
private readonly extensionProviders = new Map<string, ProviderConfigInput>();
|
|
|
|
private readonly extensionProviders = new Map<string, ProviderConfigInput>();
|
|
|
|
private readonly compositionErrors = new Map<string, string>();
|
|
|
|
private readonly compositionErrors = new Map<string, string>();
|
|
|
|
private readonly modelsPath: string | undefined;
|
|
|
|
private readonly modelsPath: string | undefined;
|
|
|
|
private readonly allowModelNetwork: boolean;
|
|
|
|
private readonly modelNetworkEnabled: boolean;
|
|
|
|
private config: ModelConfig;
|
|
|
|
private config: ModelConfig;
|
|
|
|
private snapshot: ModelRuntimeSnapshot = {
|
|
|
|
private snapshot: ModelRuntimeSnapshot = {
|
|
|
|
all: [],
|
|
|
|
all: [],
|
|
|
@@ -116,12 +118,12 @@ export class ModelRuntime implements Models {
|
|
|
|
modelsPath: string | undefined,
|
|
|
|
modelsPath: string | undefined,
|
|
|
|
modelsStore: ModelsStore,
|
|
|
|
modelsStore: ModelsStore,
|
|
|
|
providers: readonly Provider[],
|
|
|
|
providers: readonly Provider[],
|
|
|
|
allowModelNetwork: boolean,
|
|
|
|
modelNetworkEnabled: boolean,
|
|
|
|
) {
|
|
|
|
) {
|
|
|
|
this.credentials = credentials;
|
|
|
|
this.credentials = credentials;
|
|
|
|
this.config = config;
|
|
|
|
this.config = config;
|
|
|
|
this.modelsPath = modelsPath;
|
|
|
|
this.modelsPath = modelsPath;
|
|
|
|
this.allowModelNetwork = allowModelNetwork;
|
|
|
|
this.modelNetworkEnabled = modelNetworkEnabled;
|
|
|
|
this.defaultBuiltins = new Map(providers.map((provider) => [provider.id, provider]));
|
|
|
|
this.defaultBuiltins = new Map(providers.map((provider) => [provider.id, provider]));
|
|
|
|
for (const [providerId, provider] of this.defaultBuiltins) this.builtins.set(providerId, provider);
|
|
|
|
for (const [providerId, provider] of this.defaultBuiltins) this.builtins.set(providerId, provider);
|
|
|
|
this.models = createModels({ credentials, modelsStore });
|
|
|
|
this.models = createModels({ credentials, modelsStore });
|
|
|
@@ -149,16 +151,17 @@ export class ModelRuntime implements Models {
|
|
|
|
modelsPath,
|
|
|
|
modelsPath,
|
|
|
|
modelsStore,
|
|
|
|
modelsStore,
|
|
|
|
providers,
|
|
|
|
providers,
|
|
|
|
options.allowModelNetwork ?? process.env.PI_OFFLINE === undefined,
|
|
|
|
process.env.PI_OFFLINE === undefined,
|
|
|
|
);
|
|
|
|
);
|
|
|
|
runtime.configureRadiusProviders();
|
|
|
|
runtime.configureRadiusProviders();
|
|
|
|
runtime.rebuildProviders();
|
|
|
|
runtime.rebuildProviders();
|
|
|
|
const controller = new AbortController();
|
|
|
|
const refreshFromNetwork = runtime.modelNetworkEnabled && options.allowModelNetwork === true;
|
|
|
|
const timeout = runtime.allowModelNetwork
|
|
|
|
const controller = refreshFromNetwork ? new AbortController() : undefined;
|
|
|
|
|
|
|
|
const timeout = controller
|
|
|
|
? setTimeout(() => controller.abort(), options.modelRefreshTimeoutMs ?? 15_000)
|
|
|
|
? setTimeout(() => controller.abort(), options.modelRefreshTimeoutMs ?? 15_000)
|
|
|
|
: undefined;
|
|
|
|
: undefined;
|
|
|
|
try {
|
|
|
|
try {
|
|
|
|
await runtime.refresh({ allowNetwork: runtime.allowModelNetwork, signal: controller.signal });
|
|
|
|
await runtime.refresh({ allowNetwork: refreshFromNetwork, signal: controller?.signal });
|
|
|
|
} finally {
|
|
|
|
} finally {
|
|
|
|
if (timeout) clearTimeout(timeout);
|
|
|
|
if (timeout) clearTimeout(timeout);
|
|
|
|
}
|
|
|
|
}
|
|
|
@@ -389,7 +392,11 @@ export class ModelRuntime implements Models {
|
|
|
|
};
|
|
|
|
};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
async setRuntimeApiKey(providerId: string, apiKey: string): Promise<void> {
|
|
|
|
async setRuntimeApiKey(
|
|
|
|
|
|
|
|
providerId: string,
|
|
|
|
|
|
|
|
apiKey: string,
|
|
|
|
|
|
|
|
refreshOptions: ModelsRefreshOptions = {},
|
|
|
|
|
|
|
|
): Promise<void> {
|
|
|
|
this.credentials.setRuntimeApiKey(providerId, apiKey);
|
|
|
|
this.credentials.setRuntimeApiKey(providerId, apiKey);
|
|
|
|
const auth = new Map(this.snapshot.auth).set(providerId, { type: "api_key", source: "runtime API key" });
|
|
|
|
const auth = new Map(this.snapshot.auth).set(providerId, { type: "api_key", source: "runtime API key" });
|
|
|
|
const configuredProviders = new Set(this.snapshot.configuredProviders).add(providerId);
|
|
|
|
const configuredProviders = new Set(this.snapshot.configuredProviders).add(providerId);
|
|
|
@@ -401,12 +408,12 @@ export class ModelRuntime implements Models {
|
|
|
|
storedProviders,
|
|
|
|
storedProviders,
|
|
|
|
available: this.snapshot.all.filter((model) => configuredProviders.has(model.provider)),
|
|
|
|
available: this.snapshot.all.filter((model) => configuredProviders.has(model.provider)),
|
|
|
|
};
|
|
|
|
};
|
|
|
|
await this.refresh({ allowNetwork: this.allowModelNetwork });
|
|
|
|
await this.refresh(refreshOptions);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
async removeRuntimeApiKey(providerId: string): Promise<void> {
|
|
|
|
async removeRuntimeApiKey(providerId: string): Promise<void> {
|
|
|
|
this.credentials.removeRuntimeApiKey(providerId);
|
|
|
|
this.credentials.removeRuntimeApiKey(providerId);
|
|
|
|
await this.refresh({ allowNetwork: this.allowModelNetwork });
|
|
|
|
await this.refresh({ allowNetwork: this.modelNetworkEnabled });
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
listCredentials(): Promise<readonly CredentialInfo[]> {
|
|
|
|
listCredentials(): Promise<readonly CredentialInfo[]> {
|
|
|
@@ -492,7 +499,7 @@ export class ModelRuntime implements Models {
|
|
|
|
|
|
|
|
|
|
|
|
async login(providerId: string, type: AuthType, interaction: AuthInteraction): Promise<Credential> {
|
|
|
|
async login(providerId: string, type: AuthType, interaction: AuthInteraction): Promise<Credential> {
|
|
|
|
const credential = await this.models.login(providerId, type, interaction);
|
|
|
|
const credential = await this.models.login(providerId, type, interaction);
|
|
|
|
await this.refresh({ allowNetwork: this.allowModelNetwork });
|
|
|
|
await this.refresh({ allowNetwork: this.modelNetworkEnabled });
|
|
|
|
return credential;
|
|
|
|
return credential;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@@ -500,20 +507,20 @@ export class ModelRuntime implements Models {
|
|
|
|
await this.models.logout(providerId);
|
|
|
|
await this.models.logout(providerId);
|
|
|
|
// Reset credential-dependent compatibility projections before the unconfigured provider is skipped by refresh.
|
|
|
|
// Reset credential-dependent compatibility projections before the unconfigured provider is skipped by refresh.
|
|
|
|
this.recomposeProvider(providerId);
|
|
|
|
this.recomposeProvider(providerId);
|
|
|
|
await this.refresh({ allowNetwork: this.allowModelNetwork });
|
|
|
|
await this.refresh({ allowNetwork: this.modelNetworkEnabled });
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
async reloadConfig(): Promise<void> {
|
|
|
|
async reloadConfig(): Promise<void> {
|
|
|
|
this.config = await ModelConfig.load(this.modelsPath);
|
|
|
|
this.config = await ModelConfig.load(this.modelsPath);
|
|
|
|
this.configureRadiusProviders();
|
|
|
|
this.configureRadiusProviders();
|
|
|
|
this.rebuildProviders();
|
|
|
|
this.rebuildProviders();
|
|
|
|
await this.refresh({ allowNetwork: this.allowModelNetwork });
|
|
|
|
await this.refresh({ allowNetwork: this.modelNetworkEnabled });
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
async refresh(options: ModelsRefreshOptions = {}): Promise<ModelsRefreshResult> {
|
|
|
|
async refresh(options: ModelsRefreshOptions = {}): Promise<ModelsRefreshResult> {
|
|
|
|
const refreshOptions = {
|
|
|
|
const refreshOptions = {
|
|
|
|
...options,
|
|
|
|
...options,
|
|
|
|
allowNetwork: options.allowNetwork ?? this.allowModelNetwork,
|
|
|
|
allowNetwork: options.allowNetwork ?? this.modelNetworkEnabled,
|
|
|
|
};
|
|
|
|
};
|
|
|
|
// Published pi-ai builds before ModelsStore returned void and accepted a provider ID.
|
|
|
|
// Published pi-ai builds before ModelsStore returned void and accepted a provider ID.
|
|
|
|
// The fallback keeps source-mode CLI tests working without rebuilding workspace dependencies.
|
|
|
|
// The fallback keeps source-mode CLI tests working without rebuilding workspace dependencies.
|
|
|
|