a3s-code-core 8.2.0

A3S Code Core - Embeddable AI agent library with tool execution
Documentation
use a3s_code_core::{
    DurableMemoryActivation, DurableMemoryBindingV1, DurableMemoryMode, DurableMemoryRecallChannel,
    DurableMemoryRecallHit, DurableMemoryRecallPolicy, DurableMemoryRecallPreview,
    DurableMemorySession, DurableMemoryUse, DURABLE_MEMORY_BINDING_SCHEMA_VERSION,
    DURABLE_MEMORY_CONTEXT_ID_PROFILE_V2, DURABLE_MEMORY_RETRIEVAL_PROFILE_V1,
};
use a3s_memory::repository::{
    DurableMemoryKind, EvidenceKind, EvidenceRef, InMemoryRepository, MemoryChangeSet,
    MemoryNamespace, MemoryNodeDraft, MemoryOperation, MemoryRepository, MemoryStatus,
};
use chrono::{TimeZone, Utc};
use std::sync::Arc;

fn time(second: u32) -> chrono::DateTime<Utc> {
    Utc.with_ymd_and_hms(2026, 8, 29, 16, 0, second)
        .single()
        .unwrap()
}

fn evidence(uri: &str, kind: EvidenceKind, second: u32) -> EvidenceRef {
    EvidenceRef::try_new(uri, format!("sha256:{:0>64}", uri), kind, time(second)).unwrap()
}

#[test]
fn active_memory_policy_is_bounded_and_public_types_are_thread_safe() {
    fn assert_send_sync<T: Send + Sync>() {}
    assert_send_sync::<DurableMemoryActivation>();
    assert_send_sync::<DurableMemoryBindingV1>();
    assert_send_sync::<DurableMemoryRecallChannel>();
    assert_send_sync::<DurableMemoryRecallHit>();
    assert_send_sync::<DurableMemoryRecallPolicy>();
    assert_send_sync::<DurableMemoryRecallPreview>();
    assert_send_sync::<DurableMemorySession>();
    assert_send_sync::<DurableMemoryUse>();

    assert!(DurableMemoryRecallPolicy::try_new(0, 0.25).is_err());
    assert!(DurableMemoryRecallPolicy::try_new(1, f32::NAN).is_err());
    assert!(DurableMemoryRecallPolicy::try_new(1, 1.01).is_err());
    assert!(DurableMemoryRecallPolicy::try_new(1, 0.0).is_ok());
    assert!(DurableMemoryRecallPolicy::try_new(1, 0.0)
        .unwrap()
        .try_with_related_lookups(101)
        .is_err());
    assert_eq!(
        DurableMemoryRecallPolicy::try_new(1, 0.0)
            .unwrap()
            .try_with_related_lookups(4)
            .unwrap()
            .max_related_lookups(),
        4
    );

    let namespace = MemoryNamespace::try_new("tenant", "principal", "scope").unwrap();
    let policy = DurableMemoryRecallPolicy::try_new(3, 0.25)
        .unwrap()
        .try_with_related_lookups(2)
        .unwrap();
    let session = DurableMemorySession::active_recall(
        Arc::new(InMemoryRepository::new()),
        namespace.clone(),
        policy,
    );
    let binding = session.binding();
    assert_eq!(
        binding.schema_version(),
        DURABLE_MEMORY_BINDING_SCHEMA_VERSION
    );
    assert_eq!(binding.namespace(), &namespace);
    assert_eq!(binding.mode(), DurableMemoryMode::ActiveRecall);
    assert_eq!(binding.recall_policy(), Some(policy));
    assert_eq!(
        binding.retrieval_profile(),
        DURABLE_MEMORY_RETRIEVAL_PROFILE_V1
    );
    assert_eq!(
        binding.context_id_profile(),
        DURABLE_MEMORY_CONTEXT_ID_PROFILE_V2
    );
    let roundtrip: DurableMemoryBindingV1 =
        serde_json::from_str(&serde_json::to_string(&binding).unwrap()).unwrap();
    assert_eq!(roundtrip, binding);
}

#[tokio::test]
async fn active_recall_requires_explicit_evidence_backed_activation() {
    let repository = Arc::new(InMemoryRepository::new());
    let namespace = MemoryNamespace::try_new("tenant", "principal", "scope").unwrap();
    let policy = DurableMemoryRecallPolicy::try_new(3, 0.25).unwrap();
    let binding =
        DurableMemorySession::active_recall(repository.clone(), namespace.clone(), policy);
    assert_eq!(binding.mode(), DurableMemoryMode::ActiveRecall);
    assert_eq!(binding.recall_policy().unwrap().max_results(), 3);

    repository
        .apply(MemoryChangeSet::new(
            "create-candidate",
            namespace.clone(),
            time(1),
            vec![MemoryOperation::Create {
                node: MemoryNodeDraft::new(
                    "candidate",
                    namespace.clone(),
                    DurableMemoryKind::Procedural,
                    MemoryStatus::Candidate,
                    "Run focused tests after changing durable memory",
                    vec![evidence(
                        "a3s://session/one/turn/one",
                        EvidenceKind::SessionTurn,
                        1,
                    )],
                    time(1),
                ),
            }],
        ))
        .await
        .unwrap();

    let invalid = DurableMemoryActivation::try_new(
        "activate-invalid",
        "candidate",
        1,
        evidence("a3s://session/one/turn/two", EvidenceKind::SessionTurn, 2),
        time(2),
    );
    assert!(
        invalid.is_err(),
        "self-reported turn evidence is not approval"
    );

    let activated = binding
        .activate_candidate(
            DurableMemoryActivation::try_new(
                "activate-candidate",
                "candidate",
                1,
                evidence(
                    "a3s://verification/memory/candidate",
                    EvidenceKind::Verification,
                    2,
                ),
                time(2),
            )
            .unwrap(),
        )
        .await
        .unwrap();
    assert_eq!(activated.status, MemoryStatus::Active);
    assert_eq!(activated.revision, 2);
    assert_eq!(activated.evidence.len(), 2);

    binding
        .record_use(
            DurableMemoryUse::try_new("use-candidate", "candidate", 2, time(3))
                .unwrap()
                .with_context_id("turn-context-1"),
        )
        .await
        .unwrap();
    assert_eq!(
        repository
            .usage_summary(&namespace, "candidate")
            .await
            .unwrap()
            .uses,
        1
    );
}