app_intents_codegen 0.17.0 copy "app_intents_codegen: ^0.17.0" to clipboard
app_intents_codegen: ^0.17.0 copied to clipboard

Code generator for Flutter AppIntents. Produces Swift and Dart code from @IntentSpec and @EntitySpec annotations.

0.17.0 #

Behavior change for CLI users. generate_swift, generate_widget_swift and generate_kotlin now fail with exit code 1 when an annotation is invalid. Previously the analyzer's error was printed as a Warning: Could not analyze … line, the spec was left out of the output, and the command still exited 0 — so a project whose only specs were invalid got empty output with no failure. If a build that used to pass now stops here, the printed error names the file and the problem; that spec was never being generated.

Fix for FlutterBridge-mode intents — regenerate your Swift. The generated perform() invoked the Dart handler with the Swift struct name, while the generated Dart registers under @IntentSpec.identifier, so no background (FlutterBridge) intent could ever find its handler. URL scheme and foreground (cache) intents were already correct.

  • analyzeSourceFiles throws InvalidAnnotationsException instead of swallowing the analyzers' InvalidGenerationSourceError. All files are scanned before it throws, so every invalid spec is reported in one run. A file that fails to resolve is still skipped with a warning, as before.
  • Place export (#128). @EntitySpec(exportAs: EntityExportType.place) exports the entity as a GeoToolbox.PlaceDescriptor, built from fields marked @EntityExportField(EntityExportRole.latitude / .longitude / .address). IntentCurrencyAmount is deliberately not an export type: ValueRepresentation(exporting:) is only declared for IntentPerson and _SystemIntentValue conformers, and it is neither (measured against the iOS 27.0 SDK).
  • Import (#129). @EntitySpec(importable: true) generates ValueRepresentation(exporting:importing:). The import rides the value-query bridge under <identifier>#import; register the Dart side with AppIntents().registerValueImportHandler.
  • Progress, cancellation and requestValue (#130, #131, ADR 0010). Long-running intents open an execution scope, pass its id to Dart, and forward onCancel: instead of leaving a comment stub. @IntentParam(requestValue: true) lets the handler prompt for an optional primitive parameter mid-run. Generated handler signatures are unchanged — the handler reaches the scope through AppIntentExecution.current.
  • Dual identifiers (#132). @EntityStableId + @EntitySpec(syncable: true) makes the entity's id a SyncableEntityIdentifier<String, String>; the entity and its query dual-branch. Using such an entity as an @IntentParam(entityType:) value is a generation error.
  • Relevant-entity removal, re-indexing and union value queries (#133). The generated relevant-entities donator takes an operation argument; IndexedEntityQuery re-indexing is emitted behind --experimental=reindexing; @UnionValueSpec(valueQuery: true) generates an IntentValueQuery returning the union. generate_swift now also collects @UnionValueSpec classes that no intent parameter references.
  • The --app-intents-package help text warns against using it on a statically linked target, where it has been observed to stop App Intents being ingested in TestFlight / App Store builds only (ADR 0008).
  • Bumps app_intents_annotations dependency to ^0.17.0.

0.16.0 #

Heads-up for @EntitySpec(valueQuery: true) users. The IntentValueQuery type is now generated by default. If you had that flag set but were not passing --experimental=value-query, the query appears in your generated Swift for the first time — make sure a Dart <entity>ValueQuery handler exists. Everyone else is unaffected.

  • generate_widget_swift --public emits the generated declarations as public, for the shared-module setup ADR 0009 documents. Without it Swift's default internal hides the configuration intent, its parameters, the entities and the donator registration from an importing target — which a single-file swiftc -typecheck cannot reveal, since the file compiles fine on its own. scripts/verify_widget_module_swift.sh builds the output as a module and compiles a consumer that imports it.
  • Fixes two ways a relevant-intent donation lost its dates. The generated decoder used a default ISO8601DateFormatter, which rejects the fractional seconds DateTime.toIso8601String() always emits — every date / dateRange donation was silently dropped, and since the API replaces the app's whole set, a batch of only date donations cleared it instead. It now tries fractional and second precision. A DateTime widget parameter is also carried as an ISO-8601 string, because Flutter's standard codec cannot encode DateTime at all.
  • RelevantIntent donation (#55, ADR 0009). @WidgetConfigurationSpec(relevantIntents: true) makes generate_widget_swift emit a registerRelevantIntentDonator() plus a RelevantContext decoder. One donator per file, not per configuration, because RelevantIntentManager.updateRelevantIntents replaces the app's whole set. Entity parameters are resolved through the cache-backed widget query so the donated intent carries a full entity; scalar parameters absent from a donation are left unset rather than defaulted. Not experimentalRelevantIntentManager is iOS 17; only the kind: date refinements are iOS 26 and they sit behind if #available.
  • scripts/verify_experimental_swift.sh now type-checks the example's generated Widget Extension Swift too. Nothing compiled that output before except an Xcode build.
  • Placeholder parsing for dialog and snippet templates is shared between the analyzer, the Dart generator and the Swift generator, and tolerates padding ({ result.x }). Previously each had its own regex, so a dialog reading {result.…} without a snippet had its handler result discarded on the Dart side while the generated Swift still read keys from it.
  • AppIntentsPackage generation (ADR 0008). generate_swift and generate_widget_swift gain --app-intents-package <Name> and repeatable --include-package <Module.Type>, for sharing generated intents through a Swift package that several targets link. Note what the declaration is for: metadata from a statically linked module already merges without it (Xcode SPM links statically by default) — the declaration is what a dynamic link boundary needs, and is not a fix for a type missing from Metadata.appIntents.
  • Declarative snippet cards (@IntentSpec(snippet:), ADR 0007). Generates a self-contained SwiftUI <Intent>SnippetView from a fixed layout (optional SF Symbol, title, optional subtitle, LabeledContent rows) and returns it with .result(view:), so a Flutter app can put a card in Siri's result without supplying a SwiftUI view. Templates interpolate {paramName} (any execution mode) and {result.key} (the Dart handler's returned map — FlutterBridge mode only; using it on a URL scheme or foreground intent is a generation error instead of a card that renders empty). {result.key} works in resultDialogTemplate too. Row labels are collected into the String Catalog. Not experimentalShowsSnippetView is iOS 16; the generated file gains import SwiftUI because .result(view:) lives in the _AppIntents_SwiftUI overlay.
  • For an intent whose snippet or dialog reads {result.…}, the generated registration now returns the handler's value through intentResultPayload instead of discarding it. Every other intent's generated Dart is unchanged.
  • IntentDialog(full:supporting:) support (ADR 0006). @IntentSpec gains resultDialogSupportingTemplate (the on-screen half, so the spoken line can carry context a reader already has) and resultDialogSystemImageName (an SF Symbol). Both require resultDialogTemplate and are a code generation error on their own rather than a silently dropped field. The symbol initializers are iOS 17.2+ while generated intents target iOS 17.0, so the symbol form is built behind if #available(iOS 17.2, *) with the symbol-less dialog as the fallback. The supporting template is collected into the String Catalog like the main one. Not experimentalIntentDialog(full:supporting:) is iOS 16.
  • IntentValueQuery (#51) graduated out of the experimental opt-in. The protocol is declared at iOS 26.0 and ships in the released iOS 26.5 SDK (Xcode 26.6), so #if APP_INTENTS_WWDC26 was never the right guard — the <Entity>ValueQuery struct is now emitted whenever @EntitySpec(valueQuery: true) is set, under @available(iOS 26.0, *). Action required: none if you already passed --experimental=value-query (the flag is still accepted and now reported as a no-op); if you set valueQuery: true without the flag, the query now appears in your generated Swift for the first time. An entity that also opts into App Schema (#49) keeps the #if/#else pair, because the entity type itself is iOS 27 only in that branch.
  • CLI: --experimental=value-query is still accepted and now prints why it is a no-op, instead of being rejected outright once the feature graduated out of the flag list.
  • scripts/verify_experimental_swift.sh: fixed a stale AppIntentsBridge source path that had been broken since the module moved into the plugin's Swift package (#102), and taught it to run against a stable Xcode (it then checks only the non-#if branch, which is what proves an ungated feature compiles without the iOS 27 SDK).

0.15.0 #

  • No codegen changes. The import AppIntentsBridge line that generate_widget_swift emits now resolves on the CocoaPods route too (#105), and the module ships as a product of the plugin's Swift package (#102 follow-up) — see the app_intents changelog and docs/usage.md → "Consuming AppIntentsBridge".
  • Bumps app_intents_annotations dependency to ^0.15.0.

0.14.0 #

  • Widens the analyzer constraint to >=7.0.0 <15.0.0, so this package can be used alongside analyzer 14.x. Verified against analyzer 14.1.0 / _fe_analyzer_shared 105.0.0: analysis is clean, the full test suite passes, and build_runner, generate_swift, generate_widget_swift and generate_kotlin all produce byte-identical output to the 13.x resolution.
  • Bumps app_intents_annotations dependency to ^0.14.0.
  • Docs: the Swift emitted by generate_widget_swift opens with import AppIntentsBridge; that package now ships inside the app_intents pub package, so a Widget Extension target can resolve it. See docs/usage.md → "Consuming AppIntentsBridge" (#102).

0.13.0 #

  • Fix: entity @EntityId fields not named id generated Swift that does not compile. AppEntity refines Identifiable, which requires a stored property literally named id; SwiftGenerator emitted the Dart field name verbatim, so @EntityId on e.g. teamId produced type 'X' does not conform to protocol 'AppEntity' / 'Identifiable' (and a confusing 'ObjectIdentifier' does not conform to 'EntityIdentifierConvertible'). The Swift identifier property is now always emitted as id, while the Dart field name survives as the cache/dictionary key (dict["teamId"]) — matching what the Dart cache projection writes, and matching the rest of the generator, which already read <entity>.id unconditionally when serializing entity-typed intent parameters. Entities whose field is already named id generate byte-identical output. The unnormalizable case (@EntityId on a non-id field plus a separate field named id) now throws InvalidGenerationSourceError instead of emitting two var id declarations.
  • @WidgetConfigurationSpec codegen + the generate_widget_swift CLI — emits a WidgetConfigurationIntent plus a cache-backed EntityQuery for a Widget Extension target, which reads the App Group entity cache instead of going through FlutterBridge (#98). WidgetSwiftGenerator applies the same id normalization described above.
  • Bumps app_intents_annotations dependency to ^0.13.0.

0.12.0 #

  • @IntentSpec(donatable: true) (#55, requires --experimental=donation): emits a #if APP_INTENTS_WWDC26-gated register<Intent>Donator() reverse-executor that reconstructs the concrete intent from a [String: Any] params dict and calls intent.donate() (stable iOS 16+). Analyzer enforces the MVP primitive-only contract; rejects entityType / enumType / fileType / entityCollectionType / @UnionValue / non-primitive Dart types at codegen time.
  • @IntentParam(useValueState: true) (#52): emits if #available(iOS 18.2, *) { switch $field.valueState { … @unknown default … } } in perform() and adds a sibling "<field>State": "unset" | "cleared" | "set" entry to the wire dict. The state key is added via if let in both FlutterBridge and cache-mode emit paths, so it is absent on iOS < 18.2 and the Dart handler can distinguish "no state info" from a present state. Analyzer rejects opt-in on non-optional Dart params. The Swift output uses @unknown default to future-proof against Swift 6's non-frozen enum errors. No experimental flag — this is a normal feature (the SDK symbol is stable iOS 18.2).
  • AppSchemas.system.searchInApp — codegen consumes the schema string verbatim through the existing @AppIntent(schema:) / @AppEntity(schema:) macro emission (the app-schema experimental gate is unchanged); no codegen change beyond the typed accessor that lives in app_intents_annotations.
  • Bumps app_intents_annotations dependency to ^0.12.0.

0.11.0 #

  • WWDC26 experimental code generation (opt-in, default OFF). Master switch --experimental-wwdc26 + per-feature --experimental=<flag> (app-schema, ownership, long-running, rich-types, value-query, value-representation, donation). Experimental Swift is emitted inside #if APP_INTENTS_WWDC26 with a mandatory stable #else fallback, so released-SDK builds (without the flag) still compile.
    • Intent execution control (#52): LongRunningIntent / CancellableIntent / execution targets.
    • App Schema (#49) + semantic indexing (#50): @AppEntity/@AppIntent/@AppEnum(schema:) and @Property(indexingKey:) (indexing ships as a normal iOS 18.4 feature).
    • Entity ownership (#55): additive OwnershipProvidingEntity conformance.
    • Rich parameter types (#53): native Duration / PersonNameComponents / EntityCollection / @UnionValue parameters with compile-everywhere fallbacks, plus a generated union fromMap factory.
    • IntentValueQuery (#51), cross-app export (#54, IntentPerson), and SyncableEntity / RelevantEntities donation (#55).
    • Dual-branch output verified via swiftc -typecheck (with and without APP_INTENTS_WWDC26) against the Xcode 27 beta SDK; see scripts/verify_experimental_swift.sh.
  • AppIntentsTesting scaffold for the example app (#57, compile-checked, inert on stable Xcode).
  • Docs: correct the @EnumSpec / @EnumCaseDisplay examples, the Dart SDK constraint (^3.10.0) and dependency ranges, the Android toolchain versions, and add the ownership experimental flag to the feature tables.

0.10.1 #

  • No codegen changes; version bump aligns with app_intents 0.10.1 (Android compilerOptions DSL fix for Kotlin 2.3+ / AGP 9.1.0+, #20)
  • Maintenance: dependency bumps (analyzer, source_gen, build, build_test, dart_style, test)

0.10.0 #

  • No codegen changes; version bump aligns with app_intents 0.10.0 (Swift Package Manager support for the iOS plugin, #29)

0.9.0 #

  • Generated Swift EntityQuery now reads cached entities from App Group UserDefaults before waiting on the Flutter executor, mitigating the cold-start entityQueryNotConfigured error when iOS has killed the host app (#26)
  • SwiftGenerator emits the new App Group fallback path when @EntitySpec(persistedCacheKey: ...) is set, or when enumerable: true / indexed: true provides a default key app_intents.entities.<identifier>
  • Generated Swift AppShortcuts struct now uses the @AppShortcutsBuilder result builder annotation per Apple's AppShortcutsProvider protocol requirement (#25)

0.8.0 #

  • Upgrade androidx.appfunctions from 1.0.0-alpha07 to 1.0.0-alpha09 in the example app (#23)
  • KotlinGenerator now emits @AppFunction(isDescribedByKDoc = true) and @AppFunctionSerializable(isDescribedByKDoc = true) (uppercase D) to match the renamed parameter introduced in alpha08
  • Breaking for downstream Android hosts: alpha09's AAR metadata requires AGP 9.1.0+, Gradle 9.3.1+, and compileSdk = 37. Hosts also need android.newDsl=false (Flutter Gradle plugin compatibility) and android.builtInKotlin=false (KSP compatibility) in android/gradle.properties. Regenerate Kotlin output with dart run app_intents_codegen:generate_kotlin after upgrading. See docs/usage.md for the full setup.

0.7.8 #

  • No codegen changes; version bump to align with plugin fix release (Android cache no-op handlers)

0.7.7 #

  • No codegen changes; version bump to align with plugin fix release

0.7.6 #

  • No codegen changes; version bump to align with plugin bug fix release (App Group storage fix)

0.7.5 #

  • Fix: Kotlin codegen file parameter (IntentFile) now includes mimeType and filename in generated map (#15)
  • Docs: Add waitForPlugin() pattern explanation with timeout rationale and failure behavior (#16)
  • Docs: Document processPendingActions() initialization order and cold start race condition (#17)
  • Docs: Add updateAppShortcutParameters() migration guide for users migrating from other libraries (#18)

0.7.4 #

  • Fix: Use ${param} placeholder format in xcstrings keys for ParameterSummary and AppShortcut phrases (#14)
    • Swift key-path syntax \(\.$param) requires ${param} in xcstrings keys, not {param}
    • YAML translations support both {param} and ${param} key formats
  • Revert: Remove LocalizedStringResource wrapper from IntentDescription (unnecessary for localization)

0.7.3 #

  • Fix: Wrap IntentDescription with LocalizedStringResource for proper localization support (#14)

0.7.2 #

  • Fix: Escape newlines in Swift IntentDescription("...") string literal to prevent compile errors

0.7.1 #

  • Fix: Kotlin KDoc multiline description now correctly adds * prefix to continuation lines
  • Fix: Add missing import AppIntentsBridge in generated Swift code for FlutterBridge mode and entity queries

0.7.0 #

  • Add .xcstrings String Catalog generation for iOS localization
    • New XcstringsGenerator class collects all localizable strings from annotations
    • Translations YAML file support for multi-language localization
    • Merge mode preserves existing translations when regenerating
    • {param} placeholders converted to %@ / %1$@ format; ${applicationName} preserved
  • Add CLI options to generate_swift: --xcstrings, --translations, --source-language
  • Add yaml package dependency

0.6.2 #

  • Fix: _toUpperSnakeCase no longer prepends underscore to uppercase-starting enum names in KotlinGenerator
  • Fix: Add missing return keyword in displayRepresentation for entities without nullable image
  • Fix: Deduplicate generateAppShortcutsProvider / _generateShortcutsProviderBody in SwiftGenerator
  • Fix: Simplify _cleanClassName to single-pass Spec suffix removal
  • Fix: Extract _isNullableParam helper to eliminate triple-computation in DartGenerator
  • Fix: Remove unnecessary intermediate StringBuffer in generateAll
  • Fix: Add temp file cleanup in generated Swift code for FlutterBridge execution mode
  • Improve: Analyzer error reporting — InvalidGenerationSourceError instead of silent null for missing required fields
  • Improve: Fix _toDisplayTitle docstring accuracy in EnumAnalyzer
  • Improve: Inline _formatType dead abstraction in EntityAnalyzer
  • Improve: Type _extractPhrases parameter as DartObject? instead of dynamic in ShortcutAnalyzer

0.6.1 #

  • Fix: Map IntentFile/IntentFile? to String/String? in KotlinGenerator for KSP compatibility (#11)
    • KSP compiler does not support IntentFile as @AppFunction parameter type
    • File parameters now generate mapOf("path" to value) for Dart-side IntentFile.fromMap() compatibility
  • Documentation fixes: correct outdated code examples and API references

0.6.0 #

  • BREAKING: Remove inputType/outputType from IntentInfo model
  • Generate type-safe XxxParams class for each intent with parameters
    • fromMap(Map<String, dynamic>) for MethodChannel / cache mode
    • fromQueryParameters(Map<String, String>) for URL scheme deep links
    • Supports String, int, double, bool, DateTime, IntentFile types
  • Handler registration now uses Params class and always returns empty map
  • Remove _extractTypeArguments() from IntentAnalyzer

0.5.2 #

  • Fix Swift 6 strict concurrency errors in FlutterBridge.swift when used as SPM package
    • Add sending keyword to all non-Sendable parameters and return types crossing actor boundaries
    • Affects invoke(), queryEntities(), suggestedEntities(), and all executor/handler closures

0.5.1 #

  • Add root Package.swift so AppIntentsBridge can be fetched via standard SPM from repository URL

0.5.0 #

  • Fix AppShortcut phrase {paramName} to generate \(\.$paramName) Swift syntax
  • Add imageName support in @EnumCaseDisplay code generation (asset bundle image)
  • Add displayImageName support in @EntitySpec for entity DisplayRepresentation image
    • Static image via named: for entity type, per-instance @EntityImage via systemName: takes priority
  • Add EnumerableEntityQuery extension generation when enumerable: true
  • Add IndexedEntity extension generation when indexed: true (iOS 26+, import CoreSpotlight)
  • Update EnumAnalyzer to extract imageName from @EnumCaseDisplay
  • Update EntityAnalyzer to extract displayImageName, indexed, enumerable from @EntitySpec
  • 189 tests (28 new tests for all new features)

0.4.1 #

  • Widen dependency constraints to resolve conflicts with other codegen packages (e.g., go_router_builder)
    • source_gen: ">=2.0.0 <5.0.0" (was ^2.0.0)
    • analyzer: ">=7.0.0 <11.0.0" (was ^7.0.0)
    • build: ">=2.4.0 <5.0.0" (was ^2.4.0)
    • build_test: ">=2.2.0 <4.0.0" (was ^2.2.0)
  • Migrate to TypeChecker.fromUrl() for compatibility with source_gen 4.x
  • Migrate to LibraryElement.classes/.enums API for compatibility with analyzer 10.x
  • Fix nullable element.name handling for analyzer 10.x

0.4.0 #

  • Add supportedModes support in SwiftGenerator
    • Generates @available(iOS 26.0, *) static var supportedModes: IntentModes { .foreground }
    • Generates static var openAppWhenRun: Bool { true } for backward compatibility
    • Both properties generated when supportedModes: foreground or urlScheme is set
  • Add IntentFile parameter support in SwiftGenerator
    • @Parameter(supportedTypeIdentifiers:) for file type parameters
    • File serialization code generation (write to temp file, extract path/mimeType/filename)
    • import UniformTypeIdentifiers when file params present
  • Add cache mode in SwiftGenerator (_writeCachePerformMethod)
    • Auto-generated when supportedModes: foreground without urlScheme
    • Caches params to UserDefaults via AppIntentsPlugin.setPendingAction()
    • processPendingActions() delivers cached actions via existing executeIntent mechanism
  • Add IntentFile.fromMap() extraction in DartGenerator for file parameters
  • Fix: Use Map.from() for IntentFile params from MethodChannel (avoid type cast errors)
  • Add IntentModeType enum and fileType field to codegen models
  • Update IntentAnalyzer to parse supportedModes and fileType annotations

0.3.0 #

  • Add KotlinGenerator for Android AppFunctions code generation
    • @AppFunction(isDescribedByKdoc = true) annotated methods
    • @AppFunctionSerializable data classes for entities
    • AppFunctionsBridge singleton for MethodChannel communication
    • Enum class generation with fromValue() companion object
  • Add CLI command generate_kotlin for Kotlin file output
  • Extract shared analyzeSources() utility for Swift/Kotlin CLI commands
  • 154 tests (38 new Kotlin generator tests)
  • Update documentation for cross-platform support

0.2.1 #

  • Documentation updates to reflect v0.2.0 features
  • No code changes

0.2.0 #

  • BREAKING: Raise iOS minimum to 17.0
  • Add IntentResult & ProvidesDialog support via resultDialogTemplate
  • Add ParameterSummary generation via parameterSummary
  • Add AppEnum code generation (@EnumSpec, EnumAnalyzer, _generateEnumBody)
  • Add entity image support in DisplayRepresentation (SF Symbol icons)
  • Add {applicationName} to \(.applicationName) phrase conversion for AppShortcuts
  • Fix AppShortcutsProvider to use Swift result builder pattern (no array literals)
  • Fix error handling: throw AppIntentError.custom(...) instead of silent return .result()
  • Fix double-quote escaping in dialog templates
  • Fix shortcut intentIdentifier to className resolution in CLI
  • 116 tests covering all analyzers, generators, and builder

0.1.0 #

  • Initial release
  • IntentAnalyzer and EntityAnalyzer for annotation parsing
  • ShortcutAnalyzer for @AppShortcut and @AppShortcutsProvider support
  • SwiftGenerator for iOS 17+ App Intent Swift code generation
  • DartGenerator for handler initialization code generation
  • CLI tool generate_swift for Swift code output
  • Integration with build_runner via AppIntentsBuilder
0
likes
130
points
482
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

Code generator for Flutter AppIntents. Produces Swift and Dart code from @IntentSpec and @EntitySpec annotations.

Repository (GitHub)
View/report issues
Contributing

Topics

#siri #app-intents #appfunctions #codegen #build-runner

License

MIT (license)

Dependencies

analyzer, app_intents_annotations, args, build, code_builder, dart_style, glob, path, source_gen, yaml

More

Packages that depend on app_intents_codegen