@llumiverse/drivers 1.3.0 → 1.4.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.
- package/lib/{types/adobe → adobe}/firefly.d.ts +2 -1
- package/lib/adobe/firefly.d.ts.map +1 -0
- package/lib/adobe/firefly.js +120 -0
- package/lib/adobe/firefly.js.map +1 -0
- package/lib/{types/anthropic → anthropic}/index.d.ts +4 -2
- package/lib/anthropic/index.d.ts.map +1 -0
- package/lib/{esm/anthropic → anthropic}/index.js +19 -8
- package/lib/anthropic/index.js.map +1 -0
- package/lib/{types/azure → azure}/azure_foundry.d.ts +9 -7
- package/lib/azure/azure_foundry.d.ts.map +1 -0
- package/lib/{esm/azure → azure}/azure_foundry.js +138 -124
- package/lib/azure/azure_foundry.js.map +1 -0
- package/lib/{types/bedrock → bedrock}/converse.d.ts +2 -2
- package/lib/bedrock/converse.d.ts.map +1 -0
- package/lib/{esm/bedrock → bedrock}/converse.js +86 -79
- package/lib/bedrock/converse.js.map +1 -0
- package/lib/bedrock/embeddings.d.ts +4 -0
- package/lib/bedrock/embeddings.d.ts.map +1 -0
- package/lib/bedrock/embeddings.js +359 -0
- package/lib/bedrock/embeddings.js.map +1 -0
- package/lib/{types/bedrock → bedrock}/index.d.ts +33 -9
- package/lib/bedrock/index.d.ts.map +1 -0
- package/lib/{esm/bedrock → bedrock}/index.js +599 -324
- package/lib/bedrock/index.js.map +1 -0
- package/lib/{types/bedrock → bedrock}/nova-image-payload.d.ts +5 -5
- package/lib/bedrock/nova-image-payload.d.ts.map +1 -0
- package/lib/{esm/bedrock → bedrock}/nova-image-payload.js +31 -36
- package/lib/bedrock/nova-image-payload.js.map +1 -0
- package/lib/{types/bedrock → bedrock}/payloads.d.ts +1 -1
- package/lib/bedrock/payloads.d.ts.map +1 -0
- package/lib/{cjs/bedrock → bedrock}/payloads.js.map +1 -1
- package/lib/{types/bedrock → bedrock}/s3.d.ts +3 -2
- package/lib/bedrock/s3.d.ts.map +1 -0
- package/lib/{esm/bedrock → bedrock}/s3.js +27 -23
- package/lib/bedrock/s3.js.map +1 -0
- package/lib/{types/bedrock → bedrock}/twelvelabs.d.ts +8 -9
- package/lib/bedrock/twelvelabs.d.ts.map +1 -0
- package/lib/{esm/bedrock → bedrock}/twelvelabs.js +17 -21
- package/lib/bedrock/twelvelabs.js.map +1 -0
- package/lib/{types/groq → groq}/index.d.ts +6 -4
- package/lib/groq/index.d.ts.map +1 -0
- package/lib/{esm/groq → groq}/index.js +72 -39
- package/lib/groq/index.js.map +1 -0
- package/lib/{types/huggingface_ie.d.ts → huggingface_ie.d.ts} +4 -3
- package/lib/huggingface_ie.d.ts.map +1 -0
- package/lib/{esm/huggingface_ie.js → huggingface_ie.js} +32 -31
- package/lib/huggingface_ie.js.map +1 -0
- package/lib/index.d.ts +16 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +16 -0
- package/lib/index.js.map +1 -0
- package/lib/{types/mistral → mistral}/index.d.ts +6 -5
- package/lib/mistral/index.d.ts.map +1 -0
- package/lib/{esm/mistral → mistral}/index.js +66 -38
- package/lib/mistral/index.js.map +1 -0
- package/lib/{types/mistral → mistral}/types.d.ts +1 -0
- package/lib/mistral/types.d.ts.map +1 -0
- package/lib/mistral/types.js.map +1 -0
- package/lib/{types/openai → openai}/azure_openai.d.ts +5 -4
- package/lib/openai/azure_openai.d.ts.map +1 -0
- package/lib/{esm/openai → openai}/azure_openai.js +17 -14
- package/lib/openai/azure_openai.js.map +1 -0
- package/lib/openai/drivers.d.ts +4 -0
- package/lib/openai/drivers.d.ts.map +1 -0
- package/lib/openai/drivers.js +9 -0
- package/lib/openai/drivers.js.map +1 -0
- package/lib/{types/openai → openai}/index.d.ts +16 -5
- package/lib/openai/index.d.ts.map +1 -0
- package/lib/{esm/openai → openai}/index.js +242 -141
- package/lib/openai/index.js.map +1 -0
- package/lib/{types/openai → openai}/openai.d.ts +3 -3
- package/lib/openai/openai.d.ts.map +1 -0
- package/lib/openai/openai.js +15 -0
- package/lib/openai/openai.js.map +1 -0
- package/lib/{types/openai → openai}/openai_compatible.d.ts +3 -3
- package/lib/openai/openai_compatible.d.ts.map +1 -0
- package/lib/{esm/openai → openai}/openai_compatible.js +14 -11
- package/lib/openai/openai_compatible.js.map +1 -0
- package/lib/{types/openai → openai}/openai_format.d.ts +3 -2
- package/lib/openai/openai_format.d.ts.map +1 -0
- package/lib/{esm/openai → openai}/openai_format.js +66 -24
- package/lib/openai/openai_format.js.map +1 -0
- package/lib/{types/replicate.d.ts → replicate.d.ts} +3 -2
- package/lib/replicate.d.ts.map +1 -0
- package/lib/{esm/replicate.js → replicate.js} +59 -49
- package/lib/replicate.js.map +1 -0
- package/lib/{types/shared → shared}/claude-messages.d.ts +25 -1
- package/lib/shared/claude-messages.d.ts.map +1 -0
- package/lib/{esm/shared → shared}/claude-messages.js +212 -59
- package/lib/shared/claude-messages.js.map +1 -0
- package/lib/{types/shared → shared}/claude-thinking.d.ts +1 -1
- package/lib/shared/claude-thinking.d.ts.map +1 -0
- package/lib/{esm/shared → shared}/claude-thinking.js +5 -7
- package/lib/shared/claude-thinking.js.map +1 -0
- package/lib/shared/debug-prompt.d.ts +5 -0
- package/lib/shared/debug-prompt.d.ts.map +1 -0
- package/lib/shared/debug-prompt.js +25 -0
- package/lib/shared/debug-prompt.js.map +1 -0
- package/lib/{types/test-driver → test-driver}/TestErrorCompletionStream.d.ts +1 -1
- package/lib/test-driver/TestErrorCompletionStream.d.ts.map +1 -0
- package/lib/test-driver/TestErrorCompletionStream.js +16 -0
- package/lib/test-driver/TestErrorCompletionStream.js.map +1 -0
- package/lib/{types/test-driver → test-driver}/TestValidationErrorCompletionStream.d.ts +1 -1
- package/lib/test-driver/TestValidationErrorCompletionStream.d.ts.map +1 -0
- package/lib/{esm/test-driver → test-driver}/TestValidationErrorCompletionStream.js +4 -4
- package/lib/test-driver/TestValidationErrorCompletionStream.js.map +1 -0
- package/lib/{types/test-driver → test-driver}/index.d.ts +3 -3
- package/lib/test-driver/index.d.ts.map +1 -0
- package/lib/{esm/test-driver → test-driver}/index.js +20 -20
- package/lib/test-driver/index.js.map +1 -0
- package/lib/{types/test-driver → test-driver}/utils.d.ts +1 -1
- package/lib/test-driver/utils.d.ts.map +1 -0
- package/lib/{esm/test-driver → test-driver}/utils.js +4 -4
- package/lib/test-driver/utils.js.map +1 -0
- package/lib/togetherai/index.d.ts +15 -0
- package/lib/togetherai/index.d.ts.map +1 -0
- package/lib/togetherai/index.js +54 -0
- package/lib/togetherai/index.js.map +1 -0
- package/lib/{types/togetherai → togetherai}/interfaces.d.ts +1 -1
- package/lib/togetherai/interfaces.d.ts.map +1 -0
- package/lib/{cjs/watsonx → togetherai}/interfaces.js.map +1 -1
- package/lib/vertexai/debug.d.ts +2 -0
- package/lib/vertexai/debug.d.ts.map +1 -0
- package/lib/{esm/vertexai → vertexai}/debug.js +1 -1
- package/lib/vertexai/debug.js.map +1 -0
- package/lib/vertexai/embeddings/embed-legacy-multimodal.d.ts +9 -0
- package/lib/vertexai/embeddings/embed-legacy-multimodal.d.ts.map +1 -0
- package/lib/vertexai/embeddings/embed-legacy-multimodal.js +141 -0
- package/lib/vertexai/embeddings/embed-legacy-multimodal.js.map +1 -0
- package/lib/vertexai/embeddings/embed.d.ts +13 -0
- package/lib/vertexai/embeddings/embed.d.ts.map +1 -0
- package/lib/vertexai/embeddings/embed.js +162 -0
- package/lib/vertexai/embeddings/embed.js.map +1 -0
- package/lib/vertexai/embeddings/source-utils.d.ts +9 -0
- package/lib/vertexai/embeddings/source-utils.d.ts.map +1 -0
- package/lib/vertexai/embeddings/source-utils.js +18 -0
- package/lib/vertexai/embeddings/source-utils.js.map +1 -0
- package/lib/{types/vertexai → vertexai}/index.d.ts +31 -19
- package/lib/vertexai/index.d.ts.map +1 -0
- package/lib/{esm/vertexai → vertexai}/index.js +221 -159
- package/lib/vertexai/index.js.map +1 -0
- package/lib/{types/vertexai → vertexai}/models/claude.d.ts +4 -4
- package/lib/vertexai/models/claude.d.ts.map +1 -0
- package/lib/{esm/vertexai → vertexai}/models/claude.js +17 -20
- package/lib/vertexai/models/claude.js.map +1 -0
- package/lib/{types/vertexai → vertexai}/models/gemini.d.ts +28 -4
- package/lib/vertexai/models/gemini.d.ts.map +1 -0
- package/lib/{esm/vertexai → vertexai}/models/gemini.js +238 -116
- package/lib/vertexai/models/gemini.js.map +1 -0
- package/lib/{types/vertexai → vertexai}/models/imagen.d.ts +12 -11
- package/lib/vertexai/models/imagen.d.ts.map +1 -0
- package/lib/{esm/vertexai → vertexai}/models/imagen.js +74 -47
- package/lib/vertexai/models/imagen.js.map +1 -0
- package/lib/{types/vertexai → vertexai}/models/llama.d.ts +4 -4
- package/lib/vertexai/models/llama.d.ts.map +1 -0
- package/lib/{esm/vertexai → vertexai}/models/llama.js +37 -33
- package/lib/vertexai/models/llama.js.map +1 -0
- package/lib/vertexai/models.d.ts +21 -0
- package/lib/vertexai/models.d.ts.map +1 -0
- package/lib/{esm/vertexai → vertexai}/models.js +12 -9
- package/lib/vertexai/models.js.map +1 -0
- package/lib/{types/watsonx → watsonx}/index.d.ts +4 -3
- package/lib/watsonx/index.d.ts.map +1 -0
- package/lib/{esm/watsonx → watsonx}/index.js +69 -41
- package/lib/watsonx/index.js.map +1 -0
- package/lib/watsonx/interfaces.d.ts.map +1 -0
- package/lib/{esm/watsonx → watsonx}/interfaces.js.map +1 -1
- package/lib/{types/xai → xai}/index.d.ts +4 -4
- package/lib/xai/index.d.ts.map +1 -0
- package/lib/{esm/xai → xai}/index.js +22 -18
- package/lib/xai/index.js.map +1 -0
- package/package.json +87 -36
- package/src/adobe/firefly.ts +60 -43
- package/src/anthropic/index.ts +37 -20
- package/src/azure/azure_foundry.ts +210 -165
- package/src/bedrock/converse.ts +124 -101
- package/src/bedrock/embeddings.test.ts +508 -0
- package/src/bedrock/embeddings.ts +517 -0
- package/src/bedrock/error-handling.test.ts +62 -14
- package/src/bedrock/index.ts +832 -466
- package/src/bedrock/nova-image-payload.ts +98 -91
- package/src/bedrock/payloads.ts +9 -9
- package/src/bedrock/s3.test.ts +39 -0
- package/src/bedrock/s3.ts +57 -38
- package/src/bedrock/streaming-tool-use.test.ts +86 -69
- package/src/bedrock/twelvelabs.ts +35 -32
- package/src/groq/index.ts +143 -60
- package/src/http-timeout-wiring.test.ts +263 -0
- package/src/huggingface_ie.ts +45 -61
- package/src/index.ts +15 -16
- package/src/mistral/index.ts +97 -48
- package/src/mistral/types.ts +13 -12
- package/src/openai/azure_openai.ts +35 -27
- package/src/openai/drivers.ts +9 -0
- package/src/openai/error-handling.test.ts +308 -113
- package/src/openai/index.ts +378 -248
- package/src/openai/openai.ts +6 -13
- package/src/openai/openai_compatible.ts +35 -25
- package/src/openai/openai_format.ts +90 -40
- package/src/replicate.ts +108 -86
- package/src/shared/claude-messages.test.ts +37 -0
- package/src/shared/claude-messages.ts +303 -97
- package/src/shared/claude-thinking.ts +6 -12
- package/src/shared/debug-prompt.ts +28 -0
- package/src/test-driver/TestErrorCompletionStream.ts +9 -10
- package/src/test-driver/TestValidationErrorCompletionStream.ts +9 -10
- package/src/test-driver/index.ts +43 -27
- package/src/test-driver/utils.ts +8 -8
- package/src/togetherai/index.test.ts +32 -0
- package/src/togetherai/index.ts +64 -128
- package/src/togetherai/interfaces.ts +5 -5
- package/src/vertexai/debug.ts +3 -3
- package/src/vertexai/embeddings/embed-legacy-multimodal.ts +211 -0
- package/src/vertexai/embeddings/embed.ts +206 -0
- package/src/vertexai/embeddings/embeddings.test.ts +497 -0
- package/src/vertexai/embeddings/source-utils.test.ts +54 -0
- package/src/vertexai/embeddings/source-utils.ts +29 -0
- package/src/vertexai/index.ts +331 -244
- package/src/vertexai/models/claude-error-handling.test.ts +83 -36
- package/src/vertexai/models/claude-streaming-spacing.test.ts +82 -75
- package/src/vertexai/models/claude.ts +55 -40
- package/src/vertexai/models/gemini-conversation-mutation.test.ts +65 -23
- package/src/vertexai/models/gemini-error-handling.test.ts +126 -10
- package/src/vertexai/models/gemini-orphaned-tool-result.test.ts +118 -0
- package/src/vertexai/models/gemini.ts +349 -172
- package/src/vertexai/models/imagen.ts +164 -100
- package/src/vertexai/models/llama.ts +70 -48
- package/src/vertexai/models.ts +36 -16
- package/src/watsonx/index.ts +101 -65
- package/src/watsonx/interfaces.ts +10 -15
- package/src/xai/index.ts +30 -30
- package/lib/cjs/adobe/firefly.js +0 -120
- package/lib/cjs/adobe/firefly.js.map +0 -1
- package/lib/cjs/anthropic/index.js +0 -64
- package/lib/cjs/anthropic/index.js.map +0 -1
- package/lib/cjs/azure/azure_foundry.js +0 -432
- package/lib/cjs/azure/azure_foundry.js.map +0 -1
- package/lib/cjs/bedrock/converse.js +0 -359
- package/lib/cjs/bedrock/converse.js.map +0 -1
- package/lib/cjs/bedrock/index.js +0 -1508
- package/lib/cjs/bedrock/index.js.map +0 -1
- package/lib/cjs/bedrock/nova-image-payload.js +0 -207
- package/lib/cjs/bedrock/nova-image-payload.js.map +0 -1
- package/lib/cjs/bedrock/payloads.js +0 -3
- package/lib/cjs/bedrock/s3.js +0 -107
- package/lib/cjs/bedrock/s3.js.map +0 -1
- package/lib/cjs/bedrock/twelvelabs.js +0 -87
- package/lib/cjs/bedrock/twelvelabs.js.map +0 -1
- package/lib/cjs/groq/index.js +0 -328
- package/lib/cjs/groq/index.js.map +0 -1
- package/lib/cjs/huggingface_ie.js +0 -201
- package/lib/cjs/huggingface_ie.js.map +0 -1
- package/lib/cjs/index.js +0 -32
- package/lib/cjs/index.js.map +0 -1
- package/lib/cjs/mistral/index.js +0 -176
- package/lib/cjs/mistral/index.js.map +0 -1
- package/lib/cjs/mistral/types.js +0 -83
- package/lib/cjs/mistral/types.js.map +0 -1
- package/lib/cjs/openai/azure_openai.js +0 -72
- package/lib/cjs/openai/azure_openai.js.map +0 -1
- package/lib/cjs/openai/index.js +0 -1135
- package/lib/cjs/openai/index.js.map +0 -1
- package/lib/cjs/openai/openai.js +0 -21
- package/lib/cjs/openai/openai.js.map +0 -1
- package/lib/cjs/openai/openai_compatible.js +0 -63
- package/lib/cjs/openai/openai_compatible.js.map +0 -1
- package/lib/cjs/openai/openai_format.js +0 -131
- package/lib/cjs/openai/openai_format.js.map +0 -1
- package/lib/cjs/package.json +0 -3
- package/lib/cjs/replicate.js +0 -275
- package/lib/cjs/replicate.js.map +0 -1
- package/lib/cjs/shared/claude-messages.js +0 -737
- package/lib/cjs/shared/claude-messages.js.map +0 -1
- package/lib/cjs/shared/claude-thinking.js +0 -60
- package/lib/cjs/shared/claude-thinking.js.map +0 -1
- package/lib/cjs/test-driver/TestErrorCompletionStream.js +0 -20
- package/lib/cjs/test-driver/TestErrorCompletionStream.js.map +0 -1
- package/lib/cjs/test-driver/TestValidationErrorCompletionStream.js +0 -24
- package/lib/cjs/test-driver/TestValidationErrorCompletionStream.js.map +0 -1
- package/lib/cjs/test-driver/index.js +0 -109
- package/lib/cjs/test-driver/index.js.map +0 -1
- package/lib/cjs/test-driver/utils.js +0 -30
- package/lib/cjs/test-driver/utils.js.map +0 -1
- package/lib/cjs/togetherai/index.js +0 -126
- package/lib/cjs/togetherai/index.js.map +0 -1
- package/lib/cjs/togetherai/interfaces.js +0 -3
- package/lib/cjs/togetherai/interfaces.js.map +0 -1
- package/lib/cjs/vertexai/debug.js +0 -12
- package/lib/cjs/vertexai/debug.js.map +0 -1
- package/lib/cjs/vertexai/embeddings/embeddings-image.js +0 -27
- package/lib/cjs/vertexai/embeddings/embeddings-image.js.map +0 -1
- package/lib/cjs/vertexai/embeddings/embeddings-text.js +0 -23
- package/lib/cjs/vertexai/embeddings/embeddings-text.js.map +0 -1
- package/lib/cjs/vertexai/index.js +0 -644
- package/lib/cjs/vertexai/index.js.map +0 -1
- package/lib/cjs/vertexai/models/claude.js +0 -72
- package/lib/cjs/vertexai/models/claude.js.map +0 -1
- package/lib/cjs/vertexai/models/gemini.js +0 -864
- package/lib/cjs/vertexai/models/gemini.js.map +0 -1
- package/lib/cjs/vertexai/models/imagen.js +0 -303
- package/lib/cjs/vertexai/models/imagen.js.map +0 -1
- package/lib/cjs/vertexai/models/llama.js +0 -183
- package/lib/cjs/vertexai/models/llama.js.map +0 -1
- package/lib/cjs/vertexai/models.js +0 -35
- package/lib/cjs/vertexai/models.js.map +0 -1
- package/lib/cjs/watsonx/index.js +0 -161
- package/lib/cjs/watsonx/index.js.map +0 -1
- package/lib/cjs/watsonx/interfaces.js +0 -3
- package/lib/cjs/xai/index.js +0 -65
- package/lib/cjs/xai/index.js.map +0 -1
- package/lib/esm/adobe/firefly.js +0 -116
- package/lib/esm/adobe/firefly.js.map +0 -1
- package/lib/esm/anthropic/index.js.map +0 -1
- package/lib/esm/azure/azure_foundry.js.map +0 -1
- package/lib/esm/bedrock/converse.js.map +0 -1
- package/lib/esm/bedrock/index.js.map +0 -1
- package/lib/esm/bedrock/nova-image-payload.js.map +0 -1
- package/lib/esm/bedrock/payloads.js.map +0 -1
- package/lib/esm/bedrock/s3.js.map +0 -1
- package/lib/esm/bedrock/twelvelabs.js.map +0 -1
- package/lib/esm/groq/index.js.map +0 -1
- package/lib/esm/huggingface_ie.js.map +0 -1
- package/lib/esm/index.js +0 -16
- package/lib/esm/index.js.map +0 -1
- package/lib/esm/mistral/index.js.map +0 -1
- package/lib/esm/mistral/types.js.map +0 -1
- package/lib/esm/openai/azure_openai.js.map +0 -1
- package/lib/esm/openai/index.js.map +0 -1
- package/lib/esm/openai/openai.js +0 -14
- package/lib/esm/openai/openai.js.map +0 -1
- package/lib/esm/openai/openai_compatible.js.map +0 -1
- package/lib/esm/openai/openai_format.js.map +0 -1
- package/lib/esm/replicate.js.map +0 -1
- package/lib/esm/shared/claude-messages.js.map +0 -1
- package/lib/esm/shared/claude-thinking.js.map +0 -1
- package/lib/esm/test-driver/TestErrorCompletionStream.js +0 -16
- package/lib/esm/test-driver/TestErrorCompletionStream.js.map +0 -1
- package/lib/esm/test-driver/TestValidationErrorCompletionStream.js.map +0 -1
- package/lib/esm/test-driver/index.js.map +0 -1
- package/lib/esm/test-driver/utils.js.map +0 -1
- package/lib/esm/togetherai/index.js +0 -122
- package/lib/esm/togetherai/index.js.map +0 -1
- package/lib/esm/togetherai/interfaces.js.map +0 -1
- package/lib/esm/vertexai/debug.js.map +0 -1
- package/lib/esm/vertexai/embeddings/embeddings-image.js +0 -24
- package/lib/esm/vertexai/embeddings/embeddings-image.js.map +0 -1
- package/lib/esm/vertexai/embeddings/embeddings-text.js +0 -20
- package/lib/esm/vertexai/embeddings/embeddings-text.js.map +0 -1
- package/lib/esm/vertexai/index.js.map +0 -1
- package/lib/esm/vertexai/models/claude.js.map +0 -1
- package/lib/esm/vertexai/models/gemini.js.map +0 -1
- package/lib/esm/vertexai/models/imagen.js.map +0 -1
- package/lib/esm/vertexai/models/llama.js.map +0 -1
- package/lib/esm/vertexai/models.js.map +0 -1
- package/lib/esm/watsonx/index.js.map +0 -1
- package/lib/esm/xai/index.js.map +0 -1
- package/lib/types/adobe/firefly.d.ts.map +0 -1
- package/lib/types/anthropic/index.d.ts.map +0 -1
- package/lib/types/azure/azure_foundry.d.ts.map +0 -1
- package/lib/types/bedrock/converse.d.ts.map +0 -1
- package/lib/types/bedrock/index.d.ts.map +0 -1
- package/lib/types/bedrock/nova-image-payload.d.ts.map +0 -1
- package/lib/types/bedrock/payloads.d.ts.map +0 -1
- package/lib/types/bedrock/s3.d.ts.map +0 -1
- package/lib/types/bedrock/twelvelabs.d.ts.map +0 -1
- package/lib/types/groq/index.d.ts.map +0 -1
- package/lib/types/huggingface_ie.d.ts.map +0 -1
- package/lib/types/index.d.ts +0 -16
- package/lib/types/index.d.ts.map +0 -1
- package/lib/types/mistral/index.d.ts.map +0 -1
- package/lib/types/mistral/types.d.ts.map +0 -1
- package/lib/types/openai/azure_openai.d.ts.map +0 -1
- package/lib/types/openai/index.d.ts.map +0 -1
- package/lib/types/openai/openai.d.ts.map +0 -1
- package/lib/types/openai/openai_compatible.d.ts.map +0 -1
- package/lib/types/openai/openai_format.d.ts.map +0 -1
- package/lib/types/replicate.d.ts.map +0 -1
- package/lib/types/shared/claude-messages.d.ts.map +0 -1
- package/lib/types/shared/claude-thinking.d.ts.map +0 -1
- package/lib/types/test-driver/TestErrorCompletionStream.d.ts.map +0 -1
- package/lib/types/test-driver/TestValidationErrorCompletionStream.d.ts.map +0 -1
- package/lib/types/test-driver/index.d.ts.map +0 -1
- package/lib/types/test-driver/utils.d.ts.map +0 -1
- package/lib/types/togetherai/index.d.ts +0 -23
- package/lib/types/togetherai/index.d.ts.map +0 -1
- package/lib/types/togetherai/interfaces.d.ts.map +0 -1
- package/lib/types/vertexai/debug.d.ts +0 -2
- package/lib/types/vertexai/debug.d.ts.map +0 -1
- package/lib/types/vertexai/embeddings/embeddings-image.d.ts +0 -11
- package/lib/types/vertexai/embeddings/embeddings-image.d.ts.map +0 -1
- package/lib/types/vertexai/embeddings/embeddings-text.d.ts +0 -10
- package/lib/types/vertexai/embeddings/embeddings-text.d.ts.map +0 -1
- package/lib/types/vertexai/index.d.ts.map +0 -1
- package/lib/types/vertexai/models/claude.d.ts.map +0 -1
- package/lib/types/vertexai/models/gemini.d.ts.map +0 -1
- package/lib/types/vertexai/models/imagen.d.ts.map +0 -1
- package/lib/types/vertexai/models/llama.d.ts.map +0 -1
- package/lib/types/vertexai/models.d.ts +0 -20
- package/lib/types/vertexai/models.d.ts.map +0 -1
- package/lib/types/watsonx/index.d.ts.map +0 -1
- package/lib/types/watsonx/interfaces.d.ts.map +0 -1
- package/lib/types/xai/index.d.ts.map +0 -1
- package/src/vertexai/embeddings/embeddings-image.ts +0 -52
- package/src/vertexai/embeddings/embeddings-text.ts +0 -54
- /package/lib/{esm/bedrock → bedrock}/payloads.js +0 -0
- /package/lib/{esm/mistral → mistral}/types.js +0 -0
- /package/lib/{esm/togetherai → togetherai}/interfaces.js +0 -0
- /package/lib/{types/watsonx → watsonx}/interfaces.d.ts +0 -0
- /package/lib/{esm/watsonx → watsonx}/interfaces.js +0 -0
|
@@ -1,16 +1,20 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { getConversationMeta, getModelCapabilities, incrementConversationTurn, LlumiverseError, ModelType, modelModalitiesToArray, normalizeEmbeddingsOptions, OPENAI_DEFAULT_EMBEDDING_MODEL, stripBase64ImagesFromConversation, stripHeartbeatsFromConversation, supportsToolUse, TrainingJobStatus, truncateLargeTextInConversation, unwrapConversationArray, } from '@llumiverse/core';
|
|
2
|
+
import { AbstractDriver } from '@llumiverse/core/driver';
|
|
2
3
|
import { APIConnectionError, APIConnectionTimeoutError, APIError, AuthenticationError, BadRequestError, ConflictError, ContentFilterFinishReasonError, InternalServerError, LengthFinishReasonError, NotFoundError, OpenAIError, PermissionDeniedError, RateLimitError, UnprocessableEntityError, } from 'openai/error';
|
|
3
|
-
import { formatOpenAILikeMultimodalPrompt } from
|
|
4
|
+
import { formatOpenAILikeMultimodalPrompt } from './openai_format.js';
|
|
4
5
|
// Helper function to convert string to CompletionResult[]
|
|
5
6
|
function textToCompletionResult(text) {
|
|
6
|
-
return text ? [{ type:
|
|
7
|
+
return text ? [{ type: 'text', value: text }] : [];
|
|
8
|
+
}
|
|
9
|
+
function hasNumericStatus(error) {
|
|
10
|
+
return error instanceof Error && typeof error.status === 'number';
|
|
7
11
|
}
|
|
8
12
|
function isOpenAIReasoningModel(model) {
|
|
9
13
|
const normalized = model.toLowerCase();
|
|
10
|
-
return normalized.includes(
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
+
return (normalized.includes('o1') ||
|
|
15
|
+
normalized.includes('o3') ||
|
|
16
|
+
normalized.includes('o4') ||
|
|
17
|
+
normalized.includes('gpt-5'));
|
|
14
18
|
}
|
|
15
19
|
function isGpt5ProModel(model) {
|
|
16
20
|
const modelName = model.toLowerCase().split('/').pop() ?? model.toLowerCase();
|
|
@@ -21,17 +25,17 @@ function openAIReasoningEffort(model, effort) {
|
|
|
21
25
|
return undefined;
|
|
22
26
|
}
|
|
23
27
|
if (isGpt5ProModel(model)) {
|
|
24
|
-
return
|
|
28
|
+
return 'high';
|
|
25
29
|
}
|
|
26
|
-
return effort ===
|
|
30
|
+
return effort === 'low' || effort === 'medium' || effort === 'high' ? effort : undefined;
|
|
27
31
|
}
|
|
28
32
|
//TODO: Do we need a list?, replace with if statements and modernize?
|
|
29
33
|
const supportFineTunning = new Set([
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
34
|
+
'gpt-3.5-turbo-1106',
|
|
35
|
+
'gpt-3.5-turbo-0613',
|
|
36
|
+
'babbage-002',
|
|
37
|
+
'davinci-002',
|
|
38
|
+
'gpt-4-0613',
|
|
35
39
|
]);
|
|
36
40
|
export class BaseOpenAIDriver extends AbstractDriver {
|
|
37
41
|
constructor(opts) {
|
|
@@ -44,8 +48,8 @@ export class BaseOpenAIDriver extends AbstractDriver {
|
|
|
44
48
|
// Collect all parts in order (text and images)
|
|
45
49
|
const allResults = extractCompletionResults(result.output);
|
|
46
50
|
if (allResults.length === 0 && !tools) {
|
|
47
|
-
this.logger.error({ result },
|
|
48
|
-
throw new Error(
|
|
51
|
+
this.logger.error({ result }, '[OpenAI] Response is not valid');
|
|
52
|
+
throw new Error('Response is not valid: no data');
|
|
49
53
|
}
|
|
50
54
|
return {
|
|
51
55
|
result: allResults,
|
|
@@ -56,14 +60,14 @@ export class BaseOpenAIDriver extends AbstractDriver {
|
|
|
56
60
|
}
|
|
57
61
|
async requestTextCompletionStream(prompt, options) {
|
|
58
62
|
if (options.model_options?._option_id !== undefined &&
|
|
59
|
-
options.model_options?._option_id !==
|
|
60
|
-
options.model_options?._option_id !==
|
|
61
|
-
options.model_options?._option_id !==
|
|
62
|
-
this.logger.debug({ options: options.model_options },
|
|
63
|
+
options.model_options?._option_id !== 'openai-text' &&
|
|
64
|
+
options.model_options?._option_id !== 'openai-thinking' &&
|
|
65
|
+
options.model_options?._option_id !== 'text-fallback') {
|
|
66
|
+
this.logger.debug({ options: options.model_options }, 'Unexpected option id');
|
|
63
67
|
}
|
|
64
68
|
// Include conversation history (same as non-streaming)
|
|
65
69
|
// Fix orphaned function_call items (can occur when agent is stopped mid-tool-execution)
|
|
66
|
-
let conversation = fixOrphanedToolUse(updateConversation(options.conversation, prompt));
|
|
70
|
+
let conversation = fixOrphanedToolResults(fixOrphanedToolUse(updateConversation(options.conversation, prompt)));
|
|
67
71
|
const toolDefs = getToolDefinitions(options.tools);
|
|
68
72
|
const useTools = toolDefs ? supportsToolUse(options.model, this.provider, true) : false;
|
|
69
73
|
// When no tools are provided but conversation contains function_call/function_call_output
|
|
@@ -73,15 +77,15 @@ export class BaseOpenAIDriver extends AbstractDriver {
|
|
|
73
77
|
}
|
|
74
78
|
convertRoles(prompt, options.model);
|
|
75
79
|
const model_options = options.model_options;
|
|
76
|
-
insert_image_detail(prompt, model_options?.image_detail ??
|
|
77
|
-
let parsedSchema
|
|
80
|
+
insert_image_detail(prompt, model_options?.image_detail ?? 'auto');
|
|
81
|
+
let parsedSchema;
|
|
78
82
|
let strictMode = false;
|
|
79
|
-
if (options.result_schema && supportsSchema(options.model)) {
|
|
83
|
+
if (options.result_schema && supportsSchema(options.model, this.provider)) {
|
|
80
84
|
try {
|
|
81
85
|
parsedSchema = openAISchemaFormat(options.result_schema);
|
|
82
86
|
strictMode = true;
|
|
83
87
|
}
|
|
84
|
-
catch
|
|
88
|
+
catch {
|
|
85
89
|
parsedSchema = limitedSchemaFormat(options.result_schema);
|
|
86
90
|
strictMode = false;
|
|
87
91
|
}
|
|
@@ -98,43 +102,46 @@ export class BaseOpenAIDriver extends AbstractDriver {
|
|
|
98
102
|
top_p: isReasoningModel ? undefined : model_options?.top_p,
|
|
99
103
|
max_output_tokens: model_options?.max_tokens,
|
|
100
104
|
tools: useTools ? toolDefs : undefined,
|
|
101
|
-
text: parsedSchema
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
105
|
+
text: parsedSchema
|
|
106
|
+
? {
|
|
107
|
+
format: {
|
|
108
|
+
type: 'json_schema',
|
|
109
|
+
name: 'format_output',
|
|
110
|
+
schema: parsedSchema,
|
|
111
|
+
strict: strictMode,
|
|
112
|
+
},
|
|
107
113
|
}
|
|
108
|
-
|
|
114
|
+
: undefined,
|
|
109
115
|
});
|
|
110
116
|
return mapResponseStream(stream);
|
|
111
117
|
}
|
|
112
118
|
async requestTextCompletion(prompt, options) {
|
|
113
119
|
if (options.model_options?._option_id !== undefined &&
|
|
114
|
-
options.model_options?._option_id !==
|
|
115
|
-
options.model_options?._option_id !==
|
|
116
|
-
|
|
120
|
+
options.model_options?._option_id !== 'openai-text' &&
|
|
121
|
+
options.model_options?._option_id !== 'openai-thinking' &&
|
|
122
|
+
options.model_options?._option_id !== 'text-fallback') {
|
|
123
|
+
this.logger.debug({ options: options.model_options }, 'Unexpected option id');
|
|
117
124
|
}
|
|
118
125
|
convertRoles(prompt, options.model);
|
|
119
126
|
const model_options = options.model_options;
|
|
120
|
-
insert_image_detail(prompt, model_options?.image_detail ??
|
|
127
|
+
insert_image_detail(prompt, model_options?.image_detail ?? 'auto');
|
|
121
128
|
const toolDefs = getToolDefinitions(options.tools);
|
|
122
129
|
const useTools = toolDefs ? supportsToolUse(options.model, this.provider) : false;
|
|
123
130
|
// Fix orphaned function_call items (can occur when agent is stopped mid-tool-execution)
|
|
124
|
-
let conversation = fixOrphanedToolUse(updateConversation(options.conversation, prompt));
|
|
131
|
+
let conversation = fixOrphanedToolResults(fixOrphanedToolUse(updateConversation(options.conversation, prompt)));
|
|
125
132
|
// When no tools are provided but conversation contains function_call/function_call_output
|
|
126
133
|
// items (e.g. checkpoint summary calls), convert them to text to avoid API errors
|
|
127
134
|
if (!useTools) {
|
|
128
135
|
conversation = convertOpenAIFunctionItemsToText(conversation);
|
|
129
136
|
}
|
|
130
|
-
let parsedSchema
|
|
137
|
+
let parsedSchema;
|
|
131
138
|
let strictMode = false;
|
|
132
|
-
if (options.result_schema && supportsSchema(options.model)) {
|
|
139
|
+
if (options.result_schema && supportsSchema(options.model, this.provider)) {
|
|
133
140
|
try {
|
|
134
141
|
parsedSchema = openAISchemaFormat(options.result_schema);
|
|
135
142
|
strictMode = true;
|
|
136
143
|
}
|
|
137
|
-
catch
|
|
144
|
+
catch {
|
|
138
145
|
parsedSchema = limitedSchemaFormat(options.result_schema);
|
|
139
146
|
strictMode = false;
|
|
140
147
|
}
|
|
@@ -151,14 +158,16 @@ export class BaseOpenAIDriver extends AbstractDriver {
|
|
|
151
158
|
top_p: isReasoningModel ? undefined : model_options?.top_p,
|
|
152
159
|
max_output_tokens: model_options?.max_tokens, //TODO: use max_tokens for older models, currently relying on OpenAI to handle it
|
|
153
160
|
tools: useTools ? toolDefs : undefined,
|
|
154
|
-
text: parsedSchema
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
161
|
+
text: parsedSchema
|
|
162
|
+
? {
|
|
163
|
+
format: {
|
|
164
|
+
type: 'json_schema',
|
|
165
|
+
name: 'format_output',
|
|
166
|
+
schema: parsedSchema,
|
|
167
|
+
strict: strictMode,
|
|
168
|
+
},
|
|
160
169
|
}
|
|
161
|
-
|
|
170
|
+
: undefined,
|
|
162
171
|
});
|
|
163
172
|
const completion = this.extractDataFromResponse(options, res);
|
|
164
173
|
if (options.include_original_response) {
|
|
@@ -172,7 +181,7 @@ export class BaseOpenAIDriver extends AbstractDriver {
|
|
|
172
181
|
const stripOptions = {
|
|
173
182
|
keepForTurns: options.stripImagesAfterTurns ?? Infinity,
|
|
174
183
|
currentTurn,
|
|
175
|
-
textMaxTokens: options.stripTextMaxTokens
|
|
184
|
+
textMaxTokens: options.stripTextMaxTokens,
|
|
176
185
|
};
|
|
177
186
|
let processedConversation = stripBase64ImagesFromConversation(conversation, stripOptions);
|
|
178
187
|
// Truncate large text content if configured
|
|
@@ -187,13 +196,12 @@ export class BaseOpenAIDriver extends AbstractDriver {
|
|
|
187
196
|
}
|
|
188
197
|
canStream(_options) {
|
|
189
198
|
// Image generation models don't support streaming
|
|
190
|
-
if (_options.model.includes(
|
|
191
|
-
|
|
192
|
-
|
|
199
|
+
if (_options.model.includes('dall-e') ||
|
|
200
|
+
_options.model.includes('gpt-image') ||
|
|
201
|
+
_options.model.includes('chatgpt-image')) {
|
|
193
202
|
return Promise.resolve(false);
|
|
194
203
|
}
|
|
195
|
-
if (_options.model.includes(
|
|
196
|
-
&& !(_options.model.includes("mini") || _options.model.includes("preview"))) {
|
|
204
|
+
if (_options.model.includes('o1') && !(_options.model.includes('mini') || _options.model.includes('preview'))) {
|
|
197
205
|
//o1 full does not support streaming
|
|
198
206
|
//TODO: Update when OpenAI adds support for streaming, last check 16/02/2025
|
|
199
207
|
return Promise.resolve(false);
|
|
@@ -213,6 +221,7 @@ export class BaseOpenAIDriver extends AbstractDriver {
|
|
|
213
221
|
// Add assistant message as EasyInputMessage
|
|
214
222
|
if (textContent) {
|
|
215
223
|
const assistantMessage = {
|
|
224
|
+
type: 'message',
|
|
216
225
|
role: 'assistant',
|
|
217
226
|
content: textContent,
|
|
218
227
|
};
|
|
@@ -220,7 +229,7 @@ export class BaseOpenAIDriver extends AbstractDriver {
|
|
|
220
229
|
}
|
|
221
230
|
// Add function calls as separate items (Response API format)
|
|
222
231
|
if (toolUse && toolUse.length > 0) {
|
|
223
|
-
const functionCalls = toolUse.map(t => ({
|
|
232
|
+
const functionCalls = toolUse.map((t) => ({
|
|
224
233
|
type: 'function_call',
|
|
225
234
|
call_id: t.id,
|
|
226
235
|
name: t.tool_name,
|
|
@@ -235,7 +244,7 @@ export class BaseOpenAIDriver extends AbstractDriver {
|
|
|
235
244
|
const stripOptions = {
|
|
236
245
|
keepForTurns: options.stripImagesAfterTurns ?? Infinity,
|
|
237
246
|
currentTurn,
|
|
238
|
-
textMaxTokens: options.stripTextMaxTokens
|
|
247
|
+
textMaxTokens: options.stripTextMaxTokens,
|
|
239
248
|
};
|
|
240
249
|
let processedConversation = stripBase64ImagesFromConversation(conversation, stripOptions);
|
|
241
250
|
processedConversation = truncateLargeTextInConversation(processedConversation, stripOptions);
|
|
@@ -246,24 +255,24 @@ export class BaseOpenAIDriver extends AbstractDriver {
|
|
|
246
255
|
return processedConversation;
|
|
247
256
|
}
|
|
248
257
|
createTrainingPrompt(options) {
|
|
249
|
-
if (options.model.includes(
|
|
258
|
+
if (options.model.includes('gpt')) {
|
|
250
259
|
return super.createTrainingPrompt(options);
|
|
251
260
|
}
|
|
252
261
|
else {
|
|
253
262
|
// babbage, davinci not yet implemented
|
|
254
|
-
throw new Error(
|
|
263
|
+
throw new Error(`Unsupported model for training: ${options.model}`);
|
|
255
264
|
}
|
|
256
265
|
}
|
|
257
266
|
async startTraining(dataset, options) {
|
|
258
267
|
const url = await dataset.getURL();
|
|
259
268
|
const file = await this.service.files.create({
|
|
260
269
|
file: await fetch(url),
|
|
261
|
-
purpose:
|
|
270
|
+
purpose: 'fine-tune',
|
|
262
271
|
});
|
|
263
272
|
const job = await this.service.fineTuning.jobs.create({
|
|
264
273
|
training_file: file.id,
|
|
265
274
|
model: options.model,
|
|
266
|
-
hyperparameters: options.params
|
|
275
|
+
hyperparameters: options.params,
|
|
267
276
|
});
|
|
268
277
|
return jobInfo(job);
|
|
269
278
|
}
|
|
@@ -281,7 +290,7 @@ export class BaseOpenAIDriver extends AbstractDriver {
|
|
|
281
290
|
await this.service.models.list();
|
|
282
291
|
return true;
|
|
283
292
|
}
|
|
284
|
-
catch
|
|
293
|
+
catch {
|
|
285
294
|
return false;
|
|
286
295
|
}
|
|
287
296
|
}
|
|
@@ -295,22 +304,36 @@ export class BaseOpenAIDriver extends AbstractDriver {
|
|
|
295
304
|
let result = (await this.service.models.list()).data;
|
|
296
305
|
//Some of these use the completions API instead of the chat completions API.
|
|
297
306
|
//Others are for non-text input modalities. Therefore common to both.
|
|
298
|
-
const wordBlacklist = [
|
|
299
|
-
|
|
307
|
+
const wordBlacklist = [
|
|
308
|
+
'embed',
|
|
309
|
+
'whisper',
|
|
310
|
+
'transcribe',
|
|
311
|
+
'audio',
|
|
312
|
+
'moderation',
|
|
313
|
+
'tts',
|
|
314
|
+
'realtime',
|
|
315
|
+
'babbage',
|
|
316
|
+
'davinci',
|
|
317
|
+
'codex',
|
|
318
|
+
'o1-pro',
|
|
319
|
+
'computer-use',
|
|
320
|
+
'sora',
|
|
321
|
+
];
|
|
300
322
|
//OpenAI has very little information, filtering based on name.
|
|
301
323
|
result = result.filter((m) => {
|
|
302
324
|
return !wordBlacklist.some((word) => m.id.includes(word));
|
|
303
325
|
});
|
|
304
326
|
const models = filter ? result.filter(filter) : result;
|
|
305
|
-
const aiModels = models
|
|
306
|
-
|
|
327
|
+
const aiModels = models
|
|
328
|
+
.map((m) => {
|
|
329
|
+
const modelCapability = getModelCapabilities(m.id, this.provider);
|
|
307
330
|
let owner = m.owned_by;
|
|
308
|
-
if (owner
|
|
309
|
-
owner =
|
|
331
|
+
if (owner === 'system') {
|
|
332
|
+
owner = 'openai';
|
|
310
333
|
}
|
|
311
334
|
// Determine model type based on capabilities
|
|
312
335
|
let modelType = ModelType.Text;
|
|
313
|
-
if (m.id.includes(
|
|
336
|
+
if (m.id.includes('dall-e') || m.id.includes('gpt-image')) {
|
|
314
337
|
modelType = ModelType.Image;
|
|
315
338
|
}
|
|
316
339
|
return {
|
|
@@ -323,34 +346,60 @@ export class BaseOpenAIDriver extends AbstractDriver {
|
|
|
323
346
|
output_modalities: modelModalitiesToArray(modelCapability.output),
|
|
324
347
|
tool_support: modelCapability.tool_support,
|
|
325
348
|
};
|
|
326
|
-
})
|
|
349
|
+
})
|
|
350
|
+
.sort((a, b) => a.id.localeCompare(b.id));
|
|
327
351
|
return aiModels;
|
|
328
352
|
}
|
|
329
|
-
async generateEmbeddings(
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
input: text,
|
|
338
|
-
model: model,
|
|
353
|
+
async generateEmbeddings(options) {
|
|
354
|
+
const normalized = normalizeEmbeddingsOptions(options);
|
|
355
|
+
const model = normalized.model ?? OPENAI_DEFAULT_EMBEDDING_MODEL;
|
|
356
|
+
const texts = normalized.inputs.map((input) => {
|
|
357
|
+
if (input.type !== 'text') {
|
|
358
|
+
throw new Error(`Provider 'openai' does not support '${input.type}' embeddings; only 'text' is supported.`);
|
|
359
|
+
}
|
|
360
|
+
return input.text;
|
|
339
361
|
});
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
362
|
+
try {
|
|
363
|
+
const res = await this.service.embeddings.create({
|
|
364
|
+
input: texts,
|
|
365
|
+
model,
|
|
366
|
+
...(normalized.dimensions ? { dimensions: normalized.dimensions } : {}),
|
|
367
|
+
encoding_format: 'float',
|
|
368
|
+
});
|
|
369
|
+
// OpenAI does not guarantee data is returned in the same order as the input,
|
|
370
|
+
// but does return a stable `index` per item. Sort by index to align with inputs.
|
|
371
|
+
const ordered = [...res.data].sort((a, b) => a.index - b.index);
|
|
372
|
+
const items = ordered.map((entry) => {
|
|
373
|
+
if (!entry.embedding || entry.embedding.length === 0) {
|
|
374
|
+
throw new Error(`OpenAI embedding empty for input index ${entry.index}`);
|
|
375
|
+
}
|
|
376
|
+
return { outputs: [{ values: entry.embedding, modality: 'text' }] };
|
|
377
|
+
});
|
|
378
|
+
const usage = res.usage
|
|
379
|
+
? { input_tokens: res.usage.prompt_tokens, input_text_tokens: res.usage.prompt_tokens }
|
|
380
|
+
: undefined;
|
|
381
|
+
return { model, results: items, usage };
|
|
382
|
+
}
|
|
383
|
+
catch (error) {
|
|
384
|
+
if (LlumiverseError.isLlumiverseError(error))
|
|
385
|
+
throw error;
|
|
386
|
+
if (error instanceof Error && !hasNumericStatus(error))
|
|
387
|
+
throw error;
|
|
388
|
+
throw this.formatLlumiverseError(error, {
|
|
389
|
+
provider: this.provider,
|
|
390
|
+
model,
|
|
391
|
+
operation: 'execute',
|
|
392
|
+
});
|
|
343
393
|
}
|
|
344
|
-
return { values: embeddings, model };
|
|
345
394
|
}
|
|
346
|
-
imageModels = [
|
|
395
|
+
imageModels = ['dall-e', 'gpt-image', 'chatgpt-image'];
|
|
347
396
|
/**
|
|
348
397
|
* Determine if a model is specifically an image generation model (not conversational image model)
|
|
349
398
|
*/
|
|
350
399
|
isImageModel(model) {
|
|
351
400
|
// DALL-E models are standalone image generation
|
|
352
401
|
// gpt-image models can generate images in conversations, not standalone
|
|
353
|
-
return this.imageModels.some(imageModel => model.includes(imageModel));
|
|
402
|
+
return this.imageModels.some((imageModel) => model.includes(imageModel));
|
|
354
403
|
}
|
|
355
404
|
/**
|
|
356
405
|
* Request image generation from standalone Images API
|
|
@@ -360,16 +409,16 @@ export class BaseOpenAIDriver extends AbstractDriver {
|
|
|
360
409
|
this.logger.debug(`[${this.provider}] Generating image with model ${options.model}`);
|
|
361
410
|
const model_options = options.model_options;
|
|
362
411
|
// Extract prompt text from ResponseInputItem[]
|
|
363
|
-
let promptText =
|
|
412
|
+
let promptText = '';
|
|
364
413
|
for (const item of prompt) {
|
|
365
414
|
if ('content' in item && typeof item.content === 'string') {
|
|
366
|
-
promptText += item.content
|
|
415
|
+
promptText += `${item.content}\\n`;
|
|
367
416
|
}
|
|
368
417
|
else if ('content' in item && Array.isArray(item.content)) {
|
|
369
418
|
// Extract text from content array
|
|
370
419
|
for (const part of item.content) {
|
|
371
420
|
if ('type' in part && part.type === 'input_text' && 'text' in part) {
|
|
372
|
-
promptText += part.text
|
|
421
|
+
promptText += `${part.text}\\n`;
|
|
373
422
|
}
|
|
374
423
|
}
|
|
375
424
|
}
|
|
@@ -379,15 +428,15 @@ export class BaseOpenAIDriver extends AbstractDriver {
|
|
|
379
428
|
const generateParams = {
|
|
380
429
|
model: options.model,
|
|
381
430
|
prompt: promptText,
|
|
382
|
-
size: model_options?.size ||
|
|
431
|
+
size: model_options?.size || '1024x1024',
|
|
383
432
|
};
|
|
384
433
|
// Add DALL-E specific options
|
|
385
|
-
if (options.model.includes(
|
|
434
|
+
if (options.model.includes('dall-e') || model_options?._option_id === 'openai-dalle') {
|
|
386
435
|
const dalleOptions = model_options;
|
|
387
436
|
generateParams.n = dalleOptions?.n || 1;
|
|
388
|
-
generateParams.response_format = dalleOptions?.response_format ||
|
|
389
|
-
if (options.model.includes(
|
|
390
|
-
generateParams.quality = dalleOptions?.image_quality ||
|
|
437
|
+
generateParams.response_format = dalleOptions?.response_format || 'b64_json';
|
|
438
|
+
if (options.model.includes('dall-e-3')) {
|
|
439
|
+
generateParams.quality = dalleOptions?.image_quality || 'standard';
|
|
391
440
|
if (dalleOptions?.style) {
|
|
392
441
|
generateParams.style = dalleOptions.style;
|
|
393
442
|
}
|
|
@@ -415,23 +464,27 @@ export class BaseOpenAIDriver extends AbstractDriver {
|
|
|
415
464
|
continue;
|
|
416
465
|
}
|
|
417
466
|
results.push({
|
|
418
|
-
type:
|
|
419
|
-
value: imageValue
|
|
467
|
+
type: 'image',
|
|
468
|
+
value: imageValue,
|
|
420
469
|
});
|
|
421
470
|
}
|
|
422
471
|
}
|
|
423
472
|
return {
|
|
424
|
-
result: results
|
|
473
|
+
result: results,
|
|
425
474
|
};
|
|
426
475
|
}
|
|
427
476
|
catch (error) {
|
|
428
477
|
this.logger.error({ error }, `[${this.provider}] Image generation failed`);
|
|
478
|
+
const generationError = error instanceof Error ? error : new Error(String(error));
|
|
479
|
+
const errorCode = error?.code === 'content_policy_violation'
|
|
480
|
+
? 'content_policy_violation'
|
|
481
|
+
: 'validation_error';
|
|
429
482
|
return {
|
|
430
483
|
result: [],
|
|
431
484
|
error: {
|
|
432
|
-
message:
|
|
433
|
-
code:
|
|
434
|
-
}
|
|
485
|
+
message: generationError.message,
|
|
486
|
+
code: errorCode,
|
|
487
|
+
},
|
|
435
488
|
};
|
|
436
489
|
}
|
|
437
490
|
}
|
|
@@ -512,9 +565,7 @@ export class BaseOpenAIDriver extends AbstractDriver {
|
|
|
512
565
|
* Type guard to check if error is an OpenAI API error or OpenAI-specific error.
|
|
513
566
|
*/
|
|
514
567
|
isOpenAIApiError(error) {
|
|
515
|
-
return (error !== null &&
|
|
516
|
-
typeof error === 'object' &&
|
|
517
|
-
(error instanceof APIError || error instanceof OpenAIError));
|
|
568
|
+
return (error !== null && typeof error === 'object' && (error instanceof APIError || error instanceof OpenAIError));
|
|
518
569
|
}
|
|
519
570
|
/**
|
|
520
571
|
* Determine if an OpenAI API error is retryable.
|
|
@@ -591,7 +642,7 @@ export class BaseOpenAIDriver extends AbstractDriver {
|
|
|
591
642
|
return false;
|
|
592
643
|
if (errorCode === 'invalid_model')
|
|
593
644
|
return false;
|
|
594
|
-
if (errorCode.includes('invalid_'))
|
|
645
|
+
if (typeof errorCode === 'string' && errorCode.includes('invalid_'))
|
|
595
646
|
return false;
|
|
596
647
|
}
|
|
597
648
|
// Check error type
|
|
@@ -637,7 +688,9 @@ function jobInfo(job) {
|
|
|
637
688
|
}
|
|
638
689
|
else if (jobStatus === 'failed') {
|
|
639
690
|
status = TrainingJobStatus.failed;
|
|
640
|
-
details = job.error
|
|
691
|
+
details = job.error
|
|
692
|
+
? `${job.error.code} - ${job.error.message} ${job.error.param ? ` [${job.error.param}]` : ''}`
|
|
693
|
+
: 'error';
|
|
641
694
|
}
|
|
642
695
|
else if (jobStatus === 'cancelled') {
|
|
643
696
|
status = TrainingJobStatus.cancelled;
|
|
@@ -650,19 +703,20 @@ function jobInfo(job) {
|
|
|
650
703
|
id: job.id,
|
|
651
704
|
model: job.fine_tuned_model || undefined,
|
|
652
705
|
status,
|
|
653
|
-
details
|
|
706
|
+
details,
|
|
654
707
|
};
|
|
655
708
|
}
|
|
656
709
|
function mapUsage(usage) {
|
|
657
710
|
if (!usage) {
|
|
658
711
|
return undefined;
|
|
659
712
|
}
|
|
713
|
+
const cachedTokens = usage.input_tokens_details?.cached_tokens ?? usage.prompt_tokens_details?.cached_tokens ?? usage.cached_tokens;
|
|
660
714
|
return {
|
|
661
715
|
prompt: usage.input_tokens,
|
|
662
716
|
result: usage.output_tokens,
|
|
663
717
|
total: usage.total_tokens,
|
|
664
|
-
prompt_cached:
|
|
665
|
-
prompt_new: usage.input_tokens - (
|
|
718
|
+
prompt_cached: cachedTokens ?? undefined,
|
|
719
|
+
prompt_new: usage.input_tokens - (cachedTokens ?? 0),
|
|
666
720
|
};
|
|
667
721
|
}
|
|
668
722
|
function completionResultsToText(completionResults) {
|
|
@@ -670,7 +724,7 @@ function completionResultsToText(completionResults) {
|
|
|
670
724
|
return '';
|
|
671
725
|
}
|
|
672
726
|
return completionResults
|
|
673
|
-
.map(r => {
|
|
727
|
+
.map((r) => {
|
|
674
728
|
switch (r.type) {
|
|
675
729
|
case 'text':
|
|
676
730
|
return r.value;
|
|
@@ -679,8 +733,10 @@ function completionResultsToText(completionResults) {
|
|
|
679
733
|
case 'image':
|
|
680
734
|
// Skip images in conversation - they're in the result
|
|
681
735
|
return '';
|
|
682
|
-
default:
|
|
683
|
-
|
|
736
|
+
default: {
|
|
737
|
+
const _exhaustive = r;
|
|
738
|
+
return String(_exhaustive);
|
|
739
|
+
}
|
|
684
740
|
}
|
|
685
741
|
})
|
|
686
742
|
.join('');
|
|
@@ -691,6 +747,7 @@ function createAssistantMessageFromCompletion(completion) {
|
|
|
691
747
|
// Add assistant text message if present
|
|
692
748
|
if (textContent) {
|
|
693
749
|
const assistantMessage = {
|
|
750
|
+
type: 'message',
|
|
694
751
|
role: 'assistant',
|
|
695
752
|
content: textContent,
|
|
696
753
|
};
|
|
@@ -703,9 +760,7 @@ function createAssistantMessageFromCompletion(completion) {
|
|
|
703
760
|
type: 'function_call',
|
|
704
761
|
call_id: t.id,
|
|
705
762
|
name: t.tool_name,
|
|
706
|
-
arguments: typeof t.tool_input === 'string'
|
|
707
|
-
? t.tool_input
|
|
708
|
-
: JSON.stringify(t.tool_input ?? {}),
|
|
763
|
+
arguments: typeof t.tool_input === 'string' ? t.tool_input : JSON.stringify(t.tool_input ?? {}),
|
|
709
764
|
};
|
|
710
765
|
result.push(functionCall);
|
|
711
766
|
}
|
|
@@ -716,6 +771,8 @@ export function mapResponseStream(stream) {
|
|
|
716
771
|
const toolCallMetadata = new Map();
|
|
717
772
|
return {
|
|
718
773
|
async *[Symbol.asyncIterator]() {
|
|
774
|
+
let hasTextDeltas = false;
|
|
775
|
+
let refusalText = '';
|
|
719
776
|
for await (const event of stream) {
|
|
720
777
|
if (event.type === 'response.output_item.added' && event.item.type === 'function_call') {
|
|
721
778
|
const syntheticId = `tool_${event.output_index}`;
|
|
@@ -766,13 +823,34 @@ export function mapResponseStream(stream) {
|
|
|
766
823
|
}
|
|
767
824
|
}
|
|
768
825
|
else if (event.type === 'response.output_text.delta') {
|
|
826
|
+
hasTextDeltas = true;
|
|
769
827
|
yield {
|
|
770
828
|
result: textToCompletionResult(event.delta),
|
|
771
829
|
};
|
|
772
830
|
}
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
831
|
+
else if (event.type === 'response.output_text.done') {
|
|
832
|
+
// Fallback: some models (e.g. gpt-5 with json_schema structured output) buffer
|
|
833
|
+
// the entire output and never emit delta events — only the done event with the
|
|
834
|
+
// full text. Emit it here only when no deltas arrived to avoid duplication.
|
|
835
|
+
if (!hasTextDeltas && event.text) {
|
|
836
|
+
yield {
|
|
837
|
+
result: textToCompletionResult(event.text),
|
|
838
|
+
};
|
|
839
|
+
}
|
|
840
|
+
}
|
|
841
|
+
else if (event.type === 'response.refusal.delta') {
|
|
842
|
+
refusalText += event.delta;
|
|
843
|
+
}
|
|
844
|
+
else if (event.type === 'response.refusal.done') {
|
|
845
|
+
throw new Error(`[OpenAI] Model refused: ${event.refusal || refusalText}`);
|
|
846
|
+
}
|
|
847
|
+
else if (event.type === 'response.error') {
|
|
848
|
+
const errEvent = event;
|
|
849
|
+
throw new Error(`[OpenAI Responses API] ${errEvent.message}${errEvent.code ? ` (${errEvent.code})` : ''}`);
|
|
850
|
+
}
|
|
851
|
+
else if (event.type === 'response.completed' ||
|
|
852
|
+
event.type === 'response.incomplete' ||
|
|
853
|
+
event.type === 'response.failed') {
|
|
776
854
|
const finalTools = collectTools(event.response.output);
|
|
777
855
|
yield {
|
|
778
856
|
result: [],
|
|
@@ -781,11 +859,11 @@ export function mapResponseStream(stream) {
|
|
|
781
859
|
};
|
|
782
860
|
}
|
|
783
861
|
}
|
|
784
|
-
}
|
|
862
|
+
},
|
|
785
863
|
};
|
|
786
864
|
}
|
|
787
865
|
function insert_image_detail(items, detail_level) {
|
|
788
|
-
if (detail_level ===
|
|
866
|
+
if (detail_level === 'auto' || detail_level === 'low' || detail_level === 'high') {
|
|
789
867
|
for (const item of items) {
|
|
790
868
|
// Check if it's an EasyInputMessage or Message with content array
|
|
791
869
|
if ('role' in item && 'content' in item && item.role !== 'assistant') {
|
|
@@ -804,8 +882,8 @@ function insert_image_detail(items, detail_level) {
|
|
|
804
882
|
}
|
|
805
883
|
function convertRoles(items, model) {
|
|
806
884
|
//New openai models use developer role instead of system
|
|
807
|
-
if (model.includes(
|
|
808
|
-
if (model.includes(
|
|
885
|
+
if (model.includes('o1') || model.includes('o3')) {
|
|
886
|
+
if (model.includes('o1-mini') || model.includes('o1-preview')) {
|
|
809
887
|
//o1-mini and o1-preview support neither system nor developer
|
|
810
888
|
for (const item of items) {
|
|
811
889
|
if ('role' in item && item.role === 'system') {
|
|
@@ -826,12 +904,12 @@ function convertRoles(items, model) {
|
|
|
826
904
|
}
|
|
827
905
|
//Structured output support is typically aligned with tool use support
|
|
828
906
|
//Not true for realtime models, which do not support structured output, but do support tool use.
|
|
829
|
-
function supportsSchema(model) {
|
|
830
|
-
const realtimeModel = model.includes(
|
|
907
|
+
function supportsSchema(model, provider) {
|
|
908
|
+
const realtimeModel = model.includes('realtime');
|
|
831
909
|
if (realtimeModel) {
|
|
832
910
|
return false;
|
|
833
911
|
}
|
|
834
|
-
return supportsToolUse(model,
|
|
912
|
+
return supportsToolUse(model, provider);
|
|
835
913
|
}
|
|
836
914
|
/**
|
|
837
915
|
* Converts function_call and function_call_output items to text messages in OpenAI conversation.
|
|
@@ -839,17 +917,17 @@ function supportsSchema(model) {
|
|
|
839
917
|
* tools to be defined in the API request.
|
|
840
918
|
*/
|
|
841
919
|
export function convertOpenAIFunctionItemsToText(items) {
|
|
842
|
-
const hasFunctionItems = items.some(item => {
|
|
920
|
+
const hasFunctionItems = items.some((item) => {
|
|
843
921
|
const type = item.type;
|
|
844
922
|
return type === 'function_call' || type === 'function_call_output';
|
|
845
923
|
});
|
|
846
924
|
if (!hasFunctionItems)
|
|
847
925
|
return items;
|
|
848
|
-
return items.map(item => {
|
|
926
|
+
return items.map((item) => {
|
|
849
927
|
const typed = item;
|
|
850
928
|
if (typed.type === 'function_call') {
|
|
851
929
|
const argsStr = typed.arguments || '';
|
|
852
|
-
const truncated = argsStr.length > 500 ? argsStr.substring(0, 500)
|
|
930
|
+
const truncated = argsStr.length > 500 ? `${argsStr.substring(0, 500)}...` : argsStr;
|
|
853
931
|
return {
|
|
854
932
|
role: 'assistant',
|
|
855
933
|
content: `[Tool call: ${typed.name}(${truncated})]`,
|
|
@@ -857,7 +935,7 @@ export function convertOpenAIFunctionItemsToText(items) {
|
|
|
857
935
|
}
|
|
858
936
|
if (typed.type === 'function_call_output') {
|
|
859
937
|
const output = typed.output || 'No output';
|
|
860
|
-
const truncated = output.length > 500 ? output.substring(0, 500)
|
|
938
|
+
const truncated = output.length > 500 ? `${output.substring(0, 500)}...` : output;
|
|
861
939
|
return {
|
|
862
940
|
role: 'user',
|
|
863
941
|
content: `[Tool result: ${truncated}]`,
|
|
@@ -870,7 +948,7 @@ function getToolDefinitions(tools) {
|
|
|
870
948
|
return tools ? tools.map(getToolDefinition) : undefined;
|
|
871
949
|
}
|
|
872
950
|
function getToolDefinition(toolDef) {
|
|
873
|
-
let parsedSchema
|
|
951
|
+
let parsedSchema;
|
|
874
952
|
let strictMode = false;
|
|
875
953
|
if (toolDef.input_schema) {
|
|
876
954
|
try {
|
|
@@ -878,14 +956,14 @@ function getToolDefinition(toolDef) {
|
|
|
878
956
|
parsedSchema = openAISchemaFormat(toolDef.input_schema);
|
|
879
957
|
strictMode = true;
|
|
880
958
|
}
|
|
881
|
-
catch
|
|
959
|
+
catch {
|
|
882
960
|
//TODO: type assertion here is not safe, does not work with satisfies
|
|
883
961
|
parsedSchema = limitedSchemaFormat(toolDef.input_schema);
|
|
884
962
|
strictMode = false;
|
|
885
963
|
}
|
|
886
964
|
}
|
|
887
965
|
return {
|
|
888
|
-
type:
|
|
966
|
+
type: 'function',
|
|
889
967
|
name: toolDef.name,
|
|
890
968
|
description: toolDef.description,
|
|
891
969
|
parameters: parsedSchema ?? null,
|
|
@@ -941,8 +1019,8 @@ function extractCompletionResults(output) {
|
|
|
941
1019
|
for (const part of item.content) {
|
|
942
1020
|
if (part.type === 'output_text' && part.text) {
|
|
943
1021
|
results.push({
|
|
944
|
-
type:
|
|
945
|
-
value: part.text
|
|
1022
|
+
type: 'text',
|
|
1023
|
+
value: part.text,
|
|
946
1024
|
});
|
|
947
1025
|
}
|
|
948
1026
|
}
|
|
@@ -951,12 +1029,10 @@ function extractCompletionResults(output) {
|
|
|
951
1029
|
// GPT-image models return base64 encoded images in result field
|
|
952
1030
|
const base64Data = item.result;
|
|
953
1031
|
// Format as data URL for consistency with other image outputs
|
|
954
|
-
const imageUrl = base64Data.startsWith('data:')
|
|
955
|
-
? base64Data
|
|
956
|
-
: `data:image/png;base64,${base64Data}`;
|
|
1032
|
+
const imageUrl = base64Data.startsWith('data:') ? base64Data : `data:image/png;base64,${base64Data}`;
|
|
957
1033
|
results.push({
|
|
958
|
-
type:
|
|
959
|
-
value: imageUrl
|
|
1034
|
+
type: 'image',
|
|
1035
|
+
value: imageUrl,
|
|
960
1036
|
});
|
|
961
1037
|
}
|
|
962
1038
|
}
|
|
@@ -999,13 +1075,13 @@ function limitedSchemaFormat(schema) {
|
|
|
999
1075
|
//For strict mode true
|
|
1000
1076
|
function openAISchemaFormat(schema, nesting = 0) {
|
|
1001
1077
|
if (nesting > 5) {
|
|
1002
|
-
throw new Error(
|
|
1078
|
+
throw new Error('OpenAI schema nesting too deep');
|
|
1003
1079
|
}
|
|
1004
1080
|
const formattedSchema = { ...schema };
|
|
1005
1081
|
// Defaults not supported
|
|
1006
1082
|
delete formattedSchema.default;
|
|
1007
1083
|
// Additional properties not supported, required to be set.
|
|
1008
|
-
if (formattedSchema?.type ===
|
|
1084
|
+
if (formattedSchema?.type === 'object') {
|
|
1009
1085
|
formattedSchema.additionalProperties = false;
|
|
1010
1086
|
}
|
|
1011
1087
|
if (formattedSchema?.properties) {
|
|
@@ -1029,16 +1105,17 @@ function openAISchemaFormat(schema, nesting = 0) {
|
|
|
1029
1105
|
}
|
|
1030
1106
|
}
|
|
1031
1107
|
}
|
|
1032
|
-
if (formattedSchema?.type === 'object' &&
|
|
1108
|
+
if (formattedSchema?.type === 'object' &&
|
|
1109
|
+
(!formattedSchema?.properties || Object.keys(formattedSchema?.properties ?? {}).length === 0)) {
|
|
1033
1110
|
//If no properties are defined, then additionalProperties: true was set or the object would be empty.
|
|
1034
1111
|
//OpenAI does not support this on structured output/ strict mode.
|
|
1035
|
-
throw new Error(
|
|
1112
|
+
throw new Error('OpenAI does not support empty objects or objects with additionalProperties set to true');
|
|
1036
1113
|
}
|
|
1037
1114
|
return formattedSchema;
|
|
1038
1115
|
}
|
|
1039
1116
|
function responseFinishReason(response, tools) {
|
|
1040
1117
|
if (tools && tools.length > 0) {
|
|
1041
|
-
return
|
|
1118
|
+
return 'tool_use';
|
|
1042
1119
|
}
|
|
1043
1120
|
if (response.status === 'incomplete') {
|
|
1044
1121
|
if (response.incomplete_details?.reason === 'max_output_tokens') {
|
|
@@ -1113,6 +1190,30 @@ export function fixOrphanedToolUse(items) {
|
|
|
1113
1190
|
}
|
|
1114
1191
|
return result;
|
|
1115
1192
|
}
|
|
1193
|
+
/**
|
|
1194
|
+
* Drop function_call_output items whose call_id has no matching function_call
|
|
1195
|
+
* item anywhere in the input. Mirror of {@link fixOrphanedToolUse}: that
|
|
1196
|
+
* synthesizes outputs for calls left unanswered (e.g. a cancelled run); this
|
|
1197
|
+
* removes outputs left dangling after their function_call was dropped (e.g. by
|
|
1198
|
+
* conversation compaction/trimming). The OpenAI Responses API requires every
|
|
1199
|
+
* function_call_output to reference a prior function_call's call_id.
|
|
1200
|
+
*/
|
|
1201
|
+
export function fixOrphanedToolResults(items) {
|
|
1202
|
+
if (items.length === 0)
|
|
1203
|
+
return items;
|
|
1204
|
+
const callIds = new Set();
|
|
1205
|
+
for (const item of items) {
|
|
1206
|
+
if ('type' in item && item.type === 'function_call') {
|
|
1207
|
+
callIds.add(item.call_id);
|
|
1208
|
+
}
|
|
1209
|
+
}
|
|
1210
|
+
return items.filter((item) => {
|
|
1211
|
+
if ('type' in item && item.type === 'function_call_output') {
|
|
1212
|
+
return callIds.has(item.call_id);
|
|
1213
|
+
}
|
|
1214
|
+
return true;
|
|
1215
|
+
});
|
|
1216
|
+
}
|
|
1116
1217
|
function safeJsonParse(value) {
|
|
1117
1218
|
if (typeof value !== 'string') {
|
|
1118
1219
|
return value;
|