import { dateFromInput, runJxa } from "../apple-events.js"; const LISTS_SCRIPT = String.raw` function run() { const app = Application("/System/Applications/Reminders.app"); function stringValue(value) { try { return value === null || value === undefined ? null : String(value); } catch (_) { return null; } } function accountName(list) { try { const container = list.container(); return stringValue(container.name ? container.name() : container); } catch (_) { return null; } } return JSON.stringify(app.lists().map(function (list) { return { id: String(list.id()), name: String(list.name()), account: accountName(list), shared: null, assignmentMetadata: { available: null, note: "Apple Reminders automation does not expose shared-list participant metadata directly." } }; })); }`; const REMINDERS_LIST_SCRIPT = String.raw` function run(argv) { const input = JSON.parse(argv[0]); const app = Application("/System/Applications/Reminders.app"); const lists = app.lists(); const found = []; function stringValue(value) { try { return value === null || value === undefined ? null : String(value); } catch (_) { return null; } } function compact(value) { if (!value) return null; const text = String(value).trim(); return text ? text : null; } function propertyValue(object, names) { for (let i = 0; i < names.length; i++) { try { const getter = object[names[i]]; if (typeof getter !== "function") continue; const value = getter.call(object); const text = compact(stringValue(value)); if (text && !text.startsWith("[object ")) return text; if (value && typeof value.name === "function") { const name = compact(stringValue(value.name())); if (name) return name; } } catch (_) {} } return null; } function assignmentHint(title, notes) { const titleMatch = title.match(/\(([^()\n]{2,80})\)\s*$/); if (titleMatch) return { assignee: titleMatch[1].trim(), source: "title" }; const explicit = notes.match(/\b(?:assigned to|assignee)\s*:\s*([^.;,\n]{2,80})/i); if (explicit) return { assignee: explicit[1].trim(), source: "notes" }; const captured = notes.match(/\bCaptured\s+\d{4}-\d{2}-\d{2},\s*([^.;,\n]{2,80})\s*[.;]/i); if (captured) return { assignee: captured[1].trim(), source: "notes" }; return { assignee: null, source: null }; } function assignmentFor(reminder, title, notes) { const nativeAssignee = propertyValue(reminder, [ "assignedTo", "assignee", "assignment", "responsiblePerson", "principal" ]); if (nativeAssignee) { return { assignee: nativeAssignee, source: "remindersAutomation", available: true }; } const hint = assignmentHint(title, notes); return { assignee: hint.assignee, source: hint.source, available: hint.assignee !== null }; } for (let l = 0; l < lists.length && found.length < input.limit; l++) { const list = lists[l]; const name = String(list.name()); if (input.list && name !== input.list) continue; const reminders = list.reminders(); for (let r = 0; r < reminders.length && found.length < input.limit; r++) { const reminder = reminders[r]; const completed = Boolean(reminder.completed()); if (input.completed !== null && completed !== input.completed) continue; let due = null; try { const value = reminder.dueDate(); due = value ? value.toISOString() : null; } catch (_) {} const title = String(reminder.name()); const notes = String(reminder.body() || ""); found.push({ id: String(reminder.id()), list: name, title: title, completed: completed, due: due, notes: notes, assignment: assignmentFor(reminder, title, notes) }); } } return JSON.stringify(found); }`; const REMINDER_CREATE_SCRIPT = String.raw` function run(argv) { const input = JSON.parse(argv[0]); const app = Application("/System/Applications/Reminders.app"); const lists = app.lists(); let destination = null; for (let l = 0; l < lists.length; l++) { if (!input.list || String(lists[l].name()) === input.list) { destination = lists[l]; break; } } if (!destination) throw new Error("Reminders list not found"); const properties = {name: input.title, body: input.notes || ""}; if (input.due) properties.dueDate = new Date(input.due); const reminder = app.Reminder(properties); destination.reminders.push(reminder); return JSON.stringify({ id: String(reminder.id()), list: String(destination.name()), title: String(reminder.name()) }); }`; export function listReminderLists() { return runJxa(LISTS_SCRIPT); } export function listReminders(input) { return runJxa(REMINDERS_LIST_SCRIPT, input); } export function createReminder(input) { if (input.due) { dateFromInput(input.due, "due"); } return runJxa(REMINDER_CREATE_SCRIPT, input); }