Skip to content

test(docs): automated documentation quality checks (ENG-23) - #89

Open
YacineMK wants to merge 10 commits into
mainfrom
feat/automate-documentation-tests
Open

test(docs): automated documentation quality checks (ENG-23)#89
YacineMK wants to merge 10 commits into
mainfrom
feat/automate-documentation-tests

Conversation

@YacineMK

@YacineMK YacineMK commented Aug 9, 2026

Copy link
Copy Markdown
Member

Summary

Adds automated documentation quality checks under ENG-23.

  • TS snippet execution via bun — extracts .ts/.tsx/.mjs/.cjs blocks from openai-sdk-typescript, langchain, pi guides and executes them against staging.
  • Config validator — parses JSON/YAML/TOML config blocks in tool-integration guides, checks Eden AI URLs, cross-checks provider/model strings against live inventory.
  • API-reference validator — verifies the 3 remote OpenAPI specs referenced in docs.json are reachable, cross-checks every api.edenai.run/v[23]/… URL in prose.
  • Model/provider validator — scans all 133 .mdx pages for provider/model refs, cross-checks against /v3/models + /v3/info + probed embeddings.
  • Link checker — verifies internal targets exist, external URLs return non-404/410, and every docs.json nav path resolves.
  • CI — two jobs in test-snippets.yml (Python + TS), cancel-in-progress: false, weekly cron.

Bundled doc fixes: renamed stale model refs (cohere/command-r-plus-plus-08-2024, mistral/mistral-large-large-latest, codex prefix openai/azure/, several image/audio/translation catalog rewrites); rewrote pi.mdx TS snippet against the real ExtensionAPI shape; replaced broken node-fetch + form-data vision snippet with native fetch + Blob; replaced dead old-docs.edenai.co domain.

Test plan

  • pytest tests/test_snippets_execute.py tests/config_validator.py tests/api_reference_validator.py tests/model_provider_validator.py tests/link_checker.py -n0 --no-cov — passes except the 11 flagged below
  • cd tests/ts && bun test — 13 pass / 1 skip / 0 fail
  • Manual workflow_dispatch run in Actions

❓ Question — 11 failing tests need a product decision

The model/provider validator flags 11 backticked provider/model strings across 6 doc pages that don't exist in the live Eden AI catalog (/v3/models or /v3/info). These aren't code bugs — they're doc content bugs the validator surfaced. I need someone with platform context to decide the intent for each:

A. `image/generation/bytedance/*` × 5 + `image/generation/minimax` × 2 — in `v3/expert-models/features/image/generation.mdx`. Live API says these providers don't support `image/generation`.

B. `video/generation_async/pixverse/*` × 5 — in `v3/expert-models/features/video/generation-async.mdx`. Live API says these models don't exist.

C. `web/crawl_async/firecrawl` + `web/map/firecrawl` — in the corresponding `v3/expert-models/features/web/*.mdx` pages. Subfeatures exist, firecrawl isn't a supported provider for them.

For each, which one applies?

  1. Provider was removed from the platform → delete the rows from the doc tables.
  2. Provider is planned / coming soon → keep with an aspirational note and add to a tracked-stale allowlist.
  3. Wrong provider referenced → tell me the correct one and I'll swap it in.

Also flagging: `/v3/info` doesn't list `web/batch_scrape_async` or `web/structured_extraction_async` even though the API accepts them. Worked around via runtime probing in `tests/helpers/edenai_inventory.py`; backend may want to expose them in `/v3/info`.

Summary by CodeRabbit

  • Documentation

    • Updated legacy links, modification dates, provider and model references, API examples, and integration guidance.
    • Improved TypeScript upload, CLI, Pi, and configuration examples.
  • New Features

    • Added automated checks for links, API references, configuration examples, and documented model names.
    • Added TypeScript snippet extraction and execution testing.
  • Chores

    • Expanded scheduled and change-based documentation checks.
    • Added local guidance for running validators and TypeScript snippet tests.

@mintlify

mintlify Bot commented Aug 9, 2026

Copy link
Copy Markdown

Preview deployment for your docs. Learn more about Mintlify Previews.

Project Status Preview Updated (UTC)
edenai 🟢 Ready View Preview Aug 9, 2026, 3:05 PM

💡 Tip: Enable Workflows to automatically generate PRs for you.

@coderabbitai

coderabbitai Bot commented Aug 9, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@YacineMK, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 30 minutes

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 156b4cdf-924a-4bfb-97a1-64e603c96b1c

📥 Commits

Reviewing files that changed from the base of the PR and between 400d292 and 957aff2.

📒 Files selected for processing (1)
  • tests/link_checker.py

Walkthrough

The pull request adds Python and TypeScript documentation validation to CI, generates and executes TypeScript snippets, centralizes test fixtures and model inventory checks, and updates documentation links, metadata, provider mappings, and model examples.

Changes

Documentation quality and execution

