diff options
| author | soryu <soryu@soryu.co> | 2025-12-24 05:45:22 +0000 |
|---|---|---|
| committer | soryu <soryu@soryu.co> | 2025-12-24 05:45:22 +0000 |
| commit | 2faba0388f93d8e4fb86219eba7883b331d501ff (patch) | |
| tree | 92b83b8d558a652d3777627b2ac95ded250faa48 /makima/src/llm | |
| parent | 8f016a0e9d14badc39dffd67ed6fb862f9d08496 (diff) | |
| download | soryu-2faba0388f93d8e4fb86219eba7883b331d501ff.tar.gz soryu-2faba0388f93d8e4fb86219eba7883b331d501ff.zip | |
Add versioning to files
Diffstat (limited to 'makima/src/llm')
| -rw-r--r-- | makima/src/llm/mod.rs | 2 | ||||
| -rw-r--r-- | makima/src/llm/tools.rs | 168 |
2 files changed, 169 insertions, 1 deletions
diff --git a/makima/src/llm/mod.rs b/makima/src/llm/mod.rs index 7de8afe..0df492d 100644 --- a/makima/src/llm/mod.rs +++ b/makima/src/llm/mod.rs @@ -6,7 +6,7 @@ pub mod tools; pub use claude::{ClaudeClient, ClaudeModel}; pub use groq::GroqClient; -pub use tools::{execute_tool_call, Tool, ToolCall, ToolResult, AVAILABLE_TOOLS}; +pub use tools::{execute_tool_call, Tool, ToolCall, ToolResult, VersionToolRequest, AVAILABLE_TOOLS}; /// Available LLM providers and models #[derive(Debug, Clone, Copy, PartialEq, Eq, Default)] diff --git a/makima/src/llm/tools.rs b/makima/src/llm/tools.rs index e6b2954..35f321f 100644 --- a/makima/src/llm/tools.rs +++ b/makima/src/llm/tools.rs @@ -232,9 +232,62 @@ pub static AVAILABLE_TOOLS: once_cell::sync::Lazy<Vec<Tool>> = "required": ["input", "filter"] }), }, + // Version history tools + Tool { + name: "list_versions".to_string(), + description: "List all available versions of the current document. Returns version numbers, sources (user/llm/system), timestamps, and change descriptions.".to_string(), + parameters: json!({ + "type": "object", + "properties": {}, + "required": [] + }), + }, + Tool { + name: "read_version".to_string(), + description: "Read the content of a specific historical version of the document. This is read-only and does not modify the current document.".to_string(), + parameters: json!({ + "type": "object", + "properties": { + "version": { + "type": "integer", + "description": "The version number to read" + } + }, + "required": ["version"] + }), + }, + Tool { + name: "restore_version".to_string(), + description: "Restore the document to a previous version. This creates a new version with the content from the target version. The current content will be preserved as a historical version.".to_string(), + parameters: json!({ + "type": "object", + "properties": { + "target_version": { + "type": "integer", + "description": "The version number to restore to" + }, + "reason": { + "type": "string", + "description": "Optional reason for the restore (will be recorded in change description)" + } + }, + "required": ["target_version"] + }), + }, ] }); +/// Request for version-related operations that require async database access +#[derive(Debug, Clone)] +pub enum VersionToolRequest { + /// List all versions of the current file + ListVersions, + /// Read a specific version + ReadVersion { version: i32 }, + /// Restore to a specific version + RestoreVersion { target_version: i32, reason: Option<String> }, +} + /// Result of executing a tool call with modified file state #[derive(Debug)] pub struct ToolExecutionResult { @@ -242,6 +295,8 @@ pub struct ToolExecutionResult { pub new_body: Option<Vec<BodyElement>>, pub new_summary: Option<String>, pub parsed_data: Option<serde_json::Value>, + /// Request for async version operations (handled by chat handler) + pub version_request: Option<VersionToolRequest>, } /// Execute a tool call and return the result along with any state changes @@ -261,6 +316,10 @@ pub fn execute_tool_call( "parse_csv" => execute_parse_csv(call), "clear_body" => execute_clear_body(), "jq" => execute_jq(call), + // Version history tools - return request for async handling + "list_versions" => execute_list_versions(), + "read_version" => execute_read_version(call), + "restore_version" => execute_restore_version(call), _ => ToolExecutionResult { result: ToolResult { success: false, @@ -269,6 +328,7 @@ pub fn execute_tool_call( new_body: None, new_summary: None, parsed_data: None, + version_request: None, }, } } @@ -305,6 +365,7 @@ fn execute_add_heading(call: &ToolCall, current_body: &[BodyElement]) -> ToolExe new_body: Some(new_body), new_summary: None, parsed_data: None, + version_request: None, } } @@ -345,6 +406,7 @@ fn execute_add_paragraph(call: &ToolCall, current_body: &[BodyElement]) -> ToolE new_body: Some(new_body), new_summary: None, parsed_data: None, + version_request: None, } } @@ -410,6 +472,7 @@ fn execute_add_chart(call: &ToolCall, current_body: &[BodyElement]) -> ToolExecu new_body: Some(new_body), new_summary: None, parsed_data: None, + version_request: None, } } @@ -425,6 +488,7 @@ fn execute_remove_element(call: &ToolCall, current_body: &[BodyElement]) -> Tool new_body: None, new_summary: None, parsed_data: None, + version_request: None, }; }; @@ -438,6 +502,7 @@ fn execute_remove_element(call: &ToolCall, current_body: &[BodyElement]) -> Tool new_body: None, new_summary: None, parsed_data: None, + version_request: None, }; } @@ -452,6 +517,7 @@ fn execute_remove_element(call: &ToolCall, current_body: &[BodyElement]) -> Tool new_body: Some(new_body), new_summary: None, parsed_data: None, + version_request: None, } } @@ -468,6 +534,7 @@ fn execute_update_element(call: &ToolCall, current_body: &[BodyElement]) -> Tool new_body: None, new_summary: None, parsed_data: None, + version_request: None, }; }; @@ -480,6 +547,7 @@ fn execute_update_element(call: &ToolCall, current_body: &[BodyElement]) -> Tool new_body: None, new_summary: None, parsed_data: None, + version_request: None, }; }; @@ -493,6 +561,7 @@ fn execute_update_element(call: &ToolCall, current_body: &[BodyElement]) -> Tool new_body: None, new_summary: None, parsed_data: None, + version_request: None, }; } @@ -530,6 +599,7 @@ fn execute_update_element(call: &ToolCall, current_body: &[BodyElement]) -> Tool new_body: None, new_summary: None, parsed_data: None, + version_request: None, }; } }; @@ -545,6 +615,7 @@ fn execute_update_element(call: &ToolCall, current_body: &[BodyElement]) -> Tool new_body: Some(new_body), new_summary: None, parsed_data: None, + version_request: None, } } @@ -561,6 +632,7 @@ fn execute_reorder_elements(call: &ToolCall, current_body: &[BodyElement]) -> To new_body: None, new_summary: None, parsed_data: None, + version_request: None, }; }; @@ -579,6 +651,7 @@ fn execute_reorder_elements(call: &ToolCall, current_body: &[BodyElement]) -> To new_body: None, new_summary: None, parsed_data: None, + version_request: None, }; } @@ -594,6 +667,7 @@ fn execute_reorder_elements(call: &ToolCall, current_body: &[BodyElement]) -> To new_body: Some(new_body), new_summary: None, parsed_data: None, + version_request: None, } } @@ -613,6 +687,7 @@ fn execute_set_summary(call: &ToolCall, _current_summary: Option<&str>) -> ToolE new_body: None, new_summary: Some(summary), parsed_data: None, + version_request: None, } } @@ -633,6 +708,7 @@ fn execute_parse_csv(call: &ToolCall) -> ToolExecutionResult { new_body: None, new_summary: None, parsed_data: None, + version_request: None, }; } @@ -668,6 +744,7 @@ fn execute_parse_csv(call: &ToolCall) -> ToolExecutionResult { new_body: None, new_summary: None, parsed_data: Some(json!(data)), + version_request: None, } } @@ -680,6 +757,7 @@ fn execute_clear_body() -> ToolExecutionResult { new_body: Some(vec![]), new_summary: None, parsed_data: None, + version_request: None, } } @@ -695,6 +773,7 @@ fn execute_jq(call: &ToolCall) -> ToolExecutionResult { new_body: None, new_summary: None, parsed_data: None, + version_request: None, }; } }; @@ -710,6 +789,7 @@ fn execute_jq(call: &ToolCall) -> ToolExecutionResult { new_body: None, new_summary: None, parsed_data: None, + version_request: None, }; } }; @@ -729,6 +809,7 @@ fn execute_jq(call: &ToolCall) -> ToolExecutionResult { new_body: None, new_summary: None, parsed_data: None, + version_request: None, }; } @@ -741,6 +822,7 @@ fn execute_jq(call: &ToolCall) -> ToolExecutionResult { new_body: None, new_summary: None, parsed_data: None, + version_request: None, }; }; @@ -755,6 +837,7 @@ fn execute_jq(call: &ToolCall) -> ToolExecutionResult { new_body: None, new_summary: None, parsed_data: None, + version_request: None, }; } @@ -779,6 +862,7 @@ fn execute_jq(call: &ToolCall) -> ToolExecutionResult { new_body: None, new_summary: None, parsed_data: None, + version_request: None, }; } } @@ -808,6 +892,90 @@ fn execute_jq(call: &ToolCall) -> ToolExecutionResult { new_body: None, new_summary: None, parsed_data: Some(output), + version_request: None, + } +} + +// ============================================================================= +// Version History Tool Execution Functions +// ============================================================================= +// These return version_request instead of performing the operation directly, +// because they require async database access which is handled in the chat handler. + +fn execute_list_versions() -> ToolExecutionResult { + ToolExecutionResult { + result: ToolResult { + success: true, + message: "Listing versions...".to_string(), + }, + new_body: None, + new_summary: None, + parsed_data: None, + version_request: Some(VersionToolRequest::ListVersions), + } +} + +fn execute_read_version(call: &ToolCall) -> ToolExecutionResult { + let version = call.arguments.get("version").and_then(|v| v.as_i64()); + + let Some(version) = version else { + return ToolExecutionResult { + result: ToolResult { + success: false, + message: "Missing version parameter".to_string(), + }, + new_body: None, + new_summary: None, + parsed_data: None, + version_request: None, + }; + }; + + ToolExecutionResult { + result: ToolResult { + success: true, + message: format!("Reading version {}...", version), + }, + new_body: None, + new_summary: None, + parsed_data: None, + version_request: Some(VersionToolRequest::ReadVersion { version: version as i32 }), + } +} + +fn execute_restore_version(call: &ToolCall) -> ToolExecutionResult { + let target_version = call.arguments.get("target_version").and_then(|v| v.as_i64()); + let reason = call + .arguments + .get("reason") + .and_then(|v| v.as_str()) + .map(|s| s.to_string()); + + let Some(target_version) = target_version else { + return ToolExecutionResult { + result: ToolResult { + success: false, + message: "Missing target_version parameter".to_string(), + }, + new_body: None, + new_summary: None, + parsed_data: None, + version_request: None, + }; + }; + + ToolExecutionResult { + result: ToolResult { + success: true, + message: format!("Restoring to version {}...", target_version), + }, + new_body: None, + new_summary: None, + parsed_data: None, + version_request: Some(VersionToolRequest::RestoreVersion { + target_version: target_version as i32, + reason, + }), } } |
