mirror of
https://github.com/getcompanion-ai/co-mono.git
synced 2026-04-19 22:01:38 +00:00
feat: custom provider support with streamSimple
- Add resetApiProviders() to clear and re-register built-in providers - Add createAssistantMessageEventStream() factory for extensions - Add streamSimple support in ProviderConfig for custom API implementations - Call resetApiProviders() on /reload to clean up extension providers - Add custom-provider.md documentation - Add custom-provider.ts example with full Anthropic implementation - Update extensions.md with streamSimple config option
This commit is contained in:
parent
c06163bc59
commit
177c694406
11 changed files with 1243 additions and 69 deletions
|
|
@ -23,7 +23,7 @@ import type {
|
|||
ThinkingLevel,
|
||||
} from "@mariozechner/pi-agent-core";
|
||||
import type { AssistantMessage, ImageContent, Message, Model, TextContent } from "@mariozechner/pi-ai";
|
||||
import { isContextOverflow, modelsAreEqual, supportsXhigh } from "@mariozechner/pi-ai";
|
||||
import { isContextOverflow, modelsAreEqual, resetApiProviders, supportsXhigh } from "@mariozechner/pi-ai";
|
||||
import { getAuthPath } from "../config.js";
|
||||
import { theme } from "../modes/interactive/theme/theme.js";
|
||||
import { stripFrontmatter } from "../utils/frontmatter.js";
|
||||
|
|
@ -1832,6 +1832,7 @@ export class AgentSession {
|
|||
async reload(): Promise<void> {
|
||||
const previousFlagValues = this._extensionRunner?.getFlagValues();
|
||||
await this._extensionRunner?.emit({ type: "session_shutdown" });
|
||||
resetApiProviders();
|
||||
await this._resourceLoader.reload();
|
||||
this._buildRuntime({
|
||||
activeToolNames: this.getActiveToolNames(),
|
||||
|
|
|
|||
|
|
@ -16,10 +16,13 @@ import type {
|
|||
} from "@mariozechner/pi-agent-core";
|
||||
import type {
|
||||
Api,
|
||||
AssistantMessageEventStream,
|
||||
Context,
|
||||
ImageContent,
|
||||
Model,
|
||||
OAuthCredentials,
|
||||
OAuthLoginCallbacks,
|
||||
SimpleStreamOptions,
|
||||
TextContent,
|
||||
ToolResultMessage,
|
||||
} from "@mariozechner/pi-ai";
|
||||
|
|
@ -872,6 +875,7 @@ export interface ExtensionAPI {
|
|||
* If `models` is provided: replaces all existing models for this provider.
|
||||
* If only `baseUrl` is provided: overrides the URL for existing models.
|
||||
* If `oauth` is provided: registers OAuth provider for /login support.
|
||||
* If `streamSimple` is provided: registers a custom API stream handler.
|
||||
*
|
||||
* @example
|
||||
* // Register a new provider with custom models
|
||||
|
|
@ -930,6 +934,8 @@ export interface ProviderConfig {
|
|||
apiKey?: string;
|
||||
/** API type. Required at provider or model level when defining models. */
|
||||
api?: Api;
|
||||
/** Optional streamSimple handler for custom APIs. */
|
||||
streamSimple?: (model: Model<Api>, context: Context, options?: SimpleStreamOptions) => AssistantMessageEventStream;
|
||||
/** Custom headers to include in requests. */
|
||||
headers?: Record<string, string>;
|
||||
/** If true, adds Authorization: Bearer header with the resolved API key. */
|
||||
|
|
|
|||
|
|
@ -4,12 +4,16 @@
|
|||
|
||||
import {
|
||||
type Api,
|
||||
type AssistantMessageEventStream,
|
||||
type Context,
|
||||
getModels,
|
||||
getProviders,
|
||||
type KnownProvider,
|
||||
type Model,
|
||||
type OAuthProviderInterface,
|
||||
registerApiProvider,
|
||||
registerOAuthProvider,
|
||||
type SimpleStreamOptions,
|
||||
} from "@mariozechner/pi-ai";
|
||||
import { type Static, Type } from "@sinclair/typebox";
|
||||
import AjvModule from "ajv";
|
||||
|
|
@ -45,17 +49,7 @@ const OpenAICompatSchema = Type.Union([OpenAICompletionsCompatSchema, OpenAIResp
|
|||
const ModelDefinitionSchema = Type.Object({
|
||||
id: Type.String({ minLength: 1 }),
|
||||
name: Type.String({ minLength: 1 }),
|
||||
api: Type.Optional(
|
||||
Type.Union([
|
||||
Type.Literal("openai-completions"),
|
||||
Type.Literal("openai-responses"),
|
||||
Type.Literal("azure-openai-responses"),
|
||||
Type.Literal("openai-codex-responses"),
|
||||
Type.Literal("anthropic-messages"),
|
||||
Type.Literal("google-generative-ai"),
|
||||
Type.Literal("bedrock-converse-stream"),
|
||||
]),
|
||||
),
|
||||
api: Type.Optional(Type.String({ minLength: 1 })),
|
||||
reasoning: Type.Boolean(),
|
||||
input: Type.Array(Type.Union([Type.Literal("text"), Type.Literal("image")])),
|
||||
cost: Type.Object({
|
||||
|
|
@ -73,17 +67,7 @@ const ModelDefinitionSchema = Type.Object({
|
|||
const ProviderConfigSchema = Type.Object({
|
||||
baseUrl: Type.Optional(Type.String({ minLength: 1 })),
|
||||
apiKey: Type.Optional(Type.String({ minLength: 1 })),
|
||||
api: Type.Optional(
|
||||
Type.Union([
|
||||
Type.Literal("openai-completions"),
|
||||
Type.Literal("openai-responses"),
|
||||
Type.Literal("azure-openai-responses"),
|
||||
Type.Literal("openai-codex-responses"),
|
||||
Type.Literal("anthropic-messages"),
|
||||
Type.Literal("google-generative-ai"),
|
||||
Type.Literal("bedrock-converse-stream"),
|
||||
]),
|
||||
),
|
||||
api: Type.Optional(Type.String({ minLength: 1 })),
|
||||
headers: Type.Optional(Type.Record(Type.String(), Type.String())),
|
||||
authHeader: Type.Optional(Type.Boolean()),
|
||||
models: Type.Optional(Type.Array(ModelDefinitionSchema)),
|
||||
|
|
@ -482,6 +466,18 @@ export class ModelRegistry {
|
|||
registerOAuthProvider(oauthProvider);
|
||||
}
|
||||
|
||||
if (config.streamSimple) {
|
||||
if (!config.api) {
|
||||
throw new Error(`Provider ${providerName}: "api" is required when registering streamSimple.`);
|
||||
}
|
||||
const streamSimple = config.streamSimple;
|
||||
registerApiProvider({
|
||||
api: config.api,
|
||||
stream: (model, context, options) => streamSimple(model, context, options as SimpleStreamOptions),
|
||||
streamSimple,
|
||||
});
|
||||
}
|
||||
|
||||
// Store API key for auth resolution
|
||||
if (config.apiKey) {
|
||||
this.customProviderApiKeys.set(providerName, config.apiKey);
|
||||
|
|
@ -556,6 +552,7 @@ export interface ProviderConfigInput {
|
|||
baseUrl?: string;
|
||||
apiKey?: string;
|
||||
api?: Api;
|
||||
streamSimple?: (model: Model<Api>, context: Context, options?: SimpleStreamOptions) => AssistantMessageEventStream;
|
||||
headers?: Record<string, string>;
|
||||
authHeader?: boolean;
|
||||
/** OAuth provider for /login support */
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue