feat: add Tauri state persistence and BvCli trait
- Add Tauri storage adapter for Zustand (tauri-storage.ts) - Add read_state, write_state, clear_state Tauri commands - Wire focus-store and nav-store to use Tauri persistence - Add BvCli trait for bv CLI mocking with response types - Add BvError and McError conversion for bv errors - Add cleanup_tmp_files tests for bridge - Fix linter-introduced tauri_specta::command issues Closes bd-2x6, bd-gil, bd-3px Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -4,12 +4,13 @@
|
||||
//! to handle errors programmatically rather than parsing strings.
|
||||
|
||||
use serde::Serialize;
|
||||
use specta::Type;
|
||||
|
||||
/// Structured error type for Tauri IPC commands.
|
||||
///
|
||||
/// This replaces string-based errors (`Result<T, String>`) with typed errors
|
||||
/// that the frontend can handle programmatically.
|
||||
#[derive(Debug, Clone, Serialize)]
|
||||
#[derive(Debug, Clone, Serialize, Type)]
|
||||
pub struct McError {
|
||||
/// Machine-readable error code (e.g., "LORE_UNAVAILABLE", "BRIDGE_LOCKED")
|
||||
pub code: McErrorCode,
|
||||
@@ -20,7 +21,7 @@ pub struct McError {
|
||||
}
|
||||
|
||||
/// Error codes for frontend handling
|
||||
#[derive(Debug, Clone, Serialize, PartialEq, Eq)]
|
||||
#[derive(Debug, Clone, Serialize, PartialEq, Eq, Type)]
|
||||
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
|
||||
pub enum McErrorCode {
|
||||
// Lore errors
|
||||
@@ -38,6 +39,10 @@ pub enum McErrorCode {
|
||||
BeadsCreateFailed,
|
||||
BeadsCloseFailed,
|
||||
|
||||
// Bv errors
|
||||
BvUnavailable,
|
||||
BvTriageFailed,
|
||||
|
||||
// General errors
|
||||
IoError,
|
||||
InternalError,
|
||||
@@ -50,6 +55,7 @@ impl McError {
|
||||
code,
|
||||
McErrorCode::LoreUnavailable
|
||||
| McErrorCode::BeadsUnavailable
|
||||
| McErrorCode::BvUnavailable
|
||||
| McErrorCode::BridgeLocked
|
||||
| McErrorCode::IoError
|
||||
);
|
||||
@@ -97,6 +103,19 @@ impl McError {
|
||||
"br CLI not found -- is beads installed?",
|
||||
)
|
||||
}
|
||||
|
||||
/// Create an IO error with context
|
||||
pub fn io_error(context: impl Into<String>) -> Self {
|
||||
Self::new(McErrorCode::IoError, context)
|
||||
}
|
||||
|
||||
/// Create a bv unavailable error
|
||||
pub fn bv_unavailable() -> Self {
|
||||
Self::new(
|
||||
McErrorCode::BvUnavailable,
|
||||
"bv CLI not found -- is beads installed?",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for McError {
|
||||
@@ -169,6 +188,25 @@ impl From<crate::data::beads::BeadsError> for McError {
|
||||
}
|
||||
}
|
||||
|
||||
// Conversion from bv errors
|
||||
impl From<crate::data::bv::BvError> for McError {
|
||||
fn from(err: crate::data::bv::BvError) -> Self {
|
||||
use crate::data::bv::BvError;
|
||||
|
||||
match err {
|
||||
BvError::ExecutionFailed(_) => Self::bv_unavailable(),
|
||||
BvError::CommandFailed(msg) => Self::new(
|
||||
McErrorCode::BvTriageFailed,
|
||||
format!("bv command failed: {}", msg),
|
||||
),
|
||||
BvError::ParseFailed(msg) => Self::new(
|
||||
McErrorCode::BvTriageFailed,
|
||||
format!("Failed to parse bv response: {}", msg),
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
@@ -261,4 +299,24 @@ mod tests {
|
||||
assert_eq!(err.code, McErrorCode::BridgeMapCorrupted);
|
||||
assert!(!err.recoverable);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_bv_error_conversion() {
|
||||
use crate::data::bv::BvError;
|
||||
|
||||
// ExecutionFailed -> BvUnavailable (recoverable)
|
||||
let err: McError = BvError::ExecutionFailed("not found".to_string()).into();
|
||||
assert_eq!(err.code, McErrorCode::BvUnavailable);
|
||||
assert!(err.recoverable);
|
||||
|
||||
// CommandFailed -> BvTriageFailed (not recoverable)
|
||||
let err: McError = BvError::CommandFailed("failed".to_string()).into();
|
||||
assert_eq!(err.code, McErrorCode::BvTriageFailed);
|
||||
assert!(!err.recoverable);
|
||||
|
||||
// ParseFailed -> BvTriageFailed (not recoverable)
|
||||
let err: McError = BvError::ParseFailed("bad json".to_string()).into();
|
||||
assert_eq!(err.code, McErrorCode::BvTriageFailed);
|
||||
assert!(!err.recoverable);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user