8a0903ebf2
The root barrel is now core-only and side-effect free: types, createModels/createProvider, auth substrate, lazyStream/lazyApi, faux, utils. Generated catalogs, api-registry, env-api-keys, images, global stream functions, and per-API lazy wrappers leave the root. New @earendil-works/pi-ai/compat preserves the old surface verbatim as a strict superset of the root: api-dispatch stream/complete with env key injection, the builtin registration side effect (skip-if-present so it cannot clobber earlier overrides), deprecated getModel/getModels/ getProviders aliases of the new getBuiltin* reads in providers/all, lazy api wrappers + setBedrockProviderModule, and image generation. Compat dies with the coding-agent ModelManager migration. Packaging: exports map gains ./compat, ./providers/*, ./api/*; sideEffects array lists only the effectful modules. Old-global imports across agent/coding-agent/examples and pi-ai tests switch to /compat (path-only; compat is a superset). The coding-agent extension loader resolves the pi-ai ROOT specifier to compat, so existing user extensions using the old global API keep working at runtime until compat is removed. vitest configs alias /compat to src; browser smoke imports old globals from /compat.
151 lines
5.5 KiB
TypeScript
151 lines
5.5 KiB
TypeScript
/**
|
|
* Temporary compatibility entrypoint preserving the old global pi-ai API
|
|
* surface: api-dispatch `stream()`/`complete()` with env API key injection,
|
|
* the api-registry, generated catalog reads (`getModel`/`getModels`/
|
|
* `getProviders`), per-API lazy stream wrappers, and image generation.
|
|
*
|
|
* Existing apps switch imports from "@earendil-works/pi-ai" to
|
|
* "@earendil-works/pi-ai/compat" unchanged; new code uses `createModels()`
|
|
* and the provider factories. This module is deleted with the coding-agent
|
|
* ModelManager migration.
|
|
*/
|
|
|
|
export * from "./api/anthropic-messages.lazy.ts";
|
|
export * from "./api/azure-openai-responses.lazy.ts";
|
|
export * from "./api/bedrock-converse-stream.lazy.ts";
|
|
export * from "./api/google-generative-ai.lazy.ts";
|
|
export * from "./api/google-vertex.lazy.ts";
|
|
export * from "./api/mistral-conversations.lazy.ts";
|
|
export * from "./api/openai-codex-responses.lazy.ts";
|
|
export * from "./api/openai-completions.lazy.ts";
|
|
export * from "./api/openai-responses.lazy.ts";
|
|
export * from "./api-registry.ts";
|
|
export * from "./env-api-keys.ts";
|
|
export * from "./image-models.ts";
|
|
export * from "./images.ts";
|
|
export * from "./images-api-registry.ts";
|
|
export * from "./index.ts";
|
|
export * from "./providers/images/register-builtins.ts";
|
|
|
|
import { anthropicMessagesApi } from "./api/anthropic-messages.lazy.ts";
|
|
import { azureOpenAIResponsesApi } from "./api/azure-openai-responses.lazy.ts";
|
|
import { bedrockConverseStreamApi } from "./api/bedrock-converse-stream.lazy.ts";
|
|
import { googleGenerativeAIApi } from "./api/google-generative-ai.lazy.ts";
|
|
import { googleVertexApi } from "./api/google-vertex.lazy.ts";
|
|
import { mistralConversationsApi } from "./api/mistral-conversations.lazy.ts";
|
|
import { openAICodexResponsesApi } from "./api/openai-codex-responses.lazy.ts";
|
|
import { openAICompletionsApi } from "./api/openai-completions.lazy.ts";
|
|
import { openAIResponsesApi } from "./api/openai-responses.lazy.ts";
|
|
import { clearApiProviders, getApiProvider, registerApiProvider } from "./api-registry.ts";
|
|
import { getEnvApiKey } from "./env-api-keys.ts";
|
|
import { getBuiltinModel, getBuiltinModels, getBuiltinProviders } from "./providers/all.ts";
|
|
import type {
|
|
Api,
|
|
AssistantMessage,
|
|
AssistantMessageEventStream,
|
|
Context,
|
|
Model,
|
|
ProviderStreamOptions,
|
|
ProviderStreams,
|
|
SimpleStreamOptions,
|
|
StreamOptions,
|
|
} from "./types.ts";
|
|
|
|
/** @deprecated Static catalog read. Use `getBuiltinModel` from "@earendil-works/pi-ai/providers/all" or `Models.getModel()`. */
|
|
export const getModel = getBuiltinModel;
|
|
|
|
/** @deprecated Static catalog read. Use `getBuiltinModels` from "@earendil-works/pi-ai/providers/all" or `Models.getModels()`. */
|
|
export const getModels = getBuiltinModels;
|
|
|
|
/** @deprecated Static catalog read. Use `getBuiltinProviders` from "@earendil-works/pi-ai/providers/all" or `Models.getProviders()`. */
|
|
export const getProviders = getBuiltinProviders;
|
|
|
|
const BUILTIN_APIS: [Api, ProviderStreams][] = [
|
|
["anthropic-messages", anthropicMessagesApi()],
|
|
["openai-completions", openAICompletionsApi()],
|
|
["openai-responses", openAIResponsesApi()],
|
|
["openai-codex-responses", openAICodexResponsesApi()],
|
|
["azure-openai-responses", azureOpenAIResponsesApi()],
|
|
["google-generative-ai", googleGenerativeAIApi()],
|
|
["google-vertex", googleVertexApi()],
|
|
["mistral-conversations", mistralConversationsApi()],
|
|
["bedrock-converse-stream", bedrockConverseStreamApi()],
|
|
];
|
|
|
|
/**
|
|
* Registers the builtin API implementations into the api-registry without
|
|
* clobbering existing entries: compat may load after a test or extension has
|
|
* already registered an override for a builtin api id.
|
|
*/
|
|
export function registerBuiltInApiProviders(): void {
|
|
for (const [api, streams] of BUILTIN_APIS) {
|
|
if (getApiProvider(api)) continue;
|
|
registerApiProvider({ api, stream: streams.stream, streamSimple: streams.streamSimple });
|
|
}
|
|
}
|
|
|
|
export function resetApiProviders(): void {
|
|
clearApiProviders();
|
|
registerBuiltInApiProviders();
|
|
}
|
|
|
|
registerBuiltInApiProviders();
|
|
|
|
function hasExplicitApiKey(apiKey: string | undefined): apiKey is string {
|
|
return typeof apiKey === "string" && apiKey.trim().length > 0;
|
|
}
|
|
|
|
function withEnvApiKey<TOptions extends StreamOptions>(
|
|
model: Model<Api>,
|
|
options: TOptions | undefined,
|
|
): TOptions | undefined {
|
|
if (hasExplicitApiKey(options?.apiKey)) return options;
|
|
const apiKey = getEnvApiKey(model.provider);
|
|
if (!apiKey) return options;
|
|
return { ...options, apiKey } as TOptions;
|
|
}
|
|
|
|
function resolveApiProvider(api: Api) {
|
|
const provider = getApiProvider(api);
|
|
if (!provider) {
|
|
throw new Error(`No API provider registered for api: ${api}`);
|
|
}
|
|
return provider;
|
|
}
|
|
|
|
export function stream<TApi extends Api>(
|
|
model: Model<TApi>,
|
|
context: Context,
|
|
options?: ProviderStreamOptions,
|
|
): AssistantMessageEventStream {
|
|
const provider = resolveApiProvider(model.api);
|
|
return provider.stream(model, context, withEnvApiKey(model, options) as StreamOptions);
|
|
}
|
|
|
|
export async function complete<TApi extends Api>(
|
|
model: Model<TApi>,
|
|
context: Context,
|
|
options?: ProviderStreamOptions,
|
|
): Promise<AssistantMessage> {
|
|
const s = stream(model, context, options);
|
|
return s.result();
|
|
}
|
|
|
|
export function streamSimple<TApi extends Api>(
|
|
model: Model<TApi>,
|
|
context: Context,
|
|
options?: SimpleStreamOptions,
|
|
): AssistantMessageEventStream {
|
|
const provider = resolveApiProvider(model.api);
|
|
return provider.streamSimple(model, context, withEnvApiKey(model, options));
|
|
}
|
|
|
|
export async function completeSimple<TApi extends Api>(
|
|
model: Model<TApi>,
|
|
context: Context,
|
|
options?: SimpleStreamOptions,
|
|
): Promise<AssistantMessage> {
|
|
const s = streamSimple(model, context, options);
|
|
return s.result();
|
|
}
|