kcode-k1-chat-thread-web-code-errors 0.1.0

Pure model-facing error outputs for K1 Chat Web-code tasks
Documentation
#![forbid(unsafe_code)]

use kcode_k1_chat_boxes::ToolCallId;
use kcode_k1_chat_web_code_output::{self as output, Operation, WebCodeOutput};
use kcode_k1_web_code_ktool_service::{ServiceError, ServiceFailure};

pub fn service_error(
    tool_call_id: ToolCallId,
    operation: Operation,
    service_error: ServiceError,
) -> WebCodeOutput {
    let code = match service_error.failure() {
        ServiceFailure::State => "state",
        ServiceFailure::Authorization => "authorization",
        ServiceFailure::WorkspaceDenied => "workspace_denied",
        ServiceFailure::SourceUnavailable => "source_unavailable",
        ServiceFailure::LanguageRequired => "language_required",
        ServiceFailure::LanguageMismatch => "language_mismatch",
        ServiceFailure::ForeignHandle => "foreign_handle",
        ServiceFailure::StaleSource => "stale_source",
        ServiceFailure::InvalidDocument => "invalid_document",
        ServiceFailure::CheckFailed => "check_failed",
        ServiceFailure::SourcePreservation => "source_preservation",
        ServiceFailure::PublicReleaseDenied => "public_release_denied",
        ServiceFailure::Publication => "publication",
        ServiceFailure::Dependency => "dependency",
    };
    let source_object = service_error
        .source_object()
        .map(|source_object| source_object.to_string());
    error(
        tool_call_id,
        operation,
        code,
        service_error.to_string(),
        source_object.as_deref(),
    )
}

pub fn error(
    tool_call_id: ToolCallId,
    operation: Operation,
    code: &str,
    message: String,
    source_object: Option<&str>,
) -> WebCodeOutput {
    output::error(
        tool_call_id,
        Vec::new(),
        Err(message),
        operation,
        code,
        source_object,
    )
}

pub fn simple_error(
    tool_call_id: ToolCallId,
    operation: Operation,
    code: &'static str,
) -> WebCodeOutput {
    error(tool_call_id, operation, code, code.replace('_', " "), None)
}

#[cfg(test)]
mod tests {
    use super::*;
    use kcode_k1_chat_web_code_output::WEB_CODE_PUBLISH_METADATA_TYPE;

    fn tool_call_id() -> ToolCallId {
        ToolCallId::new([0x3c; 12], 17)
    }

    #[test]
    fn generic_error_preserves_safe_text_source_object_and_metadata() {
        let output = error(
            tool_call_id(),
            Operation::Publish,
            "publication",
            "complete safe text\nwith details".to_owned(),
            Some("abcdef0123456789abcdef01"),
        );

        assert_eq!(output.tool_call_id, tool_call_id());
        assert!(output.messages.is_empty());
        assert_eq!(
            output.result,
            Err("complete safe text\nwith details".to_owned())
        );
        assert_eq!(output.metadata_type, WEB_CODE_PUBLISH_METADATA_TYPE);
        assert_eq!(
            output.metadata_contents,
            r#"{"status":"error","code":"publication","source_object":"abcdef0123456789abcdef01"}"#
        );
    }

    #[test]
    fn simple_error_derives_safe_text_and_has_no_source_object() {
        let output = simple_error(tool_call_id(), Operation::Publish, "public_release_denied");

        assert!(output.messages.is_empty());
        assert_eq!(output.result, Err("public release denied".to_owned()));
        assert_eq!(
            output.metadata_contents,
            r#"{"status":"error","code":"public_release_denied","source_object":null}"#
        );
    }
}