Layer / File(s) Summary
Documentation validation pipeline
.github/workflows/test-snippets.yml, tests/*validator.py, tests/helpers/*, tests/link_checker.py, tests/README.md
CI now runs configuration, OpenAPI, model inventory, link, and navigation validators.
TypeScript snippet generation and execution
tests/snippet_extractor.py, tests/ts/*, tests/helpers/file_generators.py, .gitignore
The extractor generates TypeScript and JavaScript fixtures. Bun runs the generated snippets in a separate CI job.
Documentation links and model examples
index.mdx, v2/index.mdx, v3/expert-models/*, v3/integrations/*, v3/llms*, v3/overview/*, v3/quickstart/*
Documentation links, modification dates, provider mappings, model identifiers, and integration examples are updated.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant GitHubActions
  participant PythonValidators
  participant Documentation
  participant EdenAIAPIs
  GitHubActions->>PythonValidators: run documentation validators
  PythonValidators->>Documentation: scan pages and navigation
  PythonValidators->>EdenAIAPIs: fetch specifications and inventories
  PythonValidators-->>GitHubActions: report validation results
Loading
sequenceDiagram
  participant GitHubActions
  participant Bun
  participant GlobalSetup
  participant SnippetExtractor
  participant GeneratedSnippets
  GitHubActions->>Bun: start TypeScript tests
  Bun->>GlobalSetup: load environment and preload setup
  GlobalSetup->>SnippetExtractor: generate snippets and fixtures
  Bun->>GeneratedSnippets: execute generated snippets
  GeneratedSnippets-->>Bun: return execution status
Loading

Possibly related PRs

  • edenai/docs#35: Adds the Codex integration page updated by this pull request.
  • edenai/docs#52: Reworks the image-generation page updated by this pull request.
  • edenai/docs#83: Adds web feature pages whose provider references are corrected here.

Suggested reviewers: hmed22

Poem

A rabbit checks each link in line,
And runs the snippets, neat and fine.
New models hop into their place,
Fresh dates brighten every page.
CI thumps its little drum—
Documentation tests now run!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 7.69% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: adding automated documentation quality checks.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/automate-documentation-tests

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 13

🤖 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 @.github/workflows/test-snippets.yml:
- Around line 33-36: Restrict API-token environment variables in
.github/workflows/test-snippets.yml:33-36 to trusted events such as
protected-branch pushes, scheduled runs, or approved protected environments; at
.github/workflows/test-snippets.yml:45-46 run Python snippets without
credentials or move credentialed execution to a trusted workflow; at
.github/workflows/test-snippets.yml:67-70 remove the sandbox token from the
pull-request TypeScript job; at .github/workflows/test-snippets.yml:84-86 run
credentialed TypeScript snippets only in the trusted workflow; and in
tests/ts/snippets.test.ts:10-20 replace the process.env spread with an explicit
minimal environment.

In `@tests/config_validator.py`:
- Around line 103-111: Update test_config_guide so path existence, content
loading, and local JSON/YAML/TOML/URL validation always run regardless of
EDEN_AI_SANDBOX_API_TOKEN. Restrict the token-based skip to the
get_model_inventory() and subsequent live-inventory model validation, preserving
the existing behavior when the token is available.

In `@tests/link_checker.py`:
- Around line 96-104: Update _is_checkable and the external-link
request/redirect flow to reject private or otherwise non-global destinations,
including IPv4, IPv6, and link-local literals, before any request is made.
Resolve hostnames and validate their resulting addresses as well, and reapply
the same validation to every redirect target; alternatively, route all checks
through an established egress-controlled proxy or allowlist.

In `@tests/README.md`:
- Line 142: Update the stale-reference behavior description in tests/README.md
to match tests/model_provider_validator.py: unmatched candidates must fail
unless they are placeholders or have an excluded MIME prefix. Do not claim that
known stale references are tracked unless an explicit allowlist is implemented.

In `@tests/snippet_extractor.py`:
- Around line 336-350: Update extract_all_ts() so each generated
TypeScript/JavaScript file from a block includes the required standalone setup,
including url and headers when referenced, rather than relying on declarations
from earlier blocks on the page. Apply this during the path.write_text
generation flow while preserving existing filename, skip-marker, and
snippet-rewrite behavior.

In `@v2/index.mdx`:
- Line 3: Update the documentation links in v2/index.mdx (lines 3-3) and
v3/overview/ai-gateway.mdx (lines 162-162) to point V2 or previous-version
documentation text to https://www.edenai.co/docs/v2, preserving the surrounding
wording.

In `@v3/expert-models/features/audio/tts.mdx`:
- Line 65: Update the Google TTS model entry for gemini-3.1-flash-tts-preview to
use the correct Gemini 3.1 model identifier instead of
audio/tts/google/gemini-2.5-flash-tts, and adjust its listed price if required
by the intended 3.1 model.

In `@v3/expert-models/features/image/background-removal.mdx`:
- Line 50: Update the Stability AI row in the model table to replace the Api4ai
model identifier with the correct Stability AI model ID, while preserving the
provider label and pricing.

In `@v3/expert-models/features/image/generation.mdx`:
- Around line 76-78: Keep each catalog row’s provider, model identifier,
image-generation ID, and price aligned: in
v3/expert-models/features/image/generation.mdx lines 76-78, preserve distinct
IDs and prices for gpt-image-1, gpt-image-1.5, and gpt-image-1-mini, or remove
those rows and retain only gpt-image-2; in
v3/expert-models/features/web/research-async.mdx line 58,
v3/expert-models/features/web/scraping.mdx line 60, and
v3/expert-models/features/web/search.mdx line 71, keep each Firecrawl entry
under its corresponding /firecrawl ID or remove/rename it consistently as
linkup.

In `@v3/integrations/codex-cli.mdx`:
- Around line 110-115: Update the Codex smoke-test request in the documented
command to use the Responses API: replace the chat-completions messages payload
with an input payload while retaining the full azure/gpt-5.1-codex model
identifier.

In `@v3/integrations/pi.mdx`:
- Line 52: Update the configuration example to use the required production or
sandbox token variable: replace the EDEN_AI_API_KEY reference with the
appropriate api_token or sandbox_api_token field, and update the adjacent
environment or test fixture consistently so tests cannot consume a production
credential.

In `@v3/llms/image-generation.mdx`:
- Around line 49-52: Update the image model table to use unique provider/model
IDs matching the /v3/images/models format, replacing Universal AI-prefixed
values with IDs such as google/imagen-4.0-generate-001 and openai/gpt-image-2.
Remove the duplicate OpenAI entry and replace the Amazon row’s incomplete ID
with its provider/model-specific model ID.

In `@v3/llms/listing-models.mdx`:
- Line 107: Update the Stable alias entry in the model listing to replace
anthropic/claude-sonnet-4-6 with the catalog’s alias_of-backed
anthropic/claude-sonnet-latest, or remove the former from this entry and list it
under the versioned models section.
🪄 Autofix

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: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: c382557f-f1ae-4ae1-af2c-2b3cd8f12dd3

📥 Commits

Reviewing files that changed from the base of the PR and between 446dbd8 and 4cbfa8d.

⛔ Files ignored due to path filters (1)
  • tests/ts/bun.lock is excluded by !**/*.lock
📒 Files selected for processing (41)
  • .github/workflows/test-snippets.yml
  • .gitignore
  • index.mdx
  • tests/README.md
  • tests/api_reference_validator.py
  • tests/config_validator.py
  • tests/conftest.py
  • tests/helpers/edenai_inventory.py
  • tests/helpers/file_generators.py
  • tests/helpers/model_names.py
  • tests/link_checker.py
  • tests/model_provider_validator.py
  • tests/snippet_extractor.py
  • tests/ts/bunfig.toml
  • tests/ts/globalSetup.ts
  • tests/ts/package.json
  • tests/ts/snippets.test.ts
  • v2/index.mdx
  • v3/.claude/settings.local.json
  • v3/expert-models/features/audio/tts.mdx
  • v3/expert-models/features/image/background-removal.mdx
  • v3/expert-models/features/image/generation.mdx
  • v3/expert-models/features/web/research-async.mdx
  • v3/expert-models/features/web/scraping.mdx
  • v3/expert-models/features/web/search.mdx
  • v3/integrations/claude-code.mdx
  • v3/integrations/codex-cli.mdx
  • v3/integrations/continue-dev.mdx
  • v3/integrations/librechat.mdx
  • v3/integrations/open-webui.mdx
  • v3/integrations/openai-sdk-python.mdx
  • v3/integrations/openai-sdk-typescript.mdx
  • v3/integrations/openclaw.mdx
  • v3/integrations/pi.mdx
  • v3/llms.txt
  • v3/llms/chat-completions.mdx
  • v3/llms/image-generation.mdx
  • v3/llms/listing-models.mdx
  • v3/overview/ai-gateway.mdx
  • v3/quickstart/first-expert-model-call.mdx
  • v3/quickstart/first-llm-call.mdx
💤 Files with no reviewable changes (1)
  • v3/.claude/settings.local.json

