mirror of
https://github.com/getcompanion-ai/co-mono.git
synced 2026-04-20 21:02:02 +00:00
WIP: remove setApiKey, resolveApiKey
This commit is contained in:
parent
385e7aff62
commit
d93cbf8c32
6 changed files with 21 additions and 61 deletions
|
|
@ -2,6 +2,10 @@
|
||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
|
## Breaking Changes
|
||||||
|
- **setApiKey, resolveApiKey**: removed. You need to create your own api key storage/resolution
|
||||||
|
- **getApiKey**: renamed to `getApiKeyFromEnv`. Given a provider, checks for the known env variable holding the API key.
|
||||||
|
|
||||||
## [0.27.7] - 2025-12-24
|
## [0.27.7] - 2025-12-24
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ import type {
|
||||||
MessageParam,
|
MessageParam,
|
||||||
} from "@anthropic-ai/sdk/resources/messages.js";
|
} from "@anthropic-ai/sdk/resources/messages.js";
|
||||||
import { calculateCost } from "../models.js";
|
import { calculateCost } from "../models.js";
|
||||||
import { getApiKey } from "../stream.js";
|
import { getApiKeyFromEnv } from "../stream.js";
|
||||||
import type {
|
import type {
|
||||||
Api,
|
Api,
|
||||||
AssistantMessage,
|
AssistantMessage,
|
||||||
|
|
@ -114,7 +114,7 @@ export const streamAnthropic: StreamFunction<"anthropic-messages"> = (
|
||||||
};
|
};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const apiKey = options?.apiKey ?? getApiKey(model.provider) ?? "";
|
const apiKey = options?.apiKey ?? getApiKeyFromEnv(model.provider) ?? "";
|
||||||
const { client, isOAuthToken } = createClient(model, apiKey, options?.interleavedThinking ?? true);
|
const { client, isOAuthToken } = createClient(model, apiKey, options?.interleavedThinking ?? true);
|
||||||
const params = buildParams(model, context, isOAuthToken, options);
|
const params = buildParams(model, context, isOAuthToken, options);
|
||||||
const anthropicStream = client.messages.stream({ ...params, stream: true }, { signal: options?.signal });
|
const anthropicStream = client.messages.stream({ ...params, stream: true }, { signal: options?.signal });
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ import {
|
||||||
type ThinkingLevel,
|
type ThinkingLevel,
|
||||||
} from "@google/genai";
|
} from "@google/genai";
|
||||||
import { calculateCost } from "../models.js";
|
import { calculateCost } from "../models.js";
|
||||||
|
import { getApiKeyFromEnv } from "../stream.js";
|
||||||
import type {
|
import type {
|
||||||
Api,
|
Api,
|
||||||
AssistantMessage,
|
AssistantMessage,
|
||||||
|
|
@ -60,7 +61,8 @@ export const streamGoogle: StreamFunction<"google-generative-ai"> = (
|
||||||
};
|
};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const client = createClient(model, options?.apiKey);
|
const apiKey = options?.apiKey || getApiKeyFromEnv(model.provider) || "";
|
||||||
|
const client = createClient(model, apiKey);
|
||||||
const params = buildParams(model, context, options);
|
const params = buildParams(model, context, options);
|
||||||
const googleStream = await client.models.generateContentStream(params);
|
const googleStream = await client.models.generateContentStream(params);
|
||||||
|
|
||||||
|
|
@ -248,15 +250,6 @@ export const streamGoogle: StreamFunction<"google-generative-ai"> = (
|
||||||
};
|
};
|
||||||
|
|
||||||
function createClient(model: Model<"google-generative-ai">, apiKey?: string): GoogleGenAI {
|
function createClient(model: Model<"google-generative-ai">, apiKey?: string): GoogleGenAI {
|
||||||
if (!apiKey) {
|
|
||||||
if (!process.env.GEMINI_API_KEY) {
|
|
||||||
throw new Error(
|
|
||||||
"Gemini API key is required. Set GEMINI_API_KEY environment variable or pass it as an argument.",
|
|
||||||
);
|
|
||||||
}
|
|
||||||
apiKey = process.env.GEMINI_API_KEY;
|
|
||||||
}
|
|
||||||
|
|
||||||
const httpOptions: { baseUrl?: string; apiVersion?: string; headers?: Record<string, string> } = {};
|
const httpOptions: { baseUrl?: string; apiVersion?: string; headers?: Record<string, string> } = {};
|
||||||
if (model.baseUrl) {
|
if (model.baseUrl) {
|
||||||
httpOptions.baseUrl = model.baseUrl;
|
httpOptions.baseUrl = model.baseUrl;
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ import type {
|
||||||
ChatCompletionToolMessageParam,
|
ChatCompletionToolMessageParam,
|
||||||
} from "openai/resources/chat/completions.js";
|
} from "openai/resources/chat/completions.js";
|
||||||
import { calculateCost } from "../models.js";
|
import { calculateCost } from "../models.js";
|
||||||
|
import { getApiKeyFromEnv } from "../stream.js";
|
||||||
import type {
|
import type {
|
||||||
AssistantMessage,
|
AssistantMessage,
|
||||||
Context,
|
Context,
|
||||||
|
|
@ -98,7 +99,8 @@ export const streamOpenAICompletions: StreamFunction<"openai-completions"> = (
|
||||||
};
|
};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const client = createClient(model, context, options?.apiKey);
|
const apiKey = options?.apiKey || getApiKeyFromEnv(model.provider) || "";
|
||||||
|
const client = createClient(model, context, apiKey);
|
||||||
const params = buildParams(model, context, options);
|
const params = buildParams(model, context, options);
|
||||||
const openaiStream = await client.chat.completions.create(params, { signal: options?.signal });
|
const openaiStream = await client.chat.completions.create(params, { signal: options?.signal });
|
||||||
stream.push({ type: "start", partial: output });
|
stream.push({ type: "start", partial: output });
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ import type {
|
||||||
ResponseReasoningItem,
|
ResponseReasoningItem,
|
||||||
} from "openai/resources/responses/responses.js";
|
} from "openai/resources/responses/responses.js";
|
||||||
import { calculateCost } from "../models.js";
|
import { calculateCost } from "../models.js";
|
||||||
|
import { getApiKeyFromEnv } from "../stream.js";
|
||||||
import type {
|
import type {
|
||||||
Api,
|
Api,
|
||||||
AssistantMessage,
|
AssistantMessage,
|
||||||
|
|
@ -27,7 +28,6 @@ import type {
|
||||||
import { AssistantMessageEventStream } from "../utils/event-stream.js";
|
import { AssistantMessageEventStream } from "../utils/event-stream.js";
|
||||||
import { parseStreamingJson } from "../utils/json-parse.js";
|
import { parseStreamingJson } from "../utils/json-parse.js";
|
||||||
import { sanitizeSurrogates } from "../utils/sanitize-unicode.js";
|
import { sanitizeSurrogates } from "../utils/sanitize-unicode.js";
|
||||||
|
|
||||||
import { transformMessages } from "./transorm-messages.js";
|
import { transformMessages } from "./transorm-messages.js";
|
||||||
|
|
||||||
/** Fast deterministic hash to shorten long strings */
|
/** Fast deterministic hash to shorten long strings */
|
||||||
|
|
@ -82,7 +82,8 @@ export const streamOpenAIResponses: StreamFunction<"openai-responses"> = (
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Create OpenAI client
|
// Create OpenAI client
|
||||||
const client = createClient(model, context, options?.apiKey);
|
const apiKey = options?.apiKey || getApiKeyFromEnv(model.provider) || "";
|
||||||
|
const client = createClient(model, context, apiKey);
|
||||||
const params = buildParams(model, context, options);
|
const params = buildParams(model, context, options);
|
||||||
const openaiStream = await client.responses.create(params, { signal: options?.signal });
|
const openaiStream = await client.responses.create(params, { signal: options?.signal });
|
||||||
stream.push({ type: "start", partial: output });
|
stream.push({ type: "start", partial: output });
|
||||||
|
|
|
||||||
|
|
@ -16,27 +16,14 @@ import type {
|
||||||
ReasoningEffort,
|
ReasoningEffort,
|
||||||
SimpleStreamOptions,
|
SimpleStreamOptions,
|
||||||
} from "./types.js";
|
} from "./types.js";
|
||||||
import { getOAuthApiKey, getOAuthProviderForModelProvider } from "./utils/oauth/index.js";
|
|
||||||
|
|
||||||
const apiKeys: Map<string, string> = new Map();
|
|
||||||
|
|
||||||
export function setApiKey(provider: KnownProvider, key: string): void;
|
|
||||||
export function setApiKey(provider: string, key: string): void;
|
|
||||||
export function setApiKey(provider: any, key: string): void {
|
|
||||||
apiKeys.set(provider, key);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get API key from environment variables (sync).
|
* Get API key from environment variables (sync).
|
||||||
* Does NOT check OAuth credentials - use getApiKeyAsync for that.
|
* Does NOT check OAuth credentials - use getApiKeyAsync for that.
|
||||||
*/
|
*/
|
||||||
export function getApiKey(provider: KnownProvider): string | undefined;
|
export function getApiKeyFromEnv(provider: KnownProvider): string | undefined;
|
||||||
export function getApiKey(provider: string): string | undefined;
|
export function getApiKeyFromEnv(provider: string): string | undefined;
|
||||||
export function getApiKey(provider: any): string | undefined {
|
export function getApiKeyFromEnv(provider: any): string | undefined {
|
||||||
// Check explicit keys first
|
|
||||||
const key = apiKeys.get(provider);
|
|
||||||
if (key) return key;
|
|
||||||
|
|
||||||
// Fall back to environment variables
|
// Fall back to environment variables
|
||||||
if (provider === "github-copilot") {
|
if (provider === "github-copilot") {
|
||||||
return process.env.COPILOT_GITHUB_TOKEN || process.env.GH_TOKEN || process.env.GITHUB_TOKEN;
|
return process.env.COPILOT_GITHUB_TOKEN || process.env.GH_TOKEN || process.env.GITHUB_TOKEN;
|
||||||
|
|
@ -58,39 +45,12 @@ export function getApiKey(provider: any): string | undefined {
|
||||||
return envVar ? process.env[envVar] : undefined;
|
return envVar ? process.env[envVar] : undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Resolve API key from OAuth credentials or environment (async).
|
|
||||||
* Automatically refreshes expired OAuth tokens.
|
|
||||||
*
|
|
||||||
* Priority:
|
|
||||||
* 1. Explicitly set keys (via setApiKey)
|
|
||||||
* 2. OAuth credentials from ~/.pi/agent/oauth.json
|
|
||||||
* 3. Environment variables
|
|
||||||
*/
|
|
||||||
export async function resolveApiKey(provider: KnownProvider): Promise<string | undefined>;
|
|
||||||
export async function resolveApiKey(provider: string): Promise<string | undefined>;
|
|
||||||
export async function resolveApiKey(provider: any): Promise<string | undefined> {
|
|
||||||
// Check explicit keys first
|
|
||||||
const key = apiKeys.get(provider);
|
|
||||||
if (key) return key;
|
|
||||||
|
|
||||||
// Check OAuth credentials (auto-refresh if expired)
|
|
||||||
const oauthProvider = getOAuthProviderForModelProvider(provider);
|
|
||||||
if (oauthProvider) {
|
|
||||||
const oauthKey = await getOAuthApiKey(oauthProvider);
|
|
||||||
if (oauthKey) return oauthKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fall back to sync getApiKey for env vars
|
|
||||||
return getApiKey(provider);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function stream<TApi extends Api>(
|
export function stream<TApi extends Api>(
|
||||||
model: Model<TApi>,
|
model: Model<TApi>,
|
||||||
context: Context,
|
context: Context,
|
||||||
options?: OptionsForApi<TApi>,
|
options?: OptionsForApi<TApi>,
|
||||||
): AssistantMessageEventStream {
|
): AssistantMessageEventStream {
|
||||||
const apiKey = options?.apiKey || getApiKey(model.provider);
|
const apiKey = options?.apiKey || getApiKeyFromEnv(model.provider);
|
||||||
if (!apiKey) {
|
if (!apiKey) {
|
||||||
throw new Error(`No API key for provider: ${model.provider}`);
|
throw new Error(`No API key for provider: ${model.provider}`);
|
||||||
}
|
}
|
||||||
|
|
@ -139,7 +99,7 @@ export function streamSimple<TApi extends Api>(
|
||||||
context: Context,
|
context: Context,
|
||||||
options?: SimpleStreamOptions,
|
options?: SimpleStreamOptions,
|
||||||
): AssistantMessageEventStream {
|
): AssistantMessageEventStream {
|
||||||
const apiKey = options?.apiKey || getApiKey(model.provider);
|
const apiKey = options?.apiKey || getApiKeyFromEnv(model.provider);
|
||||||
if (!apiKey) {
|
if (!apiKey) {
|
||||||
throw new Error(`No API key for provider: ${model.provider}`);
|
throw new Error(`No API key for provider: ${model.provider}`);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue