a3s-code-core 8.0.3

A3S Code Core - Embeddable AI agent library with tool execution
Documentation
use super::super::*;
use super::support::{descriptor, executor, fast_config, input, FakeAction, FakeProvider};
use async_trait::async_trait;
use std::sync::Arc;
use tokio_util::sync::CancellationToken;

#[tokio::test]
async fn rejects_descriptor_drift_partial_batches_dimensions_and_non_finite_values() {
    let base = descriptor(3);
    let drifted = EmbeddingProviderDescriptor::new("fake", "deterministic-v2", 3);
    let cases = vec![
        (
            FakeAction::Response(EmbeddingBatchResponse::new(
                drifted,
                vec![EmbeddingVector::new("chunk-0", vec![1.0, 2.0, 3.0])],
            )),
            EmbeddingError::DescriptorChanged,
        ),
        (
            FakeAction::Response(EmbeddingBatchResponse::new(base.clone(), Vec::new())),
            EmbeddingError::OutputCountMismatch {
                expected: 1,
                actual: 0,
            },
        ),
        (
            FakeAction::Response(EmbeddingBatchResponse::new(
                base.clone(),
                vec![EmbeddingVector::new("chunk-0", vec![1.0, 2.0])],
            )),
            EmbeddingError::DimensionMismatch {
                input_index: 0,
                expected: 3,
                actual: 2,
            },
        ),
        (
            FakeAction::Response(EmbeddingBatchResponse::new(
                base.clone(),
                vec![EmbeddingVector::new("chunk-0", vec![1.0, f32::NAN, 3.0])],
            )),
            EmbeddingError::NonFiniteValue {
                input_index: 0,
                position: 1,
            },
        ),
    ];

    for (action, expected) in cases {
        let provider = FakeProvider::new(base.clone(), vec![action]);
        let error = executor(&provider, fast_config())
            .embed(vec![input(0, "source")], CancellationToken::new())
            .await
            .unwrap_err();
        assert_eq!(error, expected);
    }
}

#[tokio::test]
async fn rejects_duplicate_and_unknown_output_identifiers() {
    let base = descriptor(2);
    let provider = FakeProvider::new(
        base.clone(),
        vec![FakeAction::Response(EmbeddingBatchResponse::new(
            base.clone(),
            vec![
                EmbeddingVector::new("chunk-0", vec![1.0, 2.0]),
                EmbeddingVector::new("chunk-0", vec![3.0, 4.0]),
            ],
        ))],
    );
    let error = executor(&provider, fast_config())
        .embed(
            vec![input(0, "first"), input(1, "second")],
            CancellationToken::new(),
        )
        .await
        .unwrap_err();
    assert_eq!(error, EmbeddingError::DuplicateOutput { input_index: 0 });

    let provider = FakeProvider::new(
        base.clone(),
        vec![FakeAction::Response(EmbeddingBatchResponse::new(
            base,
            vec![EmbeddingVector::new("unknown", vec![1.0, 2.0])],
        ))],
    );
    let error = executor(&provider, fast_config())
        .embed(vec![input(0, "source")], CancellationToken::new())
        .await
        .unwrap_err();
    assert_eq!(error, EmbeddingError::UnexpectedOutput);
}

#[tokio::test]
async fn validates_unit_normalization_contract() {
    let descriptor = descriptor(2).with_normalization(EmbeddingNormalization::Unit);
    let provider = FakeProvider::new(
        descriptor.clone(),
        vec![FakeAction::Response(EmbeddingBatchResponse::new(
            descriptor,
            vec![EmbeddingVector::new("chunk-0", vec![1.0, 1.0])],
        ))],
    );
    let error = executor(&provider, fast_config())
        .embed(vec![input(0, "source")], CancellationToken::new())
        .await
        .unwrap_err();

    assert_eq!(
        error,
        EmbeddingError::NormalizationMismatch { input_index: 0 }
    );
}

