Skip to content

feat(oracle): Add Oracle GenAI Provider with full model family support#1537

Open
fede-kamel wants to merge 3 commits intoPortkey-AI:mainfrom
fede-kamel:feat/oracle-genai-provider
Open

feat(oracle): Add Oracle GenAI Provider with full model family support#1537
fede-kamel wants to merge 3 commits intoPortkey-AI:mainfrom
fede-kamel:feat/oracle-genai-provider

Conversation

@fede-kamel
Copy link

Summary

This PR adds comprehensive support for Oracle Cloud Infrastructure (OCI) Generative AI as a provider in the Portkey Gateway. As an Oracle engineer working on GenAI integrations, I've implemented this to bring Portkey's API gateway capabilities to the full range of models available on OCI GenAI.

Key Features

  • OCI Signature Authentication: Full support for OCI API key authentication with request signing
  • Multi-model family support: Meta Llama, Google Gemini, OpenAI GPT (4o, 5, OSS), xAI Grok, and Cohere models
  • Embeddings support: Cohere embedding models with all input types
  • Streaming: Full SSE streaming support for all chat models
  • Tool/Function calling: Both sync and streaming tool calls, including parallel tool calling
  • Model-specific handling: Automatic parameter adjustments for different model families

Supported Features by Model Family

Feature Meta Llama Google Gemini OpenAI GPT-4o OpenAI GPT-5 OpenAI GPT-OSS xAI Grok Cohere
Basic Chat
System Messages
Multi-turn
Streaming
Tool Calling
Tool Streaming
Parallel Tools
Embeddings - - - - - -

Model-Specific Configurations

Model Family Min Tokens Uses Reasoning Tokens Special Parameters
meta.llama 50 No -
google.gemini 100 Yes -
openai.gpt-4o 100 No -
openai.gpt-5 500 Yes maxCompletionTokens
openai.gpt-oss 200 Yes reasoningContent
xai.grok 50 No -
xai.grok-*-reasoning 100 Yes -
cohere.command 50 No -

Backwards Compatibility

Gateway Core (Shared Files)

File Change Status
jest.config.js Added ts-jest config ✅ Tests pass, pre-existing failures unrelated
src/providers/open-ai-base/index.ts Default value logic ✅ All OpenAI-based provider tests pass
src/types/requestBody.ts Added optional fields ✅ Additive only, no breaking change
src/utils/env.ts Module loading fix ✅ TypeScript compiles cleanly

Oracle Provider

Change Type Impact
Added embed endpoint Additive None - new feature
Added model handlers Additive None - internal
Added modelConfig.ts Additive None - internal
Enhanced content types Additive None - existing types still work
GPT-5 maxCompletionTokens Auto-detect None - transparent to users
Tool call streaming state Internal None - better reliability
reasoningContent handling Enhancement None - fixes empty responses

Existing Oracle users will NOT experience breaking changes. All existing functionality continues to work.

Test Coverage

Unit Tests (61 passing)

  • modelConfig.test.ts - Model configuration and helpers
  • chatComplete.test.ts - Request/response transforms

Integration Tests (Real API calls)

Feature Unit Tests Integration Tests Models Verified
Basic Chat Llama, Gemini, Grok, GPT-4o, GPT-5, GPT-OSS
System Messages All models
Multi-turn All models
Streaming All models
Tool Calling All models
Tool Streaming All models
Parallel Tools All models (3 tools simultaneously)
Embeddings 9 Cohere models
Error Handling Invalid model tests
GPT-5 maxCompletionTokens GPT-5
reasoningContent GPT-OSS

Parallel Tool Calling Results

Model Result
meta.llama-4-maverick ✅ 3 tools in parallel
google.gemini-2.5-flash ✅ 3 tools in parallel
xai.grok-3-mini ✅ 3 tools in parallel
openai.gpt-4o ✅ 3 tools in parallel
openai.gpt-5 ✅ 3 tools in parallel

Technical Implementation

Files Added/Modified

  • src/providers/oracle/ - Complete provider implementation
    • chatComplete.ts - Chat completions with OpenAI-compatible transforms
    • embed.ts - Embeddings support for Cohere models
    • modelConfig.ts - Model family configurations and helpers
    • utils.ts - OCI request signing utilities
    • handlers/ - Model-specific handler classes
    • types/ - TypeScript type definitions

Authentication

The provider uses OCI API Key authentication with request signing:

// Required headers
x-portkey-oracle-tenancy: <tenancy-ocid>
x-portkey-oracle-user: <user-ocid>
x-portkey-oracle-fingerprint: <api-key-fingerprint>
x-portkey-oracle-private-key: <pem-private-key>
x-portkey-oracle-compartment-id: <compartment-ocid>
x-portkey-oracle-region: <region> // e.g., us-chicago-1, eu-frankfurt-1

Verification Checklist

  • TypeScript compilation passes
  • Prettier formatting passes
  • Unit tests pass (61/61)
  • Integration tests verified with real API calls
  • All model families tested
  • Backwards compatibility confirmed
  • No breaking changes to existing functionality

… tests

Oracle GenAI Provider Enhancements:

