#![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)
}