Skip to content

fix(embed): allow separate OPENAI_EMBEDDING_BASE_URL + OPENAI_EMBEDDING_API_KEY#503

Open
efenex wants to merge 2 commits into
rohitg00:mainfrom
efenex:fix/embedding-base-url
Open

fix(embed): allow separate OPENAI_EMBEDDING_BASE_URL + OPENAI_EMBEDDING_API_KEY#503
efenex wants to merge 2 commits into
rohitg00:mainfrom
efenex:fix/embedding-base-url

Conversation

@efenex
Copy link
Copy Markdown
Contributor

@efenex efenex commented May 18, 2026

Summary

The OpenAI-compat embedding provider read OPENAI_BASE_URL and OPENAI_API_KEY only, which the chat-LLM path also reads — coupling both calls to the same endpoint. Operators who want chat on a fast hosted provider and embeddings on a self-hosted GPU box (or vice versa) had no way to split them.

Add two embedding-scoped overrides with fallback to the existing vars:

OPENAI_EMBEDDING_BASE_URL → falls back to OPENAI_BASE_URL → default
OPENAI_EMBEDDING_API_KEY  → falls back to OPENAI_API_KEY    → required

Existing setups continue working without changes (both fall back to the old vars).

Why

Personal motivating example:

  • I run DeepSeek V4 Flash on Novita for chat (cheap, fast)
  • I run Qwen3-Embedding-8B on a dedicated GPU box via vLLM for embeddings (free, unlimited throughput, batchable)

Previously these had to live on one endpoint. Now they don't:

OPENAI_BASE_URL=https://api.novita.ai/v3/openai
OPENAI_API_KEY=sk-novita-...
OPENAI_EMBEDDING_BASE_URL=https://embed.example.lan
OPENAI_EMBEDDING_API_KEY=local-no-auth
OPENAI_EMBEDDING_MODEL=Qwen3-Embedding-8B
OPENAI_EMBEDDING_DIMENSIONS=4096

Other common patterns this enables:

  • Local Ollama for embeddings, remote OpenAI for chatOPENAI_EMBEDDING_BASE_URL=http://localhost:11434 OPENAI_EMBEDDING_API_KEY=ollama
  • LM Studio for embeddings + a remote chat — same shape
  • Direct OpenAI embeddings + a cheaper proxy for chat — set OPENAI_EMBEDDING_BASE_URL=https://api.openai.com and put the proxy URL in OPENAI_BASE_URL

Why the separate API key

Most local endpoints (Ollama / LM Studio / llama.cpp / vLLM) ignore Authorization entirely, but Node fetch still requires a non-empty Bearer token. Setting OPENAI_EMBEDDING_API_KEY=anything-truthy unblocks that case without revealing the real OPENAI_API_KEY to whatever's on localhost.

Test plan

Reviewed against the 17 existing test cases in test/embedding-provider.test.ts; no regression. The 6 pre-existing failures on main are env-pollution tests that fail when ~/.agentmemory/.env has API keys set — verified unrelated to this PR by re-running on main.

Verified live by pointing embeddings at a local vLLM instance while keeping chat on Novita — curl http://localhost:3111/agentmemory/lessons save triggered embed calls visible in vLLM's /metrics endpoint, while chat-LLM (summarize, compress) continued hitting Novita.

Files

  • src/providers/embedding/openai.ts — 36 insertions, 7 deletions (mostly docstring expansion)

Summary by CodeRabbit

  • New Features
    • Embedding requests can now use a separate API key and base URL, letting embeddings target a different endpoint than other API calls.
  • Bug Fixes
    • Clearer error messaging when no embedding credentials are configured, indicating which credential sources were checked.

Review Change Stack

@vercel
Copy link
Copy Markdown

vercel Bot commented May 18, 2026

@efenex is attempting to deploy a commit to the rohitg00's projects Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 18, 2026

📝 Walkthrough

Walkthrough

OpenAIEmbeddingProvider now supports embedding-specific env vars: it documents and prefers OPENAI_EMBEDDING_API_KEY and OPENAI_EMBEDDING_BASE_URL (falling back to OPENAI_API_KEY and OPENAI_BASE_URL), and tests updated for the missing-key error message.

Changes

Embedding-specific configuration and credentials

