@genkit-ai/compat-oai 1.33.0 → 1.35.0

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.
@@ -48,7 +48,7 @@ type DeepSeekPlugin = {
48
48
  *
49
49
  * Usage: To use the models, initialize the deepseek plugin inside
50
50
  * `configureGenkit` and pass the configuration options. If no API key is
51
- * provided in the options, the environment variable `OPENAI_API_KEY` must be
51
+ * provided in the options, the environment variable `DEEPSEEK_API_KEY` must be
52
52
  * set.
53
53
  *
54
54
  * Example:
@@ -48,7 +48,7 @@ type DeepSeekPlugin = {
48
48
  *
49
49
  * Usage: To use the models, initialize the deepseek plugin inside
50
50
  * `configureGenkit` and pass the configuration options. If no API key is
51
- * provided in the options, the environment variable `OPENAI_API_KEY` must be
51
+ * provided in the options, the environment variable `DEEPSEEK_API_KEY` must be
52
52
  * set.
53
53
  *
54
54
  * Example:
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/deepseek/index.ts"],"sourcesContent":["/**\n * Copyright 2024 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n ActionMetadata,\n GenkitError,\n modelActionMetadata,\n ModelReference,\n z,\n} from 'genkit';\nimport { logger } from 'genkit/logging';\nimport { type GenkitPluginV2 } from 'genkit/plugin';\nimport { ActionType } from 'genkit/registry';\nimport OpenAI from 'openai';\nimport { openAICompatible, PluginOptions } from '../index.js';\nimport { defineCompatOpenAIModel } from '../model.js';\nimport {\n DeepSeekChatCompletionConfigSchema,\n deepSeekModelRef,\n deepSeekRequestBuilder,\n SUPPORTED_DEEPSEEK_MODELS,\n} from './deepseek.js';\n\nexport type DeepSeekPluginOptions = Omit<PluginOptions, 'name' | 'baseURL'>;\n\nfunction createResolver(pluginOptions: PluginOptions) {\n return async (client: OpenAI, actionType: ActionType, actionName: string) => {\n if (actionType === 'model') {\n const modelRef = deepSeekModelRef({\n name: actionName,\n });\n return defineCompatOpenAIModel({\n name: modelRef.name,\n client,\n pluginOptions,\n modelRef,\n requestBuilder: deepSeekRequestBuilder,\n });\n } else {\n logger.warn('Only model actions are supported by the DeepSeek plugin');\n return undefined;\n }\n };\n}\n\nconst listActions = async (client: OpenAI): Promise<ActionMetadata[]> => {\n return await client.models.list().then((response) =>\n response.data\n .filter((model) => model.object === 'model')\n .map((model: OpenAI.Model) => {\n const modelRef =\n SUPPORTED_DEEPSEEK_MODELS[model.id] ??\n deepSeekModelRef({\n name: model.id,\n });\n return modelActionMetadata({\n name: modelRef.name,\n info: modelRef.info,\n configSchema: modelRef.configSchema,\n });\n })\n );\n};\n\nexport function deepSeekPlugin(\n options?: DeepSeekPluginOptions\n): GenkitPluginV2 {\n const apiKey = options?.apiKey ?? process.env.DEEPSEEK_API_KEY;\n if (!apiKey) {\n throw new GenkitError({\n status: 'FAILED_PRECONDITION',\n message:\n 'Please pass in the API key or set the DEEPSEEK_API_KEY environment variable.',\n });\n }\n const pluginOptions = { name: 'deepseek', ...options };\n return openAICompatible({\n name: 'deepseek',\n baseURL: 'https://api.deepseek.com',\n apiKey,\n ...options,\n initializer: async (client) => {\n return Object.values(SUPPORTED_DEEPSEEK_MODELS).map((modelRef) =>\n defineCompatOpenAIModel({\n name: modelRef.name,\n client,\n pluginOptions,\n modelRef,\n requestBuilder: deepSeekRequestBuilder,\n })\n );\n },\n resolver: createResolver(pluginOptions),\n listActions,\n });\n}\n\nexport type DeepSeekPlugin = {\n (params?: DeepSeekPluginOptions): GenkitPluginV2;\n model(\n name: keyof typeof SUPPORTED_DEEPSEEK_MODELS,\n config?: z.infer<typeof DeepSeekChatCompletionConfigSchema>\n ): ModelReference<typeof DeepSeekChatCompletionConfigSchema>;\n model(name: string, config?: any): ModelReference<z.ZodTypeAny>;\n};\n\nconst model = ((name: string, config?: any): ModelReference<z.ZodTypeAny> => {\n return deepSeekModelRef({\n name,\n config,\n });\n}) as DeepSeekPlugin['model'];\n\n/**\n * This module provides an interface to the DeepSeek models through the Genkit\n * plugin system. It allows users to interact with various models by providing\n * an API key and optional configuration.\n *\n * The main export is the `deepseek` plugin, which can be configured with an API\n * key either directly or through environment variables. It initializes the\n * OpenAI client and makes available the models for use.\n *\n * Exports:\n * - deepSeek: The main plugin function to interact with DeepSeek, via OpenAI\n * compatible API.\n *\n * Usage: To use the models, initialize the deepseek plugin inside\n * `configureGenkit` and pass the configuration options. If no API key is\n * provided in the options, the environment variable `OPENAI_API_KEY` must be\n * set.\n *\n * Example:\n * ```\n * import { deepSeek } from '@genkit-ai/compat-oai/deepseek';\n *\n * export default configureGenkit({\n * plugins: [\n * deepSeek()\n * ... // other plugins\n * ]\n * });\n * ```\n */\nexport const deepSeek: DeepSeekPlugin = Object.assign(deepSeekPlugin, {\n model,\n});\n\nexport default deepSeek;\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAgBA,oBAMO;AACP,qBAAuB;AAIvB,eAAgD;AAChD,mBAAwC;AACxC,sBAKO;AAIP,SAAS,eAAe,eAA8B;AACpD,SAAO,OAAO,QAAgB,YAAwB,eAAuB;AAC3E,QAAI,eAAe,SAAS;AAC1B,YAAM,eAAW,kCAAiB;AAAA,QAChC,MAAM;AAAA,MACR,CAAC;AACD,iBAAO,sCAAwB;AAAA,QAC7B,MAAM,SAAS;AAAA,QACf;AAAA,QACA;AAAA,QACA;AAAA,QACA,gBAAgB;AAAA,MAClB,CAAC;AAAA,IACH,OAAO;AACL,4BAAO,KAAK,yDAAyD;AACrE,aAAO;AAAA,IACT;AAAA,EACF;AACF;AAEA,MAAM,cAAc,OAAO,WAA8C;AACvE,SAAO,MAAM,OAAO,OAAO,KAAK,EAAE;AAAA,IAAK,CAAC,aACtC,SAAS,KACN,OAAO,CAACA,WAAUA,OAAM,WAAW,OAAO,EAC1C,IAAI,CAACA,WAAwB;AAC5B,YAAM,WACJ,0CAA0BA,OAAM,EAAE,SAClC,kCAAiB;AAAA,QACf,MAAMA,OAAM;AAAA,MACd,CAAC;AACH,iBAAO,mCAAoB;AAAA,QACzB,MAAM,SAAS;AAAA,QACf,MAAM,SAAS;AAAA,QACf,cAAc,SAAS;AAAA,MACzB,CAAC;AAAA,IACH,CAAC;AAAA,EACL;AACF;AAEO,SAAS,eACd,SACgB;AAChB,QAAM,SAAS,SAAS,UAAU,QAAQ,IAAI;AAC9C,MAAI,CAAC,QAAQ;AACX,UAAM,IAAI,0BAAY;AAAA,MACpB,QAAQ;AAAA,MACR,SACE;AAAA,IACJ,CAAC;AAAA,EACH;AACA,QAAM,gBAAgB,EAAE,MAAM,YAAY,GAAG,QAAQ;AACrD,aAAO,2BAAiB;AAAA,IACtB,MAAM;AAAA,IACN,SAAS;AAAA,IACT;AAAA,IACA,GAAG;AAAA,IACH,aAAa,OAAO,WAAW;AAC7B,aAAO,OAAO,OAAO,yCAAyB,EAAE;AAAA,QAAI,CAAC,iBACnD,sCAAwB;AAAA,UACtB,MAAM,SAAS;AAAA,UACf;AAAA,UACA;AAAA,UACA;AAAA,UACA,gBAAgB;AAAA,QAClB,CAAC;AAAA,MACH;AAAA,IACF;AAAA,IACA,UAAU,eAAe,aAAa;AAAA,IACtC;AAAA,EACF,CAAC;AACH;AAWA,MAAM,SAAS,CAAC,MAAc,WAA+C;AAC3E,aAAO,kCAAiB;AAAA,IACtB;AAAA,IACA;AAAA,EACF,CAAC;AACH;AAgCO,MAAM,WAA2B,OAAO,OAAO,gBAAgB;AAAA,EACpE;AACF,CAAC;AAED,IAAO,mBAAQ;","names":["model"]}
1
+ {"version":3,"sources":["../../src/deepseek/index.ts"],"sourcesContent":["/**\n * Copyright 2024 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n ActionMetadata,\n GenkitError,\n modelActionMetadata,\n ModelReference,\n z,\n} from 'genkit';\nimport { logger } from 'genkit/logging';\nimport { type GenkitPluginV2 } from 'genkit/plugin';\nimport { ActionType } from 'genkit/registry';\nimport OpenAI from 'openai';\nimport { openAICompatible, PluginOptions } from '../index.js';\nimport { defineCompatOpenAIModel } from '../model.js';\nimport {\n DeepSeekChatCompletionConfigSchema,\n deepSeekModelRef,\n deepSeekRequestBuilder,\n SUPPORTED_DEEPSEEK_MODELS,\n} from './deepseek.js';\n\nexport type DeepSeekPluginOptions = Omit<PluginOptions, 'name' | 'baseURL'>;\n\nfunction createResolver(pluginOptions: PluginOptions) {\n return async (client: OpenAI, actionType: ActionType, actionName: string) => {\n if (actionType === 'model') {\n const modelRef = deepSeekModelRef({\n name: actionName,\n });\n return defineCompatOpenAIModel({\n name: modelRef.name,\n client,\n pluginOptions,\n modelRef,\n requestBuilder: deepSeekRequestBuilder,\n });\n } else {\n logger.warn('Only model actions are supported by the DeepSeek plugin');\n return undefined;\n }\n };\n}\n\nconst listActions = async (client: OpenAI): Promise<ActionMetadata[]> => {\n return await client.models.list().then((response) =>\n response.data\n .filter((model) => model.object === 'model')\n .map((model: OpenAI.Model) => {\n const modelRef =\n SUPPORTED_DEEPSEEK_MODELS[model.id] ??\n deepSeekModelRef({\n name: model.id,\n });\n return modelActionMetadata({\n name: modelRef.name,\n info: modelRef.info,\n configSchema: modelRef.configSchema,\n });\n })\n );\n};\n\nexport function deepSeekPlugin(\n options?: DeepSeekPluginOptions\n): GenkitPluginV2 {\n const apiKey = options?.apiKey ?? process.env.DEEPSEEK_API_KEY;\n if (!apiKey) {\n throw new GenkitError({\n status: 'FAILED_PRECONDITION',\n message:\n 'Please pass in the API key or set the DEEPSEEK_API_KEY environment variable.',\n });\n }\n const pluginOptions = { name: 'deepseek', ...options };\n return openAICompatible({\n name: 'deepseek',\n baseURL: 'https://api.deepseek.com',\n apiKey,\n ...options,\n initializer: async (client) => {\n return Object.values(SUPPORTED_DEEPSEEK_MODELS).map((modelRef) =>\n defineCompatOpenAIModel({\n name: modelRef.name,\n client,\n pluginOptions,\n modelRef,\n requestBuilder: deepSeekRequestBuilder,\n })\n );\n },\n resolver: createResolver(pluginOptions),\n listActions,\n });\n}\n\nexport type DeepSeekPlugin = {\n (params?: DeepSeekPluginOptions): GenkitPluginV2;\n model(\n name: keyof typeof SUPPORTED_DEEPSEEK_MODELS,\n config?: z.infer<typeof DeepSeekChatCompletionConfigSchema>\n ): ModelReference<typeof DeepSeekChatCompletionConfigSchema>;\n model(name: string, config?: any): ModelReference<z.ZodTypeAny>;\n};\n\nconst model = ((name: string, config?: any): ModelReference<z.ZodTypeAny> => {\n return deepSeekModelRef({\n name,\n config,\n });\n}) as DeepSeekPlugin['model'];\n\n/**\n * This module provides an interface to the DeepSeek models through the Genkit\n * plugin system. It allows users to interact with various models by providing\n * an API key and optional configuration.\n *\n * The main export is the `deepseek` plugin, which can be configured with an API\n * key either directly or through environment variables. It initializes the\n * OpenAI client and makes available the models for use.\n *\n * Exports:\n * - deepSeek: The main plugin function to interact with DeepSeek, via OpenAI\n * compatible API.\n *\n * Usage: To use the models, initialize the deepseek plugin inside\n * `configureGenkit` and pass the configuration options. If no API key is\n * provided in the options, the environment variable `DEEPSEEK_API_KEY` must be\n * set.\n *\n * Example:\n * ```\n * import { deepSeek } from '@genkit-ai/compat-oai/deepseek';\n *\n * export default configureGenkit({\n * plugins: [\n * deepSeek()\n * ... // other plugins\n * ]\n * });\n * ```\n */\nexport const deepSeek: DeepSeekPlugin = Object.assign(deepSeekPlugin, {\n model,\n});\n\nexport default deepSeek;\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAgBA,oBAMO;AACP,qBAAuB;AAIvB,eAAgD;AAChD,mBAAwC;AACxC,sBAKO;AAIP,SAAS,eAAe,eAA8B;AACpD,SAAO,OAAO,QAAgB,YAAwB,eAAuB;AAC3E,QAAI,eAAe,SAAS;AAC1B,YAAM,eAAW,kCAAiB;AAAA,QAChC,MAAM;AAAA,MACR,CAAC;AACD,iBAAO,sCAAwB;AAAA,QAC7B,MAAM,SAAS;AAAA,QACf;AAAA,QACA;AAAA,QACA;AAAA,QACA,gBAAgB;AAAA,MAClB,CAAC;AAAA,IACH,OAAO;AACL,4BAAO,KAAK,yDAAyD;AACrE,aAAO;AAAA,IACT;AAAA,EACF;AACF;AAEA,MAAM,cAAc,OAAO,WAA8C;AACvE,SAAO,MAAM,OAAO,OAAO,KAAK,EAAE;AAAA,IAAK,CAAC,aACtC,SAAS,KACN,OAAO,CAACA,WAAUA,OAAM,WAAW,OAAO,EAC1C,IAAI,CAACA,WAAwB;AAC5B,YAAM,WACJ,0CAA0BA,OAAM,EAAE,SAClC,kCAAiB;AAAA,QACf,MAAMA,OAAM;AAAA,MACd,CAAC;AACH,iBAAO,mCAAoB;AAAA,QACzB,MAAM,SAAS;AAAA,QACf,MAAM,SAAS;AAAA,QACf,cAAc,SAAS;AAAA,MACzB,CAAC;AAAA,IACH,CAAC;AAAA,EACL;AACF;AAEO,SAAS,eACd,SACgB;AAChB,QAAM,SAAS,SAAS,UAAU,QAAQ,IAAI;AAC9C,MAAI,CAAC,QAAQ;AACX,UAAM,IAAI,0BAAY;AAAA,MACpB,QAAQ;AAAA,MACR,SACE;AAAA,IACJ,CAAC;AAAA,EACH;AACA,QAAM,gBAAgB,EAAE,MAAM,YAAY,GAAG,QAAQ;AACrD,aAAO,2BAAiB;AAAA,IACtB,MAAM;AAAA,IACN,SAAS;AAAA,IACT;AAAA,IACA,GAAG;AAAA,IACH,aAAa,OAAO,WAAW;AAC7B,aAAO,OAAO,OAAO,yCAAyB,EAAE;AAAA,QAAI,CAAC,iBACnD,sCAAwB;AAAA,UACtB,MAAM,SAAS;AAAA,UACf;AAAA,UACA;AAAA,UACA;AAAA,UACA,gBAAgB;AAAA,QAClB,CAAC;AAAA,MACH;AAAA,IACF;AAAA,IACA,UAAU,eAAe,aAAa;AAAA,IACtC;AAAA,EACF,CAAC;AACH;AAWA,MAAM,SAAS,CAAC,MAAc,WAA+C;AAC3E,aAAO,kCAAiB;AAAA,IACtB;AAAA,IACA;AAAA,EACF,CAAC;AACH;AAgCO,MAAM,WAA2B,OAAO,OAAO,gBAAgB;AAAA,EACpE;AACF,CAAC;AAED,IAAO,mBAAQ;","names":["model"]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/deepseek/index.ts"],"sourcesContent":["/**\n * Copyright 2024 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n ActionMetadata,\n GenkitError,\n modelActionMetadata,\n ModelReference,\n z,\n} from 'genkit';\nimport { logger } from 'genkit/logging';\nimport { type GenkitPluginV2 } from 'genkit/plugin';\nimport { ActionType } from 'genkit/registry';\nimport OpenAI from 'openai';\nimport { openAICompatible, PluginOptions } from '../index.js';\nimport { defineCompatOpenAIModel } from '../model.js';\nimport {\n DeepSeekChatCompletionConfigSchema,\n deepSeekModelRef,\n deepSeekRequestBuilder,\n SUPPORTED_DEEPSEEK_MODELS,\n} from './deepseek.js';\n\nexport type DeepSeekPluginOptions = Omit<PluginOptions, 'name' | 'baseURL'>;\n\nfunction createResolver(pluginOptions: PluginOptions) {\n return async (client: OpenAI, actionType: ActionType, actionName: string) => {\n if (actionType === 'model') {\n const modelRef = deepSeekModelRef({\n name: actionName,\n });\n return defineCompatOpenAIModel({\n name: modelRef.name,\n client,\n pluginOptions,\n modelRef,\n requestBuilder: deepSeekRequestBuilder,\n });\n } else {\n logger.warn('Only model actions are supported by the DeepSeek plugin');\n return undefined;\n }\n };\n}\n\nconst listActions = async (client: OpenAI): Promise<ActionMetadata[]> => {\n return await client.models.list().then((response) =>\n response.data\n .filter((model) => model.object === 'model')\n .map((model: OpenAI.Model) => {\n const modelRef =\n SUPPORTED_DEEPSEEK_MODELS[model.id] ??\n deepSeekModelRef({\n name: model.id,\n });\n return modelActionMetadata({\n name: modelRef.name,\n info: modelRef.info,\n configSchema: modelRef.configSchema,\n });\n })\n );\n};\n\nexport function deepSeekPlugin(\n options?: DeepSeekPluginOptions\n): GenkitPluginV2 {\n const apiKey = options?.apiKey ?? process.env.DEEPSEEK_API_KEY;\n if (!apiKey) {\n throw new GenkitError({\n status: 'FAILED_PRECONDITION',\n message:\n 'Please pass in the API key or set the DEEPSEEK_API_KEY environment variable.',\n });\n }\n const pluginOptions = { name: 'deepseek', ...options };\n return openAICompatible({\n name: 'deepseek',\n baseURL: 'https://api.deepseek.com',\n apiKey,\n ...options,\n initializer: async (client) => {\n return Object.values(SUPPORTED_DEEPSEEK_MODELS).map((modelRef) =>\n defineCompatOpenAIModel({\n name: modelRef.name,\n client,\n pluginOptions,\n modelRef,\n requestBuilder: deepSeekRequestBuilder,\n })\n );\n },\n resolver: createResolver(pluginOptions),\n listActions,\n });\n}\n\nexport type DeepSeekPlugin = {\n (params?: DeepSeekPluginOptions): GenkitPluginV2;\n model(\n name: keyof typeof SUPPORTED_DEEPSEEK_MODELS,\n config?: z.infer<typeof DeepSeekChatCompletionConfigSchema>\n ): ModelReference<typeof DeepSeekChatCompletionConfigSchema>;\n model(name: string, config?: any): ModelReference<z.ZodTypeAny>;\n};\n\nconst model = ((name: string, config?: any): ModelReference<z.ZodTypeAny> => {\n return deepSeekModelRef({\n name,\n config,\n });\n}) as DeepSeekPlugin['model'];\n\n/**\n * This module provides an interface to the DeepSeek models through the Genkit\n * plugin system. It allows users to interact with various models by providing\n * an API key and optional configuration.\n *\n * The main export is the `deepseek` plugin, which can be configured with an API\n * key either directly or through environment variables. It initializes the\n * OpenAI client and makes available the models for use.\n *\n * Exports:\n * - deepSeek: The main plugin function to interact with DeepSeek, via OpenAI\n * compatible API.\n *\n * Usage: To use the models, initialize the deepseek plugin inside\n * `configureGenkit` and pass the configuration options. If no API key is\n * provided in the options, the environment variable `OPENAI_API_KEY` must be\n * set.\n *\n * Example:\n * ```\n * import { deepSeek } from '@genkit-ai/compat-oai/deepseek';\n *\n * export default configureGenkit({\n * plugins: [\n * deepSeek()\n * ... // other plugins\n * ]\n * });\n * ```\n */\nexport const deepSeek: DeepSeekPlugin = Object.assign(deepSeekPlugin, {\n model,\n});\n\nexport default deepSeek;\n"],"mappings":"AAgBA;AAAA,EAEE;AAAA,EACA;AAAA,OAGK;AACP,SAAS,cAAc;AAIvB,SAAS,wBAAuC;AAChD,SAAS,+BAA+B;AACxC;AAAA,EAEE;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAIP,SAAS,eAAe,eAA8B;AACpD,SAAO,OAAO,QAAgB,YAAwB,eAAuB;AAC3E,QAAI,eAAe,SAAS;AAC1B,YAAM,WAAW,iBAAiB;AAAA,QAChC,MAAM;AAAA,MACR,CAAC;AACD,aAAO,wBAAwB;AAAA,QAC7B,MAAM,SAAS;AAAA,QACf;AAAA,QACA;AAAA,QACA;AAAA,QACA,gBAAgB;AAAA,MAClB,CAAC;AAAA,IACH,OAAO;AACL,aAAO,KAAK,yDAAyD;AACrE,aAAO;AAAA,IACT;AAAA,EACF;AACF;AAEA,MAAM,cAAc,OAAO,WAA8C;AACvE,SAAO,MAAM,OAAO,OAAO,KAAK,EAAE;AAAA,IAAK,CAAC,aACtC,SAAS,KACN,OAAO,CAACA,WAAUA,OAAM,WAAW,OAAO,EAC1C,IAAI,CAACA,WAAwB;AAC5B,YAAM,WACJ,0BAA0BA,OAAM,EAAE,KAClC,iBAAiB;AAAA,QACf,MAAMA,OAAM;AAAA,MACd,CAAC;AACH,aAAO,oBAAoB;AAAA,QACzB,MAAM,SAAS;AAAA,QACf,MAAM,SAAS;AAAA,QACf,cAAc,SAAS;AAAA,MACzB,CAAC;AAAA,IACH,CAAC;AAAA,EACL;AACF;AAEO,SAAS,eACd,SACgB;AAChB,QAAM,SAAS,SAAS,UAAU,QAAQ,IAAI;AAC9C,MAAI,CAAC,QAAQ;AACX,UAAM,IAAI,YAAY;AAAA,MACpB,QAAQ;AAAA,MACR,SACE;AAAA,IACJ,CAAC;AAAA,EACH;AACA,QAAM,gBAAgB,EAAE,MAAM,YAAY,GAAG,QAAQ;AACrD,SAAO,iBAAiB;AAAA,IACtB,MAAM;AAAA,IACN,SAAS;AAAA,IACT;AAAA,IACA,GAAG;AAAA,IACH,aAAa,OAAO,WAAW;AAC7B,aAAO,OAAO,OAAO,yBAAyB,EAAE;AAAA,QAAI,CAAC,aACnD,wBAAwB;AAAA,UACtB,MAAM,SAAS;AAAA,UACf;AAAA,UACA;AAAA,UACA;AAAA,UACA,gBAAgB;AAAA,QAClB,CAAC;AAAA,MACH;AAAA,IACF;AAAA,IACA,UAAU,eAAe,aAAa;AAAA,IACtC;AAAA,EACF,CAAC;AACH;AAWA,MAAM,SAAS,CAAC,MAAc,WAA+C;AAC3E,SAAO,iBAAiB;AAAA,IACtB;AAAA,IACA;AAAA,EACF,CAAC;AACH;AAgCO,MAAM,WAA2B,OAAO,OAAO,gBAAgB;AAAA,EACpE;AACF,CAAC;AAED,IAAO,mBAAQ;","names":["model"]}
1
+ {"version":3,"sources":["../../src/deepseek/index.ts"],"sourcesContent":["/**\n * Copyright 2024 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n ActionMetadata,\n GenkitError,\n modelActionMetadata,\n ModelReference,\n z,\n} from 'genkit';\nimport { logger } from 'genkit/logging';\nimport { type GenkitPluginV2 } from 'genkit/plugin';\nimport { ActionType } from 'genkit/registry';\nimport OpenAI from 'openai';\nimport { openAICompatible, PluginOptions } from '../index.js';\nimport { defineCompatOpenAIModel } from '../model.js';\nimport {\n DeepSeekChatCompletionConfigSchema,\n deepSeekModelRef,\n deepSeekRequestBuilder,\n SUPPORTED_DEEPSEEK_MODELS,\n} from './deepseek.js';\n\nexport type DeepSeekPluginOptions = Omit<PluginOptions, 'name' | 'baseURL'>;\n\nfunction createResolver(pluginOptions: PluginOptions) {\n return async (client: OpenAI, actionType: ActionType, actionName: string) => {\n if (actionType === 'model') {\n const modelRef = deepSeekModelRef({\n name: actionName,\n });\n return defineCompatOpenAIModel({\n name: modelRef.name,\n client,\n pluginOptions,\n modelRef,\n requestBuilder: deepSeekRequestBuilder,\n });\n } else {\n logger.warn('Only model actions are supported by the DeepSeek plugin');\n return undefined;\n }\n };\n}\n\nconst listActions = async (client: OpenAI): Promise<ActionMetadata[]> => {\n return await client.models.list().then((response) =>\n response.data\n .filter((model) => model.object === 'model')\n .map((model: OpenAI.Model) => {\n const modelRef =\n SUPPORTED_DEEPSEEK_MODELS[model.id] ??\n deepSeekModelRef({\n name: model.id,\n });\n return modelActionMetadata({\n name: modelRef.name,\n info: modelRef.info,\n configSchema: modelRef.configSchema,\n });\n })\n );\n};\n\nexport function deepSeekPlugin(\n options?: DeepSeekPluginOptions\n): GenkitPluginV2 {\n const apiKey = options?.apiKey ?? process.env.DEEPSEEK_API_KEY;\n if (!apiKey) {\n throw new GenkitError({\n status: 'FAILED_PRECONDITION',\n message:\n 'Please pass in the API key or set the DEEPSEEK_API_KEY environment variable.',\n });\n }\n const pluginOptions = { name: 'deepseek', ...options };\n return openAICompatible({\n name: 'deepseek',\n baseURL: 'https://api.deepseek.com',\n apiKey,\n ...options,\n initializer: async (client) => {\n return Object.values(SUPPORTED_DEEPSEEK_MODELS).map((modelRef) =>\n defineCompatOpenAIModel({\n name: modelRef.name,\n client,\n pluginOptions,\n modelRef,\n requestBuilder: deepSeekRequestBuilder,\n })\n );\n },\n resolver: createResolver(pluginOptions),\n listActions,\n });\n}\n\nexport type DeepSeekPlugin = {\n (params?: DeepSeekPluginOptions): GenkitPluginV2;\n model(\n name: keyof typeof SUPPORTED_DEEPSEEK_MODELS,\n config?: z.infer<typeof DeepSeekChatCompletionConfigSchema>\n ): ModelReference<typeof DeepSeekChatCompletionConfigSchema>;\n model(name: string, config?: any): ModelReference<z.ZodTypeAny>;\n};\n\nconst model = ((name: string, config?: any): ModelReference<z.ZodTypeAny> => {\n return deepSeekModelRef({\n name,\n config,\n });\n}) as DeepSeekPlugin['model'];\n\n/**\n * This module provides an interface to the DeepSeek models through the Genkit\n * plugin system. It allows users to interact with various models by providing\n * an API key and optional configuration.\n *\n * The main export is the `deepseek` plugin, which can be configured with an API\n * key either directly or through environment variables. It initializes the\n * OpenAI client and makes available the models for use.\n *\n * Exports:\n * - deepSeek: The main plugin function to interact with DeepSeek, via OpenAI\n * compatible API.\n *\n * Usage: To use the models, initialize the deepseek plugin inside\n * `configureGenkit` and pass the configuration options. If no API key is\n * provided in the options, the environment variable `DEEPSEEK_API_KEY` must be\n * set.\n *\n * Example:\n * ```\n * import { deepSeek } from '@genkit-ai/compat-oai/deepseek';\n *\n * export default configureGenkit({\n * plugins: [\n * deepSeek()\n * ... // other plugins\n * ]\n * });\n * ```\n */\nexport const deepSeek: DeepSeekPlugin = Object.assign(deepSeekPlugin, {\n model,\n});\n\nexport default deepSeek;\n"],"mappings":"AAgBA;AAAA,EAEE;AAAA,EACA;AAAA,OAGK;AACP,SAAS,cAAc;AAIvB,SAAS,wBAAuC;AAChD,SAAS,+BAA+B;AACxC;AAAA,EAEE;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAIP,SAAS,eAAe,eAA8B;AACpD,SAAO,OAAO,QAAgB,YAAwB,eAAuB;AAC3E,QAAI,eAAe,SAAS;AAC1B,YAAM,WAAW,iBAAiB;AAAA,QAChC,MAAM;AAAA,MACR,CAAC;AACD,aAAO,wBAAwB;AAAA,QAC7B,MAAM,SAAS;AAAA,QACf;AAAA,QACA;AAAA,QACA;AAAA,QACA,gBAAgB;AAAA,MAClB,CAAC;AAAA,IACH,OAAO;AACL,aAAO,KAAK,yDAAyD;AACrE,aAAO;AAAA,IACT;AAAA,EACF;AACF;AAEA,MAAM,cAAc,OAAO,WAA8C;AACvE,SAAO,MAAM,OAAO,OAAO,KAAK,EAAE;AAAA,IAAK,CAAC,aACtC,SAAS,KACN,OAAO,CAACA,WAAUA,OAAM,WAAW,OAAO,EAC1C,IAAI,CAACA,WAAwB;AAC5B,YAAM,WACJ,0BAA0BA,OAAM,EAAE,KAClC,iBAAiB;AAAA,QACf,MAAMA,OAAM;AAAA,MACd,CAAC;AACH,aAAO,oBAAoB;AAAA,QACzB,MAAM,SAAS;AAAA,QACf,MAAM,SAAS;AAAA,QACf,cAAc,SAAS;AAAA,MACzB,CAAC;AAAA,IACH,CAAC;AAAA,EACL;AACF;AAEO,SAAS,eACd,SACgB;AAChB,QAAM,SAAS,SAAS,UAAU,QAAQ,IAAI;AAC9C,MAAI,CAAC,QAAQ;AACX,UAAM,IAAI,YAAY;AAAA,MACpB,QAAQ;AAAA,MACR,SACE;AAAA,IACJ,CAAC;AAAA,EACH;AACA,QAAM,gBAAgB,EAAE,MAAM,YAAY,GAAG,QAAQ;AACrD,SAAO,iBAAiB;AAAA,IACtB,MAAM;AAAA,IACN,SAAS;AAAA,IACT;AAAA,IACA,GAAG;AAAA,IACH,aAAa,OAAO,WAAW;AAC7B,aAAO,OAAO,OAAO,yBAAyB,EAAE;AAAA,QAAI,CAAC,aACnD,wBAAwB;AAAA,UACtB,MAAM,SAAS;AAAA,UACf;AAAA,UACA;AAAA,UACA;AAAA,UACA,gBAAgB;AAAA,QAClB,CAAC;AAAA,MACH;AAAA,IACF;AAAA,IACA,UAAU,eAAe,aAAa;AAAA,IACtC;AAAA,EACF,CAAC;AACH;AAWA,MAAM,SAAS,CAAC,MAAc,WAA+C;AAC3E,SAAO,iBAAiB;AAAA,IACtB;AAAA,IACA;AAAA,EACF,CAAC;AACH;AAgCO,MAAM,WAA2B,OAAO,OAAO,gBAAgB;AAAA,EACpE;AACF,CAAC;AAED,IAAO,mBAAQ;","names":["model"]}
package/lib/model.js CHANGED
@@ -36,6 +36,14 @@ var import_genkit = require("genkit");
36
36
  var import_plugin = require("genkit/plugin");
37
37
  var import_openai = require("openai");
38
38
  var import_utils = require("./utils.js");
39
+ function parseRetryAfterMs(value) {
40
+ if (!value || !value.trim()) return void 0;
41
+ const seconds = Number(value);
42
+ if (!isNaN(seconds) && seconds >= 0) return seconds * 1e3;
43
+ const date = new Date(value);
44
+ if (!isNaN(date.getTime())) return Math.max(0, date.getTime() - Date.now());
45
+ return void 0;
46
+ }
39
47
  const VisualDetailLevelSchema = import_genkit.z.enum(["auto", "low", "high"]).optional();
40
48
  const ChatCompletionCommonConfigSchema = import_genkit.GenerationCommonConfigSchema.extend({
41
49
  temperature: import_genkit.z.number().min(0).max(2).optional(),
@@ -244,7 +252,7 @@ function fromOpenAIChoice(choice, jsonMode = false) {
244
252
  (toolCall) => fromOpenAIToolCall(toolCall, choice)
245
253
  );
246
254
  let content = [];
247
- if (toolRequestParts) {
255
+ if (toolRequestParts && toolRequestParts.length > 0) {
248
256
  content = toolRequestParts;
249
257
  } else {
250
258
  if ("reasoning_content" in choice.message && choice.message.reasoning_content) {
@@ -269,7 +277,7 @@ function fromOpenAIChunkChoice(choice, jsonMode = false) {
269
277
  (toolCall) => fromOpenAIToolCall(toolCall, choice)
270
278
  );
271
279
  let content = [];
272
- if (toolRequestParts) {
280
+ if (toolRequestParts && toolRequestParts.length > 0) {
273
281
  content = toolRequestParts;
274
282
  } else {
275
283
  if ("reasoning_content" in choice.delta && choice.delta.reasoning_content) {
@@ -434,9 +442,13 @@ function openAIModelRunner(name, defaultClient, requestBuilder, pluginOptions) {
434
442
  status = "UNAVAILABLE";
435
443
  break;
436
444
  }
445
+ const retryAfterHeader = e.headers?.get?.("retry-after") ?? e.headers?.["retry-after"];
446
+ const retryAfterMs = retryAfterHeader ? parseRetryAfterMs(retryAfterHeader) : void 0;
447
+ const responseMetadata = retryAfterMs !== void 0 ? { retryAfterMs } : void 0;
437
448
  throw new import_genkit.GenkitError({
438
449
  status,
439
- message: e.message
450
+ message: e.message,
451
+ responseMetadata
440
452
  });
441
453
  }
442
454
  throw e;
package/lib/model.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/model.ts"],"sourcesContent":["/**\n * Copyright 2024 The Fire Company\n * Copyright 2024 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type {\n GenerateRequest,\n GenerateResponseChunkData,\n GenerateResponseData,\n MessageData,\n ModelReference,\n Part,\n Role,\n StreamingCallback,\n ToolRequestPart,\n} from 'genkit';\nimport {\n GenerationCommonConfigSchema,\n GenkitError,\n Message,\n StatusName,\n modelRef,\n z,\n} from 'genkit';\nimport type { ModelAction, ModelInfo, ToolDefinition } from 'genkit/model';\nimport { model } from 'genkit/plugin';\nimport OpenAI, { APIError } from 'openai';\nimport type {\n ChatCompletion,\n ChatCompletionChunk,\n ChatCompletionContentPart,\n ChatCompletionCreateParams,\n ChatCompletionCreateParamsNonStreaming,\n ChatCompletionMessageParam,\n ChatCompletionMessageToolCall,\n ChatCompletionRole,\n ChatCompletionTool,\n CompletionChoice,\n} from 'openai/resources/index.mjs';\nimport { PluginOptions } from './index.js';\nimport { maybeCreateRequestScopedOpenAIClient, toModelName } from './utils.js';\n\nconst VisualDetailLevelSchema = z.enum(['auto', 'low', 'high']).optional();\n\ntype VisualDetailLevel = z.infer<typeof VisualDetailLevelSchema>;\n\nexport type ModelRequestBuilder = (\n req: GenerateRequest,\n params: ChatCompletionCreateParams\n) => void;\n\nexport const ChatCompletionCommonConfigSchema =\n GenerationCommonConfigSchema.extend({\n temperature: z.number().min(0).max(2).optional(),\n frequencyPenalty: z.number().min(-2).max(2).optional(),\n logProbs: z.boolean().optional(),\n presencePenalty: z.number().min(-2).max(2).optional(),\n topLogProbs: z.number().int().min(0).max(20).optional(),\n });\n\nexport function toOpenAIRole(role: Role): ChatCompletionRole {\n switch (role) {\n case 'user':\n return 'user';\n case 'model':\n return 'assistant';\n case 'system':\n return 'system';\n case 'tool':\n return 'tool';\n default:\n throw new Error(`role ${role} doesn't map to an OpenAI role.`);\n }\n}\n\n/**\n * Converts a Genkit ToolDefinition to an OpenAI ChatCompletionTool object.\n * @param tool The Genkit ToolDefinition to convert.\n * @returns The converted OpenAI ChatCompletionTool object.\n */\nexport function toOpenAITool(tool: ToolDefinition): ChatCompletionTool {\n return {\n type: 'function',\n function: {\n name: tool.name,\n parameters: tool.inputSchema !== null ? tool.inputSchema : undefined,\n },\n };\n}\n\n/**\n * Checks if a content type is an image type.\n * @param contentType The content type to check.\n * @returns True if the content type is an image type.\n */\nfunction isImageContentType(contentType?: string): boolean {\n if (!contentType) return false;\n return contentType.startsWith('image/');\n}\n\n/**\n * Extracts the base64 data and content type from a data URL.\n * @param url The data URL to parse.\n * @returns The base64 data and content type, or null if invalid.\n */\nfunction extractDataFromBase64Url(url: string): {\n data: string;\n contentType: string;\n} | null {\n const match = url.match(/^data:([^;]+);base64,(.+)$/);\n return (\n match && {\n contentType: match[1],\n data: match[2],\n }\n );\n}\n\n/**\n * Map of content types to file extensions.\n */\nconst FILE_EXTENSIONS: Record<string, string> = {\n 'application/pdf': 'pdf',\n 'application/msword': 'doc',\n 'application/vnd.openxmlformats-officedocument.wordprocessingml.document':\n 'docx',\n 'text/plain': 'txt',\n 'text/csv': 'csv',\n};\n\n/**\n * Generates a filename from a content type.\n * @param contentType The content type.\n * @returns A filename with appropriate extension.\n */\nfunction generateFilenameFromContentType(contentType: string): string {\n const ext = FILE_EXTENSIONS[contentType] || '';\n return ext ? `file.${ext}` : 'file';\n}\n\n/**\n * Converts a Genkit Part to the corresponding OpenAI ChatCompletionContentPart.\n * @param part The Genkit Part to convert.\n * @param visualDetailLevel The visual detail level to use for media parts.\n * @returns The corresponding OpenAI ChatCompletionContentPart.\n * @throws Error if the part contains unsupported fields for the current message role.\n */\nexport function toOpenAITextAndMedia(\n part: Part,\n visualDetailLevel: VisualDetailLevel\n): ChatCompletionContentPart {\n if (part.text) {\n return {\n type: 'text',\n text: part.text,\n };\n } else if (part.media) {\n // Determine the content type from the media part or data URL\n let contentType = part.media.contentType;\n if (!contentType && part.media.url.startsWith('data:')) {\n const extracted = extractDataFromBase64Url(part.media.url);\n if (extracted) {\n contentType = extracted.contentType;\n }\n }\n\n // Check if this is an image type\n // If no contentType is provided, preserve legacy behavior by treating the media\n // as an image URL (e.g. signed URLs or remote images without metadata)\n if (!contentType || isImageContentType(contentType)) {\n return {\n type: 'image_url',\n image_url: {\n url: part.media.url,\n detail: visualDetailLevel,\n },\n };\n }\n\n // For non-image types (like PDF), use the file type\n // OpenAI expects the full data URL (with data: prefix) in file_data\n if (part.media.url.startsWith('data:')) {\n const extracted = extractDataFromBase64Url(part.media.url);\n if (!extracted) {\n throw Error(\n `Invalid data URL format for media: ${part.media.url.substring(0, 50)}...`\n );\n }\n return {\n type: 'file',\n file: {\n filename: generateFilenameFromContentType(extracted.contentType),\n file_data: part.media.url, // Full data URL with prefix\n },\n } as ChatCompletionContentPart;\n }\n\n // If it's a remote URL with non-image content type, this is not supported\n // for chat completions according to OpenAI docs\n throw Error(\n `File URLs are not supported for chat completions. Only base64-encoded files and image URLs are supported. Content type: ${contentType}`\n );\n }\n throw Error(\n `Unsupported genkit part fields encountered for current message role: ${JSON.stringify(part)}.`\n );\n}\n\n/**\n * Converts a Genkit MessageData array to an OpenAI ChatCompletionMessageParam array.\n * @param messages The Genkit MessageData array to convert.\n * @param visualDetailLevel The visual detail level to use for media parts.\n * @returns The converted OpenAI ChatCompletionMessageParam array.\n */\nexport function toOpenAIMessages(\n messages: MessageData[],\n visualDetailLevel: VisualDetailLevel = 'auto'\n): ChatCompletionMessageParam[] {\n const apiMessages: ChatCompletionMessageParam[] = [];\n for (const message of messages) {\n const msg = new Message(message);\n const role = toOpenAIRole(message.role);\n switch (role) {\n case 'user':\n const content = msg.content.map((part) =>\n toOpenAITextAndMedia(part, visualDetailLevel)\n );\n // Check if we have only text content\n const onlyTextContent = content.some((item) => item.type !== 'text');\n\n // If all items are strings, just add them as text\n if (!onlyTextContent) {\n content.forEach((item) => {\n if (item.type === 'text') {\n apiMessages.push({\n role: role,\n content: item.text,\n });\n }\n });\n } else {\n apiMessages.push({\n role: role,\n content: content,\n });\n }\n break;\n case 'system':\n apiMessages.push({\n role: role,\n content: msg.text,\n });\n break;\n case 'assistant': {\n const toolCalls: ChatCompletionMessageToolCall[] = msg.content\n .filter(\n (\n part\n ): part is Part & {\n toolRequest: NonNullable<Part['toolRequest']>;\n } => Boolean(part.toolRequest)\n )\n .map((part) => ({\n id: part.toolRequest.ref ?? '',\n type: 'function',\n function: {\n name: part.toolRequest.name,\n arguments: JSON.stringify(part.toolRequest.input),\n },\n }));\n if (toolCalls.length > 0) {\n apiMessages.push({\n role: role,\n tool_calls: toolCalls,\n });\n } else {\n apiMessages.push({\n role: role,\n content: msg.text,\n });\n }\n break;\n }\n case 'tool': {\n const toolResponseParts = msg.toolResponseParts();\n toolResponseParts.map((part) => {\n apiMessages.push({\n role: role,\n tool_call_id: part.toolResponse.ref ?? '',\n content:\n typeof part.toolResponse.output === 'string'\n ? part.toolResponse.output\n : JSON.stringify(part.toolResponse.output),\n });\n });\n break;\n }\n }\n }\n return apiMessages;\n}\n\nconst finishReasonMap: Record<\n // OpenAI Node SDK doesn't support tool_call in the enum, but it is returned from the API\n CompletionChoice['finish_reason'] | 'tool_calls',\n GenerateResponseData['finishReason']\n> = {\n length: 'length',\n stop: 'stop',\n tool_calls: 'stop',\n content_filter: 'blocked',\n};\n\n/**\n * Converts an OpenAI tool call to a Genkit ToolRequestPart.\n * @param toolCall The OpenAI tool call to convert.\n * @returns The converted Genkit ToolRequestPart.\n */\nexport function fromOpenAIToolCall(\n toolCall:\n | ChatCompletionMessageToolCall\n | ChatCompletionChunk.Choice.Delta.ToolCall,\n choice: ChatCompletion.Choice | ChatCompletionChunk.Choice\n): ToolRequestPart {\n if (!toolCall.function) {\n throw Error(\n `Unexpected openAI chunk choice. tool_calls was provided but one or more tool_calls is missing.`\n );\n }\n const f = toolCall.function;\n\n // Only parse arguments when it is a JSON object and the finish reason is tool_calls to avoid parsing errors\n if (choice.finish_reason === 'tool_calls') {\n return {\n toolRequest: {\n name: f.name!,\n ref: toolCall.id,\n input: f.arguments ? JSON.parse(f.arguments) : f.arguments,\n },\n };\n } else {\n return {\n toolRequest: {\n name: f.name!,\n ref: toolCall.id,\n input: '',\n },\n };\n }\n}\n\n/**\n * Converts an OpenAI message event to a Genkit GenerateResponseData object.\n * @param choice The OpenAI message event to convert.\n * @param jsonMode Whether the event is a JSON response.\n * @returns The converted Genkit GenerateResponseData object.\n */\nexport function fromOpenAIChoice(\n choice: ChatCompletion.Choice,\n jsonMode = false\n): GenerateResponseData {\n const toolRequestParts = choice.message.tool_calls?.map((toolCall) =>\n fromOpenAIToolCall(toolCall, choice)\n );\n\n // Build content array based on what's present in the message\n let content: Part[] = [];\n\n if (toolRequestParts) {\n content = toolRequestParts as ToolRequestPart[];\n } else {\n // Handle reasoning_content if present\n if (\n 'reasoning_content' in choice.message &&\n choice.message.reasoning_content\n ) {\n content.push({ reasoning: choice.message.reasoning_content as string });\n }\n\n // Handle regular content if present\n if (choice.message.content) {\n content.push(\n jsonMode\n ? { data: JSON.parse(choice.message.content!) }\n : { text: choice.message.content! }\n );\n }\n }\n\n return {\n finishReason: finishReasonMap[choice.finish_reason] || 'other',\n message: {\n role: 'model',\n content,\n },\n };\n}\n\n/**\n * Converts an OpenAI message stream event to a Genkit GenerateResponseData\n * object.\n * @param choice The OpenAI message stream event to convert.\n * @param jsonMode Whether the event is a JSON response.\n * @returns The converted Genkit GenerateResponseData object.\n */\nexport function fromOpenAIChunkChoice(\n choice: ChatCompletionChunk.Choice,\n jsonMode = false\n): GenerateResponseData {\n const toolRequestParts = choice.delta.tool_calls?.map((toolCall) =>\n fromOpenAIToolCall(toolCall, choice)\n );\n\n // Build content array based on what's present in the delta\n let content: Part[] = [];\n\n if (toolRequestParts) {\n content = toolRequestParts as ToolRequestPart[];\n } else {\n // Handle reasoning_content if present\n if ('reasoning_content' in choice.delta && choice.delta.reasoning_content) {\n content.push({ reasoning: choice.delta.reasoning_content as string });\n }\n\n // Handle regular content if present\n if (choice.delta.content) {\n content.push(\n jsonMode\n ? { data: JSON.parse(choice.delta.content!) }\n : { text: choice.delta.content! }\n );\n }\n }\n\n return {\n finishReason: choice.finish_reason\n ? finishReasonMap[choice.finish_reason] || 'other'\n : 'unknown',\n message: {\n role: 'model',\n content,\n },\n };\n}\n\n/**\n * Converts an OpenAI request to an OpenAI API request body.\n * @param modelName The name of the OpenAI model to use.\n * @param request The Genkit GenerateRequest to convert.\n * @returns The converted OpenAI API request body.\n * @throws An error if the specified model is not supported or if an unsupported output format is requested.\n */\nexport function toOpenAIRequestBody(\n modelName: string,\n request: GenerateRequest,\n requestBuilder?: ModelRequestBuilder\n) {\n const messages = toOpenAIMessages(\n request.messages,\n request.config?.visualDetailLevel\n );\n const {\n temperature,\n maxOutputTokens, // unused\n topK, // unused\n topP: top_p,\n frequencyPenalty: frequency_penalty,\n logProbs: logprobs,\n presencePenalty: presence_penalty,\n topLogProbs: top_logprobs,\n stopSequences: stop,\n version: modelVersion,\n tools: toolsFromConfig,\n apiKey,\n ...restOfConfig\n } = request.config ?? {};\n\n const tools: ChatCompletionTool[] = request.tools?.map(toOpenAITool) ?? [];\n if (toolsFromConfig) {\n tools.push(...(toolsFromConfig as any[]));\n }\n let body = {\n model: modelVersion ?? modelName,\n messages,\n tools: tools.length > 0 ? tools : undefined,\n temperature,\n top_p,\n stop,\n frequency_penalty,\n presence_penalty,\n top_logprobs,\n logprobs,\n } as ChatCompletionCreateParamsNonStreaming;\n if (requestBuilder) {\n // If override provided, apply the override to the OpenAI request.\n // User must control passthrough config too.\n requestBuilder(request, body);\n } else {\n body = { ...body, ...restOfConfig }; // passthrough for other config\n }\n const response_format = request.output?.format;\n if (response_format === 'json') {\n if (request.output?.schema) {\n body.response_format = {\n type: 'json_schema',\n json_schema: {\n name: 'output',\n schema: request.output!.schema,\n },\n };\n } else {\n body.response_format = {\n type: 'json_object',\n };\n }\n } else if (response_format === 'text') {\n body.response_format = {\n type: 'text',\n };\n }\n for (const key in body) {\n if (!body[key] || (Array.isArray(body[key]) && !body[key].length))\n delete body[key];\n }\n return body;\n}\n\n/**\n * Creates the runner used by Genkit to interact with an OpenAI compatible\n * model.\n * @param name The name of the GPT model.\n * @param client The OpenAI client instance.\n * @returns The runner that Genkit will call when the model is invoked.\n */\nexport function openAIModelRunner(\n name: string,\n defaultClient: OpenAI,\n requestBuilder?: ModelRequestBuilder,\n pluginOptions?: Omit<PluginOptions, 'apiKey'>\n) {\n return async (\n request: GenerateRequest,\n options?: {\n streamingRequested?: boolean;\n sendChunk?: StreamingCallback<GenerateResponseChunkData>;\n abortSignal?: AbortSignal;\n }\n ): Promise<GenerateResponseData> => {\n const client = maybeCreateRequestScopedOpenAIClient(\n pluginOptions,\n request,\n defaultClient\n );\n try {\n let response: ChatCompletion;\n const body = toOpenAIRequestBody(name, request, requestBuilder);\n if (options?.streamingRequested) {\n const stream = client.beta.chat.completions.stream(\n {\n ...body,\n stream: true,\n stream_options: {\n include_usage: true,\n },\n },\n { signal: options?.abortSignal }\n );\n for await (const chunk of stream) {\n chunk.choices?.forEach((chunk) => {\n const c = fromOpenAIChunkChoice(chunk);\n options?.sendChunk!({\n index: chunk.index,\n content: c.message?.content ?? [],\n });\n });\n }\n response = await stream.finalChatCompletion();\n } else {\n response = await client.chat.completions.create(body, {\n signal: options?.abortSignal,\n });\n }\n const standardResponse: GenerateResponseData = {\n usage: {\n inputTokens: response.usage?.prompt_tokens,\n outputTokens: response.usage?.completion_tokens,\n totalTokens: response.usage?.total_tokens,\n },\n raw: response,\n };\n if (response.choices.length === 0) {\n return standardResponse;\n } else {\n const choice = response.choices[0];\n return {\n ...fromOpenAIChoice(choice, request.output?.format === 'json'),\n ...standardResponse,\n };\n }\n } catch (e) {\n if (e instanceof APIError) {\n let status: StatusName = 'UNKNOWN';\n switch (e.status) {\n case 429:\n status = 'RESOURCE_EXHAUSTED';\n break;\n case 401:\n status = 'PERMISSION_DENIED';\n break;\n case 403:\n status = 'UNAUTHENTICATED';\n break;\n case 400:\n status = 'INVALID_ARGUMENT';\n break;\n case 500:\n status = 'INTERNAL';\n break;\n case 503:\n status = 'UNAVAILABLE';\n break;\n }\n throw new GenkitError({\n status,\n message: e.message,\n });\n }\n throw e;\n }\n };\n}\n\n/**\n * Method to define a new Genkit Model that is compatible with Open AI\n * Chat Completions API. \n *\n * These models are to be used to chat with a large language model.\n *\n * @param params An object containing parameters for defining the OpenAI\n * Chat model.\n * @param params.ai The Genkit AI instance.\n * @param params.name The name of the model.\n * @param params.client The OpenAI client instance.\n * @param params.modelRef Optional reference to the model's configuration and\n * custom options.\n\n * @returns the created {@link ModelAction}\n */\nexport function defineCompatOpenAIModel<\n CustomOptions extends z.ZodTypeAny = z.ZodTypeAny,\n>(params: {\n name: string;\n client: OpenAI;\n modelRef?: ModelReference<CustomOptions>;\n requestBuilder?: ModelRequestBuilder;\n pluginOptions?: PluginOptions;\n}): ModelAction {\n const { name, client, pluginOptions, modelRef, requestBuilder } = params;\n const modelName = toModelName(name, pluginOptions?.name);\n const actionName =\n modelRef?.name ?? `${pluginOptions?.name ?? 'compat-oai'}/${modelName}`;\n\n return model(\n {\n name: actionName,\n ...modelRef?.info,\n configSchema: modelRef?.configSchema,\n },\n openAIModelRunner(modelName, client, requestBuilder, pluginOptions)\n );\n}\n\nconst GENERIC_MODEL_INFO: ModelInfo = {\n supports: {\n multiturn: true,\n media: true,\n tools: true,\n toolChoice: true,\n systemRole: true,\n },\n};\n\n/** ModelRef helper, with reasonable defaults for OpenAI-compatible providers */\nexport function compatOaiModelRef<\n CustomOptions extends z.ZodTypeAny = z.ZodTypeAny,\n>(params: {\n name: string;\n info?: ModelInfo;\n configSchema?: CustomOptions;\n config?: any;\n namespace?: string;\n}): ModelReference<CustomOptions> {\n const {\n name,\n info = GENERIC_MODEL_INFO,\n configSchema,\n config = undefined,\n namespace,\n } = params;\n return modelRef({\n name,\n configSchema: configSchema || (ChatCompletionCommonConfigSchema as any),\n info: info,\n config,\n namespace,\n });\n}\n"],"mappings":"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","names":["chunk","modelRef"]}
1
+ {"version":3,"sources":["../src/model.ts"],"sourcesContent":["/**\n * Copyright 2024 The Fire Company\n * Copyright 2024 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type {\n GenerateRequest,\n GenerateResponseChunkData,\n GenerateResponseData,\n MessageData,\n ModelReference,\n Part,\n Role,\n StreamingCallback,\n ToolRequestPart,\n} from 'genkit';\nimport {\n GenerationCommonConfigSchema,\n GenkitError,\n Message,\n StatusName,\n modelRef,\n z,\n type ErrorResponseMetadata,\n} from 'genkit';\nimport type { ModelAction, ModelInfo, ToolDefinition } from 'genkit/model';\nimport { model } from 'genkit/plugin';\nimport OpenAI, { APIError } from 'openai';\nimport type {\n ChatCompletion,\n ChatCompletionChunk,\n ChatCompletionContentPart,\n ChatCompletionCreateParams,\n ChatCompletionCreateParamsNonStreaming,\n ChatCompletionMessageParam,\n ChatCompletionMessageToolCall,\n ChatCompletionRole,\n ChatCompletionTool,\n CompletionChoice,\n} from 'openai/resources/index.mjs';\nimport { PluginOptions } from './index.js';\nimport { maybeCreateRequestScopedOpenAIClient, toModelName } from './utils.js';\n\n/**\n * Parses a `Retry-After` header value into milliseconds.\n * Supports delay-seconds and HTTP-date formats (RFC 7231 §7.1.3).\n */\nfunction parseRetryAfterMs(value: string): number | undefined {\n if (!value || !value.trim()) return undefined;\n const seconds = Number(value);\n if (!isNaN(seconds) && seconds >= 0) return seconds * 1000;\n const date = new Date(value);\n if (!isNaN(date.getTime())) return Math.max(0, date.getTime() - Date.now());\n return undefined;\n}\n\nconst VisualDetailLevelSchema = z.enum(['auto', 'low', 'high']).optional();\n\ntype VisualDetailLevel = z.infer<typeof VisualDetailLevelSchema>;\n\nexport type ModelRequestBuilder = (\n req: GenerateRequest,\n params: ChatCompletionCreateParams\n) => void;\n\nexport const ChatCompletionCommonConfigSchema =\n GenerationCommonConfigSchema.extend({\n temperature: z.number().min(0).max(2).optional(),\n frequencyPenalty: z.number().min(-2).max(2).optional(),\n logProbs: z.boolean().optional(),\n presencePenalty: z.number().min(-2).max(2).optional(),\n topLogProbs: z.number().int().min(0).max(20).optional(),\n });\n\nexport function toOpenAIRole(role: Role): ChatCompletionRole {\n switch (role) {\n case 'user':\n return 'user';\n case 'model':\n return 'assistant';\n case 'system':\n return 'system';\n case 'tool':\n return 'tool';\n default:\n throw new Error(`role ${role} doesn't map to an OpenAI role.`);\n }\n}\n\n/**\n * Converts a Genkit ToolDefinition to an OpenAI ChatCompletionTool object.\n * @param tool The Genkit ToolDefinition to convert.\n * @returns The converted OpenAI ChatCompletionTool object.\n */\nexport function toOpenAITool(tool: ToolDefinition): ChatCompletionTool {\n return {\n type: 'function',\n function: {\n name: tool.name,\n parameters: tool.inputSchema !== null ? tool.inputSchema : undefined,\n },\n };\n}\n\n/**\n * Checks if a content type is an image type.\n * @param contentType The content type to check.\n * @returns True if the content type is an image type.\n */\nfunction isImageContentType(contentType?: string): boolean {\n if (!contentType) return false;\n return contentType.startsWith('image/');\n}\n\n/**\n * Extracts the base64 data and content type from a data URL.\n * @param url The data URL to parse.\n * @returns The base64 data and content type, or null if invalid.\n */\nfunction extractDataFromBase64Url(url: string): {\n data: string;\n contentType: string;\n} | null {\n const match = url.match(/^data:([^;]+);base64,(.+)$/);\n return (\n match && {\n contentType: match[1],\n data: match[2],\n }\n );\n}\n\n/**\n * Map of content types to file extensions.\n */\nconst FILE_EXTENSIONS: Record<string, string> = {\n 'application/pdf': 'pdf',\n 'application/msword': 'doc',\n 'application/vnd.openxmlformats-officedocument.wordprocessingml.document':\n 'docx',\n 'text/plain': 'txt',\n 'text/csv': 'csv',\n};\n\n/**\n * Generates a filename from a content type.\n * @param contentType The content type.\n * @returns A filename with appropriate extension.\n */\nfunction generateFilenameFromContentType(contentType: string): string {\n const ext = FILE_EXTENSIONS[contentType] || '';\n return ext ? `file.${ext}` : 'file';\n}\n\n/**\n * Converts a Genkit Part to the corresponding OpenAI ChatCompletionContentPart.\n * @param part The Genkit Part to convert.\n * @param visualDetailLevel The visual detail level to use for media parts.\n * @returns The corresponding OpenAI ChatCompletionContentPart.\n * @throws Error if the part contains unsupported fields for the current message role.\n */\nexport function toOpenAITextAndMedia(\n part: Part,\n visualDetailLevel: VisualDetailLevel\n): ChatCompletionContentPart {\n if (part.text) {\n return {\n type: 'text',\n text: part.text,\n };\n } else if (part.media) {\n // Determine the content type from the media part or data URL\n let contentType = part.media.contentType;\n if (!contentType && part.media.url.startsWith('data:')) {\n const extracted = extractDataFromBase64Url(part.media.url);\n if (extracted) {\n contentType = extracted.contentType;\n }\n }\n\n // Check if this is an image type\n // If no contentType is provided, preserve legacy behavior by treating the media\n // as an image URL (e.g. signed URLs or remote images without metadata)\n if (!contentType || isImageContentType(contentType)) {\n return {\n type: 'image_url',\n image_url: {\n url: part.media.url,\n detail: visualDetailLevel,\n },\n };\n }\n\n // For non-image types (like PDF), use the file type\n // OpenAI expects the full data URL (with data: prefix) in file_data\n if (part.media.url.startsWith('data:')) {\n const extracted = extractDataFromBase64Url(part.media.url);\n if (!extracted) {\n throw Error(\n `Invalid data URL format for media: ${part.media.url.substring(0, 50)}...`\n );\n }\n return {\n type: 'file',\n file: {\n filename: generateFilenameFromContentType(extracted.contentType),\n file_data: part.media.url, // Full data URL with prefix\n },\n } as ChatCompletionContentPart;\n }\n\n // If it's a remote URL with non-image content type, this is not supported\n // for chat completions according to OpenAI docs\n throw Error(\n `File URLs are not supported for chat completions. Only base64-encoded files and image URLs are supported. Content type: ${contentType}`\n );\n }\n throw Error(\n `Unsupported genkit part fields encountered for current message role: ${JSON.stringify(part)}.`\n );\n}\n\n/**\n * Converts a Genkit MessageData array to an OpenAI ChatCompletionMessageParam array.\n * @param messages The Genkit MessageData array to convert.\n * @param visualDetailLevel The visual detail level to use for media parts.\n * @returns The converted OpenAI ChatCompletionMessageParam array.\n */\nexport function toOpenAIMessages(\n messages: MessageData[],\n visualDetailLevel: VisualDetailLevel = 'auto'\n): ChatCompletionMessageParam[] {\n const apiMessages: ChatCompletionMessageParam[] = [];\n for (const message of messages) {\n const msg = new Message(message);\n const role = toOpenAIRole(message.role);\n switch (role) {\n case 'user':\n const content = msg.content.map((part) =>\n toOpenAITextAndMedia(part, visualDetailLevel)\n );\n // Check if we have only text content\n const onlyTextContent = content.some((item) => item.type !== 'text');\n\n // If all items are strings, just add them as text\n if (!onlyTextContent) {\n content.forEach((item) => {\n if (item.type === 'text') {\n apiMessages.push({\n role: role,\n content: item.text,\n });\n }\n });\n } else {\n apiMessages.push({\n role: role,\n content: content,\n });\n }\n break;\n case 'system':\n apiMessages.push({\n role: role,\n content: msg.text,\n });\n break;\n case 'assistant': {\n const toolCalls: ChatCompletionMessageToolCall[] = msg.content\n .filter(\n (\n part\n ): part is Part & {\n toolRequest: NonNullable<Part['toolRequest']>;\n } => Boolean(part.toolRequest)\n )\n .map((part) => ({\n id: part.toolRequest.ref ?? '',\n type: 'function',\n function: {\n name: part.toolRequest.name,\n arguments: JSON.stringify(part.toolRequest.input),\n },\n }));\n if (toolCalls.length > 0) {\n apiMessages.push({\n role: role,\n tool_calls: toolCalls,\n });\n } else {\n apiMessages.push({\n role: role,\n content: msg.text,\n });\n }\n break;\n }\n case 'tool': {\n const toolResponseParts = msg.toolResponseParts();\n toolResponseParts.map((part) => {\n apiMessages.push({\n role: role,\n tool_call_id: part.toolResponse.ref ?? '',\n content:\n typeof part.toolResponse.output === 'string'\n ? part.toolResponse.output\n : JSON.stringify(part.toolResponse.output),\n });\n });\n break;\n }\n }\n }\n return apiMessages;\n}\n\nconst finishReasonMap: Record<\n // OpenAI Node SDK doesn't support tool_call in the enum, but it is returned from the API\n CompletionChoice['finish_reason'] | 'tool_calls',\n GenerateResponseData['finishReason']\n> = {\n length: 'length',\n stop: 'stop',\n tool_calls: 'stop',\n content_filter: 'blocked',\n};\n\n/**\n * Converts an OpenAI tool call to a Genkit ToolRequestPart.\n * @param toolCall The OpenAI tool call to convert.\n * @returns The converted Genkit ToolRequestPart.\n */\nexport function fromOpenAIToolCall(\n toolCall:\n | ChatCompletionMessageToolCall\n | ChatCompletionChunk.Choice.Delta.ToolCall,\n choice: ChatCompletion.Choice | ChatCompletionChunk.Choice\n): ToolRequestPart {\n if (!toolCall.function) {\n throw Error(\n `Unexpected openAI chunk choice. tool_calls was provided but one or more tool_calls is missing.`\n );\n }\n const f = toolCall.function;\n\n // Only parse arguments when it is a JSON object and the finish reason is tool_calls to avoid parsing errors\n if (choice.finish_reason === 'tool_calls') {\n return {\n toolRequest: {\n name: f.name!,\n ref: toolCall.id,\n input: f.arguments ? JSON.parse(f.arguments) : f.arguments,\n },\n };\n } else {\n return {\n toolRequest: {\n name: f.name!,\n ref: toolCall.id,\n input: '',\n },\n };\n }\n}\n\n/**\n * Converts an OpenAI message event to a Genkit GenerateResponseData object.\n * @param choice The OpenAI message event to convert.\n * @param jsonMode Whether the event is a JSON response.\n * @returns The converted Genkit GenerateResponseData object.\n */\nexport function fromOpenAIChoice(\n choice: ChatCompletion.Choice,\n jsonMode = false\n): GenerateResponseData {\n const toolRequestParts = choice.message.tool_calls?.map((toolCall) =>\n fromOpenAIToolCall(toolCall, choice)\n );\n\n // Build content array based on what's present in the message\n let content: Part[] = [];\n\n if (toolRequestParts && toolRequestParts.length > 0) {\n content = toolRequestParts as ToolRequestPart[];\n } else {\n // Handle reasoning_content if present\n if (\n 'reasoning_content' in choice.message &&\n choice.message.reasoning_content\n ) {\n content.push({ reasoning: choice.message.reasoning_content as string });\n }\n\n // Handle regular content if present\n if (choice.message.content) {\n content.push(\n jsonMode\n ? { data: JSON.parse(choice.message.content!) }\n : { text: choice.message.content! }\n );\n }\n }\n\n return {\n finishReason: finishReasonMap[choice.finish_reason] || 'other',\n message: {\n role: 'model',\n content,\n },\n };\n}\n\n/**\n * Converts an OpenAI message stream event to a Genkit GenerateResponseData\n * object.\n * @param choice The OpenAI message stream event to convert.\n * @param jsonMode Whether the event is a JSON response.\n * @returns The converted Genkit GenerateResponseData object.\n */\nexport function fromOpenAIChunkChoice(\n choice: ChatCompletionChunk.Choice,\n jsonMode = false\n): GenerateResponseData {\n const toolRequestParts = choice.delta.tool_calls?.map((toolCall) =>\n fromOpenAIToolCall(toolCall, choice)\n );\n\n // Build content array based on what's present in the delta\n let content: Part[] = [];\n\n if (toolRequestParts && toolRequestParts.length > 0) {\n content = toolRequestParts as ToolRequestPart[];\n } else {\n // Handle reasoning_content if present\n if ('reasoning_content' in choice.delta && choice.delta.reasoning_content) {\n content.push({ reasoning: choice.delta.reasoning_content as string });\n }\n\n // Handle regular content if present\n if (choice.delta.content) {\n content.push(\n jsonMode\n ? { data: JSON.parse(choice.delta.content!) }\n : { text: choice.delta.content! }\n );\n }\n }\n\n return {\n finishReason: choice.finish_reason\n ? finishReasonMap[choice.finish_reason] || 'other'\n : 'unknown',\n message: {\n role: 'model',\n content,\n },\n };\n}\n\n/**\n * Converts an OpenAI request to an OpenAI API request body.\n * @param modelName The name of the OpenAI model to use.\n * @param request The Genkit GenerateRequest to convert.\n * @returns The converted OpenAI API request body.\n * @throws An error if the specified model is not supported or if an unsupported output format is requested.\n */\nexport function toOpenAIRequestBody(\n modelName: string,\n request: GenerateRequest,\n requestBuilder?: ModelRequestBuilder\n) {\n const messages = toOpenAIMessages(\n request.messages,\n request.config?.visualDetailLevel\n );\n const {\n temperature,\n maxOutputTokens, // unused\n topK, // unused\n topP: top_p,\n frequencyPenalty: frequency_penalty,\n logProbs: logprobs,\n presencePenalty: presence_penalty,\n topLogProbs: top_logprobs,\n stopSequences: stop,\n version: modelVersion,\n tools: toolsFromConfig,\n apiKey,\n ...restOfConfig\n } = request.config ?? {};\n\n const tools: ChatCompletionTool[] = request.tools?.map(toOpenAITool) ?? [];\n if (toolsFromConfig) {\n tools.push(...(toolsFromConfig as any[]));\n }\n let body = {\n model: modelVersion ?? modelName,\n messages,\n tools: tools.length > 0 ? tools : undefined,\n temperature,\n top_p,\n stop,\n frequency_penalty,\n presence_penalty,\n top_logprobs,\n logprobs,\n } as ChatCompletionCreateParamsNonStreaming;\n if (requestBuilder) {\n // If override provided, apply the override to the OpenAI request.\n // User must control passthrough config too.\n requestBuilder(request, body);\n } else {\n body = { ...body, ...restOfConfig }; // passthrough for other config\n }\n const response_format = request.output?.format;\n if (response_format === 'json') {\n if (request.output?.schema) {\n body.response_format = {\n type: 'json_schema',\n json_schema: {\n name: 'output',\n schema: request.output!.schema,\n },\n };\n } else {\n body.response_format = {\n type: 'json_object',\n };\n }\n } else if (response_format === 'text') {\n body.response_format = {\n type: 'text',\n };\n }\n for (const key in body) {\n if (!body[key] || (Array.isArray(body[key]) && !body[key].length))\n delete body[key];\n }\n return body;\n}\n\n/**\n * Creates the runner used by Genkit to interact with an OpenAI compatible\n * model.\n * @param name The name of the GPT model.\n * @param client The OpenAI client instance.\n * @returns The runner that Genkit will call when the model is invoked.\n */\nexport function openAIModelRunner(\n name: string,\n defaultClient: OpenAI,\n requestBuilder?: ModelRequestBuilder,\n pluginOptions?: Omit<PluginOptions, 'apiKey'>\n) {\n return async (\n request: GenerateRequest,\n options?: {\n streamingRequested?: boolean;\n sendChunk?: StreamingCallback<GenerateResponseChunkData>;\n abortSignal?: AbortSignal;\n }\n ): Promise<GenerateResponseData> => {\n const client = maybeCreateRequestScopedOpenAIClient(\n pluginOptions,\n request,\n defaultClient\n );\n try {\n let response: ChatCompletion;\n const body = toOpenAIRequestBody(name, request, requestBuilder);\n if (options?.streamingRequested) {\n const stream = client.beta.chat.completions.stream(\n {\n ...body,\n stream: true,\n stream_options: {\n include_usage: true,\n },\n },\n { signal: options?.abortSignal }\n );\n for await (const chunk of stream) {\n chunk.choices?.forEach((chunk) => {\n const c = fromOpenAIChunkChoice(chunk);\n options?.sendChunk!({\n index: chunk.index,\n content: c.message?.content ?? [],\n });\n });\n }\n response = await stream.finalChatCompletion();\n } else {\n response = await client.chat.completions.create(body, {\n signal: options?.abortSignal,\n });\n }\n const standardResponse: GenerateResponseData = {\n usage: {\n inputTokens: response.usage?.prompt_tokens,\n outputTokens: response.usage?.completion_tokens,\n totalTokens: response.usage?.total_tokens,\n },\n raw: response,\n };\n if (response.choices.length === 0) {\n return standardResponse;\n } else {\n const choice = response.choices[0];\n return {\n ...fromOpenAIChoice(choice, request.output?.format === 'json'),\n ...standardResponse,\n };\n }\n } catch (e) {\n if (e instanceof APIError) {\n let status: StatusName = 'UNKNOWN';\n switch (e.status) {\n case 429:\n status = 'RESOURCE_EXHAUSTED';\n break;\n case 401:\n status = 'PERMISSION_DENIED';\n break;\n case 403:\n status = 'UNAUTHENTICATED';\n break;\n case 400:\n status = 'INVALID_ARGUMENT';\n break;\n case 500:\n status = 'INTERNAL';\n break;\n case 503:\n status = 'UNAVAILABLE';\n break;\n }\n const retryAfterHeader =\n e.headers?.get?.('retry-after') ??\n (e.headers as any)?.['retry-after'];\n const retryAfterMs = retryAfterHeader\n ? parseRetryAfterMs(retryAfterHeader)\n : undefined;\n const responseMetadata: ErrorResponseMetadata | undefined =\n retryAfterMs !== undefined ? { retryAfterMs } : undefined;\n throw new GenkitError({\n status,\n message: e.message,\n responseMetadata,\n });\n }\n throw e;\n }\n };\n}\n\n/**\n * Method to define a new Genkit Model that is compatible with Open AI\n * Chat Completions API.\n *\n * These models are to be used to chat with a large language model.\n *\n * @param params An object containing parameters for defining the OpenAI\n * Chat model.\n * @param params.ai The Genkit AI instance.\n * @param params.name The name of the model.\n * @param params.client The OpenAI client instance.\n * @param params.modelRef Optional reference to the model's configuration and\n * custom options.\n\n * @returns the created {@link ModelAction}\n */\nexport function defineCompatOpenAIModel<\n CustomOptions extends z.ZodTypeAny = z.ZodTypeAny,\n>(params: {\n name: string;\n client: OpenAI;\n modelRef?: ModelReference<CustomOptions>;\n requestBuilder?: ModelRequestBuilder;\n pluginOptions?: PluginOptions;\n}): ModelAction {\n const { name, client, pluginOptions, modelRef, requestBuilder } = params;\n const modelName = toModelName(name, pluginOptions?.name);\n const actionName =\n modelRef?.name ?? `${pluginOptions?.name ?? 'compat-oai'}/${modelName}`;\n\n return model(\n {\n name: actionName,\n ...modelRef?.info,\n configSchema: modelRef?.configSchema,\n },\n openAIModelRunner(modelName, client, requestBuilder, pluginOptions)\n );\n}\n\nconst GENERIC_MODEL_INFO: ModelInfo = {\n supports: {\n multiturn: true,\n media: true,\n tools: true,\n toolChoice: true,\n systemRole: true,\n },\n};\n\n/** ModelRef helper, with reasonable defaults for OpenAI-compatible providers */\nexport function compatOaiModelRef<\n CustomOptions extends z.ZodTypeAny = z.ZodTypeAny,\n>(params: {\n name: string;\n info?: ModelInfo;\n configSchema?: CustomOptions;\n config?: any;\n namespace?: string;\n}): ModelReference<CustomOptions> {\n const {\n name,\n info = GENERIC_MODEL_INFO,\n configSchema,\n config = undefined,\n namespace,\n } = params;\n return modelRef({\n name,\n configSchema: configSchema || (ChatCompletionCommonConfigSchema as any),\n info: info,\n config,\n namespace,\n });\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA4BA,oBAQO;AAEP,oBAAsB;AACtB,oBAAiC;AAcjC,mBAAkE;AAMlE,SAAS,kBAAkB,OAAmC;AAC5D,MAAI,CAAC,SAAS,CAAC,MAAM,KAAK,EAAG,QAAO;AACpC,QAAM,UAAU,OAAO,KAAK;AAC5B,MAAI,CAAC,MAAM,OAAO,KAAK,WAAW,EAAG,QAAO,UAAU;AACtD,QAAM,OAAO,IAAI,KAAK,KAAK;AAC3B,MAAI,CAAC,MAAM,KAAK,QAAQ,CAAC,EAAG,QAAO,KAAK,IAAI,GAAG,KAAK,QAAQ,IAAI,KAAK,IAAI,CAAC;AAC1E,SAAO;AACT;AAEA,MAAM,0BAA0B,gBAAE,KAAK,CAAC,QAAQ,OAAO,MAAM,CAAC,EAAE,SAAS;AASlE,MAAM,mCACX,2CAA6B,OAAO;AAAA,EAClC,aAAa,gBAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,CAAC,EAAE,SAAS;AAAA,EAC/C,kBAAkB,gBAAE,OAAO,EAAE,IAAI,EAAE,EAAE,IAAI,CAAC,EAAE,SAAS;AAAA,EACrD,UAAU,gBAAE,QAAQ,EAAE,SAAS;AAAA,EAC/B,iBAAiB,gBAAE,OAAO,EAAE,IAAI,EAAE,EAAE,IAAI,CAAC,EAAE,SAAS;AAAA,EACpD,aAAa,gBAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,EAAE,EAAE,SAAS;AACxD,CAAC;AAEI,SAAS,aAAa,MAAgC;AAC3D,UAAQ,MAAM;AAAA,IACZ,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT;AACE,YAAM,IAAI,MAAM,QAAQ,IAAI,iCAAiC;AAAA,EACjE;AACF;AAOO,SAAS,aAAa,MAA0C;AACrE,SAAO;AAAA,IACL,MAAM;AAAA,IACN,UAAU;AAAA,MACR,MAAM,KAAK;AAAA,MACX,YAAY,KAAK,gBAAgB,OAAO,KAAK,cAAc;AAAA,IAC7D;AAAA,EACF;AACF;AAOA,SAAS,mBAAmB,aAA+B;AACzD,MAAI,CAAC,YAAa,QAAO;AACzB,SAAO,YAAY,WAAW,QAAQ;AACxC;AAOA,SAAS,yBAAyB,KAGzB;AACP,QAAM,QAAQ,IAAI,MAAM,4BAA4B;AACpD,SACE,SAAS;AAAA,IACP,aAAa,MAAM,CAAC;AAAA,IACpB,MAAM,MAAM,CAAC;AAAA,EACf;AAEJ;AAKA,MAAM,kBAA0C;AAAA,EAC9C,mBAAmB;AAAA,EACnB,sBAAsB;AAAA,EACtB,2EACE;AAAA,EACF,cAAc;AAAA,EACd,YAAY;AACd;AAOA,SAAS,gCAAgC,aAA6B;AACpE,QAAM,MAAM,gBAAgB,WAAW,KAAK;AAC5C,SAAO,MAAM,QAAQ,GAAG,KAAK;AAC/B;AASO,SAAS,qBACd,MACA,mBAC2B;AAC3B,MAAI,KAAK,MAAM;AACb,WAAO;AAAA,MACL,MAAM;AAAA,MACN,MAAM,KAAK;AAAA,IACb;AAAA,EACF,WAAW,KAAK,OAAO;AAErB,QAAI,cAAc,KAAK,MAAM;AAC7B,QAAI,CAAC,eAAe,KAAK,MAAM,IAAI,WAAW,OAAO,GAAG;AACtD,YAAM,YAAY,yBAAyB,KAAK,MAAM,GAAG;AACzD,UAAI,WAAW;AACb,sBAAc,UAAU;AAAA,MAC1B;AAAA,IACF;AAKA,QAAI,CAAC,eAAe,mBAAmB,WAAW,GAAG;AACnD,aAAO;AAAA,QACL,MAAM;AAAA,QACN,WAAW;AAAA,UACT,KAAK,KAAK,MAAM;AAAA,UAChB,QAAQ;AAAA,QACV;AAAA,MACF;AAAA,IACF;AAIA,QAAI,KAAK,MAAM,IAAI,WAAW,OAAO,GAAG;AACtC,YAAM,YAAY,yBAAyB,KAAK,MAAM,GAAG;AACzD,UAAI,CAAC,WAAW;AACd,cAAM;AAAA,UACJ,sCAAsC,KAAK,MAAM,IAAI,UAAU,GAAG,EAAE,CAAC;AAAA,QACvE;AAAA,MACF;AACA,aAAO;AAAA,QACL,MAAM;AAAA,QACN,MAAM;AAAA,UACJ,UAAU,gCAAgC,UAAU,WAAW;AAAA,UAC/D,WAAW,KAAK,MAAM;AAAA;AAAA,QACxB;AAAA,MACF;AAAA,IACF;AAIA,UAAM;AAAA,MACJ,2HAA2H,WAAW;AAAA,IACxI;AAAA,EACF;AACA,QAAM;AAAA,IACJ,wEAAwE,KAAK,UAAU,IAAI,CAAC;AAAA,EAC9F;AACF;AAQO,SAAS,iBACd,UACA,oBAAuC,QACT;AAC9B,QAAM,cAA4C,CAAC;AACnD,aAAW,WAAW,UAAU;AAC9B,UAAM,MAAM,IAAI,sBAAQ,OAAO;AAC/B,UAAM,OAAO,aAAa,QAAQ,IAAI;AACtC,YAAQ,MAAM;AAAA,MACZ,KAAK;AACH,cAAM,UAAU,IAAI,QAAQ;AAAA,UAAI,CAAC,SAC/B,qBAAqB,MAAM,iBAAiB;AAAA,QAC9C;AAEA,cAAM,kBAAkB,QAAQ,KAAK,CAAC,SAAS,KAAK,SAAS,MAAM;AAGnE,YAAI,CAAC,iBAAiB;AACpB,kBAAQ,QAAQ,CAAC,SAAS;AACxB,gBAAI,KAAK,SAAS,QAAQ;AACxB,0BAAY,KAAK;AAAA,gBACf;AAAA,gBACA,SAAS,KAAK;AAAA,cAChB,CAAC;AAAA,YACH;AAAA,UACF,CAAC;AAAA,QACH,OAAO;AACL,sBAAY,KAAK;AAAA,YACf;AAAA,YACA;AAAA,UACF,CAAC;AAAA,QACH;AACA;AAAA,MACF,KAAK;AACH,oBAAY,KAAK;AAAA,UACf;AAAA,UACA,SAAS,IAAI;AAAA,QACf,CAAC;AACD;AAAA,MACF,KAAK,aAAa;AAChB,cAAM,YAA6C,IAAI,QACpD;AAAA,UACC,CACE,SAGG,QAAQ,KAAK,WAAW;AAAA,QAC/B,EACC,IAAI,CAAC,UAAU;AAAA,UACd,IAAI,KAAK,YAAY,OAAO;AAAA,UAC5B,MAAM;AAAA,UACN,UAAU;AAAA,YACR,MAAM,KAAK,YAAY;AAAA,YACvB,WAAW,KAAK,UAAU,KAAK,YAAY,KAAK;AAAA,UAClD;AAAA,QACF,EAAE;AACJ,YAAI,UAAU,SAAS,GAAG;AACxB,sBAAY,KAAK;AAAA,YACf;AAAA,YACA,YAAY;AAAA,UACd,CAAC;AAAA,QACH,OAAO;AACL,sBAAY,KAAK;AAAA,YACf;AAAA,YACA,SAAS,IAAI;AAAA,UACf,CAAC;AAAA,QACH;AACA;AAAA,MACF;AAAA,MACA,KAAK,QAAQ;AACX,cAAM,oBAAoB,IAAI,kBAAkB;AAChD,0BAAkB,IAAI,CAAC,SAAS;AAC9B,sBAAY,KAAK;AAAA,YACf;AAAA,YACA,cAAc,KAAK,aAAa,OAAO;AAAA,YACvC,SACE,OAAO,KAAK,aAAa,WAAW,WAChC,KAAK,aAAa,SAClB,KAAK,UAAU,KAAK,aAAa,MAAM;AAAA,UAC/C,CAAC;AAAA,QACH,CAAC;AACD;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAEA,MAAM,kBAIF;AAAA,EACF,QAAQ;AAAA,EACR,MAAM;AAAA,EACN,YAAY;AAAA,EACZ,gBAAgB;AAClB;AAOO,SAAS,mBACd,UAGA,QACiB;AACjB,MAAI,CAAC,SAAS,UAAU;AACtB,UAAM;AAAA,MACJ;AAAA,IACF;AAAA,EACF;AACA,QAAM,IAAI,SAAS;AAGnB,MAAI,OAAO,kBAAkB,cAAc;AACzC,WAAO;AAAA,MACL,aAAa;AAAA,QACX,MAAM,EAAE;AAAA,QACR,KAAK,SAAS;AAAA,QACd,OAAO,EAAE,YAAY,KAAK,MAAM,EAAE,SAAS,IAAI,EAAE;AAAA,MACnD;AAAA,IACF;AAAA,EACF,OAAO;AACL,WAAO;AAAA,MACL,aAAa;AAAA,QACX,MAAM,EAAE;AAAA,QACR,KAAK,SAAS;AAAA,QACd,OAAO;AAAA,MACT;AAAA,IACF;AAAA,EACF;AACF;AAQO,SAAS,iBACd,QACA,WAAW,OACW;AACtB,QAAM,mBAAmB,OAAO,QAAQ,YAAY;AAAA,IAAI,CAAC,aACvD,mBAAmB,UAAU,MAAM;AAAA,EACrC;AAGA,MAAI,UAAkB,CAAC;AAEvB,MAAI,oBAAoB,iBAAiB,SAAS,GAAG;AACnD,cAAU;AAAA,EACZ,OAAO;AAEL,QACE,uBAAuB,OAAO,WAC9B,OAAO,QAAQ,mBACf;AACA,cAAQ,KAAK,EAAE,WAAW,OAAO,QAAQ,kBAA4B,CAAC;AAAA,IACxE;AAGA,QAAI,OAAO,QAAQ,SAAS;AAC1B,cAAQ;AAAA,QACN,WACI,EAAE,MAAM,KAAK,MAAM,OAAO,QAAQ,OAAQ,EAAE,IAC5C,EAAE,MAAM,OAAO,QAAQ,QAAS;AAAA,MACtC;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AAAA,IACL,cAAc,gBAAgB,OAAO,aAAa,KAAK;AAAA,IACvD,SAAS;AAAA,MACP,MAAM;AAAA,MACN;AAAA,IACF;AAAA,EACF;AACF;AASO,SAAS,sBACd,QACA,WAAW,OACW;AACtB,QAAM,mBAAmB,OAAO,MAAM,YAAY;AAAA,IAAI,CAAC,aACrD,mBAAmB,UAAU,MAAM;AAAA,EACrC;AAGA,MAAI,UAAkB,CAAC;AAEvB,MAAI,oBAAoB,iBAAiB,SAAS,GAAG;AACnD,cAAU;AAAA,EACZ,OAAO;AAEL,QAAI,uBAAuB,OAAO,SAAS,OAAO,MAAM,mBAAmB;AACzE,cAAQ,KAAK,EAAE,WAAW,OAAO,MAAM,kBAA4B,CAAC;AAAA,IACtE;AAGA,QAAI,OAAO,MAAM,SAAS;AACxB,cAAQ;AAAA,QACN,WACI,EAAE,MAAM,KAAK,MAAM,OAAO,MAAM,OAAQ,EAAE,IAC1C,EAAE,MAAM,OAAO,MAAM,QAAS;AAAA,MACpC;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AAAA,IACL,cAAc,OAAO,gBACjB,gBAAgB,OAAO,aAAa,KAAK,UACzC;AAAA,IACJ,SAAS;AAAA,MACP,MAAM;AAAA,MACN;AAAA,IACF;AAAA,EACF;AACF;AASO,SAAS,oBACd,WACA,SACA,gBACA;AACA,QAAM,WAAW;AAAA,IACf,QAAQ;AAAA,IACR,QAAQ,QAAQ;AAAA,EAClB;AACA,QAAM;AAAA,IACJ;AAAA,IACA;AAAA;AAAA,IACA;AAAA;AAAA,IACA,MAAM;AAAA,IACN,kBAAkB;AAAA,IAClB,UAAU;AAAA,IACV,iBAAiB;AAAA,IACjB,aAAa;AAAA,IACb,eAAe;AAAA,IACf,SAAS;AAAA,IACT,OAAO;AAAA,IACP;AAAA,IACA,GAAG;AAAA,EACL,IAAI,QAAQ,UAAU,CAAC;AAEvB,QAAM,QAA8B,QAAQ,OAAO,IAAI,YAAY,KAAK,CAAC;AACzE,MAAI,iBAAiB;AACnB,UAAM,KAAK,GAAI,eAAyB;AAAA,EAC1C;AACA,MAAI,OAAO;AAAA,IACT,OAAO,gBAAgB;AAAA,IACvB;AAAA,IACA,OAAO,MAAM,SAAS,IAAI,QAAQ;AAAA,IAClC;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACA,MAAI,gBAAgB;AAGlB,mBAAe,SAAS,IAAI;AAAA,EAC9B,OAAO;AACL,WAAO,EAAE,GAAG,MAAM,GAAG,aAAa;AAAA,EACpC;AACA,QAAM,kBAAkB,QAAQ,QAAQ;AACxC,MAAI,oBAAoB,QAAQ;AAC9B,QAAI,QAAQ,QAAQ,QAAQ;AAC1B,WAAK,kBAAkB;AAAA,QACrB,MAAM;AAAA,QACN,aAAa;AAAA,UACX,MAAM;AAAA,UACN,QAAQ,QAAQ,OAAQ;AAAA,QAC1B;AAAA,MACF;AAAA,IACF,OAAO;AACL,WAAK,kBAAkB;AAAA,QACrB,MAAM;AAAA,MACR;AAAA,IACF;AAAA,EACF,WAAW,oBAAoB,QAAQ;AACrC,SAAK,kBAAkB;AAAA,MACrB,MAAM;AAAA,IACR;AAAA,EACF;AACA,aAAW,OAAO,MAAM;AACtB,QAAI,CAAC,KAAK,GAAG,KAAM,MAAM,QAAQ,KAAK,GAAG,CAAC,KAAK,CAAC,KAAK,GAAG,EAAE;AACxD,aAAO,KAAK,GAAG;AAAA,EACnB;AACA,SAAO;AACT;AASO,SAAS,kBACd,MACA,eACA,gBACA,eACA;AACA,SAAO,OACL,SACA,YAKkC;AAClC,UAAM,aAAS;AAAA,MACb;AAAA,MACA;AAAA,MACA;AAAA,IACF;AACA,QAAI;AACF,UAAI;AACJ,YAAM,OAAO,oBAAoB,MAAM,SAAS,cAAc;AAC9D,UAAI,SAAS,oBAAoB;AAC/B,cAAM,SAAS,OAAO,KAAK,KAAK,YAAY;AAAA,UAC1C;AAAA,YACE,GAAG;AAAA,YACH,QAAQ;AAAA,YACR,gBAAgB;AAAA,cACd,eAAe;AAAA,YACjB;AAAA,UACF;AAAA,UACA,EAAE,QAAQ,SAAS,YAAY;AAAA,QACjC;AACA,yBAAiB,SAAS,QAAQ;AAChC,gBAAM,SAAS,QAAQ,CAACA,WAAU;AAChC,kBAAM,IAAI,sBAAsBA,MAAK;AACrC,qBAAS,UAAW;AAAA,cAClB,OAAOA,OAAM;AAAA,cACb,SAAS,EAAE,SAAS,WAAW,CAAC;AAAA,YAClC,CAAC;AAAA,UACH,CAAC;AAAA,QACH;AACA,mBAAW,MAAM,OAAO,oBAAoB;AAAA,MAC9C,OAAO;AACL,mBAAW,MAAM,OAAO,KAAK,YAAY,OAAO,MAAM;AAAA,UACpD,QAAQ,SAAS;AAAA,QACnB,CAAC;AAAA,MACH;AACA,YAAM,mBAAyC;AAAA,QAC7C,OAAO;AAAA,UACL,aAAa,SAAS,OAAO;AAAA,UAC7B,cAAc,SAAS,OAAO;AAAA,UAC9B,aAAa,SAAS,OAAO;AAAA,QAC/B;AAAA,QACA,KAAK;AAAA,MACP;AACA,UAAI,SAAS,QAAQ,WAAW,GAAG;AACjC,eAAO;AAAA,MACT,OAAO;AACL,cAAM,SAAS,SAAS,QAAQ,CAAC;AACjC,eAAO;AAAA,UACL,GAAG,iBAAiB,QAAQ,QAAQ,QAAQ,WAAW,MAAM;AAAA,UAC7D,GAAG;AAAA,QACL;AAAA,MACF;AAAA,IACF,SAAS,GAAG;AACV,UAAI,aAAa,wBAAU;AACzB,YAAI,SAAqB;AACzB,gBAAQ,EAAE,QAAQ;AAAA,UAChB,KAAK;AACH,qBAAS;AACT;AAAA,UACF,KAAK;AACH,qBAAS;AACT;AAAA,UACF,KAAK;AACH,qBAAS;AACT;AAAA,UACF,KAAK;AACH,qBAAS;AACT;AAAA,UACF,KAAK;AACH,qBAAS;AACT;AAAA,UACF,KAAK;AACH,qBAAS;AACT;AAAA,QACJ;AACA,cAAM,mBACJ,EAAE,SAAS,MAAM,aAAa,KAC7B,EAAE,UAAkB,aAAa;AACpC,cAAM,eAAe,mBACjB,kBAAkB,gBAAgB,IAClC;AACJ,cAAM,mBACJ,iBAAiB,SAAY,EAAE,aAAa,IAAI;AAClD,cAAM,IAAI,0BAAY;AAAA,UACpB;AAAA,UACA,SAAS,EAAE;AAAA,UACX;AAAA,QACF,CAAC;AAAA,MACH;AACA,YAAM;AAAA,IACR;AAAA,EACF;AACF;AAkBO,SAAS,wBAEd,QAMc;AACd,QAAM,EAAE,MAAM,QAAQ,eAAe,UAAAC,WAAU,eAAe,IAAI;AAClE,QAAM,gBAAY,0BAAY,MAAM,eAAe,IAAI;AACvD,QAAM,aACJA,WAAU,QAAQ,GAAG,eAAe,QAAQ,YAAY,IAAI,SAAS;AAEvE,aAAO;AAAA,IACL;AAAA,MACE,MAAM;AAAA,MACN,GAAGA,WAAU;AAAA,MACb,cAAcA,WAAU;AAAA,IAC1B;AAAA,IACA,kBAAkB,WAAW,QAAQ,gBAAgB,aAAa;AAAA,EACpE;AACF;AAEA,MAAM,qBAAgC;AAAA,EACpC,UAAU;AAAA,IACR,WAAW;AAAA,IACX,OAAO;AAAA,IACP,OAAO;AAAA,IACP,YAAY;AAAA,IACZ,YAAY;AAAA,EACd;AACF;AAGO,SAAS,kBAEd,QAMgC;AAChC,QAAM;AAAA,IACJ;AAAA,IACA,OAAO;AAAA,IACP;AAAA,IACA,SAAS;AAAA,IACT;AAAA,EACF,IAAI;AACJ,aAAO,wBAAS;AAAA,IACd;AAAA,IACA,cAAc,gBAAiB;AAAA,IAC/B;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AACH;","names":["chunk","modelRef"]}
package/lib/model.mjs CHANGED
@@ -8,6 +8,14 @@ import {
8
8
  import { model } from "genkit/plugin";
9
9
  import { APIError } from "openai";
10
10
  import { maybeCreateRequestScopedOpenAIClient, toModelName } from "./utils.js";
11
+ function parseRetryAfterMs(value) {
12
+ if (!value || !value.trim()) return void 0;
13
+ const seconds = Number(value);
14
+ if (!isNaN(seconds) && seconds >= 0) return seconds * 1e3;
15
+ const date = new Date(value);
16
+ if (!isNaN(date.getTime())) return Math.max(0, date.getTime() - Date.now());
17
+ return void 0;
18
+ }
11
19
  const VisualDetailLevelSchema = z.enum(["auto", "low", "high"]).optional();
12
20
  const ChatCompletionCommonConfigSchema = GenerationCommonConfigSchema.extend({
13
21
  temperature: z.number().min(0).max(2).optional(),
@@ -216,7 +224,7 @@ function fromOpenAIChoice(choice, jsonMode = false) {
216
224
  (toolCall) => fromOpenAIToolCall(toolCall, choice)
217
225
  );
218
226
  let content = [];
219
- if (toolRequestParts) {
227
+ if (toolRequestParts && toolRequestParts.length > 0) {
220
228
  content = toolRequestParts;
221
229
  } else {
222
230
  if ("reasoning_content" in choice.message && choice.message.reasoning_content) {
@@ -241,7 +249,7 @@ function fromOpenAIChunkChoice(choice, jsonMode = false) {
241
249
  (toolCall) => fromOpenAIToolCall(toolCall, choice)
242
250
  );
243
251
  let content = [];
244
- if (toolRequestParts) {
252
+ if (toolRequestParts && toolRequestParts.length > 0) {
245
253
  content = toolRequestParts;
246
254
  } else {
247
255
  if ("reasoning_content" in choice.delta && choice.delta.reasoning_content) {
@@ -406,9 +414,13 @@ function openAIModelRunner(name, defaultClient, requestBuilder, pluginOptions) {
406
414
  status = "UNAVAILABLE";
407
415
  break;
408
416
  }
417
+ const retryAfterHeader = e.headers?.get?.("retry-after") ?? e.headers?.["retry-after"];
418
+ const retryAfterMs = retryAfterHeader ? parseRetryAfterMs(retryAfterHeader) : void 0;
419
+ const responseMetadata = retryAfterMs !== void 0 ? { retryAfterMs } : void 0;
409
420
  throw new GenkitError({
410
421
  status,
411
- message: e.message
422
+ message: e.message,
423
+ responseMetadata
412
424
  });
413
425
  }
414
426
  throw e;
package/lib/model.mjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/model.ts"],"sourcesContent":["/**\n * Copyright 2024 The Fire Company\n * Copyright 2024 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type {\n GenerateRequest,\n GenerateResponseChunkData,\n GenerateResponseData,\n MessageData,\n ModelReference,\n Part,\n Role,\n StreamingCallback,\n ToolRequestPart,\n} from 'genkit';\nimport {\n GenerationCommonConfigSchema,\n GenkitError,\n Message,\n StatusName,\n modelRef,\n z,\n} from 'genkit';\nimport type { ModelAction, ModelInfo, ToolDefinition } from 'genkit/model';\nimport { model } from 'genkit/plugin';\nimport OpenAI, { APIError } from 'openai';\nimport type {\n ChatCompletion,\n ChatCompletionChunk,\n ChatCompletionContentPart,\n ChatCompletionCreateParams,\n ChatCompletionCreateParamsNonStreaming,\n ChatCompletionMessageParam,\n ChatCompletionMessageToolCall,\n ChatCompletionRole,\n ChatCompletionTool,\n CompletionChoice,\n} from 'openai/resources/index.mjs';\nimport { PluginOptions } from './index.js';\nimport { maybeCreateRequestScopedOpenAIClient, toModelName } from './utils.js';\n\nconst VisualDetailLevelSchema = z.enum(['auto', 'low', 'high']).optional();\n\ntype VisualDetailLevel = z.infer<typeof VisualDetailLevelSchema>;\n\nexport type ModelRequestBuilder = (\n req: GenerateRequest,\n params: ChatCompletionCreateParams\n) => void;\n\nexport const ChatCompletionCommonConfigSchema =\n GenerationCommonConfigSchema.extend({\n temperature: z.number().min(0).max(2).optional(),\n frequencyPenalty: z.number().min(-2).max(2).optional(),\n logProbs: z.boolean().optional(),\n presencePenalty: z.number().min(-2).max(2).optional(),\n topLogProbs: z.number().int().min(0).max(20).optional(),\n });\n\nexport function toOpenAIRole(role: Role): ChatCompletionRole {\n switch (role) {\n case 'user':\n return 'user';\n case 'model':\n return 'assistant';\n case 'system':\n return 'system';\n case 'tool':\n return 'tool';\n default:\n throw new Error(`role ${role} doesn't map to an OpenAI role.`);\n }\n}\n\n/**\n * Converts a Genkit ToolDefinition to an OpenAI ChatCompletionTool object.\n * @param tool The Genkit ToolDefinition to convert.\n * @returns The converted OpenAI ChatCompletionTool object.\n */\nexport function toOpenAITool(tool: ToolDefinition): ChatCompletionTool {\n return {\n type: 'function',\n function: {\n name: tool.name,\n parameters: tool.inputSchema !== null ? tool.inputSchema : undefined,\n },\n };\n}\n\n/**\n * Checks if a content type is an image type.\n * @param contentType The content type to check.\n * @returns True if the content type is an image type.\n */\nfunction isImageContentType(contentType?: string): boolean {\n if (!contentType) return false;\n return contentType.startsWith('image/');\n}\n\n/**\n * Extracts the base64 data and content type from a data URL.\n * @param url The data URL to parse.\n * @returns The base64 data and content type, or null if invalid.\n */\nfunction extractDataFromBase64Url(url: string): {\n data: string;\n contentType: string;\n} | null {\n const match = url.match(/^data:([^;]+);base64,(.+)$/);\n return (\n match && {\n contentType: match[1],\n data: match[2],\n }\n );\n}\n\n/**\n * Map of content types to file extensions.\n */\nconst FILE_EXTENSIONS: Record<string, string> = {\n 'application/pdf': 'pdf',\n 'application/msword': 'doc',\n 'application/vnd.openxmlformats-officedocument.wordprocessingml.document':\n 'docx',\n 'text/plain': 'txt',\n 'text/csv': 'csv',\n};\n\n/**\n * Generates a filename from a content type.\n * @param contentType The content type.\n * @returns A filename with appropriate extension.\n */\nfunction generateFilenameFromContentType(contentType: string): string {\n const ext = FILE_EXTENSIONS[contentType] || '';\n return ext ? `file.${ext}` : 'file';\n}\n\n/**\n * Converts a Genkit Part to the corresponding OpenAI ChatCompletionContentPart.\n * @param part The Genkit Part to convert.\n * @param visualDetailLevel The visual detail level to use for media parts.\n * @returns The corresponding OpenAI ChatCompletionContentPart.\n * @throws Error if the part contains unsupported fields for the current message role.\n */\nexport function toOpenAITextAndMedia(\n part: Part,\n visualDetailLevel: VisualDetailLevel\n): ChatCompletionContentPart {\n if (part.text) {\n return {\n type: 'text',\n text: part.text,\n };\n } else if (part.media) {\n // Determine the content type from the media part or data URL\n let contentType = part.media.contentType;\n if (!contentType && part.media.url.startsWith('data:')) {\n const extracted = extractDataFromBase64Url(part.media.url);\n if (extracted) {\n contentType = extracted.contentType;\n }\n }\n\n // Check if this is an image type\n // If no contentType is provided, preserve legacy behavior by treating the media\n // as an image URL (e.g. signed URLs or remote images without metadata)\n if (!contentType || isImageContentType(contentType)) {\n return {\n type: 'image_url',\n image_url: {\n url: part.media.url,\n detail: visualDetailLevel,\n },\n };\n }\n\n // For non-image types (like PDF), use the file type\n // OpenAI expects the full data URL (with data: prefix) in file_data\n if (part.media.url.startsWith('data:')) {\n const extracted = extractDataFromBase64Url(part.media.url);\n if (!extracted) {\n throw Error(\n `Invalid data URL format for media: ${part.media.url.substring(0, 50)}...`\n );\n }\n return {\n type: 'file',\n file: {\n filename: generateFilenameFromContentType(extracted.contentType),\n file_data: part.media.url, // Full data URL with prefix\n },\n } as ChatCompletionContentPart;\n }\n\n // If it's a remote URL with non-image content type, this is not supported\n // for chat completions according to OpenAI docs\n throw Error(\n `File URLs are not supported for chat completions. Only base64-encoded files and image URLs are supported. Content type: ${contentType}`\n );\n }\n throw Error(\n `Unsupported genkit part fields encountered for current message role: ${JSON.stringify(part)}.`\n );\n}\n\n/**\n * Converts a Genkit MessageData array to an OpenAI ChatCompletionMessageParam array.\n * @param messages The Genkit MessageData array to convert.\n * @param visualDetailLevel The visual detail level to use for media parts.\n * @returns The converted OpenAI ChatCompletionMessageParam array.\n */\nexport function toOpenAIMessages(\n messages: MessageData[],\n visualDetailLevel: VisualDetailLevel = 'auto'\n): ChatCompletionMessageParam[] {\n const apiMessages: ChatCompletionMessageParam[] = [];\n for (const message of messages) {\n const msg = new Message(message);\n const role = toOpenAIRole(message.role);\n switch (role) {\n case 'user':\n const content = msg.content.map((part) =>\n toOpenAITextAndMedia(part, visualDetailLevel)\n );\n // Check if we have only text content\n const onlyTextContent = content.some((item) => item.type !== 'text');\n\n // If all items are strings, just add them as text\n if (!onlyTextContent) {\n content.forEach((item) => {\n if (item.type === 'text') {\n apiMessages.push({\n role: role,\n content: item.text,\n });\n }\n });\n } else {\n apiMessages.push({\n role: role,\n content: content,\n });\n }\n break;\n case 'system':\n apiMessages.push({\n role: role,\n content: msg.text,\n });\n break;\n case 'assistant': {\n const toolCalls: ChatCompletionMessageToolCall[] = msg.content\n .filter(\n (\n part\n ): part is Part & {\n toolRequest: NonNullable<Part['toolRequest']>;\n } => Boolean(part.toolRequest)\n )\n .map((part) => ({\n id: part.toolRequest.ref ?? '',\n type: 'function',\n function: {\n name: part.toolRequest.name,\n arguments: JSON.stringify(part.toolRequest.input),\n },\n }));\n if (toolCalls.length > 0) {\n apiMessages.push({\n role: role,\n tool_calls: toolCalls,\n });\n } else {\n apiMessages.push({\n role: role,\n content: msg.text,\n });\n }\n break;\n }\n case 'tool': {\n const toolResponseParts = msg.toolResponseParts();\n toolResponseParts.map((part) => {\n apiMessages.push({\n role: role,\n tool_call_id: part.toolResponse.ref ?? '',\n content:\n typeof part.toolResponse.output === 'string'\n ? part.toolResponse.output\n : JSON.stringify(part.toolResponse.output),\n });\n });\n break;\n }\n }\n }\n return apiMessages;\n}\n\nconst finishReasonMap: Record<\n // OpenAI Node SDK doesn't support tool_call in the enum, but it is returned from the API\n CompletionChoice['finish_reason'] | 'tool_calls',\n GenerateResponseData['finishReason']\n> = {\n length: 'length',\n stop: 'stop',\n tool_calls: 'stop',\n content_filter: 'blocked',\n};\n\n/**\n * Converts an OpenAI tool call to a Genkit ToolRequestPart.\n * @param toolCall The OpenAI tool call to convert.\n * @returns The converted Genkit ToolRequestPart.\n */\nexport function fromOpenAIToolCall(\n toolCall:\n | ChatCompletionMessageToolCall\n | ChatCompletionChunk.Choice.Delta.ToolCall,\n choice: ChatCompletion.Choice | ChatCompletionChunk.Choice\n): ToolRequestPart {\n if (!toolCall.function) {\n throw Error(\n `Unexpected openAI chunk choice. tool_calls was provided but one or more tool_calls is missing.`\n );\n }\n const f = toolCall.function;\n\n // Only parse arguments when it is a JSON object and the finish reason is tool_calls to avoid parsing errors\n if (choice.finish_reason === 'tool_calls') {\n return {\n toolRequest: {\n name: f.name!,\n ref: toolCall.id,\n input: f.arguments ? JSON.parse(f.arguments) : f.arguments,\n },\n };\n } else {\n return {\n toolRequest: {\n name: f.name!,\n ref: toolCall.id,\n input: '',\n },\n };\n }\n}\n\n/**\n * Converts an OpenAI message event to a Genkit GenerateResponseData object.\n * @param choice The OpenAI message event to convert.\n * @param jsonMode Whether the event is a JSON response.\n * @returns The converted Genkit GenerateResponseData object.\n */\nexport function fromOpenAIChoice(\n choice: ChatCompletion.Choice,\n jsonMode = false\n): GenerateResponseData {\n const toolRequestParts = choice.message.tool_calls?.map((toolCall) =>\n fromOpenAIToolCall(toolCall, choice)\n );\n\n // Build content array based on what's present in the message\n let content: Part[] = [];\n\n if (toolRequestParts) {\n content = toolRequestParts as ToolRequestPart[];\n } else {\n // Handle reasoning_content if present\n if (\n 'reasoning_content' in choice.message &&\n choice.message.reasoning_content\n ) {\n content.push({ reasoning: choice.message.reasoning_content as string });\n }\n\n // Handle regular content if present\n if (choice.message.content) {\n content.push(\n jsonMode\n ? { data: JSON.parse(choice.message.content!) }\n : { text: choice.message.content! }\n );\n }\n }\n\n return {\n finishReason: finishReasonMap[choice.finish_reason] || 'other',\n message: {\n role: 'model',\n content,\n },\n };\n}\n\n/**\n * Converts an OpenAI message stream event to a Genkit GenerateResponseData\n * object.\n * @param choice The OpenAI message stream event to convert.\n * @param jsonMode Whether the event is a JSON response.\n * @returns The converted Genkit GenerateResponseData object.\n */\nexport function fromOpenAIChunkChoice(\n choice: ChatCompletionChunk.Choice,\n jsonMode = false\n): GenerateResponseData {\n const toolRequestParts = choice.delta.tool_calls?.map((toolCall) =>\n fromOpenAIToolCall(toolCall, choice)\n );\n\n // Build content array based on what's present in the delta\n let content: Part[] = [];\n\n if (toolRequestParts) {\n content = toolRequestParts as ToolRequestPart[];\n } else {\n // Handle reasoning_content if present\n if ('reasoning_content' in choice.delta && choice.delta.reasoning_content) {\n content.push({ reasoning: choice.delta.reasoning_content as string });\n }\n\n // Handle regular content if present\n if (choice.delta.content) {\n content.push(\n jsonMode\n ? { data: JSON.parse(choice.delta.content!) }\n : { text: choice.delta.content! }\n );\n }\n }\n\n return {\n finishReason: choice.finish_reason\n ? finishReasonMap[choice.finish_reason] || 'other'\n : 'unknown',\n message: {\n role: 'model',\n content,\n },\n };\n}\n\n/**\n * Converts an OpenAI request to an OpenAI API request body.\n * @param modelName The name of the OpenAI model to use.\n * @param request The Genkit GenerateRequest to convert.\n * @returns The converted OpenAI API request body.\n * @throws An error if the specified model is not supported or if an unsupported output format is requested.\n */\nexport function toOpenAIRequestBody(\n modelName: string,\n request: GenerateRequest,\n requestBuilder?: ModelRequestBuilder\n) {\n const messages = toOpenAIMessages(\n request.messages,\n request.config?.visualDetailLevel\n );\n const {\n temperature,\n maxOutputTokens, // unused\n topK, // unused\n topP: top_p,\n frequencyPenalty: frequency_penalty,\n logProbs: logprobs,\n presencePenalty: presence_penalty,\n topLogProbs: top_logprobs,\n stopSequences: stop,\n version: modelVersion,\n tools: toolsFromConfig,\n apiKey,\n ...restOfConfig\n } = request.config ?? {};\n\n const tools: ChatCompletionTool[] = request.tools?.map(toOpenAITool) ?? [];\n if (toolsFromConfig) {\n tools.push(...(toolsFromConfig as any[]));\n }\n let body = {\n model: modelVersion ?? modelName,\n messages,\n tools: tools.length > 0 ? tools : undefined,\n temperature,\n top_p,\n stop,\n frequency_penalty,\n presence_penalty,\n top_logprobs,\n logprobs,\n } as ChatCompletionCreateParamsNonStreaming;\n if (requestBuilder) {\n // If override provided, apply the override to the OpenAI request.\n // User must control passthrough config too.\n requestBuilder(request, body);\n } else {\n body = { ...body, ...restOfConfig }; // passthrough for other config\n }\n const response_format = request.output?.format;\n if (response_format === 'json') {\n if (request.output?.schema) {\n body.response_format = {\n type: 'json_schema',\n json_schema: {\n name: 'output',\n schema: request.output!.schema,\n },\n };\n } else {\n body.response_format = {\n type: 'json_object',\n };\n }\n } else if (response_format === 'text') {\n body.response_format = {\n type: 'text',\n };\n }\n for (const key in body) {\n if (!body[key] || (Array.isArray(body[key]) && !body[key].length))\n delete body[key];\n }\n return body;\n}\n\n/**\n * Creates the runner used by Genkit to interact with an OpenAI compatible\n * model.\n * @param name The name of the GPT model.\n * @param client The OpenAI client instance.\n * @returns The runner that Genkit will call when the model is invoked.\n */\nexport function openAIModelRunner(\n name: string,\n defaultClient: OpenAI,\n requestBuilder?: ModelRequestBuilder,\n pluginOptions?: Omit<PluginOptions, 'apiKey'>\n) {\n return async (\n request: GenerateRequest,\n options?: {\n streamingRequested?: boolean;\n sendChunk?: StreamingCallback<GenerateResponseChunkData>;\n abortSignal?: AbortSignal;\n }\n ): Promise<GenerateResponseData> => {\n const client = maybeCreateRequestScopedOpenAIClient(\n pluginOptions,\n request,\n defaultClient\n );\n try {\n let response: ChatCompletion;\n const body = toOpenAIRequestBody(name, request, requestBuilder);\n if (options?.streamingRequested) {\n const stream = client.beta.chat.completions.stream(\n {\n ...body,\n stream: true,\n stream_options: {\n include_usage: true,\n },\n },\n { signal: options?.abortSignal }\n );\n for await (const chunk of stream) {\n chunk.choices?.forEach((chunk) => {\n const c = fromOpenAIChunkChoice(chunk);\n options?.sendChunk!({\n index: chunk.index,\n content: c.message?.content ?? [],\n });\n });\n }\n response = await stream.finalChatCompletion();\n } else {\n response = await client.chat.completions.create(body, {\n signal: options?.abortSignal,\n });\n }\n const standardResponse: GenerateResponseData = {\n usage: {\n inputTokens: response.usage?.prompt_tokens,\n outputTokens: response.usage?.completion_tokens,\n totalTokens: response.usage?.total_tokens,\n },\n raw: response,\n };\n if (response.choices.length === 0) {\n return standardResponse;\n } else {\n const choice = response.choices[0];\n return {\n ...fromOpenAIChoice(choice, request.output?.format === 'json'),\n ...standardResponse,\n };\n }\n } catch (e) {\n if (e instanceof APIError) {\n let status: StatusName = 'UNKNOWN';\n switch (e.status) {\n case 429:\n status = 'RESOURCE_EXHAUSTED';\n break;\n case 401:\n status = 'PERMISSION_DENIED';\n break;\n case 403:\n status = 'UNAUTHENTICATED';\n break;\n case 400:\n status = 'INVALID_ARGUMENT';\n break;\n case 500:\n status = 'INTERNAL';\n break;\n case 503:\n status = 'UNAVAILABLE';\n break;\n }\n throw new GenkitError({\n status,\n message: e.message,\n });\n }\n throw e;\n }\n };\n}\n\n/**\n * Method to define a new Genkit Model that is compatible with Open AI\n * Chat Completions API. \n *\n * These models are to be used to chat with a large language model.\n *\n * @param params An object containing parameters for defining the OpenAI\n * Chat model.\n * @param params.ai The Genkit AI instance.\n * @param params.name The name of the model.\n * @param params.client The OpenAI client instance.\n * @param params.modelRef Optional reference to the model's configuration and\n * custom options.\n\n * @returns the created {@link ModelAction}\n */\nexport function defineCompatOpenAIModel<\n CustomOptions extends z.ZodTypeAny = z.ZodTypeAny,\n>(params: {\n name: string;\n client: OpenAI;\n modelRef?: ModelReference<CustomOptions>;\n requestBuilder?: ModelRequestBuilder;\n pluginOptions?: PluginOptions;\n}): ModelAction {\n const { name, client, pluginOptions, modelRef, requestBuilder } = params;\n const modelName = toModelName(name, pluginOptions?.name);\n const actionName =\n modelRef?.name ?? `${pluginOptions?.name ?? 'compat-oai'}/${modelName}`;\n\n return model(\n {\n name: actionName,\n ...modelRef?.info,\n configSchema: modelRef?.configSchema,\n },\n openAIModelRunner(modelName, client, requestBuilder, pluginOptions)\n );\n}\n\nconst GENERIC_MODEL_INFO: ModelInfo = {\n supports: {\n multiturn: true,\n media: true,\n tools: true,\n toolChoice: true,\n systemRole: true,\n },\n};\n\n/** ModelRef helper, with reasonable defaults for OpenAI-compatible providers */\nexport function compatOaiModelRef<\n CustomOptions extends z.ZodTypeAny = z.ZodTypeAny,\n>(params: {\n name: string;\n info?: ModelInfo;\n configSchema?: CustomOptions;\n config?: any;\n namespace?: string;\n}): ModelReference<CustomOptions> {\n const {\n name,\n info = GENERIC_MODEL_INFO,\n configSchema,\n config = undefined,\n namespace,\n } = params;\n return modelRef({\n name,\n configSchema: configSchema || (ChatCompletionCommonConfigSchema as any),\n info: info,\n config,\n namespace,\n });\n}\n"],"mappings":"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","names":["chunk","modelRef"]}
1
+ {"version":3,"sources":["../src/model.ts"],"sourcesContent":["/**\n * Copyright 2024 The Fire Company\n * Copyright 2024 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type {\n GenerateRequest,\n GenerateResponseChunkData,\n GenerateResponseData,\n MessageData,\n ModelReference,\n Part,\n Role,\n StreamingCallback,\n ToolRequestPart,\n} from 'genkit';\nimport {\n GenerationCommonConfigSchema,\n GenkitError,\n Message,\n StatusName,\n modelRef,\n z,\n type ErrorResponseMetadata,\n} from 'genkit';\nimport type { ModelAction, ModelInfo, ToolDefinition } from 'genkit/model';\nimport { model } from 'genkit/plugin';\nimport OpenAI, { APIError } from 'openai';\nimport type {\n ChatCompletion,\n ChatCompletionChunk,\n ChatCompletionContentPart,\n ChatCompletionCreateParams,\n ChatCompletionCreateParamsNonStreaming,\n ChatCompletionMessageParam,\n ChatCompletionMessageToolCall,\n ChatCompletionRole,\n ChatCompletionTool,\n CompletionChoice,\n} from 'openai/resources/index.mjs';\nimport { PluginOptions } from './index.js';\nimport { maybeCreateRequestScopedOpenAIClient, toModelName } from './utils.js';\n\n/**\n * Parses a `Retry-After` header value into milliseconds.\n * Supports delay-seconds and HTTP-date formats (RFC 7231 §7.1.3).\n */\nfunction parseRetryAfterMs(value: string): number | undefined {\n if (!value || !value.trim()) return undefined;\n const seconds = Number(value);\n if (!isNaN(seconds) && seconds >= 0) return seconds * 1000;\n const date = new Date(value);\n if (!isNaN(date.getTime())) return Math.max(0, date.getTime() - Date.now());\n return undefined;\n}\n\nconst VisualDetailLevelSchema = z.enum(['auto', 'low', 'high']).optional();\n\ntype VisualDetailLevel = z.infer<typeof VisualDetailLevelSchema>;\n\nexport type ModelRequestBuilder = (\n req: GenerateRequest,\n params: ChatCompletionCreateParams\n) => void;\n\nexport const ChatCompletionCommonConfigSchema =\n GenerationCommonConfigSchema.extend({\n temperature: z.number().min(0).max(2).optional(),\n frequencyPenalty: z.number().min(-2).max(2).optional(),\n logProbs: z.boolean().optional(),\n presencePenalty: z.number().min(-2).max(2).optional(),\n topLogProbs: z.number().int().min(0).max(20).optional(),\n });\n\nexport function toOpenAIRole(role: Role): ChatCompletionRole {\n switch (role) {\n case 'user':\n return 'user';\n case 'model':\n return 'assistant';\n case 'system':\n return 'system';\n case 'tool':\n return 'tool';\n default:\n throw new Error(`role ${role} doesn't map to an OpenAI role.`);\n }\n}\n\n/**\n * Converts a Genkit ToolDefinition to an OpenAI ChatCompletionTool object.\n * @param tool The Genkit ToolDefinition to convert.\n * @returns The converted OpenAI ChatCompletionTool object.\n */\nexport function toOpenAITool(tool: ToolDefinition): ChatCompletionTool {\n return {\n type: 'function',\n function: {\n name: tool.name,\n parameters: tool.inputSchema !== null ? tool.inputSchema : undefined,\n },\n };\n}\n\n/**\n * Checks if a content type is an image type.\n * @param contentType The content type to check.\n * @returns True if the content type is an image type.\n */\nfunction isImageContentType(contentType?: string): boolean {\n if (!contentType) return false;\n return contentType.startsWith('image/');\n}\n\n/**\n * Extracts the base64 data and content type from a data URL.\n * @param url The data URL to parse.\n * @returns The base64 data and content type, or null if invalid.\n */\nfunction extractDataFromBase64Url(url: string): {\n data: string;\n contentType: string;\n} | null {\n const match = url.match(/^data:([^;]+);base64,(.+)$/);\n return (\n match && {\n contentType: match[1],\n data: match[2],\n }\n );\n}\n\n/**\n * Map of content types to file extensions.\n */\nconst FILE_EXTENSIONS: Record<string, string> = {\n 'application/pdf': 'pdf',\n 'application/msword': 'doc',\n 'application/vnd.openxmlformats-officedocument.wordprocessingml.document':\n 'docx',\n 'text/plain': 'txt',\n 'text/csv': 'csv',\n};\n\n/**\n * Generates a filename from a content type.\n * @param contentType The content type.\n * @returns A filename with appropriate extension.\n */\nfunction generateFilenameFromContentType(contentType: string): string {\n const ext = FILE_EXTENSIONS[contentType] || '';\n return ext ? `file.${ext}` : 'file';\n}\n\n/**\n * Converts a Genkit Part to the corresponding OpenAI ChatCompletionContentPart.\n * @param part The Genkit Part to convert.\n * @param visualDetailLevel The visual detail level to use for media parts.\n * @returns The corresponding OpenAI ChatCompletionContentPart.\n * @throws Error if the part contains unsupported fields for the current message role.\n */\nexport function toOpenAITextAndMedia(\n part: Part,\n visualDetailLevel: VisualDetailLevel\n): ChatCompletionContentPart {\n if (part.text) {\n return {\n type: 'text',\n text: part.text,\n };\n } else if (part.media) {\n // Determine the content type from the media part or data URL\n let contentType = part.media.contentType;\n if (!contentType && part.media.url.startsWith('data:')) {\n const extracted = extractDataFromBase64Url(part.media.url);\n if (extracted) {\n contentType = extracted.contentType;\n }\n }\n\n // Check if this is an image type\n // If no contentType is provided, preserve legacy behavior by treating the media\n // as an image URL (e.g. signed URLs or remote images without metadata)\n if (!contentType || isImageContentType(contentType)) {\n return {\n type: 'image_url',\n image_url: {\n url: part.media.url,\n detail: visualDetailLevel,\n },\n };\n }\n\n // For non-image types (like PDF), use the file type\n // OpenAI expects the full data URL (with data: prefix) in file_data\n if (part.media.url.startsWith('data:')) {\n const extracted = extractDataFromBase64Url(part.media.url);\n if (!extracted) {\n throw Error(\n `Invalid data URL format for media: ${part.media.url.substring(0, 50)}...`\n );\n }\n return {\n type: 'file',\n file: {\n filename: generateFilenameFromContentType(extracted.contentType),\n file_data: part.media.url, // Full data URL with prefix\n },\n } as ChatCompletionContentPart;\n }\n\n // If it's a remote URL with non-image content type, this is not supported\n // for chat completions according to OpenAI docs\n throw Error(\n `File URLs are not supported for chat completions. Only base64-encoded files and image URLs are supported. Content type: ${contentType}`\n );\n }\n throw Error(\n `Unsupported genkit part fields encountered for current message role: ${JSON.stringify(part)}.`\n );\n}\n\n/**\n * Converts a Genkit MessageData array to an OpenAI ChatCompletionMessageParam array.\n * @param messages The Genkit MessageData array to convert.\n * @param visualDetailLevel The visual detail level to use for media parts.\n * @returns The converted OpenAI ChatCompletionMessageParam array.\n */\nexport function toOpenAIMessages(\n messages: MessageData[],\n visualDetailLevel: VisualDetailLevel = 'auto'\n): ChatCompletionMessageParam[] {\n const apiMessages: ChatCompletionMessageParam[] = [];\n for (const message of messages) {\n const msg = new Message(message);\n const role = toOpenAIRole(message.role);\n switch (role) {\n case 'user':\n const content = msg.content.map((part) =>\n toOpenAITextAndMedia(part, visualDetailLevel)\n );\n // Check if we have only text content\n const onlyTextContent = content.some((item) => item.type !== 'text');\n\n // If all items are strings, just add them as text\n if (!onlyTextContent) {\n content.forEach((item) => {\n if (item.type === 'text') {\n apiMessages.push({\n role: role,\n content: item.text,\n });\n }\n });\n } else {\n apiMessages.push({\n role: role,\n content: content,\n });\n }\n break;\n case 'system':\n apiMessages.push({\n role: role,\n content: msg.text,\n });\n break;\n case 'assistant': {\n const toolCalls: ChatCompletionMessageToolCall[] = msg.content\n .filter(\n (\n part\n ): part is Part & {\n toolRequest: NonNullable<Part['toolRequest']>;\n } => Boolean(part.toolRequest)\n )\n .map((part) => ({\n id: part.toolRequest.ref ?? '',\n type: 'function',\n function: {\n name: part.toolRequest.name,\n arguments: JSON.stringify(part.toolRequest.input),\n },\n }));\n if (toolCalls.length > 0) {\n apiMessages.push({\n role: role,\n tool_calls: toolCalls,\n });\n } else {\n apiMessages.push({\n role: role,\n content: msg.text,\n });\n }\n break;\n }\n case 'tool': {\n const toolResponseParts = msg.toolResponseParts();\n toolResponseParts.map((part) => {\n apiMessages.push({\n role: role,\n tool_call_id: part.toolResponse.ref ?? '',\n content:\n typeof part.toolResponse.output === 'string'\n ? part.toolResponse.output\n : JSON.stringify(part.toolResponse.output),\n });\n });\n break;\n }\n }\n }\n return apiMessages;\n}\n\nconst finishReasonMap: Record<\n // OpenAI Node SDK doesn't support tool_call in the enum, but it is returned from the API\n CompletionChoice['finish_reason'] | 'tool_calls',\n GenerateResponseData['finishReason']\n> = {\n length: 'length',\n stop: 'stop',\n tool_calls: 'stop',\n content_filter: 'blocked',\n};\n\n/**\n * Converts an OpenAI tool call to a Genkit ToolRequestPart.\n * @param toolCall The OpenAI tool call to convert.\n * @returns The converted Genkit ToolRequestPart.\n */\nexport function fromOpenAIToolCall(\n toolCall:\n | ChatCompletionMessageToolCall\n | ChatCompletionChunk.Choice.Delta.ToolCall,\n choice: ChatCompletion.Choice | ChatCompletionChunk.Choice\n): ToolRequestPart {\n if (!toolCall.function) {\n throw Error(\n `Unexpected openAI chunk choice. tool_calls was provided but one or more tool_calls is missing.`\n );\n }\n const f = toolCall.function;\n\n // Only parse arguments when it is a JSON object and the finish reason is tool_calls to avoid parsing errors\n if (choice.finish_reason === 'tool_calls') {\n return {\n toolRequest: {\n name: f.name!,\n ref: toolCall.id,\n input: f.arguments ? JSON.parse(f.arguments) : f.arguments,\n },\n };\n } else {\n return {\n toolRequest: {\n name: f.name!,\n ref: toolCall.id,\n input: '',\n },\n };\n }\n}\n\n/**\n * Converts an OpenAI message event to a Genkit GenerateResponseData object.\n * @param choice The OpenAI message event to convert.\n * @param jsonMode Whether the event is a JSON response.\n * @returns The converted Genkit GenerateResponseData object.\n */\nexport function fromOpenAIChoice(\n choice: ChatCompletion.Choice,\n jsonMode = false\n): GenerateResponseData {\n const toolRequestParts = choice.message.tool_calls?.map((toolCall) =>\n fromOpenAIToolCall(toolCall, choice)\n );\n\n // Build content array based on what's present in the message\n let content: Part[] = [];\n\n if (toolRequestParts && toolRequestParts.length > 0) {\n content = toolRequestParts as ToolRequestPart[];\n } else {\n // Handle reasoning_content if present\n if (\n 'reasoning_content' in choice.message &&\n choice.message.reasoning_content\n ) {\n content.push({ reasoning: choice.message.reasoning_content as string });\n }\n\n // Handle regular content if present\n if (choice.message.content) {\n content.push(\n jsonMode\n ? { data: JSON.parse(choice.message.content!) }\n : { text: choice.message.content! }\n );\n }\n }\n\n return {\n finishReason: finishReasonMap[choice.finish_reason] || 'other',\n message: {\n role: 'model',\n content,\n },\n };\n}\n\n/**\n * Converts an OpenAI message stream event to a Genkit GenerateResponseData\n * object.\n * @param choice The OpenAI message stream event to convert.\n * @param jsonMode Whether the event is a JSON response.\n * @returns The converted Genkit GenerateResponseData object.\n */\nexport function fromOpenAIChunkChoice(\n choice: ChatCompletionChunk.Choice,\n jsonMode = false\n): GenerateResponseData {\n const toolRequestParts = choice.delta.tool_calls?.map((toolCall) =>\n fromOpenAIToolCall(toolCall, choice)\n );\n\n // Build content array based on what's present in the delta\n let content: Part[] = [];\n\n if (toolRequestParts && toolRequestParts.length > 0) {\n content = toolRequestParts as ToolRequestPart[];\n } else {\n // Handle reasoning_content if present\n if ('reasoning_content' in choice.delta && choice.delta.reasoning_content) {\n content.push({ reasoning: choice.delta.reasoning_content as string });\n }\n\n // Handle regular content if present\n if (choice.delta.content) {\n content.push(\n jsonMode\n ? { data: JSON.parse(choice.delta.content!) }\n : { text: choice.delta.content! }\n );\n }\n }\n\n return {\n finishReason: choice.finish_reason\n ? finishReasonMap[choice.finish_reason] || 'other'\n : 'unknown',\n message: {\n role: 'model',\n content,\n },\n };\n}\n\n/**\n * Converts an OpenAI request to an OpenAI API request body.\n * @param modelName The name of the OpenAI model to use.\n * @param request The Genkit GenerateRequest to convert.\n * @returns The converted OpenAI API request body.\n * @throws An error if the specified model is not supported or if an unsupported output format is requested.\n */\nexport function toOpenAIRequestBody(\n modelName: string,\n request: GenerateRequest,\n requestBuilder?: ModelRequestBuilder\n) {\n const messages = toOpenAIMessages(\n request.messages,\n request.config?.visualDetailLevel\n );\n const {\n temperature,\n maxOutputTokens, // unused\n topK, // unused\n topP: top_p,\n frequencyPenalty: frequency_penalty,\n logProbs: logprobs,\n presencePenalty: presence_penalty,\n topLogProbs: top_logprobs,\n stopSequences: stop,\n version: modelVersion,\n tools: toolsFromConfig,\n apiKey,\n ...restOfConfig\n } = request.config ?? {};\n\n const tools: ChatCompletionTool[] = request.tools?.map(toOpenAITool) ?? [];\n if (toolsFromConfig) {\n tools.push(...(toolsFromConfig as any[]));\n }\n let body = {\n model: modelVersion ?? modelName,\n messages,\n tools: tools.length > 0 ? tools : undefined,\n temperature,\n top_p,\n stop,\n frequency_penalty,\n presence_penalty,\n top_logprobs,\n logprobs,\n } as ChatCompletionCreateParamsNonStreaming;\n if (requestBuilder) {\n // If override provided, apply the override to the OpenAI request.\n // User must control passthrough config too.\n requestBuilder(request, body);\n } else {\n body = { ...body, ...restOfConfig }; // passthrough for other config\n }\n const response_format = request.output?.format;\n if (response_format === 'json') {\n if (request.output?.schema) {\n body.response_format = {\n type: 'json_schema',\n json_schema: {\n name: 'output',\n schema: request.output!.schema,\n },\n };\n } else {\n body.response_format = {\n type: 'json_object',\n };\n }\n } else if (response_format === 'text') {\n body.response_format = {\n type: 'text',\n };\n }\n for (const key in body) {\n if (!body[key] || (Array.isArray(body[key]) && !body[key].length))\n delete body[key];\n }\n return body;\n}\n\n/**\n * Creates the runner used by Genkit to interact with an OpenAI compatible\n * model.\n * @param name The name of the GPT model.\n * @param client The OpenAI client instance.\n * @returns The runner that Genkit will call when the model is invoked.\n */\nexport function openAIModelRunner(\n name: string,\n defaultClient: OpenAI,\n requestBuilder?: ModelRequestBuilder,\n pluginOptions?: Omit<PluginOptions, 'apiKey'>\n) {\n return async (\n request: GenerateRequest,\n options?: {\n streamingRequested?: boolean;\n sendChunk?: StreamingCallback<GenerateResponseChunkData>;\n abortSignal?: AbortSignal;\n }\n ): Promise<GenerateResponseData> => {\n const client = maybeCreateRequestScopedOpenAIClient(\n pluginOptions,\n request,\n defaultClient\n );\n try {\n let response: ChatCompletion;\n const body = toOpenAIRequestBody(name, request, requestBuilder);\n if (options?.streamingRequested) {\n const stream = client.beta.chat.completions.stream(\n {\n ...body,\n stream: true,\n stream_options: {\n include_usage: true,\n },\n },\n { signal: options?.abortSignal }\n );\n for await (const chunk of stream) {\n chunk.choices?.forEach((chunk) => {\n const c = fromOpenAIChunkChoice(chunk);\n options?.sendChunk!({\n index: chunk.index,\n content: c.message?.content ?? [],\n });\n });\n }\n response = await stream.finalChatCompletion();\n } else {\n response = await client.chat.completions.create(body, {\n signal: options?.abortSignal,\n });\n }\n const standardResponse: GenerateResponseData = {\n usage: {\n inputTokens: response.usage?.prompt_tokens,\n outputTokens: response.usage?.completion_tokens,\n totalTokens: response.usage?.total_tokens,\n },\n raw: response,\n };\n if (response.choices.length === 0) {\n return standardResponse;\n } else {\n const choice = response.choices[0];\n return {\n ...fromOpenAIChoice(choice, request.output?.format === 'json'),\n ...standardResponse,\n };\n }\n } catch (e) {\n if (e instanceof APIError) {\n let status: StatusName = 'UNKNOWN';\n switch (e.status) {\n case 429:\n status = 'RESOURCE_EXHAUSTED';\n break;\n case 401:\n status = 'PERMISSION_DENIED';\n break;\n case 403:\n status = 'UNAUTHENTICATED';\n break;\n case 400:\n status = 'INVALID_ARGUMENT';\n break;\n case 500:\n status = 'INTERNAL';\n break;\n case 503:\n status = 'UNAVAILABLE';\n break;\n }\n const retryAfterHeader =\n e.headers?.get?.('retry-after') ??\n (e.headers as any)?.['retry-after'];\n const retryAfterMs = retryAfterHeader\n ? parseRetryAfterMs(retryAfterHeader)\n : undefined;\n const responseMetadata: ErrorResponseMetadata | undefined =\n retryAfterMs !== undefined ? { retryAfterMs } : undefined;\n throw new GenkitError({\n status,\n message: e.message,\n responseMetadata,\n });\n }\n throw e;\n }\n };\n}\n\n/**\n * Method to define a new Genkit Model that is compatible with Open AI\n * Chat Completions API.\n *\n * These models are to be used to chat with a large language model.\n *\n * @param params An object containing parameters for defining the OpenAI\n * Chat model.\n * @param params.ai The Genkit AI instance.\n * @param params.name The name of the model.\n * @param params.client The OpenAI client instance.\n * @param params.modelRef Optional reference to the model's configuration and\n * custom options.\n\n * @returns the created {@link ModelAction}\n */\nexport function defineCompatOpenAIModel<\n CustomOptions extends z.ZodTypeAny = z.ZodTypeAny,\n>(params: {\n name: string;\n client: OpenAI;\n modelRef?: ModelReference<CustomOptions>;\n requestBuilder?: ModelRequestBuilder;\n pluginOptions?: PluginOptions;\n}): ModelAction {\n const { name, client, pluginOptions, modelRef, requestBuilder } = params;\n const modelName = toModelName(name, pluginOptions?.name);\n const actionName =\n modelRef?.name ?? `${pluginOptions?.name ?? 'compat-oai'}/${modelName}`;\n\n return model(\n {\n name: actionName,\n ...modelRef?.info,\n configSchema: modelRef?.configSchema,\n },\n openAIModelRunner(modelName, client, requestBuilder, pluginOptions)\n );\n}\n\nconst GENERIC_MODEL_INFO: ModelInfo = {\n supports: {\n multiturn: true,\n media: true,\n tools: true,\n toolChoice: true,\n systemRole: true,\n },\n};\n\n/** ModelRef helper, with reasonable defaults for OpenAI-compatible providers */\nexport function compatOaiModelRef<\n CustomOptions extends z.ZodTypeAny = z.ZodTypeAny,\n>(params: {\n name: string;\n info?: ModelInfo;\n configSchema?: CustomOptions;\n config?: any;\n namespace?: string;\n}): ModelReference<CustomOptions> {\n const {\n name,\n info = GENERIC_MODEL_INFO,\n configSchema,\n config = undefined,\n namespace,\n } = params;\n return modelRef({\n name,\n configSchema: configSchema || (ChatCompletionCommonConfigSchema as any),\n info: info,\n config,\n namespace,\n });\n}\n"],"mappings":"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","names":["chunk","modelRef"]}
@@ -50,7 +50,7 @@ type XAIPlugin = {
50
50
  *
51
51
  * Usage: To use the models, initialize the xAI plugin inside
52
52
  * `configureGenkit` and pass the configuration options. If no API key is
53
- * provided in the options, the environment variable `OPENAI_API_KEY` must be
53
+ * provided in the options, the environment variable `XAI_API_KEY` must be
54
54
  * set.
55
55
  *
56
56
  * Example:
@@ -50,7 +50,7 @@ type XAIPlugin = {
50
50
  *
51
51
  * Usage: To use the models, initialize the xAI plugin inside
52
52
  * `configureGenkit` and pass the configuration options. If no API key is
53
- * provided in the options, the environment variable `OPENAI_API_KEY` must be
53
+ * provided in the options, the environment variable `XAI_API_KEY` must be
54
54
  * set.
55
55
  *
56
56
  * Example:
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/xai/index.ts"],"sourcesContent":["/**\n * Copyright 2024 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n ActionMetadata,\n GenkitError,\n modelActionMetadata,\n ModelReference,\n z,\n} from 'genkit';\nimport { logger } from 'genkit/logging';\nimport { ResolvableAction, type GenkitPluginV2 } from 'genkit/plugin';\nimport { ActionType } from 'genkit/registry';\nimport OpenAI from 'openai';\nimport {\n defineCompatOpenAIImageModel,\n ImageGenerationCommonConfigSchema,\n} from '../image.js';\nimport { openAICompatible, PluginOptions } from '../index.js';\nimport { defineCompatOpenAIModel } from '../model.js';\nimport { SUPPORTED_IMAGE_MODELS, xaiImageModelRef } from './grok-image.js';\nimport {\n grokRequestBuilder,\n SUPPORTED_LANGUAGE_MODELS,\n XaiChatCompletionConfigSchema,\n xaiModelRef,\n} from './grok.js';\n\nexport type XAIPluginOptions = Omit<PluginOptions, 'name' | 'baseURL'>;\n\nfunction createResolver(pluginOptions: PluginOptions) {\n return async (client: OpenAI, actionType: ActionType, actionName: string) => {\n if (actionType === 'model') {\n const modelRef = xaiModelRef({ name: actionName });\n return defineCompatOpenAIModel({\n name: modelRef.name,\n client,\n pluginOptions,\n modelRef,\n requestBuilder: grokRequestBuilder,\n });\n } else {\n logger.warn('Only model actions are supported by the XAI plugin');\n }\n return undefined;\n };\n}\n\nconst listActions = async (client: OpenAI): Promise<ActionMetadata[]> => {\n return await client.models.list().then((response) =>\n response.data\n .filter((model) => model.object === 'model')\n .map((model: OpenAI.Model) => {\n if (model.id.includes('image')) {\n const modelRef =\n SUPPORTED_IMAGE_MODELS[model.id] ??\n xaiImageModelRef({ name: model.id });\n return modelActionMetadata({\n name: modelRef.name,\n info: modelRef.info,\n configSchema: modelRef.configSchema,\n });\n } else {\n const modelRef =\n SUPPORTED_LANGUAGE_MODELS[model.id] ??\n xaiModelRef({ name: model.id });\n return modelActionMetadata({\n name: modelRef.name,\n info: modelRef.info,\n configSchema: modelRef.configSchema,\n });\n }\n })\n );\n};\n\nexport function xAIPlugin(options?: XAIPluginOptions): GenkitPluginV2 {\n const apiKey = options?.apiKey ?? process.env.XAI_API_KEY;\n if (!apiKey) {\n throw new GenkitError({\n status: 'FAILED_PRECONDITION',\n message:\n 'Please pass in the API key or set the XAI_API_KEY environment variable.',\n });\n }\n const pluginOptions = { name: 'xai', ...options };\n return openAICompatible({\n name: 'xai',\n baseURL: 'https://api.x.ai/v1',\n apiKey,\n ...options,\n initializer: async (client) => {\n const models = [] as ResolvableAction[];\n models.push(\n ...Object.values(SUPPORTED_LANGUAGE_MODELS).map((modelRef) =>\n defineCompatOpenAIModel({\n name: modelRef.name,\n client,\n pluginOptions,\n modelRef,\n requestBuilder: grokRequestBuilder,\n })\n )\n );\n models.push(\n ...Object.values(SUPPORTED_IMAGE_MODELS).map((modelRef) =>\n defineCompatOpenAIImageModel({\n name: modelRef.name,\n client,\n pluginOptions,\n modelRef,\n })\n )\n );\n return models;\n },\n resolver: createResolver(pluginOptions),\n listActions,\n });\n}\n\nexport type XAIPlugin = {\n (params?: XAIPluginOptions): GenkitPluginV2;\n model(\n name: keyof typeof SUPPORTED_LANGUAGE_MODELS,\n config?: z.infer<typeof XaiChatCompletionConfigSchema>\n ): ModelReference<typeof XaiChatCompletionConfigSchema>;\n model(\n name: keyof typeof SUPPORTED_IMAGE_MODELS,\n config?: z.infer<typeof ImageGenerationCommonConfigSchema>\n ): ModelReference<typeof ImageGenerationCommonConfigSchema>;\n model(name: string, config?: any): ModelReference<z.ZodTypeAny>;\n};\n\nconst model = ((name: string, config?: any): ModelReference<z.ZodTypeAny> => {\n if (name.includes('image')) {\n return xaiImageModelRef({\n name,\n config,\n });\n }\n return xaiModelRef({\n name,\n config,\n });\n}) as XAIPlugin['model'];\n\n/**\n * This module provides an interface to the XAI models through the Genkit\n * plugin system. It allows users to interact with various models by providing\n * an API key and optional configuration.\n *\n * The main export is the `xai` plugin, which can be configured with an API\n * key either directly or through environment variables. It initializes the\n * OpenAI client and makes available the models for use.\n *\n * Exports:\n * - xAI: The main plugin function to interact with XAI, via OpenAI\n * compatible API.\n *\n * Usage: To use the models, initialize the xAI plugin inside\n * `configureGenkit` and pass the configuration options. If no API key is\n * provided in the options, the environment variable `OPENAI_API_KEY` must be\n * set.\n *\n * Example:\n * ```\n * import { xAI } from '@genkit-ai/compat-oai/xai';\n *\n * export default configureGenkit({\n * plugins: [\n * xAI()\n * ... // other plugins\n * ]\n * });\n * ```\n */\nexport const xAI: XAIPlugin = Object.assign(xAIPlugin, {\n model,\n});\n\nexport default xAI;\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAgBA,oBAMO;AACP,qBAAuB;AAIvB,mBAGO;AACP,eAAgD;AAChD,mBAAwC;AACxC,wBAAyD;AACzD,kBAKO;AAIP,SAAS,eAAe,eAA8B;AACpD,SAAO,OAAO,QAAgB,YAAwB,eAAuB;AAC3E,QAAI,eAAe,SAAS;AAC1B,YAAM,eAAW,yBAAY,EAAE,MAAM,WAAW,CAAC;AACjD,iBAAO,sCAAwB;AAAA,QAC7B,MAAM,SAAS;AAAA,QACf;AAAA,QACA;AAAA,QACA;AAAA,QACA,gBAAgB;AAAA,MAClB,CAAC;AAAA,IACH,OAAO;AACL,4BAAO,KAAK,oDAAoD;AAAA,IAClE;AACA,WAAO;AAAA,EACT;AACF;AAEA,MAAM,cAAc,OAAO,WAA8C;AACvE,SAAO,MAAM,OAAO,OAAO,KAAK,EAAE;AAAA,IAAK,CAAC,aACtC,SAAS,KACN,OAAO,CAACA,WAAUA,OAAM,WAAW,OAAO,EAC1C,IAAI,CAACA,WAAwB;AAC5B,UAAIA,OAAM,GAAG,SAAS,OAAO,GAAG;AAC9B,cAAM,WACJ,yCAAuBA,OAAM,EAAE,SAC/B,oCAAiB,EAAE,MAAMA,OAAM,GAAG,CAAC;AACrC,mBAAO,mCAAoB;AAAA,UACzB,MAAM,SAAS;AAAA,UACf,MAAM,SAAS;AAAA,UACf,cAAc,SAAS;AAAA,QACzB,CAAC;AAAA,MACH,OAAO;AACL,cAAM,WACJ,sCAA0BA,OAAM,EAAE,SAClC,yBAAY,EAAE,MAAMA,OAAM,GAAG,CAAC;AAChC,mBAAO,mCAAoB;AAAA,UACzB,MAAM,SAAS;AAAA,UACf,MAAM,SAAS;AAAA,UACf,cAAc,SAAS;AAAA,QACzB,CAAC;AAAA,MACH;AAAA,IACF,CAAC;AAAA,EACL;AACF;AAEO,SAAS,UAAU,SAA4C;AACpE,QAAM,SAAS,SAAS,UAAU,QAAQ,IAAI;AAC9C,MAAI,CAAC,QAAQ;AACX,UAAM,IAAI,0BAAY;AAAA,MACpB,QAAQ;AAAA,MACR,SACE;AAAA,IACJ,CAAC;AAAA,EACH;AACA,QAAM,gBAAgB,EAAE,MAAM,OAAO,GAAG,QAAQ;AAChD,aAAO,2BAAiB;AAAA,IACtB,MAAM;AAAA,IACN,SAAS;AAAA,IACT;AAAA,IACA,GAAG;AAAA,IACH,aAAa,OAAO,WAAW;AAC7B,YAAM,SAAS,CAAC;AAChB,aAAO;AAAA,QACL,GAAG,OAAO,OAAO,qCAAyB,EAAE;AAAA,UAAI,CAAC,iBAC/C,sCAAwB;AAAA,YACtB,MAAM,SAAS;AAAA,YACf;AAAA,YACA;AAAA,YACA;AAAA,YACA,gBAAgB;AAAA,UAClB,CAAC;AAAA,QACH;AAAA,MACF;AACA,aAAO;AAAA,QACL,GAAG,OAAO,OAAO,wCAAsB,EAAE;AAAA,UAAI,CAAC,iBAC5C,2CAA6B;AAAA,YAC3B,MAAM,SAAS;AAAA,YACf;AAAA,YACA;AAAA,YACA;AAAA,UACF,CAAC;AAAA,QACH;AAAA,MACF;AACA,aAAO;AAAA,IACT;AAAA,IACA,UAAU,eAAe,aAAa;AAAA,IACtC;AAAA,EACF,CAAC;AACH;AAeA,MAAM,SAAS,CAAC,MAAc,WAA+C;AAC3E,MAAI,KAAK,SAAS,OAAO,GAAG;AAC1B,eAAO,oCAAiB;AAAA,MACtB;AAAA,MACA;AAAA,IACF,CAAC;AAAA,EACH;AACA,aAAO,yBAAY;AAAA,IACjB;AAAA,IACA;AAAA,EACF,CAAC;AACH;AAgCO,MAAM,MAAiB,OAAO,OAAO,WAAW;AAAA,EACrD;AACF,CAAC;AAED,IAAO,cAAQ;","names":["model"]}
1
+ {"version":3,"sources":["../../src/xai/index.ts"],"sourcesContent":["/**\n * Copyright 2024 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n ActionMetadata,\n GenkitError,\n modelActionMetadata,\n ModelReference,\n z,\n} from 'genkit';\nimport { logger } from 'genkit/logging';\nimport { ResolvableAction, type GenkitPluginV2 } from 'genkit/plugin';\nimport { ActionType } from 'genkit/registry';\nimport OpenAI from 'openai';\nimport {\n defineCompatOpenAIImageModel,\n ImageGenerationCommonConfigSchema,\n} from '../image.js';\nimport { openAICompatible, PluginOptions } from '../index.js';\nimport { defineCompatOpenAIModel } from '../model.js';\nimport { SUPPORTED_IMAGE_MODELS, xaiImageModelRef } from './grok-image.js';\nimport {\n grokRequestBuilder,\n SUPPORTED_LANGUAGE_MODELS,\n XaiChatCompletionConfigSchema,\n xaiModelRef,\n} from './grok.js';\n\nexport type XAIPluginOptions = Omit<PluginOptions, 'name' | 'baseURL'>;\n\nfunction createResolver(pluginOptions: PluginOptions) {\n return async (client: OpenAI, actionType: ActionType, actionName: string) => {\n if (actionType === 'model') {\n const modelRef = xaiModelRef({ name: actionName });\n return defineCompatOpenAIModel({\n name: modelRef.name,\n client,\n pluginOptions,\n modelRef,\n requestBuilder: grokRequestBuilder,\n });\n } else {\n logger.warn('Only model actions are supported by the XAI plugin');\n }\n return undefined;\n };\n}\n\nconst listActions = async (client: OpenAI): Promise<ActionMetadata[]> => {\n return await client.models.list().then((response) =>\n response.data\n .filter((model) => model.object === 'model')\n .map((model: OpenAI.Model) => {\n if (model.id.includes('image')) {\n const modelRef =\n SUPPORTED_IMAGE_MODELS[model.id] ??\n xaiImageModelRef({ name: model.id });\n return modelActionMetadata({\n name: modelRef.name,\n info: modelRef.info,\n configSchema: modelRef.configSchema,\n });\n } else {\n const modelRef =\n SUPPORTED_LANGUAGE_MODELS[model.id] ??\n xaiModelRef({ name: model.id });\n return modelActionMetadata({\n name: modelRef.name,\n info: modelRef.info,\n configSchema: modelRef.configSchema,\n });\n }\n })\n );\n};\n\nexport function xAIPlugin(options?: XAIPluginOptions): GenkitPluginV2 {\n const apiKey = options?.apiKey ?? process.env.XAI_API_KEY;\n if (!apiKey) {\n throw new GenkitError({\n status: 'FAILED_PRECONDITION',\n message:\n 'Please pass in the API key or set the XAI_API_KEY environment variable.',\n });\n }\n const pluginOptions = { name: 'xai', ...options };\n return openAICompatible({\n name: 'xai',\n baseURL: 'https://api.x.ai/v1',\n apiKey,\n ...options,\n initializer: async (client) => {\n const models = [] as ResolvableAction[];\n models.push(\n ...Object.values(SUPPORTED_LANGUAGE_MODELS).map((modelRef) =>\n defineCompatOpenAIModel({\n name: modelRef.name,\n client,\n pluginOptions,\n modelRef,\n requestBuilder: grokRequestBuilder,\n })\n )\n );\n models.push(\n ...Object.values(SUPPORTED_IMAGE_MODELS).map((modelRef) =>\n defineCompatOpenAIImageModel({\n name: modelRef.name,\n client,\n pluginOptions,\n modelRef,\n })\n )\n );\n return models;\n },\n resolver: createResolver(pluginOptions),\n listActions,\n });\n}\n\nexport type XAIPlugin = {\n (params?: XAIPluginOptions): GenkitPluginV2;\n model(\n name: keyof typeof SUPPORTED_LANGUAGE_MODELS,\n config?: z.infer<typeof XaiChatCompletionConfigSchema>\n ): ModelReference<typeof XaiChatCompletionConfigSchema>;\n model(\n name: keyof typeof SUPPORTED_IMAGE_MODELS,\n config?: z.infer<typeof ImageGenerationCommonConfigSchema>\n ): ModelReference<typeof ImageGenerationCommonConfigSchema>;\n model(name: string, config?: any): ModelReference<z.ZodTypeAny>;\n};\n\nconst model = ((name: string, config?: any): ModelReference<z.ZodTypeAny> => {\n if (name.includes('image')) {\n return xaiImageModelRef({\n name,\n config,\n });\n }\n return xaiModelRef({\n name,\n config,\n });\n}) as XAIPlugin['model'];\n\n/**\n * This module provides an interface to the XAI models through the Genkit\n * plugin system. It allows users to interact with various models by providing\n * an API key and optional configuration.\n *\n * The main export is the `xai` plugin, which can be configured with an API\n * key either directly or through environment variables. It initializes the\n * OpenAI client and makes available the models for use.\n *\n * Exports:\n * - xAI: The main plugin function to interact with XAI, via OpenAI\n * compatible API.\n *\n * Usage: To use the models, initialize the xAI plugin inside\n * `configureGenkit` and pass the configuration options. If no API key is\n * provided in the options, the environment variable `XAI_API_KEY` must be\n * set.\n *\n * Example:\n * ```\n * import { xAI } from '@genkit-ai/compat-oai/xai';\n *\n * export default configureGenkit({\n * plugins: [\n * xAI()\n * ... // other plugins\n * ]\n * });\n * ```\n */\nexport const xAI: XAIPlugin = Object.assign(xAIPlugin, {\n model,\n});\n\nexport default xAI;\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAgBA,oBAMO;AACP,qBAAuB;AAIvB,mBAGO;AACP,eAAgD;AAChD,mBAAwC;AACxC,wBAAyD;AACzD,kBAKO;AAIP,SAAS,eAAe,eAA8B;AACpD,SAAO,OAAO,QAAgB,YAAwB,eAAuB;AAC3E,QAAI,eAAe,SAAS;AAC1B,YAAM,eAAW,yBAAY,EAAE,MAAM,WAAW,CAAC;AACjD,iBAAO,sCAAwB;AAAA,QAC7B,MAAM,SAAS;AAAA,QACf;AAAA,QACA;AAAA,QACA;AAAA,QACA,gBAAgB;AAAA,MAClB,CAAC;AAAA,IACH,OAAO;AACL,4BAAO,KAAK,oDAAoD;AAAA,IAClE;AACA,WAAO;AAAA,EACT;AACF;AAEA,MAAM,cAAc,OAAO,WAA8C;AACvE,SAAO,MAAM,OAAO,OAAO,KAAK,EAAE;AAAA,IAAK,CAAC,aACtC,SAAS,KACN,OAAO,CAACA,WAAUA,OAAM,WAAW,OAAO,EAC1C,IAAI,CAACA,WAAwB;AAC5B,UAAIA,OAAM,GAAG,SAAS,OAAO,GAAG;AAC9B,cAAM,WACJ,yCAAuBA,OAAM,EAAE,SAC/B,oCAAiB,EAAE,MAAMA,OAAM,GAAG,CAAC;AACrC,mBAAO,mCAAoB;AAAA,UACzB,MAAM,SAAS;AAAA,UACf,MAAM,SAAS;AAAA,UACf,cAAc,SAAS;AAAA,QACzB,CAAC;AAAA,MACH,OAAO;AACL,cAAM,WACJ,sCAA0BA,OAAM,EAAE,SAClC,yBAAY,EAAE,MAAMA,OAAM,GAAG,CAAC;AAChC,mBAAO,mCAAoB;AAAA,UACzB,MAAM,SAAS;AAAA,UACf,MAAM,SAAS;AAAA,UACf,cAAc,SAAS;AAAA,QACzB,CAAC;AAAA,MACH;AAAA,IACF,CAAC;AAAA,EACL;AACF;AAEO,SAAS,UAAU,SAA4C;AACpE,QAAM,SAAS,SAAS,UAAU,QAAQ,IAAI;AAC9C,MAAI,CAAC,QAAQ;AACX,UAAM,IAAI,0BAAY;AAAA,MACpB,QAAQ;AAAA,MACR,SACE;AAAA,IACJ,CAAC;AAAA,EACH;AACA,QAAM,gBAAgB,EAAE,MAAM,OAAO,GAAG,QAAQ;AAChD,aAAO,2BAAiB;AAAA,IACtB,MAAM;AAAA,IACN,SAAS;AAAA,IACT;AAAA,IACA,GAAG;AAAA,IACH,aAAa,OAAO,WAAW;AAC7B,YAAM,SAAS,CAAC;AAChB,aAAO;AAAA,QACL,GAAG,OAAO,OAAO,qCAAyB,EAAE;AAAA,UAAI,CAAC,iBAC/C,sCAAwB;AAAA,YACtB,MAAM,SAAS;AAAA,YACf;AAAA,YACA;AAAA,YACA;AAAA,YACA,gBAAgB;AAAA,UAClB,CAAC;AAAA,QACH;AAAA,MACF;AACA,aAAO;AAAA,QACL,GAAG,OAAO,OAAO,wCAAsB,EAAE;AAAA,UAAI,CAAC,iBAC5C,2CAA6B;AAAA,YAC3B,MAAM,SAAS;AAAA,YACf;AAAA,YACA;AAAA,YACA;AAAA,UACF,CAAC;AAAA,QACH;AAAA,MACF;AACA,aAAO;AAAA,IACT;AAAA,IACA,UAAU,eAAe,aAAa;AAAA,IACtC;AAAA,EACF,CAAC;AACH;AAeA,MAAM,SAAS,CAAC,MAAc,WAA+C;AAC3E,MAAI,KAAK,SAAS,OAAO,GAAG;AAC1B,eAAO,oCAAiB;AAAA,MACtB;AAAA,MACA;AAAA,IACF,CAAC;AAAA,EACH;AACA,aAAO,yBAAY;AAAA,IACjB;AAAA,IACA;AAAA,EACF,CAAC;AACH;AAgCO,MAAM,MAAiB,OAAO,OAAO,WAAW;AAAA,EACrD;AACF,CAAC;AAED,IAAO,cAAQ;","names":["model"]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/xai/index.ts"],"sourcesContent":["/**\n * Copyright 2024 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n ActionMetadata,\n GenkitError,\n modelActionMetadata,\n ModelReference,\n z,\n} from 'genkit';\nimport { logger } from 'genkit/logging';\nimport { ResolvableAction, type GenkitPluginV2 } from 'genkit/plugin';\nimport { ActionType } from 'genkit/registry';\nimport OpenAI from 'openai';\nimport {\n defineCompatOpenAIImageModel,\n ImageGenerationCommonConfigSchema,\n} from '../image.js';\nimport { openAICompatible, PluginOptions } from '../index.js';\nimport { defineCompatOpenAIModel } from '../model.js';\nimport { SUPPORTED_IMAGE_MODELS, xaiImageModelRef } from './grok-image.js';\nimport {\n grokRequestBuilder,\n SUPPORTED_LANGUAGE_MODELS,\n XaiChatCompletionConfigSchema,\n xaiModelRef,\n} from './grok.js';\n\nexport type XAIPluginOptions = Omit<PluginOptions, 'name' | 'baseURL'>;\n\nfunction createResolver(pluginOptions: PluginOptions) {\n return async (client: OpenAI, actionType: ActionType, actionName: string) => {\n if (actionType === 'model') {\n const modelRef = xaiModelRef({ name: actionName });\n return defineCompatOpenAIModel({\n name: modelRef.name,\n client,\n pluginOptions,\n modelRef,\n requestBuilder: grokRequestBuilder,\n });\n } else {\n logger.warn('Only model actions are supported by the XAI plugin');\n }\n return undefined;\n };\n}\n\nconst listActions = async (client: OpenAI): Promise<ActionMetadata[]> => {\n return await client.models.list().then((response) =>\n response.data\n .filter((model) => model.object === 'model')\n .map((model: OpenAI.Model) => {\n if (model.id.includes('image')) {\n const modelRef =\n SUPPORTED_IMAGE_MODELS[model.id] ??\n xaiImageModelRef({ name: model.id });\n return modelActionMetadata({\n name: modelRef.name,\n info: modelRef.info,\n configSchema: modelRef.configSchema,\n });\n } else {\n const modelRef =\n SUPPORTED_LANGUAGE_MODELS[model.id] ??\n xaiModelRef({ name: model.id });\n return modelActionMetadata({\n name: modelRef.name,\n info: modelRef.info,\n configSchema: modelRef.configSchema,\n });\n }\n })\n );\n};\n\nexport function xAIPlugin(options?: XAIPluginOptions): GenkitPluginV2 {\n const apiKey = options?.apiKey ?? process.env.XAI_API_KEY;\n if (!apiKey) {\n throw new GenkitError({\n status: 'FAILED_PRECONDITION',\n message:\n 'Please pass in the API key or set the XAI_API_KEY environment variable.',\n });\n }\n const pluginOptions = { name: 'xai', ...options };\n return openAICompatible({\n name: 'xai',\n baseURL: 'https://api.x.ai/v1',\n apiKey,\n ...options,\n initializer: async (client) => {\n const models = [] as ResolvableAction[];\n models.push(\n ...Object.values(SUPPORTED_LANGUAGE_MODELS).map((modelRef) =>\n defineCompatOpenAIModel({\n name: modelRef.name,\n client,\n pluginOptions,\n modelRef,\n requestBuilder: grokRequestBuilder,\n })\n )\n );\n models.push(\n ...Object.values(SUPPORTED_IMAGE_MODELS).map((modelRef) =>\n defineCompatOpenAIImageModel({\n name: modelRef.name,\n client,\n pluginOptions,\n modelRef,\n })\n )\n );\n return models;\n },\n resolver: createResolver(pluginOptions),\n listActions,\n });\n}\n\nexport type XAIPlugin = {\n (params?: XAIPluginOptions): GenkitPluginV2;\n model(\n name: keyof typeof SUPPORTED_LANGUAGE_MODELS,\n config?: z.infer<typeof XaiChatCompletionConfigSchema>\n ): ModelReference<typeof XaiChatCompletionConfigSchema>;\n model(\n name: keyof typeof SUPPORTED_IMAGE_MODELS,\n config?: z.infer<typeof ImageGenerationCommonConfigSchema>\n ): ModelReference<typeof ImageGenerationCommonConfigSchema>;\n model(name: string, config?: any): ModelReference<z.ZodTypeAny>;\n};\n\nconst model = ((name: string, config?: any): ModelReference<z.ZodTypeAny> => {\n if (name.includes('image')) {\n return xaiImageModelRef({\n name,\n config,\n });\n }\n return xaiModelRef({\n name,\n config,\n });\n}) as XAIPlugin['model'];\n\n/**\n * This module provides an interface to the XAI models through the Genkit\n * plugin system. It allows users to interact with various models by providing\n * an API key and optional configuration.\n *\n * The main export is the `xai` plugin, which can be configured with an API\n * key either directly or through environment variables. It initializes the\n * OpenAI client and makes available the models for use.\n *\n * Exports:\n * - xAI: The main plugin function to interact with XAI, via OpenAI\n * compatible API.\n *\n * Usage: To use the models, initialize the xAI plugin inside\n * `configureGenkit` and pass the configuration options. If no API key is\n * provided in the options, the environment variable `OPENAI_API_KEY` must be\n * set.\n *\n * Example:\n * ```\n * import { xAI } from '@genkit-ai/compat-oai/xai';\n *\n * export default configureGenkit({\n * plugins: [\n * xAI()\n * ... // other plugins\n * ]\n * });\n * ```\n */\nexport const xAI: XAIPlugin = Object.assign(xAIPlugin, {\n model,\n});\n\nexport default xAI;\n"],"mappings":"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","names":["model"]}
1
+ {"version":3,"sources":["../../src/xai/index.ts"],"sourcesContent":["/**\n * Copyright 2024 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n ActionMetadata,\n GenkitError,\n modelActionMetadata,\n ModelReference,\n z,\n} from 'genkit';\nimport { logger } from 'genkit/logging';\nimport { ResolvableAction, type GenkitPluginV2 } from 'genkit/plugin';\nimport { ActionType } from 'genkit/registry';\nimport OpenAI from 'openai';\nimport {\n defineCompatOpenAIImageModel,\n ImageGenerationCommonConfigSchema,\n} from '../image.js';\nimport { openAICompatible, PluginOptions } from '../index.js';\nimport { defineCompatOpenAIModel } from '../model.js';\nimport { SUPPORTED_IMAGE_MODELS, xaiImageModelRef } from './grok-image.js';\nimport {\n grokRequestBuilder,\n SUPPORTED_LANGUAGE_MODELS,\n XaiChatCompletionConfigSchema,\n xaiModelRef,\n} from './grok.js';\n\nexport type XAIPluginOptions = Omit<PluginOptions, 'name' | 'baseURL'>;\n\nfunction createResolver(pluginOptions: PluginOptions) {\n return async (client: OpenAI, actionType: ActionType, actionName: string) => {\n if (actionType === 'model') {\n const modelRef = xaiModelRef({ name: actionName });\n return defineCompatOpenAIModel({\n name: modelRef.name,\n client,\n pluginOptions,\n modelRef,\n requestBuilder: grokRequestBuilder,\n });\n } else {\n logger.warn('Only model actions are supported by the XAI plugin');\n }\n return undefined;\n };\n}\n\nconst listActions = async (client: OpenAI): Promise<ActionMetadata[]> => {\n return await client.models.list().then((response) =>\n response.data\n .filter((model) => model.object === 'model')\n .map((model: OpenAI.Model) => {\n if (model.id.includes('image')) {\n const modelRef =\n SUPPORTED_IMAGE_MODELS[model.id] ??\n xaiImageModelRef({ name: model.id });\n return modelActionMetadata({\n name: modelRef.name,\n info: modelRef.info,\n configSchema: modelRef.configSchema,\n });\n } else {\n const modelRef =\n SUPPORTED_LANGUAGE_MODELS[model.id] ??\n xaiModelRef({ name: model.id });\n return modelActionMetadata({\n name: modelRef.name,\n info: modelRef.info,\n configSchema: modelRef.configSchema,\n });\n }\n })\n );\n};\n\nexport function xAIPlugin(options?: XAIPluginOptions): GenkitPluginV2 {\n const apiKey = options?.apiKey ?? process.env.XAI_API_KEY;\n if (!apiKey) {\n throw new GenkitError({\n status: 'FAILED_PRECONDITION',\n message:\n 'Please pass in the API key or set the XAI_API_KEY environment variable.',\n });\n }\n const pluginOptions = { name: 'xai', ...options };\n return openAICompatible({\n name: 'xai',\n baseURL: 'https://api.x.ai/v1',\n apiKey,\n ...options,\n initializer: async (client) => {\n const models = [] as ResolvableAction[];\n models.push(\n ...Object.values(SUPPORTED_LANGUAGE_MODELS).map((modelRef) =>\n defineCompatOpenAIModel({\n name: modelRef.name,\n client,\n pluginOptions,\n modelRef,\n requestBuilder: grokRequestBuilder,\n })\n )\n );\n models.push(\n ...Object.values(SUPPORTED_IMAGE_MODELS).map((modelRef) =>\n defineCompatOpenAIImageModel({\n name: modelRef.name,\n client,\n pluginOptions,\n modelRef,\n })\n )\n );\n return models;\n },\n resolver: createResolver(pluginOptions),\n listActions,\n });\n}\n\nexport type XAIPlugin = {\n (params?: XAIPluginOptions): GenkitPluginV2;\n model(\n name: keyof typeof SUPPORTED_LANGUAGE_MODELS,\n config?: z.infer<typeof XaiChatCompletionConfigSchema>\n ): ModelReference<typeof XaiChatCompletionConfigSchema>;\n model(\n name: keyof typeof SUPPORTED_IMAGE_MODELS,\n config?: z.infer<typeof ImageGenerationCommonConfigSchema>\n ): ModelReference<typeof ImageGenerationCommonConfigSchema>;\n model(name: string, config?: any): ModelReference<z.ZodTypeAny>;\n};\n\nconst model = ((name: string, config?: any): ModelReference<z.ZodTypeAny> => {\n if (name.includes('image')) {\n return xaiImageModelRef({\n name,\n config,\n });\n }\n return xaiModelRef({\n name,\n config,\n });\n}) as XAIPlugin['model'];\n\n/**\n * This module provides an interface to the XAI models through the Genkit\n * plugin system. It allows users to interact with various models by providing\n * an API key and optional configuration.\n *\n * The main export is the `xai` plugin, which can be configured with an API\n * key either directly or through environment variables. It initializes the\n * OpenAI client and makes available the models for use.\n *\n * Exports:\n * - xAI: The main plugin function to interact with XAI, via OpenAI\n * compatible API.\n *\n * Usage: To use the models, initialize the xAI plugin inside\n * `configureGenkit` and pass the configuration options. If no API key is\n * provided in the options, the environment variable `XAI_API_KEY` must be\n * set.\n *\n * Example:\n * ```\n * import { xAI } from '@genkit-ai/compat-oai/xai';\n *\n * export default configureGenkit({\n * plugins: [\n * xAI()\n * ... // other plugins\n * ]\n * });\n * ```\n */\nexport const xAI: XAIPlugin = Object.assign(xAIPlugin, {\n model,\n});\n\nexport default xAI;\n"],"mappings":"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","names":["model"]}
package/package.json CHANGED
@@ -11,7 +11,7 @@
11
11
  "genai",
12
12
  "generative-ai"
13
13
  ],
14
- "version": "1.33.0",
14
+ "version": "1.35.0",
15
15
  "type": "commonjs",
16
16
  "repository": {
17
17
  "type": "git",
@@ -24,7 +24,7 @@
24
24
  "openai": "^4.95.0"
25
25
  },
26
26
  "peerDependencies": {
27
- "genkit": "^1.33.0"
27
+ "genkit": "^1.35.0"
28
28
  },
29
29
  "devDependencies": {
30
30
  "@jest/globals": "^29.7.0",
@@ -33,7 +33,8 @@
33
33
  "npm-run-all": "^4.1.5",
34
34
  "ts-jest": "^29.1.2",
35
35
  "tsup": "^8.0.2",
36
- "typescript": "^5.9.3"
36
+ "typescript": "^5.9.3",
37
+ "rimraf": "^6.0.1"
37
38
  },
38
39
  "types": "./lib/index.d.ts",
39
40
  "exports": {
@@ -85,7 +86,7 @@
85
86
  "scripts": {
86
87
  "check": "tsc",
87
88
  "compile": "tsup-node",
88
- "build:clean": "rm -rf ./lib",
89
+ "build:clean": "rimraf ./lib",
89
90
  "build": "npm-run-all build:clean check compile",
90
91
  "build:watch": "tsup-node --watch",
91
92
  "test": "jest --coverage"