kcode-k1-chat-thread-web-code-open-targets 0.1.0

Pure Open presentation and target classification for K1 Chat Web-code
Documentation
#![forbid(unsafe_code)]

use kcode_k1_chat_boxes::{BoxId, ChatBox, ToolCallId};
use kcode_k1_chat_web_code_output::{
    DocumentPart, Language as OutputLanguage, WEB_CODE_OPEN_METADATA_TYPE, WebCodeOutput, open,
};
use kcode_k1_web_code_document::{CodeDocument, Language};
use std::fmt::{Display, Formatter};

#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct OpenLayout {
    originating_call: BoxId,
    tool_call_id: ToolCallId,
    code_message_count: u64,
}

impl OpenLayout {
    pub const fn originating_call(self) -> BoxId {
        self.originating_call
    }

    pub const fn tool_call_id(self) -> ToolCallId {
        self.tool_call_id
    }

    pub const fn code_message_count(self) -> u64 {
        self.code_message_count
    }
}

#[derive(Clone, Debug, Eq, PartialEq)]
pub struct OpenPresentation {
    pub output: WebCodeOutput,
    pub layout: OpenLayout,
}

pub fn present_open(
    originating_call: BoxId,
    tool_call_id: ToolCallId,
    document: &CodeDocument,
    authority: &str,
    name: &str,
    version: &str,
) -> OpenPresentation {
    let ranges = document.chunk_ranges();
    let code_message_count =
        u64::try_from(ranges.len()).expect("code chunk count must fit in a u64");
    let documentation = std::str::from_utf8(document.documentation())
        .expect("CodeDocument maintains UTF-8 documentation")
        .to_owned();

    let mut messages = Vec::with_capacity(ranges.len());
    messages.push(documentation);
    for range in &ranges[..ranges.len() - 1] {
        messages.push(
            std::str::from_utf8(&document.code()[range.clone()])
                .expect("CodeDocument chunks preserve UTF-8 boundaries")
                .to_owned(),
        );
    }

    let final_range = ranges
        .last()
        .expect("CodeDocument always returns at least one code chunk");
    let result = Ok(std::str::from_utf8(&document.code()[final_range.clone()])
        .expect("CodeDocument chunks preserve UTF-8 boundaries")
        .to_owned());
    let language = match document.language() {
        Language::JavaScript => OutputLanguage::Javascript,
        Language::Html => OutputLanguage::Html,
        Language::Css => OutputLanguage::Css,
    };
    let output = open(
        tool_call_id,
        messages,
        result,
        authority,
        name,
        version,
        language,
        code_message_count,
    );

    OpenPresentation {
        output,
        layout: OpenLayout {
            originating_call,
            tool_call_id,
            code_message_count,
        },
    }
}

#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum TargetRejection {
    HistoryAbsent,
    HistoryDuplicate,
    MalformedPayload,
    DifferentOpen,
    MessageOutOfLayout,
    FailedResult,
    NotOpenPayload,
}

impl TargetRejection {
    pub const fn code(self) -> &'static str {
        match self {
            Self::HistoryAbsent => "history_absent",
            Self::HistoryDuplicate => "history_duplicate",
            Self::MalformedPayload => "malformed_payload",
            Self::DifferentOpen => "different_open",
            Self::MessageOutOfLayout => "message_out_of_layout",
            Self::FailedResult => "failed_result",
            Self::NotOpenPayload => "not_open_payload",
        }
    }
}

impl Display for TargetRejection {
    fn fmt(&self, formatter: &mut Formatter<'_>) -> std::fmt::Result {
        formatter.write_str(match self {
            Self::HistoryAbsent => "target box is absent from history",
            Self::HistoryDuplicate => "target box ID occurs more than once in history",
            Self::MalformedPayload => "target has malformed tool metadata",
            Self::DifferentOpen => "target belongs to a different Open",
            Self::MessageOutOfLayout => "target message index is outside the Open layout",
            Self::FailedResult => "target is a failed Open result",
            Self::NotOpenPayload => "target is not an Open payload",
        })
    }
}

impl std::error::Error for TargetRejection {}

pub fn classify_original_target(
    history: &[ChatBox],
    target_id: BoxId,
    layout: OpenLayout,
) -> Result<DocumentPart, TargetRejection> {
    let mut matching = history.iter().filter(|value| value.id() == target_id);
    let target = matching.next().ok_or(TargetRejection::HistoryAbsent)?;
    if matching.next().is_some() {
        return Err(TargetRejection::HistoryDuplicate);
    }

    match target.tool_message_metadata() {
        Err(_) => return Err(TargetRejection::MalformedPayload),
        Ok(Some(message)) => {
            if message.tool_call_id != layout.tool_call_id
                || message.originating_call != layout.originating_call
            {
                return Err(TargetRejection::DifferentOpen);
            }
            return match message.message_index {
                1 => Ok(DocumentPart::Documentation),
                index if (2..=layout.code_message_count).contains(&index) => Ok(DocumentPart::Code),
                _ => Err(TargetRejection::MessageOutOfLayout),
            };
        }
        Ok(None) => {}
    }

    let result = target
        .tool_result_v2_metadata()
        .map_err(|_| TargetRejection::MalformedPayload)?
        .ok_or(TargetRejection::NotOpenPayload)?;
    if result.tool_call_id != layout.tool_call_id
        || result.originating_call != layout.originating_call
    {
        return Err(TargetRejection::DifferentOpen);
    }
    if result.metadata_type != WEB_CODE_OPEN_METADATA_TYPE {
        return Err(TargetRejection::NotOpenPayload);
    }
    if result.result.is_err() {
        return Err(TargetRejection::FailedResult);
    }

    Ok(DocumentPart::Code)
}