// // TaskTemplate.swift // Zyquo Agent // // Author: Simon-Pierre Boucher // Mail: contact@spboucher.ai // // Ready-made agent task templates (Phase 6): a title, category, prompt with // {{variable}} placeholders, and a suggested safety mode. The built-in // library ships ≥25 genuinely useful tasks; user templates layer on top // (TemplateStore). Using a template with variables opens the fill-in sheet. // import Foundation /// Template grouping shown in the browser and the command palette. enum TemplateCategory: String, Codable, CaseIterable, Identifiable { case filesAndFolders case development case automation case data case systemInfo case writing var id: String { rawValue } var displayName: String { switch self { case .filesAndFolders: return "Files & Folders" case .development: return "Development" case .automation: return "Automation (AppleScript)" case .data: return "Data" case .systemInfo: return "System Info" case .writing: return "Writing" } } var symbolName: String { switch self { case .filesAndFolders: return "folder" case .development: return "chevron.left.forwardslash.chevron.right" case .automation: return "applescript" case .data: return "tablecells" case .systemInfo: return "cpu" case .writing: return "text.quote" } } } /// One reusable agent task. `prompt` may contain `{{variable}}` placeholders /// filled in by the user before the task is created. struct TaskTemplate: Codable, Identifiable, Hashable { var id: UUID = UUID() var title: String var category: TemplateCategory /// SF Symbol shown next to the title (defaults to the category glyph). var symbolName: String? var prompt: String var suggestedSafetyMode: SafetyMode = .guarded /// Built-ins are read-only; user templates are editable/deletable. var isBuiltIn: Bool = false var displaySymbol: String { symbolName ?? category.symbolName } /// Distinct `{{variable}}` names in declaration order. var variables: [String] { Self.variables(in: prompt) } /// Extracts distinct `{{name}}` placeholders from a prompt. static func variables(in prompt: String) -> [String] { var names: [String] = [] var rest = Substring(prompt) while let open = rest.range(of: "{{"), let close = rest[open.upperBound...].range(of: "}}") { let name = rest[open.upperBound.. String { var rendered = prompt for (name, value) in values { rendered = rendered.replacingOccurrences(of: "{{\(name)}}", with: value) rendered = rendered.replacingOccurrences(of: "{{ \(name) }}", with: value) } return rendered } } // MARK: - Built-in library (≥25 templates) enum TaskTemplateLibrary { static let builtIn: [TaskTemplate] = [ // ---- Files & Folders (6) --------------------------------------- TaskTemplate( title: "Organize my Downloads folder", category: .filesAndFolders, symbolName: "folder.badge.gearshape", prompt: "Look at my Downloads folder (~/Downloads), group the files by type into subfolders (Images, Documents, Archives, Installers, Audio, Video, Other), move them accordingly, and show me a summary table of what you moved. Do not delete anything.", isBuiltIn: true ), TaskTemplate( title: "Batch-rename files by pattern", category: .filesAndFolders, symbolName: "textformat.abc.dottedunderline", prompt: "Rename all files in {{folder}} to a consistent kebab-case pattern with a zero-padded numeric suffix ({{prefix}}-01, {{prefix}}-02, …), keeping extensions, and list the before → after mapping.", isBuiltIn: true ), TaskTemplate( title: "Find my largest files", category: .filesAndFolders, prompt: "Find the 20 largest files under {{folder}} (skip hidden files and app bundles), and present them as a table with size, path, and last-modified date. Do not modify anything.", isBuiltIn: true ), TaskTemplate( title: "Deduplicate a folder", category: .filesAndFolders, symbolName: "doc.on.doc", prompt: "Scan {{folder}} for duplicate files (same content, compare by checksum). Report every duplicate group with paths and sizes, then move the redundant copies (keep the oldest of each group) into a 'Duplicates' subfolder — never delete outright.", isBuiltIn: true ), TaskTemplate( title: "Archive old files", category: .filesAndFolders, symbolName: "archivebox", prompt: "In {{folder}}, find files not modified in the last {{months}} months, move them into an 'Archive-{{months}}mo' subfolder preserving their relative structure, then zip that subfolder and report the space it occupies.", isBuiltIn: true ), TaskTemplate( title: "Build a folder structure from a spec", category: .filesAndFolders, symbolName: "folder.badge.plus", prompt: "Create this folder structure in the workspace and put a short README.md in each leaf folder describing its purpose:\n\n{{structure}}", isBuiltIn: true ), // ---- Development (6) -------------------------------------------- TaskTemplate( title: "Set up a Python project and run the tests", category: .development, prompt: "Create a small Python project in the workspace with a src/ layout, one example module with two functions, pytest tests for them, then run the tests and report the results.", isBuiltIn: true ), TaskTemplate( title: "Scaffold a Node.js CLI tool", category: .development, symbolName: "terminal", prompt: "Scaffold a Node.js command-line tool named {{name}} in the workspace: package.json with a bin entry, a src/index.js implementing {{description}}, and a README. Run it once with --help to verify it works.", isBuiltIn: true ), TaskTemplate( title: "Initialize a git repository with hygiene files", category: .development, symbolName: "arrow.triangle.branch", prompt: "Initialize a git repository in the workspace with a sensible .gitignore for {{language}}, a README.md skeleton, an MIT LICENSE with the current year, and make the initial commit. Show the resulting git log.", isBuiltIn: true ), TaskTemplate( title: "Explain and fix a failing script", category: .development, symbolName: "ladybug", prompt: "Here is a script that fails. Save it in the workspace, run it, diagnose the failure from the actual output, fix it, re-run to verify, and explain the root cause:\n\n{{script}}", isBuiltIn: true ), TaskTemplate( title: "Write a script to automate a chore", category: .development, symbolName: "wand.and.stars", prompt: "Write a well-commented shell script in the workspace that {{chore}}. Test it against sample data you create in the workspace first, show the output, and explain how to use it.", isBuiltIn: true ), TaskTemplate( title: "Profile a directory's code statistics", category: .development, symbolName: "chart.bar", prompt: "Analyze the source code under {{folder}}: count files and lines per language/extension, find the 10 longest files, and summarize the project layout in a short report saved as report.md in the workspace.", isBuiltIn: true ), // ---- Automation (AppleScript) (5) -------------------------------- TaskTemplate( title: "Export my Notes to Markdown", category: .automation, symbolName: "note.text", prompt: "Use AppleScript to read my Apple Notes and export each note in the default folder as a Markdown file in the workspace, named after its title.", isBuiltIn: true ), TaskTemplate( title: "Create a reminder", category: .automation, symbolName: "checklist", prompt: "Use AppleScript to create a reminder in the Reminders app titled \"{{title}}\" due {{due}}. Confirm it was created by reading it back.", isBuiltIn: true ), TaskTemplate( title: "List today's calendar events", category: .automation, symbolName: "calendar", prompt: "Use AppleScript to read today's events from the Calendar app and present them as a Markdown agenda (time, title, calendar name). Save it as agenda.md in the workspace.", isBuiltIn: true ), TaskTemplate( title: "Tidy my Desktop into a dated folder", category: .automation, symbolName: "menubar.dock.rectangle", prompt: "Use Finder automation (AppleScript or shell) to move everything currently on my Desktop into a new folder named 'Desktop {{date}}' inside ~/Documents, then list what was moved.", isBuiltIn: true ), TaskTemplate( title: "Draft an email in Mail", category: .automation, symbolName: "envelope", prompt: "Use AppleScript to create a DRAFT (do not send) in Apple Mail addressed to {{recipient}} with subject \"{{subject}}\". Write the body from these points: {{points}}. Leave it open for my review.", isBuiltIn: true ), // ---- Data (4) ----------------------------------------------------- TaskTemplate( title: "Parse a CSV and summarize it", category: .data, prompt: "Read the CSV file at {{path}}, describe its columns and row count, compute basic statistics for the numeric columns (min/max/mean), surface anything anomalous, and save the summary as summary.md in the workspace.", isBuiltIn: true ), TaskTemplate( title: "Convert JSON to CSV", category: .data, symbolName: "arrow.left.arrow.right", prompt: "Read the JSON file at {{path}}, flatten its records sensibly, write them as a CSV in the workspace, and show me the header plus the first 5 rows.", isBuiltIn: true ), TaskTemplate( title: "Aggregate a log file", category: .data, symbolName: "doc.plaintext", prompt: "Analyze the log file at {{path}}: count entries per severity level, extract the 10 most frequent error messages with counts, note the time range covered, and write findings.md in the workspace.", isBuiltIn: true ), TaskTemplate( title: "Diff two files and explain the changes", category: .data, symbolName: "plus.forwardslash.minus", prompt: "Compare {{fileA}} and {{fileB}} with diff, then explain the meaningful differences in plain language, grouped by theme, and save the annotated diff in the workspace.", isBuiltIn: true ), // ---- System Info (4) ----------------------------------------------- TaskTemplate( title: "Storage health report", category: .systemInfo, symbolName: "internaldrive", prompt: "Produce a storage report for this Mac: total/used/free disk space, the 10 largest folders in my home directory (one level deep), and cache folders that look safely cleanable. Report only — do not delete anything.", isBuiltIn: true ), TaskTemplate( title: "Snapshot my Mac's configuration", category: .systemInfo, prompt: "Collect a configuration snapshot: macOS version, hardware model, CPU/RAM, uptime, network interfaces with IPs, and installed developer toolchains (git, node, python3, swift — with versions). Save it as system-snapshot.md in the workspace.", isBuiltIn: true ), TaskTemplate( title: "What is using my resources right now?", category: .systemInfo, symbolName: "gauge.with.needle", prompt: "Show the 10 processes using the most CPU and the 10 using the most memory right now, with a one-line interpretation of anything unusual. Read-only — do not kill anything.", isBuiltIn: true ), TaskTemplate( title: "Audit my login items and launch agents", category: .systemInfo, symbolName: "power", prompt: "List my user LaunchAgents (~/Library/LaunchAgents) and the system ones, with each plist's program and schedule, and flag anything that looks like abandoned software. Read-only — change nothing.", isBuiltIn: true ), // ---- Writing (4) ---------------------------------------------------- TaskTemplate( title: "Summarize a document", category: .writing, prompt: "Read the document at {{path}} and write a structured summary (TL;DR, key points, open questions) as summary.md in the workspace, keeping it under 400 words.", isBuiltIn: true ), TaskTemplate( title: "Draft a README for a project", category: .writing, symbolName: "book", prompt: "Inspect the project at {{folder}} (layout, manifest files, entry points) and draft a complete README.md in the workspace: what it is, how to install, how to run, and project structure.", isBuiltIn: true ), TaskTemplate( title: "Turn rough notes into a document", category: .writing, symbolName: "square.and.pencil", prompt: "Turn these rough notes into a well-structured Markdown document with headings, saved as {{filename}}.md in the workspace:\n\n{{notes}}", isBuiltIn: true ), TaskTemplate( title: "Weekly review from my file activity", category: .writing, symbolName: "calendar.badge.clock", prompt: "Find files under {{folder}} modified in the last 7 days, group them by project/folder, and draft a short weekly review (what moved, what looks stalled) as weekly-review.md in the workspace.", isBuiltIn: true ), ] }