SPB Git

spb/zyquo-agent Public MIT

The autonomous agent that actually operates your Mac — plans, runs real commands, verifies its own work.

Swift 94.7% Shell 4.1% Python 0.7% Makefile 0.5%
14.8 KB · 311 lines swift
Raw Blame History
1//2//  TaskTemplate.swift3//  Zyquo Agent4//5//  Author: Simon-Pierre Boucher6//  Mail: contact@spboucher.ai7//8//  Ready-made agent task templates (Phase 6): a title, category, prompt with9//  {{variable}} placeholders, and a suggested safety mode. The built-in10//  library ships ≥25 genuinely useful tasks; user templates layer on top11//  (TemplateStore). Using a template with variables opens the fill-in sheet.12//1314import Foundation1516/// Template grouping shown in the browser and the command palette.17enum TemplateCategory: String, Codable, CaseIterable, Identifiable {18    case filesAndFolders19    case development20    case automation21    case data22    case systemInfo23    case writing2425    var id: String { rawValue }2627    var displayName: String {28        switch self {29        case .filesAndFolders: return "Files & Folders"30        case .development: return "Development"31        case .automation: return "Automation (AppleScript)"32        case .data: return "Data"33        case .systemInfo: return "System Info"34        case .writing: return "Writing"35        }36    }3738    var symbolName: String {39        switch self {40        case .filesAndFolders: return "folder"41        case .development: return "chevron.left.forwardslash.chevron.right"42        case .automation: return "applescript"43        case .data: return "tablecells"44        case .systemInfo: return "cpu"45        case .writing: return "text.quote"46        }47    }48}4950/// One reusable agent task. `prompt` may contain `{{variable}}` placeholders51/// filled in by the user before the task is created.52struct TaskTemplate: Codable, Identifiable, Hashable {53    var id: UUID = UUID()54    var title: String55    var category: TemplateCategory56    /// SF Symbol shown next to the title (defaults to the category glyph).57    var symbolName: String?58    var prompt: String59    var suggestedSafetyMode: SafetyMode = .guarded60    /// Built-ins are read-only; user templates are editable/deletable.61    var isBuiltIn: Bool = false6263    var displaySymbol: String { symbolName ?? category.symbolName }6465    /// Distinct `{{variable}}` names in declaration order.66    var variables: [String] {67        Self.variables(in: prompt)68    }6970    /// Extracts distinct `{{name}}` placeholders from a prompt.71    static func variables(in prompt: String) -> [String] {72        var names: [String] = []73        var rest = Substring(prompt)74        while let open = rest.range(of: "{{"), let close = rest[open.upperBound...].range(of: "}}") {75            let name = rest[open.upperBound..<close.lowerBound]76                .trimmingCharacters(in: .whitespaces)77            if !name.isEmpty, !names.contains(name) {78                names.append(name)79            }80            rest = rest[close.upperBound...]81        }82        return names83    }8485    /// The prompt with every `{{variable}}` replaced by its filled value.86    func renderedPrompt(values: [String: String]) -> String {87        var rendered = prompt88        for (name, value) in values {89            rendered = rendered.replacingOccurrences(of: "{{\(name)}}", with: value)90            rendered = rendered.replacingOccurrences(of: "{{ \(name) }}", with: value)91        }92        return rendered93    }94}9596// MARK: - Built-in library (≥25 templates)9798enum TaskTemplateLibrary {99    static let builtIn: [TaskTemplate] = [100        // ---- Files & Folders (6) ---------------------------------------101        TaskTemplate(102            title: "Organize my Downloads folder",103            category: .filesAndFolders,104            symbolName: "folder.badge.gearshape",105            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.",106            isBuiltIn: true107        ),108        TaskTemplate(109            title: "Batch-rename files by pattern",110            category: .filesAndFolders,111            symbolName: "textformat.abc.dottedunderline",112            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.",113            isBuiltIn: true114        ),115        TaskTemplate(116            title: "Find my largest files",117            category: .filesAndFolders,118            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.",119            isBuiltIn: true120        ),121        TaskTemplate(122            title: "Deduplicate a folder",123            category: .filesAndFolders,124            symbolName: "doc.on.doc",125            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.",126            isBuiltIn: true127        ),128        TaskTemplate(129            title: "Archive old files",130            category: .filesAndFolders,131            symbolName: "archivebox",132            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.",133            isBuiltIn: true134        ),135        TaskTemplate(136            title: "Build a folder structure from a spec",137            category: .filesAndFolders,138            symbolName: "folder.badge.plus",139            prompt: "Create this folder structure in the workspace and put a short README.md in each leaf folder describing its purpose:\n\n{{structure}}",140            isBuiltIn: true141        ),142143        // ---- Development (6) --------------------------------------------144        TaskTemplate(145            title: "Set up a Python project and run the tests",146            category: .development,147            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.",148            isBuiltIn: true149        ),150        TaskTemplate(151            title: "Scaffold a Node.js CLI tool",152            category: .development,153            symbolName: "terminal",154            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.",155            isBuiltIn: true156        ),157        TaskTemplate(158            title: "Initialize a git repository with hygiene files",159            category: .development,160            symbolName: "arrow.triangle.branch",161            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.",162            isBuiltIn: true163        ),164        TaskTemplate(165            title: "Explain and fix a failing script",166            category: .development,167            symbolName: "ladybug",168            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}}",169            isBuiltIn: true170        ),171        TaskTemplate(172            title: "Write a script to automate a chore",173            category: .development,174            symbolName: "wand.and.stars",175            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.",176            isBuiltIn: true177        ),178        TaskTemplate(179            title: "Profile a directory's code statistics",180            category: .development,181            symbolName: "chart.bar",182            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.",183            isBuiltIn: true184        ),185186        // ---- Automation (AppleScript) (5) --------------------------------187        TaskTemplate(188            title: "Export my Notes to Markdown",189            category: .automation,190            symbolName: "note.text",191            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.",192            isBuiltIn: true193        ),194        TaskTemplate(195            title: "Create a reminder",196            category: .automation,197            symbolName: "checklist",198            prompt: "Use AppleScript to create a reminder in the Reminders app titled \"{{title}}\" due {{due}}. Confirm it was created by reading it back.",199            isBuiltIn: true200        ),201        TaskTemplate(202            title: "List today's calendar events",203            category: .automation,204            symbolName: "calendar",205            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.",206            isBuiltIn: true207        ),208        TaskTemplate(209            title: "Tidy my Desktop into a dated folder",210            category: .automation,211            symbolName: "menubar.dock.rectangle",212            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.",213            isBuiltIn: true214        ),215        TaskTemplate(216            title: "Draft an email in Mail",217            category: .automation,218            symbolName: "envelope",219            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.",220            isBuiltIn: true221        ),222223        // ---- Data (4) -----------------------------------------------------224        TaskTemplate(225            title: "Parse a CSV and summarize it",226            category: .data,227            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.",228            isBuiltIn: true229        ),230        TaskTemplate(231            title: "Convert JSON to CSV",232            category: .data,233            symbolName: "arrow.left.arrow.right",234            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.",235            isBuiltIn: true236        ),237        TaskTemplate(238            title: "Aggregate a log file",239            category: .data,240            symbolName: "doc.plaintext",241            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.",242            isBuiltIn: true243        ),244        TaskTemplate(245            title: "Diff two files and explain the changes",246            category: .data,247            symbolName: "plus.forwardslash.minus",248            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.",249            isBuiltIn: true250        ),251252        // ---- System Info (4) -----------------------------------------------253        TaskTemplate(254            title: "Storage health report",255            category: .systemInfo,256            symbolName: "internaldrive",257            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.",258            isBuiltIn: true259        ),260        TaskTemplate(261            title: "Snapshot my Mac's configuration",262            category: .systemInfo,263            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.",264            isBuiltIn: true265        ),266        TaskTemplate(267            title: "What is using my resources right now?",268            category: .systemInfo,269            symbolName: "gauge.with.needle",270            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.",271            isBuiltIn: true272        ),273        TaskTemplate(274            title: "Audit my login items and launch agents",275            category: .systemInfo,276            symbolName: "power",277            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.",278            isBuiltIn: true279        ),280281        // ---- Writing (4) ----------------------------------------------------282        TaskTemplate(283            title: "Summarize a document",284            category: .writing,285            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.",286            isBuiltIn: true287        ),288        TaskTemplate(289            title: "Draft a README for a project",290            category: .writing,291            symbolName: "book",292            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.",293            isBuiltIn: true294        ),295        TaskTemplate(296            title: "Turn rough notes into a document",297            category: .writing,298            symbolName: "square.and.pencil",299            prompt: "Turn these rough notes into a well-structured Markdown document with headings, saved as {{filename}}.md in the workspace:\n\n{{notes}}",300            isBuiltIn: true301        ),302        TaskTemplate(303            title: "Weekly review from my file activity",304            category: .writing,305            symbolName: "calendar.badge.clock",306            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.",307            isBuiltIn: true308        ),309    ]310}311