From ef0fbeac97d658ced45d3acf0a3e64c5c3246865 Mon Sep 17 00:00:00 2001 From: link2026 Date: Mon, 25 May 2026 16:00:47 +0800 Subject: [PATCH] =?UTF-8?q?fix(ai,persistence):=20ModelStore=20+=20FileVau?= =?UTF-8?q?lt=20=E6=A0=87=20@unchecked=20Sendable?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Xcode 26 默认开启 Swift 6 严格并发检查。AIRuntime(actor) 调用 ModelStore.shared.isReady(...) 跨 actor 边界,因 ModelStore 非 Sendable 而编译报错"Expression is 'async' but is not marked with 'await'; this is an error in the Swift 6 language mode"。 两个类的内部状态只读(rootURL: let),方法只做线程安全的 filesystem I/O,符合 Sendable 语义,标 @unchecked Sendable 即可,不必加锁或重构。 修复目标错误: - AIRuntime.swift:48 - guard ModelStore.shared.isReady(.llm) ... - 后续 CaptureService 调 FileVault.shared.writeJPEG 同样路径 不影响: - HomeView/B5ResultView 里 Text "+" 的 macOS 26.0 deprecation 是 warning,不阻塞 build,留待 UI polish 周清理 Co-Authored-By: Claude Opus 4.7 (1M context) --- 体己/AI/ModelStore.swift | 4 +++- 体己/Persistence/FileVault.swift | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/体己/AI/ModelStore.swift b/体己/AI/ModelStore.swift index e9167a5..06ce918 100644 --- a/体己/AI/ModelStore.swift +++ b/体己/AI/ModelStore.swift @@ -19,7 +19,9 @@ enum ModelKind: String, CaseIterable { var sentinelFilename: String { "config.json" } } -final class ModelStore { +/// `@unchecked Sendable`:rootURL 是 let,方法只读 filesystem(线程安全), +/// 可被任意 actor / Task 跨边界访问。 +final class ModelStore: @unchecked Sendable { static let shared: ModelStore = { do { let appSupport = try FileManager.default.url( diff --git a/体己/Persistence/FileVault.swift b/体己/Persistence/FileVault.swift index f11675d..0d42634 100644 --- a/体己/Persistence/FileVault.swift +++ b/体己/Persistence/FileVault.swift @@ -8,7 +8,9 @@ enum FileVaultError: Error { case decodeFailed } -final class FileVault { +/// `@unchecked Sendable`:rootURL 是 let,方法只 I/O 到沙盒目录(线程安全), +/// 可被任意 actor / Task 跨边界访问。 +final class FileVault: @unchecked Sendable { static let shared: FileVault = { do { let appSupport = try FileManager.default.url(