Skip to content

feat: cloud provider catalog (Azure OpenAI, Bedrock, Vertex) + embeddings capability (§3.4)#335

Open
gnanirahulnutakki wants to merge 6 commits into
devfrom
feat/cloud-providers-embeddings-2026-07-14
Open

feat: cloud provider catalog (Azure OpenAI, Bedrock, Vertex) + embeddings capability (§3.4)#335
gnanirahulnutakki wants to merge 6 commits into
devfrom
feat/cloud-providers-embeddings-2026-07-14

Conversation

@gnanirahulnutakki

@gnanirahulnutakki gnanirahulnutakki commented Jul 14, 2026

Copy link
Copy Markdown
Member

Summary

Extends ardur-agent's model/LLM provider breadth per a lane assignment to own this domain. plans/3.0 already unifies the Provider trait and plans/3.1-3.3/12.5 already implement Anthropic, OpenAI-compatible, Ollama, OpenRouter, and Claude Code CLI — all left untouched. No blueprint existed for AWS Bedrock, Google Vertex, Azure OpenAI, or an embeddings capability (they appeared only as an unwritten future-catalog name-check), so a plans/3.4 design doc was authored first (local-only; plans/ is gitignored in this repo and synced by the docs-resync lane) and these crates were built against it:

  • ardur-provider-runtime: new EmbeddingProvider trait (separate from Provider — not every backend offers both capabilities) + EmbeddingProviderRegistry.
  • ardur-provider-azure-openai: real HTTP against Azure's resource/deployment-scoped Chat Completions + Embeddings endpoints, plus real incremental SSE streaming (a hand-rolled line-buffered decoder — Azure's streaming wire framing is byte-identical to OpenAI's).
  • ardur-provider-bedrock: real HTTP against Bedrock Runtime's InvokeModel/InvokeModelWithResponseStream for Anthropic Claude models, authenticated with a hand-rolled AWS SigV4 signer (built on sha2+hmac, already workspace deps — no aws-sdk/aws-sigv4 pulled in). Streaming decodes AWS's binary application/vnd.amazon.eventstream framing (length-prefixed frames + CRC32 — hand-rolled, checked against the standard test vector) and maps the base64-wrapped Anthropic-native streaming events onto the shared protocol.
  • ardur-provider-vertex: real HTTP against Vertex's generateContent/streamGenerateContent?alt=sse for Gemini models. Standard Vertex auth needs an RS256 service-account JWT and the workspace has no RSA crate, so Phase 1 takes a pre-minted bearer token via ARDUR_VERTEX_ACCESS_TOKEN rather than adding new asymmetric-crypto dependencies without separate review (flagged as a Phase 2 TODO).
  • ardur-provider-selector: wired all three in (ARDUR_PROVIDER=azure-openai|bedrock|vertex).

All three new providers implement tool-calling via the shared ToolDef/ToolCall envelope and now have real incremental streaming parity with the existing five providers (supports_streaming() == true, no longer wrapping the trait-default single-shot complete() call).

Test plan

  • cargo test -p ardur-provider-runtime — EmbeddingProvider trait
  • cargo test -p ardur-provider-azure-openai — 14 unit + 4 wiremock e2e (chat + embeddings + streaming + 401 mapping)
  • cargo test -p ardur-provider-bedrock — 21 unit (incl. SigV4 signer + event-stream frame decoder + CRC32) + 3 wiremock e2e (complete + tool_use + full sign→frame→decode streaming round-trip)
  • cargo test -p ardur-provider-vertex — 12 unit + 4 wiremock e2e (complete + function-call + streaming + 401 mapping)
  • cargo test -p ardur-provider-selector — 12 unit + 12 env-integration (incl. 3 new azure/bedrock/vertex cases)
  • cargo fmt --check — clean
  • cargo build --workspace — green
  • cargo clippy --workspace --all-targets -- -D warnings — green
  • cargo test --workspace — green (317 test result: ok blocks, 0 failures, verified via direct exit code not a piped tail)

No live credentials required for any of the above — every provider ships a wiremock-backed stub test (including real SSE / binary-eventstream bytes for the streaming paths), matching the §3.1 pattern. Live-credential smoke tests, Bedrock/Vertex embeddings, and Vertex local service-account JWT minting are documented Phase 2 follow-ups.

Gnani Nutakki added 2 commits July 14, 2026 02:09
Adds the text-embedding sibling of the §3.0 Provider trait: a separate
object-safe EmbeddingProvider (embed/id/embedding_dim/rate_card) plus an
EmbeddingProviderRegistry, matching ProviderRegistry's shape. Kept separate
from Provider rather than added as a method, since not every backend offers
both capabilities (Anthropic has no embeddings endpoint).

