SPB Git

spb/poche Public

Agent personnel 100 % on-device — SwiftUI + Apple Foundation Models + EventKit + SwiftData. Aucune API, aucun serveur.

Swift 100%
2.7 KB · 76 lines swift
Raw Blame History
1//2//  UpdateTaskTool.swift3//  Poche4//5//  Author:  Simon-Pierre Boucher6//  Contact: contact@spboucher.ai7//89import Foundation10import FoundationModels1112struct UpdateTaskTool: Tool {13    let name = "updateTask"14    let description = "Propose de modifier une tâche existante de Poche (titre, échéance, marquer faite). L'utilisateur devra confirmer."1516    @Generable17    struct Arguments {18        @Guide(description: "Mots du titre de la tâche à retrouver")19        let taskQuery: String20        @Guide(description: "Nouveau titre, seulement si l'utilisateur veut le changer")21        let newTitle: String?22        @Guide(description: "Nouvelle échéance ISO 8601, seulement si l'utilisateur veut la changer")23        let newDueDate: String?24        @Guide(description: "Vrai seulement si l'utilisateur veut marquer la tâche comme faite")25        let markDone: Bool?26    }2728    private let confirm: ConfirmCenter29    private let store: PocheStore3031    init(confirm: ConfirmCenter, store: PocheStore) {32        self.confirm = confirm33        self.store = store34    }3536    func call(arguments: Arguments) async throws -> String {37        guard let query = ToolInput.title(arguments.taskQuery) else {38            return "Erreur : précise quelle tâche modifier."39        }4041        let matches = await store.findTasks(matching: query)42        guard let task = matches.first else {43            return "Aucune tâche ne correspond à « \(query) ». Demande à l'utilisateur de préciser."44        }45        if matches.count > 1 {46            let titles = matches.prefix(3).map { \($0.title) »" }.joined(separator: ", ")47            return "Plusieurs tâches correspondent : \(titles). Demande à l'utilisateur laquelle modifier."48        }4950        var newDue: Date?51        if let rawDue = arguments.newDueDate, !rawDue.trimmingCharacters(in: .whitespaces).isEmpty {52            do {53                newDue = try DateResolver.resolve(iso: rawDue)54            } catch {55                return "Erreur sur l'échéance : \(error.localizedDescription)"56            }57        }5859        let newTitle = arguments.newTitle.flatMap(ToolInput.title)60        guard newTitle != nil || newDue != nil || arguments.markDone != nil else {61            return "Erreur : aucune modification demandée. Demande à l'utilisateur ce qu'il veut changer."62        }6364        let draft = TaskUpdateDraft(65            taskID: task.uuid,66            currentTitle: task.title,67            newTitle: newTitle,68            newDue: newDue,69            markDone: arguments.markDone70        )71        await confirm.propose(PendingAction(payload: .taskUpdate(draft)))7273        return "Proposition affichée : modification de la tâche « \(task.title) ». Rien n'est encore modifié — l'utilisateur doit confirmer."74    }75}76