c118996746
- SwiftUI macOS app with C++17 code analysis engine (ObjC++ bridge) - Agentic AI loop: LLM plans → tool calls → execution → feedback loop - 15 agent tools: file ops, terminal, git, xcode build, code intel - 7 persistent terminal tools with background session management - Chat sidebar with agent step rendering and auto-apply - NVIDIA NIM API integration (Llama 3.3 70B default) - OpenAI tool_calls format with prompt-based fallback - Code editor with syntax highlighting and multi-tab support - File tree, console view, terminal view - Git integration and workspace management
77 lines
2.6 KiB
Swift
77 lines
2.6 KiB
Swift
import Foundation
|
|
|
|
struct FileItem: Identifiable, Hashable {
|
|
let id: UUID
|
|
let name: String
|
|
let url: URL
|
|
let isDirectory: Bool
|
|
var children: [FileItem]?
|
|
|
|
init(name: String, url: URL, isDirectory: Bool = false, children: [FileItem]? = nil) {
|
|
self.id = UUID()
|
|
self.name = name
|
|
self.url = url
|
|
self.isDirectory = isDirectory
|
|
self.children = children
|
|
}
|
|
|
|
var fileExtension: String {
|
|
url.pathExtension.lowercased()
|
|
}
|
|
|
|
var iconName: String {
|
|
if isDirectory { return "folder.fill" }
|
|
switch fileExtension {
|
|
case "swift": return "swift"
|
|
case "h", "hpp": return "doc.text"
|
|
case "c", "cpp", "m", "mm": return "doc.text.fill"
|
|
case "json": return "curlybraces"
|
|
case "md", "txt": return "doc.plaintext"
|
|
case "png", "jpg", "jpeg", "gif": return "photo"
|
|
case "xcodeproj", "xcworkspace": return "hammer"
|
|
default: return "doc"
|
|
}
|
|
}
|
|
|
|
var iconColorName: String {
|
|
if isDirectory { return "blue" }
|
|
switch fileExtension {
|
|
case "swift": return "orange"
|
|
case "h", "hpp": return "purple"
|
|
case "c", "cpp": return "cyan"
|
|
case "m", "mm": return "teal"
|
|
case "json": return "yellow"
|
|
default: return "gray"
|
|
}
|
|
}
|
|
|
|
static func loadDirectory(at url: URL) throws -> [FileItem] {
|
|
let fm = FileManager.default
|
|
let contents = try fm.contentsOfDirectory(
|
|
at: url,
|
|
includingPropertiesForKeys: [.isDirectoryKey],
|
|
options: [.skipsHiddenFiles]
|
|
)
|
|
|
|
return try contents
|
|
.sorted { $0.lastPathComponent.localizedCaseInsensitiveCompare($1.lastPathComponent) == .orderedAscending }
|
|
.map { itemURL in
|
|
let resourceValues = try itemURL.resourceValues(forKeys: [.isDirectoryKey])
|
|
let isDir = resourceValues.isDirectory ?? false
|
|
let children = isDir ? try loadDirectory(at: itemURL) : nil
|
|
return FileItem(
|
|
name: itemURL.lastPathComponent,
|
|
url: itemURL,
|
|
isDirectory: isDir,
|
|
children: children
|
|
)
|
|
}
|
|
}
|
|
|
|
var sortedChildren: [FileItem]? {
|
|
children?.sorted { lhs, rhs in
|
|
if lhs.isDirectory != rhs.isDirectory { return lhs.isDirectory }
|
|
return lhs.name.localizedCaseInsensitiveCompare(rhs.name) == .orderedAscending
|
|
}
|
|
}
|
|
} |