Comment thread .github/workflows/test-snippets.yml Outdated
Comment on lines +33 to +36
env:
EDEN_AI_BASE_URL: ${{ vars.EDEN_AI_BASE_URL || 'https://staging-api.edenai.run' }}
EDEN_AI_SANDBOX_API_TOKEN: ${{ secrets.EDEN_AI_SANDBOX_TOKEN }}
EDEN_AI_PRODUCTION_API_TOKEN: ${{ secrets.EDEN_AI_PRODUCTION_TOKEN }}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟠 Major | 🏗️ Heavy lift

Do not execute pull-request content with API credentials.

A same-repository pull request can add a documentation snippet that reads the sandbox token and sends it to an external service. The TypeScript runner also forwards the complete process environment to each generated snippet.

  • .github/workflows/test-snippets.yml#L33-L36: bind API tokens only for trusted events, such as protected-branch pushes, scheduled runs, or approved protected environments.
  • .github/workflows/test-snippets.yml#L45-L46: run Python snippet execution without credentials on pull requests, or move credentialed execution to a trusted workflow.
  • .github/workflows/test-snippets.yml#L67-L70: remove the sandbox token from the pull-request TypeScript job.
  • .github/workflows/test-snippets.yml#L84-L86: run credentialed TypeScript snippets only in the trusted workflow.
  • tests/ts/snippets.test.ts#L10-L20: pass an explicit minimal environment instead of spreading process.env.
📍 Affects 2 files
  • .github/workflows/test-snippets.yml#L33-L36 (this comment)
  • .github/workflows/test-snippets.yml#L45-L46
  • .github/workflows/test-snippets.yml#L67-L70
  • .github/workflows/test-snippets.yml#L84-L86
  • tests/ts/snippets.test.ts#L10-L20
🤖 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 @.github/workflows/test-snippets.yml around lines 33 - 36, Restrict API-token
environment variables in .github/workflows/test-snippets.yml:33-36 to trusted
events such as protected-branch pushes, scheduled runs, or approved protected
environments; at .github/workflows/test-snippets.yml:45-46 run Python snippets
without credentials or move credentialed execution to a trusted workflow; at
.github/workflows/test-snippets.yml:67-70 remove the sandbox token from the
pull-request TypeScript job; at .github/workflows/test-snippets.yml:84-86 run
credentialed TypeScript snippets only in the trusted workflow; and in
tests/ts/snippets.test.ts:10-20 replace the process.env spread with an explicit
minimal environment.

Source: Linters/SAST tools

Comment thread tests/config_validator.py Outdated
Comment on lines +103 to +111
@pytest.mark.parametrize("guide", CONFIG_GUIDES, ids=lambda p: Path(p).stem)
def test_config_guide(guide: str) -> None:
if not os.environ.get("EDEN_AI_SANDBOX_API_TOKEN"):
pytest.skip("EDEN_AI_SANDBOX_API_TOKEN not set")

path = DOCS_ROOT / guide
assert path.exists(), f"Guide not found: {path}"
content = path.read_text(encoding="utf-8")
inventory = get_model_inventory()

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Run local validation when the token is absent.

Line 105 skips JSON, YAML, TOML, and URL validation when EDEN_AI_SANDBOX_API_TOKEN is absent. Only get_model_inventory() requires the token. Run the local checks unconditionally, and skip only the live-inventory model validation.

🤖 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 `@tests/config_validator.py` around lines 103 - 111, Update test_config_guide
so path existence, content loading, and local JSON/YAML/TOML/URL validation
always run regardless of EDEN_AI_SANDBOX_API_TOKEN. Restrict the token-based
skip to the get_model_inventory() and subsequent live-inventory model
validation, preserving the existing behavior when the token is available.

Comment thread tests/link_checker.py
Comment thread tests/README.md Outdated
Comment on lines +336 to +350
for rel in TS_GUIDES:
mdx_path = DOCS_ROOT / rel
if not mdx_path.exists():
raise FileNotFoundError(f"Guide not found: {mdx_path}")
blocks = extract_ts_blocks(mdx_path)
if not blocks:
continue

stem = sanitize_filename(mdx_path)
files: list[dict] = []
for i, block in enumerate(blocks, start=1):
skip_marker = ".skip" if block["skip"] else ""
name = f"{stem}__block_{i}{skip_marker}.{block['ext']}"
path = GENERATED_TS_DIR / name
path.write_text(rewrite_ts_snippet(block["code"], block["ext"]))

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

for guide in \
  v3/integrations/openai-sdk-typescript.mdx \
  v3/integrations/langchain.mdx \
  v3/integrations/pi.mdx
do
  echo "===== $guide ====="
  nl -ba "$guide" | sed -n '/^.*```\(typescript\|ts\|tsx\|javascript\|js\|jsx\)/,/^.*```/p'
done

Repository: edenai/docs

Length of output: 244


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "===== Guide files ====="
for guide in \
  v3/integrations/openai-sdk-typescript.mdx \
  v3/integrations/langchain.mdx \
  v3/integrations/pi.mdx
do
  if [ -f "$guide" ]; then
    echo "FOUND $guide"
  else
    echo "MISSING $guide"
  fi
done

echo "===== All TS-like fenced blocks in TS_GUIDES files ====="
python3 - <<'PY'
from pathlib import Path
import re

files = [
    Path("v3/integrations/openai-sdk-typescript.mdx"),
    Path("v3/integrations/langchain.mdx"),
    Path("v3/integrations/pi.mdx"),
]
fence_re = re.compile(r"^```(\w+)\s*$")
skip_re = re.compile(r"\{\s*\n?\s*{}\s*\n?\s*/\*\s*skip-test\s*\*/\s*\n?\s*\}\s*$|^{\s*\n?\s*{}\s*\n?\s*/\*\s*skip-test\s*\*/\s*\n?\s*\}\s*$", re.M)

for guide in files:
    if not guide.is_file():
        print(f"=== {guide} (missing) ===")
        continue
    print(f"=== {guide} ===")
    lines = guide.read_text(encoding="utf-8").splitlines()
    in_fence = False
    fence_lang = None
    block_lines = []
    for no, line in enumerate(lines, 1):
        if not in_fence:
            m = fence_re.match(line)
            if m:
                in_fence = True
                fence_lang = m.group(1)
                block_lines = []
        else:
            if line.startswith("```"):
                code = "\n".join(block_lines)
                print(f"line {no - len(block_lines):4}-{no:4} {fence_lang}")
                print(code or "<empty>")
                if code and skip_re.search(code):
                    print("<<< SKIP-MARKED BLOCK >>>")
                print("---")
                in_fence = False
                fence_lang = None
                block_lines = []
            else:
                block_lines.append(line)
    print()
PY

echo "===== Search for url/headers across guide files and generated test files ====="
python3 - <<'PY'
from pathlib import Path
import re

files = [
    Path("v3/integrations/openai-sdk-typescript.mdx"),
    Path("v3/integrations/langchain.mdx"),
    Path("v3/integrations/pi.mdx"),
]
fence_re = re.compile(r"^```(\w+)\s*$")
identifier_re = re.compile(r"\b(url|headers|fetch)\b", re.M)