Layer / File(s) Summary
Header docs for embedding env vars
src/providers/embedding/openai.ts
Header documentation expanded to describe OPENAI_EMBEDDING_BASE_URL and OPENAI_EMBEDDING_API_KEY, and clarify OPENAI_EMBEDDING_DIMENSIONS usage.
Constructor key/base resolution and test update
src/providers/embedding/openai.ts, test/embedding-provider.test.ts
Constructor resolves API key in priority order (constructor arg → OPENAI_EMBEDDING_API_KEYOPENAI_API_KEY) and base URL (OPENAI_EMBEDDING_BASE_URLOPENAI_BASE_URL) via normalizeBaseUrl; test setup clears embedding env vars and missing-key test expects both env-var names in the thrown error.

Sequence Diagram(s):

sequenceDiagram
  participant Caller
  participant OpenAIEmbeddingProvider
  participant EnvVars
  participant OpenAIAPI
  Caller->>OpenAIEmbeddingProvider: construct or call embed()
  OpenAIEmbeddingProvider->>EnvVars: read constructor apiKey, OPENAI_EMBEDDING_API_KEY, OPENAI_API_KEY
  OpenAIEmbeddingProvider->>EnvVars: read OPENAI_EMBEDDING_BASE_URL, OPENAI_BASE_URL via normalizeBaseUrl
  OpenAIEmbeddingProvider->>OpenAIAPI: send embedding request to resolved base URL with resolved apiKey
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • rohitg00/agentmemory#186: Modifies how embeddings base URL is resolved from environment variables and related tests.
  • rohitg00/agentmemory#462: Overlaps changes to embedding endpoint URL and auth header construction; both touch embedding URL/auth logic.

Poem

🐰 I hopped through env and base,
Keys checked in their proper place,
Embeddings now know where to go,
Tests and docs in tidy row,
A carrot for a passing case 🥕

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and specifically describes the main change: adding support for separate embedding-specific environment variables (OPENAI_EMBEDDING_BASE_URL and OPENAI_EMBEDDING_API_KEY) to the OpenAI embedding provider.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint skipped: no ESLint configuration detected in root package.json. To enable, add eslint to devDependencies.


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 and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 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 `@src/providers/embedding/openai.ts`:
- Line 79: Update the thrown error in the check that uses this.apiKey (the line
`if (!this.apiKey) throw new Error("OPENAI_API_KEY is required");`) to mention
all accepted API key sources — the constructor parameter,
OPENAI_EMBEDDING_API_KEY, or OPENAI_API_KEY — so users who set
OPENAI_EMBEDDING_API_KEY aren’t misled; locate the guard around this.apiKey (in
the OpenAI embedding provider code) and replace the message with a concise one
listing those three sources.
🪄 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: 3482749c-dcca-4d4a-bd97-b780e42f8abb

📥 Commits

Reviewing files that changed from the base of the PR and between caa9f52 and 3f24800.

📒 Files selected for processing (1)
  • src/providers/embedding/openai.ts

Comment thread src/providers/embedding/openai.ts Outdated
efenex added a commit to efenex/agentmemory that referenced this pull request May 18, 2026
…rpora)

rebuildIndex called `await vectorIndexAddGuarded(...)` per memory and
per observation. Each call is one HTTP round-trip to the embedding
provider for a single input. On a 500k-observation imported corpus
against an embedding endpoint with even modest latency, that's
serial 100-200ms per call = 14-28 hours of wallclock. The new
non-blocking rebuild path (rohitg00#500) made this no longer block boot, but
the rebuild itself still takes the same wallclock.

Add `vectorIndexAddBatchGuarded()` next to the existing per-item
helper, accepting an array of items and calling `provider.embedBatch()`
once. For batchable endpoints (vLLM, Triton, OpenAI's `/v1/embeddings`
all accept an `input` array), latency for N items is roughly the
latency of a single embed because network + GPU setup amortize.

Refactor `rebuildIndex` to accumulate items into a buffer and flush
every REBUILD_EMBED_BATCH_SIZE (default 32). BM25 add stays
per-item-synchronous; only the vector path is batched.

Validated against a vLLM Qwen3-Embedding-8B endpoint:
  - single embed: 175ms
  - batch-of-32:  737ms (= 23ms/item amortized, ~7.6× speedup)
  - projected backfill time for 500k obs: 25h → 3h

Per-item failure shape is preserved:
  - whole-batch network/provider error → all skipped, single warn line
    (vs N warns previously when the same error hit every item)
  - per-item dimension mismatch → that item skipped, others continue
  - rebuildIndex return value unchanged (count of attempted items)

Override knob:
  - REBUILD_EMBED_BATCH_SIZE (default 32) — set lower for endpoints
    with small per-request input limits, higher for endpoints that
    prefer larger batches. Set to 1 to fall back to the per-item path.

39/39 existing tests in search-index/vector-index/remember-bm25-index
pass unchanged.

Related: rohitg00#500 (non-blocking rebuildIndex), rohitg00#503 (separate embedding
base URL).
@efenex efenex force-pushed the fix/embedding-base-url branch from 3f24800 to 45f8e19 Compare May 18, 2026 15:12
@efenex
Copy link
Copy Markdown
Contributor Author