- Add embeddings support (embed.ts) with Cohere model compatibility
- Add model configuration system (modelConfig.ts) for model-specific behaviors
- Add model handler classes for different families (Meta, Gemini, GPT, Grok, Cohere)
- Support reasoningContent for GPT-OSS reasoning models
- Handle content in multiple formats (array, string, reasoningContent)
- Add oracleEndpointId to Options type for dedicated serving mode

Testing:
- Add comprehensive unit tests (61 tests passing)
- Add integration tests for chat completions and embeddings
- Add run-tests.sh script for easy test execution with OCI profiles

Models tested:
- Google Gemini 2.5 (flash, flash-lite, pro)
- OpenAI GPT-OSS (20b, 120b)
- Meta Llama Maverick
- Cohere embeddings (v4.0, v3.0 variants)
- Add usesMaxCompletionTokens() helper for GPT-5+ model detection
- Update chatRequest transform to use maxCompletionTokens for GPT-5 models
- Add model configs for openai.gpt-5 and openai.gpt-4o families
- Add OracleStreamChunk type definition for streaming responses
- Set appropriate minTokens (500) for GPT-5 reasoning models
- Test multiple tool calls in a single response (weather, time, stock)
- Test parallel tool calls with streaming
- Verify models can call 2+ tools simultaneously
@fede-kamel
Copy link
Author

Note on src/providers/open-ai-base/index.ts change

While working on the Oracle provider, I ran tsc --noEmit to verify type safety and discovered a pre-existing TypeScript error in open-ai-base/index.ts:

src/providers/open-ai-base/index.ts(72,23): error TS2339: Property 'default' does not exist on type 'ParameterConfig | ParameterConfig[]'.

This error existed on main before my changes. The code works at runtime (JavaScript ignores types), but TypeScript couldn't properly narrow the union type when accessing via index.

Original code:

if (Object.hasOwn(baseParams, key) && !Array.isArray(baseParams[key])) {
  baseParams[key].default = defaultValues?.[key];  // TS error
}

Fixed code:

const param = baseParams[key];
if (param && !Array.isArray(param)) {
  (param as { default?: any }).default = defaultValues?.[key];  // ✅
}

I included this fix since I was already touching the codebase and it improves type safety. If you prefer, I can revert this change and keep it Oracle-only.

@fede-kamel
Copy link
Author

fede-kamel commented Feb 26, 2026

Issue Discovery: OCI Streaming Tool Calls

While testing portkey-strands (Strands Agents SDK integration with Portkey), I discovered a critical issue with OCI GenAI streaming responses for tool/function calling.

The Problem

When using OCI GenAI models through the current production Portkey gateway, streaming responses do not properly return tool call data. The model indicates it wants to call a tool (finish_reason: "tool_calls"), but the actual tool call information (function name, arguments) is missing from the streamed chunks.

Test Results (before this PR):

Provider Model Basic Chat Tool Use
OpenAI gpt-4o ✅ Pass ✅ Pass
Anthropic claude-sonnet-4-6 ✅ Pass ✅ Pass
OCI meta.llama-3.3-70b ✅ Pass ✅ Pass
OCI xai.grok-4-1-fast-reasoning ✅ Pass ✅ Passl
OCI cohere.command-a ✅ Pass

Actual Error

# Model returns end_turn with empty content instead of tool_use
AgentResult(
    stop_reason='end_turn',  # Should be 'tool_use'
    message={'role': 'assistant', 'content': []},  # Tool call data missing
    ...
)

The streaming response returns stopReason: 'end_turn' instead of 'tool_use', and the contentBlockStart events for tool calls are never emitted.

Why This PR Fixes It

This PR includes proper streaming state management for tool calls:

  1. Tool call accumulation - Properly buffers tool call chunks across SSE events
  2. Index tracking - Maintains tool call indices for parallel tool calls
  3. Finish reason mapping - Correctly maps OCI's finish reasons to OpenAI-compatible format
  4. Content block emission - Emits proper contentBlockStart/contentBlockDelta/contentBlockStop events for tools

Verification

After applying this PR's changes, all OCI models pass tool calling tests:

  • Single tool calls
  • Multiple sequential tools
  • Parallel tool calls (3+ simultaneous)
  • Streaming tool calls

This enables full agentic workflows with OCI GenAI models through Portkey.

@fede-kamel
Copy link
Author

cc @VisargD - This PR addresses a critical issue affecting agentic workflows with OCI GenAI models. The streaming tool call bug prevents Strands Agents (and likely other agent frameworks) from working properly with OCI models through Portkey.

Would appreciate a review when you have time!

@fede-kamel
Copy link
Author

Tracking issue created: #1538

This documents the critical streaming tool call bug and explains why keeping the Oracle GenAI integration up to date is important for enterprise customers.

@fede-kamel
Copy link
Author

Rebased check done: branch is already up to date with main (no conflicts).

Validation run:

  • Unit: tests/unit/src/providers/oracle/chatComplete.test.ts, tests/unit/src/providers/oracle/modelConfig.test.ts (PASS)
  • Integration (OCI profile LUIGI_FRA_API): tests/integration/src/providers/oracle/run-tests.sh ... all (PASS; chat+embed suites)

Re-pinging for review.

@fede-kamel
Copy link
Author

Friendly follow-up on this one when you have a moment: @VisargD @narengogi\n\nWould appreciate a review. Thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant