feat(core): add Eden AI as a built-in model provider - #1386
Conversation
Eden AI is an EU-based, OpenAI-compatible LLM gateway. It is registered as an EXTRA_PROVIDER_REGISTRY entry wired through the existing @ai-sdk/openai-compatible adapter, exactly like MiniMax, and reached with edenai/<vendor>/<model> ids (e.g. edenai/openai/gpt-4o-mini). The provider reads EDENAI_API_KEY and defaults to https://api.edenai.run/v3, with EDENAI_BASE_URL supported for the EU endpoint. Adds a registry spec mirroring the MiniMax test and a with-edenai example.
🦋 Changeset detectedLatest commit: 18aae4d The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
📝 WalkthroughWalkthroughAdds Eden AI as a built-in OpenAI-compatible model provider and introduces a complete ChangesEden AI provider integration
Estimated code review effort: 3 (Moderate) | ~20 minutes Sequence Diagram(s)sequenceDiagram
participant Agent
participant ModelProviderRegistry
participant EdenAIAPI
Agent->>ModelProviderRegistry: Resolve edenai/openai/gpt-4o-mini
ModelProviderRegistry->>EdenAIAPI: Configure OpenAI-compatible provider
Agent->>EdenAIAPI: Generate text
EdenAIAPI-->>Agent: Return text and usage
Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Warning There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure. 🔧 Checkov (3.3.8)examples/with-edenai/package.jsonTraceback (most recent call last): examples/with-edenai/tsconfig.jsonTraceback (most recent call last): Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment Warning |
There was a problem hiding this comment.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
examples/with-edenai/.gitignore (1)
4-5: 🔒 Security & Privacy | 🔴 Critical | ⚡ Quick winAdd
.envto.gitignoreto prevent credential leaks.The
README.mdinstructs users to create a.envfile containing theirEDENAI_API_KEY. When users scaffold a new app from this example template using the CLI, they will inherit this.gitignore. Omitting.envfrom this file creates a critical security risk where users can inadvertently commit and leak their sensitive API keys to source control.🔒️ Proposed fix
.DS_Store .voltagent/ +.env🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@examples/with-edenai/.gitignore` around lines 4 - 5, Add .env to the ignore entries in the example’s .gitignore, alongside .voltagent/, so scaffolded applications exclude environment files containing EDENAI_API_KEY from version control.
🧹 Nitpick comments (1)
examples/with-edenai/src/index.ts (1)
37-44: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick winHandle potential promise rejections.
The anonymous async execution block does not handle errors. If
agent.generateTextfails (e.g., due to a network timeout or invalid API key), it will cause an unhandled promise rejection and abruptly crash the process. While this is an example, demonstrating robust error handling is highly recommended.🛡️ Proposed refactor for graceful error handling
(async () => { - const result = await agent.generateText("Explain how observability helps with AI cost control."); - - logger.info("Eden AI example request completed", { - text: result.text, - usage: result.usage, - }); + try { + const result = await agent.generateText("Explain how observability helps with AI cost control."); + + logger.info("Eden AI example request completed", { + text: result.text, + usage: result.usage, + }); + } catch (error) { + logger.error("Eden AI example request failed", { error }); + process.exit(1); + } })();🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@examples/with-edenai/src/index.ts` around lines 37 - 44, Update the anonymous async execution block around agent.generateText to catch promise rejections and log the failure through logger.info or the appropriate error-level logger, including useful error details. Preserve the existing success logging for completed requests while ensuring failures are handled without an unhandled promise rejection.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@examples/with-edenai/package.json`:
- Line 34: Update the package.json start script to invoke Node with
--env-file=.env before dist/index.js, matching the existing dev script’s
environment loading behavior while preserving the compiled-output startup
command.
In `@packages/core/src/registries/model-provider-registry-edenai.spec.ts`:
- Around line 7-9: Update the safeStringify mock in the test setup to remove
JSON.stringify, using String or an explicit stubbed string representation while
preserving the mock’s string-returning behavior.
---
Outside diff comments:
In `@examples/with-edenai/.gitignore`:
- Around line 4-5: Add .env to the ignore entries in the example’s .gitignore,
alongside .voltagent/, so scaffolded applications exclude environment files
containing EDENAI_API_KEY from version control.
---
Nitpick comments:
In `@examples/with-edenai/src/index.ts`:
- Around line 37-44: Update the anonymous async execution block around
agent.generateText to catch promise rejections and log the failure through
logger.info or the appropriate error-level logger, including useful error
details. Preserve the existing success logging for completed requests while
ensuring failures are handled without an unhandled promise rejection.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 645bdcd7-72f3-42ce-8f5f-c29beb33f061
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (9)
.changeset/edenai-provider.mdexamples/with-edenai/.env.exampleexamples/with-edenai/.gitignoreexamples/with-edenai/README.mdexamples/with-edenai/package.jsonexamples/with-edenai/src/index.tsexamples/with-edenai/tsconfig.jsonpackages/core/src/registries/model-provider-registry-edenai.spec.tspackages/core/src/registries/model-provider-registry.ts
| "scripts": { | ||
| "build": "tsc", | ||
| "dev": "tsx watch --env-file=.env ./src", | ||
| "start": "node dist/index.js", |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Add --env-file=.env to the start script.
To ensure the example works consistently when users follow the README instruction to test the compiled output (pnpm build && pnpm start), the start script needs to load the .env file, just like the dev script does.
🐛 Proposed fix
- "start": "node dist/index.js",
+ "start": "node --env-file=.env dist/index.js",📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| "start": "node dist/index.js", | |
| "start": "node --env-file=.env dist/index.js", |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@examples/with-edenai/package.json` at line 34, Update the package.json start
script to invoke Node with --env-file=.env before dist/index.js, matching the
existing dev script’s environment loading behavior while preserving the
compiled-output startup command.
| vi.mock("@voltagent/internal", () => ({ | ||
| safeStringify: (value: unknown) => JSON.stringify(value), | ||
| })); |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Remove JSON.stringify to comply with coding guidelines.
As per coding guidelines, JSON.stringify should never be used. Even within a test mock, this strict rule must be adhered to. You can use a simpler primitive like String or explicitly return a stubbed string representation instead of relying on JSON.stringify.
♻️ Proposed alternative
// Mock `@voltagent/internal` to avoid build dependency
vi.mock("`@voltagent/internal`", () => ({
- safeStringify: (value: unknown) => JSON.stringify(value),
+ safeStringify: (value: unknown) => String(value),
}));📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| vi.mock("@voltagent/internal", () => ({ | |
| safeStringify: (value: unknown) => JSON.stringify(value), | |
| })); | |
| vi.mock("`@voltagent/internal`", () => ({ | |
| safeStringify: (value: unknown) => String(value), | |
| })); |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@packages/core/src/registries/model-provider-registry-edenai.spec.ts` around
lines 7 - 9, Update the safeStringify mock in the test setup to remove
JSON.stringify, using String or an explicit stubbed string representation while
preserving the mock’s string-returning behavior.
Source: Coding guidelines
There was a problem hiding this comment.
2 issues found across 10 files
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="packages/core/src/registries/model-provider-registry-edenai.spec.ts">
<violation number="1" location="packages/core/src/registries/model-provider-registry-edenai.spec.ts:8">
P3: The `safeStringify` mock uses `JSON.stringify` directly. If the project's coding guidelines discourage `JSON.stringify` usage (preferring `safeStringify` from `@voltagent/internal` for safety), even test mocks should avoid it to stay consistent. Since no test here actually depends on the serialization output, a simpler stub like `String(value)` or a fixed string return would satisfy the mock contract without importing the discouraged primitive.</violation>
</file>
<file name="examples/with-edenai/package.json">
<violation number="1" location="examples/with-edenai/package.json:34">
P2: The `start` script doesn't load environment variables from `.env`, unlike the `dev` script which uses `--env-file=.env`. Since `src/index.ts` throws immediately if `EDENAI_API_KEY` is missing, running `pnpm build && pnpm start` (as the README suggests) will fail unless the user manually exports the variable. Adding `--env-file=.env` keeps behavior consistent with the dev script and the documented workflow.</violation>
</file>
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
| "scripts": { | ||
| "build": "tsc", | ||
| "dev": "tsx watch --env-file=.env ./src", | ||
| "start": "node dist/index.js", |
There was a problem hiding this comment.
P2: The start script doesn't load environment variables from .env, unlike the dev script which uses --env-file=.env. Since src/index.ts throws immediately if EDENAI_API_KEY is missing, running pnpm build && pnpm start (as the README suggests) will fail unless the user manually exports the variable. Adding --env-file=.env keeps behavior consistent with the dev script and the documented workflow.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At examples/with-edenai/package.json, line 34:
<comment>The `start` script doesn't load environment variables from `.env`, unlike the `dev` script which uses `--env-file=.env`. Since `src/index.ts` throws immediately if `EDENAI_API_KEY` is missing, running `pnpm build && pnpm start` (as the README suggests) will fail unless the user manually exports the variable. Adding `--env-file=.env` keeps behavior consistent with the dev script and the documented workflow.</comment>
<file context>
@@ -0,0 +1,38 @@
+ "scripts": {
+ "build": "tsc",
+ "dev": "tsx watch --env-file=.env ./src",
+ "start": "node dist/index.js",
+ "volt": "volt"
+ },
</file context>
|
|
||
| // Mock @voltagent/internal to avoid build dependency | ||
| vi.mock("@voltagent/internal", () => ({ | ||
| safeStringify: (value: unknown) => JSON.stringify(value), |
There was a problem hiding this comment.
P3: The safeStringify mock uses JSON.stringify directly. If the project's coding guidelines discourage JSON.stringify usage (preferring safeStringify from @voltagent/internal for safety), even test mocks should avoid it to stay consistent. Since no test here actually depends on the serialization output, a simpler stub like String(value) or a fixed string return would satisfy the mock contract without importing the discouraged primitive.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/core/src/registries/model-provider-registry-edenai.spec.ts, line 8:
<comment>The `safeStringify` mock uses `JSON.stringify` directly. If the project's coding guidelines discourage `JSON.stringify` usage (preferring `safeStringify` from `@voltagent/internal` for safety), even test mocks should avoid it to stay consistent. Since no test here actually depends on the serialization output, a simpler stub like `String(value)` or a fixed string return would satisfy the mock contract without importing the discouraged primitive.</comment>
<file context>
@@ -0,0 +1,117 @@
+
+// Mock @voltagent/internal to avoid build dependency
+vi.mock("@voltagent/internal", () => ({
+ safeStringify: (value: unknown) => JSON.stringify(value),
+}));
+
</file context>
What
Adds Eden AI as a built-in model provider.
Eden AI is an EU-based, OpenAI-compatible LLM gateway (single API key, one endpoint, many upstream vendors). Because it speaks the OpenAI-compatible protocol, it slots into the existing
EXTRA_PROVIDER_REGISTRYand is wired through the shared@ai-sdk/openai-compatibleadapter, exactly like the MiniMax entries. No new adapter code is required.Usage
Eden AI model ids are vendor-prefixed, so the full router id is
edenai/<vendor>/<model>, for example:edenai/openai/gpt-4o-miniedenai/anthropic/claude-haiku-4-5edenai/mistral/mistral-small-latestThe provider reads
EDENAI_API_KEYand defaults tohttps://api.edenai.run/v3. SetEDENAI_BASE_URL=https://api.eu.edenai.run/v3for EU data residency. The registry splits on the first slash, so theedenaisegment is the provider and the remaining<vendor>/<model>is passed straight through to Eden AI.Changes
packages/core/src/registries/model-provider-registry.ts: oneEXTRA_PROVIDER_REGISTRYentry (id: "edenai",@ai-sdk/openai-compatible,api: https://api.edenai.run/v3,env: ["EDENAI_API_KEY"]).packages/core/src/registries/model-provider-registry-edenai.spec.ts: unit tests mirroring the MiniMax spec (provider is registered, resolves through@ai-sdk/openai-compatiblewith the right base URL and API key, keeps the vendor-prefixed model id after the provider segment, honorsEDENAI_BASE_URL, throws when the key is missing).examples/with-edenai/: runnable example mirroringexamples/with-openrouter..changeset/edenai-provider.md: patch changeset for@voltagent/core.Testing
vitest runon the registry specs, 13 tests).createOpenAICompatible({ name: "edenai", baseURL: "https://api.edenai.run/v3", apiKey })) andgenerateTextfromai@6. Three upstream vendors returned completions:openai/gpt-4o-mini,anthropic/claude-haiku-4-5,mistral/mistral-small-latest.biome checkclean; example typechecks withtsc --noEmit.Summary by cubic
Add Eden AI as a built-in model provider via the
@ai-sdk/openai-compatibleadapter, enabling models addressed asedenai/<vendor>/<model>with EU endpoint support. Includes a runnable example and unit tests; no new adapter code.edenaiinEXTRA_PROVIDER_REGISTRYwith APIhttps://api.edenai.run/v3; readsEDENAI_API_KEYand supportsEDENAI_BASE_URL.edenai/(e.g.edenai/openai/gpt-4o-mini).examples/with-edenaiand a spec verifying registration, base URL override, and missing-key errors.Written for commit 18aae4d. Summary will update on new commits.
Summary by CodeRabbit
New Features
edenai/openai/gpt-4o-mini.EDENAI_API_KEY; optional EU routing is supported throughEDENAI_BASE_URL.Documentation