style: apply cargo fmt formatting
This commit is contained in:
parent
1011fc1db4
commit
c8a717adee
@ -106,10 +106,7 @@ impl Provider for AnthropicProvider {
|
|||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
let model = json["model"]
|
let model = json["model"].as_str().unwrap_or(&config.model).to_string();
|
||||||
.as_str()
|
|
||||||
.unwrap_or(&config.model)
|
|
||||||
.to_string();
|
|
||||||
|
|
||||||
Ok(ChatResponse {
|
Ok(ChatResponse {
|
||||||
content,
|
content,
|
||||||
|
|||||||
@ -30,10 +30,7 @@ impl Provider for OpenAiProvider {
|
|||||||
config: &ProviderConfig,
|
config: &ProviderConfig,
|
||||||
) -> anyhow::Result<ChatResponse> {
|
) -> anyhow::Result<ChatResponse> {
|
||||||
let client = reqwest::Client::new();
|
let client = reqwest::Client::new();
|
||||||
let url = format!(
|
let url = format!("{}/chat/completions", config.api_url.trim_end_matches('/'));
|
||||||
"{}/chat/completions",
|
|
||||||
config.api_url.trim_end_matches('/')
|
|
||||||
);
|
|
||||||
|
|
||||||
let body = serde_json::json!({
|
let body = serde_json::json!({
|
||||||
"model": config.model,
|
"model": config.model,
|
||||||
|
|||||||
@ -54,8 +54,14 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_write_audit_event_inserts_row() {
|
fn test_write_audit_event_inserts_row() {
|
||||||
let conn = setup_test_db();
|
let conn = setup_test_db();
|
||||||
write_audit_event(&conn, "test_action", "issue", "issue-123", r#"{"key":"val"}"#)
|
write_audit_event(
|
||||||
.expect("should insert");
|
&conn,
|
||||||
|
"test_action",
|
||||||
|
"issue",
|
||||||
|
"issue-123",
|
||||||
|
r#"{"key":"val"}"#,
|
||||||
|
)
|
||||||
|
.expect("should insert");
|
||||||
|
|
||||||
let count: i64 = conn
|
let count: i64 = conn
|
||||||
.prepare("SELECT COUNT(*) FROM audit_log")
|
.prepare("SELECT COUNT(*) FROM audit_log")
|
||||||
|
|||||||
@ -48,10 +48,7 @@ pub async fn analyze_logs(
|
|||||||
},
|
},
|
||||||
Message {
|
Message {
|
||||||
role: "user".into(),
|
role: "user".into(),
|
||||||
content: format!(
|
content: format!("Analyze logs for issue {}:\n\n{}", issue_id, log_contents),
|
||||||
"Analyze logs for issue {}:\n\n{}",
|
|
||||||
issue_id, log_contents
|
|
||||||
),
|
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
@ -61,8 +58,13 @@ pub async fn analyze_logs(
|
|||||||
.map_err(|e| e.to_string())?;
|
.map_err(|e| e.to_string())?;
|
||||||
|
|
||||||
let content = &response.content;
|
let content = &response.content;
|
||||||
let summary = extract_section(content, "SUMMARY:")
|
let summary = extract_section(content, "SUMMARY:").unwrap_or_else(|| {
|
||||||
.unwrap_or_else(|| content.lines().next().unwrap_or("Analysis complete").to_string());
|
content
|
||||||
|
.lines()
|
||||||
|
.next()
|
||||||
|
.unwrap_or("Analysis complete")
|
||||||
|
.to_string()
|
||||||
|
});
|
||||||
let key_findings = extract_list(content, "KEY_FINDINGS:");
|
let key_findings = extract_list(content, "KEY_FINDINGS:");
|
||||||
let suggested_why1 = extract_section(content, "FIRST_WHY:")
|
let suggested_why1 = extract_section(content, "FIRST_WHY:")
|
||||||
.unwrap_or_else(|| "Why did this issue occur?".to_string());
|
.unwrap_or_else(|| "Why did this issue occur?".to_string());
|
||||||
@ -76,7 +78,8 @@ pub async fn analyze_logs(
|
|||||||
"ai_analyze_logs".to_string(),
|
"ai_analyze_logs".to_string(),
|
||||||
"issue".to_string(),
|
"issue".to_string(),
|
||||||
issue_id.clone(),
|
issue_id.clone(),
|
||||||
serde_json::json!({ "log_file_ids": log_file_ids, "provider": provider_config.name }).to_string(),
|
serde_json::json!({ "log_file_ids": log_file_ids, "provider": provider_config.name })
|
||||||
|
.to_string(),
|
||||||
);
|
);
|
||||||
db.execute(
|
db.execute(
|
||||||
"INSERT INTO audit_log (id, timestamp, action, entity_type, entity_id, user_id, details) \
|
"INSERT INTO audit_log (id, timestamp, action, entity_type, entity_id, user_id, details) \
|
||||||
@ -275,10 +278,7 @@ pub async fn list_providers() -> Result<Vec<ProviderInfo>, String> {
|
|||||||
ProviderInfo {
|
ProviderInfo {
|
||||||
name: "gemini".to_string(),
|
name: "gemini".to_string(),
|
||||||
supports_streaming: false,
|
supports_streaming: false,
|
||||||
models: vec![
|
models: vec!["gemini-1.5-pro".to_string(), "gemini-1.5-flash".to_string()],
|
||||||
"gemini-1.5-pro".to_string(),
|
|
||||||
"gemini-1.5-flash".to_string(),
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
ProviderInfo {
|
ProviderInfo {
|
||||||
name: "mistral".to_string(),
|
name: "mistral".to_string(),
|
||||||
|
|||||||
@ -64,8 +64,13 @@ pub async fn upload_log_file(
|
|||||||
"INSERT INTO audit_log (id, timestamp, action, entity_type, entity_id, user_id, details) \
|
"INSERT INTO audit_log (id, timestamp, action, entity_type, entity_id, user_id, details) \
|
||||||
VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7)",
|
VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7)",
|
||||||
rusqlite::params![
|
rusqlite::params![
|
||||||
entry.id, entry.timestamp, entry.action,
|
entry.id,
|
||||||
entry.entity_type, entry.entity_id, entry.user_id, entry.details
|
entry.timestamp,
|
||||||
|
entry.action,
|
||||||
|
entry.entity_type,
|
||||||
|
entry.entity_id,
|
||||||
|
entry.user_id,
|
||||||
|
entry.details
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -163,14 +168,16 @@ pub async fn apply_redactions(
|
|||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
drop(db);
|
drop(db);
|
||||||
raw.into_iter()
|
raw.into_iter()
|
||||||
.map(|(id, pii_type, start, end, original, replacement)| pii::PiiSpan {
|
.map(
|
||||||
id,
|
|(id, pii_type, start, end, original, replacement)| pii::PiiSpan {
|
||||||
pii_type,
|
id,
|
||||||
start: start as usize,
|
pii_type,
|
||||||
end: end as usize,
|
start: start as usize,
|
||||||
original,
|
end: end as usize,
|
||||||
replacement,
|
original,
|
||||||
})
|
replacement,
|
||||||
|
},
|
||||||
|
)
|
||||||
.filter(|span| approved_span_ids.contains(&span.id))
|
.filter(|span| approved_span_ids.contains(&span.id))
|
||||||
.collect()
|
.collect()
|
||||||
};
|
};
|
||||||
|
|||||||
@ -247,23 +247,29 @@ pub async fn update_issue(
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
pub async fn delete_issue(
|
pub async fn delete_issue(issue_id: String, state: State<'_, AppState>) -> Result<(), String> {
|
||||||
issue_id: String,
|
|
||||||
state: State<'_, AppState>,
|
|
||||||
) -> Result<(), String> {
|
|
||||||
let db = state.db.lock().map_err(|e| e.to_string())?;
|
let db = state.db.lock().map_err(|e| e.to_string())?;
|
||||||
|
|
||||||
// Delete related records (CASCADE should handle this, but be explicit)
|
// Delete related records (CASCADE should handle this, but be explicit)
|
||||||
db.execute("DELETE FROM ai_messages WHERE conversation_id IN (SELECT id FROM ai_conversations WHERE issue_id = ?1)", [&issue_id])
|
db.execute("DELETE FROM ai_messages WHERE conversation_id IN (SELECT id FROM ai_conversations WHERE issue_id = ?1)", [&issue_id])
|
||||||
.map_err(|e| e.to_string())?;
|
.map_err(|e| e.to_string())?;
|
||||||
db.execute("DELETE FROM ai_conversations WHERE issue_id = ?1", [&issue_id])
|
db.execute(
|
||||||
.map_err(|e| e.to_string())?;
|
"DELETE FROM ai_conversations WHERE issue_id = ?1",
|
||||||
db.execute("DELETE FROM pii_spans WHERE log_file_id IN (SELECT id FROM log_files WHERE issue_id = ?1)", [&issue_id])
|
[&issue_id],
|
||||||
.map_err(|e| e.to_string())?;
|
)
|
||||||
|
.map_err(|e| e.to_string())?;
|
||||||
|
db.execute(
|
||||||
|
"DELETE FROM pii_spans WHERE log_file_id IN (SELECT id FROM log_files WHERE issue_id = ?1)",
|
||||||
|
[&issue_id],
|
||||||
|
)
|
||||||
|
.map_err(|e| e.to_string())?;
|
||||||
db.execute("DELETE FROM log_files WHERE issue_id = ?1", [&issue_id])
|
db.execute("DELETE FROM log_files WHERE issue_id = ?1", [&issue_id])
|
||||||
.map_err(|e| e.to_string())?;
|
.map_err(|e| e.to_string())?;
|
||||||
db.execute("DELETE FROM resolution_steps WHERE issue_id = ?1", [&issue_id])
|
db.execute(
|
||||||
.map_err(|e| e.to_string())?;
|
"DELETE FROM resolution_steps WHERE issue_id = ?1",
|
||||||
|
[&issue_id],
|
||||||
|
)
|
||||||
|
.map_err(|e| e.to_string())?;
|
||||||
db.execute("DELETE FROM issues WHERE id = ?1", [&issue_id])
|
db.execute("DELETE FROM issues WHERE id = ?1", [&issue_id])
|
||||||
.map_err(|e| e.to_string())?;
|
.map_err(|e| e.to_string())?;
|
||||||
|
|
||||||
@ -364,13 +370,7 @@ pub async fn add_five_why(
|
|||||||
evidence: String,
|
evidence: String,
|
||||||
state: State<'_, AppState>,
|
state: State<'_, AppState>,
|
||||||
) -> Result<ResolutionStep, String> {
|
) -> Result<ResolutionStep, String> {
|
||||||
let step = ResolutionStep::new(
|
let step = ResolutionStep::new(issue_id.clone(), step_order, why_question, answer, evidence);
|
||||||
issue_id.clone(),
|
|
||||||
step_order,
|
|
||||||
why_question,
|
|
||||||
answer,
|
|
||||||
evidence,
|
|
||||||
);
|
|
||||||
|
|
||||||
let db = state.db.lock().map_err(|e| e.to_string())?;
|
let db = state.db.lock().map_err(|e| e.to_string())?;
|
||||||
db.execute(
|
db.execute(
|
||||||
@ -444,8 +444,13 @@ pub async fn add_timeline_event(
|
|||||||
"INSERT INTO audit_log (id, timestamp, action, entity_type, entity_id, user_id, details) \
|
"INSERT INTO audit_log (id, timestamp, action, entity_type, entity_id, user_id, details) \
|
||||||
VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7)",
|
VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7)",
|
||||||
rusqlite::params![
|
rusqlite::params![
|
||||||
entry.id, entry.timestamp, entry.action,
|
entry.id,
|
||||||
entry.entity_type, entry.entity_id, entry.user_id, entry.details
|
entry.timestamp,
|
||||||
|
entry.action,
|
||||||
|
entry.entity_type,
|
||||||
|
entry.entity_id,
|
||||||
|
entry.user_id,
|
||||||
|
entry.details
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
.map_err(|e| e.to_string())?;
|
.map_err(|e| e.to_string())?;
|
||||||
|
|||||||
@ -52,8 +52,13 @@ pub async fn generate_rca(
|
|||||||
"INSERT INTO audit_log (id, timestamp, action, entity_type, entity_id, user_id, details) \
|
"INSERT INTO audit_log (id, timestamp, action, entity_type, entity_id, user_id, details) \
|
||||||
VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7)",
|
VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7)",
|
||||||
rusqlite::params![
|
rusqlite::params![
|
||||||
entry.id, entry.timestamp, entry.action,
|
entry.id,
|
||||||
entry.entity_type, entry.entity_id, entry.user_id, entry.details
|
entry.timestamp,
|
||||||
|
entry.action,
|
||||||
|
entry.entity_type,
|
||||||
|
entry.entity_id,
|
||||||
|
entry.user_id,
|
||||||
|
entry.details
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -94,8 +99,13 @@ pub async fn generate_postmortem(
|
|||||||
"INSERT INTO audit_log (id, timestamp, action, entity_type, entity_id, user_id, details) \
|
"INSERT INTO audit_log (id, timestamp, action, entity_type, entity_id, user_id, details) \
|
||||||
VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7)",
|
VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7)",
|
||||||
rusqlite::params![
|
rusqlite::params![
|
||||||
entry.id, entry.timestamp, entry.action,
|
entry.id,
|
||||||
entry.entity_type, entry.entity_id, entry.user_id, entry.details
|
entry.timestamp,
|
||||||
|
entry.action,
|
||||||
|
entry.entity_type,
|
||||||
|
entry.entity_id,
|
||||||
|
entry.user_id,
|
||||||
|
entry.details
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -103,10 +113,7 @@ pub async fn generate_postmortem(
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
pub async fn update_document(
|
pub async fn update_document(doc_id: String, content_md: String) -> Result<(), String> {
|
||||||
doc_id: String,
|
|
||||||
content_md: String,
|
|
||||||
) -> Result<(), String> {
|
|
||||||
// Documents are generated on-demand and held in memory / frontend state.
|
// Documents are generated on-demand and held in memory / frontend state.
|
||||||
// This is a no-op placeholder. In a future version with a documents table,
|
// This is a no-op placeholder. In a future version with a documents table,
|
||||||
// this would persist updates.
|
// this would persist updates.
|
||||||
|
|||||||
@ -9,9 +9,7 @@ use crate::state::{AppSettings, AppState};
|
|||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
pub async fn check_ollama_installed() -> Result<OllamaStatus, String> {
|
pub async fn check_ollama_installed() -> Result<OllamaStatus, String> {
|
||||||
installer::check_ollama()
|
installer::check_ollama().await.map_err(|e| e.to_string())
|
||||||
.await
|
|
||||||
.map_err(|e| e.to_string())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
@ -55,9 +53,7 @@ pub async fn recommend_models() -> Result<Vec<ModelRecommendation>, String> {
|
|||||||
// --- Settings commands ---
|
// --- Settings commands ---
|
||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
pub async fn get_settings(
|
pub async fn get_settings(state: tauri::State<'_, AppState>) -> Result<AppSettings, String> {
|
||||||
state: tauri::State<'_, AppState>,
|
|
||||||
) -> Result<AppSettings, String> {
|
|
||||||
state
|
state
|
||||||
.settings
|
.settings
|
||||||
.lock()
|
.lock()
|
||||||
|
|||||||
@ -35,8 +35,7 @@ pub fn export_pdf(content_md: &str, title: &str, output_path: &str) -> anyhow::R
|
|||||||
|
|
||||||
for line_info in &lines {
|
for line_info in &lines {
|
||||||
if line_count >= max_lines_per_page {
|
if line_count >= max_lines_per_page {
|
||||||
let (new_page, new_layer) =
|
let (new_page, new_layer) = doc.add_page(Mm(210.0), Mm(297.0), "Layer 1");
|
||||||
doc.add_page(Mm(210.0), Mm(297.0), "Layer 1");
|
|
||||||
current_layer = doc.get_page(new_page).get_layer(new_layer);
|
current_layer = doc.get_page(new_page).get_layer(new_layer);
|
||||||
y_pos = margin_top;
|
y_pos = margin_top;
|
||||||
line_count = 0;
|
line_count = 0;
|
||||||
@ -185,13 +184,18 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_markdown_to_lines_title() {
|
fn test_markdown_to_lines_title() {
|
||||||
let lines = markdown_to_lines("# My Title\n\nSome text");
|
let lines = markdown_to_lines("# My Title\n\nSome text");
|
||||||
assert!(lines.iter().any(|l| l.text == "My Title" && matches!(l.style, LineStyle::Title)));
|
assert!(lines
|
||||||
|
.iter()
|
||||||
|
.any(|l| l.text == "My Title" && matches!(l.style, LineStyle::Title)));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_markdown_to_lines_heading() {
|
fn test_markdown_to_lines_heading() {
|
||||||
let lines = markdown_to_lines("## Section\n### Subsection");
|
let lines = markdown_to_lines("## Section\n### Subsection");
|
||||||
let headings: Vec<_> = lines.iter().filter(|l| matches!(l.style, LineStyle::Heading)).collect();
|
let headings: Vec<_> = lines
|
||||||
|
.iter()
|
||||||
|
.filter(|l| matches!(l.style, LineStyle::Heading))
|
||||||
|
.collect();
|
||||||
assert_eq!(headings.len(), 2);
|
assert_eq!(headings.len(), 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -204,7 +208,9 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_markdown_to_lines_table_row() {
|
fn test_markdown_to_lines_table_row() {
|
||||||
let lines = markdown_to_lines("| Col1 | Col2 |\n|------|------|\n| A | B |");
|
let lines = markdown_to_lines("| Col1 | Col2 |\n|------|------|\n| A | B |");
|
||||||
assert!(lines.iter().any(|l| l.text.contains("Col1") && l.text.contains("Col2")));
|
assert!(lines
|
||||||
|
.iter()
|
||||||
|
.any(|l| l.text.contains("Col1") && l.text.contains("Col2")));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|||||||
@ -5,10 +5,7 @@ pub fn generate_postmortem_markdown(detail: &IssueDetail) -> String {
|
|||||||
|
|
||||||
let mut md = String::new();
|
let mut md = String::new();
|
||||||
|
|
||||||
md.push_str(&format!(
|
md.push_str(&format!("# Blameless Post-Mortem: {}\n\n", issue.title));
|
||||||
"# Blameless Post-Mortem: {}\n\n",
|
|
||||||
issue.title
|
|
||||||
));
|
|
||||||
|
|
||||||
// Header metadata
|
// Header metadata
|
||||||
md.push_str("## Metadata\n\n");
|
md.push_str("## Metadata\n\n");
|
||||||
@ -19,7 +16,11 @@ pub fn generate_postmortem_markdown(detail: &IssueDetail) -> String {
|
|||||||
md.push_str(&format!("- **Last Updated:** {}\n", issue.updated_at));
|
md.push_str(&format!("- **Last Updated:** {}\n", issue.updated_at));
|
||||||
md.push_str(&format!(
|
md.push_str(&format!(
|
||||||
"- **Assigned To:** {}\n",
|
"- **Assigned To:** {}\n",
|
||||||
if issue.assigned_to.is_empty() { "_Unassigned_" } else { &issue.assigned_to }
|
if issue.assigned_to.is_empty() {
|
||||||
|
"_Unassigned_"
|
||||||
|
} else {
|
||||||
|
&issue.assigned_to
|
||||||
|
}
|
||||||
));
|
));
|
||||||
md.push_str("- **Authors:** _[Add authors]_\n");
|
md.push_str("- **Authors:** _[Add authors]_\n");
|
||||||
md.push_str("- **Reviewers:** _[Add reviewers]_\n\n");
|
md.push_str("- **Reviewers:** _[Add reviewers]_\n\n");
|
||||||
|
|||||||
@ -15,7 +15,14 @@ pub fn generate_rca_markdown(detail: &IssueDetail) -> String {
|
|||||||
md.push_str(&format!("| **Status** | {} |\n", issue.status));
|
md.push_str(&format!("| **Status** | {} |\n", issue.status));
|
||||||
md.push_str(&format!("| **Severity** | {} |\n", issue.severity));
|
md.push_str(&format!("| **Severity** | {} |\n", issue.severity));
|
||||||
md.push_str(&format!("| **Source** | {} |\n", issue.source));
|
md.push_str(&format!("| **Source** | {} |\n", issue.source));
|
||||||
md.push_str(&format!("| **Assigned To** | {} |\n", if issue.assigned_to.is_empty() { "Unassigned" } else { &issue.assigned_to }));
|
md.push_str(&format!(
|
||||||
|
"| **Assigned To** | {} |\n",
|
||||||
|
if issue.assigned_to.is_empty() {
|
||||||
|
"Unassigned"
|
||||||
|
} else {
|
||||||
|
&issue.assigned_to
|
||||||
|
}
|
||||||
|
));
|
||||||
md.push_str(&format!("| **Created** | {} |\n", issue.created_at));
|
md.push_str(&format!("| **Created** | {} |\n", issue.created_at));
|
||||||
md.push_str(&format!("| **Last Updated** | {} |\n", issue.updated_at));
|
md.push_str(&format!("| **Last Updated** | {} |\n", issue.updated_at));
|
||||||
if let Some(ref resolved) = issue.resolved_at {
|
if let Some(ref resolved) = issue.resolved_at {
|
||||||
|
|||||||
@ -19,7 +19,10 @@ pub struct WorkItem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub async fn test_connection(_config: &AzureDevOpsConfig) -> Result<ConnectionResult, String> {
|
pub async fn test_connection(_config: &AzureDevOpsConfig) -> Result<ConnectionResult, String> {
|
||||||
Err("Azure DevOps integration available in v0.2. Please update to the latest version.".to_string())
|
Err(
|
||||||
|
"Azure DevOps integration available in v0.2. Please update to the latest version."
|
||||||
|
.to_string(),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn create_work_item(
|
pub async fn create_work_item(
|
||||||
@ -29,14 +32,20 @@ pub async fn create_work_item(
|
|||||||
_work_item_type: &str,
|
_work_item_type: &str,
|
||||||
_severity: &str,
|
_severity: &str,
|
||||||
) -> Result<TicketResult, String> {
|
) -> Result<TicketResult, String> {
|
||||||
Err("Azure DevOps integration available in v0.2. Please update to the latest version.".to_string())
|
Err(
|
||||||
|
"Azure DevOps integration available in v0.2. Please update to the latest version."
|
||||||
|
.to_string(),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_work_item(
|
pub async fn get_work_item(
|
||||||
_config: &AzureDevOpsConfig,
|
_config: &AzureDevOpsConfig,
|
||||||
_work_item_id: i64,
|
_work_item_id: i64,
|
||||||
) -> Result<WorkItem, String> {
|
) -> Result<WorkItem, String> {
|
||||||
Err("Azure DevOps integration available in v0.2. Please update to the latest version.".to_string())
|
Err(
|
||||||
|
"Azure DevOps integration available in v0.2. Please update to the latest version."
|
||||||
|
.to_string(),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn update_work_item(
|
pub async fn update_work_item(
|
||||||
@ -44,5 +53,8 @@ pub async fn update_work_item(
|
|||||||
_work_item_id: i64,
|
_work_item_id: i64,
|
||||||
_updates: serde_json::Value,
|
_updates: serde_json::Value,
|
||||||
) -> Result<TicketResult, String> {
|
) -> Result<TicketResult, String> {
|
||||||
Err("Azure DevOps integration available in v0.2. Please update to the latest version.".to_string())
|
Err(
|
||||||
|
"Azure DevOps integration available in v0.2. Please update to the latest version."
|
||||||
|
.to_string(),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -24,11 +24,17 @@ pub struct Page {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub async fn test_connection(_config: &ConfluenceConfig) -> Result<ConnectionResult, String> {
|
pub async fn test_connection(_config: &ConfluenceConfig) -> Result<ConnectionResult, String> {
|
||||||
Err("Confluence integration available in v0.2. Please update to the latest version.".to_string())
|
Err(
|
||||||
|
"Confluence integration available in v0.2. Please update to the latest version."
|
||||||
|
.to_string(),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn list_spaces(_config: &ConfluenceConfig) -> Result<Vec<Space>, String> {
|
pub async fn list_spaces(_config: &ConfluenceConfig) -> Result<Vec<Space>, String> {
|
||||||
Err("Confluence integration available in v0.2. Please update to the latest version.".to_string())
|
Err(
|
||||||
|
"Confluence integration available in v0.2. Please update to the latest version."
|
||||||
|
.to_string(),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn publish_page(
|
pub async fn publish_page(
|
||||||
@ -38,7 +44,10 @@ pub async fn publish_page(
|
|||||||
_content_html: &str,
|
_content_html: &str,
|
||||||
_parent_page_id: Option<&str>,
|
_parent_page_id: Option<&str>,
|
||||||
) -> Result<PublishResult, String> {
|
) -> Result<PublishResult, String> {
|
||||||
Err("Confluence integration available in v0.2. Please update to the latest version.".to_string())
|
Err(
|
||||||
|
"Confluence integration available in v0.2. Please update to the latest version."
|
||||||
|
.to_string(),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn update_page(
|
pub async fn update_page(
|
||||||
@ -48,5 +57,8 @@ pub async fn update_page(
|
|||||||
_content_html: &str,
|
_content_html: &str,
|
||||||
_version: i32,
|
_version: i32,
|
||||||
) -> Result<PublishResult, String> {
|
) -> Result<PublishResult, String> {
|
||||||
Err("Confluence integration available in v0.2. Please update to the latest version.".to_string())
|
Err(
|
||||||
|
"Confluence integration available in v0.2. Please update to the latest version."
|
||||||
|
.to_string(),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -20,7 +20,10 @@ pub struct Incident {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub async fn test_connection(_config: &ServiceNowConfig) -> Result<ConnectionResult, String> {
|
pub async fn test_connection(_config: &ServiceNowConfig) -> Result<ConnectionResult, String> {
|
||||||
Err("ServiceNow integration available in v0.2. Please update to the latest version.".to_string())
|
Err(
|
||||||
|
"ServiceNow integration available in v0.2. Please update to the latest version."
|
||||||
|
.to_string(),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn create_incident(
|
pub async fn create_incident(
|
||||||
@ -30,14 +33,20 @@ pub async fn create_incident(
|
|||||||
_urgency: &str,
|
_urgency: &str,
|
||||||
_impact: &str,
|
_impact: &str,
|
||||||
) -> Result<TicketResult, String> {
|
) -> Result<TicketResult, String> {
|
||||||
Err("ServiceNow integration available in v0.2. Please update to the latest version.".to_string())
|
Err(
|
||||||
|
"ServiceNow integration available in v0.2. Please update to the latest version."
|
||||||
|
.to_string(),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_incident(
|
pub async fn get_incident(
|
||||||
_config: &ServiceNowConfig,
|
_config: &ServiceNowConfig,
|
||||||
_incident_number: &str,
|
_incident_number: &str,
|
||||||
) -> Result<Incident, String> {
|
) -> Result<Incident, String> {
|
||||||
Err("ServiceNow integration available in v0.2. Please update to the latest version.".to_string())
|
Err(
|
||||||
|
"ServiceNow integration available in v0.2. Please update to the latest version."
|
||||||
|
.to_string(),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn update_incident(
|
pub async fn update_incident(
|
||||||
@ -45,5 +54,8 @@ pub async fn update_incident(
|
|||||||
_incident_number: &str,
|
_incident_number: &str,
|
||||||
_updates: serde_json::Value,
|
_updates: serde_json::Value,
|
||||||
) -> Result<TicketResult, String> {
|
) -> Result<TicketResult, String> {
|
||||||
Err("ServiceNow integration available in v0.2. Please update to the latest version.".to_string())
|
Err(
|
||||||
|
"ServiceNow integration available in v0.2. Please update to the latest version."
|
||||||
|
.to_string(),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,13 +8,9 @@ pub async fn check_ollama() -> anyhow::Result<OllamaStatus> {
|
|||||||
"which"
|
"which"
|
||||||
};
|
};
|
||||||
|
|
||||||
let which_result = std::process::Command::new(which_cmd)
|
let which_result = std::process::Command::new(which_cmd).arg("ollama").output();
|
||||||
.arg("ollama")
|
|
||||||
.output();
|
|
||||||
|
|
||||||
let installed = which_result
|
let installed = which_result.map(|o| o.status.success()).unwrap_or(false);
|
||||||
.map(|o| o.status.success())
|
|
||||||
.unwrap_or(false);
|
|
||||||
|
|
||||||
let version = if installed {
|
let version = if installed {
|
||||||
std::process::Command::new("ollama")
|
std::process::Command::new("ollama")
|
||||||
@ -104,7 +100,10 @@ mod tests {
|
|||||||
fn test_macos_install_guide() {
|
fn test_macos_install_guide() {
|
||||||
let guide = get_install_instructions("macos");
|
let guide = get_install_instructions("macos");
|
||||||
assert_eq!(guide.platform, "macOS");
|
assert_eq!(guide.platform, "macOS");
|
||||||
assert!(guide.steps.iter().any(|s| s.contains("dmg") || s.contains("Applications")));
|
assert!(guide
|
||||||
|
.steps
|
||||||
|
.iter()
|
||||||
|
.any(|s| s.contains("dmg") || s.contains("Applications")));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|||||||
@ -46,8 +46,7 @@ pub fn recommend_models(hw: &HardwareInfo) -> Vec<ModelRecommendation> {
|
|||||||
size: "40 GB".to_string(),
|
size: "40 GB".to_string(),
|
||||||
min_ram_gb: 48.0,
|
min_ram_gb: 48.0,
|
||||||
description: "Full Llama 3.1 70B. Best quality, requires significant RAM.".to_string(),
|
description: "Full Llama 3.1 70B. Best quality, requires significant RAM.".to_string(),
|
||||||
recommended: ram >= 48.0
|
recommended: ram >= 48.0 || (has_gpu && hw.gpu_vram_gb.unwrap_or(0.0) >= 40.0),
|
||||||
|| (has_gpu && hw.gpu_vram_gb.unwrap_or(0.0) >= 40.0),
|
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user