infrastructure tier

infrastructure-ai

_No description in Cargo.toml._

Tierinfrastructure
Roleunclassified (baselined)
Pathcrates/infrastructure/ai
Edition2021
Targetsinfrastructure_ai, connection_setup_smoke
Public items4 across 2 modules
Tests72

What it is for

Library crates for AI provider integration.

Provides a pluggable interface for AI backends with support for multiple providers, request/response types, and a stub provider for testing.

# Features

# Cargo Features

# Example

use infrastructure_ai::{AiProvider, CompletionRequest, StubAiProvider};

# async fn example() -> infrastructure_ai::Result<()> {
// Use the stub provider for testing
let provider = StubAiProvider::new(true);

// Create a completion request
let request = CompletionRequest::new(
"You are a helpful assistant.",
"What is 2 + 2?"
)
.with_max_tokens(100)
.with_temperature(0.5);

// Get a response
let response = provider.complete(request).await?;
println!("Response: {}", response.content);

// Check token usage
if let Some(usage) = response.usage {
println!("Tokens used: {}", usage.total_tokens);
}
# Ok(())
# }

# Provider Registry

use infrastructure_ai::{ProviderRegistry, StubAiProvider};
use std::sync::Arc;

let mut registry = ProviderRegistry::new();
registry.register(Arc::new(StubAiProvider::new(true)));

// Get an available provider
if let Some(provider) = registry.available_provider() {
println!("Using provider: {}", provider.name());
}

# Per-Tenant AI (with full feature)

use infrastructure_ai::{AiProviderFactory, TenantAiSettings, AiProviderType};

// Create factory with database pool
let factory = AiProviderFactory::new(pool);

// Load tenant settings (from preferences or database)
let settings = TenantAiSettings::new(AiProviderType::OpenRouter)
.with_model("anthropic/claude-3.5-sonnet")
.with_enabled(true);

// Get provider for tenant (loads encrypted API key from database)
let provider = factory.for_tenant(tenant_id, &settings).await;

// Use provider
let response = provider.complete(request).await?;

Capabilities

answer (other)

Reading a model's answer back as JSON.

Item
fn json_object(answer : & str) -> Result <serde_json::Value, String>
fn json_as <T : DeserializeOwned>(answer : & str) -> Result <T, String>

connection_setup (other)

Connection-setup helper for ai_credentials encryption (Sprint 0.12).

Item
async fn set_encryption_key(pool : & PgPool, encryption_key : & str) -> Result <()>
async fn set_encryption_key_on_connection(conn : & mut sqlx::PgConnection, encryption_key : & str,) -> Result <()>

How to use it

From this crate's own rustdoc:

use infrastructure_ai::{AiProvider, CompletionRequest, StubAiProvider};

# async fn example() -> infrastructure_ai::Result<()> {
// Use the stub provider for testing
let provider = StubAiProvider::new(true);

// Create a completion request
let request = CompletionRequest::new(
    "You are a helpful assistant.",
    "What is 2 + 2?"
)
.with_max_tokens(100)
.with_temperature(0.5);

// Get a response
let response = provider.complete(request).await?;
println!("Response: {}", response.content);

// Check token usage
if let Some(usage) = response.usage {
    println!("Tokens used: {}", usage.total_tokens);
}
# Ok(())
# }

From this crate's own rustdoc:

use infrastructure_ai::{ProviderRegistry, StubAiProvider};
use std::sync::Arc;

let mut registry = ProviderRegistry::new();
registry.register(Arc::new(StubAiProvider::new(true)));

// Get an available provider
if let Some(provider) = registry.available_provider() {
    println!("Using provider: {}", provider.name());
}

Module structure

infrastructure_ai

flowchart TD
  n_infrastructure_ai["infrastructure_ai"]
  n_infrastructure_ai --> n_answer["answer"]
  n_infrastructure_ai --> n_connection_setup["connection_setup"]

Public surface

`answer`

ItemWhat it is
fn json_object(answer : & str) -> Result <serde_json::Value, String>Pull the JSON object out of a model's answer
fn json_as <T : DeserializeOwned>(answer : & str) -> Result <T, String>json_object, then into the caller's type

`connection_setup`

ItemWhat it is
async fn set_encryption_key(pool : & PgPool, encryption_key : & str) -> Result <()>Set app.encryption_key on the given pool's connections
async fn set_encryption_key_on_connection(conn : & mut sqlx::PgConnection, encryption_key : & str,) -> Result <()>Per-connection setter — call from a sqlx after_connect hook