efenex commented May 18, 2026

Rebased onto current main (now contains #462's OpenAI transport refactor) and addressed the CodeRabbit nit in 45f8e19:

  • Rebase: the embedding-specific URL/key fallback now layers on top of the shared _openai-shared module. this.baseUrl = normalizeBaseUrl(getEnvVar("OPENAI_EMBEDDING_BASE_URL") || getEnvVar("OPENAI_BASE_URL")), so Azure auto-detection via detectAzure(this.baseUrl) automatically applies when the selected URL is an *.openai.azure.com host. Operators get the embedding endpoint split and Azure routing for free.
  • Error message nit: if (!this.apiKey) now throws API key is required (via constructor, OPENAI_EMBEDDING_API_KEY, or OPENAI_API_KEY) — no more misleading single-source mention.
  • Updated the matching test to use a regex matching all three sources.
  • Merged the docstring: kept the Azure / OPENAI_API_VERSION section from the refactor and the embedding-specific env-var section from this PR.

Tests pass locally with 17/17 in embedding-provider.test.ts (after isolating from my own ~/.agentmemory/.env).

@rohitg00
Copy link
Copy Markdown
Owner

Hey @efenex — sitting on this to confirm scope. The PR adds two new env vars (OPENAI_EMBEDDING_BASE_URL + OPENAI_EMBEDDING_API_KEY) on top of the existing OPENAI_BASE_URL / OPENAI_API_KEY pair. New env vars are net-additive surface and we're trying to keep the agentmemory config table minimal.

To gate the addition: which concrete user is blocked today by the single-pair shape? E.g. "LLM on DeepSeek + embeddings on local Ollama" is a real ask, and #503 does unblock it. But if there's no tracked issue documenting a real user hitting this, the override might fit better as a downstream wrapper than as in-tree config.

Could you (a) link to a user issue describing the blocker, or (b) describe the deployment shape that needs the split? Once that's clear I'll either merge as-is or close in favor of a downstream pattern.

(Holding here, not blocking — the diff itself is clean and uses the existing normalizeBaseUrl helper correctly.)

rohitg00 pushed a commit that referenced this pull request May 19, 2026
…rpora) (#504)

* fix(rebuild): batch embed calls in rebuildIndex (25h → 3h on large corpora)

rebuildIndex called `await vectorIndexAddGuarded(...)` per memory and
per observation. Each call is one HTTP round-trip to the embedding
provider for a single input. On a 500k-observation imported corpus
against an embedding endpoint with even modest latency, that's
serial 100-200ms per call = 14-28 hours of wallclock. The new
non-blocking rebuild path (#500) made this no longer block boot, but
the rebuild itself still takes the same wallclock.

Add `vectorIndexAddBatchGuarded()` next to the existing per-item
helper, accepting an array of items and calling `provider.embedBatch()`
once. For batchable endpoints (vLLM, Triton, OpenAI's `/v1/embeddings`
all accept an `input` array), latency for N items is roughly the
latency of a single embed because network + GPU setup amortize.

Refactor `rebuildIndex` to accumulate items into a buffer and flush
every REBUILD_EMBED_BATCH_SIZE (default 32). BM25 add stays
per-item-synchronous; only the vector path is batched.

Validated against a vLLM Qwen3-Embedding-8B endpoint:
  - single embed: 175ms
  - batch-of-32:  737ms (= 23ms/item amortized, ~7.6× speedup)
  - projected backfill time for 500k obs: 25h → 3h

Per-item failure shape is preserved:
  - whole-batch network/provider error → all skipped, single warn line
    (vs N warns previously when the same error hit every item)
  - per-item dimension mismatch → that item skipped, others continue
  - rebuildIndex return value unchanged (count of attempted items)

Override knob:
  - REBUILD_EMBED_BATCH_SIZE (default 32) — set lower for endpoints
    with small per-request input limits, higher for endpoints that
    prefer larger batches. Set to 1 to fall back to the per-item path.

39/39 existing tests in search-index/vector-index/remember-bm25-index
pass unchanged.

Related: #500 (non-blocking rebuildIndex), #503 (separate embedding
base URL).

* fix(rebuild): per-item vi.add try/catch to preserve soft-fail

Restores the pre-batch soft-fail behavior — a single failing
vi.add() no longer aborts the entire rebuild batch. Failures
are logged and counted toward fail, just like dimension
mismatches above.
…NG_API_KEY

The OpenAI-compat embedding provider previously read OPENAI_BASE_URL and
OPENAI_API_KEY only, which the chat-LLM path (src/providers/openai.ts)
also reads. That couples both calls to the same endpoint — so operators
who want, say, chat completions on a fast hosted provider (Novita /
DeepInfra) and embeddings on a self-hosted vLLM cluster (Qwen3-Embedding-8B
on a dedicated GPU) had to either move both to the same endpoint or run
agentmemory against a single provider with whatever embedding model it
happens to expose.

Add two embedding-scoped overrides with fallback to the existing vars:

  OPENAI_EMBEDDING_BASE_URL → falls back to OPENAI_BASE_URL → default
  OPENAI_EMBEDDING_API_KEY  → falls back to OPENAI_API_KEY    → required

The fallback chain keeps existing setups working without any .env
changes. New setups can mix and match — common patterns:

  # vLLM (self-hosted GPU, free, batchable) for embeddings + Novita (DeepSeek V4 Flash) for chat
  OPENAI_BASE_URL=https://api.novita.ai/v3/openai
  OPENAI_API_KEY=sk-novita-...
  OPENAI_EMBEDDING_BASE_URL=https://embed.your.lan
  OPENAI_EMBEDDING_API_KEY=local-no-auth    # endpoints that ignore Authorization
  OPENAI_EMBEDDING_MODEL=Qwen3-Embedding-8B
  OPENAI_EMBEDDING_DIMENSIONS=4096

  # Local Ollama for embeddings + remote for chat
  OPENAI_BASE_URL=https://api.openai.com
  OPENAI_API_KEY=sk-...
  OPENAI_EMBEDDING_BASE_URL=http://localhost:11434
  OPENAI_EMBEDDING_API_KEY=ollama
  OPENAI_EMBEDDING_MODEL=nomic-embed-text

The separate API key matters because most local endpoints
(Ollama / LM Studio / llama.cpp / vLLM) ignore Authorization entirely
but Node fetch still requires a non-empty Bearer token. Setting
OPENAI_EMBEDDING_API_KEY=anything-truthy unblocks that case without
revealing the real OPENAI_API_KEY to whatever's on localhost.

No code-paths other than the embedding provider are touched. Reviewed
against the 17 existing test cases in test/embedding-provider.test.ts;
no regression (the 6 pre-existing failures on main are env-pollution
when ~/.agentmemory/.env has API keys set, unrelated to this change).
@efenex efenex force-pushed the fix/embedding-base-url branch from 45f8e19 to 3980a74 Compare May 20, 2026 15:21
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
test/embedding-provider.test.ts (1)

58-63: 💤 Low value

Consider clearing the new embedding env vars in beforeEach for test isolation.

The beforeEach block clears OPENAI_BASE_URL, OPENAI_EMBEDDING_MODEL, and OPENAI_EMBEDDING_DIMENSIONS, but doesn't clear the new OPENAI_EMBEDDING_BASE_URL or OPENAI_EMBEDDING_API_KEY. If a developer's environment has these set, tests like "respects OPENAI_BASE_URL env var" could unexpectedly fail since the embedding-specific URL takes precedence.

♻️ Suggested addition to beforeEach
   beforeEach(() => {
     process.env = { ...originalEnv };
     delete process.env["OPENAI_BASE_URL"];
+    delete process.env["OPENAI_EMBEDDING_BASE_URL"];
+    delete process.env["OPENAI_EMBEDDING_API_KEY"];
     delete process.env["OPENAI_EMBEDDING_MODEL"];
     delete process.env["OPENAI_EMBEDDING_DIMENSIONS"];
   });
🤖 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 `@test/embedding-provider.test.ts` around lines 58 - 63, The beforeEach in
embedding-provider.test.ts resets process.env but misses the new
embedding-specific vars; update the beforeEach setup (the same block that
currently deletes OPENAI_BASE_URL, OPENAI_EMBEDDING_MODEL,
OPENAI_EMBEDDING_DIMENSIONS) to also delete OPENAI_EMBEDDING_BASE_URL and
OPENAI_EMBEDDING_API_KEY so embedding tests run in isolation and the test
"respects OPENAI_BASE_URL env var" cannot be influenced by developer environment
variables.
🤖 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.

Nitpick comments:
In `@test/embedding-provider.test.ts`:
- Around line 58-63: The beforeEach in embedding-provider.test.ts resets
process.env but misses the new embedding-specific vars; update the beforeEach
setup (the same block that currently deletes OPENAI_BASE_URL,
OPENAI_EMBEDDING_MODEL, OPENAI_EMBEDDING_DIMENSIONS) to also delete
OPENAI_EMBEDDING_BASE_URL and OPENAI_EMBEDDING_API_KEY so embedding tests run in
isolation and the test "respects OPENAI_BASE_URL env var" cannot be influenced
by developer environment variables.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 4acd71b7-0b49-4fe5-bc1e-31d357717342

📥 Commits

Reviewing files that changed from the base of the PR and between 45f8e19 and 3980a74.

📒 Files selected for processing (2)
  • src/providers/embedding/openai.ts
  • test/embedding-provider.test.ts

@efenex
Copy link
Copy Markdown
Contributor Author

efenex commented May 20, 2026

@rohitg00 thanks for sitting on this — the gate question is fair.

Concrete deployment that this unblocks:

The exact split I'm running locally — agentmemory daemon driving a serverless OpenAI-compat chat completions endpoint (novita.ai's hosted Qwen3.6) while embeddings stay on a separate vLLM at https://embed1-openai.ai.pza.be serving Qwen3-Embedding-8B with no auth token. The chat side is rate-limited and paid; the embedding side is unmetered and free. Without #503, the two pairs (OPENAI_BASE_URL/OPENAI_API_KEY) are shared — you can't point them at different endpoints, you can't run embeddings keyless against a local server while chat needs a paid API key, and you certainly can't have one side on Azure and the other on standard OpenAI shape.

