@elizaos/plugin-openai 1.0.11 → 1.5.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,10 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/index.ts"],
4
+ "sourcesContent": [
5
+ "import { createOpenAI } from \"@ai-sdk/openai\";\nimport type {\n DetokenizeTextParams,\n GenerateTextParams,\n IAgentRuntime,\n ImageDescriptionParams,\n ModelTypeName,\n ObjectGenerationParams,\n Plugin,\n TextEmbeddingParams,\n TokenizeTextParams,\n} from \"@elizaos/core\";\nimport { EventType, logger, ModelType, VECTOR_DIMS } from \"@elizaos/core\";\nimport {\n generateObject,\n generateText,\n JSONParseError,\n type JSONValue,\n type LanguageModelUsage,\n} from \"ai\";\nimport { encodingForModel, type TiktokenModel } from \"js-tiktoken\";\n\n/**\n * Retrieves a configuration setting from the runtime, falling back to environment variables or a default value if not found.\n *\n * @param key - The name of the setting to retrieve.\n * @param defaultValue - The value to return if the setting is not found in the runtime or environment.\n * @returns The resolved setting value, or {@link defaultValue} if not found.\n */\nfunction getSetting(\n runtime: IAgentRuntime,\n key: string,\n defaultValue?: string,\n): string | undefined {\n return runtime.getSetting(key) ?? process.env[key] ?? defaultValue;\n}\n\nfunction isBrowser(): boolean {\n return (\n typeof globalThis !== \"undefined\" &&\n typeof (globalThis as any).document !== \"undefined\"\n );\n}\n\nfunction getAuthHeader(\n runtime: IAgentRuntime,\n forEmbedding = false,\n): Record<string, string> {\n if (isBrowser()) return {};\n const key = forEmbedding ? getEmbeddingApiKey(runtime) : getApiKey(runtime);\n return key ? { Authorization: `Bearer ${key}` } : {};\n}\n\n/**\n * Retrieves the OpenAI API base URL from runtime settings, environment variables, or defaults, using provider-aware resolution.\n *\n * @returns The resolved base URL for OpenAI API requests.\n */\nfunction getBaseURL(runtime: IAgentRuntime): string {\n const browserURL = getSetting(runtime, \"OPENAI_BROWSER_BASE_URL\");\n const baseURL = (\n isBrowser() && browserURL\n ? browserURL\n : getSetting(runtime, \"OPENAI_BASE_URL\", \"https://api.openai.com/v1\")\n ) as string;\n logger.debug(`[OpenAI] Default base URL: ${baseURL}`);\n return baseURL;\n}\n\n/**\n * Retrieves the OpenAI API base URL for embeddings, falling back to the general base URL.\n *\n * @returns The resolved base URL for OpenAI embedding requests.\n */\nfunction getEmbeddingBaseURL(runtime: IAgentRuntime): string {\n const embeddingURL = isBrowser()\n ? getSetting(runtime, \"OPENAI_BROWSER_EMBEDDING_URL\") ||\n getSetting(runtime, \"OPENAI_BROWSER_BASE_URL\")\n : getSetting(runtime, \"OPENAI_EMBEDDING_URL\");\n if (embeddingURL) {\n logger.debug(`[OpenAI] Using specific embedding base URL: ${embeddingURL}`);\n return embeddingURL;\n }\n logger.debug(\"[OpenAI] Falling back to general base URL for embeddings.\");\n return getBaseURL(runtime);\n}\n\n/**\n * Helper function to get the API key for OpenAI\n *\n * @param runtime The runtime context\n * @returns The configured API key\n */\nfunction getApiKey(runtime: IAgentRuntime): string | undefined {\n return getSetting(runtime, \"OPENAI_API_KEY\");\n}\n\n/**\n * Helper function to get the embedding API key for OpenAI, falling back to the general API key if not set.\n *\n * @param runtime The runtime context\n * @returns The configured API key\n */\nfunction getEmbeddingApiKey(runtime: IAgentRuntime): string | undefined {\n const embeddingApiKey = getSetting(runtime, \"OPENAI_EMBEDDING_API_KEY\");\n if (embeddingApiKey) {\n logger.debug(\"[OpenAI] Using specific embedding API key (present)\");\n return embeddingApiKey;\n }\n logger.debug(\"[OpenAI] Falling back to general API key for embeddings.\");\n return getApiKey(runtime);\n}\n\n/**\n * Helper function to get the small model name with fallbacks\n *\n * @param runtime The runtime context\n * @returns The configured small model name\n */\nfunction getSmallModel(runtime: IAgentRuntime): string {\n return (\n getSetting(runtime, \"OPENAI_SMALL_MODEL\") ??\n (getSetting(runtime, \"SMALL_MODEL\", \"gpt-5-nano\") as string)\n );\n}\n\n/**\n * Helper function to get the large model name with fallbacks\n *\n * @param runtime The runtime context\n * @returns The configured large model name\n */\nfunction getLargeModel(runtime: IAgentRuntime): string {\n return (\n getSetting(runtime, \"OPENAI_LARGE_MODEL\") ??\n (getSetting(runtime, \"LARGE_MODEL\", \"gpt-5-mini\") as string)\n );\n}\n\n/**\n * Helper function to get the image description model name with fallbacks\n *\n * @param runtime The runtime context\n * @returns The configured image description model name\n */\nfunction getImageDescriptionModel(runtime: IAgentRuntime): string {\n return (\n getSetting(runtime, \"OPENAI_IMAGE_DESCRIPTION_MODEL\", \"gpt-5-nano\") ??\n \"gpt-5-nano\"\n );\n}\n\n/**\n * Helper function to get experimental telemetry setting\n *\n * @param runtime The runtime context\n * @returns Whether experimental telemetry is enabled\n */\nfunction getExperimentalTelemetry(runtime: IAgentRuntime): boolean {\n const setting = getSetting(runtime, \"OPENAI_EXPERIMENTAL_TELEMETRY\", \"false\");\n // Convert to string and check for truthy values\n const normalizedSetting = String(setting).toLowerCase();\n const result = normalizedSetting === \"true\";\n logger.debug(\n `[OpenAI] Experimental telemetry in function: \"${setting}\" (type: ${typeof setting}, normalized: \"${normalizedSetting}\", result: ${result})`,\n );\n return result;\n}\n\n/**\n * Create an OpenAI client with proper configuration\n *\n * @param runtime The runtime context\n * @returns Configured OpenAI client\n */\nfunction createOpenAIClient(runtime: IAgentRuntime) {\n return createOpenAI({\n apiKey: getApiKey(runtime),\n baseURL: getBaseURL(runtime),\n });\n}\n\n/**\n * Asynchronously tokenizes the given text based on the specified model and prompt.\n *\n * @param {ModelTypeName} model - The type of model to use for tokenization.\n * @param {string} prompt - The text prompt to tokenize.\n * @returns {number[]} - An array of tokens representing the encoded prompt.\n */\nasync function tokenizeText(model: ModelTypeName, prompt: string) {\n const modelName =\n model === ModelType.TEXT_SMALL\n ? (process.env.OPENAI_SMALL_MODEL ??\n process.env.SMALL_MODEL ??\n \"gpt-5-nano\")\n : (process.env.LARGE_MODEL ?? \"gpt-5-mini\");\n const tokens = encodingForModel(modelName as TiktokenModel).encode(prompt);\n return tokens;\n}\n\n/**\n * Detokenize a sequence of tokens back into text using the specified model.\n *\n * @param {ModelTypeName} model - The type of model to use for detokenization.\n * @param {number[]} tokens - The sequence of tokens to detokenize.\n * @returns {string} The detokenized text.\n */\nasync function detokenizeText(model: ModelTypeName, tokens: number[]) {\n const modelName =\n model === ModelType.TEXT_SMALL\n ? (process.env.OPENAI_SMALL_MODEL ??\n process.env.SMALL_MODEL ??\n \"gpt-5-nano\")\n : (process.env.OPENAI_LARGE_MODEL ??\n process.env.LARGE_MODEL ??\n \"gpt-5-mini\");\n return encodingForModel(modelName as TiktokenModel).decode(tokens);\n}\n\n/**\n * Helper function to generate objects using specified model type\n */\nasync function generateObjectByModelType(\n runtime: IAgentRuntime,\n params: ObjectGenerationParams,\n modelType: string,\n getModelFn: (runtime: IAgentRuntime) => string,\n): Promise<JSONValue> {\n const openai = createOpenAIClient(runtime);\n const modelName = getModelFn(runtime);\n logger.log(`[OpenAI] Using ${modelType} model: ${modelName}`);\n const temperature = params.temperature ?? 0;\n const schemaPresent = !!params.schema;\n\n if (schemaPresent) {\n logger.info(\n `Using ${modelType} without schema validation (schema provided but output=no-schema)`,\n );\n }\n\n try {\n const { object, usage } = await generateObject({\n model: openai.languageModel(modelName),\n output: \"no-schema\",\n prompt: params.prompt,\n temperature: temperature,\n experimental_repairText: getJsonRepairFunction(),\n });\n\n if (usage) {\n emitModelUsageEvent(\n runtime,\n modelType as ModelTypeName,\n params.prompt,\n usage,\n );\n }\n return object;\n } catch (error: unknown) {\n if (error instanceof JSONParseError) {\n logger.error(`[generateObject] Failed to parse JSON: ${error.message}`);\n\n const repairFunction = getJsonRepairFunction();\n const repairedJsonString = await repairFunction({\n text: error.text,\n error,\n });\n\n if (repairedJsonString) {\n try {\n const repairedObject = JSON.parse(repairedJsonString);\n logger.info(\"[generateObject] Successfully repaired JSON.\");\n return repairedObject;\n } catch (repairParseError: unknown) {\n const message =\n repairParseError instanceof Error\n ? repairParseError.message\n : String(repairParseError);\n logger.error(\n `[generateObject] Failed to parse repaired JSON: ${message}`,\n );\n throw repairParseError;\n }\n } else {\n logger.error(\"[generateObject] JSON repair failed.\");\n throw error;\n }\n } else {\n const message = error instanceof Error ? error.message : String(error);\n logger.error(`[generateObject] Unknown error: ${message}`);\n throw error;\n }\n }\n}\n\n/**\n * Returns a function to repair JSON text\n */\nfunction getJsonRepairFunction(): (params: {\n text: string;\n error: unknown;\n}) => Promise<string | null> {\n return async ({ text, error }: { text: string; error: unknown }) => {\n try {\n if (error instanceof JSONParseError) {\n const cleanedText = text.replace(/```json\\n|\\n```|```/g, \"\");\n JSON.parse(cleanedText);\n return cleanedText;\n }\n return null;\n } catch (jsonError: unknown) {\n const message =\n jsonError instanceof Error ? jsonError.message : String(jsonError);\n logger.warn(`Failed to repair JSON text: ${message}`);\n return null;\n }\n };\n}\n\n/**\n * Emits a model usage event\n * @param runtime The runtime context\n * @param type The model type\n * @param prompt The prompt used\n * @param usage The LLM usage data\n */\nfunction emitModelUsageEvent(\n runtime: IAgentRuntime,\n type: ModelTypeName,\n prompt: string,\n usage: LanguageModelUsage,\n) {\n runtime.emitEvent(EventType.MODEL_USED, {\n provider: \"openai\",\n type,\n prompt,\n tokens: {\n prompt: usage.inputTokens,\n completion: usage.outputTokens,\n total: usage.totalTokens,\n },\n });\n}\n\n/**\n * function for text-to-speech\n */\nasync function fetchTextToSpeech(runtime: IAgentRuntime, text: string) {\n const model = getSetting(runtime, \"OPENAI_TTS_MODEL\", \"gpt-4o-mini-tts\");\n const voice = getSetting(runtime, \"OPENAI_TTS_VOICE\", \"nova\");\n const instructions = getSetting(runtime, \"OPENAI_TTS_INSTRUCTIONS\", \"\");\n const baseURL = getBaseURL(runtime);\n\n try {\n const res = await fetch(`${baseURL}/audio/speech`, {\n method: \"POST\",\n headers: {\n ...getAuthHeader(runtime),\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({\n model,\n voice,\n input: text,\n ...(instructions && { instructions }),\n }),\n });\n\n if (!res.ok) {\n const err = await res.text();\n throw new Error(`OpenAI TTS error ${res.status}: ${err}`);\n }\n\n return res.body;\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n throw new Error(`Failed to fetch speech from OpenAI TTS: ${message}`);\n }\n}\n\n/**\n * Defines the OpenAI plugin with its name, description, and configuration options.\n * @type {Plugin}\n */\nexport const openaiPlugin: Plugin = {\n name: \"openai\",\n description: \"OpenAI plugin\",\n config: {\n OPENAI_API_KEY: process.env.OPENAI_API_KEY,\n OPENAI_BASE_URL: process.env.OPENAI_BASE_URL,\n OPENAI_SMALL_MODEL: process.env.OPENAI_SMALL_MODEL,\n OPENAI_LARGE_MODEL: process.env.OPENAI_LARGE_MODEL,\n SMALL_MODEL: process.env.SMALL_MODEL,\n LARGE_MODEL: process.env.LARGE_MODEL,\n OPENAI_EMBEDDING_MODEL: process.env.OPENAI_EMBEDDING_MODEL,\n OPENAI_EMBEDDING_API_KEY: process.env.OPENAI_EMBEDDING_API_KEY,\n OPENAI_EMBEDDING_URL: process.env.OPENAI_EMBEDDING_URL,\n OPENAI_EMBEDDING_DIMENSIONS: process.env.OPENAI_EMBEDDING_DIMENSIONS,\n OPENAI_IMAGE_DESCRIPTION_MODEL: process.env.OPENAI_IMAGE_DESCRIPTION_MODEL,\n OPENAI_IMAGE_DESCRIPTION_MAX_TOKENS:\n process.env.OPENAI_IMAGE_DESCRIPTION_MAX_TOKENS,\n OPENAI_EXPERIMENTAL_TELEMETRY: process.env.OPENAI_EXPERIMENTAL_TELEMETRY,\n },\n async init(_config, runtime) {\n // do check in the background\n new Promise<void>(async (resolve) => {\n resolve();\n try {\n if (!getApiKey(runtime) && !isBrowser()) {\n logger.warn(\n \"OPENAI_API_KEY is not set in environment - OpenAI functionality will be limited\",\n );\n return;\n }\n try {\n const baseURL = getBaseURL(runtime);\n const response = await fetch(`${baseURL}/models`, {\n headers: { ...getAuthHeader(runtime) },\n });\n if (!response.ok) {\n logger.warn(\n `OpenAI API key validation failed: ${response.statusText}`,\n );\n logger.warn(\n \"OpenAI functionality will be limited until a valid API key is provided\",\n );\n } else {\n logger.log(\"OpenAI API key validated successfully\");\n }\n } catch (fetchError: unknown) {\n const message =\n fetchError instanceof Error\n ? fetchError.message\n : String(fetchError);\n logger.warn(`Error validating OpenAI API key: ${message}`);\n logger.warn(\n \"OpenAI functionality will be limited until a valid API key is provided\",\n );\n }\n } catch (error: unknown) {\n const message =\n (error as { errors?: Array<{ message: string }> })?.errors\n ?.map((e) => e.message)\n .join(\", \") ||\n (error instanceof Error ? error.message : String(error));\n logger.warn(\n `OpenAI plugin configuration issue: ${message} - You need to configure the OPENAI_API_KEY in your environment variables`,\n );\n }\n });\n },\n\n models: {\n [ModelType.TEXT_EMBEDDING]: async (\n runtime: IAgentRuntime,\n params: TextEmbeddingParams | string | null,\n ): Promise<number[]> => {\n const embeddingModelName = getSetting(\n runtime,\n \"OPENAI_EMBEDDING_MODEL\",\n \"text-embedding-3-small\",\n );\n const embeddingDimension = Number.parseInt(\n getSetting(runtime, \"OPENAI_EMBEDDING_DIMENSIONS\", \"1536\") || \"1536\",\n 10,\n ) as (typeof VECTOR_DIMS)[keyof typeof VECTOR_DIMS];\n\n if (!Object.values(VECTOR_DIMS).includes(embeddingDimension)) {\n const errorMsg = `Invalid embedding dimension: ${embeddingDimension}. Must be one of: ${Object.values(VECTOR_DIMS).join(\", \")}`;\n logger.error(errorMsg);\n throw new Error(errorMsg);\n }\n if (params === null) {\n logger.debug(\"Creating test embedding for initialization\");\n const testVector = Array(embeddingDimension).fill(0);\n testVector[0] = 0.1;\n return testVector;\n }\n let text: string;\n if (typeof params === \"string\") {\n text = params;\n } else if (typeof params === \"object\" && params.text) {\n text = params.text;\n } else {\n logger.warn(\"Invalid input format for embedding\");\n const fallbackVector = Array(embeddingDimension).fill(0);\n fallbackVector[0] = 0.2;\n return fallbackVector;\n }\n if (!text.trim()) {\n logger.warn(\"Empty text for embedding\");\n const emptyVector = Array(embeddingDimension).fill(0);\n emptyVector[0] = 0.3;\n return emptyVector;\n }\n\n const embeddingBaseURL = getEmbeddingBaseURL(runtime);\n\n try {\n const response = await fetch(`${embeddingBaseURL}/embeddings`, {\n method: \"POST\",\n headers: {\n ...getAuthHeader(runtime, true),\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({\n model: embeddingModelName,\n input: text,\n }),\n });\n\n const responseClone = response.clone();\n const rawResponseBody = await responseClone.text();\n\n if (!response.ok) {\n logger.error(\n `OpenAI API error: ${response.status} - ${response.statusText}`,\n );\n const errorVector = Array(embeddingDimension).fill(0);\n errorVector[0] = 0.4;\n return errorVector;\n }\n\n const data = (await response.json()) as {\n data: [{ embedding: number[] }];\n usage?: { prompt_tokens: number; total_tokens: number };\n };\n\n if (!data?.data?.[0]?.embedding) {\n logger.error(\"API returned invalid structure\");\n const errorVector = Array(embeddingDimension).fill(0);\n errorVector[0] = 0.5;\n return errorVector;\n }\n\n const embedding = data.data[0].embedding;\n\n if (data.usage) {\n const usage = {\n inputTokens: data.usage.prompt_tokens,\n outputTokens: 0,\n totalTokens: data.usage.total_tokens,\n };\n\n emitModelUsageEvent(runtime, ModelType.TEXT_EMBEDDING, text, usage);\n }\n\n logger.log(`Got valid embedding with length ${embedding.length}`);\n return embedding;\n } catch (error: unknown) {\n const message = error instanceof Error ? error.message : String(error);\n logger.error(`Error generating embedding: ${message}`);\n const errorVector = Array(embeddingDimension).fill(0);\n errorVector[0] = 0.6;\n return errorVector;\n }\n },\n [ModelType.TEXT_TOKENIZER_ENCODE]: async (\n _runtime,\n { prompt, modelType = ModelType.TEXT_LARGE }: TokenizeTextParams,\n ) => {\n return await tokenizeText(modelType ?? ModelType.TEXT_LARGE, prompt);\n },\n [ModelType.TEXT_TOKENIZER_DECODE]: async (\n _runtime,\n { tokens, modelType = ModelType.TEXT_LARGE }: DetokenizeTextParams,\n ) => {\n return await detokenizeText(modelType ?? ModelType.TEXT_LARGE, tokens);\n },\n [ModelType.TEXT_SMALL]: async (\n runtime: IAgentRuntime,\n {\n prompt,\n stopSequences = [],\n maxTokens = 8192,\n temperature = 0.7,\n frequencyPenalty = 0.7,\n presencePenalty = 0.7,\n }: GenerateTextParams,\n ) => {\n const openai = createOpenAIClient(runtime);\n const modelName = getSmallModel(runtime);\n const experimentalTelemetry = getExperimentalTelemetry(runtime);\n\n logger.log(`[OpenAI] Using TEXT_SMALL model: ${modelName}`);\n logger.log(prompt);\n\n const { text: openaiResponse, usage } = await generateText({\n model: openai.languageModel(modelName),\n prompt: prompt,\n system: runtime.character.system ?? undefined,\n temperature: temperature,\n maxOutputTokens: maxTokens,\n frequencyPenalty: frequencyPenalty,\n presencePenalty: presencePenalty,\n stopSequences: stopSequences,\n experimental_telemetry: {\n isEnabled: experimentalTelemetry,\n },\n });\n\n if (usage) {\n emitModelUsageEvent(runtime, ModelType.TEXT_SMALL, prompt, usage);\n }\n\n return openaiResponse;\n },\n [ModelType.TEXT_LARGE]: async (\n runtime: IAgentRuntime,\n {\n prompt,\n stopSequences = [],\n maxTokens = 8192,\n temperature = 0.7,\n frequencyPenalty = 0.7,\n presencePenalty = 0.7,\n }: GenerateTextParams,\n ) => {\n const openai = createOpenAIClient(runtime);\n const modelName = getLargeModel(runtime);\n const experimentalTelemetry = getExperimentalTelemetry(runtime);\n\n logger.log(`[OpenAI] Using TEXT_LARGE model: ${modelName}`);\n logger.log(prompt);\n\n const { text: openaiResponse, usage } = await generateText({\n model: openai.languageModel(modelName),\n prompt: prompt,\n system: runtime.character.system ?? undefined,\n temperature: temperature,\n maxOutputTokens: maxTokens,\n frequencyPenalty: frequencyPenalty,\n presencePenalty: presencePenalty,\n stopSequences: stopSequences,\n experimental_telemetry: {\n isEnabled: experimentalTelemetry,\n },\n });\n\n if (usage) {\n emitModelUsageEvent(runtime, ModelType.TEXT_LARGE, prompt, usage);\n }\n\n return openaiResponse;\n },\n [ModelType.IMAGE]: async (\n runtime: IAgentRuntime,\n params: {\n prompt: string;\n n?: number;\n size?: string;\n },\n ) => {\n const n = params.n || 1;\n const size = params.size || \"1024x1024\";\n const prompt = params.prompt;\n const modelName = \"dall-e-3\"; // Default DALL-E model\n logger.log(`[OpenAI] Using IMAGE model: ${modelName}`);\n\n const baseURL = getBaseURL(runtime);\n\n try {\n const response = await fetch(`${baseURL}/images/generations`, {\n method: \"POST\",\n headers: {\n ...getAuthHeader(runtime),\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({\n prompt: prompt,\n n: n,\n size: size,\n }),\n });\n\n const responseClone = response.clone();\n const rawResponseBody = await responseClone.text();\n\n if (!response.ok) {\n throw new Error(`Failed to generate image: ${response.statusText}`);\n }\n\n const data = await response.json();\n const typedData = data as { data: { url: string }[] };\n\n return typedData.data;\n } catch (error: unknown) {\n const message = error instanceof Error ? error.message : String(error);\n throw error;\n }\n },\n [ModelType.IMAGE_DESCRIPTION]: async (\n runtime: IAgentRuntime,\n params: ImageDescriptionParams | string,\n ) => {\n let imageUrl: string;\n let promptText: string | undefined;\n const modelName = getImageDescriptionModel(runtime);\n logger.log(`[OpenAI] Using IMAGE_DESCRIPTION model: ${modelName}`);\n const maxTokens = Number.parseInt(\n getSetting(runtime, \"OPENAI_IMAGE_DESCRIPTION_MAX_TOKENS\", \"8192\") ||\n \"8192\",\n 10,\n );\n\n if (typeof params === \"string\") {\n imageUrl = params;\n promptText =\n \"Please analyze this image and provide a title and detailed description.\";\n } else {\n imageUrl = params.imageUrl;\n promptText =\n params.prompt ||\n \"Please analyze this image and provide a title and detailed description.\";\n }\n\n const messages = [\n {\n role: \"user\",\n content: [\n { type: \"text\", text: promptText },\n { type: \"image_url\", image_url: { url: imageUrl } },\n ],\n },\n ];\n\n const baseURL = getBaseURL(runtime);\n\n try {\n const requestBody: Record<string, any> = {\n model: modelName,\n messages: messages,\n max_tokens: maxTokens,\n };\n\n const response = await fetch(`${baseURL}/chat/completions`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n ...getAuthHeader(runtime),\n },\n body: JSON.stringify(requestBody),\n });\n\n const responseClone = response.clone();\n const rawResponseBody = await responseClone.text();\n\n if (!response.ok) {\n throw new Error(`OpenAI API error: ${response.status}`);\n }\n\n const result: unknown = await response.json();\n\n type OpenAIResponseType = {\n choices?: Array<{\n message?: { content?: string };\n finish_reason?: string;\n }>;\n usage?: {\n prompt_tokens: number;\n completion_tokens: number;\n total_tokens: number;\n };\n };\n\n const typedResult = result as OpenAIResponseType;\n const content = typedResult.choices?.[0]?.message?.content;\n\n if (typedResult.usage) {\n emitModelUsageEvent(\n runtime,\n ModelType.IMAGE_DESCRIPTION,\n typeof params === \"string\" ? params : params.prompt || \"\",\n {\n inputTokens: typedResult.usage.prompt_tokens,\n outputTokens: typedResult.usage.completion_tokens,\n totalTokens: typedResult.usage.total_tokens,\n },\n );\n }\n\n if (!content) {\n return {\n title: \"Failed to analyze image\",\n description: \"No response from API\",\n };\n }\n\n // Check if a custom prompt was provided (not the default prompt)\n const isCustomPrompt =\n typeof params === \"object\" &&\n params.prompt &&\n params.prompt !==\n \"Please analyze this image and provide a title and detailed description.\";\n\n // If custom prompt is used, return the raw content\n if (isCustomPrompt) {\n return content;\n }\n\n // Otherwise, maintain backwards compatibility with object return\n const titleMatch = content.match(/title[:\\s]+(.+?)(?:\\n|$)/i);\n const title = titleMatch?.[1]?.trim() || \"Image Analysis\";\n const description = content\n .replace(/title[:\\s]+(.+?)(?:\\n|$)/i, \"\")\n .trim();\n\n const processedResult = { title, description };\n return processedResult;\n } catch (error: unknown) {\n const message = error instanceof Error ? error.message : String(error);\n logger.error(`Error analyzing image: ${message}`);\n return {\n title: \"Failed to analyze image\",\n description: `Error: ${message}`,\n };\n }\n },\n [ModelType.TRANSCRIPTION]: async (\n runtime: IAgentRuntime,\n audioBuffer: Buffer,\n ) => {\n logger.debug({ size: audioBuffer?.length ?? 0 }, \"audioBuffer received\");\n\n const modelName = \"whisper-1\";\n logger.log(`[OpenAI] Using TRANSCRIPTION model: ${modelName}`);\n\n const baseURL = getBaseURL(runtime);\n if (!audioBuffer || audioBuffer.length === 0) {\n throw new Error(\"Audio buffer is empty or invalid for transcription\");\n }\n\n const formData = new FormData();\n const arrayBuffer = (\n audioBuffer as unknown as {\n buffer: ArrayBuffer;\n byteOffset: number;\n byteLength: number;\n }\n ).buffer;\n const start = (audioBuffer as any).byteOffset || 0;\n const end = start + ((audioBuffer as any).byteLength || 0);\n const safeArrayBuffer = arrayBuffer.slice(start, end);\n formData.append(\n \"file\",\n new Blob([safeArrayBuffer], { type: \"audio/mpeg\" }),\n \"recording.mp3\",\n );\n formData.append(\"model\", \"whisper-1\");\n\n try {\n const response = await fetch(`${baseURL}/audio/transcriptions`, {\n method: \"POST\",\n headers: {\n ...getAuthHeader(runtime),\n },\n body: formData,\n });\n\n const responseClone = response.clone();\n const rawResponseBody = await responseClone.text();\n\n logger.log({ response }, \"response\");\n\n if (!response.ok) {\n throw new Error(`Failed to transcribe audio: ${response.statusText}`);\n }\n\n const data = (await response.json()) as { text: string };\n const processedText = data.text;\n\n return processedText;\n } catch (error: unknown) {\n const message = error instanceof Error ? error.message : String(error);\n throw error;\n }\n },\n [ModelType.TEXT_TO_SPEECH]: async (\n runtime: IAgentRuntime,\n text: string,\n ) => {\n const ttsModelName = getSetting(\n runtime,\n \"OPENAI_TTS_MODEL\",\n \"gpt-4o-mini-tts\",\n );\n logger.log(`[OpenAI] Using TEXT_TO_SPEECH model: ${ttsModelName}`);\n try {\n const speechStream = await fetchTextToSpeech(runtime, text);\n return speechStream;\n } catch (error: unknown) {\n const message = error instanceof Error ? error.message : String(error);\n throw error;\n }\n },\n [ModelType.OBJECT_SMALL]: async (\n runtime: IAgentRuntime,\n params: ObjectGenerationParams,\n ) => {\n return generateObjectByModelType(\n runtime,\n params,\n ModelType.OBJECT_SMALL,\n getSmallModel,\n );\n },\n [ModelType.OBJECT_LARGE]: async (\n runtime: IAgentRuntime,\n params: ObjectGenerationParams,\n ) => {\n return generateObjectByModelType(\n runtime,\n params,\n ModelType.OBJECT_LARGE,\n getLargeModel,\n );\n },\n },\n tests: [\n {\n name: \"openai_plugin_tests\",\n tests: [\n {\n name: \"openai_test_url_and_api_key_validation\",\n fn: async (runtime: IAgentRuntime) => {\n const baseURL = getBaseURL(runtime);\n const response = await fetch(`${baseURL}/models`, {\n headers: {\n Authorization: `Bearer ${getApiKey(runtime)}`,\n },\n });\n const data = await response.json();\n logger.log(\n { data: (data as { data?: unknown[] })?.data?.length ?? \"N/A\" },\n \"Models Available\",\n );\n if (!response.ok) {\n throw new Error(\n `Failed to validate OpenAI API key: ${response.statusText}`,\n );\n }\n },\n },\n {\n name: \"openai_test_text_embedding\",\n fn: async (runtime: IAgentRuntime) => {\n try {\n const embedding = await runtime.useModel(\n ModelType.TEXT_EMBEDDING,\n {\n text: \"Hello, world!\",\n },\n );\n logger.log({ embedding }, \"embedding\");\n } catch (error: unknown) {\n const message =\n error instanceof Error ? error.message : String(error);\n logger.error(`Error in test_text_embedding: ${message}`);\n throw error;\n }\n },\n },\n {\n name: \"openai_test_text_large\",\n fn: async (runtime: IAgentRuntime) => {\n try {\n const text = await runtime.useModel(ModelType.TEXT_LARGE, {\n prompt: \"What is the nature of reality in 10 words?\",\n });\n if (text.length === 0) {\n throw new Error(\"Failed to generate text\");\n }\n logger.log({ text }, \"generated with test_text_large\");\n } catch (error: unknown) {\n const message =\n error instanceof Error ? error.message : String(error);\n logger.error(`Error in test_text_large: ${message}`);\n throw error;\n }\n },\n },\n {\n name: \"openai_test_text_small\",\n fn: async (runtime: IAgentRuntime) => {\n try {\n const text = await runtime.useModel(ModelType.TEXT_SMALL, {\n prompt: \"What is the nature of reality in 10 words?\",\n });\n if (text.length === 0) {\n throw new Error(\"Failed to generate text\");\n }\n logger.log({ text }, \"generated with test_text_small\");\n } catch (error: unknown) {\n const message =\n error instanceof Error ? error.message : String(error);\n logger.error(`Error in test_text_small: ${message}`);\n throw error;\n }\n },\n },\n {\n name: \"openai_test_image_generation\",\n fn: async (runtime: IAgentRuntime) => {\n logger.log(\"openai_test_image_generation\");\n try {\n const image = await runtime.useModel(ModelType.IMAGE, {\n prompt: \"A beautiful sunset over a calm ocean\",\n n: 1,\n size: \"1024x1024\",\n });\n logger.log({ image }, \"generated with test_image_generation\");\n } catch (error: unknown) {\n const message =\n error instanceof Error ? error.message : String(error);\n logger.error(`Error in test_image_generation: ${message}`);\n throw error;\n }\n },\n },\n {\n name: \"image-description\",\n fn: async (runtime: IAgentRuntime) => {\n try {\n logger.log(\"openai_test_image_description\");\n try {\n const result = await runtime.useModel(\n ModelType.IMAGE_DESCRIPTION,\n \"https://upload.wikimedia.org/wikipedia/commons/thumb/1/1c/Vitalik_Buterin_TechCrunch_London_2015_%28cropped%29.jpg/537px-Vitalik_Buterin_TechCrunch_London_2015_%28cropped%29.jpg\",\n );\n\n if (\n result &&\n typeof result === \"object\" &&\n \"title\" in result &&\n \"description\" in result\n ) {\n logger.log({ result }, \"Image description\");\n } else {\n logger.error(\n \"Invalid image description result format:\",\n result,\n );\n }\n } catch (e: unknown) {\n const message = e instanceof Error ? e.message : String(e);\n logger.error(`Error in image description test: ${message}`);\n }\n } catch (e: unknown) {\n const message = e instanceof Error ? e.message : String(e);\n logger.error(\n `Error in openai_test_image_description: ${message}`,\n );\n }\n },\n },\n {\n name: \"openai_test_transcription\",\n fn: async (runtime: IAgentRuntime) => {\n logger.log(\"openai_test_transcription\");\n try {\n const response = await fetch(\n \"https://upload.wikimedia.org/wikipedia/en/4/40/Chris_Benoit_Voice_Message.ogg\",\n );\n const arrayBuffer = await response.arrayBuffer();\n const transcription = await runtime.useModel(\n ModelType.TRANSCRIPTION,\n Buffer.from(new Uint8Array(arrayBuffer)),\n );\n logger.log(\n { transcription },\n \"generated with test_transcription\",\n );\n } catch (error: unknown) {\n const message =\n error instanceof Error ? error.message : String(error);\n logger.error(`Error in test_transcription: ${message}`);\n throw error;\n }\n },\n },\n {\n name: \"openai_test_text_tokenizer_encode\",\n fn: async (runtime: IAgentRuntime) => {\n const prompt = \"Hello tokenizer encode!\";\n const tokens = await runtime.useModel(\n ModelType.TEXT_TOKENIZER_ENCODE,\n { prompt },\n );\n if (!Array.isArray(tokens) || tokens.length === 0) {\n throw new Error(\n \"Failed to tokenize text: expected non-empty array of tokens\",\n );\n }\n logger.log({ tokens }, \"Tokenized output\");\n },\n },\n {\n name: \"openai_test_text_tokenizer_decode\",\n fn: async (runtime: IAgentRuntime) => {\n const prompt = \"Hello tokenizer decode!\";\n const tokens = await runtime.useModel(\n ModelType.TEXT_TOKENIZER_ENCODE,\n { prompt },\n );\n const decodedText = await runtime.useModel(\n ModelType.TEXT_TOKENIZER_DECODE,\n { tokens },\n );\n if (decodedText !== prompt) {\n throw new Error(\n `Decoded text does not match original. Expected \"${prompt}\", got \"${decodedText}\"`,\n );\n }\n logger.log({ decodedText }, \"Decoded text\");\n },\n },\n {\n name: \"openai_test_text_to_speech\",\n fn: async (runtime: IAgentRuntime) => {\n try {\n const text = \"Hello, this is a test for text-to-speech.\";\n const response = await fetchTextToSpeech(runtime, text);\n if (!response) {\n throw new Error(\"Failed to generate speech\");\n }\n logger.log(\"Generated speech successfully\");\n } catch (error: unknown) {\n const message =\n error instanceof Error ? error.message : String(error);\n logger.error(`Error in openai_test_text_to_speech: ${message}`);\n throw error;\n }\n },\n },\n ],\n },\n ],\n};\nexport default openaiPlugin;\n"
6
+ ],
7
+ "mappings": "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",
8
+ "debugId": "3AA0E1EB713F16F564756E2164756E21",
9
+ "names": []
10
+ }
@@ -0,0 +1,2 @@
1
+ export * from "./index";
2
+ export { default } from "./index";
package/dist/index.d.ts CHANGED
@@ -1,9 +1,7 @@
1
- import { Plugin } from '@elizaos/core';
2
-
1
+ import type { Plugin } from "@elizaos/core";
3
2
  /**
4
3
  * Defines the OpenAI plugin with its name, description, and configuration options.
5
4
  * @type {Plugin}
6
5
  */