#[tokio::test]
async fn validates_inputs_and_budgets_before_calling_the_provider() {
    let provider = FakeProvider::new(descriptor(2), Vec::new());
    let execution = executor(
        &provider,
        EmbeddingExecutorConfig {
            max_input_text_bytes: 4,
            max_batch_text_bytes: 4,
            max_request_text_bytes: 8,
            ..fast_config()
        },
    );
    let cases = vec![
        (Vec::new(), EmbeddingError::EmptyRequest),
        (
            vec![EmbeddingInput::new("", "text")],
            EmbeddingError::InvalidInput {
                index: 0,
                reason: "identifier is empty, oversized, or contains a control character",
            },
        ),
        (
            vec![input(0, "text"), input(0, "text")],
            EmbeddingError::InvalidInput {
                index: 1,
                reason: "identifier is duplicated",
            },
        ),
        (
            vec![input(0, "oversized")],
            EmbeddingError::BudgetExceeded {
                resource: "input text byte",
                requested: 9,
                limit: 4,
            },
        ),
    ];
    for (inputs, expected) in cases {
        assert_eq!(
            execution
                .embed(inputs, CancellationToken::new())
                .await
                .unwrap_err(),
            expected
        );
    }
    assert_eq!(provider.call_count(), 0);
}

#[tokio::test]
async fn provider_panics_are_converted_to_typed_errors() {
    let provider = FakeProvider::new(descriptor(2), vec![FakeAction::Panic]);
    let error = executor(&provider, fast_config())
        .embed(vec![input(0, "source")], CancellationToken::new())
        .await
        .unwrap_err();

    assert_eq!(
        error,
        EmbeddingError::ProviderPanicked { operation: "embed" }
    );
    assert!(!error.to_string().contains("fake provider panic"));
}

struct PanickingDescriptorProvider;

#[async_trait]
impl EmbeddingProvider for PanickingDescriptorProvider {
    fn descriptor(&self) -> EmbeddingProviderDescriptor {
        panic!("descriptor panic payload")
    }

    async fn embed(
        &self,
        _request: EmbeddingBatchRequest,
        _cancellation: CancellationToken,
    ) -> Result<EmbeddingBatchResponse, EmbeddingProviderError> {
        unreachable!("constructor must fail before embed")
    }
}

#[test]
fn constructor_contains_descriptor_panics() {
    let provider: Arc<dyn EmbeddingProvider> = Arc::new(PanickingDescriptorProvider);
    let error = EmbeddingExecutor::new(provider, fast_config()).unwrap_err();

    assert_eq!(
        error,
        EmbeddingError::ProviderPanicked {
            operation: "descriptor"
        }
    );
    assert!(!error.to_string().contains("descriptor panic payload"));
}

#[test]
fn debug_and_errors_do_not_expose_source_vector_or_identifier_content() {
    let sentinel = "sk-source-secret-123456";
    let input = EmbeddingInput::new(sentinel, sentinel);
    let request = EmbeddingBatchRequest::new(vec![input.clone()]);
    let vector = EmbeddingVector::new(sentinel, vec![123.456, 789.012]);
    let response = EmbeddingBatchResponse::new(descriptor(2), vec![vector.clone()]);
    let rendered = format!("{input:?} {request:?} {vector:?} {response:?}");

    assert!(!rendered.contains(sentinel));
    assert!(!rendered.contains("123.456"));
    assert!(!EmbeddingProviderError::Authentication
        .to_string()
        .contains(sentinel));
}

#[test]
fn constructor_rejects_invalid_descriptors_and_configs() {
    let provider = FakeProvider::new(descriptor(0), Vec::new());
    let provider_port: Arc<dyn EmbeddingProvider> = provider;
    assert_eq!(
        EmbeddingExecutor::new(provider_port, fast_config()).unwrap_err(),
        EmbeddingError::InvalidDescriptor { field: "dimension" }
    );

    let provider = FakeProvider::new(descriptor(2), Vec::new());
    let provider_port: Arc<dyn EmbeddingProvider> = provider;
    let config = EmbeddingExecutorConfig {
        max_batch_inputs: 0,
        ..fast_config()
    };
    assert_eq!(
        EmbeddingExecutor::new(provider_port, config).unwrap_err(),
        EmbeddingError::InvalidConfiguration {
            field: "max_batch_inputs",
            reason: "must be greater than zero",
        }
    );

    let provider = FakeProvider::new(descriptor(2), Vec::new());
    let provider_port: Arc<dyn EmbeddingProvider> = provider;
    let config = EmbeddingExecutorConfig {
        max_retries: 9,
        ..fast_config()
    };
    assert_eq!(
        EmbeddingExecutor::new(provider_port, config).unwrap_err(),
        EmbeddingError::InvalidConfiguration {
            field: "max_retries",
            reason: "must not exceed eight",
        }
    );
}