for guide in files:
    if not guide.is_file():
        continue
    print(f"=== {guide} ===")
    lines = guide.read_text(encoding="utf-8").splitlines()
    in_fence = False
    block_lines = []
    env = {}
    for no, line in enumerate(lines, 1):
        if not in_fence:
            m = fence_re.match(line)
            if m:
                in_fence = True
                block_lines = []
        else:
            if line.startswith("```"):
                print(f"block {env.get('lang')!r} lines {env.get('start')}-{no}:")
                code = "\n".join(block_lines)
                if identifier_re.search(line := "\n".join(block_lines)):
                    for match in reversed(list(identifier_re.finditer(code))):
                        print(f"  {match.group()} at char {match.start()}")
                env = {"lang": m.group(1), "start": no - len(block_lines)}
                in_fence = False
                block_lines = []
            else:
                block_lines.append(line)

generated = Path("generated-js")
if generated.exists():
    print(f"=== generated-js ({len(list(generated.glob('*')))} files) ===")
    for path in sorted(generated.glob("*")):
        text = path.read_text(encoding="utf-8", errors="replace")
        matches = list(identifier_re.finditer(text))
        if len(matches) >= 2:
            print(path.relative_to(generated.parent), "has", len(matches), "matches")
            for label, text in [("url", "url"), ("headers", "headers"), ("fetch", "fetch")]:
                print(f"  {label}: {text in text}")
PY

Repository: edenai/docs

Length of output: 663


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "===== snippet_extractor outline / relevant sections ====="
python3 - <<'PY'
from pathlib import Path
p = Path("tests/snippet_extractor.py")
print(f"exists={p.exists()}")
if p.exists():
    lines = p.read_text(encoding="utf-8").splitlines()
    for i, line in enumerate(lines, 1):
        if "TS_GUIDES" in line or "extract_ts_blocks" in line or "rewrite_ts_snippet" in line or "GENERATED_TS_DIR" in line or "sanitize_filename" in line or "extract_all_ts" in line:
            print(f"{i}: {line}")
PY

echo "===== Read relevant tests/snippet_extractor.py section ====="
python3 - <<'PY'
from pathlib import Path
p = Path("tests/snippet_extractor.py")
if not p.exists():
    print("MISSING")
else:
    lines = p.read_text(encoding="utf-8").splitlines()
    start, end = 1, len(lines)
    for needle in ("TS_GUIDES", "extract_ts_blocks", "rewrite_ts_snippet"):
        for i, line in enumerate(lines, 1):
            if needle in line:
                start = min(start, max(1, i-30))
                end = max(end, min(len(lines), i+60))
    for i in range(start, end+1):
        print(f"{i:4}: {lines[i-1]}")
PY

echo "===== Search exact fenced block syntax in target guides ====="
python3 - <<'PY'
from pathlib import Path
import re

target = Path("tests/snippet_extractor.py")
if not target.exists():
    raise SystemExit("tests/snippet_extractor.py missing")
lines = target.read_text(encoding="utf-8").splitlines()
# Extract TS_GUIDES literal from file to avoid relying on hard-coded guides in this verifier.
text = "\n".join(lines)
m = re.search(r"TS_GUIDES\s*=\s*\[(.*?)\]", text, re.S)
if not m:
    print("TS_GUIDES not found")
    raise SystemExit(1)
glob_str = "[" + m.group(1).split("]",1)[0] + "]"
guides = re.findall(r"'([^']+)'|\"([^\"]+)\"", glob_str)
guides = [g for pair in guides for g in pair]
print("TS_GUIDES:", guides)

fence_re = re.compile(r"^```([A-Za-z0-9_]+)\s*$")
skip_re = re.compile(r"\{\s*\n?\s*{}\s*\n?\s*/\*\s*skip-test\s*\*/\s*\n?\s*\}\s*$|^{\s*\n?\s*{}\s*\n?\s*/\*\s*skip-test\s*\*/\s*\n?\s*\}\s*$", re.M)

ts_langs = {"ts", "typescript", "tsx", "tsx-typescript", "js", "javascript", "jsx"}

for guide_path in guides:
    guide = Path(guide_path)
    print(f"=== {guide_path} exists={guide.exists()} ===")
    if not guide.exists():
        continue
    ns = guide.read_text(encoding="utf-8").splitlines()
    blocks = []
    in_fence = False
    fence_lang = None
    block_lines = []
    block_start = 0
    for no, line in enumerate(ns, 1):
        if not in_fence:
            fm = fence_re.match(line)
            if fm and fm.group(1) in ts_langs:
                in_fence = True
                fence_lang = fm.group(1)
                block_start = no
                block_lines = []
        else:
            if line.startswith("```"):
                blocks.append((block_start, no, fence_lang, "\n".join(block_lines), skip_re.search(block_lines)))
                in_fence = False
                fence_lang = None
                block_lines = []
            else:
                block_lines.append(line)
    for start, end, lang, code, skip in blocks:
        print(f"block {start}-{end} lang={lang} skip={bool(skip)}")
        print(code[:2000] if code else "<empty>")
        print("---")
PY

Repository: edenai/docs

Length of output: 16306


🏁 Script executed:

#!/bin/bash
set -euo pipefail

python3 - <<'PY'
from pathlib import Path
import re

target = Path("tests/snippet_extractor.py")
text = target.read_text(encoding="utf-8")

m = re.search(r"TS_GUIDES:\s*list\[str\]\s*=\s*\[(.*?)\]", text, re.S)
if not m:
    raise SystemExit("TS_GUIDES not found")
glob_text = "[" + m.group(1).split("]", 1)[0] + "]"
guides = re.findall(r"[\"']([^\"']+)[\"']", glob_text)
print("TS_GUIDES:")
for g in guides:
    print(f"  {g}")

skip_re = re.compile(r"(/\*\s*skip-test\s*\*/|{\s*\n?\s*{}\s*\n?\s*/\*\s*skip-test\s*\*/\s*\n?\s*}\s*)", re.S)

fence_re = re.compile(
    r"^```(?P<lang>typescript|ts|tsx|javascript|js|jsx)"
    r"(?:[ \t]+[^\n]*)?[ \t]*\n(?P<body>.*?)^\s*```",
    re.MULTILINE | re.DOTALL,
)
for guide_path in guides:
    guide = Path(guide_path)
    print(f"\n=== {guide_path} exists={guide.exists()} ===")
    if not guide.exists():
        continue
    all_identifiers = []
    content = guide.read_text(encoding="utf-8")
    for match in fence_re.finditer(content):
        body = match.group("body")
        preceding = content[: match.start()]
        recent_lines = preceding.rsplit("\n", 3)[-3:]
        skip = bool(any(skip_re.search(line) for line in recent_lines))
        block_line = preceding.count("\n") + 2
        block_identifiers = re.findall(r"\b(url|headers|fetch)\b", body)
        all_identifiers.extend((block_line, body.count("\n") + 1, block_identifiers))
        print(f"block line {block_line}: {len(all_identifiers)} identifier refs={block_identifiers} skip={skip}")
        if body.strip():
            for idx, line_no, _ in all_identifiers[-1:]:
                # print last block body unless already printed in a long list
                print(body[:180].replace("\n", "\\n"))
    # Also print if identifiers appear outside TS fences because Python extractor can rewrite those later
    all_refs = re.findall(r"\b(url|headers|fetch)\b", content)
    print(f"total url/headers/fetch refs in file={len(all_refs)}")