7
- declare const openaiPlugin: Plugin;
8
-
9
- export { openaiPlugin as default, openaiPlugin };
6
+ export declare const openaiPlugin: Plugin;
7
+ export default openaiPlugin;
@@ -0,0 +1,2 @@
1
+ export * from "./index";
2
+ export { default } from "./index";
@@ -0,0 +1,2 @@
1
+ export * from '../index';
2
+ export { default } from '../index';
@@ -7,17 +7,26 @@ import {
7
7
  JSONParseError
8
8
  } from "ai";
9
9
  import { encodingForModel } from "js-tiktoken";
10
- import { fetch, FormData } from "undici";
11
10
  function getSetting(runtime, key, defaultValue) {
12
11
  return runtime.getSetting(key) ?? process.env[key] ?? defaultValue;
13
12
  }
13
+ function isBrowser() {
14
+ return typeof globalThis !== "undefined" && typeof globalThis.document !== "undefined";
15
+ }
16
+ function getAuthHeader(runtime, forEmbedding = false) {
17
+ if (isBrowser())
18
+ return {};
19
+ const key = forEmbedding ? getEmbeddingApiKey(runtime) : getApiKey(runtime);
20
+ return key ? { Authorization: `Bearer ${key}` } : {};
21
+ }
14
22
  function getBaseURL(runtime) {
15
- const baseURL = getSetting(runtime, "OPENAI_BASE_URL", "https://api.openai.com/v1");
23
+ const browserURL = getSetting(runtime, "OPENAI_BROWSER_BASE_URL");
24
+ const baseURL = isBrowser() && browserURL ? browserURL : getSetting(runtime, "OPENAI_BASE_URL", "https://api.openai.com/v1");
16
25
  logger.debug(`[OpenAI] Default base URL: ${baseURL}`);
17
26
  return baseURL;
18
27
  }