Checkpoint: architect/sessions/cloud-providers-embeddings-2026-07-14/journal.md
Signed-off-by: Gnani Nutakki <gnani.nutakki@gmail.com>
No prior blueprint covered these three clouds — plans/3.0-3.3 and 12.5 cover
Anthropic/OpenAI/Ollama/OpenRouter/Claude-CLI only, and Bedrock/Vertex/Azure
appeared solely as an unwritten future-catalog name-check. Authored
plans/3.4 (local design doc; plans/ is gitignored here and synced by the
docs-resync lane) and built these three Provider implementations against it:

- ardur-provider-azure-openai: real HTTP against Azure's resource/deployment
  -scoped Chat Completions + Embeddings endpoints (api-key header).
- ardur-provider-bedrock: real HTTP against Bedrock Runtime's InvokeModel for
  Anthropic Claude models, authenticated with a hand-rolled AWS SigV4 signer
  (sha2+hmac, already workspace deps — no aws-sdk/aws-sigv4 pulled in for one
  signed POST).
- ardur-provider-vertex: real HTTP against Vertex's generateContent for
  Gemini models. Standard Vertex auth needs an RS256 service-account JWT and
  the workspace has no RSA crate; Phase 1 takes a pre-minted bearer token via
  ARDUR_VERTEX_ACCESS_TOKEN instead of adding new asymmetric-crypto deps
  without separate review.

All three implement tool-calling via the shared ToolDef/ToolCall envelope;
supports_streaming() is false for all three (Phase 2 TODO — each cloud's
incremental path is a distinct wire protocol from the shared SSE type), so
Provider::stream's trait default wraps one complete() call, matching the
non-streaming precedent provider-codex/provider-claude-cli already set.

Wires all three into provider-selector (ARDUR_PROVIDER=azure-openai|bedrock
|vertex). Each crate ships unit tests plus a wiremock e2e-stub test of its
public surface; provider-selector gains matching from_env integration tests.

cargo build --workspace / clippy --workspace --all-targets -D warnings /
test --workspace all green.

Checkpoint: architect/sessions/cloud-providers-embeddings-2026-07-14/journal.md
Signed-off-by: Gnani Nutakki <gnani.nutakki@gmail.com>
@coderabbitai

coderabbitai Bot commented Jul 14, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: c7db7de5-cc18-4182-abca-b1dd23f3d14a

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/cloud-providers-embeddings-2026-07-14

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

Gnani Nutakki and others added 4 commits July 14, 2026 02:30
…ex (§3.4)

Closes the streaming-parity gap left by the initial cloud-provider drop:
all three previously wrapped Provider::stream's trait default (a single-shot
complete() call). Now each has a real incremental decoder and
supports_streaming() == true:

- Azure OpenAI: hand-rolled line-buffered SSE decoder (wire framing is
  byte-identical to OpenAI's) — no eventsource-stream dependency, matching
  provider-openai-compat's established pattern.
- Vertex: streamGenerateContent?alt=sse (Gemini's documented SSE mode), same
  line-buffered approach. Gemini streams whole functionCalls per chunk
  rather than incremental argument fragments.
- Bedrock: InvokeModelWithResponseStream answers with AWS's binary
  application/vnd.amazon.eventstream framing, not SSE — a new eventstream.rs
  hand-rolls the generic frame decoder (length-prefixed messages + CRC32,
  checked against the standard "123456789" test vector; no crc32fast/
  aws-eventstream crate pulled in), and streaming.rs maps the base64-wrapped
  Anthropic-native streaming events (message_start/content_block_start/
  content_block_delta/content_block_stop/message_delta/message_stop) onto
  the shared StreamEvent protocol.

Every provider ships a full E2E streaming test driving the real public
Provider::stream() method through actual wiremock-served SSE/event-stream
bytes (Bedrock's through a real SigV4-signed, CRC-valid binary frame feed) —
not just unit tests of the decode functions in isolation.

cargo build --workspace / clippy --workspace --all-targets -D warnings /
test --workspace all green (317 test-result blocks, 0 failures).

Checkpoint: architect/sessions/cloud-providers-embeddings-2026-07-14/journal.md
Signed-off-by: Gnani Nutakki <gnani.nutakki@gmail.com>
…ry and parse_retry_after_ms

Signed-off-by: ArdurAI <team@ardur.ai>
…mbeddings-2026-07-14

Signed-off-by: ArdurAI <team@ardur.ai>
Signed-off-by: ArdurAI <team@ardur.ai>
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