PY

Repository: edenai/docs

Length of output: 505


Add required setup to each standalone TS/JS file.

extract_all_ts() writes each fence body into its own generated file, so later files cannot access variables declared by earlier files. Add the minimum setup, such as url and headers, inside files that depend on them instead of relying on page-level declaration order.

🤖 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 `@tests/snippet_extractor.py` around lines 336 - 350, Update extract_all_ts()
so each generated TypeScript/JavaScript file from a block includes the required
standalone setup, including url and headers when referenced, rather than relying
on declarations from earlier blocks on the page. Apply this during the
path.write_text generation flow while preserving existing filename, skip-marker,
and snippet-rewrite behavior.

Source: Coding guidelines

Comment on lines +76 to +78
| openai (gpt-image-1) | `image/generation/openai/gpt-image-2` | $0.042 per image |
| openai (gpt-image-1.5) | `image/generation/openai/gpt-image-2` | $0.034 per image |
| openai (gpt-image-1-mini) | `image/generation/openai/gpt-image-2` | $0.011 per image |

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Files:"
git ls-files | rg '^v3/expert-models/features/(image/generation|web/research-async|web/scraping|web/search)\.mdx$'

echo
echo "Relevant catalogs:"
for f in \
  v3/expert-models/features/image/generation.mdx \
  v3/expert-models/features/web/research-async.mdx \
  v3/expert-models/features/web/scraping.mdx \
  v3/expert-models/features/web/search.mdx
do
  echo "--- $f"
  nl -ba "$f" | sed -n '1,110p'
done

echo
echo "Git diff stat/name-only:"
git diff --stat
git diff -- v3/expert-models/features/image/generation.mdx v3/expert-models/features/web/research-async.mdx v3/expert-models/features/web/scraping.mdx v3/expert-models/features/web/search.mdx | sed -n '1,160p'

Repository: edenai/docs

Length of output: 448


🌐 Web query:

Eden AI v3 expert models image generation OpenAI gpt-image-1 gpt-image-1.5 gpt-image-1-mini pricing

💡 Result:

Eden AI v3 provides access to image generation models through two main mechanisms: its Universal AI endpoint [1][2] and dedicated OpenAI-compatible image endpoints [3]. While Eden AI aggregates models from many providers, the OpenAI image models you referenced—specifically gpt-image-1, gpt-image-1.5, and gpt-image-1-mini—are part of OpenAI's proprietary model suite [4][5][6][7]. 1. Eden AI v3 Image Generation: Eden AI offers two primary ways to access image generation: - Universal AI Endpoint (/v3/universal-ai): Used for expert models (including specialized image tasks) where you specify the model using the format feature/subfeature/provider[/model] [1][2]. - OpenAI-Compatible Endpoints (/v3/images/generations): These endpoints provide a drop-in, OpenAI-compatible experience. They accept the standard OpenAI request format and return the standard OpenAI response shape, including Eden's own cost and provider tracking fields [3][8]. You can use GET /v3/images/models to list the specific models available to your account [3][8]. 2. OpenAI GPT Image Models: The models you mentioned are specific OpenAI offerings [4]: - gpt-image-1: A natively multimodal model supporting text and image inputs with image outputs [6]. - gpt-image-1.5: An improved version of gpt-image-1 featuring better instruction following, improved image preservation and editing, and lower cost [5][9]. - gpt-image-1-mini: A cost-efficient version of gpt-image-1 [7]. 3. Pricing: - Eden AI Pricing: Eden AI does not charge a markup on the models themselves [10]. You pay the underlying provider's exact price, plus a 5.5% platform fee [10]. Every API response includes a cost field in USD, detailing the exact charge for that specific request [2]. - OpenAI GPT Image Model Pricing: OpenAI’s pricing for these models is tiered based on the quality setting (Low, Medium, High) and the target image resolution (e.g., 1024x1024, 1024x1536) [4]. You should consult the official OpenAI pricing documentation for the current, per-request rates for these specific models [4]. Because Eden AI acts as an aggregator, if you access these models through the Eden AI platform, your total cost per request will be the sum of the OpenAI model's rate plus the 5.5% Eden AI platform fee [10].

Citations:


🌐 Web query:

Eden AI v3 expert models web research_async firecrawl linkup pricing

💡 Result:

Eden AI V3 organizes its specialized AI capabilities—such as OCR, image analysis, text processing, translation, and audio services—under the Universal AI endpoint [1][2]. Expert Models Overview The Universal AI endpoint allows access to hundreds of expert models through a single, unified API structure [2]. Requests are made to the POST /v3/universal-ai endpoint, using a model string format of feature/subfeature/provider[/model] (e.g., text/moderation/google or image/generation/openai/dall-e-3) [1][3]. This system provides a standardized interface for specialized tasks that go beyond general-purpose LLMs [2][4]. Pricing and Credits Eden AI operates on a pay-per-use credit system [5]. The pricing model is designed for transparency: - No Markup: Eden AI does not apply a markup to the underlying provider's pricing; users pay exactly what the provider charges [6][7]. - Platform Fee: A 5.5% platform fee is applied at checkout when purchasing credits [6][7]. - Transparency: Every API response includes a cost field in USD, allowing users to track the exact spend for each request [2][5]. - Billing: Users can manage costs via a self-serve prepaid model (with recommended auto-refill) or transition to a postpaid billing arrangement under an Advanced/Enterprise plan for high-volume or specific business needs [6][7][5]. Web Research and Firecrawl There is no documentation indicating that Eden AI natively incorporates Firecrawl into its V3 Expert Models or Universal AI endpoint. Eden AI functions as a unified gateway for AI model providers rather than a web crawling or scraping service [2][4]. Documentation and Resources Official technical documentation for Eden AI V3 is available at their developer portal, which includes API references, integration guides, and programmatic ways to list all available features, models, and pricing [8][9]. Top Results: [8], [2], [6], [7], [5]

Citations:


🌐 Web query:

Eden AI v3 web scraping firecrawl linkup pricing

💡 Result:

Eden AI and Firecrawl are distinct platforms with separate pricing models; there is no integrated "Eden AI v3 Firecrawl" pricing package [1][2][3][4]. Users typically integrate these services by connecting them through automation platforms (such as viaSocket) or by using their respective APIs independently within a custom application workflow [5][4][6]. Eden AI Pricing Eden AI operates on a pay-per-use model with no monthly subscription fees [3]. When using Eden AI, you pay exactly what the underlying AI provider charges, plus a 5.5% platform fee applied at checkout [2][3]. You can either bring your own API keys to avoid Eden AI credit purchases or buy credits through the Eden AI dashboard to access various models [3]. Firecrawl Pricing Firecrawl uses a credit-based billing system where costs vary based on the plan and the specific features used (e.g., Scrape, Crawl, Map, or Search) [7][8]. - Free Plan: Includes 1,000 monthly credits [7]. - Paid Plans: Ranging from Hobby to Scale, these provide higher credit allotments, increased concurrent browsers, and additional support [7][8]. Pricing for these plans is typically billed monthly or yearly [7][8]. - Credit Usage: Standard scraping tasks generally consume 1 credit per page, while other actions like Search or Interact may have different consumption rates [7][8]. To combine these services, you would typically use Firecrawl to perform web scraping and data extraction, then send the resulting content to an Eden AI workflow for further processing (such as summarization or information extraction) [5][4]. You are billed separately by each platform according to their respective pricing structures [7][2][3].

