Plug-In: AFM • Solar Power Example

REQUIRES: macOS 26, iOS 26, iPados 26, visionOS 26 • OmniFocus 4.8

Based upon the example in the Omni Automation API, this plug-in demonstrates interacting with the on-device Apple Foundation Model (AFM) through an Omni Automation plug-in.

It will create a new OmniFocus project containing a set of tasks representing the steps necessary to install solar power in a home.

The plug-in provides the on-device Apple Language Models (AFM) with an example JSON schema showing how to organize the response data. Once the AFM has returned the response, it is parsed to create a new multi-level project. In addition, tasks are assigned priority level though the use of mutually-exclusive tags.

Documentation

Complete documentation regarding the integration of Omni Automation with the Apple Foundation Models frameworks is available in two sections:

AFM • Solar Power Example
  

/*{ "type": "action", "targets": ["omnifocus"], "author": "Otto Automator", "identifier": "com.omni-automation.of.solar-project-example", "version": "1.1", "description": "An example plug-in that uses the on-device Apple Language Model to generate an OmniFocus project detailing the steps required to add solar power to a home.", "label": "AFM • Solar Project Example", "shortLabel": "AFM • Solar Project", "paletteLabel": "AFM • Solar Project", "image": "apple.intelligence" }*/ (() => { // SCHEMA FOR THE AFM var schemaJSON = { arrayOf: { name: "step-schema", properties: [ { name: "title", isOptional: false }, { name: "description", isOptional: false }, { name: "priority", schema: { name: "priority-schema", anyOf: [ { constant: "high" }, { constant: "low" } ] } }, { name: "substeps", description: "A breakdown of steps.", isOptional: true, schema: { arrayOf: { referenceTo: "step-schema" }, minimumElements: 1 } } ] } } // FUNCTION FOR CREATING PROJECT USING AFM RESPONSE function insertJsonUnderParent(steps, parent) { steps.forEach(step => { title = step.title description = step.description priority = step.priority console.log("Title:", title) console.log("Description:", description) console.log("Priority:", priority) task = new Task(title, parent) task.note = description priorityTag = (priority === "low") ? lowTag:highTag task.addTag(priorityTag) console.log("Priority Tag:", priorityTag) console.log("---------------------") if (step['substeps']) { insertJsonUnderParent(step['substeps'], task); } }); } function expandNotes(object, window){ contentTree = window.content; node = contentTree.nodeForObject(object); node.expandNote(true); } const action = new PlugIn.Action(async function(selection, sender){ try { // CREATE PROJECT project = new Project("Thinking…") window = document.windows[0] window.perspective = Perspective.BuiltIn.Projects window.focus = [project] // QUERY THE ON-DEVICE APPLE LANGUAGE MODEL schema = LanguageModel.Schema.fromJSON(schemaJSON) prompt = "Provide a list of steps required to add solar power to a home." session = new LanguageModel.Session() options = new LanguageModel.GenerationOptions() options.maximumResponseTokens = 4096 response = await session.respondWithSchema(prompt, schema) responseJSON = JSON.parse(response) console.log(JSON.stringify(response, null, 2)) // CREATE MUTUALLY-EXCLUSIVE PRIORITY TAG GROUP AS NEEDED tagGroup = flattenedTags.byName("Priority") || new Tag("Priority") lowTag = tagGroup.tagNamed("Low") || new Tag("Low", tagGroup.beginning) highTag = tagGroup.tagNamed("High") || new Tag("High", tagGroup.beginning) tagGroup.childrenAreMutuallyExclusive = true // RENAME PROJECT project.name = "Home Solar Project" // CREATE PROJECT HEIRARCHY insertJsonUnderParent(response, project) // DISPLAY PROJECT project.url.open() expandNotes(project, selection.window) } catch(err){ if(project){ document.windows[0].focus = [] deleteObject(project) } if(!err.causedByUserCancelling){ console.error(err.name, err.message) new Alert(err.name, err.message).show() } } }); action.validate = function(selection, sender){ // VERIFY DEVICE IS RUNNING OS26 OR NEWER compatibility = Device.current.operatingSystemVersion.atLeast(new Version("26")) return compatibility }; return action; })();