Expose createTodo via Android AppFunctions (Gemini-ready capture)#13
Open
colonelpanic8 wants to merge 1 commit into
Open
Expose createTodo via Android AppFunctions (Gemini-ready capture)#13colonelpanic8 wants to merge 1 commit into
colonelpanic8 wants to merge 1 commit into
Conversation
Add androidx.appfunctions (Jetpack) support so on-device assistants/agents (eventually Gemini) can capture a todo into Mova by voice. Implements a single @appfunction, createTodo(appFunctionContext, title, notes?), that POSTs to the user's org-agenda-api server at {apiUrl}/capture with {"template":"default","values":{"Title":...}} over HTTP Basic auth, matching the existing widget/QuickCapture capture path. Credentials: reuses the native-readable copy the RN app already writes at login. context/AuthContext.tsx -> widgets/storage.ts -> SharedStorageModule persists the server URL + username + password into the "mova_widget_prefs" SharedPreferences (keys mova_api_url/mova_username/mova_password), which QuickCaptureActivity already reads natively. The AppFunction reads the same prefs via AppFunctionContext.context, so no new persistence layer is introduced. No credentials -> AppFunctionAppUnknown Exception with a "log in first" message; network/server error -> AppFunctionApp UnknownException; blank title -> AppFunctionInvalidArgumentException. Timeouts are bounded (connect 8s, read 12s) to match the codebase style. Wiring: - MainApplication implements AppFunctionConfiguration.Provider and registers a factory for the stateless MovaAppFunctions enclosing class. - appfunctions-service supplies the platform AppFunctionService via its own merged manifest, so no manual <service> declaration is needed. - The KSP appfunctions-compiler generates the app_functions_v2.xml descriptor that the OS indexes; verified createTodo (title required, notes optional) and its KDoc descriptions appear in the generated descriptor. Version pinning / risk: - Pinned to androidx.appfunctions 1.0.0-alpha08, the last release compatible with the current Expo SDK 54 / React Native 0.81 toolchain (compileSdk 36, AGP 8.11, Kotlin 2.1.20). alpha09 requires compileSdk 37 and alpha10 requires AGP 9.1; neither is available under Expo's pinned toolchain, so no compileSdk/AGP bump was made. Bump all three appfunctions artifacts (and revisit the AppFunctionContext vs entry-point API shape) once Expo moves to AGP 9 / compileSdk 37. - KSP is added to the app module: plugin classpath pinned to 2.1.20-2.0.1 in android/build.gradle (matches RN's Kotlin 2.1.20); bump alongside any Kotlin bump. - These native edits (gradle, MainApplication) live in the committed android/ project like the existing QuickCapture/widget code; a future `expo prebuild --clean` would need them reapplied, same as the existing custom native code. Verified: `:app:compileDebugKotlin` (incl. kspDebugKotlin) succeeds in the nix .#android dev shell. No device was available for `adb shell cmd app_function list-app-functions`. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds Android AppFunctions (
androidx.appfunctionsJetpack, Android 16+) support to the app, exposing a single@AppFunction—createTodo(title, notes?)— that captures a todo into Mova by POSTing to the user's org-agenda-api/captureendpoint. On-device agents (eventually Gemini) discover the function via the OS index and read its KDoc as the tool description.This is the forward-looking half of making on-the-go capture hands-free: App Actions' modern replacement. Gemini invocation of third-party AppFunctions is currently in Google's private preview / EAP, so this ships the mechanism now so it lights up when the preview opens.
What it does
createTodo(appFunctionContext, title, notes?)— trims/validates the title, reads the user's stored server URL + credentials, and POSTs{"template":"default","values":{"Title":…, "Body":…}}with HTTP Basic auth (connect 8s / read 12s, matching the codebase).mova_widget_prefsSharedPreferences (mova_api_url/mova_username/mova_password) that the RN app writes at login viaSharedStorageModuleand thatQuickCaptureActivityalready reads. Verified the file name and keys match the existing native code.AppFunctionInvalidArgumentException; not-signed-in / network / server error →AppFunctionAppUnknownExceptionwith messages written for the model to read back.Build / toolchain
androidx.appfunctions:appfunctions{,-service,-compiler}= 1.0.0-alpha08, plus the KSP plugin (2.1.20-2.0.1, matching RN 0.81's pinned Kotlin 2.1.20).@AppFunctionServiceEntryPointservice model). Bump all three artifacts + revisit the API shape once Expo/RN moves to AGP 9 / compileSdk 37. No compileSdk/AGP bump required by this PR.:app:compileDebugKotlin(incl.kspDebugKotlin) builds green in thenix develop --impure .#androidshell; KSP generatedapp_functions_v2.xmlwithMovaAppFunctions#createTodo(title required, notes optional,CreateTodoResultschema, KDoc descriptions).Not yet verified / follow-ups
adb shell cmd app_function list-app-functions | grep com.colonelpanic.movaand invoke via Google's sample agent app.notes→"Body"value assumes the default capture template has a Body field; it's only sent when non-blank and degrades to title-only otherwise. Worth confirming against the live template (QuickCaptureActivitydiscovers field names dynamically via/capture-templates; this function hardcodesTitlelike the wearCaptureClient).expo prebuild --cleanwould drop theseandroid/edits (same caveat as the existing QuickCapture/widget native code).🤖 Generated with Claude Code