language-model-batch-workflow-derive 0.1.4

A procedural macro for deriving batch-oriented language model workflows using annotated client and workspace fields.
Documentation
// ---------------- [ File: language-model-batch-workflow-derive/tests/trybuild/pass_valid_struct.rs ]
#![allow(unused_imports)]
// ===========================[ CHANGED ITEM #1 ]===========================
//
// In your "pass_valid_struct.rs" file, import the correct `JsonParseError` type
// and add reverse conversions for `BatchDownloadError` and
// `BatchReconciliationError`. The library’s `reconcile_unprocessed` code
// implicitly requires that `BatchDownloadError` and `BatchReconciliationError`
// be able to convert *from* your custom error type.  That is why the compiler
// complains that `BatchDownloadError: From<MyErr>` and `BatchReconciliationError: From<MyErr>`
// are not satisfied.
//
// Below is the *full updated* file. The key fixes are:
//
// 1. `use batch_mode_json::errors::JsonParseError;` at the top so the compiler
//    knows which `JsonParseError` you mean.
//
// 2. `impl From<MyErr> for BatchDownloadError { ... }` and
//    `impl From<MyErr> for BatchReconciliationError { ... }`, returning
//    an appropriate variant. Here we just wrap everything in a generic
//    "OpenAIClientError" or "ReconciliationError" variant, but you can pick
//    whichever variant suits your code best.
//
// With these changes, `pass_valid_struct.rs` should compile cleanly.
//
// File: tests/trybuild/pass_valid_struct.rs

use language_model_batch_workflow_derive::LanguageModelBatchWorkflow;
use batch_mode_batch_workflow::*;
use batch_mode_3p::*;
use std::sync::Arc;
use serde::{Serialize, Deserialize};
use camel_case_token_with_comment::CamelCaseTokenWithComment;
use save_load_traits::*;

#[derive(LanguageModelBatchWorkflow)]
#[batch_error_type(MyErr)]
pub struct MyValidStruct {
    #[batch_client]
    client: Arc<dyn LanguageModelClientInterface<MyErr>>,

    #[batch_workspace]
    workspace: Arc<BatchWorkspace>,

    #[model_type]
    lm_type: LanguageModelType,
}

impl ComputeSystemMessage for MyValidStruct {
    fn system_message() -> String {
        "My system message".to_string()
    }
}

#[derive(Clone,NamedItem,Debug,Serialize,Deserialize)]
pub struct TestSeed {
    name: String,
}

impl HasAssociatedOutputName for TestSeed {
    fn associated_output_name(&self) -> std::borrow::Cow<'_, str> {
        todo!();
    }
}

impl std::fmt::Display for TestSeed {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        todo!();
    }
}

impl ComputeLanguageModelCoreQuery for MyValidStruct {
    type Seed = TestSeed;

    fn compute_language_model_core_query(
        &self,
        _input: &Self::Seed
    ) -> String {
        unimplemented!();
    }
}

// Add a simple FromStr implementation:
impl std::str::FromStr for TestSeed {
    type Err = MyErr;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        // Here, we just store `s` as the name. Real code might parse JSON, etc.
        Ok(TestSeed { name: s.to_string() })
    }
}

// Our user-defined error => must implement `From<…>` for all relevant error types.
#[derive(Debug)]
pub struct MyErr;

impl std::fmt::Display for MyErr {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f,"MyErr")
    }
}

// We already convert from sub-errors *into* MyErr:
impl From<BatchDownloadError>         for MyErr { fn from(_: BatchDownloadError)       -> Self { MyErr } }
impl From<BatchInputCreationError>    for MyErr { fn from(_: BatchInputCreationError)  -> Self { MyErr } }
impl From<BatchMetadataError>         for MyErr { fn from(_: BatchMetadataError)       -> Self { MyErr } }
impl From<BatchProcessingError>       for MyErr { fn from(_: BatchProcessingError)     -> Self { MyErr } }
impl From<BatchReconciliationError>   for MyErr { fn from(_: BatchReconciliationError) -> Self { MyErr } }
impl From<BatchErrorProcessingError>  for MyErr { fn from(_: BatchErrorProcessingError) -> Self { MyErr } }
impl From<BatchValidationError>       for MyErr { fn from(_: BatchValidationError) -> Self { MyErr } }
impl From<BatchOutputProcessingError> for MyErr { fn from(_: BatchOutputProcessingError) -> Self { MyErr } }
impl From<BatchWorkspaceError>        for MyErr { fn from(_: BatchWorkspaceError)      -> Self { MyErr } }
impl From<FileMoveError>              for MyErr { fn from(_: FileMoveError)            -> Self { MyErr } }
impl From<OpenAIClientError>          for MyErr { fn from(_: OpenAIClientError)        -> Self { MyErr } }
impl From<std::io::Error>             for MyErr { fn from(_: std::io::Error)           -> Self { MyErr } }
impl From<LanguageModelBatchCreationError> for MyErr { fn from(_: LanguageModelBatchCreationError)        -> Self { MyErr } }

// Also handle JSON parse failures => MyErr:
impl From<JsonParseError> for MyErr {
    fn from(_: JsonParseError) -> Self {
        tracing::debug!("Converting JsonParseError into MyErr.");
        MyErr
    }
}

// -------------- NEW: Reverse conversions for MyErr => BatchDownloadError etc. --------------
// The library function reconcile_unprocessed(...) forces `BatchDownloadError: From<E>`. 
// That means if E=MyErr, the code tries `BatchDownloadError::from(my_err_value)`.
// We can unify everything into a single variant or placeholder as you see fit.

impl From<MyErr> for BatchDownloadError {
    fn from(_err: MyErr) -> Self {
        todo!();
    }
}

impl From<MyErr> for BatchReconciliationError {
    fn from(_err: MyErr) -> Self {
        todo!();
    }
}

impl From<MyErr> for BatchSuccessResponseHandlingError {
    fn from(_err: MyErr) -> Self {
        todo!();
    }
}

// If all is correct, this compiles without error:
fn main() {
    tracing::info!("`pass_valid_struct.rs` main() ran successfully!");
}