Citations:


🌐 Web query:

Eden AI v3 web search firecrawl linkup pricing

💡 Result:

Eden AI offers a native web search feature for its LLM endpoints in v3, while Firecrawl is a separate third-party service often used in conjunction with AI platforms via automation tools [1][2][3]. There is no direct "Firecrawl linkup" pricing within Eden AI's billing; rather, each service maintains its own separate pricing structure [4][5][3]. Eden AI Pricing Eden AI operates on a pay-per-use model with no upfront fees or minimum commitments [6][5]. Its pricing consists of: - Provider Pricing: You pay exactly what the underlying AI provider charges for the models you use [4]. - Platform Fee: A 5.5% platform fee is applied to all usage [4]. - Costs are tracked per API request, and your account balance is deducted in USD [6][5]. Web Search Feature Eden AI's v3 LLM endpoints support native web search, which allows models to retrieve real-time information [1]. This feature is enabled by adding web_search_options to your chat completion request [1]. Not all models support this, so you should check model capabilities via the List LLM Models endpoint [1][7]. Firecrawl Integration Firecrawl is a separate web scraping and data extraction service [8]. It is not a built-in component of Eden AI; however, they can be used together in automated workflows via third-party integration platforms like viaSocket or Make [2][9][3]. - If you use Firecrawl to scrape data and then send it to Eden AI for processing, you will incur costs separately for both services based on their respective usage plans [4][5][3]. - You can manage these connections using visual automation builders without needing to write custom code [2][3]. For the most accurate and current information regarding Eden AI's specific model rates, you can use their info endpoints (e.g., GET /v3/info/{feature}/{subfeature}) to retrieve programmatic pricing data [10][11].

Citations:


Keep catalog rows aligned with their provider, model identifier, and price.

The changed rows rewrite provider/model identifiers without preserving unique catalog entries. This produces duplicate image IDs with conflicting prices and confusing Firecrawl/Linkup row labeling.

  • v3/expert-models/features/image/generation.mdx#L76-L78: Keep gpt-image-1, gpt-image-1.5, and gpt-image-1-mini on distinct image-generation IDs and prices, or remove those rows and keep only gpt-image-2.
  • v3/expert-models/features/web/research-async.mdx#L58: Keep the Firecrawl row as web/research_async/firecrawl, or remove/rename it if it should be linkup.
  • v3/expert-models/features/web/scraping.mdx#L60: Keep the Firecrawl row as web/scraping/firecrawl, or remove/rename it if it should be linkup.
  • v3/expert-models/features/web/search.mdx#L71: Keep the Firecrawl row as web/search/firecrawl, or remove/rename it if it should be linkup.
🧰 Tools
🪛 GitHub Check: Mintlify Validation (edenai) - vale-spellcheck

[warning] 76-76: v3/expert-models/features/image/generation.mdx#L76
Did you really mean 'openai'?


[warning] 77-77: v3/expert-models/features/image/generation.mdx#L77
Did you really mean 'openai'?


[warning] 78-78: v3/expert-models/features/image/generation.mdx#L78
Did you really mean 'openai'?

📍 Affects 4 files
  • v3/expert-models/features/image/generation.mdx#L76-L78 (this comment)
  • v3/expert-models/features/web/research-async.mdx#L58-L58
  • v3/expert-models/features/web/scraping.mdx#L60-L60
  • v3/expert-models/features/web/search.mdx#L71-L71
🤖 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 `@v3/expert-models/features/image/generation.mdx` around lines 76 - 78, Keep
each catalog row’s provider, model identifier, image-generation ID, and price
aligned: in v3/expert-models/features/image/generation.mdx lines 76-78, preserve
distinct IDs and prices for gpt-image-1, gpt-image-1.5, and gpt-image-1-mini, or
remove those rows and retain only gpt-image-2; in
v3/expert-models/features/web/research-async.mdx line 58,
v3/expert-models/features/web/scraping.mdx line 60, and
v3/expert-models/features/web/search.mdx line 71, keep each Firecrawl entry
under its corresponding /firecrawl ID or remove/rename it consistently as
linkup.

