mirror of
https://github.com/openclaw/openclaw.git
synced 2026-07-17 14:41:34 +00:00
104 lines
3.8 KiB
Swift
104 lines
3.8 KiB
Swift
import Foundation
|
|
import OpenClawKit
|
|
|
|
enum MacNodeFileSystemCommands {
|
|
private struct ListDirectoryParams: Decodable {
|
|
var path: String?
|
|
}
|
|
|
|
private struct DirectoryEntry: Encodable {
|
|
var name: String
|
|
var path: String
|
|
var hidden: Bool?
|
|
}
|
|
|
|
private struct ListDirectoryPayload: Encodable {
|
|
var path: String
|
|
var parent: String?
|
|
var home: String
|
|
var entries: [DirectoryEntry]
|
|
}
|
|
|
|
static func listDirectory(_ request: BridgeInvokeRequest) throws -> BridgeInvokeResponse {
|
|
let params: ListDirectoryParams = if let paramsJSON = request.paramsJSON {
|
|
try self.decodeParams(paramsJSON)
|
|
} else {
|
|
ListDirectoryParams(path: nil)
|
|
}
|
|
let home = FileManager.default.homeDirectoryForCurrentUser.path
|
|
let requested = params.path?.trimmingCharacters(in: .whitespacesAndNewlines)
|
|
let rawPath = requested.flatMap { $0.isEmpty ? nil : $0 } ?? home
|
|
guard NSString(string: rawPath).isAbsolutePath else {
|
|
return self.errorResponse(
|
|
request,
|
|
code: .invalidRequest,
|
|
message: "INVALID_REQUEST: fs.listDir path must be absolute")
|
|
}
|
|
|
|
let directory = URL(fileURLWithPath: rawPath, isDirectory: true).standardizedFileURL
|
|
let children = try FileManager.default.contentsOfDirectory(
|
|
at: directory,
|
|
includingPropertiesForKeys: [.isDirectoryKey],
|
|
options: [])
|
|
var entries: [DirectoryEntry] = []
|
|
for child in children {
|
|
var isDirectory: ObjCBool = false
|
|
guard FileManager.default.fileExists(atPath: child.path, isDirectory: &isDirectory),
|
|
isDirectory.boolValue
|
|
else { continue }
|
|
let name = child.lastPathComponent
|
|
entries.append(DirectoryEntry(
|
|
name: name,
|
|
path: directory.appendingPathComponent(name, isDirectory: true).path,
|
|
hidden: name.hasPrefix(".") ? true : nil))
|
|
}
|
|
entries.sort { lhs, rhs in
|
|
if (lhs.hidden != nil) != (rhs.hidden != nil) {
|
|
return lhs.hidden == nil
|
|
}
|
|
return lhs.name.utf8.lexicographicallyPrecedes(rhs.name.utf8)
|
|
}
|
|
|
|
let parentPath = directory.deletingLastPathComponent().path
|
|
let payload = ListDirectoryPayload(
|
|
path: directory.path,
|
|
parent: parentPath == directory.path ? nil : parentPath,
|
|
home: home,
|
|
entries: entries)
|
|
return try BridgeInvokeResponse(
|
|
id: request.id,
|
|
ok: true,
|
|
payloadJSON: self.encodePayload(payload))
|
|
}
|
|
|
|
private static func decodeParams(_ paramsJSON: String) throws -> ListDirectoryParams {
|
|
guard let data = paramsJSON.data(using: .utf8) else {
|
|
throw NSError(domain: "Gateway", code: 20, userInfo: [
|
|
NSLocalizedDescriptionKey: "INVALID_REQUEST: paramsJSON required",
|
|
])
|
|
}
|
|
return try JSONDecoder().decode(ListDirectoryParams.self, from: data)
|
|
}
|
|
|
|
private static func encodePayload(_ payload: ListDirectoryPayload) throws -> String {
|
|
let data = try JSONEncoder().encode(payload)
|
|
guard let json = String(bytes: data, encoding: .utf8) else {
|
|
throw NSError(domain: "Node", code: 21, userInfo: [
|
|
NSLocalizedDescriptionKey: "Failed to encode payload as UTF-8",
|
|
])
|
|
}
|
|
return json
|
|
}
|
|
|
|
private static func errorResponse(
|
|
_ request: BridgeInvokeRequest,
|
|
code: OpenClawNodeErrorCode,
|
|
message: String) -> BridgeInvokeResponse
|
|
{
|
|
BridgeInvokeResponse(
|
|
id: request.id,
|
|
ok: false,
|
|
error: OpenClawNodeError(code: code, message: message))
|
|
}
|
|
}
|