Re-exports. Exported here, defined elsewhere.

ExportDefined in
AiProviderFactoryfactory::AiProviderFactory
AnthropicProvideranthropic::AnthropicProvider
ClaudeCliProviderclaude_cli::ClaudeCliProvider
OllamaProviderollama::OllamaProvider
OpenRouterProvideropenrouter::OpenRouterProvider
{AiContentPart,AiProvider,CompletionRequest,CompletionResponse,ProviderRegistry,StubAiProvider,TokenUsage,}provider::{AiContentPart,AiProvider,CompletionRequest,CompletionResponse,ProviderRegistry,StubAiProvider,TokenUsage,}
{AiError,Result}error::{AiError,Result}
{AiProviderType,TenantAiSettings}settings::{AiProviderType,TenantAiSettings}
{ChatMessage,ChatRequest,ChatResponse,ChatRole,FinishReason,ProviderCapabilities,ToolCall,ToolSpec,}chat::{ChatMessage,ChatRequest,ChatResponse,ChatRole,FinishReason,ProviderCapabilities,ToolCall,ToolSpec,}
{combine_prompt,truncate_utf8_bounded,DEFAULT_MAX_OUTPUT_BYTES,DEFAULT_TIMEOUT_SECS,}claude_cli::{combine_prompt,truncate_utf8_bounded,DEFAULT_MAX_OUTPUT_BYTES,DEFAULT_TIMEOUT_SECS,}
{delete_api_key,delete_system_api_key,get_api_key,get_system_api_key,has_api_key,has_system_api_key,list_providers,list_system_providers,set_api_key_enabled,set_system_api_key_enabled,setup_encryption,store_api_key,store_system_api_key,touch_api_key,ProviderInfo,}credentials::{delete_api_key,delete_system_api_key,get_api_key,get_system_api_key,has_api_key,has_system_api_key,list_providers,list_system_providers,set_api_key_enabled,set_system_api_key_enabled,setup_encryption,store_api_key,store_system_api_key,touch_api_key,ProviderInfo,}
{json_as,json_object}answer::{json_as,json_object}

Boundary

Reaches into foundation.

Shares tier infrastructure with 82 other crates: infrastructure-acquire, infrastructure-adapters-google-calendar, infrastructure-adapters-google-gmail, infrastructure-adapters-google-places, infrastructure-adapters-google-trends, infrastructure-adapters-shodan, infrastructure-adapters-yelp, infrastructure-agent, … (82 total).

_What this crate deliberately does NOT own is a judgment. No committed registry records one for it, so none is stated here._

Where it sits

Tier (ontology)infrastructure
Architectural role (taxonomy)unclassified (baselined)
Locationcrates/infrastructure/ai
Vocabulary in force (lexicon)current

Tier flow. Which tiers this crate's own edges cross.

flowchart LR
  n_infrastructure["infrastructure"] --> n_foundation["foundation"]

Dependencies

Runtime, in this workspace.

CrateTierOptionalOnly on
`foundation-bounded-io`foundationnoalways
`infrastructure-fetcher`infrastructureyesalways

Runtime, from outside the workspace.

CrateRequirementFeaturesOptionalOnly on
async-trait^0.1noalways
chrono^0.4serdeyesalways
reqwest^0.12jsonyesalways
serde^1derivenoalways
serde_json^1noalways
sqlx^0.8runtime-tokio, postgres, chrono, uuid, jsonyesalways
thiserror^2noalways
tokio^1fullyesalways
tracing^0.1noalways
uuid^1v4, v7, serde, jsnoalways

Development, from outside the workspace.

CrateRequirementFeaturesOptionalOnly on
tokio^1full, macros, rt-multi-threadnoalways

Build. None.

Depended on by. 17 workspace crates.

Signal flow — what reaches this crate, and what it reaches.