Comment on lines +110 to +115
-d '{"model": "azure/gpt-5.1-codex", "messages": [{"role": "user", "content": "ping"}]}'
```

### Model not found

Use the full `provider/model` string (e.g. `openai/gpt-5.1-codex`, not `gpt-5.1-codex`). Confirm the ID is in the catalog returned by `GET /v3/models`.
Use the full `provider/model` string (e.g. `azure/gpt-5.1-codex`, not `gpt-5.1-codex`). Confirm the ID is in the catalog returned by `GET /v3/models`.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== locate file =="
git ls-files | rg '^v3/integrations/codex-cli\.mdx$' || true

echo "== relevant excerpt =="
if [ -f v3/integrations/codex-cli.mdx ]; then
  nl -ba v3/integrations/codex-cli.mdx | sed -n '35,130p'
fi

echo "== search for codex references =="
rg -n "codex|wire_api|responses|chat/completions|gpt-5\.1-codex|Codex" v3/integrations/codex-cli.mdx || true

echo "== repo-wide codex occurrences (concise) =="
rg -n "codex|gpt-5\.1-codex|wire_api|v3/responses" . || true

echo "== git diff stat/name/status =="
git diff --stat || true
git diff -- v3/integrations/codex-cli.mdx | sed -n '1,220p' || true

Repository: edenai/docs

Length of output: 260


🏁 Script executed:

#!/bin/bash
set -euo pipefail

python3 - <<'PY'
from pathlib import Path
p = Path('v3/integrations/codex-cli.mdx')
if not p.exists():
    raise SystemExit
text = p.read_text()
lines = text.splitlines()
for needle in ['wire_api', 'chat/completions', '/v3/responses', 'gpt-5.1-codex', '"input"', '"messages"']:
    print(f'-- {needle!r} --')
    for i,l in enumerate(lines, 1):
        if needle in l:
            print(f'{i}: {l}')
PY

Repository: edenai/docs

Length of output: 1072


🌐 Web query:

OpenAI Codex responses endpoint vs chat completions wire_api responses responses endpoint input

💡 Result:

As of August 9, 2026, the OpenAI Codex ecosystem has fully transitioned to the Responses API for its primary interactions, with the legacy Chat Completions API deprecated and unsupported for Codex-specific workflows [1][2][3]. Key differences and status: 1. Relationship between APIs: The Responses API is an evolution of the Chat Completions API designed specifically to handle complex, agentic coding workflows [4]. While Chat Completions treats input as a simple list of messages, the Responses API uses a system of typed "Items" (e.g., messages, reasoning, function_call_outputs) and supports stateful features like previous_response_id for chaining interactions [4][2]. 2. Codex API Support: Codex models and the official Codex CLI/desktop app now exclusively use the wire_api = "responses" protocol [1][2]. The legacy Chat Completions API is considered an obsolete target for Codex and is no longer supported for new integrations [1][2][3]. Configurations or custom providers still attempting to use wire_api = "chat" will fail as support was fully removed in February 2026 [1]. 3. Endpoint and Implementation: - Official Codex traffic primarily utilizes relay endpoints such as https://chat-response.codex-openai.com/relay/responses or internal paths like https://chatgpt.com/backend-api/codex/responses [5][6][7]. - These endpoints are generally intended for first-party clients (the Codex or ChatGPT desktop apps) and require specific headers and authentication tokens (e.g., ChatGPT-Account-ID, OpenAI-Beta: responses=v1) [5][6]. - There is no publicly documented, stable contract for third-party clients to interface directly with these subscription-based relay endpoints; they are subject to internal changes, version coupling, and circuit-breaker protections [6][7]. Developers building integrations should use the standard OpenAI platform API rather than attempting to route through internal Codex relay endpoints, as the latter are designed for internal application state management rather than public API consumption [6].

Citations:


Use the Responses API for the Codex smoke test.

The provider sets wire_api = "responses", but the test sends a chat-completions request with messages. Replace it with a Responses request that uses input so a passing check actually exercises the configured protocol.

Proposed smoke-test correction
-curl -X POST https://api.edenai.run/v3/chat/completions \
+curl -X POST https://api.edenai.run/v3/responses \
   -H "Authorization: Bearer $EDENAI_API_KEY" \
   -H "Content-Type: application/json" \
-  -d '{"model": "azure/gpt-5.1-codex", "messages": [{"role": "user", "content": "ping"}]}'
+  -d '{"model": "azure/gpt-5.1-codex", "input": "ping"}'
📝 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.

Suggested change
-d '{"model": "azure/gpt-5.1-codex", "messages": [{"role": "user", "content": "ping"}]}'
```
### Model not found
Use the full `provider/model` string (e.g. `openai/gpt-5.1-codex`, not `gpt-5.1-codex`). Confirm the ID is in the catalog returned by `GET /v3/models`.
Use the full `provider/model` string (e.g. `azure/gpt-5.1-codex`, not `gpt-5.1-codex`). Confirm the ID is in the catalog returned by `GET /v3/models`.
curl -X POST https://api.edenai.run/v3/responses \
-H "Authorization: Bearer $EDENAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{"model": "azure/gpt-5.1-codex", "input": "ping"}'
🤖 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 `@v3/integrations/codex-cli.mdx` around lines 110 - 115, Update the Codex
smoke-test request in the documented command to use the Responses API: replace
the chat-completions messages payload with an input payload while retaining the
full azure/gpt-5.1-codex model identifier.

Comment thread v3/integrations/pi.mdx
name: "Eden AI",
api: "openai-completions",
baseUrl: "https://api.edenai.run/v3",
apiKey: process.env.EDEN_AI_API_KEY,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟡 Minor | ⚡ Quick win

Use the required production and sandbox token variables.

The new example reads process.env.EDEN_AI_API_KEY. V3 examples must use api_token for production and sandbox_api_token for testing. Rename the variable and update the adjacent environment or test fixture so test execution cannot use a production credential.

As per coding guidelines, distinguish api_token for production from sandbox_api_token for testing.

🤖 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 `@v3/integrations/pi.mdx` at line 52, Update the configuration example to use
the required production or sandbox token variable: replace the EDEN_AI_API_KEY
reference with the appropriate api_token or sandbox_api_token field, and update
the adjacent environment or test fixture consistently so tests cannot consume a
production credential.

Source: Coding guidelines

Comment on lines +49 to +52
| Google | `google/gemini-3.1-flash-image`, `google/gemini-3-pro-image`, `image/generation/google/imagen-4.0-generate-001` |
| OpenAI | `image/generation/openai/gpt-image-2`, `image/generation/openai/gpt-image-2` |
| Stability | `stabilityai/sd3.5-large` |
| Amazon | `amazon/amazon.nova-canvas-v1:0` |
| Amazon | `image/generation/amazon` |

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Locate file =="
git ls-files | grep -F 'v3/llms/image-generation.mdx' || true

echo "== Relevant file sections =="
if [ -f v3/llms/image-generation.mdx ]; then
  nl -ba v3/llms/image-generation.mdx | sed -n '1,140p;180,215p'
fi

echo "== References to image catalog and model IDs in docs =="
rg -n 'GET /v3/images/models|images/models|image/generation|gpt-image-2|imagen-4\.0|gemini-3' v3/llms/image-generation.mdx v3 -g '*.mdx' | head -200

Repository: edenai/docs

Length of output: 265


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Read relevant sections =="
awk '{printf "%6d\t%s\n", NR, $0}' v3/llms/image-generation.mdx | sed -n '1,160p;180,215p'

echo "== Search relevant model references =="
grep -nE 'GET /v3/images/models|images/models|image/generation|gpt-image-2|imagen-4\.0|gemini-3' v3/llms/image-generation.mdx v3 -g '*.mdx' | head -200 || true

Repository: edenai/docs

Length of output: 7806


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Search relevant model references =="
grep -RIn --glob '*.mdx' 'GET /v3/images/models\|images/models\|image/generation\|gpt-image-2\|imagen-4\.0\|gemini-3' v3 || true

echo "== Check runtime availability =="
command -v curl || true
command -v jq || true

Repository: edenai/docs

Length of output: 365


🌐 Web query:

Eden AI v3 images models provider model strings gpt-image-2 imagen-4.0-generate-001

💡 Result:

In the Eden AI v3 image generation API, models are accessed using a provider-prefixed format, typically expressed as provider/model_string [1][2]. For the models you mentioned, the expected Eden AI v3 model strings are: Google: google/imagen-4.0-generate-001 [1] OpenAI: openai/gpt-image-2 [2][3] The Eden AI v3 image API utilizes these strings within the model parameter of the request payload (e.g., in the /v3/images/generations or /v3/images/edits endpoints) [1][2]. Eden AI documentation notes that while it provides an OpenAI-compatible interface for these image models, you must use the full provider-prefixed string (such as openai/gpt-image-2) to correctly route the request to the desired backend provider [1][2]. You can retrieve a complete, real-time list of supported models and their exact strings by calling GET /v3/images/models or GET /v3/models via the Eden AI API [1].

Citations:


Use provider/model IDs in the image model table.