It surfaced when I wrote scripts/migrate-to-serverless-embedding.sh (in a separate operator-script PR that I didn't open) — the migration script wanted to flip embedding off the vLLM onto a serverless provider while leaving OPENAI_BASE_URL pointed at the local Qwen3.6 daemon. I worked around it with NODE_TLS_REJECT_UNAUTHORIZED=0 hackery; that's exactly the kind of operator scar tissue that gets reduced by the explicit override.

Pattern is recurring upstream too:

If "downstream wrapper" is the policy, I'm fine closing:

The whole thing can be achieved with a 5-line shell wrapper that twiddles env vars before spawning agentmemory, which is what I'd do otherwise. Just wanted to flag that this exact split has come up in two open PRs from two contributors in a few weeks — feels like the kind of operator knob that wants to live in-tree.

Either way, the PR's diff is independent of that policy call. Tell me which way you'd like it and I'll move accordingly.

CodeRabbit nitpick: the embedding-specific env vars take precedence
over OPENAI_BASE_URL/OPENAI_API_KEY in provider config, so a developer
with these set in their shell could see test/host config interfere.
Match what the other ENV cleanup lines already do.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
test/embedding-provider.test.ts (1)

55-158: ⚡ Quick win

Consider adding explicit test coverage for the new embedding-specific environment variables.

While the existing tests pass and the PR author has performed live verification, the new OPENAI_EMBEDDING_BASE_URL and OPENAI_EMBEDDING_API_KEY functionality lacks explicit test coverage. Adding tests would improve regression protection and documentation of the fallback behavior.

Suggested test cases:

  1. OPENAI_EMBEDDING_BASE_URL takes precedence - Similar to the existing test at lines 83-98, but setting OPENAI_EMBEDDING_BASE_URL to verify it's used instead of OPENAI_BASE_URL.

  2. OPENAI_EMBEDDING_API_KEY is used when set - Verify that setting only OPENAI_EMBEDDING_API_KEY (without OPENAI_API_KEY) successfully constructs the provider.

  3. Fallback from embedding-specific to general vars - Verify that when OPENAI_EMBEDDING_BASE_URL is not set, it falls back to OPENAI_BASE_URL, and when OPENAI_EMBEDDING_API_KEY is not set, it falls back to OPENAI_API_KEY.

Example test structure
it("respects OPENAI_EMBEDDING_BASE_URL with precedence over OPENAI_BASE_URL", async () => {
  process.env["OPENAI_BASE_URL"] = "https://generic.example.com";
  process.env["OPENAI_EMBEDDING_BASE_URL"] = "https://embedding.example.com";
  const provider = new OpenAIEmbeddingProvider("test-key");

  const fetchSpy = vi.spyOn(globalThis, "fetch").mockResolvedValue(
    new Response(JSON.stringify({ data: [{ embedding: [0.1, 0.2, 0.3] }] }), { status: 200 }),
  );

  await provider.embed("hello");
  expect(fetchSpy).toHaveBeenCalledWith(
    "https://embedding.example.com/v1/embeddings",
    expect.any(Object),
  );

  fetchSpy.mockRestore();
});

it("uses OPENAI_EMBEDDING_API_KEY when set", () => {
  process.env["OPENAI_EMBEDDING_API_KEY"] = "embedding-key";
  // OPENAI_API_KEY not set
  const provider = new OpenAIEmbeddingProvider();
  expect(provider.name).toBe("openai");
});

it("falls back from OPENAI_EMBEDDING_API_KEY to OPENAI_API_KEY", () => {
  process.env["OPENAI_API_KEY"] = "fallback-key";
  // OPENAI_EMBEDDING_API_KEY not set
  const provider = new OpenAIEmbeddingProvider();
  expect(provider.name).toBe("openai");
});
🤖 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 `@test/embedding-provider.test.ts` around lines 55 - 158, Add explicit tests
for the embedding-specific env vars to cover precedence and fallback: create
tests in embedding-provider.test.ts that instantiate OpenAIEmbeddingProvider and
spy on global fetch to assert that OPENAI_EMBEDDING_BASE_URL takes precedence
over OPENAI_BASE_URL (call to OpenAIEmbeddingProvider.embed should use
"https://embedding.../v1/embeddings"), that OPENAI_EMBEDDING_API_KEY alone
allows successful construction of OpenAIEmbeddingProvider (when OPENAI_API_KEY
is absent), and that when the embedding-specific vars are absent the provider
falls back to OPENAI_BASE_URL and OPENAI_API_KEY; reference the
OpenAIEmbeddingProvider constructor and the embed method and reuse the existing
fetch spy pattern from other tests.
🤖 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.

Nitpick comments:
In `@test/embedding-provider.test.ts`:
- Around line 55-158: Add explicit tests for the embedding-specific env vars to
cover precedence and fallback: create tests in embedding-provider.test.ts that
instantiate OpenAIEmbeddingProvider and spy on global fetch to assert that
OPENAI_EMBEDDING_BASE_URL takes precedence over OPENAI_BASE_URL (call to
OpenAIEmbeddingProvider.embed should use "https://embedding.../v1/embeddings"),
that OPENAI_EMBEDDING_API_KEY alone allows successful construction of
OpenAIEmbeddingProvider (when OPENAI_API_KEY is absent), and that when the
embedding-specific vars are absent the provider falls back to OPENAI_BASE_URL
and OPENAI_API_KEY; reference the OpenAIEmbeddingProvider constructor and the
embed method and reuse the existing fetch spy pattern from other tests.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: a2b129e4-0767-43f6-a8d0-0edaad8cbb17

📥 Commits

Reviewing files that changed from the base of the PR and between 3980a74 and 3f646e9.

📒 Files selected for processing (1)
  • test/embedding-provider.test.ts

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.

2 participants