19
28
  function getEmbeddingBaseURL(runtime) {
20
- const embeddingURL = getSetting(runtime, "OPENAI_EMBEDDING_URL");
29
+ const embeddingURL = isBrowser() ? getSetting(runtime, "OPENAI_BROWSER_EMBEDDING_URL") || getSetting(runtime, "OPENAI_BROWSER_BASE_URL") : getSetting(runtime, "OPENAI_EMBEDDING_URL");
21
30
  if (embeddingURL) {
22
31
  logger.debug(`[OpenAI] Using specific embedding base URL: ${embeddingURL}`);
23
32
  return embeddingURL;
@@ -31,7 +40,7 @@ function getApiKey(runtime) {
31
40
  function getEmbeddingApiKey(runtime) {
32
41
  const embeddingApiKey = getSetting(runtime, "OPENAI_EMBEDDING_API_KEY");
33
42
  if (embeddingApiKey) {
34
- logger.debug(`[OpenAI] Using specific embedding API key: ${embeddingApiKey}`);
43
+ logger.debug("[OpenAI] Using specific embedding API key (present)");
35
44
  return embeddingApiKey;
36
45
  }
37
46
  logger.debug("[OpenAI] Falling back to general API key for embeddings.");
@@ -50,9 +59,7 @@ function getExperimentalTelemetry(runtime) {
50
59
  const setting = getSetting(runtime, "OPENAI_EXPERIMENTAL_TELEMETRY", "false");
51
60
  const normalizedSetting = String(setting).toLowerCase();
52
61
  const result = normalizedSetting === "true";
53
- logger.debug(
54
- `[OpenAI] Experimental telemetry in function: "${setting}" (type: ${typeof setting}, normalized: "${normalizedSetting}", result: ${result})`
55
- );
62
+ logger.debug(`[OpenAI] Experimental telemetry in function: "${setting}" (type: ${typeof setting}, normalized: "${normalizedSetting}", result: ${result})`);
56
63
  return result;
57
64
  }
58
65
  function createOpenAIClient(runtime) {
@@ -63,14 +70,12 @@ function createOpenAIClient(runtime) {
63
70
  }
64
71
  async function tokenizeText(model, prompt) {
65
72
  const modelName = model === ModelType.TEXT_SMALL ? process.env.OPENAI_SMALL_MODEL ?? process.env.SMALL_MODEL ?? "gpt-5-nano" : process.env.LARGE_MODEL ?? "gpt-5-mini";
66
- const encoding = encodingForModel(modelName);
67
- const tokens = encoding.encode(prompt);
73
+ const tokens = encodingForModel(modelName).encode(prompt);
68
74
  return tokens;
69
75
  }
70
76
  async function detokenizeText(model, tokens) {
71
77
  const modelName = model === ModelType.TEXT_SMALL ? process.env.OPENAI_SMALL_MODEL ?? process.env.SMALL_MODEL ?? "gpt-5-nano" : process.env.OPENAI_LARGE_MODEL ?? process.env.LARGE_MODEL ?? "gpt-5-mini";
72
- const encoding = encodingForModel(modelName);
73
- return encoding.decode(tokens);
78
+ return encodingForModel(modelName).decode(tokens);
74
79
  }
75
80
  async function generateObjectByModelType(runtime, params, modelType, getModelFn) {
76
81
  const openai = createOpenAIClient(runtime);
@@ -79,9 +84,7 @@ async function generateObjectByModelType(runtime, params, modelType, getModelFn)
79
84
  const temperature = params.temperature ?? 0;
80
85
  const schemaPresent = !!params.schema;
81
86
  if (schemaPresent) {
82
- logger.info(
83
- `Using ${modelType} without schema validation (schema provided but output=no-schema)`
84
- );
87
+ logger.info(`Using ${modelType} without schema validation (schema provided but output=no-schema)`);
85
88
  }
86
89
  try {
87
90
  const { object, usage } = await generateObject({
@@ -146,14 +149,13 @@ function emitModelUsageEvent(runtime, type, prompt, usage) {
146
149
  type,
147
150
  prompt,
148
151
  tokens: {
149
- prompt: usage.promptTokens,
150
- completion: usage.completionTokens,
152
+ prompt: usage.inputTokens,
153
+ completion: usage.outputTokens,
151
154
  total: usage.totalTokens
152
155
  }
153
156
  });
154
157
  }
155
158
  async function fetchTextToSpeech(runtime, text) {
156
- const apiKey = getApiKey(runtime);
157
159
  const model = getSetting(runtime, "OPENAI_TTS_MODEL", "gpt-4o-mini-tts");
158
160
  const voice = getSetting(runtime, "OPENAI_TTS_VOICE", "nova");
159
161
  const instructions = getSetting(runtime, "OPENAI_TTS_INSTRUCTIONS", "");
@@ -162,7 +164,7 @@ async function fetchTextToSpeech(runtime, text) {
162
164
  const res = await fetch(`${baseURL}/audio/speech`, {
163
165
  method: "POST",
164
166
  headers: {
165
- Authorization: `Bearer ${apiKey}`,
167
+ ...getAuthHeader(runtime),
166
168
  "Content-Type": "application/json"
167
169
  },
168
170
  body: JSON.stringify({
@@ -204,16 +206,14 @@ var openaiPlugin = {
204
206
  new Promise(async (resolve) => {
205
207
  resolve();
206
208
  try {
207
- if (!getApiKey(runtime)) {
208
- logger.warn(
209
- "OPENAI_API_KEY is not set in environment - OpenAI functionality will be limited"
210
- );
209
+ if (!getApiKey(runtime) && !isBrowser()) {
210
+ logger.warn("OPENAI_API_KEY is not set in environment - OpenAI functionality will be limited");
211
211
  return;
212
212
  }
213
213
  try {
214
214
  const baseURL = getBaseURL(runtime);
215
215
  const response = await fetch(`${baseURL}/models`, {
216
- headers: { Authorization: `Bearer ${getApiKey(runtime)}` }
216
+ headers: { ...getAuthHeader(runtime) }
217
217
  });
218
218
  if (!response.ok) {
219
219
  logger.warn(`OpenAI API key validation failed: ${response.statusText}`);
@@ -228,23 +228,14 @@ var openaiPlugin = {
228
228
  }
229
229
  } catch (error) {
230
230
  const message = error?.errors?.map((e) => e.message).join(", ") || (error instanceof Error ? error.message : String(error));
231
- logger.warn(
232
- `OpenAI plugin configuration issue: ${message} - You need to configure the OPENAI_API_KEY in your environment variables`
233
- );
231
+ logger.warn(`OpenAI plugin configuration issue: ${message} - You need to configure the OPENAI_API_KEY in your environment variables`);
234
232
  }
235
233
  });
236
234
  },
237
235
  models: {
238
236
  [ModelType.TEXT_EMBEDDING]: async (runtime, params) => {
239
- const embeddingModelName = getSetting(
240
- runtime,
241
- "OPENAI_EMBEDDING_MODEL",
242
- "text-embedding-3-small"
243
- );
244
- const embeddingDimension = Number.parseInt(
245
- getSetting(runtime, "OPENAI_EMBEDDING_DIMENSIONS", "1536") || "1536",
246
- 10
247
- );
237
+ const embeddingModelName = getSetting(runtime, "OPENAI_EMBEDDING_MODEL", "text-embedding-3-small");
238
+ const embeddingDimension = Number.parseInt(getSetting(runtime, "OPENAI_EMBEDDING_DIMENSIONS", "1536") || "1536", 10);
248
239
  if (!Object.values(VECTOR_DIMS).includes(embeddingDimension)) {
249
240
  const errorMsg = `Invalid embedding dimension: ${embeddingDimension}. Must be one of: ${Object.values(VECTOR_DIMS).join(", ")}`;
250
241
  logger.error(errorMsg);
@@ -274,15 +265,11 @@ var openaiPlugin = {
274
265
  return emptyVector;
275
266
  }
276
267
  const embeddingBaseURL = getEmbeddingBaseURL(runtime);
277
- const apiKey = getEmbeddingApiKey(runtime);
278
- if (!apiKey) {
279
- throw new Error("OpenAI API key not configured");
280
- }
281
268
  try {
282
269
  const response = await fetch(`${embeddingBaseURL}/embeddings`, {
283
270
  method: "POST",
284
271
  headers: {
285
- Authorization: `Bearer ${apiKey}`,
272
+ ...getAuthHeader(runtime, true),
286
273
  "Content-Type": "application/json"
287
274
  },
288
275
  body: JSON.stringify({
@@ -308,8 +295,8 @@ var openaiPlugin = {
308
295
  const embedding = data.data[0].embedding;
309
296
  if (data.usage) {
310
297
  const usage = {
311
- promptTokens: data.usage.prompt_tokens,
312
- completionTokens: 0,
298
+ inputTokens: data.usage.prompt_tokens,
299
+ outputTokens: 0,
313
300
  totalTokens: data.usage.total_tokens
314
301
  };
315
302
  emitModelUsageEvent(runtime, ModelType.TEXT_EMBEDDING, text, usage);
@@ -346,9 +333,9 @@ var openaiPlugin = {
346
333
  const { text: openaiResponse, usage } = await generateText({
347
334
  model: openai.languageModel(modelName),
348
335
  prompt,
349
- system: runtime.character.system ?? void 0,
336
+ system: runtime.character.system ?? undefined,
350
337
  temperature,
351
- maxTokens,
338
+ maxOutputTokens: maxTokens,
352
339
  frequencyPenalty,
353
340
  presencePenalty,
354
341
  stopSequences,
@@ -377,9 +364,9 @@ var openaiPlugin = {
377
364
  const { text: openaiResponse, usage } = await generateText({
378
365
  model: openai.languageModel(modelName),
379
366
  prompt,
380
- system: runtime.character.system ?? void 0,
367
+ system: runtime.character.system ?? undefined,
381
368
  temperature,
382
- maxTokens,
369
+ maxOutputTokens: maxTokens,
383
370
  frequencyPenalty,
384
371
  presencePenalty,
385
372
  stopSequences,
@@ -399,15 +386,11 @@ var openaiPlugin = {
399
386
  const modelName = "dall-e-3";
400
387
  logger.log(`[OpenAI] Using IMAGE model: ${modelName}`);
401
388
  const baseURL = getBaseURL(runtime);
402
- const apiKey = getApiKey(runtime);
403
- if (!apiKey) {
404
- throw new Error("OpenAI API key not configured");
405
- }
406
389
  try {
407
390
  const response = await fetch(`${baseURL}/images/generations`, {
408
391
  method: "POST",
409
392
  headers: {
410
- Authorization: `Bearer ${apiKey}`,
393
+ ...getAuthHeader(runtime),
411
394
  "Content-Type": "application/json"
412
395
  },
413
396
  body: JSON.stringify({
@@ -434,10 +417,7 @@ var openaiPlugin = {
434
417
  let promptText;
435
418
  const modelName = getImageDescriptionModel(runtime);
436
419
  logger.log(`[OpenAI] Using IMAGE_DESCRIPTION model: ${modelName}`);
437
- const maxTokens = Number.parseInt(
438
- getSetting(runtime, "OPENAI_IMAGE_DESCRIPTION_MAX_TOKENS", "8192") || "8192",
439
- 10
440
- );
420
+ const maxTokens = Number.parseInt(getSetting(runtime, "OPENAI_IMAGE_DESCRIPTION_MAX_TOKENS", "8192") || "8192", 10);
441
421
  if (typeof params === "string") {
442
422
  imageUrl = params;
443
423
  promptText = "Please analyze this image and provide a title and detailed description.";
@@ -455,14 +435,6 @@ var openaiPlugin = {
455
435
  }
456
436
  ];
457
437
  const baseURL = getBaseURL(runtime);
458
- const apiKey = getApiKey(runtime);
459
- if (!apiKey) {
460
- logger.error("OpenAI API key not set");
461
- return {
462
- title: "Failed to analyze image",
463
- description: "API key not configured"
464
- };
465
- }
466
438
  try {
467
439
  const requestBody = {
468
440
  model: modelName,
@@ -473,7 +445,7 @@ var openaiPlugin = {
473
445
  method: "POST",
474
446
  headers: {
475
447
  "Content-Type": "application/json",
476
- Authorization: `Bearer ${apiKey}`
448
+ ...getAuthHeader(runtime)
477
449
  },
478
450
  body: JSON.stringify(requestBody)
479
451
  });
@@ -486,16 +458,11 @@ var openaiPlugin = {
486
458
  const typedResult = result;
487
459
  const content = typedResult.choices?.[0]?.message?.content;
488
460
  if (typedResult.usage) {
489
- emitModelUsageEvent(
490
- runtime,
491
- ModelType.IMAGE_DESCRIPTION,
492
- typeof params === "string" ? params : params.prompt || "",
493
- {
494
- promptTokens: typedResult.usage.prompt_tokens,
495
- completionTokens: typedResult.usage.completion_tokens,
496
- totalTokens: typedResult.usage.total_tokens
497
- }
498
- );
461
+ emitModelUsageEvent(runtime, ModelType.IMAGE_DESCRIPTION, typeof params === "string" ? params : params.prompt || "", {
462
+ inputTokens: typedResult.usage.prompt_tokens,
463
+ outputTokens: typedResult.usage.completion_tokens,
464
+ totalTokens: typedResult.usage.total_tokens
465
+ });
499
466
  }
500
467
  if (!content) {
501
468
  return {
@@ -522,25 +489,25 @@ var openaiPlugin = {
522
489
  }
523
490
  },
524
491
  [ModelType.TRANSCRIPTION]: async (runtime, audioBuffer) => {
525
- logger.log({ audioBuffer }, "audioBuffer");
492
+ logger.debug({ size: audioBuffer?.length ?? 0 }, "audioBuffer received");
526
493
  const modelName = "whisper-1";
527
494
  logger.log(`[OpenAI] Using TRANSCRIPTION model: ${modelName}`);
528
495
  const baseURL = getBaseURL(runtime);
529
- const apiKey = getApiKey(runtime);
530
- if (!apiKey) {
531
- throw new Error("OpenAI API key not configured - Cannot make request");
532
- }
533
496
  if (!audioBuffer || audioBuffer.length === 0) {
534
497
  throw new Error("Audio buffer is empty or invalid for transcription");
535
498
  }
536
- const formData = new FormData();
537
- formData.append("file", new Blob([audioBuffer]), "recording.mp3");
499
+ const formData = new FormData;
500
+ const arrayBuffer = audioBuffer.buffer;
501
+ const start = audioBuffer.byteOffset || 0;
502
+ const end = start + (audioBuffer.byteLength || 0);
503
+ const safeArrayBuffer = arrayBuffer.slice(start, end);
504
+ formData.append("file", new Blob([safeArrayBuffer], { type: "audio/mpeg" }), "recording.mp3");
538
505
  formData.append("model", "whisper-1");
539
506
  try {
540
507
  const response = await fetch(`${baseURL}/audio/transcriptions`, {
541
508
  method: "POST",
542
509
  headers: {
543
- Authorization: `Bearer ${apiKey}`
510
+ ...getAuthHeader(runtime)
544
511
  },
545
512
  body: formData
546
513
  });
@@ -590,10 +557,7 @@ var openaiPlugin = {
590
557
  }
591
558
  });
592
559
  const data = await response.json();
593
- logger.log(
594
- { data: data?.data?.length ?? "N/A" },
595
- "Models Available"
596
- );
560
+ logger.log({ data: data?.data?.length ?? "N/A" }, "Models Available");
597
561
  if (!response.ok) {
598
562
  throw new Error(`Failed to validate OpenAI API key: ${response.statusText}`);
599
563
  }
@@ -674,10 +638,7 @@ var openaiPlugin = {
674
638
  try {
675
639
  logger.log("openai_test_image_description");
676
640
  try {
677
- const result = await runtime.useModel(
678
- ModelType.IMAGE_DESCRIPTION,
679
- "https://upload.wikimedia.org/wikipedia/commons/thumb/1/1c/Vitalik_Buterin_TechCrunch_London_2015_%28cropped%29.jpg/537px-Vitalik_Buterin_TechCrunch_London_2015_%28cropped%29.jpg"
680
- );
641
+ const result = await runtime.useModel(ModelType.IMAGE_DESCRIPTION, "https://upload.wikimedia.org/wikipedia/commons/thumb/1/1c/Vitalik_Buterin_TechCrunch_London_2015_%28cropped%29.jpg/537px-Vitalik_Buterin_TechCrunch_London_2015_%28cropped%29.jpg");
681
642
  if (result && typeof result === "object" && "title" in result && "description" in result) {
682
643
  logger.log({ result }, "Image description");
683
644
  } else {
@@ -698,14 +659,9 @@ var openaiPlugin = {
698
659
  fn: async (runtime) => {
699
660
  logger.log("openai_test_transcription");
700
661
  try {
701
- const response = await fetch(
702
- "https://upload.wikimedia.org/wikipedia/en/4/40/Chris_Benoit_Voice_Message.ogg"
703
- );
662
+ const response = await fetch("https://upload.wikimedia.org/wikipedia/en/4/40/Chris_Benoit_Voice_Message.ogg");
704
663
  const arrayBuffer = await response.arrayBuffer();
705
- const transcription = await runtime.useModel(
706
- ModelType.TRANSCRIPTION,
707
- Buffer.from(new Uint8Array(arrayBuffer))
708
- );
664
+ const transcription = await runtime.useModel(ModelType.TRANSCRIPTION, Buffer.from(new Uint8Array(arrayBuffer)));
709
665
  logger.log({ transcription }, "generated with test_transcription");
710
666
  } catch (error) {
711
667
  const message = error instanceof Error ? error.message : String(error);
@@ -732,9 +688,7 @@ var openaiPlugin = {
732
688
  const tokens = await runtime.useModel(ModelType.TEXT_TOKENIZER_ENCODE, { prompt });
733
689
  const decodedText = await runtime.useModel(ModelType.TEXT_TOKENIZER_DECODE, { tokens });
734
690
  if (decodedText !== prompt) {
735
- throw new Error(
736
- `Decoded text does not match original. Expected "${prompt}", got "${decodedText}"`
737
- );
691
+ throw new Error(`Decoded text does not match original. Expected "${prompt}", got "${decodedText}"`);
738
692
  }
739
693
  logger.log({ decodedText }, "Decoded text");
740
694
  }
@@ -760,9 +714,10 @@ var openaiPlugin = {
760
714
  }
761
715
  ]
762
716
  };
763
- var index_default = openaiPlugin;
717
+ var src_default = openaiPlugin;
764
718
  export {
765
- index_default as default,
766
- openaiPlugin
719
+ openaiPlugin,
720
+ src_default as default
767
721
  };
768
- //# sourceMappingURL=index.js.map
722
+
723
+ //# debugId=3D7FEC05492A6D1864756E2164756E21