Files
Termind/TFI/Application/FeatureModels/MobileSkillEditorModel.swift
T
Kaede Akino e9c269ab5e Replace starter skills with built-in skill helpers
Keep previously installed starter skills as ordinary user-owned records. Provide hidden read-only Skill Creator and Skill Installer instructions, use AgentKit 0.13.0 for reviewed complete GitHub package installation, and remove skill seeding and Reset.

Move Hermes Memory below MCP, use Enabled for its switch, and localize its Chinese title as persistent memory. Preserve existing user edits and synchronize user skill packages through the existing atomic store.

Validation: AgentKit 213 tests and iOS 452 tests passed. macOS app 1183 tests passed; shared frameworks passed 231/232 with the existing SpeechWaveformViewTests PNG byte-equality failure. Related skill, sync, localization and UI checks passed. Strict Swift formatting, Chinese localization checks, and git diff --check passed.
2026-09-17 08:34:10 +08:00

55 lines
2.0 KiB
Swift

import AgentKit
import Foundation
import Observation
import TermindApplication
@MainActor @Observable
final class MobileSkillEditorModel {
let original: AgentSkill
var draft: AgentSkill
private let library: SkillLibraryModel
private let wasPersisted: Bool
init(library: SkillLibraryModel, skill: AgentSkill) {
self.library = library
original = skill
draft = skill
wasPersisted = library.skill(skill.id) != nil
}
var isDirty: Bool { draft != original }
var canSave: Bool {
draft.summary.count <= AgentSkill.maximumSummaryCharacters
&& draft.body.utf8.count <= AgentSkill.maximumBodyBytes
}
func save() throws {
guard canSave else { return }
var value = draft
if wasPersisted {
guard let current = library.skill(original.id) else {
throw MobileEditorError.message(String(localized: "Skill Deleted"))
}
var fields = SettingsFields(original, draft, current)
if draft.name != original.name {
guard library.conflictingSkillIDs.contains(original.id), AgentSkillNaming.isValid(draft.name),
!library.hasNameConflict(draft.name, excluding: draft.id)
else {
throw MobileEditorError.message(String(localized: "Another skill already uses this name."))
}
try fields.merge(\.name)
}
try fields.merge(\.isEnabled)
try fields.merge(\.title)
try fields.merge(\.summary)
try fields.merge(\.body)
try fields.merge(\.package)
value = fields.result
}
if value.name.isEmpty, AgentSkillNaming.isValid(value.effectiveName),
!library.hasNameConflict(value.effectiveName, excluding: value.id)
{
value.name = value.effectiveName
}
library.upsert(value)
if let error = library.storageError { throw MobileEditorError.message(error) }
}
}