expo-ai-kit 0.1.20 → 0.1.22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +207 -2
- package/build/hooks.d.ts +88 -0
- package/build/hooks.d.ts.map +1 -0
- package/build/hooks.js +293 -0
- package/build/hooks.js.map +1 -0
- package/build/index.d.ts +1 -0
- package/build/index.d.ts.map +1 -1
- package/build/index.js +1 -0
- package/build/index.js.map +1 -1
- package/build/types.d.ts +71 -0
- package/build/types.d.ts.map +1 -1
- package/build/types.js.map +1 -1
- package/ios/ExpoAiKit.podspec +1 -1
- package/package.json +5 -9
- package/src/hooks.ts +331 -0
- package/src/index.ts +1 -0
- package/src/types.ts +80 -0
- package/android/.gradle/8.9/checksums/checksums.lock +0 -0
- package/android/.gradle/8.9/dependencies-accessors/gc.properties +0 -0
- package/android/.gradle/8.9/fileChanges/last-build.bin +0 -0
- package/android/.gradle/8.9/fileHashes/fileHashes.lock +0 -0
- package/android/.gradle/8.9/gc.properties +0 -0
- package/android/.gradle/buildOutputCleanup/buildOutputCleanup.lock +0 -0
- package/android/.gradle/buildOutputCleanup/cache.properties +0 -2
- package/android/.gradle/vcs-1/gc.properties +0 -0
- package/android/build/.transforms/550f2d3d50c89e495845cc30f2214044/results.bin +0 -1
- package/android/build/.transforms/550f2d3d50c89e495845cc30f2214044/transformed/classes/classes_dex/classes.dex +0 -0
- package/android/build/.transforms/a588f18db136c18b668ecd9727a7dc6b/results.bin +0 -1
- package/android/build/.transforms/a588f18db136c18b668ecd9727a7dc6b/transformed/classes/classes_dex/classes.dex +0 -0
- package/android/build/.transforms/c485bab123d2a96b9ef2e8051e8dcd8c/results.bin +0 -1
- package/android/build/.transforms/c485bab123d2a96b9ef2e8051e8dcd8c/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/aikit/BuildConfig.dex +0 -0
- package/android/build/.transforms/c485bab123d2a96b9ef2e8051e8dcd8c/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/aikit/ExpoAiKitModule$definition$1$5$1.dex +0 -0
- package/android/build/.transforms/c485bab123d2a96b9ef2e8051e8dcd8c/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/aikit/ExpoAiKitModule$definition$lambda$6$$inlined$AsyncFunction$1.dex +0 -0
- package/android/build/.transforms/c485bab123d2a96b9ef2e8051e8dcd8c/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/aikit/ExpoAiKitModule$definition$lambda$6$$inlined$AsyncFunction$2.dex +0 -0
- package/android/build/.transforms/c485bab123d2a96b9ef2e8051e8dcd8c/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/aikit/ExpoAiKitModule$definition$lambda$6$$inlined$AsyncFunction$3.dex +0 -0
- package/android/build/.transforms/c485bab123d2a96b9ef2e8051e8dcd8c/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/aikit/ExpoAiKitModule$definition$lambda$6$$inlined$AsyncFunctionWithoutArgs$1.dex +0 -0
- package/android/build/.transforms/c485bab123d2a96b9ef2e8051e8dcd8c/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/aikit/ExpoAiKitModule$definition$lambda$6$$inlined$Constant$1.dex +0 -0
- package/android/build/.transforms/c485bab123d2a96b9ef2e8051e8dcd8c/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/aikit/ExpoAiKitModule$definition$lambda$6$$inlined$FunctionWithoutArgs$1.dex +0 -0
- package/android/build/.transforms/c485bab123d2a96b9ef2e8051e8dcd8c/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/aikit/ExpoAiKitModule$definition$lambda$6$$inlined$View$1.dex +0 -0
- package/android/build/.transforms/c485bab123d2a96b9ef2e8051e8dcd8c/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/aikit/ExpoAiKitModule$definition$lambda$6$lambda$5$$inlined$Prop$1.dex +0 -0
- package/android/build/.transforms/c485bab123d2a96b9ef2e8051e8dcd8c/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/aikit/ExpoAiKitModule.dex +0 -0
- package/android/build/.transforms/c485bab123d2a96b9ef2e8051e8dcd8c/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/aikit/ExpoAiKitView$webView$1$1.dex +0 -0
- package/android/build/.transforms/c485bab123d2a96b9ef2e8051e8dcd8c/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/aikit/ExpoAiKitView.dex +0 -0
- package/android/build/.transforms/c485bab123d2a96b9ef2e8051e8dcd8c/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/aikit/PromptApiClient$isAvailable$1.dex +0 -0
- package/android/build/.transforms/c485bab123d2a96b9ef2e8051e8dcd8c/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/aikit/PromptApiClient$isAvailableBlocking$1.dex +0 -0
- package/android/build/.transforms/c485bab123d2a96b9ef2e8051e8dcd8c/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/aikit/PromptApiClient.dex +0 -0
- package/android/build/.transforms/c485bab123d2a96b9ef2e8051e8dcd8c/transformed/bundleLibRuntimeToDirDebug/desugar_graph.bin +0 -0
- package/android/build/.transforms/e7552020676c2f8a620fec964bf11729/results.bin +0 -1
- package/android/build/.transforms/e7552020676c2f8a620fec964bf11729/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/aikit/BuildConfig.dex +0 -0
- package/android/build/.transforms/e7552020676c2f8a620fec964bf11729/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/aikit/ExpoAiKitModule$definition$1$2$conversationPrompt$2.dex +0 -0
- package/android/build/.transforms/e7552020676c2f8a620fec964bf11729/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/aikit/ExpoAiKitModule$definition$1$3$conversationPrompt$2.dex +0 -0
- package/android/build/.transforms/e7552020676c2f8a620fec964bf11729/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/aikit/ExpoAiKitModule$definition$1$3$job$1$1.dex +0 -0
- package/android/build/.transforms/e7552020676c2f8a620fec964bf11729/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/aikit/ExpoAiKitModule$definition$1$3$job$1.dex +0 -0
- package/android/build/.transforms/e7552020676c2f8a620fec964bf11729/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/aikit/ExpoAiKitModule$definition$lambda$11$$inlined$AsyncFunction$1.dex +0 -0
- package/android/build/.transforms/e7552020676c2f8a620fec964bf11729/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/aikit/ExpoAiKitModule$definition$lambda$11$$inlined$AsyncFunction$2.dex +0 -0
- package/android/build/.transforms/e7552020676c2f8a620fec964bf11729/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/aikit/ExpoAiKitModule$definition$lambda$11$$inlined$AsyncFunction$3.dex +0 -0
- package/android/build/.transforms/e7552020676c2f8a620fec964bf11729/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/aikit/ExpoAiKitModule$definition$lambda$11$$inlined$AsyncFunction$4.dex +0 -0
- package/android/build/.transforms/e7552020676c2f8a620fec964bf11729/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/aikit/ExpoAiKitModule$definition$lambda$11$$inlined$AsyncFunction$5.dex +0 -0
- package/android/build/.transforms/e7552020676c2f8a620fec964bf11729/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/aikit/ExpoAiKitModule$definition$lambda$11$$inlined$AsyncFunction$6.dex +0 -0
- package/android/build/.transforms/e7552020676c2f8a620fec964bf11729/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/aikit/ExpoAiKitModule$definition$lambda$11$$inlined$AsyncFunction$7.dex +0 -0
- package/android/build/.transforms/e7552020676c2f8a620fec964bf11729/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/aikit/ExpoAiKitModule$definition$lambda$11$$inlined$Coroutine$1.dex +0 -0
- package/android/build/.transforms/e7552020676c2f8a620fec964bf11729/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/aikit/ExpoAiKitModule$definition$lambda$11$$inlined$Coroutine$2.dex +0 -0
- package/android/build/.transforms/e7552020676c2f8a620fec964bf11729/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/aikit/ExpoAiKitModule$definition$lambda$11$$inlined$Coroutine$3.dex +0 -0
- package/android/build/.transforms/e7552020676c2f8a620fec964bf11729/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/aikit/ExpoAiKitModule$definition$lambda$11$$inlined$FunctionWithoutArgs$1.dex +0 -0
- package/android/build/.transforms/e7552020676c2f8a620fec964bf11729/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/aikit/ExpoAiKitModule.dex +0 -0
- package/android/build/.transforms/e7552020676c2f8a620fec964bf11729/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/aikit/PromptApiClient$generateText$2.dex +0 -0
- package/android/build/.transforms/e7552020676c2f8a620fec964bf11729/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/aikit/PromptApiClient$generateTextStream$2$1.dex +0 -0
- package/android/build/.transforms/e7552020676c2f8a620fec964bf11729/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/aikit/PromptApiClient$generateTextStream$2.dex +0 -0
- package/android/build/.transforms/e7552020676c2f8a620fec964bf11729/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/aikit/PromptApiClient$isAvailable$1.dex +0 -0
- package/android/build/.transforms/e7552020676c2f8a620fec964bf11729/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/aikit/PromptApiClient$isAvailableBlocking$1.dex +0 -0
- package/android/build/.transforms/e7552020676c2f8a620fec964bf11729/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/aikit/PromptApiClient.dex +0 -0
- package/android/build/.transforms/e7552020676c2f8a620fec964bf11729/transformed/bundleLibRuntimeToDirDebug/desugar_graph.bin +0 -0
- package/android/build/generated/source/buildConfig/debug/expo/modules/aikit/BuildConfig.java +0 -10
- package/android/build/intermediates/aapt_friendly_merged_manifests/debug/processDebugManifest/aapt/AndroidManifest.xml +0 -7
- package/android/build/intermediates/aapt_friendly_merged_manifests/debug/processDebugManifest/aapt/output-metadata.json +0 -18
- package/android/build/intermediates/aar_metadata/debug/writeDebugAarMetadata/aar-metadata.properties +0 -6
- package/android/build/intermediates/annotation_processor_list/debug/javaPreCompileDebug/annotationProcessors.json +0 -1
- package/android/build/intermediates/compile_library_classes_jar/debug/bundleLibCompileToJarDebug/classes.jar +0 -0
- package/android/build/intermediates/compile_r_class_jar/debug/generateDebugRFile/R.jar +0 -0
- package/android/build/intermediates/compile_symbol_list/debug/generateDebugRFile/R.txt +0 -0
- package/android/build/intermediates/incremental/debug/packageDebugResources/compile-file-map.properties +0 -1
- package/android/build/intermediates/incremental/debug/packageDebugResources/merger.xml +0 -2
- package/android/build/intermediates/incremental/mergeDebugAssets/merger.xml +0 -2
- package/android/build/intermediates/incremental/mergeDebugJniLibFolders/merger.xml +0 -2
- package/android/build/intermediates/incremental/mergeDebugShaders/merger.xml +0 -2
- package/android/build/intermediates/java_res/debug/processDebugJavaRes/out/META-INF/expo-ai-kit_debug.kotlin_module +0 -0
- package/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/expo/modules/aikit/BuildConfig.class +0 -0
- package/android/build/intermediates/local_only_symbol_list/debug/parseDebugLocalResources/R-def.txt +0 -2
- package/android/build/intermediates/manifest_merge_blame_file/debug/processDebugManifest/manifest-merger-blame-debug-report.txt +0 -7
- package/android/build/intermediates/merged_manifest/debug/processDebugManifest/AndroidManifest.xml +0 -7
- package/android/build/intermediates/navigation_json/debug/extractDeepLinksDebug/navigation.json +0 -1
- package/android/build/intermediates/nested_resources_validation_report/debug/generateDebugResources/nestedResourcesValidationReport.txt +0 -1
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/META-INF/expo-ai-kit_debug.kotlin_module +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/aikit/BuildConfig.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/aikit/ExpoAiKitModule$definition$1$2$conversationPrompt$2.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/aikit/ExpoAiKitModule$definition$1$3$conversationPrompt$2.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/aikit/ExpoAiKitModule$definition$1$3$job$1$1.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/aikit/ExpoAiKitModule$definition$1$3$job$1.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/aikit/ExpoAiKitModule$definition$lambda$11$$inlined$AsyncFunction$1.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/aikit/ExpoAiKitModule$definition$lambda$11$$inlined$AsyncFunction$2.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/aikit/ExpoAiKitModule$definition$lambda$11$$inlined$AsyncFunction$3.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/aikit/ExpoAiKitModule$definition$lambda$11$$inlined$AsyncFunction$4.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/aikit/ExpoAiKitModule$definition$lambda$11$$inlined$AsyncFunction$5.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/aikit/ExpoAiKitModule$definition$lambda$11$$inlined$AsyncFunction$6.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/aikit/ExpoAiKitModule$definition$lambda$11$$inlined$AsyncFunction$7.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/aikit/ExpoAiKitModule$definition$lambda$11$$inlined$Coroutine$1.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/aikit/ExpoAiKitModule$definition$lambda$11$$inlined$Coroutine$2.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/aikit/ExpoAiKitModule$definition$lambda$11$$inlined$Coroutine$3.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/aikit/ExpoAiKitModule$definition$lambda$11$$inlined$FunctionWithoutArgs$1.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/aikit/ExpoAiKitModule.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/aikit/PromptApiClient$generateText$2.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/aikit/PromptApiClient$generateTextStream$2$1.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/aikit/PromptApiClient$generateTextStream$2.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/aikit/PromptApiClient$isAvailable$1.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/aikit/PromptApiClient$isAvailableBlocking$1.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/aikit/PromptApiClient.class +0 -0
- package/android/build/intermediates/runtime_library_classes_jar/debug/bundleLibRuntimeToJarDebug/classes.jar +0 -0
- package/android/build/intermediates/symbol_list_with_package_name/debug/generateDebugRFile/package-aware-r.txt +0 -1
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.keystream +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.keystream.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.values.at +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab_i +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab_i.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.keystream +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.keystream.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.values.at +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab_i +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab_i.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.keystream +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.keystream.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.values.at +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab_i +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab_i.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.keystream +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.keystream.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.values.at +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab_i +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab_i.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.keystream +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.keystream.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.values.at +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab_i +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab_i.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.keystream +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.keystream.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.values.at +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab_i +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab_i.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab.keystream +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab.keystream.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab.values.at +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab_i +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab_i.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.keystream +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.keystream.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.values.at +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab_i +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab_i.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/counters.tab +0 -2
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.keystream +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.keystream.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.values.at +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab_i +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab_i.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.keystream +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.keystream.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.values.at +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab_i +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab_i.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.keystream +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.keystream.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.values.at +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab_i +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab_i.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/last-build.bin +0 -0
- package/android/build/kotlin/compileDebugKotlin/classpath-snapshot/shrunk-classpath-snapshot.bin +0 -0
- package/android/build/kotlin/compileDebugKotlin/local-state/build-history.bin +0 -0
- package/android/build/outputs/logs/manifest-merger-debug-report.txt +0 -14
- package/android/build/tmp/compileDebugJavaWithJavac/previous-compilation-data.bin +0 -0
- package/android/build/tmp/kotlin-classes/debug/META-INF/expo-ai-kit_debug.kotlin_module +0 -0
- package/android/build/tmp/kotlin-classes/debug/expo/modules/aikit/ExpoAiKitModule$definition$1$2$conversationPrompt$2.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/expo/modules/aikit/ExpoAiKitModule$definition$1$3$conversationPrompt$2.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/expo/modules/aikit/ExpoAiKitModule$definition$1$3$job$1$1.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/expo/modules/aikit/ExpoAiKitModule$definition$1$3$job$1.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/expo/modules/aikit/ExpoAiKitModule$definition$lambda$11$$inlined$AsyncFunction$1.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/expo/modules/aikit/ExpoAiKitModule$definition$lambda$11$$inlined$AsyncFunction$2.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/expo/modules/aikit/ExpoAiKitModule$definition$lambda$11$$inlined$AsyncFunction$3.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/expo/modules/aikit/ExpoAiKitModule$definition$lambda$11$$inlined$AsyncFunction$4.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/expo/modules/aikit/ExpoAiKitModule$definition$lambda$11$$inlined$AsyncFunction$5.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/expo/modules/aikit/ExpoAiKitModule$definition$lambda$11$$inlined$AsyncFunction$6.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/expo/modules/aikit/ExpoAiKitModule$definition$lambda$11$$inlined$AsyncFunction$7.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/expo/modules/aikit/ExpoAiKitModule$definition$lambda$11$$inlined$Coroutine$1.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/expo/modules/aikit/ExpoAiKitModule$definition$lambda$11$$inlined$Coroutine$2.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/expo/modules/aikit/ExpoAiKitModule$definition$lambda$11$$inlined$Coroutine$3.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/expo/modules/aikit/ExpoAiKitModule$definition$lambda$11$$inlined$FunctionWithoutArgs$1.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/expo/modules/aikit/ExpoAiKitModule.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/expo/modules/aikit/PromptApiClient$generateText$2.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/expo/modules/aikit/PromptApiClient$generateTextStream$2$1.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/expo/modules/aikit/PromptApiClient$generateTextStream$2.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/expo/modules/aikit/PromptApiClient$isAvailable$1.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/expo/modules/aikit/PromptApiClient$isAvailableBlocking$1.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/expo/modules/aikit/PromptApiClient.class +0 -0
package/README.md
CHANGED
|
@@ -32,6 +32,7 @@ On-device AI for Expo apps. Run language models locally—no API keys, no cloud,
|
|
|
32
32
|
- **Simple API** — Core functions plus prompt helpers for common tasks
|
|
33
33
|
- **Prompt helpers** — Built-in `summarize()`, `translate()`, `rewrite()`, and more
|
|
34
34
|
- **Smart suggestions** — `suggest()`, `smartReply()`, and `autocomplete()` for predictive text
|
|
35
|
+
- **React Hooks** — `useChat`, `useCompletion`, and `useOnDeviceAI` for plug-and-play integration
|
|
35
36
|
- **Chat memory** — Built-in `ChatMemoryManager` for managing conversation history
|
|
36
37
|
|
|
37
38
|
## Requirements
|
|
@@ -290,6 +291,95 @@ const { promise, stop } = streamSummarize(
|
|
|
290
291
|
);
|
|
291
292
|
```
|
|
292
293
|
|
|
294
|
+
### React Hooks
|
|
295
|
+
|
|
296
|
+
expo-ai-kit provides React hooks that handle state management, streaming, and conversation memory automatically.
|
|
297
|
+
|
|
298
|
+
#### `useChat` — Full Chat Interface
|
|
299
|
+
|
|
300
|
+
The easiest way to build a chat UI. Manages messages, input, streaming, and memory for you:
|
|
301
|
+
|
|
302
|
+
```tsx
|
|
303
|
+
import { useChat } from 'expo-ai-kit';
|
|
304
|
+
|
|
305
|
+
function ChatScreen() {
|
|
306
|
+
const { messages, input, setInput, sendMessage, isStreaming, stop, clear, error } = useChat({
|
|
307
|
+
systemPrompt: 'You are a helpful assistant.',
|
|
308
|
+
maxTurns: 10,
|
|
309
|
+
});
|
|
310
|
+
|
|
311
|
+
return (
|
|
312
|
+
<View style={{ flex: 1 }}>
|
|
313
|
+
<FlatList
|
|
314
|
+
data={messages}
|
|
315
|
+
keyExtractor={(_, i) => i.toString()}
|
|
316
|
+
renderItem={({ item }) => (
|
|
317
|
+
<Text>{item.role}: {item.content}</Text>
|
|
318
|
+
)}
|
|
319
|
+
/>
|
|
320
|
+
<TextInput value={input} onChangeText={setInput} />
|
|
321
|
+
{isStreaming ? (
|
|
322
|
+
<Button title="Stop" onPress={stop} />
|
|
323
|
+
) : (
|
|
324
|
+
<Button title="Send" onPress={() => sendMessage()} />
|
|
325
|
+
)}
|
|
326
|
+
<Button title="Clear" onPress={clear} />
|
|
327
|
+
</View>
|
|
328
|
+
);
|
|
329
|
+
}
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
You can also send a message programmatically:
|
|
333
|
+
|
|
334
|
+
```tsx
|
|
335
|
+
// Send custom text instead of current input
|
|
336
|
+
sendMessage('What is the weather today?');
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
#### `useCompletion` — Single-shot Completions
|
|
340
|
+
|
|
341
|
+
For one-off tasks like summarization, translation, or content generation (no conversation history):
|
|
342
|
+
|
|
343
|
+
```tsx
|
|
344
|
+
import { useCompletion } from 'expo-ai-kit';
|
|
345
|
+
|
|
346
|
+
function Summarizer() {
|
|
347
|
+
const { completion, isLoading, complete, stop, error } = useCompletion({
|
|
348
|
+
systemPrompt: 'Summarize the given text concisely.',
|
|
349
|
+
});
|
|
350
|
+
|
|
351
|
+
return (
|
|
352
|
+
<View>
|
|
353
|
+
<Button
|
|
354
|
+
title="Summarize"
|
|
355
|
+
onPress={() => complete('Long article text here...')}
|
|
356
|
+
/>
|
|
357
|
+
{isLoading && <Button title="Stop" onPress={stop} />}
|
|
358
|
+
<Text>{completion}</Text>
|
|
359
|
+
</View>
|
|
360
|
+
);
|
|
361
|
+
}
|
|
362
|
+
```
|
|
363
|
+
|
|
364
|
+
#### `useOnDeviceAI` — Availability Check
|
|
365
|
+
|
|
366
|
+
A simple hook to check if on-device AI is available, with caching across components:
|
|
367
|
+
|
|
368
|
+
```tsx
|
|
369
|
+
import { useOnDeviceAI } from 'expo-ai-kit';
|
|
370
|
+
|
|
371
|
+
function App() {
|
|
372
|
+
const { isAvailable, isChecking } = useOnDeviceAI();
|
|
373
|
+
|
|
374
|
+
if (isChecking) return <Text>Checking AI availability...</Text>;
|
|
375
|
+
if (!isAvailable) return <Text>On-device AI not available</Text>;
|
|
376
|
+
|
|
377
|
+
return <ChatScreen />;
|
|
378
|
+
}
|
|
379
|
+
```
|
|
380
|
+
|
|
381
|
+
---
|
|
382
|
+
|
|
293
383
|
### Streaming with Cancel Button
|
|
294
384
|
|
|
295
385
|
```tsx
|
|
@@ -668,6 +758,80 @@ function parseSuggestResponse(raw: string): LLMSuggestResponse
|
|
|
668
758
|
|
|
669
759
|
---
|
|
670
760
|
|
|
761
|
+
### `useChat(options?)`
|
|
762
|
+
|
|
763
|
+
React hook for building chat interfaces. Manages messages, input, streaming, and conversation memory automatically.
|
|
764
|
+
|
|
765
|
+
```typescript
|
|
766
|
+
function useChat(options?: UseChatOptions): UseChatReturn
|
|
767
|
+
```
|
|
768
|
+
|
|
769
|
+
| Option | Type | Description |
|
|
770
|
+
|--------|------|-------------|
|
|
771
|
+
| `systemPrompt` | `string` | System prompt for the AI assistant |
|
|
772
|
+
| `maxTurns` | `number` | Maximum conversation turns to keep in memory (default: `10`) |
|
|
773
|
+
| `initialMessages` | `LLMMessage[]` | Initial messages to populate the chat |
|
|
774
|
+
| `onFinish` | `(response: LLMResponse) => void` | Callback when a response is complete |
|
|
775
|
+
| `onError` | `(error: Error) => void` | Callback when an error occurs |
|
|
776
|
+
|
|
777
|
+
**Returns:**
|
|
778
|
+
|
|
779
|
+
| Property | Type | Description |
|
|
780
|
+
|----------|------|-------------|
|
|
781
|
+
| `messages` | `LLMMessage[]` | All messages in the conversation |
|
|
782
|
+
| `input` | `string` | Current input text value |
|
|
783
|
+
| `setInput` | `(input: string) => void` | Set the input text value |
|
|
784
|
+
| `sendMessage` | `(text?: string) => Promise<void>` | Send the current input (or provided text) |
|
|
785
|
+
| `isStreaming` | `boolean` | Whether the AI is currently streaming |
|
|
786
|
+
| `stop` | `() => void` | Stop the current streaming response |
|
|
787
|
+
| `clear` | `() => void` | Clear all messages and reset |
|
|
788
|
+
| `error` | `Error \| null` | The most recent error, if any |
|
|
789
|
+
|
|
790
|
+
---
|
|
791
|
+
|
|
792
|
+
### `useCompletion(options?)`
|
|
793
|
+
|
|
794
|
+
React hook for single-shot AI completions (summarization, translation, etc.).
|
|
795
|
+
|
|
796
|
+
```typescript
|
|
797
|
+
function useCompletion(options?: UseCompletionOptions): UseCompletionReturn
|
|
798
|
+
```
|
|
799
|
+
|
|
800
|
+
| Option | Type | Description |
|
|
801
|
+
|--------|------|-------------|
|
|
802
|
+
| `systemPrompt` | `string` | System prompt for the AI |
|
|
803
|
+
| `onFinish` | `(response: LLMResponse) => void` | Callback when completion is done |
|
|
804
|
+
| `onError` | `(error: Error) => void` | Callback when an error occurs |
|
|
805
|
+
|
|
806
|
+
**Returns:**
|
|
807
|
+
|
|
808
|
+
| Property | Type | Description |
|
|
809
|
+
|----------|------|-------------|
|
|
810
|
+
| `completion` | `string` | The current completion text |
|
|
811
|
+
| `isLoading` | `boolean` | Whether a completion is in progress |
|
|
812
|
+
| `complete` | `(prompt: string) => Promise<string>` | Request a completion |
|
|
813
|
+
| `stop` | `() => void` | Stop the current completion |
|
|
814
|
+
| `error` | `Error \| null` | The most recent error, if any |
|
|
815
|
+
|
|
816
|
+
---
|
|
817
|
+
|
|
818
|
+
### `useOnDeviceAI()`
|
|
819
|
+
|
|
820
|
+
React hook to check if on-device AI is available. Caches the result across components.
|
|
821
|
+
|
|
822
|
+
```typescript
|
|
823
|
+
function useOnDeviceAI(): UseOnDeviceAIReturn
|
|
824
|
+
```
|
|
825
|
+
|
|
826
|
+
**Returns:**
|
|
827
|
+
|
|
828
|
+
| Property | Type | Description |
|
|
829
|
+
|----------|------|-------------|
|
|
830
|
+
| `isAvailable` | `boolean` | Whether on-device AI is available |
|
|
831
|
+
| `isChecking` | `boolean` | Whether the check is still in progress |
|
|
832
|
+
|
|
833
|
+
---
|
|
834
|
+
|
|
671
835
|
### `ChatMemoryManager`
|
|
672
836
|
|
|
673
837
|
Manages conversation history for stateless on-device AI models. Automatically handles turn limits and provides the full message array for each request.
|
|
@@ -851,6 +1015,45 @@ type LLMSuggestResponse = {
|
|
|
851
1015
|
raw: string;
|
|
852
1016
|
};
|
|
853
1017
|
|
|
1018
|
+
// Hook Types
|
|
1019
|
+
type UseChatOptions = {
|
|
1020
|
+
systemPrompt?: string;
|
|
1021
|
+
maxTurns?: number;
|
|
1022
|
+
initialMessages?: LLMMessage[];
|
|
1023
|
+
onFinish?: (response: LLMResponse) => void;
|
|
1024
|
+
onError?: (error: Error) => void;
|
|
1025
|
+
};
|
|
1026
|
+
|
|
1027
|
+
type UseChatReturn = {
|
|
1028
|
+
messages: LLMMessage[];
|
|
1029
|
+
input: string;
|
|
1030
|
+
setInput: (input: string) => void;
|
|
1031
|
+
sendMessage: (text?: string) => Promise<void>;
|
|
1032
|
+
isStreaming: boolean;
|
|
1033
|
+
stop: () => void;
|
|
1034
|
+
clear: () => void;
|
|
1035
|
+
error: Error | null;
|
|
1036
|
+
};
|
|
1037
|
+
|
|
1038
|
+
type UseCompletionOptions = {
|
|
1039
|
+
systemPrompt?: string;
|
|
1040
|
+
onFinish?: (response: LLMResponse) => void;
|
|
1041
|
+
onError?: (error: Error) => void;
|
|
1042
|
+
};
|
|
1043
|
+
|
|
1044
|
+
type UseCompletionReturn = {
|
|
1045
|
+
completion: string;
|
|
1046
|
+
isLoading: boolean;
|
|
1047
|
+
complete: (prompt: string) => Promise<string>;
|
|
1048
|
+
stop: () => void;
|
|
1049
|
+
error: Error | null;
|
|
1050
|
+
};
|
|
1051
|
+
|
|
1052
|
+
type UseOnDeviceAIReturn = {
|
|
1053
|
+
isAvailable: boolean;
|
|
1054
|
+
isChecking: boolean;
|
|
1055
|
+
};
|
|
1056
|
+
|
|
854
1057
|
// Chat Memory Types
|
|
855
1058
|
type ChatMemoryOptions = {
|
|
856
1059
|
/** Maximum conversation turns to keep (default: 10) */
|
|
@@ -877,6 +1080,7 @@ type ChatMemorySnapshot = {
|
|
|
877
1080
|
| Prompt helpers | ✅ | ✅ |
|
|
878
1081
|
| Smart suggestions | ✅ | ✅ |
|
|
879
1082
|
| `ChatMemoryManager` | ✅ | ✅ |
|
|
1083
|
+
| React Hooks (`useChat`, etc.) | ✅ | ✅ |
|
|
880
1084
|
| System prompts | ✅ Native | ✅ Prepended |
|
|
881
1085
|
| Multi-turn context | ✅ | ✅ |
|
|
882
1086
|
| Cancel streaming | ✅ | ✅ |
|
|
@@ -930,10 +1134,11 @@ const { text } = await sendMessage(messages, { systemPrompt: '...' });
|
|
|
930
1134
|
| ✅ Prompt helpers (summarize, translate, etc.) | Done | - |
|
|
931
1135
|
| ✅ Chat memory management | Done | - |
|
|
932
1136
|
| ✅ Smart suggestions (suggest, smartReply, autocomplete) | Done | - |
|
|
1137
|
+
| ✅ React Hooks (useChat, useCompletion, useOnDeviceAI) | Done | - |
|
|
933
1138
|
| Web/generic fallback | Idea | Medium |
|
|
934
1139
|
| Configurable hyperparameters (temperature, etc.) | Idea | Low |
|
|
935
1140
|
|
|
936
|
-
Have a feature request? [Open an issue](https://github.com/
|
|
1141
|
+
Have a feature request? [Open an issue](https://github.com/saidkaban/expo-ai-kit/issues)!
|
|
937
1142
|
|
|
938
1143
|
## License
|
|
939
1144
|
|
|
@@ -947,6 +1152,6 @@ Contributions are welcome! Please refer to guidelines described in the [contribu
|
|
|
947
1152
|
|
|
948
1153
|
- [Documentation](https://expo-ai-kit.com)
|
|
949
1154
|
- [npm package](https://www.npmjs.com/package/expo-ai-kit)
|
|
950
|
-
- [GitHub repository](https://github.com/
|
|
1155
|
+
- [GitHub repository](https://github.com/saidkaban/expo-ai-kit)
|
|
951
1156
|
- [Apple Foundation Models](https://developer.apple.com/documentation/foundationmodels)
|
|
952
1157
|
- [Google ML Kit Prompt API](https://developers.google.com/ml-kit/genai)
|
package/build/hooks.d.ts
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import type { UseChatOptions, UseChatReturn, UseCompletionOptions, UseCompletionReturn, UseOnDeviceAIReturn } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* React hook to check if on-device AI is available.
|
|
4
|
+
*
|
|
5
|
+
* Caches the result so multiple components don't re-check.
|
|
6
|
+
*
|
|
7
|
+
* @returns Object with isAvailable and isChecking states
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```tsx
|
|
11
|
+
* function MyComponent() {
|
|
12
|
+
* const { isAvailable, isChecking } = useOnDeviceAI();
|
|
13
|
+
*
|
|
14
|
+
* if (isChecking) return <Text>Checking AI availability...</Text>;
|
|
15
|
+
* if (!isAvailable) return <Text>On-device AI not available</Text>;
|
|
16
|
+
*
|
|
17
|
+
* return <ChatComponent />;
|
|
18
|
+
* }
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
export declare function useOnDeviceAI(): UseOnDeviceAIReturn;
|
|
22
|
+
/**
|
|
23
|
+
* React hook for building chat interfaces with on-device AI.
|
|
24
|
+
*
|
|
25
|
+
* Manages messages, input state, streaming, and conversation memory automatically.
|
|
26
|
+
* Built on top of ChatMemoryManager and streamMessage.
|
|
27
|
+
*
|
|
28
|
+
* @param options - Configuration options for the chat
|
|
29
|
+
* @returns Chat state and control functions
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* ```tsx
|
|
33
|
+
* function ChatScreen() {
|
|
34
|
+
* const { messages, input, setInput, sendMessage, isStreaming, stop } = useChat({
|
|
35
|
+
* systemPrompt: 'You are a helpful assistant.',
|
|
36
|
+
* });
|
|
37
|
+
*
|
|
38
|
+
* return (
|
|
39
|
+
* <View>
|
|
40
|
+
* <FlatList
|
|
41
|
+
* data={messages}
|
|
42
|
+
* renderItem={({ item }) => (
|
|
43
|
+
* <Text>{item.role}: {item.content}</Text>
|
|
44
|
+
* )}
|
|
45
|
+
* />
|
|
46
|
+
* <TextInput value={input} onChangeText={setInput} />
|
|
47
|
+
* {isStreaming ? (
|
|
48
|
+
* <Button title="Stop" onPress={stop} />
|
|
49
|
+
* ) : (
|
|
50
|
+
* <Button title="Send" onPress={() => sendMessage()} />
|
|
51
|
+
* )}
|
|
52
|
+
* </View>
|
|
53
|
+
* );
|
|
54
|
+
* }
|
|
55
|
+
* ```
|
|
56
|
+
*/
|
|
57
|
+
export declare function useChat(options?: UseChatOptions): UseChatReturn;
|
|
58
|
+
/**
|
|
59
|
+
* React hook for single-shot AI completions.
|
|
60
|
+
*
|
|
61
|
+
* Unlike useChat (which manages a conversation), useCompletion is for
|
|
62
|
+
* one-off tasks like summarization, translation, or content generation.
|
|
63
|
+
*
|
|
64
|
+
* @param options - Configuration options
|
|
65
|
+
* @returns Completion state and control functions
|
|
66
|
+
*
|
|
67
|
+
* @example
|
|
68
|
+
* ```tsx
|
|
69
|
+
* function SummarizerScreen() {
|
|
70
|
+
* const { completion, isLoading, complete, stop } = useCompletion({
|
|
71
|
+
* systemPrompt: 'You are a summarization assistant. Summarize the given text concisely.',
|
|
72
|
+
* });
|
|
73
|
+
*
|
|
74
|
+
* return (
|
|
75
|
+
* <View>
|
|
76
|
+
* <Button
|
|
77
|
+
* title="Summarize"
|
|
78
|
+
* onPress={() => complete('Long article text here...')}
|
|
79
|
+
* />
|
|
80
|
+
* {isLoading && <Button title="Stop" onPress={stop} />}
|
|
81
|
+
* <Text>{completion}</Text>
|
|
82
|
+
* </View>
|
|
83
|
+
* );
|
|
84
|
+
* }
|
|
85
|
+
* ```
|
|
86
|
+
*/
|
|
87
|
+
export declare function useCompletion(options?: UseCompletionOptions): UseCompletionReturn;
|
|
88
|
+
//# sourceMappingURL=hooks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../src/hooks.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAEV,cAAc,EACd,aAAa,EACb,oBAAoB,EACpB,mBAAmB,EACnB,mBAAmB,EACpB,MAAM,SAAS,CAAC;AAmBjB;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,aAAa,IAAI,mBAAmB,CAwBnD;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,wBAAgB,OAAO,CAAC,OAAO,GAAE,cAAmB,GAAG,aAAa,CA8GnE;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,aAAa,CAAC,OAAO,GAAE,oBAAyB,GAAG,mBAAmB,CAgFrF"}
|
package/build/hooks.js
ADDED
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
import { useState, useEffect, useRef, useCallback } from 'react';
|
|
2
|
+
import { isAvailable, streamMessage } from './index';
|
|
3
|
+
import { ChatMemoryManager } from './memory';
|
|
4
|
+
// Cache availability result across all hook instances
|
|
5
|
+
let availabilityCache = null;
|
|
6
|
+
let availabilityPromise = null;
|
|
7
|
+
function checkAvailability() {
|
|
8
|
+
if (availabilityCache !== null) {
|
|
9
|
+
return Promise.resolve(availabilityCache);
|
|
10
|
+
}
|
|
11
|
+
if (!availabilityPromise) {
|
|
12
|
+
availabilityPromise = isAvailable().then((result) => {
|
|
13
|
+
availabilityCache = result;
|
|
14
|
+
return result;
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
return availabilityPromise;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* React hook to check if on-device AI is available.
|
|
21
|
+
*
|
|
22
|
+
* Caches the result so multiple components don't re-check.
|
|
23
|
+
*
|
|
24
|
+
* @returns Object with isAvailable and isChecking states
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
* ```tsx
|
|
28
|
+
* function MyComponent() {
|
|
29
|
+
* const { isAvailable, isChecking } = useOnDeviceAI();
|
|
30
|
+
*
|
|
31
|
+
* if (isChecking) return <Text>Checking AI availability...</Text>;
|
|
32
|
+
* if (!isAvailable) return <Text>On-device AI not available</Text>;
|
|
33
|
+
*
|
|
34
|
+
* return <ChatComponent />;
|
|
35
|
+
* }
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
export function useOnDeviceAI() {
|
|
39
|
+
const [available, setAvailable] = useState(availabilityCache ?? false);
|
|
40
|
+
const [checking, setChecking] = useState(availabilityCache === null);
|
|
41
|
+
useEffect(() => {
|
|
42
|
+
if (availabilityCache !== null) {
|
|
43
|
+
setAvailable(availabilityCache);
|
|
44
|
+
setChecking(false);
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
let mounted = true;
|
|
48
|
+
checkAvailability().then((result) => {
|
|
49
|
+
if (mounted) {
|
|
50
|
+
setAvailable(result);
|
|
51
|
+
setChecking(false);
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
return () => {
|
|
55
|
+
mounted = false;
|
|
56
|
+
};
|
|
57
|
+
}, []);
|
|
58
|
+
return { isAvailable: available, isChecking: checking };
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* React hook for building chat interfaces with on-device AI.
|
|
62
|
+
*
|
|
63
|
+
* Manages messages, input state, streaming, and conversation memory automatically.
|
|
64
|
+
* Built on top of ChatMemoryManager and streamMessage.
|
|
65
|
+
*
|
|
66
|
+
* @param options - Configuration options for the chat
|
|
67
|
+
* @returns Chat state and control functions
|
|
68
|
+
*
|
|
69
|
+
* @example
|
|
70
|
+
* ```tsx
|
|
71
|
+
* function ChatScreen() {
|
|
72
|
+
* const { messages, input, setInput, sendMessage, isStreaming, stop } = useChat({
|
|
73
|
+
* systemPrompt: 'You are a helpful assistant.',
|
|
74
|
+
* });
|
|
75
|
+
*
|
|
76
|
+
* return (
|
|
77
|
+
* <View>
|
|
78
|
+
* <FlatList
|
|
79
|
+
* data={messages}
|
|
80
|
+
* renderItem={({ item }) => (
|
|
81
|
+
* <Text>{item.role}: {item.content}</Text>
|
|
82
|
+
* )}
|
|
83
|
+
* />
|
|
84
|
+
* <TextInput value={input} onChangeText={setInput} />
|
|
85
|
+
* {isStreaming ? (
|
|
86
|
+
* <Button title="Stop" onPress={stop} />
|
|
87
|
+
* ) : (
|
|
88
|
+
* <Button title="Send" onPress={() => sendMessage()} />
|
|
89
|
+
* )}
|
|
90
|
+
* </View>
|
|
91
|
+
* );
|
|
92
|
+
* }
|
|
93
|
+
* ```
|
|
94
|
+
*/
|
|
95
|
+
export function useChat(options = {}) {
|
|
96
|
+
const { systemPrompt, maxTurns, initialMessages, onFinish, onError } = options;
|
|
97
|
+
const memoryRef = useRef(new ChatMemoryManager({ maxTurns, systemPrompt }));
|
|
98
|
+
// Initialize with initial messages
|
|
99
|
+
const initializedRef = useRef(false);
|
|
100
|
+
if (!initializedRef.current && initialMessages) {
|
|
101
|
+
for (const msg of initialMessages) {
|
|
102
|
+
memoryRef.current.addMessage(msg);
|
|
103
|
+
}
|
|
104
|
+
initializedRef.current = true;
|
|
105
|
+
}
|
|
106
|
+
const [messages, setMessages] = useState(memoryRef.current.getMessages());
|
|
107
|
+
const [input, setInput] = useState('');
|
|
108
|
+
const [isStreaming, setIsStreaming] = useState(false);
|
|
109
|
+
const [error, setError] = useState(null);
|
|
110
|
+
const stopRef = useRef(null);
|
|
111
|
+
const mountedRef = useRef(true);
|
|
112
|
+
const inputRef = useRef(input);
|
|
113
|
+
inputRef.current = input;
|
|
114
|
+
const streamingRef = useRef(isStreaming);
|
|
115
|
+
streamingRef.current = isStreaming;
|
|
116
|
+
const onFinishRef = useRef(onFinish);
|
|
117
|
+
onFinishRef.current = onFinish;
|
|
118
|
+
const onErrorRef = useRef(onError);
|
|
119
|
+
onErrorRef.current = onError;
|
|
120
|
+
useEffect(() => {
|
|
121
|
+
return () => {
|
|
122
|
+
mountedRef.current = false;
|
|
123
|
+
stopRef.current?.();
|
|
124
|
+
};
|
|
125
|
+
}, []);
|
|
126
|
+
const send = useCallback(async (text) => {
|
|
127
|
+
const content = (text ?? inputRef.current).trim();
|
|
128
|
+
if (!content || streamingRef.current)
|
|
129
|
+
return;
|
|
130
|
+
setError(null);
|
|
131
|
+
// Add user message
|
|
132
|
+
memoryRef.current.addUserMessage(content);
|
|
133
|
+
setMessages([...memoryRef.current.getMessages()]);
|
|
134
|
+
if (!text)
|
|
135
|
+
setInput('');
|
|
136
|
+
setIsStreaming(true);
|
|
137
|
+
try {
|
|
138
|
+
const allMessages = memoryRef.current.getAllMessages();
|
|
139
|
+
// Use a temporary message for streaming display
|
|
140
|
+
let accumulatedText = '';
|
|
141
|
+
const { promise, stop } = streamMessage(allMessages, (event) => {
|
|
142
|
+
if (!mountedRef.current)
|
|
143
|
+
return;
|
|
144
|
+
accumulatedText = event.accumulatedText;
|
|
145
|
+
// Update messages with streaming assistant response
|
|
146
|
+
const currentMessages = memoryRef.current.getMessages();
|
|
147
|
+
setMessages([
|
|
148
|
+
...currentMessages,
|
|
149
|
+
{ role: 'assistant', content: accumulatedText },
|
|
150
|
+
]);
|
|
151
|
+
});
|
|
152
|
+
stopRef.current = stop;
|
|
153
|
+
const response = await promise;
|
|
154
|
+
if (!mountedRef.current)
|
|
155
|
+
return;
|
|
156
|
+
// Add the final assistant message to memory
|
|
157
|
+
memoryRef.current.addAssistantMessage(response.text);
|
|
158
|
+
setMessages([...memoryRef.current.getMessages()]);
|
|
159
|
+
onFinishRef.current?.(response);
|
|
160
|
+
}
|
|
161
|
+
catch (err) {
|
|
162
|
+
if (!mountedRef.current)
|
|
163
|
+
return;
|
|
164
|
+
const e = err instanceof Error ? err : new Error(String(err));
|
|
165
|
+
setError(e);
|
|
166
|
+
onErrorRef.current?.(e);
|
|
167
|
+
}
|
|
168
|
+
finally {
|
|
169
|
+
stopRef.current = null;
|
|
170
|
+
if (mountedRef.current) {
|
|
171
|
+
setIsStreaming(false);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}, []);
|
|
175
|
+
const stop = useCallback(() => {
|
|
176
|
+
stopRef.current?.();
|
|
177
|
+
}, []);
|
|
178
|
+
const clear = useCallback(() => {
|
|
179
|
+
memoryRef.current.clear();
|
|
180
|
+
setMessages([]);
|
|
181
|
+
setError(null);
|
|
182
|
+
}, []);
|
|
183
|
+
return {
|
|
184
|
+
messages,
|
|
185
|
+
input,
|
|
186
|
+
setInput,
|
|
187
|
+
sendMessage: send,
|
|
188
|
+
isStreaming,
|
|
189
|
+
stop,
|
|
190
|
+
clear,
|
|
191
|
+
error,
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* React hook for single-shot AI completions.
|
|
196
|
+
*
|
|
197
|
+
* Unlike useChat (which manages a conversation), useCompletion is for
|
|
198
|
+
* one-off tasks like summarization, translation, or content generation.
|
|
199
|
+
*
|
|
200
|
+
* @param options - Configuration options
|
|
201
|
+
* @returns Completion state and control functions
|
|
202
|
+
*
|
|
203
|
+
* @example
|
|
204
|
+
* ```tsx
|
|
205
|
+
* function SummarizerScreen() {
|
|
206
|
+
* const { completion, isLoading, complete, stop } = useCompletion({
|
|
207
|
+
* systemPrompt: 'You are a summarization assistant. Summarize the given text concisely.',
|
|
208
|
+
* });
|
|
209
|
+
*
|
|
210
|
+
* return (
|
|
211
|
+
* <View>
|
|
212
|
+
* <Button
|
|
213
|
+
* title="Summarize"
|
|
214
|
+
* onPress={() => complete('Long article text here...')}
|
|
215
|
+
* />
|
|
216
|
+
* {isLoading && <Button title="Stop" onPress={stop} />}
|
|
217
|
+
* <Text>{completion}</Text>
|
|
218
|
+
* </View>
|
|
219
|
+
* );
|
|
220
|
+
* }
|
|
221
|
+
* ```
|
|
222
|
+
*/
|
|
223
|
+
export function useCompletion(options = {}) {
|
|
224
|
+
const { systemPrompt, onFinish, onError } = options;
|
|
225
|
+
const [completion, setCompletion] = useState('');
|
|
226
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
227
|
+
const [error, setError] = useState(null);
|
|
228
|
+
const stopRef = useRef(null);
|
|
229
|
+
const mountedRef = useRef(true);
|
|
230
|
+
const loadingRef = useRef(isLoading);
|
|
231
|
+
loadingRef.current = isLoading;
|
|
232
|
+
const completionRef = useRef(completion);
|
|
233
|
+
completionRef.current = completion;
|
|
234
|
+
const systemPromptRef = useRef(systemPrompt);
|
|
235
|
+
systemPromptRef.current = systemPrompt;
|
|
236
|
+
const onFinishRef = useRef(onFinish);
|
|
237
|
+
onFinishRef.current = onFinish;
|
|
238
|
+
const onErrorRef = useRef(onError);
|
|
239
|
+
onErrorRef.current = onError;
|
|
240
|
+
useEffect(() => {
|
|
241
|
+
return () => {
|
|
242
|
+
mountedRef.current = false;
|
|
243
|
+
stopRef.current?.();
|
|
244
|
+
};
|
|
245
|
+
}, []);
|
|
246
|
+
const complete = useCallback(async (prompt) => {
|
|
247
|
+
if (loadingRef.current)
|
|
248
|
+
return completionRef.current;
|
|
249
|
+
setError(null);
|
|
250
|
+
setCompletion('');
|
|
251
|
+
setIsLoading(true);
|
|
252
|
+
try {
|
|
253
|
+
const messages = [{ role: 'user', content: prompt }];
|
|
254
|
+
const { promise, stop } = streamMessage(messages, (event) => {
|
|
255
|
+
if (!mountedRef.current)
|
|
256
|
+
return;
|
|
257
|
+
setCompletion(event.accumulatedText);
|
|
258
|
+
}, systemPromptRef.current ? { systemPrompt: systemPromptRef.current } : undefined);
|
|
259
|
+
stopRef.current = stop;
|
|
260
|
+
const response = await promise;
|
|
261
|
+
if (!mountedRef.current)
|
|
262
|
+
return '';
|
|
263
|
+
setCompletion(response.text);
|
|
264
|
+
onFinishRef.current?.(response);
|
|
265
|
+
return response.text;
|
|
266
|
+
}
|
|
267
|
+
catch (err) {
|
|
268
|
+
if (!mountedRef.current)
|
|
269
|
+
return '';
|
|
270
|
+
const e = err instanceof Error ? err : new Error(String(err));
|
|
271
|
+
setError(e);
|
|
272
|
+
onErrorRef.current?.(e);
|
|
273
|
+
return '';
|
|
274
|
+
}
|
|
275
|
+
finally {
|
|
276
|
+
stopRef.current = null;
|
|
277
|
+
if (mountedRef.current) {
|
|
278
|
+
setIsLoading(false);
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
}, []);
|
|
282
|
+
const stop = useCallback(() => {
|
|
283
|
+
stopRef.current?.();
|
|
284
|
+
}, []);
|
|
285
|
+
return {
|
|
286
|
+
completion,
|
|
287
|
+
isLoading,
|
|
288
|
+
complete,
|
|
289
|
+
stop,
|
|
290
|
+
error,
|
|
291
|
+
};
|
|
292
|
+
}
|
|
293
|
+
//# sourceMappingURL=hooks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hooks.js","sourceRoot":"","sources":["../src/hooks.ts"],"names":[],"mappings":"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","sourcesContent":["import { useState, useEffect, useRef, useCallback } from 'react';\nimport { isAvailable, streamMessage } from './index';\nimport { ChatMemoryManager } from './memory';\nimport type {\n LLMMessage,\n UseChatOptions,\n UseChatReturn,\n UseCompletionOptions,\n UseCompletionReturn,\n UseOnDeviceAIReturn,\n} from './types';\n\n// Cache availability result across all hook instances\nlet availabilityCache: boolean | null = null;\nlet availabilityPromise: Promise<boolean> | null = null;\n\nfunction checkAvailability(): Promise<boolean> {\n if (availabilityCache !== null) {\n return Promise.resolve(availabilityCache);\n }\n if (!availabilityPromise) {\n availabilityPromise = isAvailable().then((result) => {\n availabilityCache = result;\n return result;\n });\n }\n return availabilityPromise;\n}\n\n/**\n * React hook to check if on-device AI is available.\n *\n * Caches the result so multiple components don't re-check.\n *\n * @returns Object with isAvailable and isChecking states\n *\n * @example\n * ```tsx\n * function MyComponent() {\n * const { isAvailable, isChecking } = useOnDeviceAI();\n *\n * if (isChecking) return <Text>Checking AI availability...</Text>;\n * if (!isAvailable) return <Text>On-device AI not available</Text>;\n *\n * return <ChatComponent />;\n * }\n * ```\n */\nexport function useOnDeviceAI(): UseOnDeviceAIReturn {\n const [available, setAvailable] = useState(availabilityCache ?? false);\n const [checking, setChecking] = useState(availabilityCache === null);\n\n useEffect(() => {\n if (availabilityCache !== null) {\n setAvailable(availabilityCache);\n setChecking(false);\n return;\n }\n\n let mounted = true;\n checkAvailability().then((result) => {\n if (mounted) {\n setAvailable(result);\n setChecking(false);\n }\n });\n return () => {\n mounted = false;\n };\n }, []);\n\n return { isAvailable: available, isChecking: checking };\n}\n\n/**\n * React hook for building chat interfaces with on-device AI.\n *\n * Manages messages, input state, streaming, and conversation memory automatically.\n * Built on top of ChatMemoryManager and streamMessage.\n *\n * @param options - Configuration options for the chat\n * @returns Chat state and control functions\n *\n * @example\n * ```tsx\n * function ChatScreen() {\n * const { messages, input, setInput, sendMessage, isStreaming, stop } = useChat({\n * systemPrompt: 'You are a helpful assistant.',\n * });\n *\n * return (\n * <View>\n * <FlatList\n * data={messages}\n * renderItem={({ item }) => (\n * <Text>{item.role}: {item.content}</Text>\n * )}\n * />\n * <TextInput value={input} onChangeText={setInput} />\n * {isStreaming ? (\n * <Button title=\"Stop\" onPress={stop} />\n * ) : (\n * <Button title=\"Send\" onPress={() => sendMessage()} />\n * )}\n * </View>\n * );\n * }\n * ```\n */\nexport function useChat(options: UseChatOptions = {}): UseChatReturn {\n const { systemPrompt, maxTurns, initialMessages, onFinish, onError } = options;\n\n const memoryRef = useRef(new ChatMemoryManager({ maxTurns, systemPrompt }));\n\n // Initialize with initial messages\n const initializedRef = useRef(false);\n if (!initializedRef.current && initialMessages) {\n for (const msg of initialMessages) {\n memoryRef.current.addMessage(msg);\n }\n initializedRef.current = true;\n }\n\n const [messages, setMessages] = useState<LLMMessage[]>(memoryRef.current.getMessages());\n const [input, setInput] = useState('');\n const [isStreaming, setIsStreaming] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n const stopRef = useRef<(() => void) | null>(null);\n const mountedRef = useRef(true);\n const inputRef = useRef(input);\n inputRef.current = input;\n const streamingRef = useRef(isStreaming);\n streamingRef.current = isStreaming;\n const onFinishRef = useRef(onFinish);\n onFinishRef.current = onFinish;\n const onErrorRef = useRef(onError);\n onErrorRef.current = onError;\n\n useEffect(() => {\n return () => {\n mountedRef.current = false;\n stopRef.current?.();\n };\n }, []);\n\n const send = useCallback(\n async (text?: string) => {\n const content = (text ?? inputRef.current).trim();\n if (!content || streamingRef.current) return;\n\n setError(null);\n\n // Add user message\n memoryRef.current.addUserMessage(content);\n setMessages([...memoryRef.current.getMessages()]);\n if (!text) setInput('');\n\n setIsStreaming(true);\n\n try {\n const allMessages = memoryRef.current.getAllMessages();\n\n // Use a temporary message for streaming display\n let accumulatedText = '';\n const { promise, stop } = streamMessage(allMessages, (event) => {\n if (!mountedRef.current) return;\n accumulatedText = event.accumulatedText;\n // Update messages with streaming assistant response\n const currentMessages = memoryRef.current.getMessages();\n setMessages([\n ...currentMessages,\n { role: 'assistant' as const, content: accumulatedText },\n ]);\n });\n\n stopRef.current = stop;\n const response = await promise;\n\n if (!mountedRef.current) return;\n\n // Add the final assistant message to memory\n memoryRef.current.addAssistantMessage(response.text);\n setMessages([...memoryRef.current.getMessages()]);\n onFinishRef.current?.(response);\n } catch (err) {\n if (!mountedRef.current) return;\n const e = err instanceof Error ? err : new Error(String(err));\n setError(e);\n onErrorRef.current?.(e);\n } finally {\n stopRef.current = null;\n if (mountedRef.current) {\n setIsStreaming(false);\n }\n }\n },\n []\n );\n\n const stop = useCallback(() => {\n stopRef.current?.();\n }, []);\n\n const clear = useCallback(() => {\n memoryRef.current.clear();\n setMessages([]);\n setError(null);\n }, []);\n\n return {\n messages,\n input,\n setInput,\n sendMessage: send,\n isStreaming,\n stop,\n clear,\n error,\n };\n}\n\n/**\n * React hook for single-shot AI completions.\n *\n * Unlike useChat (which manages a conversation), useCompletion is for\n * one-off tasks like summarization, translation, or content generation.\n *\n * @param options - Configuration options\n * @returns Completion state and control functions\n *\n * @example\n * ```tsx\n * function SummarizerScreen() {\n * const { completion, isLoading, complete, stop } = useCompletion({\n * systemPrompt: 'You are a summarization assistant. Summarize the given text concisely.',\n * });\n *\n * return (\n * <View>\n * <Button\n * title=\"Summarize\"\n * onPress={() => complete('Long article text here...')}\n * />\n * {isLoading && <Button title=\"Stop\" onPress={stop} />}\n * <Text>{completion}</Text>\n * </View>\n * );\n * }\n * ```\n */\nexport function useCompletion(options: UseCompletionOptions = {}): UseCompletionReturn {\n const { systemPrompt, onFinish, onError } = options;\n\n const [completion, setCompletion] = useState('');\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n const stopRef = useRef<(() => void) | null>(null);\n const mountedRef = useRef(true);\n const loadingRef = useRef(isLoading);\n loadingRef.current = isLoading;\n const completionRef = useRef(completion);\n completionRef.current = completion;\n const systemPromptRef = useRef(systemPrompt);\n systemPromptRef.current = systemPrompt;\n const onFinishRef = useRef(onFinish);\n onFinishRef.current = onFinish;\n const onErrorRef = useRef(onError);\n onErrorRef.current = onError;\n\n useEffect(() => {\n return () => {\n mountedRef.current = false;\n stopRef.current?.();\n };\n }, []);\n\n const complete = useCallback(\n async (prompt: string) => {\n if (loadingRef.current) return completionRef.current;\n\n setError(null);\n setCompletion('');\n setIsLoading(true);\n\n try {\n const messages: LLMMessage[] = [{ role: 'user', content: prompt }];\n const { promise, stop } = streamMessage(\n messages,\n (event) => {\n if (!mountedRef.current) return;\n setCompletion(event.accumulatedText);\n },\n systemPromptRef.current ? { systemPrompt: systemPromptRef.current } : undefined\n );\n\n stopRef.current = stop;\n const response = await promise;\n\n if (!mountedRef.current) return '';\n\n setCompletion(response.text);\n onFinishRef.current?.(response);\n return response.text;\n } catch (err) {\n if (!mountedRef.current) return '';\n const e = err instanceof Error ? err : new Error(String(err));\n setError(e);\n onErrorRef.current?.(e);\n return '';\n } finally {\n stopRef.current = null;\n if (mountedRef.current) {\n setIsLoading(false);\n }\n }\n },\n []\n );\n\n const stop = useCallback(() => {\n stopRef.current?.();\n }, []);\n\n return {\n completion,\n isLoading,\n complete,\n stop,\n error,\n };\n}\n"]}
|
package/build/index.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { LLMMessage, LLMSendOptions, LLMResponse, LLMStreamOptions, LLMStreamCallback, LLMSummarizeOptions, LLMTranslateOptions, LLMRewriteOptions, LLMExtractKeyPointsOptions, LLMAnswerQuestionOptions, LLMSuggestOptions, LLMSuggestResponse, LLMSmartReplyOptions, LLMAutocompleteOptions } from './types';
|
|
2
2
|
export * from './types';
|
|
3
3
|
export * from './memory';
|
|
4
|
+
export * from './hooks';
|
|
4
5
|
/**
|
|
5
6
|
* Check if on-device AI is available on the current device.
|
|
6
7
|
* Returns false on unsupported platforms (web, etc.).
|