flowchart LR
  n_application_ai["application-ai"] -->|uses| SELF
  n_application_classify["application-classify"] -->|uses| SELF
  n_application_cms["application-cms"] -->|uses| SELF
  n_application_conversation["application-conversation"] -->|uses| SELF
  n_application_messaging["application-messaging"] -->|uses| SELF
  n_domain_ai_report["domain-ai-report"] -->|uses| SELF
  n_infrastructure_agent["infrastructure-agent"] -->|uses| SELF
  n_infrastructure_ocr_ai["infrastructure-ocr-ai"] -->|uses| SELF
  n_infrastructure_ocr_provider["infrastructure-ocr-provider"] -->|uses| SELF
  n_infrastructure_translate["infrastructure-translate"] -->|uses| SELF
  n_platform_privacy_scan_api["platform-privacy-scan-api"] -->|uses| SELF
  n_tools_doc_ask["tools-doc-ask"] -->|uses| SELF
  n_tools_imp["tools-imp"] -->|uses| SELF
  n_tools_knowitall["tools-knowitall"] -->|uses| SELF
  n_tools_local_ask["tools-local-ask"] -->|uses| SELF
  n_tools_packet_compile["tools-packet-compile"] -->|uses| SELF
  n_tools_prompt_shaper["tools-prompt-shaper"] -->|uses| SELF
  SELF["infrastructure-ai"]
  SELF -->|runtime| n_foundation_bounded_io["foundation-bounded-io"]
  SELF -->|runtime| n_infrastructure_fetcher["infrastructure-fetcher"]
  classDef self fill:#1f883d,stroke:#1f883d,color:#fff;
  class SELF self;

Feature flags

FeatureEnablesOn by default
clitokiono
defaultyes
fullhttp, postgres, clino
httpreqwest, dep:infrastructure-fetcherno
postgresdep:sqlx, dep:chronono
reqwestdep:reqwestno
tokiodep:tokiono
flowchart LR
  n_cli["cli"] --> n_tokio["tokio"]
  n_default["default"]
  n_full["full"] --> n_http["http"]
  n_full["full"] --> n_postgres["postgres"]
  n_full["full"] --> n_cli["cli"]
  n_http["http"] --> n_reqwest["reqwest"]
  n_http["http"] --> n_dep_infrastructure_fetcher["dep:infrastructure-fetcher"]
  n_postgres["postgres"] --> n_dep_sqlx["dep:sqlx"]
  n_postgres["postgres"] --> n_dep_chrono["dep:chrono"]
  n_reqwest["reqwest"] --> n_dep_reqwest["dep:reqwest"]
  n_tokio["tokio"] --> n_dep_tokio["dep:tokio"]

Targets

KindNameSource
libinfrastructure_ai`src/lib.rs`
testconnection_setup_smoke`tests/connection_setup_smoke.rs`

Error model

No public error type was detected: no public item declares a type named *Error, and no public signature returns one.

Operational characteristics

PropertyEvidence
async public surfaceyes
async runtimeyes
database accessyes
network I/Oyes
unsafe codenone detected
environment variablesyes

No unsafe block, unsafe fn, unsafe impl or unsafe trait was found by the parser anywhere in this crate's source.

Configuration

VariableRead in
ANTHROPIC_API_KEYsrc/anthropic.rs
ANTHROPIC_MODELsrc/anthropic.rs
CLAUDE_BINsrc/claude_cli.rs
OLLAMA_BASE_URLsrc/factory.rs
OLLAMA_MODELsrc/ollama.rs
OPENROUTER_API_KEYsrc/openrouter.rs
OPENROUTER_MODELsrc/openrouter.rs

17 workspace crates depend on this one: application-ai, application-classify, application-cms, application-conversation, application-messaging, domain-ai-report, infrastructure-agent, infrastructure-ocr-ai, infrastructure-ocr-provider, infrastructure-translate, platform-privacy-scan-api, tools-doc-ask, … (17 total).

Verification

KindCount
Unit tests70
Integration tests2
Examples0
Doctests3

Evidence by module. How often each public module is named by something executable.

ModuleTestsExamplesConsumers
answer200
connection_setup201

What the tests establish, by name:

Documentation coverage

MeasureDocumentedTotal
Public items with rustdoc44
Public modules with a //! block22
pie showData
    title Public items with rustdoc
    "Documented" : 4
    "No rustdoc detected" : 0

Metrics

MetricValue
Rust source files13
Source lines4395
Code lines3089
Public API items4
Public modules2
Tests72
Examples0
Cargo features7
Direct runtime dependencies12
Workspace reverse dependencies17
pie showData
    title Public API by kind
    "function" : 4
pie showData
    title Rust source composition
    "Code" : 3089
    "Blank or comment" : 1306

Generation

Rendered by tools-corpus corpus readme from repository evidence alone, renderer schema 2, lexicon current. No model, network service or database was consulted. Regenerate with tools-corpus corpus readme --write; verify with --check.

All infrastructure · Manual