// // UpdateTaskTool.swift // Poche // // Author: Simon-Pierre Boucher // Contact: contact@spboucher.ai // import Foundation import FoundationModels struct UpdateTaskTool: Tool { let name = "updateTask" let description = "Propose de modifier une tâche existante de Poche (titre, échéance, marquer faite). L'utilisateur devra confirmer." @Generable struct Arguments { @Guide(description: "Mots du titre de la tâche à retrouver") let taskQuery: String @Guide(description: "Nouveau titre, seulement si l'utilisateur veut le changer") let newTitle: String? @Guide(description: "Nouvelle échéance ISO 8601, seulement si l'utilisateur veut la changer") let newDueDate: String? @Guide(description: "Vrai seulement si l'utilisateur veut marquer la tâche comme faite") let markDone: Bool? } private let confirm: ConfirmCenter private let store: PocheStore init(confirm: ConfirmCenter, store: PocheStore) { self.confirm = confirm self.store = store } func call(arguments: Arguments) async throws -> String { guard let query = ToolInput.title(arguments.taskQuery) else { return "Erreur : précise quelle tâche modifier." } let matches = await store.findTasks(matching: query) guard let task = matches.first else { return "Aucune tâche ne correspond à « \(query) ». Demande à l'utilisateur de préciser." } if matches.count > 1 { let titles = matches.prefix(3).map { "« \($0.title) »" }.joined(separator: ", ") return "Plusieurs tâches correspondent : \(titles). Demande à l'utilisateur laquelle modifier." } var newDue: Date? if let rawDue = arguments.newDueDate, !rawDue.trimmingCharacters(in: .whitespaces).isEmpty { do { newDue = try DateResolver.resolve(iso: rawDue) } catch { return "Erreur sur l'échéance : \(error.localizedDescription)" } } let newTitle = arguments.newTitle.flatMap(ToolInput.title) guard newTitle != nil || newDue != nil || arguments.markDone != nil else { return "Erreur : aucune modification demandée. Demande à l'utilisateur ce qu'il veut changer." } let draft = TaskUpdateDraft( taskID: task.uuid, currentTitle: task.title, newTitle: newTitle, newDue: newDue, markDone: arguments.markDone ) await confirm.propose(PendingAction(payload: .taskUpdate(draft))) return "Proposition affichée : modification de la tâche « \(task.title) ». Rien n'est encore modifié — l'utilisateur doit confirmer." } }