The /v3/images/* surface uses provider/model model strings, but the table includes Universal AI IDs such as image/generation/..., a duplicate OpenAI entry, and the Amazon row without a model suffix. Use /v3/images/models IDs like google/imagen-4.0-generate-001 and openai/gpt-image-2, and keep the list unique.

🤖 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 `@v3/llms/image-generation.mdx` around lines 49 - 52, Update the image model
table to use unique provider/model IDs matching the /v3/images/models format,
replacing Universal AI-prefixed values with IDs such as
google/imagen-4.0-generate-001 and openai/gpt-image-2. Remove the duplicate
OpenAI entry and replace the Amazon row’s incomplete ID with its
provider/model-specific model ID.

Sources: Coding guidelines, MCP tools

Some models are available under a **stable alias**, a version-agnostic name that always points to the current release, alongside versioned or dated snapshot IDs:

- **Stable alias:** `google/gemini-flash-latest`, `anthropic/claude-sonnet-latest`, `deepseek/deepseek-chat`
- **Stable alias:** `google/gemini-flash-latest`, `anthropic/claude-sonnet-4-6`, `deepseek/deepseek-chat`

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

model_json="$(
  curl -fsS https://api.edenai.run/v3/models |
    jq -c '.data[] | select(.id == "anthropic/claude-sonnet-4-6")'
)"

test -n "$model_json"
jq -e '(.alias_of // null) != null' <<<"$model_json"

Repository: edenai/docs

Length of output: 155


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

printf '--- relevant documentation context ---\n'
sed -n '90,120p' v3/llms/listing-models.mdx || true

printf '\n--- API response fields for anthropic/claude-sonnet-4-6 ---\n'
curl -fsS https://api.edenai.run/v3/models | jq '{id, alias_of, aliases}' | jq -s 'map(select(.id == "anthropic/claude-sonnet-4-6" or .id == "anthropic/claude-sonnet-latest"))'

printf '\n--- API response fields for anthropic/claude-sonnet-latest ---\n'
curl -fsS https://api.edenai.run/v3/models | jq '{id, alias_of, aliases}' | jq -s 'map(select(.id == "anthropic/claude-sonnet-latest"))'

Repository: edenai/docs

Length of output: 240


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

printf '%s\n' '--- relevant documentation context ---'
sed -n '90,120p' v3/llms/listing-models.mdx || true

printf '%s\n' ''
printf '%s\n' '--- API response fields for anthropic/claude-sonnet-4-6 ---'
curl -fsS https://api.edenai.run/v3/models | jq '{id, alias_of, aliases}' | jq -s 'map(select(.id == "anthropic/claude-sonnet-4-6" or .id == "anthropic/claude-sonnet-latest"))'

Repository: edenai/docs

Length of output: 1767


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

printf '%s\n' '--- API model lookup for anthropic/claude-sonnet-4-6 ---'
python3 - <<'PY'
import urllib.request, json
url = "https://api.edenai.run/v3/models"
with urllib.request.urlopen(url, timeout=20) as r:
    data = json.load(r)
for m in data.get("data", []):
    if "claude-sonnet-4-6" in m.get("id", "") or "claude-sonnet-latest" in m.get("id", ""):
        print(json.dumps({
            "id": m.get("id"),
            "alias_of": m.get("alias_of"),
            "aliases": m.get("aliases"),
        }, indent=2))
PY

printf '%s\n' ''
printf '%s\n' '--- Catalog model ids from API containing claud-sonnet or gemini-flash/latest patterns ---'
python3 - <<'PY'
import urllib.request, json
url = "https://api.edenai.run/v3/models"
with urllib.request.urlopen(url, timeout=20) as r:
    ids = [m.get("id") for m in json.load(r).get("data", [])]
for key in [
    "google/gemini-flash-latest",
    "anthropic/claude-sonnet-latest",
    "deepseek/deepseek-chat",
    "anthropic/claude-opus-4-5",
    "anthropic/claude-sonnet-4-6",
]:
    print(f"{key} -> {key in ids}")
PY

Repository: edenai/docs

Length of output: 2492


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

curl -fsSL --cacert /etc/ssl/certs/ca-certificates.crt https://api.edenai.run/v3/models > /tmp/edenai_models.json
python3 - <<'PY'
import json
from pathlib import Path
data = json.loads(Path("/tmp/edenai_models.json").read_text())
keys = [
    "google/gemini-flash-latest",
    "anthropic/claude-sonnet-latest",
    "deepseek/deepseek-chat",
    "anthropic/claude-opus-4-5",
    "anthropic/claude-sonnet-4-6",
    "google/gemini-3.6-flash",
]
for key in keys:
    hits = []
    for m in data.get("data", []):
        if key in m.get("id", "") or key == m.get("id"):
            hits.append({"id": m.get("id"), "alias_of": m.get("alias_of"), "aliases": m.get("aliases")})
    print(f"{key}:")
    print(json.dumps(hits, indent=2))
PY

Repository: edenai/docs

Length of output: 1120


Do not list anthropic/claude-sonnet-4-6 as a stable alias.

anthropic/claude-sonnet-latest is the version-agnostic alias_of-backed stable alias in the model catalog. Use anthropic/claude-sonnet-latest here, or move anthropic/claude-sonnet-4-6 to the versioned model section instead.

🧰 Tools
🪛 LanguageTool

[grammar] ~107-~107: Ensure spelling is correct
Context: ... alias:** google/gemini-flash-latest, anthropic/claude-sonnet-4-6, deepseek/deepseek-chat - Versioned snapshot: anthropic/claude-opus-4-5-20251101 Use the stable alias when you want y...

(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_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 `@v3/llms/listing-models.mdx` at line 107, Update the Stable alias entry in the
model listing to replace anthropic/claude-sonnet-4-6 with the catalog’s
alias_of-backed anthropic/claude-sonnet-latest, or remove the former from this
entry and list it under the versioned models section.

Source: MCP tools

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 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 `@tests/link_checker.py`:
- Around line 128-134: Update the request flow in the link-checking function
around _classify_host so redirects are not followed automatically; disable
redirect handling for both the HEAD request and GET fallback, then parse and
validate every Location target with _classify_host before issuing the next
request, rejecting private or link-local destinations.
- Around line 31-36: Update _classify_host so transient socket.gaierror results
are not retained by the process-wide `@cache`; ensure DNS failures can be retried
for later links while preserving caching for successful classifications,
preferably with a bounded lifetime as requested.
🪄 Autofix

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: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 9b28f335-6a30-4927-87f1-4b257148707d

📥 Commits

Reviewing files that changed from the base of the PR and between 4cbfa8d and 400d292.

📒 Files selected for processing (8)
  • .github/workflows/test-snippets.yml
  • index.mdx
  • tests/README.md
  • tests/config_validator.py
  • tests/link_checker.py
  • tests/ts/snippets.test.ts
  • v2/index.mdx
  • v3/overview/ai-gateway.mdx
🚧 Files skipped from review as they are similar to previous changes (6)
  • index.mdx
  • v2/index.mdx
  • v3/overview/ai-gateway.mdx
  • tests/README.md
  • tests/config_validator.py
  • .github/workflows/test-snippets.yml

Comment thread tests/link_checker.py Outdated
Comment thread tests/link_checker.py Outdated
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