feat(packages): Add selective pi-ai base entrypoints (#5348)
This commit is contained in:
@@ -31,6 +31,24 @@ agent.subscribe((event) => {
|
|||||||
await agent.prompt("Hello!");
|
await agent.prompt("Hello!");
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Base Entry Point
|
||||||
|
|
||||||
|
Use `@earendil-works/pi-agent-core/base` with `@earendil-works/pi-ai/base` when bundling applications that should include only selected provider transports:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { Agent } from "@earendil-works/pi-agent-core/base";
|
||||||
|
import { getModel } from "@earendil-works/pi-ai/base";
|
||||||
|
import { register } from "@earendil-works/pi-ai/anthropic";
|
||||||
|
|
||||||
|
register();
|
||||||
|
|
||||||
|
const agent = new Agent({
|
||||||
|
initialState: { model: getModel("anthropic", "claude-sonnet-4-6") },
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
The default `@earendil-works/pi-agent-core` entry point remains batteries-included and registers pi-ai's lazy built-in transports for backward compatibility.
|
||||||
|
|
||||||
## Core Concepts
|
## Core Concepts
|
||||||
|
|
||||||
### AgentMessage vs LLM Message
|
### AgentMessage vs LLM Message
|
||||||
|
|||||||
@@ -10,6 +10,10 @@
|
|||||||
"types": "./dist/index.d.ts",
|
"types": "./dist/index.d.ts",
|
||||||
"import": "./dist/index.js"
|
"import": "./dist/index.js"
|
||||||
},
|
},
|
||||||
|
"./base": {
|
||||||
|
"types": "./dist/base.d.ts",
|
||||||
|
"import": "./dist/base.js"
|
||||||
|
},
|
||||||
"./node": {
|
"./node": {
|
||||||
"types": "./dist/node.d.ts",
|
"types": "./dist/node.d.ts",
|
||||||
"import": "./dist/node.js"
|
"import": "./dist/node.js"
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import {
|
|||||||
streamSimple,
|
streamSimple,
|
||||||
type ToolResultMessage,
|
type ToolResultMessage,
|
||||||
validateToolArguments,
|
validateToolArguments,
|
||||||
} from "@earendil-works/pi-ai";
|
} from "@earendil-works/pi-ai/base";
|
||||||
import type {
|
import type {
|
||||||
AgentContext,
|
AgentContext,
|
||||||
AgentEvent,
|
AgentEvent,
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import {
|
|||||||
type TextContent,
|
type TextContent,
|
||||||
type ThinkingBudgets,
|
type ThinkingBudgets,
|
||||||
type Transport,
|
type Transport,
|
||||||
} from "@earendil-works/pi-ai";
|
} from "@earendil-works/pi-ai/base";
|
||||||
import { runAgentLoop, runAgentLoopContinue } from "./agent-loop.ts";
|
import { runAgentLoop, runAgentLoopContinue } from "./agent-loop.ts";
|
||||||
import type {
|
import type {
|
||||||
AfterToolCallContext,
|
AfterToolCallContext,
|
||||||
|
|||||||
39
packages/agent/src/base.ts
Normal file
39
packages/agent/src/base.ts
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
export * from "./agent.ts";
|
||||||
|
export * from "./agent-loop.ts";
|
||||||
|
export * from "./harness/agent-harness.ts";
|
||||||
|
export {
|
||||||
|
type BranchPreparation,
|
||||||
|
type BranchSummaryDetails,
|
||||||
|
type CollectEntriesResult,
|
||||||
|
collectEntriesForBranchSummary,
|
||||||
|
generateBranchSummary,
|
||||||
|
prepareBranchEntries,
|
||||||
|
} from "./harness/compaction/branch-summarization.ts";
|
||||||
|
export {
|
||||||
|
calculateContextTokens,
|
||||||
|
compact,
|
||||||
|
DEFAULT_COMPACTION_SETTINGS,
|
||||||
|
estimateContextTokens,
|
||||||
|
estimateTokens,
|
||||||
|
findCutPoint,
|
||||||
|
findTurnStartIndex,
|
||||||
|
generateSummary,
|
||||||
|
getLastAssistantUsage,
|
||||||
|
prepareCompaction,
|
||||||
|
serializeConversation,
|
||||||
|
shouldCompact,
|
||||||
|
} from "./harness/compaction/compaction.ts";
|
||||||
|
export * from "./harness/messages.ts";
|
||||||
|
export * from "./harness/prompt-templates.ts";
|
||||||
|
export * from "./harness/session/jsonl-repo.ts";
|
||||||
|
export * from "./harness/session/memory-repo.ts";
|
||||||
|
export * from "./harness/session/repo-utils.ts";
|
||||||
|
export * from "./harness/session/session.ts";
|
||||||
|
export { uuidv7 } from "./harness/session/uuid.ts";
|
||||||
|
export * from "./harness/skills.ts";
|
||||||
|
export * from "./harness/system-prompt.ts";
|
||||||
|
export * from "./harness/types.ts";
|
||||||
|
export * from "./harness/utils/shell-output.ts";
|
||||||
|
export * from "./harness/utils/truncate.ts";
|
||||||
|
export * from "./proxy.ts";
|
||||||
|
export * from "./types.ts";
|
||||||
@@ -4,7 +4,7 @@ import {
|
|||||||
type Model,
|
type Model,
|
||||||
streamSimple,
|
streamSimple,
|
||||||
type UserMessage,
|
type UserMessage,
|
||||||
} from "@earendil-works/pi-ai";
|
} from "@earendil-works/pi-ai/base";
|
||||||
import { runAgentLoop } from "../agent-loop.ts";
|
import { runAgentLoop } from "../agent-loop.ts";
|
||||||
import type {
|
import type {
|
||||||
AgentContext,
|
AgentContext,
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import type { Model } from "@earendil-works/pi-ai";
|
import { completeSimple, type Model } from "@earendil-works/pi-ai/base";
|
||||||
import { completeSimple } from "@earendil-works/pi-ai";
|
|
||||||
import type { AgentMessage } from "../../types.ts";
|
import type { AgentMessage } from "../../types.ts";
|
||||||
import {
|
import {
|
||||||
convertToLlm,
|
convertToLlm,
|
||||||
|
|||||||
@@ -1,5 +1,11 @@
|
|||||||
import type { AssistantMessage, ImageContent, Model, TextContent, Usage } from "@earendil-works/pi-ai";
|
import {
|
||||||
import { completeSimple } from "@earendil-works/pi-ai";
|
type AssistantMessage,
|
||||||
|
completeSimple,
|
||||||
|
type ImageContent,
|
||||||
|
type Model,
|
||||||
|
type TextContent,
|
||||||
|
type Usage,
|
||||||
|
} from "@earendil-works/pi-ai/base";
|
||||||
import type { AgentMessage, ThinkingLevel } from "../../types.ts";
|
import type { AgentMessage, ThinkingLevel } from "../../types.ts";
|
||||||
import {
|
import {
|
||||||
convertToLlm,
|
convertToLlm,
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { Message } from "@earendil-works/pi-ai";
|
import type { Message } from "@earendil-works/pi-ai/base";
|
||||||
import type { AgentMessage } from "../../types.ts";
|
import type { AgentMessage } from "../../types.ts";
|
||||||
|
|
||||||
/** File paths touched by a session branch or compaction range. */
|
/** File paths touched by a session branch or compaction range. */
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { ImageContent, Message, TextContent } from "@earendil-works/pi-ai";
|
import type { ImageContent, Message, TextContent } from "@earendil-works/pi-ai/base";
|
||||||
import type { AgentMessage } from "../types.ts";
|
import type { AgentMessage } from "../types.ts";
|
||||||
|
|
||||||
export const COMPACTION_SUMMARY_PREFIX = `The conversation history before this point was compacted into the following summary:
|
export const COMPACTION_SUMMARY_PREFIX = `The conversation history before this point was compacted into the following summary:
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { ImageContent, TextContent } from "@earendil-works/pi-ai";
|
import type { ImageContent, TextContent } from "@earendil-works/pi-ai/base";
|
||||||
import type { AgentMessage } from "../../types.ts";
|
import type { AgentMessage } from "../../types.ts";
|
||||||
import { createBranchSummaryMessage, createCompactionSummaryMessage, createCustomMessage } from "../messages.ts";
|
import { createBranchSummaryMessage, createCompactionSummaryMessage, createCustomMessage } from "../messages.ts";
|
||||||
import type {
|
import type {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import type { ImageContent, Model, SimpleStreamOptions, TextContent, Transport } from "@earendil-works/pi-ai";
|
import type { ImageContent, Model, SimpleStreamOptions, TextContent, Transport } from "@earendil-works/pi-ai/base";
|
||||||
import type { AgentEvent, AgentMessage, AgentTool, QueueMode, ThinkingLevel } from "../index.ts";
|
import type { AgentEvent, AgentMessage, AgentTool, QueueMode, ThinkingLevel } from "../types.ts";
|
||||||
import type { Session } from "./session/session.ts";
|
import type { Session } from "./session/session.ts";
|
||||||
|
|
||||||
/** Result of a fallible operation. Expected failures are returned as `ok: false` instead of thrown. */
|
/** Result of a fallible operation. Expected failures are returned as `ok: false` instead of thrown. */
|
||||||
|
|||||||
@@ -1,44 +1,5 @@
|
|||||||
// Core Agent
|
// Import the default pi-ai entrypoint so that all built-in providers register
|
||||||
export * from "./agent.ts";
|
// automatically. Unlike "@earendil-works/pi-ai/base" which does not.
|
||||||
// Loop functions
|
import "@earendil-works/pi-ai";
|
||||||
export * from "./agent-loop.ts";
|
|
||||||
export * from "./harness/agent-harness.ts";
|
export * from "./base.ts";
|
||||||
export {
|
|
||||||
type BranchPreparation,
|
|
||||||
type BranchSummaryDetails,
|
|
||||||
type CollectEntriesResult,
|
|
||||||
collectEntriesForBranchSummary,
|
|
||||||
generateBranchSummary,
|
|
||||||
prepareBranchEntries,
|
|
||||||
} from "./harness/compaction/branch-summarization.ts";
|
|
||||||
export {
|
|
||||||
calculateContextTokens,
|
|
||||||
compact,
|
|
||||||
DEFAULT_COMPACTION_SETTINGS,
|
|
||||||
estimateContextTokens,
|
|
||||||
estimateTokens,
|
|
||||||
findCutPoint,
|
|
||||||
findTurnStartIndex,
|
|
||||||
generateSummary,
|
|
||||||
getLastAssistantUsage,
|
|
||||||
prepareCompaction,
|
|
||||||
serializeConversation,
|
|
||||||
shouldCompact,
|
|
||||||
} from "./harness/compaction/compaction.ts";
|
|
||||||
export * from "./harness/messages.ts";
|
|
||||||
export * from "./harness/prompt-templates.ts";
|
|
||||||
export * from "./harness/session/jsonl-repo.ts";
|
|
||||||
export * from "./harness/session/memory-repo.ts";
|
|
||||||
export * from "./harness/session/repo-utils.ts";
|
|
||||||
export * from "./harness/session/session.ts";
|
|
||||||
export { uuidv7 } from "./harness/session/uuid.ts";
|
|
||||||
export * from "./harness/skills.ts";
|
|
||||||
export * from "./harness/system-prompt.ts";
|
|
||||||
// Harness
|
|
||||||
export * from "./harness/types.ts";
|
|
||||||
export * from "./harness/utils/shell-output.ts";
|
|
||||||
export * from "./harness/utils/truncate.ts";
|
|
||||||
// Proxy utilities
|
|
||||||
export * from "./proxy.ts";
|
|
||||||
// Types
|
|
||||||
export * from "./types.ts";
|
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ import {
|
|||||||
type SimpleStreamOptions,
|
type SimpleStreamOptions,
|
||||||
type StopReason,
|
type StopReason,
|
||||||
type ToolCall,
|
type ToolCall,
|
||||||
} from "@earendil-works/pi-ai";
|
} from "@earendil-works/pi-ai/base";
|
||||||
|
|
||||||
// Create stream class matching ProxyMessageEventStream
|
// Create stream class matching ProxyMessageEventStream
|
||||||
class ProxyMessageEventStream extends EventStream<AssistantMessageEvent, AssistantMessage> {
|
class ProxyMessageEventStream extends EventStream<AssistantMessageEvent, AssistantMessage> {
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import type {
|
|||||||
TextContent,
|
TextContent,
|
||||||
Tool,
|
Tool,
|
||||||
ToolResultMessage,
|
ToolResultMessage,
|
||||||
} from "@earendil-works/pi-ai";
|
} from "@earendil-works/pi-ai/base";
|
||||||
import type { Static, TSchema } from "typebox";
|
import type { Static, TSchema } from "typebox";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,6 +1,12 @@
|
|||||||
import { defineConfig } from "vitest/config";
|
import { defineConfig } from "vitest/config";
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
|
resolve: {
|
||||||
|
alias: {
|
||||||
|
"@earendil-works/pi-ai/base": new URL("../ai/src/base.ts", import.meta.url).pathname,
|
||||||
|
"@earendil-works/pi-ai": new URL("../ai/src/index.ts", import.meta.url).pathname,
|
||||||
|
},
|
||||||
|
},
|
||||||
test: {
|
test: {
|
||||||
globals: true,
|
globals: true,
|
||||||
environment: "node",
|
environment: "node",
|
||||||
|
|||||||
@@ -1,6 +1,12 @@
|
|||||||
import { defineConfig } from "vitest/config";
|
import { defineConfig } from "vitest/config";
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
|
resolve: {
|
||||||
|
alias: {
|
||||||
|
"@earendil-works/pi-ai/base": new URL("../ai/src/base.ts", import.meta.url).pathname,
|
||||||
|
"@earendil-works/pi-ai": new URL("../ai/src/index.ts", import.meta.url).pathname,
|
||||||
|
},
|
||||||
|
},
|
||||||
test: {
|
test: {
|
||||||
globals: true,
|
globals: true,
|
||||||
environment: "node",
|
environment: "node",
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ Unified LLM API with automatic model discovery, provider configuration, token an
|
|||||||
|
|
||||||
- [Supported Providers](#supported-providers)
|
- [Supported Providers](#supported-providers)
|
||||||
- [Installation](#installation)
|
- [Installation](#installation)
|
||||||
|
- [Base Entry Point](#base-entry-point)
|
||||||
- [Quick Start](#quick-start)
|
- [Quick Start](#quick-start)
|
||||||
- [Tools](#tools)
|
- [Tools](#tools)
|
||||||
- [Defining Tools](#defining-tools)
|
- [Defining Tools](#defining-tools)
|
||||||
@@ -88,6 +89,30 @@ npm install @earendil-works/pi-ai
|
|||||||
|
|
||||||
TypeBox exports are re-exported from `@earendil-works/pi-ai`: `Type`, `Static`, and `TSchema`.
|
TypeBox exports are re-exported from `@earendil-works/pi-ai`: `Type`, `Static`, and `TSchema`.
|
||||||
|
|
||||||
|
## Base Entry Point
|
||||||
|
|
||||||
|
Use `@earendil-works/pi-ai/base` when a bundler should include only explicitly selected transport implementations. The base entry point exposes model discovery, registries, generic dispatch, environment-key helpers, and provider-neutral utilities without registering built-in transports during module initialization. Generic dispatch still resolves configured environment keys when called.
|
||||||
|
|
||||||
|
Import each selected transport directly and call its `register()` function:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { getModel, streamSimple } from '@earendil-works/pi-ai/base';
|
||||||
|
import { register as registerAnthropic } from '@earendil-works/pi-ai/anthropic';
|
||||||
|
|
||||||
|
registerAnthropic();
|
||||||
|
|
||||||
|
const model = getModel('anthropic', 'claude-sonnet-4-6');
|
||||||
|
const response = await streamSimple(model, {
|
||||||
|
messages: [{ role: 'user', content: 'Hello!' }]
|
||||||
|
}, {
|
||||||
|
apiKey: process.env.ANTHROPIC_API_KEY
|
||||||
|
}).result();
|
||||||
|
```
|
||||||
|
|
||||||
|
Direct transport imports bundle their implementation and SDK code. Register only the transports used by the application. For example, OpenRouter, Groq, xAI, and DeepSeek chat models share the `@earendil-works/pi-ai/openai-completions` transport.
|
||||||
|
|
||||||
|
Use `@earendil-works/pi-ai` for the batteries-included behavior. The root entry point remains backward-compatible: it registers lazy wrappers for all built-in transports and resolves environment API keys automatically during dispatch.
|
||||||
|
|
||||||
## Quick Start
|
## Quick Start
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
@@ -438,7 +463,7 @@ Do not use `stream()` or `complete()` for image generation. Image generation is
|
|||||||
### Basic Image Generation
|
### Basic Image Generation
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
import { getImageModel, generateImages } from '@mariozechner/pi-ai';
|
import { getImageModel, generateImages } from '@earendil-works/pi-ai';
|
||||||
|
|
||||||
const model = getImageModel('openrouter', 'google/gemini-2.5-flash-image');
|
const model = getImageModel('openrouter', 'google/gemini-2.5-flash-image');
|
||||||
|
|
||||||
@@ -1097,6 +1122,7 @@ const response = await complete(model, {
|
|||||||
- OAuth login flows are not supported in browser environments. Use the `@earendil-works/pi-ai/oauth` entry point in Node.js.
|
- OAuth login flows are not supported in browser environments. Use the `@earendil-works/pi-ai/oauth` entry point in Node.js.
|
||||||
- In browser builds, Bedrock can still appear in model lists. Calls to Bedrock models fail at runtime.
|
- In browser builds, Bedrock can still appear in model lists. Calls to Bedrock models fail at runtime.
|
||||||
- Use a server-side proxy or backend service if you need Bedrock or OAuth-based auth from a web app.
|
- Use a server-side proxy or backend service if you need Bedrock or OAuth-based auth from a web app.
|
||||||
|
- Use `@earendil-works/pi-ai/base` plus explicit direct transport registration when a browser bundle should exclude unused provider SDK implementations.
|
||||||
|
|
||||||
### Environment Variables (Node.js only)
|
### Environment Variables (Node.js only)
|
||||||
|
|
||||||
@@ -1333,6 +1359,7 @@ Create a new provider file (for example `amazon-bedrock.ts`) that exports:
|
|||||||
|
|
||||||
- `stream<Provider>()` function returning `AssistantMessageEventStream`
|
- `stream<Provider>()` function returning `AssistantMessageEventStream`
|
||||||
- `streamSimple<Provider>()` for `SimpleStreamOptions` mapping
|
- `streamSimple<Provider>()` for `SimpleStreamOptions` mapping
|
||||||
|
- `register()` for explicit direct transport registration from `@earendil-works/pi-ai/base`
|
||||||
- Provider-specific options interface
|
- Provider-specific options interface
|
||||||
- Message conversion functions to transform `Context` to provider format
|
- Message conversion functions to transform `Context` to provider format
|
||||||
- Tool conversion if the provider supports tools
|
- Tool conversion if the provider supports tools
|
||||||
@@ -1343,7 +1370,8 @@ Create a new provider file (for example `amazon-bedrock.ts`) that exports:
|
|||||||
- Register the API with `registerApiProvider()`
|
- Register the API with `registerApiProvider()`
|
||||||
- Add a package subpath export in `package.json` for the provider module (`./dist/providers/<provider>.js`)
|
- Add a package subpath export in `package.json` for the provider module (`./dist/providers/<provider>.js`)
|
||||||
- Add lazy loader wrappers in `src/providers/register-builtins.ts`, do not statically import provider implementation modules there
|
- Add lazy loader wrappers in `src/providers/register-builtins.ts`, do not statically import provider implementation modules there
|
||||||
- Add any root-level `export type` re-exports in `src/index.ts` that should remain available from `@earendil-works/pi-ai`
|
- Add any root-level `export type` re-exports in `src/index.ts` and `src/base.ts` that should remain available from `@earendil-works/pi-ai` and `@earendil-works/pi-ai/base`
|
||||||
|
- Keep `src/base.ts` free of built-in registration imports
|
||||||
- Add credential detection in `env-api-keys.ts` for the new provider
|
- Add credential detection in `env-api-keys.ts` for the new provider
|
||||||
- Ensure `streamSimple` handles auth lookup via `getEnvApiKey()` or provider-specific auth
|
- Ensure `streamSimple` handles auth lookup via `getEnvApiKey()` or provider-specific auth
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,14 @@
|
|||||||
"types": "./dist/index.d.ts",
|
"types": "./dist/index.d.ts",
|
||||||
"import": "./dist/index.js"
|
"import": "./dist/index.js"
|
||||||
},
|
},
|
||||||
|
"./base": {
|
||||||
|
"types": "./dist/base.d.ts",
|
||||||
|
"import": "./dist/base.js"
|
||||||
|
},
|
||||||
|
"./amazon-bedrock": {
|
||||||
|
"types": "./dist/providers/amazon-bedrock.d.ts",
|
||||||
|
"import": "./dist/providers/amazon-bedrock.js"
|
||||||
|
},
|
||||||
"./anthropic": {
|
"./anthropic": {
|
||||||
"types": "./dist/providers/anthropic.d.ts",
|
"types": "./dist/providers/anthropic.d.ts",
|
||||||
"import": "./dist/providers/anthropic.js"
|
"import": "./dist/providers/anthropic.js"
|
||||||
@@ -42,6 +50,10 @@
|
|||||||
"types": "./dist/providers/openai-responses.d.ts",
|
"types": "./dist/providers/openai-responses.d.ts",
|
||||||
"import": "./dist/providers/openai-responses.js"
|
"import": "./dist/providers/openai-responses.js"
|
||||||
},
|
},
|
||||||
|
"./openrouter-images": {
|
||||||
|
"types": "./dist/providers/images/openrouter.d.ts",
|
||||||
|
"import": "./dist/providers/images/openrouter.js"
|
||||||
|
},
|
||||||
"./oauth": {
|
"./oauth": {
|
||||||
"types": "./dist/oauth.d.ts",
|
"types": "./dist/oauth.d.ts",
|
||||||
"import": "./dist/oauth.js"
|
"import": "./dist/oauth.js"
|
||||||
|
|||||||
45
packages/ai/src/base.ts
Normal file
45
packages/ai/src/base.ts
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
export type { Static, TSchema } from "typebox";
|
||||||
|
export { Type } from "typebox";
|
||||||
|
|
||||||
|
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 "./models.ts";
|
||||||
|
export type { BedrockOptions, BedrockThinkingDisplay } from "./providers/amazon-bedrock.ts";
|
||||||
|
export type { AnthropicEffort, AnthropicOptions, AnthropicThinkingDisplay } from "./providers/anthropic.ts";
|
||||||
|
export type { AzureOpenAIResponsesOptions } from "./providers/azure-openai-responses.ts";
|
||||||
|
export * from "./providers/faux.ts";
|
||||||
|
export type { GoogleOptions } from "./providers/google.ts";
|
||||||
|
export type { GoogleThinkingLevel } from "./providers/google-shared.ts";
|
||||||
|
export type { GoogleVertexOptions } from "./providers/google-vertex.ts";
|
||||||
|
export type { MistralOptions } from "./providers/mistral.ts";
|
||||||
|
export type {
|
||||||
|
OpenAICodexResponsesOptions,
|
||||||
|
OpenAICodexWebSocketDebugStats,
|
||||||
|
} from "./providers/openai-codex-responses.ts";
|
||||||
|
export type { OpenAICompletionsOptions } from "./providers/openai-completions.ts";
|
||||||
|
export type { OpenAIResponsesOptions } from "./providers/openai-responses.ts";
|
||||||
|
export * from "./session-resources.ts";
|
||||||
|
export * from "./stream.ts";
|
||||||
|
export * from "./types.ts";
|
||||||
|
export * from "./utils/diagnostics.ts";
|
||||||
|
export * from "./utils/event-stream.ts";
|
||||||
|
export * from "./utils/json-parse.ts";
|
||||||
|
export type {
|
||||||
|
OAuthAuthInfo,
|
||||||
|
OAuthCredentials,
|
||||||
|
OAuthDeviceCodeInfo,
|
||||||
|
OAuthLoginCallbacks,
|
||||||
|
OAuthPrompt,
|
||||||
|
OAuthProvider,
|
||||||
|
OAuthProviderId,
|
||||||
|
OAuthProviderInfo,
|
||||||
|
OAuthProviderInterface,
|
||||||
|
OAuthSelectOption,
|
||||||
|
OAuthSelectPrompt,
|
||||||
|
} from "./utils/oauth/types.ts";
|
||||||
|
export * from "./utils/overflow.ts";
|
||||||
|
export * from "./utils/typebox-helpers.ts";
|
||||||
|
export * from "./utils/validation.ts";
|
||||||
@@ -1,4 +1,6 @@
|
|||||||
import { streamBedrock, streamSimpleBedrock } from "./providers/amazon-bedrock.ts";
|
import { register, streamBedrock, streamSimpleBedrock } from "./providers/amazon-bedrock.ts";
|
||||||
|
|
||||||
|
export { register };
|
||||||
|
|
||||||
export const bedrockProviderModule = {
|
export const bedrockProviderModule = {
|
||||||
streamBedrock,
|
streamBedrock,
|
||||||
|
|||||||
@@ -51,3 +51,7 @@ export function registerImagesApiProvider<TApi extends ImagesApi, TOptions exten
|
|||||||
export function getImagesApiProvider(api: ImagesApi): ImagesApiProviderInternal | undefined {
|
export function getImagesApiProvider(api: ImagesApi): ImagesApiProviderInternal | undefined {
|
||||||
return imagesApiProviderRegistry.get(api)?.provider;
|
return imagesApiProviderRegistry.get(api)?.provider;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function clearImagesApiProviders(): void {
|
||||||
|
imagesApiProviderRegistry.clear();
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
import "./providers/images/register-builtins.ts";
|
|
||||||
|
|
||||||
import { getImagesApiProvider } from "./images-api-registry.ts";
|
import { getImagesApiProvider } from "./images-api-registry.ts";
|
||||||
import type { AssistantImages, ImagesApi, ImagesContext, ImagesModel, ProviderImagesOptions } from "./types.ts";
|
import type { AssistantImages, ImagesApi, ImagesContext, ImagesModel, ProviderImagesOptions } from "./types.ts";
|
||||||
|
|
||||||
|
|||||||
@@ -1,47 +1,6 @@
|
|||||||
export type { Static, TSchema } from "typebox";
|
import { registerBuiltInImagesApiProviders } from "./providers/register-builtins.ts";
|
||||||
export { Type } from "typebox";
|
|
||||||
|
|
||||||
export * from "./api-registry.ts";
|
export * from "./base.ts";
|
||||||
export * from "./env-api-keys.ts";
|
|
||||||
export * from "./image-models.ts";
|
|
||||||
export * from "./images.ts";
|
|
||||||
export * from "./images-api-registry.ts";
|
|
||||||
export * from "./models.ts";
|
|
||||||
export type { BedrockOptions, BedrockThinkingDisplay } from "./providers/amazon-bedrock.ts";
|
|
||||||
export type { AnthropicEffort, AnthropicOptions, AnthropicThinkingDisplay } from "./providers/anthropic.ts";
|
|
||||||
export type { AzureOpenAIResponsesOptions } from "./providers/azure-openai-responses.ts";
|
|
||||||
export * from "./providers/faux.ts";
|
|
||||||
export type { GoogleOptions } from "./providers/google.ts";
|
|
||||||
export type { GoogleThinkingLevel } from "./providers/google-shared.ts";
|
|
||||||
export type { GoogleVertexOptions } from "./providers/google-vertex.ts";
|
|
||||||
export * from "./providers/images/register-builtins.ts";
|
|
||||||
export type { MistralOptions } from "./providers/mistral.ts";
|
|
||||||
export type {
|
|
||||||
OpenAICodexResponsesOptions,
|
|
||||||
OpenAICodexWebSocketDebugStats,
|
|
||||||
} from "./providers/openai-codex-responses.ts";
|
|
||||||
export type { OpenAICompletionsOptions } from "./providers/openai-completions.ts";
|
|
||||||
export type { OpenAIResponsesOptions } from "./providers/openai-responses.ts";
|
|
||||||
export * from "./providers/register-builtins.ts";
|
export * from "./providers/register-builtins.ts";
|
||||||
export * from "./session-resources.ts";
|
|
||||||
export * from "./stream.ts";
|
registerBuiltInImagesApiProviders();
|
||||||
export * from "./types.ts";
|
|
||||||
export * from "./utils/diagnostics.ts";
|
|
||||||
export * from "./utils/event-stream.ts";
|
|
||||||
export * from "./utils/json-parse.ts";
|
|
||||||
export type {
|
|
||||||
OAuthAuthInfo,
|
|
||||||
OAuthCredentials,
|
|
||||||
OAuthDeviceCodeInfo,
|
|
||||||
OAuthLoginCallbacks,
|
|
||||||
OAuthPrompt,
|
|
||||||
OAuthProvider,
|
|
||||||
OAuthProviderId,
|
|
||||||
OAuthProviderInfo,
|
|
||||||
OAuthProviderInterface,
|
|
||||||
OAuthSelectOption,
|
|
||||||
OAuthSelectPrompt,
|
|
||||||
} from "./utils/oauth/types.ts";
|
|
||||||
export * from "./utils/overflow.ts";
|
|
||||||
export * from "./utils/typebox-helpers.ts";
|
|
||||||
export * from "./utils/validation.ts";
|
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ import { NodeHttpHandler } from "@smithy/node-http-handler";
|
|||||||
import type { BuildMiddleware, DocumentType, MetadataBearer } from "@smithy/types";
|
import type { BuildMiddleware, DocumentType, MetadataBearer } from "@smithy/types";
|
||||||
import { HttpProxyAgent } from "http-proxy-agent";
|
import { HttpProxyAgent } from "http-proxy-agent";
|
||||||
import { HttpsProxyAgent } from "https-proxy-agent";
|
import { HttpsProxyAgent } from "https-proxy-agent";
|
||||||
|
import { registerApiProvider } from "../api-registry.ts";
|
||||||
import { calculateCost } from "../models.ts";
|
import { calculateCost } from "../models.ts";
|
||||||
import type {
|
import type {
|
||||||
Api,
|
Api,
|
||||||
@@ -413,6 +414,14 @@ export const streamSimpleBedrock: StreamFunction<"bedrock-converse-stream", Simp
|
|||||||
} satisfies BedrockOptions);
|
} satisfies BedrockOptions);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export function register(): void {
|
||||||
|
registerApiProvider({
|
||||||
|
api: "bedrock-converse-stream",
|
||||||
|
stream: streamBedrock,
|
||||||
|
streamSimple: streamSimpleBedrock,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function handleContentBlockStart(
|
function handleContentBlockStart(
|
||||||
event: ContentBlockStartEvent,
|
event: ContentBlockStartEvent,
|
||||||
blocks: Block[],
|
blocks: Block[],
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import type {
|
|||||||
RawMessageStreamEvent,
|
RawMessageStreamEvent,
|
||||||
RefusalStopDetails,
|
RefusalStopDetails,
|
||||||
} from "@anthropic-ai/sdk/resources/messages.js";
|
} from "@anthropic-ai/sdk/resources/messages.js";
|
||||||
|
import { registerApiProvider } from "../api-registry.ts";
|
||||||
import { calculateCost } from "../models.ts";
|
import { calculateCost } from "../models.ts";
|
||||||
import type {
|
import type {
|
||||||
AnthropicMessagesCompat,
|
AnthropicMessagesCompat,
|
||||||
@@ -786,6 +787,14 @@ export const streamSimpleAnthropic: StreamFunction<"anthropic-messages", SimpleS
|
|||||||
} satisfies AnthropicOptions);
|
} satisfies AnthropicOptions);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export function register(): void {
|
||||||
|
registerApiProvider({
|
||||||
|
api: "anthropic-messages",
|
||||||
|
stream: streamAnthropic,
|
||||||
|
streamSimple: streamSimpleAnthropic,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function isOAuthToken(apiKey: string): boolean {
|
function isOAuthToken(apiKey: string): boolean {
|
||||||
return apiKey.includes("sk-ant-oat");
|
return apiKey.includes("sk-ant-oat");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { AzureOpenAI } from "openai";
|
import { AzureOpenAI } from "openai";
|
||||||
import type { ResponseCreateParamsStreaming } from "openai/resources/responses/responses.js";
|
import type { ResponseCreateParamsStreaming } from "openai/resources/responses/responses.js";
|
||||||
|
import { registerApiProvider } from "../api-registry.ts";
|
||||||
import { clampThinkingLevel } from "../models.ts";
|
import { clampThinkingLevel } from "../models.ts";
|
||||||
import type {
|
import type {
|
||||||
Api,
|
Api,
|
||||||
@@ -170,6 +171,14 @@ export const streamSimpleAzureOpenAIResponses: StreamFunction<"azure-openai-resp
|
|||||||
} satisfies AzureOpenAIResponsesOptions);
|
} satisfies AzureOpenAIResponsesOptions);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export function register(): void {
|
||||||
|
registerApiProvider({
|
||||||
|
api: "azure-openai-responses",
|
||||||
|
stream: streamAzureOpenAIResponses,
|
||||||
|
streamSimple: streamSimpleAzureOpenAIResponses,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function normalizeAzureBaseUrl(baseUrl: string): string {
|
function normalizeAzureBaseUrl(baseUrl: string): string {
|
||||||
const trimmed = baseUrl.trim().replace(/\/+$/, "");
|
const trimmed = baseUrl.trim().replace(/\/+$/, "");
|
||||||
let url: URL;
|
let url: URL;
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import {
|
|||||||
type ThinkingConfig,
|
type ThinkingConfig,
|
||||||
ThinkingLevel,
|
ThinkingLevel,
|
||||||
} from "@google/genai";
|
} from "@google/genai";
|
||||||
|
import { registerApiProvider } from "../api-registry.ts";
|
||||||
import { calculateCost, clampThinkingLevel } from "../models.ts";
|
import { calculateCost, clampThinkingLevel } from "../models.ts";
|
||||||
import type {
|
import type {
|
||||||
Api,
|
Api,
|
||||||
@@ -330,6 +331,14 @@ export const streamSimpleGoogleVertex: StreamFunction<"google-vertex", SimpleStr
|
|||||||
} satisfies GoogleVertexOptions);
|
} satisfies GoogleVertexOptions);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export function register(): void {
|
||||||
|
registerApiProvider({
|
||||||
|
api: "google-vertex",
|
||||||
|
stream: streamGoogleVertex,
|
||||||
|
streamSimple: streamSimpleGoogleVertex,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function createClient(
|
function createClient(
|
||||||
model: Model<"google-vertex">,
|
model: Model<"google-vertex">,
|
||||||
project: string,
|
project: string,
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import {
|
|||||||
GoogleGenAI,
|
GoogleGenAI,
|
||||||
type ThinkingConfig,
|
type ThinkingConfig,
|
||||||
} from "@google/genai";
|
} from "@google/genai";
|
||||||
|
import { registerApiProvider } from "../api-registry.ts";
|
||||||
import { calculateCost, clampThinkingLevel } from "../models.ts";
|
import { calculateCost, clampThinkingLevel } from "../models.ts";
|
||||||
import type {
|
import type {
|
||||||
Api,
|
Api,
|
||||||
@@ -315,6 +316,14 @@ export const streamSimpleGoogle: StreamFunction<"google-generative-ai", SimpleSt
|
|||||||
} satisfies GoogleOptions);
|
} satisfies GoogleOptions);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export function register(): void {
|
||||||
|
registerApiProvider({
|
||||||
|
api: "google-generative-ai",
|
||||||
|
stream: streamGoogle,
|
||||||
|
streamSimple: streamSimpleGoogle,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function createClient(
|
function createClient(
|
||||||
model: Model<"google-generative-ai">,
|
model: Model<"google-generative-ai">,
|
||||||
apiKey?: string,
|
apiKey?: string,
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import type {
|
|||||||
ChatCompletionContentPartText,
|
ChatCompletionContentPartText,
|
||||||
ChatCompletionCreateParamsNonStreaming,
|
ChatCompletionCreateParamsNonStreaming,
|
||||||
} from "openai/resources/chat/completions.js";
|
} from "openai/resources/chat/completions.js";
|
||||||
|
import { registerImagesApiProvider } from "../../images-api-registry.ts";
|
||||||
import type {
|
import type {
|
||||||
AssistantImages,
|
AssistantImages,
|
||||||
ImageContent,
|
ImageContent,
|
||||||
@@ -103,6 +104,13 @@ export const generateImagesOpenRouter: ImagesFunction<"openrouter-images", Image
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export function register(): void {
|
||||||
|
registerImagesApiProvider({
|
||||||
|
api: "openrouter-images",
|
||||||
|
generateImages: generateImagesOpenRouter,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function createClient(
|
function createClient(
|
||||||
model: ImagesModel<"openrouter-images">,
|
model: ImagesModel<"openrouter-images">,
|
||||||
apiKey: string,
|
apiKey: string,
|
||||||
|
|||||||
@@ -1,50 +0,0 @@
|
|||||||
import { registerImagesApiProvider } from "../../images-api-registry.ts";
|
|
||||||
import type { AssistantImages, ImagesContext, ImagesFunction, ImagesModel, ImagesOptions } from "../../types.ts";
|
|
||||||
import type { generateImagesOpenRouter as generateImagesOpenRouterFunction } from "./openrouter.ts";
|
|
||||||
|
|
||||||
interface OpenRouterImagesProviderModule {
|
|
||||||
generateImagesOpenRouter: typeof generateImagesOpenRouterFunction;
|
|
||||||
}
|
|
||||||
|
|
||||||
let openRouterImagesProviderModulePromise: Promise<OpenRouterImagesProviderModule> | undefined;
|
|
||||||
|
|
||||||
function createLazyLoadErrorImages(model: ImagesModel<"openrouter-images">, error: unknown): AssistantImages {
|
|
||||||
return {
|
|
||||||
api: model.api,
|
|
||||||
provider: model.provider,
|
|
||||||
model: model.id,
|
|
||||||
output: [],
|
|
||||||
stopReason: "error",
|
|
||||||
errorMessage: error instanceof Error ? error.message : String(error),
|
|
||||||
timestamp: Date.now(),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function loadOpenRouterImagesProviderModule(): Promise<OpenRouterImagesProviderModule> {
|
|
||||||
openRouterImagesProviderModulePromise ||= import("./openrouter.ts").then(
|
|
||||||
(module) => module as OpenRouterImagesProviderModule,
|
|
||||||
);
|
|
||||||
return openRouterImagesProviderModulePromise;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const generateImagesOpenRouter: ImagesFunction<"openrouter-images", ImagesOptions> = async (
|
|
||||||
model: ImagesModel<"openrouter-images">,
|
|
||||||
context: ImagesContext,
|
|
||||||
options?: ImagesOptions,
|
|
||||||
) => {
|
|
||||||
try {
|
|
||||||
const module = await loadOpenRouterImagesProviderModule();
|
|
||||||
return await module.generateImagesOpenRouter(model, context, options);
|
|
||||||
} catch (error) {
|
|
||||||
return createLazyLoadErrorImages(model, error);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export function registerBuiltInImagesApiProviders(): void {
|
|
||||||
registerImagesApiProvider({
|
|
||||||
api: "openrouter-images",
|
|
||||||
generateImages: generateImagesOpenRouter,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
registerBuiltInImagesApiProviders();
|
|
||||||
@@ -6,6 +6,7 @@ import type {
|
|||||||
ContentChunk,
|
ContentChunk,
|
||||||
FunctionTool,
|
FunctionTool,
|
||||||
} from "@mistralai/mistralai/models/components";
|
} from "@mistralai/mistralai/models/components";
|
||||||
|
import { registerApiProvider } from "../api-registry.ts";
|
||||||
import { calculateCost, clampThinkingLevel } from "../models.ts";
|
import { calculateCost, clampThinkingLevel } from "../models.ts";
|
||||||
import type {
|
import type {
|
||||||
AssistantMessage,
|
AssistantMessage,
|
||||||
@@ -130,6 +131,14 @@ export const streamSimpleMistral: StreamFunction<"mistral-conversations", Simple
|
|||||||
} satisfies MistralOptions);
|
} satisfies MistralOptions);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export function register(): void {
|
||||||
|
registerApiProvider({
|
||||||
|
api: "mistral-conversations",
|
||||||
|
stream: streamMistral,
|
||||||
|
streamSimple: streamSimpleMistral,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function createOutput(model: Model<"mistral-conversations">): AssistantMessage {
|
function createOutput(model: Model<"mistral-conversations">): AssistantMessage {
|
||||||
return {
|
return {
|
||||||
role: "assistant",
|
role: "assistant",
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ if (typeof process !== "undefined" && (process.versions?.node || process.version
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
import { registerApiProvider } from "../api-registry.ts";
|
||||||
import { clampThinkingLevel } from "../models.ts";
|
import { clampThinkingLevel } from "../models.ts";
|
||||||
import { registerSessionResourceCleanup } from "../session-resources.ts";
|
import { registerSessionResourceCleanup } from "../session-resources.ts";
|
||||||
import type {
|
import type {
|
||||||
@@ -428,6 +429,14 @@ export const streamSimpleOpenAICodexResponses: StreamFunction<"openai-codex-resp
|
|||||||
} satisfies OpenAICodexResponsesOptions);
|
} satisfies OpenAICodexResponsesOptions);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export function register(): void {
|
||||||
|
registerApiProvider({
|
||||||
|
api: "openai-codex-responses",
|
||||||
|
stream: streamOpenAICodexResponses,
|
||||||
|
streamSimple: streamSimpleOpenAICodexResponses,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// Request Building
|
// Request Building
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import type {
|
|||||||
ChatCompletionSystemMessageParam,
|
ChatCompletionSystemMessageParam,
|
||||||
ChatCompletionToolMessageParam,
|
ChatCompletionToolMessageParam,
|
||||||
} from "openai/resources/chat/completions.js";
|
} from "openai/resources/chat/completions.js";
|
||||||
|
import { registerApiProvider } from "../api-registry.ts";
|
||||||
import { calculateCost, clampThinkingLevel } from "../models.ts";
|
import { calculateCost, clampThinkingLevel } from "../models.ts";
|
||||||
import type {
|
import type {
|
||||||
AssistantMessage,
|
AssistantMessage,
|
||||||
@@ -449,6 +450,14 @@ export const streamSimpleOpenAICompletions: StreamFunction<"openai-completions",
|
|||||||
} satisfies OpenAICompletionsOptions);
|
} satisfies OpenAICompletionsOptions);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export function register(): void {
|
||||||
|
registerApiProvider({
|
||||||
|
api: "openai-completions",
|
||||||
|
stream: streamOpenAICompletions,
|
||||||
|
streamSimple: streamSimpleOpenAICompletions,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function createClient(
|
function createClient(
|
||||||
model: Model<"openai-completions">,
|
model: Model<"openai-completions">,
|
||||||
context: Context,
|
context: Context,
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import OpenAI from "openai";
|
import OpenAI from "openai";
|
||||||
import type { ResponseCreateParamsStreaming } from "openai/resources/responses/responses.js";
|
import type { ResponseCreateParamsStreaming } from "openai/resources/responses/responses.js";
|
||||||
|
import { registerApiProvider } from "../api-registry.ts";
|
||||||
import { clampThinkingLevel } from "../models.ts";
|
import { clampThinkingLevel } from "../models.ts";
|
||||||
import type {
|
import type {
|
||||||
Api,
|
Api,
|
||||||
@@ -181,6 +182,14 @@ export const streamSimpleOpenAIResponses: StreamFunction<"openai-responses", Sim
|
|||||||
} satisfies OpenAIResponsesOptions);
|
} satisfies OpenAIResponsesOptions);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export function register(): void {
|
||||||
|
registerApiProvider({
|
||||||
|
api: "openai-responses",
|
||||||
|
stream: streamOpenAIResponses,
|
||||||
|
streamSimple: streamSimpleOpenAIResponses,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function createClient(
|
function createClient(
|
||||||
model: Model<"openai-responses">,
|
model: Model<"openai-responses">,
|
||||||
context: Context,
|
context: Context,
|
||||||
|
|||||||
@@ -1,9 +1,14 @@
|
|||||||
import { clearApiProviders, registerApiProvider } from "../api-registry.ts";
|
import { type ApiProvider, clearApiProviders, getApiProvider, registerApiProvider } from "../api-registry.ts";
|
||||||
|
import { getImagesApiProvider, type ImagesApiProvider, registerImagesApiProvider } from "../images-api-registry.ts";
|
||||||
import type {
|
import type {
|
||||||
Api,
|
Api,
|
||||||
|
AssistantImages,
|
||||||
AssistantMessage,
|
AssistantMessage,
|
||||||
AssistantMessageEvent,
|
AssistantMessageEvent,
|
||||||
Context,
|
ImagesApi,
|
||||||
|
ImagesContext,
|
||||||
|
ImagesModel,
|
||||||
|
ImagesOptions,
|
||||||
Model,
|
Model,
|
||||||
SimpleStreamOptions,
|
SimpleStreamOptions,
|
||||||
StreamFunction,
|
StreamFunction,
|
||||||
@@ -20,70 +25,47 @@ import type { OpenAICodexResponsesOptions } from "./openai-codex-responses.ts";
|
|||||||
import type { OpenAICompletionsOptions } from "./openai-completions.ts";
|
import type { OpenAICompletionsOptions } from "./openai-completions.ts";
|
||||||
import type { OpenAIResponsesOptions } from "./openai-responses.ts";
|
import type { OpenAIResponsesOptions } from "./openai-responses.ts";
|
||||||
|
|
||||||
interface LazyProviderModule<
|
interface RegisteringProviderModule {
|
||||||
TApi extends Api,
|
register(): void;
|
||||||
TOptions extends StreamOptions,
|
|
||||||
TSimpleOptions extends SimpleStreamOptions,
|
|
||||||
> {
|
|
||||||
stream: (model: Model<TApi>, context: Context, options?: TOptions) => AsyncIterable<AssistantMessageEvent>;
|
|
||||||
streamSimple: (
|
|
||||||
model: Model<TApi>,
|
|
||||||
context: Context,
|
|
||||||
options?: TSimpleOptions,
|
|
||||||
) => AsyncIterable<AssistantMessageEvent>;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
interface AnthropicProviderModule {
|
function createLazyLoadErrorImages(model: ImagesModel<"openrouter-images">, error: unknown): AssistantImages {
|
||||||
streamAnthropic: StreamFunction<"anthropic-messages", AnthropicOptions>;
|
return {
|
||||||
streamSimpleAnthropic: StreamFunction<"anthropic-messages", SimpleStreamOptions>;
|
api: model.api,
|
||||||
|
provider: model.provider,
|
||||||
|
model: model.id,
|
||||||
|
output: [],
|
||||||
|
stopReason: "error",
|
||||||
|
errorMessage: error instanceof Error ? error.message : String(error),
|
||||||
|
timestamp: Date.now(),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
interface AzureOpenAIResponsesProviderModule {
|
function createLazyImagesApiProvider<TApi extends ImagesApi, TOptions extends ImagesOptions>(
|
||||||
streamAzureOpenAIResponses: StreamFunction<"azure-openai-responses", AzureOpenAIResponsesOptions>;
|
api: TApi,
|
||||||
streamSimpleAzureOpenAIResponses: StreamFunction<"azure-openai-responses", SimpleStreamOptions>;
|
loadModule: () => Promise<RegisteringProviderModule>,
|
||||||
}
|
): ImagesApiProvider<TApi, TOptions> {
|
||||||
|
return {
|
||||||
interface GoogleProviderModule {
|
api,
|
||||||
streamGoogle: StreamFunction<"google-generative-ai", GoogleOptions>;
|
generateImages: async (model: ImagesModel<TApi>, context: ImagesContext, options?: TOptions) => {
|
||||||
streamSimpleGoogle: StreamFunction<"google-generative-ai", SimpleStreamOptions>;
|
try {
|
||||||
}
|
const module = await loadModule();
|
||||||
|
module.register();
|
||||||
interface GoogleVertexProviderModule {
|
const provider = getImagesApiProvider(api);
|
||||||
streamGoogleVertex: StreamFunction<"google-vertex", GoogleVertexOptions>;
|
if (!provider) {
|
||||||
streamSimpleGoogleVertex: StreamFunction<"google-vertex", SimpleStreamOptions>;
|
throw new Error(`No API provider registered for api: ${api}`);
|
||||||
}
|
}
|
||||||
|
return await provider.generateImages(model, context, options);
|
||||||
interface MistralProviderModule {
|
} catch (error) {
|
||||||
streamMistral: StreamFunction<"mistral-conversations", MistralOptions>;
|
return createLazyLoadErrorImages(model as ImagesModel<"openrouter-images">, error);
|
||||||
streamSimpleMistral: StreamFunction<"mistral-conversations", SimpleStreamOptions>;
|
}
|
||||||
}
|
},
|
||||||
|
};
|
||||||
interface OpenAICodexResponsesProviderModule {
|
|
||||||
streamOpenAICodexResponses: StreamFunction<"openai-codex-responses", OpenAICodexResponsesOptions>;
|
|
||||||
streamSimpleOpenAICodexResponses: StreamFunction<"openai-codex-responses", SimpleStreamOptions>;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface OpenAICompletionsProviderModule {
|
|
||||||
streamOpenAICompletions: StreamFunction<"openai-completions", OpenAICompletionsOptions>;
|
|
||||||
streamSimpleOpenAICompletions: StreamFunction<"openai-completions", SimpleStreamOptions>;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface OpenAIResponsesProviderModule {
|
|
||||||
streamOpenAIResponses: StreamFunction<"openai-responses", OpenAIResponsesOptions>;
|
|
||||||
streamSimpleOpenAIResponses: StreamFunction<"openai-responses", SimpleStreamOptions>;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
interface BedrockProviderModule {
|
interface BedrockProviderModule {
|
||||||
streamBedrock: (
|
streamBedrock: StreamFunction<"bedrock-converse-stream", BedrockOptions>;
|
||||||
model: Model<"bedrock-converse-stream">,
|
streamSimpleBedrock: StreamFunction<"bedrock-converse-stream", SimpleStreamOptions>;
|
||||||
context: Context,
|
|
||||||
options?: BedrockOptions,
|
|
||||||
) => AsyncIterable<AssistantMessageEvent>;
|
|
||||||
streamSimpleBedrock: (
|
|
||||||
model: Model<"bedrock-converse-stream">,
|
|
||||||
context: Context,
|
|
||||||
options?: SimpleStreamOptions,
|
|
||||||
) => AsyncIterable<AssistantMessageEvent>;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const importNodeOnlyProvider = (specifier: string): Promise<unknown> => {
|
const importNodeOnlyProvider = (specifier: string): Promise<unknown> => {
|
||||||
@@ -91,42 +73,10 @@ const importNodeOnlyProvider = (specifier: string): Promise<unknown> => {
|
|||||||
return import(runtimeSpecifier);
|
return import(runtimeSpecifier);
|
||||||
};
|
};
|
||||||
|
|
||||||
let anthropicProviderModulePromise:
|
let bedrockProviderModuleOverride: BedrockProviderModule | undefined;
|
||||||
| Promise<LazyProviderModule<"anthropic-messages", AnthropicOptions, SimpleStreamOptions>>
|
|
||||||
| undefined;
|
|
||||||
let azureOpenAIResponsesProviderModulePromise:
|
|
||||||
| Promise<LazyProviderModule<"azure-openai-responses", AzureOpenAIResponsesOptions, SimpleStreamOptions>>
|
|
||||||
| undefined;
|
|
||||||
let googleProviderModulePromise:
|
|
||||||
| Promise<LazyProviderModule<"google-generative-ai", GoogleOptions, SimpleStreamOptions>>
|
|
||||||
| undefined;
|
|
||||||
let googleVertexProviderModulePromise:
|
|
||||||
| Promise<LazyProviderModule<"google-vertex", GoogleVertexOptions, SimpleStreamOptions>>
|
|
||||||
| undefined;
|
|
||||||
let mistralProviderModulePromise:
|
|
||||||
| Promise<LazyProviderModule<"mistral-conversations", MistralOptions, SimpleStreamOptions>>
|
|
||||||
| undefined;
|
|
||||||
let openAICodexResponsesProviderModulePromise:
|
|
||||||
| Promise<LazyProviderModule<"openai-codex-responses", OpenAICodexResponsesOptions, SimpleStreamOptions>>
|
|
||||||
| undefined;
|
|
||||||
let openAICompletionsProviderModulePromise:
|
|
||||||
| Promise<LazyProviderModule<"openai-completions", OpenAICompletionsOptions, SimpleStreamOptions>>
|
|
||||||
| undefined;
|
|
||||||
let openAIResponsesProviderModulePromise:
|
|
||||||
| Promise<LazyProviderModule<"openai-responses", OpenAIResponsesOptions, SimpleStreamOptions>>
|
|
||||||
| undefined;
|
|
||||||
let bedrockProviderModuleOverride:
|
|
||||||
| LazyProviderModule<"bedrock-converse-stream", BedrockOptions, SimpleStreamOptions>
|
|
||||||
| undefined;
|
|
||||||
let bedrockProviderModulePromise:
|
|
||||||
| Promise<LazyProviderModule<"bedrock-converse-stream", BedrockOptions, SimpleStreamOptions>>
|
|
||||||
| undefined;
|
|
||||||
|
|
||||||
export function setBedrockProviderModule(module: BedrockProviderModule): void {
|
export function setBedrockProviderModule(module: BedrockProviderModule): void {
|
||||||
bedrockProviderModuleOverride = {
|
bedrockProviderModuleOverride = module;
|
||||||
stream: module.streamBedrock,
|
|
||||||
streamSimple: module.streamSimpleBedrock,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function forwardStream(target: AssistantMessageEventStream, source: AsyncIterable<AssistantMessageEvent>): void {
|
function forwardStream(target: AssistantMessageEventStream, source: AsyncIterable<AssistantMessageEvent>): void {
|
||||||
@@ -159,15 +109,29 @@ function createLazyLoadErrorMessage<TApi extends Api>(model: Model<TApi>, error:
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function createLazyStream<TApi extends Api, TOptions extends StreamOptions, TSimpleOptions extends SimpleStreamOptions>(
|
async function loadAndRegisterProvider<TApi extends Api>(
|
||||||
loadModule: () => Promise<LazyProviderModule<TApi, TOptions, TSimpleOptions>>,
|
api: TApi,
|
||||||
|
loadModule: () => Promise<RegisteringProviderModule>,
|
||||||
|
) {
|
||||||
|
const module = await loadModule();
|
||||||
|
module.register();
|
||||||
|
const provider = getApiProvider(api);
|
||||||
|
if (!provider) {
|
||||||
|
throw new Error(`No API provider registered for api: ${api}`);
|
||||||
|
}
|
||||||
|
return provider;
|
||||||
|
}
|
||||||
|
|
||||||
|
function createLazyStream<TApi extends Api, TOptions extends StreamOptions>(
|
||||||
|
api: TApi,
|
||||||
|
loadModule: () => Promise<RegisteringProviderModule>,
|
||||||
): StreamFunction<TApi, TOptions> {
|
): StreamFunction<TApi, TOptions> {
|
||||||
return (model, context, options) => {
|
return (model, context, options) => {
|
||||||
const outer = new AssistantMessageEventStream();
|
const outer = new AssistantMessageEventStream();
|
||||||
|
|
||||||
loadModule()
|
loadAndRegisterProvider(api, loadModule)
|
||||||
.then((module) => {
|
.then((provider) => {
|
||||||
const inner = module.stream(model, context, options);
|
const inner = provider.stream(model, context, options);
|
||||||
forwardStream(outer, inner);
|
forwardStream(outer, inner);
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
@@ -180,17 +144,16 @@ function createLazyStream<TApi extends Api, TOptions extends StreamOptions, TSim
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function createLazySimpleStream<
|
function createLazySimpleStream<TApi extends Api>(
|
||||||
TApi extends Api,
|
api: TApi,
|
||||||
TOptions extends StreamOptions,
|
loadModule: () => Promise<RegisteringProviderModule>,
|
||||||
TSimpleOptions extends SimpleStreamOptions,
|
): StreamFunction<TApi, SimpleStreamOptions> {
|
||||||
>(loadModule: () => Promise<LazyProviderModule<TApi, TOptions, TSimpleOptions>>): StreamFunction<TApi, TSimpleOptions> {
|
|
||||||
return (model, context, options) => {
|
return (model, context, options) => {
|
||||||
const outer = new AssistantMessageEventStream();
|
const outer = new AssistantMessageEventStream();
|
||||||
|
|
||||||
loadModule()
|
loadAndRegisterProvider(api, loadModule)
|
||||||
.then((module) => {
|
.then((provider) => {
|
||||||
const inner = module.streamSimple(model, context, options);
|
const inner = provider.streamSimple(model, context, options);
|
||||||
forwardStream(outer, inner);
|
forwardStream(outer, inner);
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
@@ -203,201 +166,114 @@ function createLazySimpleStream<
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function loadAnthropicProviderModule(): Promise<
|
function createLazyApiProvider<TApi extends Api, TOptions extends StreamOptions>(
|
||||||
LazyProviderModule<"anthropic-messages", AnthropicOptions, SimpleStreamOptions>
|
api: TApi,
|
||||||
> {
|
loadModule: () => Promise<RegisteringProviderModule>,
|
||||||
anthropicProviderModulePromise ||= import("./anthropic.ts").then((module) => {
|
): ApiProvider<TApi, TOptions> {
|
||||||
const provider = module as AnthropicProviderModule;
|
return {
|
||||||
return {
|
api,
|
||||||
stream: provider.streamAnthropic,
|
stream: createLazyStream<TApi, TOptions>(api, loadModule),
|
||||||
streamSimple: provider.streamSimpleAnthropic,
|
streamSimple: createLazySimpleStream(api, loadModule),
|
||||||
};
|
};
|
||||||
});
|
|
||||||
return anthropicProviderModulePromise;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function loadAzureOpenAIResponsesProviderModule(): Promise<
|
function registerBedrockProviderModule(module: BedrockProviderModule): void {
|
||||||
LazyProviderModule<"azure-openai-responses", AzureOpenAIResponsesOptions, SimpleStreamOptions>
|
|
||||||
> {
|
|
||||||
azureOpenAIResponsesProviderModulePromise ||= import("./azure-openai-responses.ts").then((module) => {
|
|
||||||
const provider = module as AzureOpenAIResponsesProviderModule;
|
|
||||||
return {
|
|
||||||
stream: provider.streamAzureOpenAIResponses,
|
|
||||||
streamSimple: provider.streamSimpleAzureOpenAIResponses,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
return azureOpenAIResponsesProviderModulePromise;
|
|
||||||
}
|
|
||||||
|
|
||||||
function loadGoogleProviderModule(): Promise<
|
|
||||||
LazyProviderModule<"google-generative-ai", GoogleOptions, SimpleStreamOptions>
|
|
||||||
> {
|
|
||||||
googleProviderModulePromise ||= import("./google.ts").then((module) => {
|
|
||||||
const provider = module as GoogleProviderModule;
|
|
||||||
return {
|
|
||||||
stream: provider.streamGoogle,
|
|
||||||
streamSimple: provider.streamSimpleGoogle,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
return googleProviderModulePromise;
|
|
||||||
}
|
|
||||||
|
|
||||||
function loadGoogleVertexProviderModule(): Promise<
|
|
||||||
LazyProviderModule<"google-vertex", GoogleVertexOptions, SimpleStreamOptions>
|
|
||||||
> {
|
|
||||||
googleVertexProviderModulePromise ||= import("./google-vertex.ts").then((module) => {
|
|
||||||
const provider = module as GoogleVertexProviderModule;
|
|
||||||
return {
|
|
||||||
stream: provider.streamGoogleVertex,
|
|
||||||
streamSimple: provider.streamSimpleGoogleVertex,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
return googleVertexProviderModulePromise;
|
|
||||||
}
|
|
||||||
|
|
||||||
function loadMistralProviderModule(): Promise<
|
|
||||||
LazyProviderModule<"mistral-conversations", MistralOptions, SimpleStreamOptions>
|
|
||||||
> {
|
|
||||||
mistralProviderModulePromise ||= import("./mistral.ts").then((module) => {
|
|
||||||
const provider = module as MistralProviderModule;
|
|
||||||
return {
|
|
||||||
stream: provider.streamMistral,
|
|
||||||
streamSimple: provider.streamSimpleMistral,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
return mistralProviderModulePromise;
|
|
||||||
}
|
|
||||||
|
|
||||||
function loadOpenAICodexResponsesProviderModule(): Promise<
|
|
||||||
LazyProviderModule<"openai-codex-responses", OpenAICodexResponsesOptions, SimpleStreamOptions>
|
|
||||||
> {
|
|
||||||
openAICodexResponsesProviderModulePromise ||= import("./openai-codex-responses.ts").then((module) => {
|
|
||||||
const provider = module as OpenAICodexResponsesProviderModule;
|
|
||||||
return {
|
|
||||||
stream: provider.streamOpenAICodexResponses,
|
|
||||||
streamSimple: provider.streamSimpleOpenAICodexResponses,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
return openAICodexResponsesProviderModulePromise;
|
|
||||||
}
|
|
||||||
|
|
||||||
function loadOpenAICompletionsProviderModule(): Promise<
|
|
||||||
LazyProviderModule<"openai-completions", OpenAICompletionsOptions, SimpleStreamOptions>
|
|
||||||
> {
|
|
||||||
openAICompletionsProviderModulePromise ||= import("./openai-completions.ts").then((module) => {
|
|
||||||
const provider = module as OpenAICompletionsProviderModule;
|
|
||||||
return {
|
|
||||||
stream: provider.streamOpenAICompletions,
|
|
||||||
streamSimple: provider.streamSimpleOpenAICompletions,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
return openAICompletionsProviderModulePromise;
|
|
||||||
}
|
|
||||||
|
|
||||||
function loadOpenAIResponsesProviderModule(): Promise<
|
|
||||||
LazyProviderModule<"openai-responses", OpenAIResponsesOptions, SimpleStreamOptions>
|
|
||||||
> {
|
|
||||||
openAIResponsesProviderModulePromise ||= import("./openai-responses.ts").then((module) => {
|
|
||||||
const provider = module as OpenAIResponsesProviderModule;
|
|
||||||
return {
|
|
||||||
stream: provider.streamOpenAIResponses,
|
|
||||||
streamSimple: provider.streamSimpleOpenAIResponses,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
return openAIResponsesProviderModulePromise;
|
|
||||||
}
|
|
||||||
|
|
||||||
function loadBedrockProviderModule(): Promise<
|
|
||||||
LazyProviderModule<"bedrock-converse-stream", BedrockOptions, SimpleStreamOptions>
|
|
||||||
> {
|
|
||||||
if (bedrockProviderModuleOverride) {
|
|
||||||
return Promise.resolve(bedrockProviderModuleOverride);
|
|
||||||
}
|
|
||||||
bedrockProviderModulePromise ||= importNodeOnlyProvider("./amazon-bedrock.ts").then((module) => {
|
|
||||||
const provider = module as BedrockProviderModule;
|
|
||||||
return {
|
|
||||||
stream: provider.streamBedrock,
|
|
||||||
streamSimple: provider.streamSimpleBedrock,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
return bedrockProviderModulePromise;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const streamAnthropic = createLazyStream(loadAnthropicProviderModule);
|
|
||||||
export const streamSimpleAnthropic = createLazySimpleStream(loadAnthropicProviderModule);
|
|
||||||
export const streamAzureOpenAIResponses = createLazyStream(loadAzureOpenAIResponsesProviderModule);
|
|
||||||
export const streamSimpleAzureOpenAIResponses = createLazySimpleStream(loadAzureOpenAIResponsesProviderModule);
|
|
||||||
export const streamGoogle = createLazyStream(loadGoogleProviderModule);
|
|
||||||
export const streamSimpleGoogle = createLazySimpleStream(loadGoogleProviderModule);
|
|
||||||
export const streamGoogleVertex = createLazyStream(loadGoogleVertexProviderModule);
|
|
||||||
export const streamSimpleGoogleVertex = createLazySimpleStream(loadGoogleVertexProviderModule);
|
|
||||||
export const streamMistral = createLazyStream(loadMistralProviderModule);
|
|
||||||
export const streamSimpleMistral = createLazySimpleStream(loadMistralProviderModule);
|
|
||||||
export const streamOpenAICodexResponses = createLazyStream(loadOpenAICodexResponsesProviderModule);
|
|
||||||
export const streamSimpleOpenAICodexResponses = createLazySimpleStream(loadOpenAICodexResponsesProviderModule);
|
|
||||||
export const streamOpenAICompletions = createLazyStream(loadOpenAICompletionsProviderModule);
|
|
||||||
export const streamSimpleOpenAICompletions = createLazySimpleStream(loadOpenAICompletionsProviderModule);
|
|
||||||
export const streamOpenAIResponses = createLazyStream(loadOpenAIResponsesProviderModule);
|
|
||||||
export const streamSimpleOpenAIResponses = createLazySimpleStream(loadOpenAIResponsesProviderModule);
|
|
||||||
const streamBedrockLazy = createLazyStream(loadBedrockProviderModule);
|
|
||||||
const streamSimpleBedrockLazy = createLazySimpleStream(loadBedrockProviderModule);
|
|
||||||
|
|
||||||
export function registerBuiltInApiProviders(): void {
|
|
||||||
registerApiProvider({
|
|
||||||
api: "anthropic-messages",
|
|
||||||
stream: streamAnthropic,
|
|
||||||
streamSimple: streamSimpleAnthropic,
|
|
||||||
});
|
|
||||||
|
|
||||||
registerApiProvider({
|
|
||||||
api: "openai-completions",
|
|
||||||
stream: streamOpenAICompletions,
|
|
||||||
streamSimple: streamSimpleOpenAICompletions,
|
|
||||||
});
|
|
||||||
|
|
||||||
registerApiProvider({
|
|
||||||
api: "mistral-conversations",
|
|
||||||
stream: streamMistral,
|
|
||||||
streamSimple: streamSimpleMistral,
|
|
||||||
});
|
|
||||||
|
|
||||||
registerApiProvider({
|
|
||||||
api: "openai-responses",
|
|
||||||
stream: streamOpenAIResponses,
|
|
||||||
streamSimple: streamSimpleOpenAIResponses,
|
|
||||||
});
|
|
||||||
|
|
||||||
registerApiProvider({
|
|
||||||
api: "azure-openai-responses",
|
|
||||||
stream: streamAzureOpenAIResponses,
|
|
||||||
streamSimple: streamSimpleAzureOpenAIResponses,
|
|
||||||
});
|
|
||||||
|
|
||||||
registerApiProvider({
|
|
||||||
api: "openai-codex-responses",
|
|
||||||
stream: streamOpenAICodexResponses,
|
|
||||||
streamSimple: streamSimpleOpenAICodexResponses,
|
|
||||||
});
|
|
||||||
|
|
||||||
registerApiProvider({
|
|
||||||
api: "google-generative-ai",
|
|
||||||
stream: streamGoogle,
|
|
||||||
streamSimple: streamSimpleGoogle,
|
|
||||||
});
|
|
||||||
|
|
||||||
registerApiProvider({
|
|
||||||
api: "google-vertex",
|
|
||||||
stream: streamGoogleVertex,
|
|
||||||
streamSimple: streamSimpleGoogleVertex,
|
|
||||||
});
|
|
||||||
|
|
||||||
registerApiProvider({
|
registerApiProvider({
|
||||||
api: "bedrock-converse-stream",
|
api: "bedrock-converse-stream",
|
||||||
stream: streamBedrockLazy,
|
stream: module.streamBedrock,
|
||||||
streamSimple: streamSimpleBedrockLazy,
|
streamSimple: module.streamSimpleBedrock,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function loadBedrockProviderModule(): Promise<RegisteringProviderModule> {
|
||||||
|
const module = bedrockProviderModuleOverride;
|
||||||
|
if (module) {
|
||||||
|
return Promise.resolve({ register: () => registerBedrockProviderModule(module) });
|
||||||
|
}
|
||||||
|
return importNodeOnlyProvider("./amazon-bedrock.ts").then((provider) => provider as RegisteringProviderModule);
|
||||||
|
}
|
||||||
|
|
||||||
|
const anthropicProvider = createLazyApiProvider<"anthropic-messages", AnthropicOptions>(
|
||||||
|
"anthropic-messages",
|
||||||
|
() => import("./anthropic.ts"),
|
||||||
|
);
|
||||||
|
const azureOpenAIResponsesProvider = createLazyApiProvider<"azure-openai-responses", AzureOpenAIResponsesOptions>(
|
||||||
|
"azure-openai-responses",
|
||||||
|
() => import("./azure-openai-responses.ts"),
|
||||||
|
);
|
||||||
|
const googleProvider = createLazyApiProvider<"google-generative-ai", GoogleOptions>(
|
||||||
|
"google-generative-ai",
|
||||||
|
() => import("./google.ts"),
|
||||||
|
);
|
||||||
|
const googleVertexProvider = createLazyApiProvider<"google-vertex", GoogleVertexOptions>(
|
||||||
|
"google-vertex",
|
||||||
|
() => import("./google-vertex.ts"),
|
||||||
|
);
|
||||||
|
const mistralProvider = createLazyApiProvider<"mistral-conversations", MistralOptions>(
|
||||||
|
"mistral-conversations",
|
||||||
|
() => import("./mistral.ts"),
|
||||||
|
);
|
||||||
|
const openAICodexResponsesProvider = createLazyApiProvider<"openai-codex-responses", OpenAICodexResponsesOptions>(
|
||||||
|
"openai-codex-responses",
|
||||||
|
() => import("./openai-codex-responses.ts"),
|
||||||
|
);
|
||||||
|
const openAICompletionsProvider = createLazyApiProvider<"openai-completions", OpenAICompletionsOptions>(
|
||||||
|
"openai-completions",
|
||||||
|
() => import("./openai-completions.ts"),
|
||||||
|
);
|
||||||
|
const openAIResponsesProvider = createLazyApiProvider<"openai-responses", OpenAIResponsesOptions>(
|
||||||
|
"openai-responses",
|
||||||
|
() => import("./openai-responses.ts"),
|
||||||
|
);
|
||||||
|
const bedrockProvider = createLazyApiProvider<"bedrock-converse-stream", BedrockOptions>(
|
||||||
|
"bedrock-converse-stream",
|
||||||
|
loadBedrockProviderModule,
|
||||||
|
);
|
||||||
|
const openRouterImagesProvider = createLazyImagesApiProvider(
|
||||||
|
"openrouter-images",
|
||||||
|
() => import("./images/openrouter.ts"),
|
||||||
|
);
|
||||||
|
|
||||||
|
export const generateImagesOpenRouter = openRouterImagesProvider.generateImages;
|
||||||
|
export const streamAnthropic = anthropicProvider.stream;
|
||||||
|
export const streamSimpleAnthropic = anthropicProvider.streamSimple;
|
||||||
|
export const streamAzureOpenAIResponses = azureOpenAIResponsesProvider.stream;
|
||||||
|
export const streamSimpleAzureOpenAIResponses = azureOpenAIResponsesProvider.streamSimple;
|
||||||
|
export const streamGoogle = googleProvider.stream;
|
||||||
|
export const streamSimpleGoogle = googleProvider.streamSimple;
|
||||||
|
export const streamGoogleVertex = googleVertexProvider.stream;
|
||||||
|
export const streamSimpleGoogleVertex = googleVertexProvider.streamSimple;
|
||||||
|
export const streamMistral = mistralProvider.stream;
|
||||||
|
export const streamSimpleMistral = mistralProvider.streamSimple;
|
||||||
|
export const streamOpenAICodexResponses = openAICodexResponsesProvider.stream;
|
||||||
|
export const streamSimpleOpenAICodexResponses = openAICodexResponsesProvider.streamSimple;
|
||||||
|
export const streamOpenAICompletions = openAICompletionsProvider.stream;
|
||||||
|
export const streamSimpleOpenAICompletions = openAICompletionsProvider.streamSimple;
|
||||||
|
export const streamOpenAIResponses = openAIResponsesProvider.stream;
|
||||||
|
export const streamSimpleOpenAIResponses = openAIResponsesProvider.streamSimple;
|
||||||
|
|
||||||
|
const registerBuiltInApiProviderFunctions = [
|
||||||
|
() => registerApiProvider(anthropicProvider),
|
||||||
|
() => registerApiProvider(openAICompletionsProvider),
|
||||||
|
() => registerApiProvider(mistralProvider),
|
||||||
|
() => registerApiProvider(openAIResponsesProvider),
|
||||||
|
() => registerApiProvider(azureOpenAIResponsesProvider),
|
||||||
|
() => registerApiProvider(openAICodexResponsesProvider),
|
||||||
|
() => registerApiProvider(googleProvider),
|
||||||
|
() => registerApiProvider(googleVertexProvider),
|
||||||
|
() => registerApiProvider(bedrockProvider),
|
||||||
|
];
|
||||||
|
|
||||||
|
export function registerBuiltInImagesApiProviders(): void {
|
||||||
|
registerImagesApiProvider(openRouterImagesProvider);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function registerBuiltInApiProviders(): void {
|
||||||
|
for (const register of registerBuiltInApiProviderFunctions) {
|
||||||
|
register();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export function resetApiProviders(): void {
|
export function resetApiProviders(): void {
|
||||||
clearApiProviders();
|
clearApiProviders();
|
||||||
registerBuiltInApiProviders();
|
registerBuiltInApiProviders();
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
import "./providers/register-builtins.ts";
|
|
||||||
|
|
||||||
import { getApiProvider } from "./api-registry.ts";
|
import { getApiProvider } from "./api-registry.ts";
|
||||||
import { getEnvApiKey } from "./env-api-keys.ts";
|
import { getEnvApiKey } from "./env-api-keys.ts";
|
||||||
import type {
|
import type {
|
||||||
@@ -13,8 +11,6 @@ import type {
|
|||||||
StreamOptions,
|
StreamOptions,
|
||||||
} from "./types.ts";
|
} from "./types.ts";
|
||||||
|
|
||||||
export { getEnvApiKey } from "./env-api-keys.ts";
|
|
||||||
|
|
||||||
function hasExplicitApiKey(apiKey: string | undefined): apiKey is string {
|
function hasExplicitApiKey(apiKey: string | undefined): apiKey is string {
|
||||||
return typeof apiKey === "string" && apiKey.trim().length > 0;
|
return typeof apiKey === "string" && apiKey.trim().length > 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { describe, expect, it } from "vitest";
|
import { describe, expect, it } from "vitest";
|
||||||
|
import { complete, stream } from "../src/index.ts";
|
||||||
import { getModel } from "../src/models.ts";
|
import { getModel } from "../src/models.ts";
|
||||||
import { complete, stream } from "../src/stream.ts";
|
|
||||||
import type { Api, Context, Model, StreamOptions } from "../src/types.ts";
|
import type { Api, Context, Model, StreamOptions } from "../src/types.ts";
|
||||||
|
|
||||||
type StreamOptionsWithExtras = StreamOptions & Record<string, unknown>;
|
type StreamOptionsWithExtras = StreamOptions & Record<string, unknown>;
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import { Type } from "typebox";
|
import { Type } from "typebox";
|
||||||
import { describe, expect, it } from "vitest";
|
import { describe, expect, it } from "vitest";
|
||||||
import { getEnvApiKey } from "../src/env-api-keys.ts";
|
import { getEnvApiKey } from "../src/env-api-keys.ts";
|
||||||
|
import { complete } from "../src/index.ts";
|
||||||
import { getModels, getProviders } from "../src/models.ts";
|
import { getModels, getProviders } from "../src/models.ts";
|
||||||
import { complete } from "../src/stream.ts";
|
|
||||||
import type { Api, KnownProvider, Model, ProviderStreamOptions, Tool } from "../src/types.ts";
|
import type { Api, KnownProvider, Model, ProviderStreamOptions, Tool } from "../src/types.ts";
|
||||||
import { resolveApiKey } from "./oauth.ts";
|
import { resolveApiKey } from "./oauth.ts";
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { describe, expect, it } from "vitest";
|
import { describe, expect, it } from "vitest";
|
||||||
import { streamSimple } from "../src/stream.ts";
|
import { streamSimple } from "../src/index.ts";
|
||||||
import type { AssistantMessage, Context, Model } from "../src/types.ts";
|
import type { AssistantMessage, Context, Model } from "../src/types.ts";
|
||||||
|
|
||||||
interface AnthropicPayload {
|
interface AnthropicPayload {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { describe, expect, it } from "vitest";
|
import { describe, expect, it } from "vitest";
|
||||||
|
import { streamSimple } from "../src/index.ts";
|
||||||
import { getModel } from "../src/models.ts";
|
import { getModel } from "../src/models.ts";
|
||||||
import { streamSimple } from "../src/stream.ts";
|
|
||||||
import type { Context, Model, SimpleStreamOptions } from "../src/types.ts";
|
import type { Context, Model, SimpleStreamOptions } from "../src/types.ts";
|
||||||
|
|
||||||
interface AnthropicThinkingPayload {
|
interface AnthropicThinkingPayload {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { describe, expect, it } from "vitest";
|
import { describe, expect, it } from "vitest";
|
||||||
import { getEnvApiKey } from "../src/env-api-keys.ts";
|
import { getEnvApiKey } from "../src/env-api-keys.ts";
|
||||||
|
import { complete } from "../src/index.ts";
|
||||||
import { getModels, getProviders } from "../src/models.ts";
|
import { getModels, getProviders } from "../src/models.ts";
|
||||||
import { complete } from "../src/stream.ts";
|
|
||||||
import type { Api, KnownProvider, Model, ProviderStreamOptions } from "../src/types.ts";
|
import type { Api, KnownProvider, Model, ProviderStreamOptions } from "../src/types.ts";
|
||||||
import { resolveApiKey } from "./oauth.ts";
|
import { resolveApiKey } from "./oauth.ts";
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { describe, expect, it } from "vitest";
|
import { describe, expect, it } from "vitest";
|
||||||
|
import { streamSimple } from "../src/index.ts";
|
||||||
import { getModel } from "../src/models.ts";
|
import { getModel } from "../src/models.ts";
|
||||||
import { streamSimple } from "../src/stream.ts";
|
|
||||||
import type { Context } from "../src/types.ts";
|
import type { Context } from "../src/types.ts";
|
||||||
|
|
||||||
interface AnthropicThinkingPayload {
|
interface AnthropicThinkingPayload {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { describe, expect, it } from "vitest";
|
import { describe, expect, it } from "vitest";
|
||||||
|
import { streamSimple } from "../src/index.ts";
|
||||||
import { getModel } from "../src/models.ts";
|
import { getModel } from "../src/models.ts";
|
||||||
import { streamSimple } from "../src/stream.ts";
|
|
||||||
import type { Context, Model, SimpleStreamOptions } from "../src/types.ts";
|
import type { Context, Model, SimpleStreamOptions } from "../src/types.ts";
|
||||||
|
|
||||||
interface AnthropicTemperaturePayload {
|
interface AnthropicTemperaturePayload {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { describe, expect, it } from "vitest";
|
import { describe, expect, it } from "vitest";
|
||||||
|
import { streamSimple } from "../src/index.ts";
|
||||||
import { getModel } from "../src/models.ts";
|
import { getModel } from "../src/models.ts";
|
||||||
import { streamSimple } from "../src/stream.ts";
|
|
||||||
import type { Context, Model, SimpleStreamOptions } from "../src/types.ts";
|
import type { Context, Model, SimpleStreamOptions } from "../src/types.ts";
|
||||||
|
|
||||||
interface AnthropicThinkingPayload {
|
interface AnthropicThinkingPayload {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { Type } from "typebox";
|
import { Type } from "typebox";
|
||||||
import { describe, expect, it } from "vitest";
|
import { describe, expect, it } from "vitest";
|
||||||
|
import { stream } from "../src/index.ts";
|
||||||
import { getModel } from "../src/models.ts";
|
import { getModel } from "../src/models.ts";
|
||||||
import { stream } from "../src/stream.ts";
|
|
||||||
import type { Context, Tool } from "../src/types.ts";
|
import type { Context, Tool } from "../src/types.ts";
|
||||||
import { resolveApiKey } from "./oauth.ts";
|
import { resolveApiKey } from "./oauth.ts";
|
||||||
|
|
||||||
|
|||||||
68
packages/ai/test/base-entrypoint.test.ts
Normal file
68
packages/ai/test/base-entrypoint.test.ts
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
import { afterEach, describe, expect, it } from "vitest";
|
||||||
|
import { clearApiProviders, complete, getApiProvider, getApiProviders } from "../src/base.ts";
|
||||||
|
import { register as registerAmazonBedrock } from "../src/providers/amazon-bedrock.ts";
|
||||||
|
import { register as registerAnthropic } from "../src/providers/anthropic.ts";
|
||||||
|
import { register as registerAzureOpenAIResponses } from "../src/providers/azure-openai-responses.ts";
|
||||||
|
import { fauxAssistantMessage, registerFauxProvider } from "../src/providers/faux.ts";
|
||||||
|
import { register as registerGoogle } from "../src/providers/google.ts";
|
||||||
|
import { register as registerGoogleVertex } from "../src/providers/google-vertex.ts";
|
||||||
|
import { register as registerMistral } from "../src/providers/mistral.ts";
|
||||||
|
import { register as registerOpenAICodexResponses } from "../src/providers/openai-codex-responses.ts";
|
||||||
|
import { register as registerOpenAICompletions } from "../src/providers/openai-completions.ts";
|
||||||
|
import { register as registerOpenAIResponses } from "../src/providers/openai-responses.ts";
|
||||||
|
|
||||||
|
const registrations = [
|
||||||
|
["bedrock-converse-stream", registerAmazonBedrock],
|
||||||
|
["anthropic-messages", registerAnthropic],
|
||||||
|
["azure-openai-responses", registerAzureOpenAIResponses],
|
||||||
|
["google-generative-ai", registerGoogle],
|
||||||
|
["google-vertex", registerGoogleVertex],
|
||||||
|
["mistral-conversations", registerMistral],
|
||||||
|
["openai-codex-responses", registerOpenAICodexResponses],
|
||||||
|
["openai-completions", registerOpenAICompletions],
|
||||||
|
["openai-responses", registerOpenAIResponses],
|
||||||
|
] as const;
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
clearApiProviders();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("base entrypoint", () => {
|
||||||
|
it("starts without built-in provider registrations", () => {
|
||||||
|
expect(getApiProviders()).toEqual([]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it.each(registrations)("registers the %s transport explicitly", (api, register) => {
|
||||||
|
register();
|
||||||
|
expect(getApiProvider(api)?.api).toBe(api);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("dispatches custom providers", async () => {
|
||||||
|
const registration = registerFauxProvider();
|
||||||
|
registration.setResponses([fauxAssistantMessage("hello")]);
|
||||||
|
const response = await complete(registration.getModel(), {
|
||||||
|
messages: [{ role: "user", content: "hi", timestamp: Date.now() }],
|
||||||
|
});
|
||||||
|
expect(response.content).toEqual([{ type: "text", text: "hello" }]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("fails clearly when no transport is registered", async () => {
|
||||||
|
await expect(
|
||||||
|
complete(
|
||||||
|
{
|
||||||
|
id: "missing-model",
|
||||||
|
name: "Missing Model",
|
||||||
|
api: "missing-api",
|
||||||
|
provider: "missing-provider",
|
||||||
|
baseUrl: "https://example.com",
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text"],
|
||||||
|
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
||||||
|
contextWindow: 1,
|
||||||
|
maxTokens: 1,
|
||||||
|
},
|
||||||
|
{ messages: [] },
|
||||||
|
),
|
||||||
|
).rejects.toThrow("No API provider registered for api: missing-api");
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -17,8 +17,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { describe, expect, it } from "vitest";
|
import { describe, expect, it } from "vitest";
|
||||||
|
import { complete } from "../src/index.ts";
|
||||||
import { getModels } from "../src/models.ts";
|
import { getModels } from "../src/models.ts";
|
||||||
import { complete } from "../src/stream.ts";
|
|
||||||
import type { Context } from "../src/types.ts";
|
import type { Context } from "../src/types.ts";
|
||||||
import { hasBedrockCredentials } from "./bedrock-utils.ts";
|
import { hasBedrockCredentials } from "./bedrock-utils.ts";
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
import { afterEach, beforeEach, describe, expect, it } from "vitest";
|
import { afterEach, beforeEach, describe, expect, it } from "vitest";
|
||||||
|
import { stream } from "../src/index.ts";
|
||||||
import { MODELS } from "../src/models.generated.ts";
|
import { MODELS } from "../src/models.generated.ts";
|
||||||
import { getModel } from "../src/models.ts";
|
import { getModel } from "../src/models.ts";
|
||||||
import { streamAnthropic } from "../src/providers/anthropic.ts";
|
import { streamAnthropic } from "../src/providers/anthropic.ts";
|
||||||
import { streamOpenAICompletions } from "../src/providers/openai-completions.ts";
|
import { streamOpenAICompletions } from "../src/providers/openai-completions.ts";
|
||||||
import { streamOpenAIResponses } from "../src/providers/openai-responses.ts";
|
import { streamOpenAIResponses } from "../src/providers/openai-responses.ts";
|
||||||
import { stream } from "../src/stream.ts";
|
|
||||||
import type { Context, Model } from "../src/types.ts";
|
import type { Context, Model } from "../src/types.ts";
|
||||||
|
|
||||||
class PayloadCaptured extends Error {
|
class PayloadCaptured extends Error {
|
||||||
|
|||||||
@@ -14,8 +14,8 @@
|
|||||||
import type { ChildProcess } from "child_process";
|
import type { ChildProcess } from "child_process";
|
||||||
import { execSync, spawn } from "child_process";
|
import { execSync, spawn } from "child_process";
|
||||||
import { afterAll, beforeAll, describe, expect, it } from "vitest";
|
import { afterAll, beforeAll, describe, expect, it } from "vitest";
|
||||||
|
import { complete } from "../src/index.ts";
|
||||||
import { getModel, getModels } from "../src/models.ts";
|
import { getModel, getModels } from "../src/models.ts";
|
||||||
import { complete } from "../src/stream.ts";
|
|
||||||
import type { AssistantMessage, Context, Model, Usage } from "../src/types.ts";
|
import type { AssistantMessage, Context, Model, Usage } from "../src/types.ts";
|
||||||
import { isContextOverflow } from "../src/utils/overflow.ts";
|
import { isContextOverflow } from "../src/utils/overflow.ts";
|
||||||
import { hasAzureOpenAICredentials } from "./azure-utils.ts";
|
import { hasAzureOpenAICredentials } from "./azure-utils.ts";
|
||||||
|
|||||||
@@ -25,8 +25,8 @@
|
|||||||
import { writeFileSync } from "fs";
|
import { writeFileSync } from "fs";
|
||||||
import { Type } from "typebox";
|
import { Type } from "typebox";
|
||||||
import { beforeAll, describe, expect, it } from "vitest";
|
import { beforeAll, describe, expect, it } from "vitest";
|
||||||
|
import { completeSimple, getEnvApiKey } from "../src/index.ts";
|
||||||
import { getModel } from "../src/models.ts";
|
import { getModel } from "../src/models.ts";
|
||||||
import { completeSimple, getEnvApiKey } from "../src/stream.ts";
|
|
||||||
import type { Api, AssistantMessage, Message, Model, Tool, ToolResultMessage } from "../src/types.ts";
|
import type { Api, AssistantMessage, Message, Model, Tool, ToolResultMessage } from "../src/types.ts";
|
||||||
import { hasAzureOpenAICredentials } from "./azure-utils.ts";
|
import { hasAzureOpenAICredentials } from "./azure-utils.ts";
|
||||||
import { hasCloudflareAiGatewayCredentials, hasCloudflareWorkersAICredentials } from "./cloudflare-utils.ts";
|
import { hasCloudflareAiGatewayCredentials, hasCloudflareWorkersAICredentials } from "./cloudflare-utils.ts";
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { describe, expect, it } from "vitest";
|
import { describe, expect, it } from "vitest";
|
||||||
|
import { complete } from "../src/index.ts";
|
||||||
import { getModel } from "../src/models.ts";
|
import { getModel } from "../src/models.ts";
|
||||||
import { complete } from "../src/stream.ts";
|
|
||||||
import type { Api, AssistantMessage, Context, Model, StreamOptions, UserMessage } from "../src/types.ts";
|
import type { Api, AssistantMessage, Context, Model, StreamOptions, UserMessage } from "../src/types.ts";
|
||||||
|
|
||||||
type StreamOptionsWithExtras = StreamOptions & Record<string, unknown>;
|
type StreamOptionsWithExtras = StreamOptions & Record<string, unknown>;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { describe, expect, it } from "vitest";
|
import { describe, expect, it } from "vitest";
|
||||||
|
import { streamSimple } from "../src/index.ts";
|
||||||
import { getModel } from "../src/models.ts";
|
import { getModel } from "../src/models.ts";
|
||||||
import { streamSimple } from "../src/stream.ts";
|
|
||||||
import type { Api, Context, Model, SimpleStreamOptions } from "../src/types.ts";
|
import type { Api, Context, Model, SimpleStreamOptions } from "../src/types.ts";
|
||||||
|
|
||||||
type SimpleOptionsWithExtras = SimpleStreamOptions & Record<string, unknown>;
|
type SimpleOptionsWithExtras = SimpleStreamOptions & Record<string, unknown>;
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import { Type } from "typebox";
|
import { Type } from "typebox";
|
||||||
import { describe, expect, it } from "vitest";
|
import { describe, expect, it } from "vitest";
|
||||||
import { getEnvApiKey } from "../src/env-api-keys.ts";
|
import { getEnvApiKey } from "../src/env-api-keys.ts";
|
||||||
|
import { completeSimple } from "../src/index.ts";
|
||||||
import { getModel } from "../src/models.ts";
|
import { getModel } from "../src/models.ts";
|
||||||
import { completeSimple } from "../src/stream.ts";
|
|
||||||
import type { Api, Context, Model, StopReason, Tool, ToolCall, ToolResultMessage } from "../src/types.ts";
|
import type { Api, Context, Model, StopReason, Tool, ToolCall, ToolResultMessage } from "../src/types.ts";
|
||||||
import { StringEnum } from "../src/utils/typebox-helpers.ts";
|
import { StringEnum } from "../src/utils/typebox-helpers.ts";
|
||||||
import { hasBedrockCredentials } from "./bedrock-utils.ts";
|
import { hasBedrockCredentials } from "./bedrock-utils.ts";
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import { describe, expect, it } from "vitest";
|
|||||||
|
|
||||||
const packageRoot = resolve(dirname(fileURLToPath(import.meta.url)), "..");
|
const packageRoot = resolve(dirname(fileURLToPath(import.meta.url)), "..");
|
||||||
const aiEntryUrl = new URL("../src/index.ts", import.meta.url).href;
|
const aiEntryUrl = new URL("../src/index.ts", import.meta.url).href;
|
||||||
|
const baseEntryUrl = new URL("../src/base.ts", import.meta.url).href;
|
||||||
|
|
||||||
const SDK_SPECIFIERS = [
|
const SDK_SPECIFIERS = [
|
||||||
"@anthropic-ai/sdk",
|
"@anthropic-ai/sdk",
|
||||||
@@ -16,9 +17,10 @@ const SDK_SPECIFIERS = [
|
|||||||
|
|
||||||
type ProbeResult = {
|
type ProbeResult = {
|
||||||
loadedSpecifiers: string[];
|
loadedSpecifiers: string[];
|
||||||
|
value?: unknown;
|
||||||
};
|
};
|
||||||
|
|
||||||
function runProbe(action: string): ProbeResult {
|
function runProbe(action: string, entryUrl = aiEntryUrl): ProbeResult {
|
||||||
const script = `
|
const script = `
|
||||||
import { registerHooks } from "node:module";
|
import { registerHooks } from "node:module";
|
||||||
|
|
||||||
@@ -34,9 +36,11 @@ function runProbe(action: string): ProbeResult {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const mod = await import(${JSON.stringify(aiEntryUrl)});
|
const mod = await import(${JSON.stringify(entryUrl)});
|
||||||
${action}
|
const value = await (async () => {
|
||||||
console.log(JSON.stringify({ loadedSpecifiers: [...new Set(loaded)] }));
|
${action}
|
||||||
|
})();
|
||||||
|
console.log(JSON.stringify({ loadedSpecifiers: [...new Set(loaded)], value }));
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const result = spawnSync(process.execPath, ["--input-type=module", "--eval", script], {
|
const result = spawnSync(process.execPath, ["--input-type=module", "--eval", script], {
|
||||||
@@ -66,6 +70,33 @@ describe("lazy provider module loading", () => {
|
|||||||
expect(result.loadedSpecifiers).toEqual([]);
|
expect(result.loadedSpecifiers).toEqual([]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("registers built-in transports when importing the root barrel", () => {
|
||||||
|
const result = runProbe(`return mod.getApiProviders().map((provider) => provider.api).sort();`);
|
||||||
|
expect(result.value).toEqual([
|
||||||
|
"anthropic-messages",
|
||||||
|
"azure-openai-responses",
|
||||||
|
"bedrock-converse-stream",
|
||||||
|
"google-generative-ai",
|
||||||
|
"google-vertex",
|
||||||
|
"mistral-conversations",
|
||||||
|
"openai-codex-responses",
|
||||||
|
"openai-completions",
|
||||||
|
"openai-responses",
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("registers built-in image transports when importing the root barrel", () => {
|
||||||
|
const result = runProbe(`return mod.getImagesApiProvider("openrouter-images")?.api;`);
|
||||||
|
expect(result.loadedSpecifiers).toEqual([]);
|
||||||
|
expect(result.value).toBe("openrouter-images");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("does not load provider SDKs or register transports when importing the base barrel", () => {
|
||||||
|
const result = runProbe(`return mod.getApiProviders().map((provider) => provider.api);`, baseEntryUrl);
|
||||||
|
expect(result.loadedSpecifiers).toEqual([]);
|
||||||
|
expect(result.value).toEqual([]);
|
||||||
|
});
|
||||||
|
|
||||||
it("loads only the Anthropic SDK when calling the root lazy wrapper", () => {
|
it("loads only the Anthropic SDK when calling the root lazy wrapper", () => {
|
||||||
const result = runProbe(`
|
const result = runProbe(`
|
||||||
const model = {
|
const model = {
|
||||||
@@ -96,4 +127,17 @@ describe("lazy provider module loading", () => {
|
|||||||
|
|
||||||
expect(result.loadedSpecifiers).toEqual(["@anthropic-ai/sdk"]);
|
expect(result.loadedSpecifiers).toEqual(["@anthropic-ai/sdk"]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("dispatches through a lazy wrapper again after resetting providers", () => {
|
||||||
|
const result = runProbe(`
|
||||||
|
const model = mod.getModel("anthropic", "claude-sonnet-4-6");
|
||||||
|
const context = { messages: [{ role: "user", content: "hi" }] };
|
||||||
|
await mod.streamSimple(model, context).result();
|
||||||
|
mod.resetApiProviders();
|
||||||
|
return (await mod.streamSimple(model, context).result()).stopReason;
|
||||||
|
`);
|
||||||
|
|
||||||
|
expect(result.loadedSpecifiers).toEqual(["@anthropic-ai/sdk"]);
|
||||||
|
expect(result.value).toBe("error");
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { describe, expect, it } from "vitest";
|
import { describe, expect, it } from "vitest";
|
||||||
|
import { streamSimple } from "../src/index.ts";
|
||||||
import { getModel } from "../src/models.ts";
|
import { getModel } from "../src/models.ts";
|
||||||
import { streamSimple } from "../src/stream.ts";
|
|
||||||
import type { Context, Model, SimpleStreamOptions } from "../src/types.ts";
|
import type { Context, Model, SimpleStreamOptions } from "../src/types.ts";
|
||||||
|
|
||||||
interface MistralPayload {
|
interface MistralPayload {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { Type } from "typebox";
|
import { Type } from "typebox";
|
||||||
import { describe, expect, it } from "vitest";
|
import { describe, expect, it } from "vitest";
|
||||||
|
import { complete } from "../src/index.ts";
|
||||||
import { getModel } from "../src/models.ts";
|
import { getModel } from "../src/models.ts";
|
||||||
import { complete } from "../src/stream.ts";
|
|
||||||
import type { Context, Model } from "../src/types.ts";
|
import type { Context, Model } from "../src/types.ts";
|
||||||
|
|
||||||
interface MistralToolPayload {
|
interface MistralToolPayload {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { describe, expect, it } from "vitest";
|
import { describe, expect, it } from "vitest";
|
||||||
|
import { complete } from "../src/index.ts";
|
||||||
import { getModel } from "../src/models.ts";
|
import { getModel } from "../src/models.ts";
|
||||||
import { complete } from "../src/stream.ts";
|
|
||||||
import type { Context } from "../src/types.ts";
|
import type { Context } from "../src/types.ts";
|
||||||
import { resolveApiKey } from "./oauth.ts";
|
import { resolveApiKey } from "./oauth.ts";
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||||
|
import { streamSimple } from "../src/index.ts";
|
||||||
import { getModel } from "../src/models.ts";
|
import { getModel } from "../src/models.ts";
|
||||||
import { streamSimple } from "../src/stream.ts";
|
|
||||||
|
|
||||||
// Empty tools arrays must NOT be serialized as `tools: []` — some OpenAI-compatible
|
// Empty tools arrays must NOT be serialized as `tools: []` — some OpenAI-compatible
|
||||||
// backends (e.g. DashScope / Aliyun Qwen via compatible-mode) reject the request with
|
// backends (e.g. DashScope / Aliyun Qwen via compatible-mode) reject the request with
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||||
import { complete } from "../src/stream.ts";
|
import { complete } from "../src/index.ts";
|
||||||
import type { Model } from "../src/types.ts";
|
import type { Model } from "../src/types.ts";
|
||||||
|
|
||||||
// Router/virtual ids (e.g. OpenRouter `auto`) keep `model` pinned to the
|
// Router/virtual ids (e.g. OpenRouter `auto`) keep `model` pinned to the
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import { Type } from "typebox";
|
import { Type } from "typebox";
|
||||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||||
|
import { stream, streamSimple } from "../src/index.ts";
|
||||||
import { getModel } from "../src/models.ts";
|
import { getModel } from "../src/models.ts";
|
||||||
import { convertMessages } from "../src/providers/openai-completions.ts";
|
import { convertMessages } from "../src/providers/openai-completions.ts";
|
||||||
import { stream, streamSimple } from "../src/stream.ts";
|
|
||||||
import type { AssistantMessage, Model, Tool, ToolResultMessage } from "../src/types.ts";
|
import type { AssistantMessage, Model, Tool, ToolResultMessage } from "../src/types.ts";
|
||||||
|
|
||||||
const mockState = vi.hoisted(() => ({
|
const mockState = vi.hoisted(() => ({
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { describe, expect, it } from "vitest";
|
import { describe, expect, it } from "vitest";
|
||||||
|
import { complete } from "../src/index.ts";
|
||||||
import { getModel } from "../src/models.ts";
|
import { getModel } from "../src/models.ts";
|
||||||
import { complete } from "../src/stream.ts";
|
|
||||||
import type { Context } from "../src/types.ts";
|
import type { Context } from "../src/types.ts";
|
||||||
|
|
||||||
describe.skipIf(!process.env.OPENAI_API_KEY)("openai responses cache affinity e2e", () => {
|
describe.skipIf(!process.env.OPENAI_API_KEY)("openai responses cache affinity e2e", () => {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { Type } from "typebox";
|
import { Type } from "typebox";
|
||||||
import { describe, expect, it } from "vitest";
|
import { describe, expect, it } from "vitest";
|
||||||
|
import { complete, getEnvApiKey } from "../src/index.ts";
|
||||||
import { getModel } from "../src/models.ts";
|
import { getModel } from "../src/models.ts";
|
||||||
import { complete, getEnvApiKey } from "../src/stream.ts";
|
|
||||||
import type { AssistantMessage, Context, Message, Tool, ToolCall } from "../src/types.ts";
|
import type { AssistantMessage, Context, Message, Tool, ToolCall } from "../src/types.ts";
|
||||||
|
|
||||||
const testToolSchema = Type.Object({
|
const testToolSchema = Type.Object({
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { describe, expect, it } from "vitest";
|
import { describe, expect, it } from "vitest";
|
||||||
|
import { completeSimple } from "../src/index.ts";
|
||||||
import { getModel } from "../src/models.ts";
|
import { getModel } from "../src/models.ts";
|
||||||
import { completeSimple } from "../src/stream.ts";
|
|
||||||
|
|
||||||
function createLongSystemPrompt(): string {
|
function createLongSystemPrompt(): string {
|
||||||
const nonce = `${Date.now()}-${Math.random()}`;
|
const nonce = `${Date.now()}-${Math.random()}`;
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||||
import { generateImages } from "../src/images.ts";
|
import { generateImages } from "../src/images.ts";
|
||||||
|
import { clearImagesApiProviders, getImagesApiProvider } from "../src/images-api-registry.ts";
|
||||||
|
import { register as registerOpenRouterImages } from "../src/providers/images/openrouter.ts";
|
||||||
|
import { registerBuiltInImagesApiProviders } from "../src/providers/register-builtins.ts";
|
||||||
import type { ImagesContext, ImagesModel } from "../src/types.ts";
|
import type { ImagesContext, ImagesModel } from "../src/types.ts";
|
||||||
|
|
||||||
const mockState = vi.hoisted(() => ({
|
const mockState = vi.hoisted(() => ({
|
||||||
@@ -62,6 +65,15 @@ describe("openrouter images", () => {
|
|||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
mockState.lastParams = undefined;
|
mockState.lastParams = undefined;
|
||||||
mockState.lastRequestOptions = undefined;
|
mockState.lastRequestOptions = undefined;
|
||||||
|
clearImagesApiProviders();
|
||||||
|
registerBuiltInImagesApiProviders();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("registers the direct OpenRouter images transport explicitly", () => {
|
||||||
|
clearImagesApiProviders();
|
||||||
|
expect(getImagesApiProvider("openrouter-images")).toBeUndefined();
|
||||||
|
registerOpenRouterImages();
|
||||||
|
expect(getImagesApiProvider("openrouter-images")?.api).toBe("openrouter-images");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("returns text plus images in final output", async () => {
|
it("returns text plus images in final output", async () => {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { describe, expect, it } from "vitest";
|
import { describe, expect, it } from "vitest";
|
||||||
|
import { complete } from "../src/index.ts";
|
||||||
import { getModel } from "../src/models.ts";
|
import { getModel } from "../src/models.ts";
|
||||||
import { complete } from "../src/stream.ts";
|
|
||||||
import type { Api, Context, Model, StreamOptions } from "../src/types.ts";
|
import type { Api, Context, Model, StreamOptions } from "../src/types.ts";
|
||||||
import { hasAzureOpenAICredentials, resolveAzureDeploymentName } from "./azure-utils.ts";
|
import { hasAzureOpenAICredentials, resolveAzureDeploymentName } from "./azure-utils.ts";
|
||||||
import { resolveApiKey } from "./oauth.ts";
|
import { resolveApiKey } from "./oauth.ts";
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ import { dirname, join } from "path";
|
|||||||
import { Type } from "typebox";
|
import { Type } from "typebox";
|
||||||
import { fileURLToPath } from "url";
|
import { fileURLToPath } from "url";
|
||||||
import { afterAll, beforeAll, describe, expect, it } from "vitest";
|
import { afterAll, beforeAll, describe, expect, it } from "vitest";
|
||||||
|
import { complete, stream } from "../src/index.ts";
|
||||||
import { getModel } from "../src/models.ts";
|
import { getModel } from "../src/models.ts";
|
||||||
import { complete, stream } from "../src/stream.ts";
|
|
||||||
import type { Api, Context, ImageContent, Model, StreamOptions, Tool, ToolResultMessage } from "../src/types.ts";
|
import type { Api, Context, ImageContent, Model, StreamOptions, Tool, ToolResultMessage } from "../src/types.ts";
|
||||||
|
|
||||||
type StreamOptionsWithExtras = StreamOptions & Record<string, unknown>;
|
type StreamOptionsWithExtras = StreamOptions & Record<string, unknown>;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { describe, expect, it } from "vitest";
|
import { describe, expect, it } from "vitest";
|
||||||
|
import { stream } from "../src/index.ts";
|
||||||
import { getModel, getModels } from "../src/models.ts";
|
import { getModel, getModels } from "../src/models.ts";
|
||||||
import { stream } from "../src/stream.ts";
|
|
||||||
import type { Api, Context, Model, StreamOptions } from "../src/types.ts";
|
import type { Api, Context, Model, StreamOptions } from "../src/types.ts";
|
||||||
|
|
||||||
type StreamOptionsWithExtras = StreamOptions & Record<string, unknown>;
|
type StreamOptionsWithExtras = StreamOptions & Record<string, unknown>;
|
||||||
|
|||||||
@@ -12,8 +12,8 @@
|
|||||||
|
|
||||||
import { Type } from "typebox";
|
import { Type } from "typebox";
|
||||||
import { describe, expect, it } from "vitest";
|
import { describe, expect, it } from "vitest";
|
||||||
|
import { completeSimple, getEnvApiKey } from "../src/index.ts";
|
||||||
import { getModel } from "../src/models.ts";
|
import { getModel } from "../src/models.ts";
|
||||||
import { completeSimple, getEnvApiKey } from "../src/stream.ts";
|
|
||||||
import type { AssistantMessage, Message, Tool, ToolResultMessage } from "../src/types.ts";
|
import type { AssistantMessage, Message, Tool, ToolResultMessage } from "../src/types.ts";
|
||||||
import { resolveApiKey } from "./oauth.ts";
|
import { resolveApiKey } from "./oauth.ts";
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { Type } from "typebox";
|
import { Type } from "typebox";
|
||||||
import { describe, expect, it } from "vitest";
|
import { describe, expect, it } from "vitest";
|
||||||
|
import { complete } from "../src/index.ts";
|
||||||
import { getModel } from "../src/models.ts";
|
import { getModel } from "../src/models.ts";
|
||||||
import { complete } from "../src/stream.ts";
|
|
||||||
import type { Api, Context, Model, StreamOptions, Tool } from "../src/types.ts";
|
import type { Api, Context, Model, StreamOptions, Tool } from "../src/types.ts";
|
||||||
|
|
||||||
type StreamOptionsWithExtras = StreamOptions & Record<string, unknown>;
|
type StreamOptionsWithExtras = StreamOptions & Record<string, unknown>;
|
||||||
|
|||||||
@@ -13,8 +13,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { describe, expect, it } from "vitest";
|
import { describe, expect, it } from "vitest";
|
||||||
|
import { complete } from "../src/index.ts";
|
||||||
import { getModel } from "../src/models.ts";
|
import { getModel } from "../src/models.ts";
|
||||||
import { complete } from "../src/stream.ts";
|
|
||||||
import type { Api, Context, Model, StreamOptions, Usage } from "../src/types.ts";
|
import type { Api, Context, Model, StreamOptions, Usage } from "../src/types.ts";
|
||||||
|
|
||||||
type StreamOptionsWithExtras = StreamOptions & Record<string, unknown>;
|
type StreamOptionsWithExtras = StreamOptions & Record<string, unknown>;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { Type } from "typebox";
|
import { Type } from "typebox";
|
||||||
import { describe, expect, it } from "vitest";
|
import { describe, expect, it } from "vitest";
|
||||||
|
import { complete } from "../src/index.ts";
|
||||||
import { getModel } from "../src/models.ts";
|
import { getModel } from "../src/models.ts";
|
||||||
import { complete } from "../src/stream.ts";
|
|
||||||
import type { Api, Context, Model, StreamOptions, ToolResultMessage } from "../src/types.ts";
|
import type { Api, Context, Model, StreamOptions, ToolResultMessage } from "../src/types.ts";
|
||||||
|
|
||||||
type StreamOptionsWithExtras = StreamOptions & Record<string, unknown>;
|
type StreamOptionsWithExtras = StreamOptions & Record<string, unknown>;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { describe, expect, it } from "vitest";
|
import { describe, expect, it } from "vitest";
|
||||||
|
import { stream } from "../src/index.ts";
|
||||||
import { getModel } from "../src/models.ts";
|
import { getModel } from "../src/models.ts";
|
||||||
import { stream } from "../src/stream.ts";
|
|
||||||
import type { Context, Model } from "../src/types.ts";
|
import type { Context, Model } from "../src/types.ts";
|
||||||
|
|
||||||
function makeContext(): Context {
|
function makeContext(): Context {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { describe, expect, it } from "vitest";
|
import { describe, expect, it } from "vitest";
|
||||||
import { completeSimple, getEnvApiKey, streamSimple } from "../src/stream.ts";
|
import { completeSimple, getEnvApiKey, streamSimple } from "../src/index.ts";
|
||||||
import type { AssistantMessage, Context, Model } from "../src/types.ts";
|
import type { AssistantMessage, Context, Model } from "../src/types.ts";
|
||||||
|
|
||||||
const provider = "xiaomi-token-plan-ams";
|
const provider = "xiaomi-token-plan-ams";
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { describe, expect, it } from "vitest";
|
import { describe, expect, it } from "vitest";
|
||||||
|
import { complete } from "../src/index.ts";
|
||||||
import { MODELS } from "../src/models.generated.ts";
|
import { MODELS } from "../src/models.generated.ts";
|
||||||
import { complete } from "../src/stream.ts";
|
|
||||||
import type { Model } from "../src/types.ts";
|
import type { Model } from "../src/types.ts";
|
||||||
|
|
||||||
describe.skipIf(!process.env.OPENCODE_API_KEY)("OpenCode Models Smoke Test", () => {
|
describe.skipIf(!process.env.OPENCODE_API_KEY)("OpenCode Models Smoke Test", () => {
|
||||||
|
|||||||
@@ -2,8 +2,11 @@ import { fileURLToPath } from "node:url";
|
|||||||
import { defineConfig } from "vitest/config";
|
import { defineConfig } from "vitest/config";
|
||||||
|
|
||||||
const aiSrcIndex = fileURLToPath(new URL("../ai/src/index.ts", import.meta.url));
|
const aiSrcIndex = fileURLToPath(new URL("../ai/src/index.ts", import.meta.url));
|
||||||
|
const aiSrcBase = fileURLToPath(new URL("../ai/src/base.ts", import.meta.url));
|
||||||
const aiSrcOAuth = fileURLToPath(new URL("../ai/src/oauth.ts", import.meta.url));
|
const aiSrcOAuth = fileURLToPath(new URL("../ai/src/oauth.ts", import.meta.url));
|
||||||
|
const aiOpenRouterImages = fileURLToPath(new URL("../ai/src/providers/images/openrouter.ts", import.meta.url));
|
||||||
const agentSrcIndex = fileURLToPath(new URL("../agent/src/index.ts", import.meta.url));
|
const agentSrcIndex = fileURLToPath(new URL("../agent/src/index.ts", import.meta.url));
|
||||||
|
const agentSrcBase = fileURLToPath(new URL("../agent/src/base.ts", import.meta.url));
|
||||||
const tuiSrcIndex = fileURLToPath(new URL("../tui/src/index.ts", import.meta.url));
|
const tuiSrcIndex = fileURLToPath(new URL("../tui/src/index.ts", import.meta.url));
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
@@ -20,12 +23,18 @@ export default defineConfig({
|
|||||||
resolve: {
|
resolve: {
|
||||||
alias: [
|
alias: [
|
||||||
{ find: /^@earendil-works\/pi-ai$/, replacement: aiSrcIndex },
|
{ find: /^@earendil-works\/pi-ai$/, replacement: aiSrcIndex },
|
||||||
|
{ find: /^@earendil-works\/pi-ai\/base$/, replacement: aiSrcBase },
|
||||||
{ find: /^@earendil-works\/pi-ai\/oauth$/, replacement: aiSrcOAuth },
|
{ find: /^@earendil-works\/pi-ai\/oauth$/, replacement: aiSrcOAuth },
|
||||||
|
{ find: /^@earendil-works\/pi-ai\/openrouter-images$/, replacement: aiOpenRouterImages },
|
||||||
{ find: /^@earendil-works\/pi-agent-core$/, replacement: agentSrcIndex },
|
{ find: /^@earendil-works\/pi-agent-core$/, replacement: agentSrcIndex },
|
||||||
|
{ find: /^@earendil-works\/pi-agent-core\/base$/, replacement: agentSrcBase },
|
||||||
{ find: /^@earendil-works\/pi-tui$/, replacement: tuiSrcIndex },
|
{ find: /^@earendil-works\/pi-tui$/, replacement: tuiSrcIndex },
|
||||||
{ find: /^@mariozechner\/pi-ai$/, replacement: aiSrcIndex },
|
{ find: /^@mariozechner\/pi-ai$/, replacement: aiSrcIndex },
|
||||||
|
{ find: /^@mariozechner\/pi-ai\/base$/, replacement: aiSrcBase },
|
||||||
{ find: /^@mariozechner\/pi-ai\/oauth$/, replacement: aiSrcOAuth },
|
{ find: /^@mariozechner\/pi-ai\/oauth$/, replacement: aiSrcOAuth },
|
||||||
|
{ find: /^@mariozechner\/pi-ai\/openrouter-images$/, replacement: aiOpenRouterImages },
|
||||||
{ find: /^@mariozechner\/pi-agent-core$/, replacement: agentSrcIndex },
|
{ find: /^@mariozechner\/pi-agent-core$/, replacement: agentSrcIndex },
|
||||||
|
{ find: /^@mariozechner\/pi-agent-core\/base$/, replacement: agentSrcBase },
|
||||||
{ find: /^@mariozechner\/pi-tui$/, replacement: tuiSrcIndex },
|
{ find: /^@mariozechner\/pi-tui$/, replacement: tuiSrcIndex },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -4,7 +4,21 @@ import { join } from "node:path";
|
|||||||
import { build } from "esbuild";
|
import { build } from "esbuild";
|
||||||
|
|
||||||
const outputPath = join(tmpdir(), "pi-browser-smoke.js");
|
const outputPath = join(tmpdir(), "pi-browser-smoke.js");
|
||||||
|
const baseOutputPath = join(tmpdir(), "pi-browser-base-smoke.js");
|
||||||
|
const selectiveOutputPath = join(tmpdir(), "pi-browser-selective-smoke.js");
|
||||||
const errorLogPath = join(tmpdir(), "pi-browser-smoke-errors.log");
|
const errorLogPath = join(tmpdir(), "pi-browser-smoke-errors.log");
|
||||||
|
const providerImplementationInputs = [
|
||||||
|
"packages/ai/src/providers/amazon-bedrock.ts",
|
||||||
|
"packages/ai/src/providers/anthropic.ts",
|
||||||
|
"packages/ai/src/providers/azure-openai-responses.ts",
|
||||||
|
"packages/ai/src/providers/google.ts",
|
||||||
|
"packages/ai/src/providers/google-vertex.ts",
|
||||||
|
"packages/ai/src/providers/images/openrouter.ts",
|
||||||
|
"packages/ai/src/providers/mistral.ts",
|
||||||
|
"packages/ai/src/providers/openai-codex-responses.ts",
|
||||||
|
"packages/ai/src/providers/openai-completions.ts",
|
||||||
|
"packages/ai/src/providers/openai-responses.ts",
|
||||||
|
];
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await build({
|
await build({
|
||||||
@@ -15,6 +29,36 @@ try {
|
|||||||
logLevel: "silent",
|
logLevel: "silent",
|
||||||
outfile: outputPath,
|
outfile: outputPath,
|
||||||
});
|
});
|
||||||
|
const baseBuild = await build({
|
||||||
|
stdin: {
|
||||||
|
contents: `import { complete } from "@earendil-works/pi-ai/base";\nimport { Agent } from "@earendil-works/pi-agent-core/base";\nconsole.log(typeof complete, typeof Agent);\n`,
|
||||||
|
resolveDir: process.cwd(),
|
||||||
|
sourcefile: "pi-browser-base-smoke-entry.ts",
|
||||||
|
},
|
||||||
|
bundle: true,
|
||||||
|
platform: "browser",
|
||||||
|
format: "esm",
|
||||||
|
logLevel: "silent",
|
||||||
|
metafile: true,
|
||||||
|
outfile: baseOutputPath,
|
||||||
|
});
|
||||||
|
const bundledInputs = new Set(Object.keys(baseBuild.metafile.inputs));
|
||||||
|
const reachableProviderImplementations = providerImplementationInputs.filter((input) => bundledInputs.has(input));
|
||||||
|
if (reachableProviderImplementations.length > 0) {
|
||||||
|
throw new Error(`Base browser bundle reached provider implementations:\n${reachableProviderImplementations.join("\n")}`);
|
||||||
|
}
|
||||||
|
await build({
|
||||||
|
stdin: {
|
||||||
|
contents: `import { register as registerAnthropic } from "@earendil-works/pi-ai/anthropic";\nimport { register as registerOpenAICompletions } from "@earendil-works/pi-ai/openai-completions";\nimport { register as registerOpenRouterImages } from "@earendil-works/pi-ai/openrouter-images";\nconsole.log(typeof registerAnthropic, typeof registerOpenAICompletions, typeof registerOpenRouterImages);\n`,
|
||||||
|
resolveDir: process.cwd(),
|
||||||
|
sourcefile: "pi-browser-selective-smoke-entry.ts",
|
||||||
|
},
|
||||||
|
bundle: true,
|
||||||
|
platform: "browser",
|
||||||
|
format: "esm",
|
||||||
|
logLevel: "silent",
|
||||||
|
outfile: selectiveOutputPath,
|
||||||
|
});
|
||||||
process.exit(0);
|
process.exit(0);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
let detailedErrors = "";
|
let detailedErrors = "";
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
"*": ["./*"],
|
"*": ["./*"],
|
||||||
"@earendil-works/pi-ai": ["./packages/ai/src/index.ts"],
|
"@earendil-works/pi-ai": ["./packages/ai/src/index.ts"],
|
||||||
"@earendil-works/pi-ai/oauth": ["./packages/ai/src/oauth.ts"],
|
"@earendil-works/pi-ai/oauth": ["./packages/ai/src/oauth.ts"],
|
||||||
|
"@earendil-works/pi-ai/openrouter-images": ["./packages/ai/src/providers/images/openrouter.ts"],
|
||||||
"@earendil-works/pi-ai/*": ["./packages/ai/src/*.ts", "./packages/ai/src/providers/*.ts"],
|
"@earendil-works/pi-ai/*": ["./packages/ai/src/*.ts", "./packages/ai/src/providers/*.ts"],
|
||||||
"@earendil-works/pi-ai/dist/*": ["./packages/ai/src/*"],
|
"@earendil-works/pi-ai/dist/*": ["./packages/ai/src/*"],
|
||||||
"@earendil-works/pi-agent-core": ["./packages/agent/src/index.ts"],
|
"@earendil-works/pi-agent-core": ["./packages/agent/src/index.ts"],
|
||||||
|
|||||||
Reference in New Issue
Block a user