Skip to main content

kcode_k1_chat_thread_web_code_errors/
lib.rs

1#![forbid(unsafe_code)]
2
3use kcode_k1_chat_boxes::ToolCallId;
4use kcode_k1_chat_web_code_output::{self as output, Operation, WebCodeOutput};
5use kcode_k1_web_code_ktool_service::{ServiceError, ServiceFailure};
6
7pub fn service_error(
8    tool_call_id: ToolCallId,
9    operation: Operation,
10    service_error: ServiceError,
11) -> WebCodeOutput {
12    let code = match service_error.failure() {
13        ServiceFailure::State => "state",
14        ServiceFailure::Authorization => "authorization",
15        ServiceFailure::WorkspaceDenied => "workspace_denied",
16        ServiceFailure::FamilyExists => "family_exists",
17        ServiceFailure::SourceUnavailable => "source_unavailable",
18        ServiceFailure::VersionUsed => "version_used",
19        ServiceFailure::ForeignHandle => "foreign_handle",
20        ServiceFailure::StaleSource => "stale_source",
21        ServiceFailure::InvalidDocument => "invalid_document",
22        ServiceFailure::CheckFailed => "check_failed",
23        ServiceFailure::SourcePreservation => "source_preservation",
24        ServiceFailure::PublicReleaseDenied => "public_release_denied",
25        ServiceFailure::Publication => "publication",
26        ServiceFailure::Dependency => "dependency",
27    };
28    let source_object = service_error.source_object().map(|value| value.to_string());
29    error(
30        tool_call_id,
31        operation,
32        code,
33        service_error.to_string(),
34        source_object.as_deref(),
35    )
36}
37
38pub fn error(
39    tool_call_id: ToolCallId,
40    operation: Operation,
41    code: &str,
42    message: String,
43    source_object: Option<&str>,
44) -> WebCodeOutput {
45    output::error(
46        tool_call_id,
47        Vec::new(),
48        Err(message),
49        operation,
50        code,
51        source_object,
52    )
53}
54
55pub fn simple_error(
56    tool_call_id: ToolCallId,
57    operation: Operation,
58    code: &'static str,
59) -> WebCodeOutput {
60    error(tool_call_id, operation, code, code.replace('_', " "), None)
61}
62
63#[cfg(test)]
64mod tests {
65    use super::*;
66
67    fn tool_call_id() -> ToolCallId {
68        ToolCallId::new([0x3c; 12], 17)
69    }
70
71    #[test]
72    fn generic_error_preserves_safe_text_object_and_v2_metadata() {
73        let value = error(
74            tool_call_id(),
75            Operation::Publish,
76            "publication",
77            "complete safe text\nwith details".to_owned(),
78            Some("abcdef0123456789abcdef01"),
79        );
80        assert_eq!(value.tool_call_id, tool_call_id());
81        assert!(value.messages.is_empty());
82        assert_eq!(
83            value.result,
84            Err("complete safe text\nwith details".to_owned())
85        );
86        assert_eq!(value.metadata_type, "k1.web-code-publish/v2");
87        assert_eq!(
88            value.metadata_contents,
89            r#"{"status":"error","code":"publication","source_object":"abcdef0123456789abcdef01"}"#
90        );
91    }
92
93    #[test]
94    fn simple_error_has_no_source_object() {
95        let value = simple_error(tool_call_id(), Operation::Publish, "public_release_denied");
96        assert_eq!(value.result, Err("public release denied".to_owned()));
97        assert_eq!(
98            value.metadata_contents,
99            r#"{"status":"error","code":"public_release_denied","source_object":null}"#
100        );
101    }
102}