feat: initial implementation of TFTSR IT Triage & RCA application
Implements Phases 1-8 of the TFTSR implementation plan.
Rust backend (Tauri 2.x, src-tauri/):
- Multi-provider AI: OpenAI-compatible, Anthropic, Gemini, Mistral, Ollama
- PII detection engine: 11 regex patterns with overlap resolution
- SQLCipher AES-256 encrypted database with 10 versioned migrations
- 28 Tauri IPC commands for triage, analysis, document, and system ops
- Ollama: hardware probe, model recommendations, pull/delete with events
- RCA and blameless post-mortem Markdown document generators
- PDF export via printpdf
- Audit log: SHA-256 hash of every external data send
- Integration stubs for Confluence, ServiceNow, Azure DevOps (v0.2)
Frontend (React 18 + TypeScript + Vite, src/):
- 9 pages: full triage workflow NewIssue→LogUpload→Triage→Resolution→RCA→Postmortem→History+Settings
- 7 components: ChatWindow, TriageProgress, PiiDiffViewer, DocEditor, HardwareReport, ModelSelector, UI primitives
- 3 Zustand stores: session, settings (persisted), history
- Type-safe tauriCommands.ts matching Rust backend types exactly
- 8 IT domain system prompts (Linux, Windows, Network, K8s, DB, Virt, HW, Obs)
DevOps:
- .woodpecker/test.yml: rustfmt, clippy, cargo test, tsc, vitest on every push
- .woodpecker/release.yml: linux/amd64 + linux/arm64 builds, Gogs release upload
Verified:
- cargo check: zero errors
- tsc --noEmit: zero errors
- vitest run: 13/13 unit tests passing
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 03:36:25 +00:00
|
|
|
use crate::ollama::{InstallGuide, OllamaStatus};
|
|
|
|
|
|
|
|
|
|
pub async fn check_ollama() -> anyhow::Result<OllamaStatus> {
|
|
|
|
|
// Check if binary exists
|
|
|
|
|
let which_cmd = if cfg!(target_os = "windows") {
|
|
|
|
|
"where"
|
|
|
|
|
} else {
|
|
|
|
|
"which"
|
|
|
|
|
};
|
|
|
|
|
|
2026-03-15 17:43:46 +00:00
|
|
|
let which_result = std::process::Command::new(which_cmd).arg("ollama").output();
|
feat: initial implementation of TFTSR IT Triage & RCA application
Implements Phases 1-8 of the TFTSR implementation plan.
Rust backend (Tauri 2.x, src-tauri/):
- Multi-provider AI: OpenAI-compatible, Anthropic, Gemini, Mistral, Ollama
- PII detection engine: 11 regex patterns with overlap resolution
- SQLCipher AES-256 encrypted database with 10 versioned migrations
- 28 Tauri IPC commands for triage, analysis, document, and system ops
- Ollama: hardware probe, model recommendations, pull/delete with events
- RCA and blameless post-mortem Markdown document generators
- PDF export via printpdf
- Audit log: SHA-256 hash of every external data send
- Integration stubs for Confluence, ServiceNow, Azure DevOps (v0.2)
Frontend (React 18 + TypeScript + Vite, src/):
- 9 pages: full triage workflow NewIssue→LogUpload→Triage→Resolution→RCA→Postmortem→History+Settings
- 7 components: ChatWindow, TriageProgress, PiiDiffViewer, DocEditor, HardwareReport, ModelSelector, UI primitives
- 3 Zustand stores: session, settings (persisted), history
- Type-safe tauriCommands.ts matching Rust backend types exactly
- 8 IT domain system prompts (Linux, Windows, Network, K8s, DB, Virt, HW, Obs)
DevOps:
- .woodpecker/test.yml: rustfmt, clippy, cargo test, tsc, vitest on every push
- .woodpecker/release.yml: linux/amd64 + linux/arm64 builds, Gogs release upload
Verified:
- cargo check: zero errors
- tsc --noEmit: zero errors
- vitest run: 13/13 unit tests passing
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 03:36:25 +00:00
|
|
|
|
2026-03-31 12:25:33 +00:00
|
|
|
// Check common install paths explicitly — Tauri's process PATH may omit /usr/local/bin
|
2026-03-31 13:05:13 +00:00
|
|
|
let in_common_path = [
|
|
|
|
|
"/usr/local/bin/ollama",
|
|
|
|
|
"/opt/homebrew/bin/ollama",
|
|
|
|
|
"/usr/bin/ollama",
|
|
|
|
|
]
|
|
|
|
|
.iter()
|
|
|
|
|
.any(|p| std::path::Path::new(p).exists());
|
2026-03-31 12:25:33 +00:00
|
|
|
|
|
|
|
|
let installed = which_result.map(|o| o.status.success()).unwrap_or(false) || in_common_path;
|
feat: initial implementation of TFTSR IT Triage & RCA application
Implements Phases 1-8 of the TFTSR implementation plan.
Rust backend (Tauri 2.x, src-tauri/):
- Multi-provider AI: OpenAI-compatible, Anthropic, Gemini, Mistral, Ollama
- PII detection engine: 11 regex patterns with overlap resolution
- SQLCipher AES-256 encrypted database with 10 versioned migrations
- 28 Tauri IPC commands for triage, analysis, document, and system ops
- Ollama: hardware probe, model recommendations, pull/delete with events
- RCA and blameless post-mortem Markdown document generators
- PDF export via printpdf
- Audit log: SHA-256 hash of every external data send
- Integration stubs for Confluence, ServiceNow, Azure DevOps (v0.2)
Frontend (React 18 + TypeScript + Vite, src/):
- 9 pages: full triage workflow NewIssue→LogUpload→Triage→Resolution→RCA→Postmortem→History+Settings
- 7 components: ChatWindow, TriageProgress, PiiDiffViewer, DocEditor, HardwareReport, ModelSelector, UI primitives
- 3 Zustand stores: session, settings (persisted), history
- Type-safe tauriCommands.ts matching Rust backend types exactly
- 8 IT domain system prompts (Linux, Windows, Network, K8s, DB, Virt, HW, Obs)
DevOps:
- .woodpecker/test.yml: rustfmt, clippy, cargo test, tsc, vitest on every push
- .woodpecker/release.yml: linux/amd64 + linux/arm64 builds, Gogs release upload
Verified:
- cargo check: zero errors
- tsc --noEmit: zero errors
- vitest run: 13/13 unit tests passing
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 03:36:25 +00:00
|
|
|
|
|
|
|
|
let version = if installed {
|
|
|
|
|
std::process::Command::new("ollama")
|
|
|
|
|
.arg("--version")
|
|
|
|
|
.output()
|
|
|
|
|
.ok()
|
|
|
|
|
.and_then(|o| String::from_utf8(o.stdout).ok())
|
|
|
|
|
.map(|s| s.trim().to_string())
|
|
|
|
|
} else {
|
|
|
|
|
None
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Check if Ollama API is responding
|
|
|
|
|
let running = reqwest::Client::new()
|
|
|
|
|
.get("http://localhost:11434/api/tags")
|
|
|
|
|
.timeout(std::time::Duration::from_secs(2))
|
|
|
|
|
.send()
|
|
|
|
|
.await
|
|
|
|
|
.map(|r| r.status().is_success())
|
|
|
|
|
.unwrap_or(false);
|
|
|
|
|
|
2026-03-31 12:25:33 +00:00
|
|
|
// If the API is responding, Ollama is definitely installed even if binary wasn't found in PATH
|
|
|
|
|
let installed = installed || running;
|
|
|
|
|
|
feat: initial implementation of TFTSR IT Triage & RCA application
Implements Phases 1-8 of the TFTSR implementation plan.
Rust backend (Tauri 2.x, src-tauri/):
- Multi-provider AI: OpenAI-compatible, Anthropic, Gemini, Mistral, Ollama
- PII detection engine: 11 regex patterns with overlap resolution
- SQLCipher AES-256 encrypted database with 10 versioned migrations
- 28 Tauri IPC commands for triage, analysis, document, and system ops
- Ollama: hardware probe, model recommendations, pull/delete with events
- RCA and blameless post-mortem Markdown document generators
- PDF export via printpdf
- Audit log: SHA-256 hash of every external data send
- Integration stubs for Confluence, ServiceNow, Azure DevOps (v0.2)
Frontend (React 18 + TypeScript + Vite, src/):
- 9 pages: full triage workflow NewIssue→LogUpload→Triage→Resolution→RCA→Postmortem→History+Settings
- 7 components: ChatWindow, TriageProgress, PiiDiffViewer, DocEditor, HardwareReport, ModelSelector, UI primitives
- 3 Zustand stores: session, settings (persisted), history
- Type-safe tauriCommands.ts matching Rust backend types exactly
- 8 IT domain system prompts (Linux, Windows, Network, K8s, DB, Virt, HW, Obs)
DevOps:
- .woodpecker/test.yml: rustfmt, clippy, cargo test, tsc, vitest on every push
- .woodpecker/release.yml: linux/amd64 + linux/arm64 builds, Gogs release upload
Verified:
- cargo check: zero errors
- tsc --noEmit: zero errors
- vitest run: 13/13 unit tests passing
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 03:36:25 +00:00
|
|
|
Ok(OllamaStatus {
|
|
|
|
|
installed,
|
|
|
|
|
version,
|
|
|
|
|
running,
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn get_install_instructions(platform: &str) -> InstallGuide {
|
|
|
|
|
let url = "https://ollama.com/download".to_string();
|
|
|
|
|
match platform {
|
|
|
|
|
"linux" => InstallGuide {
|
|
|
|
|
platform: "Linux".to_string(),
|
|
|
|
|
steps: vec![
|
|
|
|
|
"Open a terminal".to_string(),
|
|
|
|
|
"Run: curl -fsSL https://ollama.com/install.sh | sh".to_string(),
|
|
|
|
|
"Start Ollama: ollama serve".to_string(),
|
|
|
|
|
"Pull a model: ollama pull llama3.2:3b".to_string(),
|
|
|
|
|
],
|
|
|
|
|
url,
|
|
|
|
|
},
|
|
|
|
|
"macos" => InstallGuide {
|
|
|
|
|
platform: "macOS".to_string(),
|
|
|
|
|
steps: vec![
|
|
|
|
|
"Download the macOS installer from ollama.com/download".to_string(),
|
|
|
|
|
"Open the downloaded .dmg file".to_string(),
|
|
|
|
|
"Drag Ollama to Applications".to_string(),
|
|
|
|
|
"Launch Ollama from Applications".to_string(),
|
|
|
|
|
"Pull a model: ollama pull llama3.2:3b".to_string(),
|
|
|
|
|
],
|
|
|
|
|
url,
|
|
|
|
|
},
|
|
|
|
|
"windows" => InstallGuide {
|
|
|
|
|
platform: "Windows".to_string(),
|
|
|
|
|
steps: vec![
|
|
|
|
|
"Download OllamaSetup.exe from ollama.com/download".to_string(),
|
|
|
|
|
"Run the installer and follow the prompts".to_string(),
|
|
|
|
|
"Ollama will start automatically in the system tray".to_string(),
|
|
|
|
|
"Pull a model: ollama pull llama3.2:3b".to_string(),
|
|
|
|
|
],
|
|
|
|
|
url,
|
|
|
|
|
},
|
|
|
|
|
_ => InstallGuide {
|
|
|
|
|
platform: platform.to_string(),
|
|
|
|
|
steps: vec![
|
|
|
|
|
"Visit https://ollama.com/download for installation instructions".to_string(),
|
|
|
|
|
],
|
|
|
|
|
url,
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
|
mod tests {
|
|
|
|
|
use super::*;
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_linux_install_guide() {
|
|
|
|
|
let guide = get_install_instructions("linux");
|
|
|
|
|
assert_eq!(guide.platform, "Linux");
|
|
|
|
|
assert!(!guide.steps.is_empty());
|
|
|
|
|
assert!(guide.steps.iter().any(|s| s.contains("curl")));
|
|
|
|
|
assert!(guide.url.contains("ollama.com"));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_macos_install_guide() {
|
|
|
|
|
let guide = get_install_instructions("macos");
|
|
|
|
|
assert_eq!(guide.platform, "macOS");
|
2026-03-15 17:43:46 +00:00
|
|
|
assert!(guide
|
|
|
|
|
.steps
|
|
|
|
|
.iter()
|
|
|
|
|
.any(|s| s.contains("dmg") || s.contains("Applications")));
|
feat: initial implementation of TFTSR IT Triage & RCA application
Implements Phases 1-8 of the TFTSR implementation plan.
Rust backend (Tauri 2.x, src-tauri/):
- Multi-provider AI: OpenAI-compatible, Anthropic, Gemini, Mistral, Ollama
- PII detection engine: 11 regex patterns with overlap resolution
- SQLCipher AES-256 encrypted database with 10 versioned migrations
- 28 Tauri IPC commands for triage, analysis, document, and system ops
- Ollama: hardware probe, model recommendations, pull/delete with events
- RCA and blameless post-mortem Markdown document generators
- PDF export via printpdf
- Audit log: SHA-256 hash of every external data send
- Integration stubs for Confluence, ServiceNow, Azure DevOps (v0.2)
Frontend (React 18 + TypeScript + Vite, src/):
- 9 pages: full triage workflow NewIssue→LogUpload→Triage→Resolution→RCA→Postmortem→History+Settings
- 7 components: ChatWindow, TriageProgress, PiiDiffViewer, DocEditor, HardwareReport, ModelSelector, UI primitives
- 3 Zustand stores: session, settings (persisted), history
- Type-safe tauriCommands.ts matching Rust backend types exactly
- 8 IT domain system prompts (Linux, Windows, Network, K8s, DB, Virt, HW, Obs)
DevOps:
- .woodpecker/test.yml: rustfmt, clippy, cargo test, tsc, vitest on every push
- .woodpecker/release.yml: linux/amd64 + linux/arm64 builds, Gogs release upload
Verified:
- cargo check: zero errors
- tsc --noEmit: zero errors
- vitest run: 13/13 unit tests passing
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 03:36:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_windows_install_guide() {
|
|
|
|
|
let guide = get_install_instructions("windows");
|
|
|
|
|
assert_eq!(guide.platform, "Windows");
|
|
|
|
|
assert!(guide.steps.iter().any(|s| s.contains("OllamaSetup")));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_unknown_platform_fallback() {
|
|
|
|
|
let guide = get_install_instructions("freebsd");
|
|
|
|
|
assert_eq!(guide.platform, "freebsd");
|
|
|
|
|
assert_eq!(guide.steps.len(), 1);
|
|
|
|
|
assert!(guide.steps[0].contains("ollama.com"));
|
|
|
|
|
}
|
|
|
|
|
}
|