diff --git a/packages/firebase_dynamic_links/README.md b/packages/firebase_dynamic_links/README.md deleted file mode 100644 index df2b0cde1d15..000000000000 --- a/packages/firebase_dynamic_links/README.md +++ /dev/null @@ -1,27 +0,0 @@ -# Firebase Dynamic Links - -⚠️ **DEPRECATED** ⚠️ - -This package has been deprecated and removed from the FlutterFire repository. - -## Why was it deprecated? - -Firebase Dynamic Links has been deprecated by Google and will be shut down on August 25th, 2025. For more information about the deprecation and migration options, please visit: - -**[Firebase Dynamic Links Deprecation FAQ](https://firebase.google.com/support/dynamic-links-faq)** - -## Migration Options - -The deprecation FAQ provides detailed guidance on how to migrate from Firebase Dynamic Links, including: - -- **Full feature parity**: Use alternative deep-linking service providers -- **Simple deep-linking**: Migrate to App Links and Universal Links -- **No replacement needed**: Remove the package entirely - -## Timeline - -- **August 25th, 2025**: Firebase Dynamic Links service will be completely shut down -- All existing links will stop working -- All APIs will return error responses - -Please refer to the official deprecation FAQ for complete migration guidance and support. \ No newline at end of file diff --git a/packages/firebase_vertexai/README.md b/packages/firebase_vertexai/README.md new file mode 100644 index 000000000000..cee1314420b2 --- /dev/null +++ b/packages/firebase_vertexai/README.md @@ -0,0 +1,39 @@ +# Firebase Vertex AI + +⚠️ **DEPRECATED** ⚠️ + +This package has been deprecated and replaced by the Firebase AI Logic package. + +## Why was it deprecated? + +The "Vertex AI in Firebase" SDK has been replaced by the Firebase AI Logic client SDKs to accommodate the evolving set of supported features and services. The new Firebase AI Logic SDK provides better alignment across platforms and improved functionality. + +## Migration Options + +Migrate to the new Firebase AI Logic package (`firebase_ai`) which provides: + +- **Enhanced functionality**: Access to the latest AI features and models +- **Better platform alignment**: Consistent APIs across all supported platforms +- **Improved performance**: Optimized for modern AI workloads +- **Future-proof**: Active development and support + +## Migration Guide + +For detailed migration instructions, please visit: + +**[Firebase AI Logic Migration Guide](https://firebase.google.com/docs/ai-logic/migrate-from-preview?api=dev)** + +The migration guide covers: +- API changes and breaking changes +- Code migration examples +- Platform-specific migration notes +- Troubleshooting common issues + +## Next Steps + +1. **Install the new package**: Add `firebase_ai` to your `pubspec.yaml` +2. **Update your code**: Follow the migration guide to update your implementation +3. **Test thoroughly**: Ensure all functionality works as expected +4. **Remove old package**: Remove `firebase_vertexai` from your dependencies + +Please refer to the official migration guide for complete migration guidance and support. \ No newline at end of file diff --git a/packages/firebase_vertexai/all_lint_rules.yaml b/packages/firebase_vertexai/all_lint_rules.yaml deleted file mode 100644 index dc4ec3a951c3..000000000000 --- a/packages/firebase_vertexai/all_lint_rules.yaml +++ /dev/null @@ -1,183 +0,0 @@ -# Copyright 2021 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# in the LICENSE file. - -linter: - rules: - - always_declare_return_types - - always_put_control_body_on_new_line - - always_put_required_named_parameters_first - - always_require_non_null_named_parameters - - always_specify_types - - always_use_package_imports - - annotate_overrides - - avoid_annotating_with_dynamic - - avoid_bool_literals_in_conditional_expressions - - avoid_catches_without_on_clauses - - avoid_catching_errors - - avoid_classes_with_only_static_members - - avoid_double_and_int_checks - - avoid_empty_else - - avoid_equals_and_hash_code_on_mutable_classes - - avoid_escaping_inner_quotes - - avoid_field_initializers_in_const_classes - - avoid_function_literals_in_foreach_calls - - avoid_implementing_value_types - - avoid_init_to_null - - avoid_js_rounded_ints - - avoid_null_checks_in_equality_operators - - avoid_positional_boolean_parameters - - avoid_print - - avoid_private_typedef_functions - - avoid_redundant_argument_values - - avoid_relative_lib_imports - - avoid_renaming_method_parameters - - avoid_return_types_on_setters - - avoid_returning_null - - avoid_returning_null_for_future - - avoid_returning_null_for_void - - avoid_returning_this - - avoid_setters_without_getters - - avoid_shadowing_type_parameters - - avoid_single_cascade_in_expression_statements - - avoid_slow_async_io - - avoid_type_to_string - - avoid_types_as_parameter_names - - avoid_types_on_closure_parameters - - avoid_unnecessary_containers - - avoid_unused_constructor_parameters - - avoid_void_async - - avoid_web_libraries_in_flutter - - await_only_futures - - camel_case_extensions - - camel_case_types - - cancel_subscriptions - - cascade_invocations - - cast_nullable_to_non_nullable - - close_sinks - - comment_references - - constant_identifier_names - - control_flow_in_finally - - curly_braces_in_flow_control_structures - - diagnostic_describe_all_properties - - directives_ordering - - do_not_use_environment - - empty_catches - - empty_constructor_bodies - - empty_statements - - exhaustive_cases - - file_names - - flutter_style_todos - - hash_and_equals - - implementation_imports - - invariant_booleans - - iterable_contains_unrelated_type - - join_return_with_assignment - - leading_newlines_in_multiline_strings - - library_names - - library_prefixes - - lines_longer_than_80_chars - - list_remove_unrelated_type - - literal_only_boolean_expressions - - missing_whitespace_between_adjacent_strings - - no_adjacent_strings_in_list - - no_default_cases - - no_duplicate_case_values - - no_logic_in_create_state - - no_runtimeType_toString - - non_constant_identifier_names - - null_check_on_nullable_type_parameter - - null_closures - - omit_local_variable_types - - one_member_abstracts - - only_throw_errors - - overridden_fields - - package_api_docs - - package_names - - package_prefixed_library_names - - parameter_assignments - - prefer_adjacent_string_concatenation - - prefer_asserts_in_initializer_lists - - prefer_asserts_with_message - - prefer_collection_literals - - prefer_conditional_assignment - - prefer_const_constructors - - prefer_const_constructors_in_immutables - - prefer_const_declarations - - prefer_const_literals_to_create_immutables - - prefer_constructors_over_static_methods - - prefer_contains - - prefer_double_quotes - - prefer_equal_for_default_values - - prefer_expression_function_bodies - - prefer_final_fields - - prefer_final_in_for_each - - prefer_final_locals - - prefer_for_elements_to_map_fromIterable - - prefer_foreach - - prefer_function_declarations_over_variables - - prefer_generic_function_type_aliases - - prefer_if_elements_to_conditional_expressions - - prefer_if_null_operators - - prefer_initializing_formals - - prefer_inlined_adds - - prefer_int_literals - - prefer_interpolation_to_compose_strings - - prefer_is_empty - - prefer_is_not_empty - - prefer_is_not_operator - - prefer_iterable_whereType - - prefer_mixin - - prefer_null_aware_operators - - prefer_relative_imports - - prefer_single_quotes - - prefer_spread_collections - - prefer_typing_uninitialized_variables - - prefer_void_to_null - - provide_deprecation_message - - public_member_api_docs - - recursive_getters - - sized_box_for_whitespace - - slash_for_doc_comments - - sort_child_properties_last - - sort_constructors_first - - sort_pub_dependencies - - sort_unnamed_constructors_first - - test_types_in_equals - - throw_in_finally - - tighten_type_of_initializing_formals - - type_annotate_public_apis - - type_init_formals - - unawaited_futures - - unnecessary_await_in_return - - unnecessary_brace_in_string_interps - - unnecessary_const - - unnecessary_final - - unnecessary_getters_setters - - unnecessary_lambdas - - unnecessary_new - - unnecessary_null_aware_assignments - - unnecessary_null_checks - - unnecessary_null_in_if_null_operators - - unnecessary_nullable_for_final_variable_declarations - - unnecessary_overrides - - unnecessary_parenthesis - - unnecessary_raw_strings - - unnecessary_statements - - unnecessary_string_escapes - - unnecessary_string_interpolations - - unnecessary_this - - unrelated_type_equality_checks - - unsafe_html - - use_full_hex_values_for_flutter_colors - - use_function_type_syntax_for_parameters - - use_is_even_rather_than_modulo - - use_key_in_widget_constructors - - use_late_for_private_fields_and_variables - - use_raw_strings - - use_rethrow_when_possible - - use_setters_to_change_properties - - use_string_buffers - - use_to_and_as_if_applicable - - valid_regexps - - void_checks diff --git a/packages/firebase_vertexai/analysis_options.yaml b/packages/firebase_vertexai/analysis_options.yaml deleted file mode 100644 index ef9d047bb7f0..000000000000 --- a/packages/firebase_vertexai/analysis_options.yaml +++ /dev/null @@ -1,89 +0,0 @@ -# Copyright 2021 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# in the LICENSE file. - -include: all_lint_rules.yaml -analyzer: - # TODO(rrousselGit): disable implicit-cast/implicit-dynamic - errors: - # Otherwise cause the import of all_lint_rules to warn because of some rules conflicts. - # We explicitly enabled even conflicting rules and are fixing the conflict - # in this file - included_file_warning: ignore - deprecated_member_use_from_same_package: ignore - -linter: - rules: - ## Disabled rules because the repository doesn't respect them (yet) - - always_put_control_body_on_new_line: false - comment_references: false - prefer_constructors_over_static_methods: false - prefer_final_fields: false - prefer_final_locals: false - omit_local_variable_types: false - avoid_equals_and_hash_code_on_mutable_classes: false - - ############# - - # Personal preference. I don't find it more readable - cascade_invocations: false - - # Conflicts with `prefer_single_quotes` - # Single quotes are easier to type and don't compromise on readability. - prefer_double_quotes: false - - # Conflicts with `omit_local_variable_types` and other rules. - # As per Dart guidelines, we want to avoid unnecessary types to make the code - # more readable. - # See https://dart.dev/guides/language/effective-dart/design#avoid-type-annotating-initialized-local-variables - always_specify_types: false - - # Incompatible with `prefer_final_locals` - # Having immutable local variables makes larger functions more predictable - # so we will use `prefer_final_locals` instead. - unnecessary_final: false - - # Not quite suitable for Flutter, which may have a `build` method with a single - # return, but that return is still complex enough that a "body" is worth it. - prefer_expression_function_bodies: false - - # Conflicts with the convention used by flutter, which puts `Key key` - # and `@required Widget child` last. - always_put_required_named_parameters_first: false - - # This project doesn't use Flutter-style todos - flutter_style_todos: false - - # There are situations where we voluntarily want to catch everything, - # especially as a library. - avoid_catches_without_on_clauses: false - - # Boring as it sometimes force a line of 81 characters to be split in two. - # As long as we try to respect that 80 characters limit, going slightly - # above is fine. - lines_longer_than_80_chars: false - - # Conflicts with disabling `implicit-dynamic` - avoid_annotating_with_dynamic: false - - # conflicts with `prefer_relative_imports` - always_use_package_imports: false - - # Disabled for now until we have NNBD as it otherwise conflicts with `missing_return` - no_default_cases: false - - # False positive, null checks don't need a message - prefer_asserts_with_message: false - - # Cumbersome with `context.select` - avoid_types_on_closure_parameters: false - - # Too many false positive (builders) - diagnostic_describe_all_properties: false - - # false positives (setter-like functions) - avoid_positional_boolean_parameters: false - - # Does not apply to providers - prefer_const_constructors_in_immutables: false diff --git a/packages/firebase_vertexai/firebase_vertexai/.gitignore b/packages/firebase_vertexai/firebase_vertexai/.gitignore deleted file mode 100644 index ac5aa9893e48..000000000000 --- a/packages/firebase_vertexai/firebase_vertexai/.gitignore +++ /dev/null @@ -1,29 +0,0 @@ -# Miscellaneous -*.class -*.log -*.pyc -*.swp -.DS_Store -.atom/ -.buildlog/ -.history -.svn/ -migrate_working_dir/ - -# IntelliJ related -*.iml -*.ipr -*.iws -.idea/ - -# The .vscode folder contains launch configuration and tasks you configure in -# VS Code which you may wish to be included in version control, so this line -# is commented out by default. -#.vscode/ - -# Flutter/Dart/Pub related -# Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock. -/pubspec.lock -**/doc/api/ -.dart_tool/ -build/ diff --git a/packages/firebase_vertexai/firebase_vertexai/.metadata b/packages/firebase_vertexai/firebase_vertexai/.metadata deleted file mode 100644 index f1665318eeba..000000000000 --- a/packages/firebase_vertexai/firebase_vertexai/.metadata +++ /dev/null @@ -1,10 +0,0 @@ -# This file tracks properties of this Flutter project. -# Used by Flutter tool to assess capabilities and perform upgrades etc. -# -# This file should be version controlled and should not be manually edited. - -version: - revision: "b7e7d46a046ba8a22897a514bf2311a0f81ab198" - channel: "beta" - -project_type: package diff --git a/packages/firebase_vertexai/firebase_vertexai/CHANGELOG.md b/packages/firebase_vertexai/firebase_vertexai/CHANGELOG.md deleted file mode 100644 index 161c8c754f8c..000000000000 --- a/packages/firebase_vertexai/firebase_vertexai/CHANGELOG.md +++ /dev/null @@ -1,167 +0,0 @@ -## 2.2.0 - - - **FIX**(firebaseai): remove candidateCount from LiveGenerationConfig since the connection fails silently when it is set ([#17647](https://github.com/firebase/flutterfire/issues/17647)). ([537a3c30](https://github.com/firebase/flutterfire/commit/537a3c30397a82459c02dfdd70e3a9670c26fd59)) - - **FEAT**(firebaseai): add thinking feature ([#17652](https://github.com/firebase/flutterfire/issues/17652)). ([5faec2c1](https://github.com/firebase/flutterfire/commit/5faec2c1ddf0682ef9d88fb2d354f5f3f22405fa)) - - **FEAT**(firebaseai): imagen editing ([#17556](https://github.com/firebase/flutterfire/issues/17556)). ([62811a61](https://github.com/firebase/flutterfire/commit/62811a61354d412c6322bd68004b8d1537e3e483)) - -## 2.1.0 - - - **FEAT**(firebaseai): make Live API working with developer API ([#17503](https://github.com/firebase/flutterfire/issues/17503)). ([467eaa18](https://github.com/firebase/flutterfire/commit/467eaa1810257a420039d29a070314784218a03f)) - - **FEAT**(firebaseai): handle unknown parts when parsing content ([#17522](https://github.com/firebase/flutterfire/issues/17522)). ([ac59c249](https://github.com/firebase/flutterfire/commit/ac59c249ade0388b9b375766fb6c2f1b0c4daddd)) - -## 2.0.0 - -> Note: This release has breaking changes. - - - **BREAKING** **FEAT**: bump iOS SDK to version 12.0.0 ([#17549](https://github.com/firebase/flutterfire/issues/17549)). ([b2619e68](https://github.com/firebase/flutterfire/commit/b2619e685fec897513483df1d7be347b64f95606)) - -## 1.8.3 - - - Update a dependency to the latest release. - -## 1.8.2 - - - Update a dependency to the latest release. - -## 1.8.1 - - - **FIX**(core): bump Pigeon to v25.3.2 ([#17438](https://github.com/firebase/flutterfire/issues/17438)). ([4d24ef53](https://github.com/firebase/flutterfire/commit/4d24ef534464b39dcaef4151c83c78f87b36fb78)) - -## 1.8.0 - - - **FEAT**(firebaseai): Add flutter_soloud for sound output in Live API audio streaming example. ([#17305](https://github.com/firebase/flutterfire/issues/17305)). ([86350e9f](https://github.com/firebase/flutterfire/commit/86350e9f36534cb0dd871f61dba70a44aee7a427)) - -## 1.7.0 - -[changed] **Renamed / Replaced:** Vertex AI in Firebase and its `FirebaseVertexAI` library have been renamed and replaced by the new Firebase AI Logic SDK: `FirebaseAI`. This is to accommodate the evolving set of supported features and services. Please migrate to the new `FirebaseAI` module. See details in the [migration guide](https://firebase.google.com/docs/vertex-ai/migrate-to-latest-sdk). - -Note: Existing `FirebaseVertexAI` users may continue to use `import firebase_vertexai` and the `FirebaseVertexAI` top-level class, though these will be removed in a future release. Also, going forward, new features will only be added into the new `FirebaseAI` module. - -## 1.6.0 - - - **FIX**(vertexai): add missing HarmBlockThreshold to exported APIs ([#17249](https://github.com/firebase/flutterfire/issues/17249)). ([59d902c6](https://github.com/firebase/flutterfire/commit/59d902c63bd1bd040f5357cb6a341db446429430)) - - **FEAT**(vertexai): Live API breaking changes ([#17299](https://github.com/firebase/flutterfire/issues/17299)). ([69cd2a64](https://github.com/firebase/flutterfire/commit/69cd2a640d25e0f2b623f2e631d090ead8af140d)) - -## 1.5.0 - - - **FIX**(vertex_ai): handle null predictions ([#17211](https://github.com/firebase/flutterfire/issues/17211)). ([d559703d](https://github.com/firebase/flutterfire/commit/d559703d71904918fc5c0e8ad02b86313738d263)) - - **FIX**(vertexai): follow up changes for LiveModel ([#17236](https://github.com/firebase/flutterfire/issues/17236)). ([a7a842ef](https://github.com/firebase/flutterfire/commit/a7a842ef3ecee197dc5c2eefd12781086071d53b)) - - **FIX**(vertexai): Add meta to the dependency list ([#17208](https://github.com/firebase/flutterfire/issues/17208)). ([5c9c2221](https://github.com/firebase/flutterfire/commit/5c9c222198dc9ea8d1af8535e8d64ca2e2174ea4)) - - **FEAT**(vertexai): Add repetition penalties to GenerationConfig ([#17234](https://github.com/firebase/flutterfire/issues/17234)). ([6e23afc2](https://github.com/firebase/flutterfire/commit/6e23afc2d7d1ed177f8c54741f2e26a6cbb892e8)) - - **FEAT**(vertexai): Add Live streaming feature ([#16991](https://github.com/firebase/flutterfire/issues/16991)). ([4ab6b4c9](https://github.com/firebase/flutterfire/commit/4ab6b4c92878eec4c12b2bf57553d85a2288b8f3)) - - **FEAT**(vertexai): Add HarmBlockMethod ([#17125](https://github.com/firebase/flutterfire/issues/17125)). ([bbf618db](https://github.com/firebase/flutterfire/commit/bbf618dbb0def1c9afaccedf6fcddda80d8c96ac)) - - **FEAT**(vertexai): Unhandled ContentModality fix with more multimodal examples for vertexai testapp ([#17150](https://github.com/firebase/flutterfire/issues/17150)). ([76461d78](https://github.com/firebase/flutterfire/commit/76461d78631d5e9ce128f5cb79bc21483fd53508)) - -## 1.4.0 - - - **FEAT**(vertexai): add Imagen support ([#16976](https://github.com/firebase/flutterfire/issues/16976)). ([cd9d896d](https://github.com/firebase/flutterfire/commit/cd9d896d87ffe9f4949b025ddbb13b88bafbc176)) - -## 1.3.0 - - - **FEAT**(vertexai): add support for token-based usage metrics ([#17065](https://github.com/firebase/flutterfire/issues/17065)). ([b1bd93fb](https://github.com/firebase/flutterfire/commit/b1bd93fb25dbe36621fbc4b13e13bec805b79328)) - -## 1.2.0 - - - **FIX**(firebase_vertexai): Corrected minor typo in VertexAISDKException ([#17033](https://github.com/firebase/flutterfire/issues/17033)). ([ba543d08](https://github.com/firebase/flutterfire/commit/ba543d08a68f60476ce2b2260506fe035c503aaa)) - - **FEAT**(vertexai): organize example page and functions ([#17008](https://github.com/firebase/flutterfire/issues/17008)). ([6b76260d](https://github.com/firebase/flutterfire/commit/6b76260de7bc03aa6e1cd68bed2e224d53437239)) - -## 1.1.1 - - - Update a dependency to the latest release. - -## 1.1.0 - - - **FIX**(firebase_vertexai): Remove unnecessary trailing whitespace ([#16926](https://github.com/firebase/flutterfire/issues/16926)). ([d9c98c40](https://github.com/firebase/flutterfire/commit/d9c98c403b4652c2a962c015e0f05d21ae580a71)) - -## 1.0.4 - - - Update a dependency to the latest release. - -## 1.0.3 - - - Update a dependency to the latest release. - -## 1.0.2 - - - **FIX**(vertexai): fix the url in the service not available error ([#13547](https://github.com/firebase/flutterfire/issues/13547)). ([a8bfebd7](https://github.com/firebase/flutterfire/commit/a8bfebd7295f26f7ef16e2ed51a8ccaa35755c46)) - -## 1.0.1 - - - **FIX**(vertexai): hotfix for vertexai auth access to storage ([#13534](https://github.com/firebase/flutterfire/issues/13534)). ([9f693094](https://github.com/firebase/flutterfire/commit/9f6930947dbd35a61c583c17bb128f1af4702a5d)) - -## 1.0.0 - -Use the Vertex AI in Firebase SDK to call the Vertex AI Gemini API directly from your app. This client SDK is built specifically for use with Flutter apps, offering security options against unauthorized clients as well as integrations with other Firebase services. - - * If you're new to this SDK, visit the getting started guide. - * If you used the preview version of the library, visit the migration guide to learn about some important updates. - -> Note: This release has breaking changes. - - - **BREAKING** **FEAT**(vertexai): Vertex AI in Firebase is now Generally Available (GA) and can be used in production apps. ([#13453](https://github.com/firebase/flutterfire/issues/13453)). ([77b48800](https://github.com/firebase/flutterfire/commit/77b488001a2b68b46ccff4fc96d143ef891d3e5a)) - -## 0.2.3+4 - - - Update a dependency to the latest release. - -## 0.2.3+3 - - - Update a dependency to the latest release. - -## 0.2.3+2 - - - Update a dependency to the latest release. - -## 0.2.3+1 - - - Update a dependency to the latest release. - -## 0.2.3 - - - **FIX**(vertexai): update history getter to reflect google_generative_ai updates ([#13040](https://github.com/firebase/flutterfire/issues/13040)). ([cc542d76](https://github.com/firebase/flutterfire/commit/cc542d76b989d550f29a9b0a1adb761da64372a7)) - - **FEAT**: bump iOS SDK to version 11.0.0 ([#13158](https://github.com/firebase/flutterfire/issues/13158)). ([c0e0c997](https://github.com/firebase/flutterfire/commit/c0e0c99703ea394d1bb873ac225c5fe3539b002d)) - -## 0.2.2+4 - - - Update a dependency to the latest release. - -## 0.2.2+3 - - - Update a dependency to the latest release. - -## 0.2.2+2 - - - Update a dependency to the latest release. - -## 0.2.2+1 - - - Update a dependency to the latest release. - -## 0.2.2 - - - **FEAT**(vertexai): add name constructor for function calling schema ([#12898](https://github.com/firebase/flutterfire/issues/12898)). ([466884b6](https://github.com/firebase/flutterfire/commit/466884b6474b47ffe4f3f4ca5b3e989a5898dba9)) - -## 0.2.1 - - - **FIX**(vertexai): fix the countTokens brokage ([#12899](https://github.com/firebase/flutterfire/issues/12899)). ([e946eb9b](https://github.com/firebase/flutterfire/commit/e946eb9b429da16bea617b68dda32f23d0deb5bc)) - -## 0.2.0 - -> Note: This release has breaking changes. - - - **BREAKING** **REFACTOR**: bump all iOS deployment targets to iOS 13 ahead of Firebase iOS SDK `v11` breaking change ([#12872](https://github.com/firebase/flutterfire/issues/12872)). ([de0cea2c](https://github.com/firebase/flutterfire/commit/de0cea2c3c36694a76361be784255986fac84a43)) - -## 0.1.1 - - - **REFACTOR**(vertexai): Split into separate libraries ([#12794](https://github.com/firebase/flutterfire/issues/12794)). ([85a517f4](https://github.com/firebase/flutterfire/commit/85a517f42930ce902881be9b321e360b0801530f)) - - **FEAT**(vertexai): Add support for UsageMetaData ([#12787](https://github.com/firebase/flutterfire/issues/12787)). ([08f61ecb](https://github.com/firebase/flutterfire/commit/08f61ecb05526d52a469436248833d5d93f85298)) - - **FEAT**(vertexai): Add a few more parameters to the model request ([#12824](https://github.com/firebase/flutterfire/issues/12824)). ([35ad8d41](https://github.com/firebase/flutterfire/commit/35ad8d41237af2190c9a6ef2ebdfff08b4e813cf)) - - **FEAT**(vertex): Add auth support in the vertexai ([#12797](https://github.com/firebase/flutterfire/issues/12797)). ([3241c0b8](https://github.com/firebase/flutterfire/commit/3241c0b8a9a7dbb4d8ba85d5d0ace35b82204222)) - -## 0.1.0+1 - - - Update a dependency to the latest release. - -## 0.1.0 - -- Initial release of the Vertex AI in Firebase SDK (public preview). Learn how to [get started](https://firebase.google.com/docs/vertex-ai/get-started) with the SDK in your app. diff --git a/packages/firebase_vertexai/firebase_vertexai/LICENSE b/packages/firebase_vertexai/firebase_vertexai/LICENSE deleted file mode 100644 index e58143fccfb6..000000000000 --- a/packages/firebase_vertexai/firebase_vertexai/LICENSE +++ /dev/null @@ -1,202 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright 2024 Google LLC - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/packages/firebase_vertexai/firebase_vertexai/README.md b/packages/firebase_vertexai/firebase_vertexai/README.md deleted file mode 100644 index a09cb52bd87a..000000000000 --- a/packages/firebase_vertexai/firebase_vertexai/README.md +++ /dev/null @@ -1,26 +0,0 @@ -# Vertex AI in Firebase Flutter -[![pub package](https://img.shields.io/pub/v/firebase_vertexai.svg)](https://pub.dev/packages/firebase_vertexai) - -A Flutter plugin to use the [Vertex AI](https://firebase.google.com/docs/vertex-ai/). - -To learn more about Vertex AI, please visit the [website](https://cloud.google.com/vertex-ai) - -**Generally Available**: Vertex AI in Firebase is now Generally Available (GA) and can be used in production apps - -## Getting Started - -To get started with Vertex AI in Firebase Flutter, please [see the documentation](https://firebase.google.com/docs/vertex-ai/get-started?platform=flutter). - -## Usage - -To start use this plugin, please visit the [Text only prompt documentation](https://firebase.google.com/docs/vertex-ai/text-gen-from-text?platform=flutter) - -## Issues and feedback - -Please file FlutterFire specific issues, bugs, or feature requests in our [issue tracker](https://github.com/firebase/flutterfire/issues/new). - -Plugin issues that are not specific to FlutterFire can be filed in the [Flutter issue tracker](https://github.com/flutter/flutter/issues/new). - -To contribute a change to this plugin, -please review our [contribution guide](https://github.com/firebase/flutterfire/blob/main/CONTRIBUTING.md) -and open a [pull request](https://github.com/firebase/flutterfire/pulls). diff --git a/packages/firebase_vertexai/firebase_vertexai/example/.gitignore b/packages/firebase_vertexai/firebase_vertexai/example/.gitignore deleted file mode 100644 index 53bed76d8faa..000000000000 --- a/packages/firebase_vertexai/firebase_vertexai/example/.gitignore +++ /dev/null @@ -1,51 +0,0 @@ -# Miscellaneous -*.class -*.log -*.pyc -*.swp -.DS_Store -.atom/ -.build/ -.buildlog/ -.history -.svn/ -.swiftpm/ -migrate_working_dir/ - -# IntelliJ related -*.iml -*.ipr -*.iws -.idea/ - -# The .vscode folder contains launch configuration and tasks you configure in -# VS Code which you may wish to be included in version control, so this line -# is commented out by default. -#.vscode/ - -# Flutter/Dart/Pub related -**/doc/api/ -**/ios/Flutter/.last_build_id -.dart_tool/ -.flutter-plugins -.flutter-plugins-dependencies -.pub-cache/ -.pub/ -/build/ - -# Symbolication related -app.*.symbols - -# Obfuscation related -app.*.map.json - -# Android Studio will place build artifacts here -/android/app/debug -/android/app/profile -/android/app/release - -#firebase -firebase_options.dart -google-services.json -GoogleService-Info.plist -firebase.json diff --git a/packages/firebase_vertexai/firebase_vertexai/example/.metadata b/packages/firebase_vertexai/firebase_vertexai/example/.metadata deleted file mode 100644 index e8f7bf911cbc..000000000000 --- a/packages/firebase_vertexai/firebase_vertexai/example/.metadata +++ /dev/null @@ -1,45 +0,0 @@ -# This file tracks properties of this Flutter project. -# Used by Flutter tool to assess capabilities and perform upgrades etc. -# -# This file should be version controlled and should not be manually edited. - -version: - revision: "ea121f8859e4b13e47a8f845e4586164519588bc" - channel: "stable" - -project_type: app - -# Tracks metadata for the flutter migrate command -migration: - platforms: - - platform: root - create_revision: ea121f8859e4b13e47a8f845e4586164519588bc - base_revision: ea121f8859e4b13e47a8f845e4586164519588bc - - platform: android - create_revision: ea121f8859e4b13e47a8f845e4586164519588bc - base_revision: ea121f8859e4b13e47a8f845e4586164519588bc - - platform: ios - create_revision: ea121f8859e4b13e47a8f845e4586164519588bc - base_revision: ea121f8859e4b13e47a8f845e4586164519588bc - - platform: linux - create_revision: ea121f8859e4b13e47a8f845e4586164519588bc - base_revision: ea121f8859e4b13e47a8f845e4586164519588bc - - platform: macos - create_revision: ea121f8859e4b13e47a8f845e4586164519588bc - base_revision: ea121f8859e4b13e47a8f845e4586164519588bc - - platform: web - create_revision: ea121f8859e4b13e47a8f845e4586164519588bc - base_revision: ea121f8859e4b13e47a8f845e4586164519588bc - - platform: windows - create_revision: ea121f8859e4b13e47a8f845e4586164519588bc - base_revision: ea121f8859e4b13e47a8f845e4586164519588bc - - # User provided section - - # List of Local paths (relative to this file) that should be - # ignored by the migrate tool. - # - # Files that are not part of the templates will be ignored by default. - unmanaged_files: - - 'lib/main.dart' - - 'ios/Runner.xcodeproj/project.pbxproj' diff --git a/packages/firebase_vertexai/firebase_vertexai/example/README.md b/packages/firebase_vertexai/firebase_vertexai/example/README.md deleted file mode 100644 index cd631c7d2747..000000000000 --- a/packages/firebase_vertexai/firebase_vertexai/example/README.md +++ /dev/null @@ -1,16 +0,0 @@ -# firebase_vertexai_example - -Sample app to show how to use Vertex AI in Firebase. - -## Getting Started - -This project is a starting point for a Flutter application. - -A few resources to get you started if this is your first Flutter project: - -- [Lab: Write your first Flutter app](https://docs.flutter.dev/get-started/codelab) -- [Cookbook: Useful Flutter samples](https://docs.flutter.dev/cookbook) - -For help getting started with Flutter development, view the -[online documentation](https://docs.flutter.dev/), which offers tutorials, -samples, guidance on mobile development, and a full API reference. diff --git a/packages/firebase_vertexai/firebase_vertexai/example/analysis_options.yaml b/packages/firebase_vertexai/firebase_vertexai/example/analysis_options.yaml deleted file mode 100644 index b6cd704fb940..000000000000 --- a/packages/firebase_vertexai/firebase_vertexai/example/analysis_options.yaml +++ /dev/null @@ -1,10 +0,0 @@ -# Copyright 2021 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# in the LICENSE file. - -include: ../../../../analysis_options.yaml -linter: - rules: - avoid_print: false - depend_on_referenced_packages: false - library_private_types_in_public_api: false diff --git a/packages/firebase_vertexai/firebase_vertexai/example/android/.gitignore b/packages/firebase_vertexai/firebase_vertexai/example/android/.gitignore deleted file mode 100644 index be3943c96d8e..000000000000 --- a/packages/firebase_vertexai/firebase_vertexai/example/android/.gitignore +++ /dev/null @@ -1,14 +0,0 @@ -gradle-wrapper.jar -/.gradle -/captures/ -/gradlew -/gradlew.bat -/local.properties -GeneratedPluginRegistrant.java -.cxx/ - -# Remember to never publicly share your keystore. -# See https://flutter.dev/to/reference-keystore -key.properties -**/*.keystore -**/*.jks diff --git a/packages/firebase_vertexai/firebase_vertexai/example/android/app/build.gradle b/packages/firebase_vertexai/firebase_vertexai/example/android/app/build.gradle deleted file mode 100644 index 1c814271cc8e..000000000000 --- a/packages/firebase_vertexai/firebase_vertexai/example/android/app/build.gradle +++ /dev/null @@ -1,59 +0,0 @@ -plugins { - id "com.android.application" - // START: FlutterFire Configuration - id 'com.google.gms.google-services' - // END: FlutterFire Configuration - id "kotlin-android" - id "dev.flutter.flutter-gradle-plugin" -} - -def localProperties = new Properties() -def localPropertiesFile = rootProject.file('local.properties') -if (localPropertiesFile.exists()) { - localPropertiesFile.withReader('UTF-8') { reader -> - localProperties.load(reader) - } -} - -def flutterVersionCode = localProperties.getProperty('flutter.versionCode') -if (flutterVersionCode == null) { - flutterVersionCode = '1' -} - -def flutterVersionName = localProperties.getProperty('flutter.versionName') -if (flutterVersionName == null) { - flutterVersionName = '1.0' -} - -android { - namespace "io.flutter.plugins.firebase.vertexai.example" - - compileSdk 35 - - defaultConfig { - applicationId "io.flutter.plugins.firebase.vertexai.example" - minSdk 23 - targetSdk 33 - versionCode flutterVersionCode.toInteger() - versionName flutterVersionName - } - - buildFeatures { - buildConfig true - } - - buildTypes { - release { - // TODO: Add your own signing config for the release build. - // Signing with the debug keys for now, so `flutter run --release` works. - signingConfig signingConfigs.debug - } - } - kotlinOptions { - jvmTarget = '1.8' // Or '11' - } -} - -flutter { - source '../..' -} diff --git a/packages/firebase_vertexai/firebase_vertexai/example/android/app/build.gradle.kts b/packages/firebase_vertexai/firebase_vertexai/example/android/app/build.gradle.kts deleted file mode 100644 index 3415989fde7e..000000000000 --- a/packages/firebase_vertexai/firebase_vertexai/example/android/app/build.gradle.kts +++ /dev/null @@ -1,47 +0,0 @@ -plugins { - id("com.android.application") - // START: FlutterFire Configuration - id("com.google.gms.google-services") - // END: FlutterFire Configuration - id("kotlin-android") - // The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins. - id("dev.flutter.flutter-gradle-plugin") -} - -android { - namespace = "com.example.vertex_ai_example" - compileSdk = flutter.compileSdkVersion - ndkVersion = "27.0.12077973" - - compileOptions { - sourceCompatibility = JavaVersion.VERSION_11 - targetCompatibility = JavaVersion.VERSION_11 - } - - kotlinOptions { - jvmTarget = JavaVersion.VERSION_11.toString() - } - - defaultConfig { - // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). - applicationId = "com.example.vertex_ai_example" - // You can update the following values to match your application needs. - // For more information, see: https://flutter.dev/to/review-gradle-config. - minSdk = 23 - targetSdk = flutter.targetSdkVersion - versionCode = flutter.versionCode - versionName = flutter.versionName - } - - buildTypes { - release { - // TODO: Add your own signing config for the release build. - // Signing with the debug keys for now, so `flutter run --release` works. - signingConfig = signingConfigs.getByName("debug") - } - } -} - -flutter { - source = "../.." -} diff --git a/packages/firebase_vertexai/firebase_vertexai/example/android/app/src/debug/AndroidManifest.xml b/packages/firebase_vertexai/firebase_vertexai/example/android/app/src/debug/AndroidManifest.xml deleted file mode 100644 index d30de11e3410..000000000000 --- a/packages/firebase_vertexai/firebase_vertexai/example/android/app/src/debug/AndroidManifest.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - diff --git a/packages/firebase_vertexai/firebase_vertexai/example/android/app/src/main/AndroidManifest.xml b/packages/firebase_vertexai/firebase_vertexai/example/android/app/src/main/AndroidManifest.xml deleted file mode 100644 index 48622205141f..000000000000 --- a/packages/firebase_vertexai/firebase_vertexai/example/android/app/src/main/AndroidManifest.xml +++ /dev/null @@ -1,51 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/packages/firebase_vertexai/firebase_vertexai/example/android/app/src/main/kotlin/com/example/vertex_ai_example/MainActivity.kt b/packages/firebase_vertexai/firebase_vertexai/example/android/app/src/main/kotlin/com/example/vertex_ai_example/MainActivity.kt deleted file mode 100644 index a09c414f7bc6..000000000000 --- a/packages/firebase_vertexai/firebase_vertexai/example/android/app/src/main/kotlin/com/example/vertex_ai_example/MainActivity.kt +++ /dev/null @@ -1,5 +0,0 @@ -package com.example.vertex_ai_example - -import io.flutter.embedding.android.FlutterActivity - -class MainActivity : FlutterActivity() diff --git a/packages/firebase_vertexai/firebase_vertexai/example/android/app/src/main/res/drawable-v21/launch_background.xml b/packages/firebase_vertexai/firebase_vertexai/example/android/app/src/main/res/drawable-v21/launch_background.xml deleted file mode 100644 index f74085f3f6a2..000000000000 --- a/packages/firebase_vertexai/firebase_vertexai/example/android/app/src/main/res/drawable-v21/launch_background.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - diff --git a/packages/firebase_vertexai/firebase_vertexai/example/android/app/src/main/res/drawable/launch_background.xml b/packages/firebase_vertexai/firebase_vertexai/example/android/app/src/main/res/drawable/launch_background.xml deleted file mode 100644 index 304732f88420..000000000000 --- a/packages/firebase_vertexai/firebase_vertexai/example/android/app/src/main/res/drawable/launch_background.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - diff --git a/packages/firebase_vertexai/firebase_vertexai/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/packages/firebase_vertexai/firebase_vertexai/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index db77bb4b7b09..000000000000 Binary files a/packages/firebase_vertexai/firebase_vertexai/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png and /dev/null differ diff --git a/packages/firebase_vertexai/firebase_vertexai/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/packages/firebase_vertexai/firebase_vertexai/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png deleted file mode 100644 index 17987b79bb8a..000000000000 Binary files a/packages/firebase_vertexai/firebase_vertexai/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png and /dev/null differ diff --git a/packages/firebase_vertexai/firebase_vertexai/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/packages/firebase_vertexai/firebase_vertexai/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png deleted file mode 100644 index 09d4391482be..000000000000 Binary files a/packages/firebase_vertexai/firebase_vertexai/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png and /dev/null differ diff --git a/packages/firebase_vertexai/firebase_vertexai/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/packages/firebase_vertexai/firebase_vertexai/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png deleted file mode 100644 index d5f1c8d34e7a..000000000000 Binary files a/packages/firebase_vertexai/firebase_vertexai/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png and /dev/null differ diff --git a/packages/firebase_vertexai/firebase_vertexai/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/packages/firebase_vertexai/firebase_vertexai/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png deleted file mode 100644 index 4d6372eebdb2..000000000000 Binary files a/packages/firebase_vertexai/firebase_vertexai/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png and /dev/null differ diff --git a/packages/firebase_vertexai/firebase_vertexai/example/android/app/src/main/res/values-night/styles.xml b/packages/firebase_vertexai/firebase_vertexai/example/android/app/src/main/res/values-night/styles.xml deleted file mode 100644 index 06952be745f9..000000000000 --- a/packages/firebase_vertexai/firebase_vertexai/example/android/app/src/main/res/values-night/styles.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - diff --git a/packages/firebase_vertexai/firebase_vertexai/example/android/app/src/main/res/values/styles.xml b/packages/firebase_vertexai/firebase_vertexai/example/android/app/src/main/res/values/styles.xml deleted file mode 100644 index cb1ef88056ed..000000000000 --- a/packages/firebase_vertexai/firebase_vertexai/example/android/app/src/main/res/values/styles.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - diff --git a/packages/firebase_vertexai/firebase_vertexai/example/android/app/src/profile/AndroidManifest.xml b/packages/firebase_vertexai/firebase_vertexai/example/android/app/src/profile/AndroidManifest.xml deleted file mode 100644 index 399f6981d5d3..000000000000 --- a/packages/firebase_vertexai/firebase_vertexai/example/android/app/src/profile/AndroidManifest.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - diff --git a/packages/firebase_vertexai/firebase_vertexai/example/android/build.gradle b/packages/firebase_vertexai/firebase_vertexai/example/android/build.gradle deleted file mode 100644 index 4533872eedd6..000000000000 --- a/packages/firebase_vertexai/firebase_vertexai/example/android/build.gradle +++ /dev/null @@ -1,31 +0,0 @@ -buildscript { - repositories { - google() - mavenCentral() - } - - dependencies { - classpath 'com.android.tools.build:gradle:8.3.0' - // START: FlutterFire Configuration - classpath 'com.google.gms:google-services:4.4.0' - // END: FlutterFire Configuration - } -} -allprojects { - repositories { - google() - mavenCentral() - } -} - -rootProject.buildDir = '../build' -subprojects { - project.buildDir = "${rootProject.buildDir}/${project.name}" -} -subprojects { - project.evaluationDependsOn(':app') -} - -tasks.register("clean", Delete) { - delete rootProject.buildDir -} diff --git a/packages/firebase_vertexai/firebase_vertexai/example/android/build.gradle.kts b/packages/firebase_vertexai/firebase_vertexai/example/android/build.gradle.kts deleted file mode 100644 index 89176ef44e8c..000000000000 --- a/packages/firebase_vertexai/firebase_vertexai/example/android/build.gradle.kts +++ /dev/null @@ -1,21 +0,0 @@ -allprojects { - repositories { - google() - mavenCentral() - } -} - -val newBuildDir: Directory = rootProject.layout.buildDirectory.dir("../../build").get() -rootProject.layout.buildDirectory.value(newBuildDir) - -subprojects { - val newSubprojectBuildDir: Directory = newBuildDir.dir(project.name) - project.layout.buildDirectory.value(newSubprojectBuildDir) -} -subprojects { - project.evaluationDependsOn(":app") -} - -tasks.register("clean") { - delete(rootProject.layout.buildDirectory) -} diff --git a/packages/firebase_vertexai/firebase_vertexai/example/android/gradle.properties b/packages/firebase_vertexai/firebase_vertexai/example/android/gradle.properties deleted file mode 100644 index f018a61817f5..000000000000 --- a/packages/firebase_vertexai/firebase_vertexai/example/android/gradle.properties +++ /dev/null @@ -1,3 +0,0 @@ -org.gradle.jvmargs=-Xmx8G -XX:MaxMetaspaceSize=4G -XX:ReservedCodeCacheSize=512m -XX:+HeapDumpOnOutOfMemoryError -android.useAndroidX=true -android.enableJetifier=true diff --git a/packages/firebase_vertexai/firebase_vertexai/example/android/gradle/wrapper/gradle-wrapper.properties b/packages/firebase_vertexai/firebase_vertexai/example/android/gradle/wrapper/gradle-wrapper.properties deleted file mode 100644 index afa1e8eb0a83..000000000000 --- a/packages/firebase_vertexai/firebase_vertexai/example/android/gradle/wrapper/gradle-wrapper.properties +++ /dev/null @@ -1,5 +0,0 @@ -distributionBase=GRADLE_USER_HOME -distributionPath=wrapper/dists -zipStoreBase=GRADLE_USER_HOME -zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-all.zip diff --git a/packages/firebase_vertexai/firebase_vertexai/example/android/settings.gradle b/packages/firebase_vertexai/firebase_vertexai/example/android/settings.gradle deleted file mode 100644 index a4d924db8bec..000000000000 --- a/packages/firebase_vertexai/firebase_vertexai/example/android/settings.gradle +++ /dev/null @@ -1,28 +0,0 @@ -pluginManagement { - def flutterSdkPath = { - def properties = new Properties() - file("local.properties").withInputStream { properties.load(it) } - def flutterSdkPath = properties.getProperty("flutter.sdk") - assert flutterSdkPath != null, "flutter.sdk not set in local.properties" - return flutterSdkPath - }() - - includeBuild("$flutterSdkPath/packages/flutter_tools/gradle") - - repositories { - google() - mavenCentral() - gradlePluginPortal() - } -} - -plugins { - id "dev.flutter.flutter-plugin-loader" version "1.0.0" - id "com.android.application" version "8.3.0" apply false - // START: FlutterFire Configuration - id "com.google.gms.google-services" version "4.3.15" apply false - // END: FlutterFire Configuration - id "org.jetbrains.kotlin.android" version "1.9.22" apply false -} - -include ":app" diff --git a/packages/firebase_vertexai/firebase_vertexai/example/android/settings.gradle.kts b/packages/firebase_vertexai/firebase_vertexai/example/android/settings.gradle.kts deleted file mode 100644 index 9e2d35ccf5e0..000000000000 --- a/packages/firebase_vertexai/firebase_vertexai/example/android/settings.gradle.kts +++ /dev/null @@ -1,28 +0,0 @@ -pluginManagement { - val flutterSdkPath = run { - val properties = java.util.Properties() - file("local.properties").inputStream().use { properties.load(it) } - val flutterSdkPath = properties.getProperty("flutter.sdk") - require(flutterSdkPath != null) { "flutter.sdk not set in local.properties" } - flutterSdkPath - } - - includeBuild("$flutterSdkPath/packages/flutter_tools/gradle") - - repositories { - google() - mavenCentral() - gradlePluginPortal() - } -} - -plugins { - id("dev.flutter.flutter-plugin-loader") version "1.0.0" - id("com.android.application") version "8.7.0" apply false - // START: FlutterFire Configuration - id("com.google.gms.google-services") version("4.3.15") apply false - // END: FlutterFire Configuration - id("org.jetbrains.kotlin.android") version "1.8.22" apply false -} - -include(":app") diff --git a/packages/firebase_vertexai/firebase_vertexai/example/assets/documents/gemini_summary.pdf b/packages/firebase_vertexai/firebase_vertexai/example/assets/documents/gemini_summary.pdf deleted file mode 100644 index 08881c7839ec..000000000000 Binary files a/packages/firebase_vertexai/firebase_vertexai/example/assets/documents/gemini_summary.pdf and /dev/null differ diff --git a/packages/firebase_vertexai/firebase_vertexai/example/assets/images/cat.jpg b/packages/firebase_vertexai/firebase_vertexai/example/assets/images/cat.jpg deleted file mode 100644 index 8d2069e6c979..000000000000 Binary files a/packages/firebase_vertexai/firebase_vertexai/example/assets/images/cat.jpg and /dev/null differ diff --git a/packages/firebase_vertexai/firebase_vertexai/example/assets/images/scones.jpg b/packages/firebase_vertexai/firebase_vertexai/example/assets/images/scones.jpg deleted file mode 100644 index ce689588e871..000000000000 Binary files a/packages/firebase_vertexai/firebase_vertexai/example/assets/images/scones.jpg and /dev/null differ diff --git a/packages/firebase_vertexai/firebase_vertexai/example/assets/videos/landscape.mp4 b/packages/firebase_vertexai/firebase_vertexai/example/assets/videos/landscape.mp4 deleted file mode 100644 index a7f4298dd7e9..000000000000 Binary files a/packages/firebase_vertexai/firebase_vertexai/example/assets/videos/landscape.mp4 and /dev/null differ diff --git a/packages/firebase_vertexai/firebase_vertexai/example/ios/.gitignore b/packages/firebase_vertexai/firebase_vertexai/example/ios/.gitignore deleted file mode 100644 index 7a7f9873ad7d..000000000000 --- a/packages/firebase_vertexai/firebase_vertexai/example/ios/.gitignore +++ /dev/null @@ -1,34 +0,0 @@ -**/dgph -*.mode1v3 -*.mode2v3 -*.moved-aside -*.pbxuser -*.perspectivev3 -**/*sync/ -.sconsign.dblite -.tags* -**/.vagrant/ -**/DerivedData/ -Icon? -**/Pods/ -**/.symlinks/ -profile -xcuserdata -**/.generated/ -Flutter/App.framework -Flutter/Flutter.framework -Flutter/Flutter.podspec -Flutter/Generated.xcconfig -Flutter/ephemeral/ -Flutter/app.flx -Flutter/app.zip -Flutter/flutter_assets/ -Flutter/flutter_export_environment.sh -ServiceDefinitions.json -Runner/GeneratedPluginRegistrant.* - -# Exceptions to above rules. -!default.mode1v3 -!default.mode2v3 -!default.pbxuser -!default.perspectivev3 diff --git a/packages/firebase_vertexai/firebase_vertexai/example/ios/Flutter/AppFrameworkInfo.plist b/packages/firebase_vertexai/firebase_vertexai/example/ios/Flutter/AppFrameworkInfo.plist deleted file mode 100644 index 7c5696400627..000000000000 --- a/packages/firebase_vertexai/firebase_vertexai/example/ios/Flutter/AppFrameworkInfo.plist +++ /dev/null @@ -1,26 +0,0 @@ - - - - - CFBundleDevelopmentRegion - en - CFBundleExecutable - App - CFBundleIdentifier - io.flutter.flutter.app - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - App - CFBundlePackageType - FMWK - CFBundleShortVersionString - 1.0 - CFBundleSignature - ???? - CFBundleVersion - 1.0 - MinimumOSVersion - 12.0 - - diff --git a/packages/firebase_vertexai/firebase_vertexai/example/ios/Flutter/Debug.xcconfig b/packages/firebase_vertexai/firebase_vertexai/example/ios/Flutter/Debug.xcconfig deleted file mode 100644 index ec97fc6f3021..000000000000 --- a/packages/firebase_vertexai/firebase_vertexai/example/ios/Flutter/Debug.xcconfig +++ /dev/null @@ -1,2 +0,0 @@ -#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" -#include "Generated.xcconfig" diff --git a/packages/firebase_vertexai/firebase_vertexai/example/ios/Flutter/Release.xcconfig b/packages/firebase_vertexai/firebase_vertexai/example/ios/Flutter/Release.xcconfig deleted file mode 100644 index c4855bfe2000..000000000000 --- a/packages/firebase_vertexai/firebase_vertexai/example/ios/Flutter/Release.xcconfig +++ /dev/null @@ -1,2 +0,0 @@ -#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" -#include "Generated.xcconfig" diff --git a/packages/firebase_vertexai/firebase_vertexai/example/ios/Podfile b/packages/firebase_vertexai/firebase_vertexai/example/ios/Podfile deleted file mode 100644 index 6649374d4c19..000000000000 --- a/packages/firebase_vertexai/firebase_vertexai/example/ios/Podfile +++ /dev/null @@ -1,43 +0,0 @@ -# Uncomment this line to define a global platform for your project -platform :ios, '15.0' - -# CocoaPods analytics sends network stats synchronously affecting flutter build latency. -ENV['COCOAPODS_DISABLE_STATS'] = 'true' - -project 'Runner', { - 'Debug' => :debug, - 'Profile' => :release, - 'Release' => :release, -} - -def flutter_root - generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__) - unless File.exist?(generated_xcode_build_settings_path) - raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first" - end - - File.foreach(generated_xcode_build_settings_path) do |line| - matches = line.match(/FLUTTER_ROOT\=(.*)/) - return matches[1].strip if matches - end - raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get" -end - -require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) - -flutter_ios_podfile_setup - -target 'Runner' do - use_frameworks! - - flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) - target 'RunnerTests' do - inherit! :search_paths - end -end - -post_install do |installer| - installer.pods_project.targets.each do |target| - flutter_additional_ios_build_settings(target) - end -end diff --git a/packages/firebase_vertexai/firebase_vertexai/example/ios/Runner.xcodeproj/project.pbxproj b/packages/firebase_vertexai/firebase_vertexai/example/ios/Runner.xcodeproj/project.pbxproj deleted file mode 100644 index 37f29d6208ac..000000000000 --- a/packages/firebase_vertexai/firebase_vertexai/example/ios/Runner.xcodeproj/project.pbxproj +++ /dev/null @@ -1,731 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 54; - objects = { - -/* Begin PBXBuildFile section */ - 12DD27C70B6F1A3A29F606CA /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5EC8278BABD88B76D174C9B3 /* Pods_RunnerTests.framework */; }; - 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; - 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; }; - 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; - 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; - 7B483211B8F8447551559CD8 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5A7451CAF0BF9B58B1FC94AC /* Pods_Runner.framework */; }; - 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; - 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; - 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; -/* End PBXBuildFile section */ - -/* Begin PBXContainerItemProxy section */ - 331C8085294A63A400263BE5 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 97C146E61CF9000F007C117D /* Project object */; - proxyType = 1; - remoteGlobalIDString = 97C146ED1CF9000F007C117D; - remoteInfo = Runner; - }; -/* End PBXContainerItemProxy section */ - -/* Begin PBXCopyFilesBuildPhase section */ - 9705A1C41CF9048500538489 /* Embed Frameworks */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = ""; - dstSubfolderSpec = 10; - files = ( - ); - name = "Embed Frameworks"; - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXCopyFilesBuildPhase section */ - -/* Begin PBXFileReference section */ - 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; - 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; - 1B003FC08370C067F6112BA3 /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = ""; }; - 1E4EFC92E26DC42959308596 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; - 2DF9D5C450661BB71EE1CA4A /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; - 331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; }; - 331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; - 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; - 5A7451CAF0BF9B58B1FC94AC /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 5EC8278BABD88B76D174C9B3 /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; - 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; - 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; - 8E74AA7A780E6AD093F2280C /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = ""; }; - 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; - 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; - 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; - 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; - 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; - 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - B2BD865801978D1293EC9548 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; - B5411DA55636D994211B15CD /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = ""; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 97C146EB1CF9000F007C117D /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 7B483211B8F8447551559CD8 /* Pods_Runner.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - E0117E231D8F6E331F0AF95D /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 12DD27C70B6F1A3A29F606CA /* Pods_RunnerTests.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 331C8082294A63A400263BE5 /* RunnerTests */ = { - isa = PBXGroup; - children = ( - 331C807B294A618700263BE5 /* RunnerTests.swift */, - ); - path = RunnerTests; - sourceTree = ""; - }; - 51AC52FF58548C49E2FD13CA /* Pods */ = { - isa = PBXGroup; - children = ( - 2DF9D5C450661BB71EE1CA4A /* Pods-Runner.debug.xcconfig */, - B2BD865801978D1293EC9548 /* Pods-Runner.release.xcconfig */, - 1E4EFC92E26DC42959308596 /* Pods-Runner.profile.xcconfig */, - 1B003FC08370C067F6112BA3 /* Pods-RunnerTests.debug.xcconfig */, - 8E74AA7A780E6AD093F2280C /* Pods-RunnerTests.release.xcconfig */, - B5411DA55636D994211B15CD /* Pods-RunnerTests.profile.xcconfig */, - ); - name = Pods; - path = Pods; - sourceTree = ""; - }; - 67A1388587063912C673254D /* Frameworks */ = { - isa = PBXGroup; - children = ( - 5A7451CAF0BF9B58B1FC94AC /* Pods_Runner.framework */, - 5EC8278BABD88B76D174C9B3 /* Pods_RunnerTests.framework */, - ); - name = Frameworks; - sourceTree = ""; - }; - 9740EEB11CF90186004384FC /* Flutter */ = { - isa = PBXGroup; - children = ( - 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, - 9740EEB21CF90195004384FC /* Debug.xcconfig */, - 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, - 9740EEB31CF90195004384FC /* Generated.xcconfig */, - ); - name = Flutter; - sourceTree = ""; - }; - 97C146E51CF9000F007C117D = { - isa = PBXGroup; - children = ( - 9740EEB11CF90186004384FC /* Flutter */, - 97C146F01CF9000F007C117D /* Runner */, - 97C146EF1CF9000F007C117D /* Products */, - 331C8082294A63A400263BE5 /* RunnerTests */, - 51AC52FF58548C49E2FD13CA /* Pods */, - 67A1388587063912C673254D /* Frameworks */, - ); - sourceTree = ""; - }; - 97C146EF1CF9000F007C117D /* Products */ = { - isa = PBXGroup; - children = ( - 97C146EE1CF9000F007C117D /* Runner.app */, - 331C8081294A63A400263BE5 /* RunnerTests.xctest */, - ); - name = Products; - sourceTree = ""; - }; - 97C146F01CF9000F007C117D /* Runner */ = { - isa = PBXGroup; - children = ( - 97C146FA1CF9000F007C117D /* Main.storyboard */, - 97C146FD1CF9000F007C117D /* Assets.xcassets */, - 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, - 97C147021CF9000F007C117D /* Info.plist */, - 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, - 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, - 74858FAE1ED2DC5600515810 /* AppDelegate.swift */, - 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */, - ); - path = Runner; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 331C8080294A63A400263BE5 /* RunnerTests */ = { - isa = PBXNativeTarget; - buildConfigurationList = 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */; - buildPhases = ( - 8580F0CE7F25830B9BDEF0A0 /* [CP] Check Pods Manifest.lock */, - 331C807D294A63A400263BE5 /* Sources */, - 331C807F294A63A400263BE5 /* Resources */, - E0117E231D8F6E331F0AF95D /* Frameworks */, - ); - buildRules = ( - ); - dependencies = ( - 331C8086294A63A400263BE5 /* PBXTargetDependency */, - ); - name = RunnerTests; - productName = RunnerTests; - productReference = 331C8081294A63A400263BE5 /* RunnerTests.xctest */; - productType = "com.apple.product-type.bundle.unit-test"; - }; - 97C146ED1CF9000F007C117D /* Runner */ = { - isa = PBXNativeTarget; - buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; - buildPhases = ( - 0C5779354B72E692610FCBAC /* [CP] Check Pods Manifest.lock */, - 9740EEB61CF901F6004384FC /* Run Script */, - 97C146EA1CF9000F007C117D /* Sources */, - 97C146EB1CF9000F007C117D /* Frameworks */, - 97C146EC1CF9000F007C117D /* Resources */, - 9705A1C41CF9048500538489 /* Embed Frameworks */, - 3B06AD1E1E4923F5004D2608 /* Thin Binary */, - 8F2729CA72CB997339394B4E /* [CP] Embed Pods Frameworks */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = Runner; - productName = Runner; - productReference = 97C146EE1CF9000F007C117D /* Runner.app */; - productType = "com.apple.product-type.application"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 97C146E61CF9000F007C117D /* Project object */ = { - isa = PBXProject; - attributes = { - BuildIndependentTargetsInParallel = YES; - LastUpgradeCheck = 1510; - ORGANIZATIONNAME = ""; - TargetAttributes = { - 331C8080294A63A400263BE5 = { - CreatedOnToolsVersion = 14.0; - TestTargetID = 97C146ED1CF9000F007C117D; - }; - 97C146ED1CF9000F007C117D = { - CreatedOnToolsVersion = 7.3.1; - LastSwiftMigration = 1100; - }; - }; - }; - buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; - compatibilityVersion = "Xcode 9.3"; - developmentRegion = en; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = 97C146E51CF9000F007C117D; - productRefGroup = 97C146EF1CF9000F007C117D /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 97C146ED1CF9000F007C117D /* Runner */, - 331C8080294A63A400263BE5 /* RunnerTests */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 331C807F294A63A400263BE5 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 97C146EC1CF9000F007C117D /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, - 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, - 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, - 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXShellScriptBuildPhase section */ - 0C5779354B72E692610FCBAC /* [CP] Check Pods Manifest.lock */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - ); - inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", - ); - name = "[CP] Check Pods Manifest.lock"; - outputFileListPaths = ( - ); - outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; - showEnvVarsInLog = 0; - }; - 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { - isa = PBXShellScriptBuildPhase; - alwaysOutOfDate = 1; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}", - ); - name = "Thin Binary"; - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; - }; - 8580F0CE7F25830B9BDEF0A0 /* [CP] Check Pods Manifest.lock */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - ); - inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", - ); - name = "[CP] Check Pods Manifest.lock"; - outputFileListPaths = ( - ); - outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-RunnerTests-checkManifestLockResult.txt", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; - showEnvVarsInLog = 0; - }; - 8F2729CA72CB997339394B4E /* [CP] Embed Pods Frameworks */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", - ); - name = "[CP] Embed Pods Frameworks"; - outputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; - showEnvVarsInLog = 0; - }; - 9740EEB61CF901F6004384FC /* Run Script */ = { - isa = PBXShellScriptBuildPhase; - alwaysOutOfDate = 1; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - name = "Run Script"; - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; - }; -/* End PBXShellScriptBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 331C807D294A63A400263BE5 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 97C146EA1CF9000F007C117D /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */, - 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXTargetDependency section */ - 331C8086294A63A400263BE5 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 97C146ED1CF9000F007C117D /* Runner */; - targetProxy = 331C8085294A63A400263BE5 /* PBXContainerItemProxy */; - }; -/* End PBXTargetDependency section */ - -/* Begin PBXVariantGroup section */ - 97C146FA1CF9000F007C117D /* Main.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 97C146FB1CF9000F007C117D /* Base */, - ); - name = Main.storyboard; - sourceTree = ""; - }; - 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 97C147001CF9000F007C117D /* Base */, - ); - name = LaunchScreen.storyboard; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - -/* Begin XCBuildConfiguration section */ - 249021D3217E4FDB00AE95B9 /* Profile */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; - CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_USER_SCRIPT_SANDBOXING = NO; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 12.0; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = iphoneos; - SUPPORTED_PLATFORMS = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - }; - name = Profile; - }; - 249021D4217E4FDB00AE95B9 /* Profile */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CLANG_ENABLE_MODULES = YES; - CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; - DEVELOPMENT_TEAM = S8QB4VV633; - ENABLE_BITCODE = NO; - INFOPLIST_FILE = Runner/Info.plist; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - ); - PRODUCT_BUNDLE_IDENTIFIER = com.example.vertexAiExample; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; - SWIFT_VERSION = 5.0; - VERSIONING_SYSTEM = "apple-generic"; - }; - name = Profile; - }; - 331C8088294A63A400263BE5 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 1B003FC08370C067F6112BA3 /* Pods-RunnerTests.debug.xcconfig */; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; - GENERATE_INFOPLIST_FILE = YES; - MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = com.example.vertexAiExample.RunnerTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 5.0; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; - }; - name = Debug; - }; - 331C8089294A63A400263BE5 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 8E74AA7A780E6AD093F2280C /* Pods-RunnerTests.release.xcconfig */; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; - GENERATE_INFOPLIST_FILE = YES; - MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = com.example.vertexAiExample.RunnerTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 5.0; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; - }; - name = Release; - }; - 331C808A294A63A400263BE5 /* Profile */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = B5411DA55636D994211B15CD /* Pods-RunnerTests.profile.xcconfig */; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; - GENERATE_INFOPLIST_FILE = YES; - MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = com.example.vertexAiExample.RunnerTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 5.0; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; - }; - name = Profile; - }; - 97C147031CF9000F007C117D /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; - CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = dwarf; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; - ENABLE_USER_SCRIPT_SANDBOXING = NO; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 12.0; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; - 97C147041CF9000F007C117D /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; - CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_USER_SCRIPT_SANDBOXING = NO; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 12.0; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = iphoneos; - SUPPORTED_PLATFORMS = iphoneos; - SWIFT_COMPILATION_MODE = wholemodule; - SWIFT_OPTIMIZATION_LEVEL = "-O"; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - 97C147061CF9000F007C117D /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CLANG_ENABLE_MODULES = YES; - CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; - DEVELOPMENT_TEAM = S8QB4VV633; - ENABLE_BITCODE = NO; - INFOPLIST_FILE = Runner/Info.plist; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - ); - PRODUCT_BUNDLE_IDENTIFIER = com.example.vertexAiExample; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 5.0; - VERSIONING_SYSTEM = "apple-generic"; - }; - name = Debug; - }; - 97C147071CF9000F007C117D /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CLANG_ENABLE_MODULES = YES; - CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; - DEVELOPMENT_TEAM = S8QB4VV633; - ENABLE_BITCODE = NO; - INFOPLIST_FILE = Runner/Info.plist; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - ); - PRODUCT_BUNDLE_IDENTIFIER = com.example.vertexAiExample; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; - SWIFT_VERSION = 5.0; - VERSIONING_SYSTEM = "apple-generic"; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 331C8088294A63A400263BE5 /* Debug */, - 331C8089294A63A400263BE5 /* Release */, - 331C808A294A63A400263BE5 /* Profile */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 97C147031CF9000F007C117D /* Debug */, - 97C147041CF9000F007C117D /* Release */, - 249021D3217E4FDB00AE95B9 /* Profile */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 97C147061CF9000F007C117D /* Debug */, - 97C147071CF9000F007C117D /* Release */, - 249021D4217E4FDB00AE95B9 /* Profile */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 97C146E61CF9000F007C117D /* Project object */; -} diff --git a/packages/firebase_vertexai/firebase_vertexai/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/packages/firebase_vertexai/firebase_vertexai/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata deleted file mode 100644 index 919434a6254f..000000000000 --- a/packages/firebase_vertexai/firebase_vertexai/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata +++ /dev/null @@ -1,7 +0,0 @@ - - - - - diff --git a/packages/firebase_vertexai/firebase_vertexai/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/packages/firebase_vertexai/firebase_vertexai/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist deleted file mode 100644 index 18d981003d68..000000000000 --- a/packages/firebase_vertexai/firebase_vertexai/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +++ /dev/null @@ -1,8 +0,0 @@ - - - - - IDEDidComputeMac32BitWarning - - - diff --git a/packages/firebase_vertexai/firebase_vertexai/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/packages/firebase_vertexai/firebase_vertexai/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings deleted file mode 100644 index f9b0d7c5ea15..000000000000 --- a/packages/firebase_vertexai/firebase_vertexai/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings +++ /dev/null @@ -1,8 +0,0 @@ - - - - - PreviewsEnabled - - - diff --git a/packages/firebase_vertexai/firebase_vertexai/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/packages/firebase_vertexai/firebase_vertexai/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme deleted file mode 100644 index 15cada4838e2..000000000000 --- a/packages/firebase_vertexai/firebase_vertexai/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ /dev/null @@ -1,99 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/packages/firebase_vertexai/firebase_vertexai/example/ios/Runner.xcworkspace/contents.xcworkspacedata b/packages/firebase_vertexai/firebase_vertexai/example/ios/Runner.xcworkspace/contents.xcworkspacedata deleted file mode 100644 index 21a3cc14c74e..000000000000 --- a/packages/firebase_vertexai/firebase_vertexai/example/ios/Runner.xcworkspace/contents.xcworkspacedata +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - diff --git a/packages/firebase_vertexai/firebase_vertexai/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/packages/firebase_vertexai/firebase_vertexai/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist deleted file mode 100644 index 18d981003d68..000000000000 --- a/packages/firebase_vertexai/firebase_vertexai/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +++ /dev/null @@ -1,8 +0,0 @@ - - - - - IDEDidComputeMac32BitWarning - - - diff --git a/packages/firebase_vertexai/firebase_vertexai/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/packages/firebase_vertexai/firebase_vertexai/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings deleted file mode 100644 index f9b0d7c5ea15..000000000000 --- a/packages/firebase_vertexai/firebase_vertexai/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings +++ /dev/null @@ -1,8 +0,0 @@ - - - - - PreviewsEnabled - - - diff --git a/packages/firebase_vertexai/firebase_vertexai/example/ios/Runner/AppDelegate.swift b/packages/firebase_vertexai/firebase_vertexai/example/ios/Runner/AppDelegate.swift deleted file mode 100644 index 626664468b89..000000000000 --- a/packages/firebase_vertexai/firebase_vertexai/example/ios/Runner/AppDelegate.swift +++ /dev/null @@ -1,13 +0,0 @@ -import Flutter -import UIKit - -@main -@objc class AppDelegate: FlutterAppDelegate { - override func application( - _ application: UIApplication, - didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? - ) -> Bool { - GeneratedPluginRegistrant.register(with: self) - return super.application(application, didFinishLaunchingWithOptions: launchOptions) - } -} diff --git a/packages/firebase_vertexai/firebase_vertexai/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/packages/firebase_vertexai/firebase_vertexai/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json deleted file mode 100644 index d36b1fab2d9d..000000000000 --- a/packages/firebase_vertexai/firebase_vertexai/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json +++ /dev/null @@ -1,122 +0,0 @@ -{ - "images" : [ - { - "size" : "20x20", - "idiom" : "iphone", - "filename" : "Icon-App-20x20@2x.png", - "scale" : "2x" - }, - { - "size" : "20x20", - "idiom" : "iphone", - "filename" : "Icon-App-20x20@3x.png", - "scale" : "3x" - }, - { - "size" : "29x29", - "idiom" : "iphone", - "filename" : "Icon-App-29x29@1x.png", - "scale" : "1x" - }, - { - "size" : "29x29", - "idiom" : "iphone", - "filename" : "Icon-App-29x29@2x.png", - "scale" : "2x" - }, - { - "size" : "29x29", - "idiom" : "iphone", - "filename" : "Icon-App-29x29@3x.png", - "scale" : "3x" - }, - { - "size" : "40x40", - "idiom" : "iphone", - "filename" : "Icon-App-40x40@2x.png", - "scale" : "2x" - }, - { - "size" : "40x40", - "idiom" : "iphone", - "filename" : "Icon-App-40x40@3x.png", - "scale" : "3x" - }, - { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "Icon-App-60x60@2x.png", - "scale" : "2x" - }, - { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "Icon-App-60x60@3x.png", - "scale" : "3x" - }, - { - "size" : "20x20", - "idiom" : "ipad", - "filename" : "Icon-App-20x20@1x.png", - "scale" : "1x" - }, - { - "size" : "20x20", - "idiom" : "ipad", - "filename" : "Icon-App-20x20@2x.png", - "scale" : "2x" - }, - { - "size" : "29x29", - "idiom" : "ipad", - "filename" : "Icon-App-29x29@1x.png", - "scale" : "1x" - }, - { - "size" : "29x29", - "idiom" : "ipad", - "filename" : "Icon-App-29x29@2x.png", - "scale" : "2x" - }, - { - "size" : "40x40", - "idiom" : "ipad", - "filename" : "Icon-App-40x40@1x.png", - "scale" : "1x" - }, - { - "size" : "40x40", - "idiom" : "ipad", - "filename" : "Icon-App-40x40@2x.png", - "scale" : "2x" - }, - { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "Icon-App-76x76@1x.png", - "scale" : "1x" - }, - { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "Icon-App-76x76@2x.png", - "scale" : "2x" - }, - { - "size" : "83.5x83.5", - "idiom" : "ipad", - "filename" : "Icon-App-83.5x83.5@2x.png", - "scale" : "2x" - }, - { - "size" : "1024x1024", - "idiom" : "ios-marketing", - "filename" : "Icon-App-1024x1024@1x.png", - "scale" : "1x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} diff --git a/packages/firebase_vertexai/firebase_vertexai/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png b/packages/firebase_vertexai/firebase_vertexai/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png deleted file mode 100644 index dc9ada4725e9..000000000000 Binary files a/packages/firebase_vertexai/firebase_vertexai/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png and /dev/null differ diff --git a/packages/firebase_vertexai/firebase_vertexai/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png b/packages/firebase_vertexai/firebase_vertexai/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png deleted file mode 100644 index 7353c41ecf9c..000000000000 Binary files a/packages/firebase_vertexai/firebase_vertexai/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png and /dev/null differ diff --git a/packages/firebase_vertexai/firebase_vertexai/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png b/packages/firebase_vertexai/firebase_vertexai/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png deleted file mode 100644 index 797d452e4589..000000000000 Binary files a/packages/firebase_vertexai/firebase_vertexai/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png and /dev/null differ diff --git a/packages/firebase_vertexai/firebase_vertexai/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png b/packages/firebase_vertexai/firebase_vertexai/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png deleted file mode 100644 index 6ed2d933e112..000000000000 Binary files a/packages/firebase_vertexai/firebase_vertexai/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png and /dev/null differ diff --git a/packages/firebase_vertexai/firebase_vertexai/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png b/packages/firebase_vertexai/firebase_vertexai/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png deleted file mode 100644 index 4cd7b0099ca8..000000000000 Binary files a/packages/firebase_vertexai/firebase_vertexai/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png and /dev/null differ diff --git a/packages/firebase_vertexai/firebase_vertexai/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png b/packages/firebase_vertexai/firebase_vertexai/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png deleted file mode 100644 index fe730945a01f..000000000000 Binary files a/packages/firebase_vertexai/firebase_vertexai/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png and /dev/null differ diff --git a/packages/firebase_vertexai/firebase_vertexai/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png b/packages/firebase_vertexai/firebase_vertexai/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png deleted file mode 100644 index 321773cd857a..000000000000 Binary files a/packages/firebase_vertexai/firebase_vertexai/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png and /dev/null differ diff --git a/packages/firebase_vertexai/firebase_vertexai/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png b/packages/firebase_vertexai/firebase_vertexai/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png deleted file mode 100644 index 797d452e4589..000000000000 Binary files a/packages/firebase_vertexai/firebase_vertexai/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png and /dev/null differ diff --git a/packages/firebase_vertexai/firebase_vertexai/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png b/packages/firebase_vertexai/firebase_vertexai/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png deleted file mode 100644 index 502f463a9bc8..000000000000 Binary files a/packages/firebase_vertexai/firebase_vertexai/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png and /dev/null differ diff --git a/packages/firebase_vertexai/firebase_vertexai/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png b/packages/firebase_vertexai/firebase_vertexai/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png deleted file mode 100644 index 0ec303439225..000000000000 Binary files a/packages/firebase_vertexai/firebase_vertexai/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png and /dev/null differ diff --git a/packages/firebase_vertexai/firebase_vertexai/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/packages/firebase_vertexai/firebase_vertexai/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png deleted file mode 100644 index 0ec303439225..000000000000 Binary files a/packages/firebase_vertexai/firebase_vertexai/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png and /dev/null differ diff --git a/packages/firebase_vertexai/firebase_vertexai/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/packages/firebase_vertexai/firebase_vertexai/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png deleted file mode 100644 index e9f5fea27c70..000000000000 Binary files a/packages/firebase_vertexai/firebase_vertexai/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png and /dev/null differ diff --git a/packages/firebase_vertexai/firebase_vertexai/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png b/packages/firebase_vertexai/firebase_vertexai/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png deleted file mode 100644 index 84ac32ae7d98..000000000000 Binary files a/packages/firebase_vertexai/firebase_vertexai/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png and /dev/null differ diff --git a/packages/firebase_vertexai/firebase_vertexai/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png b/packages/firebase_vertexai/firebase_vertexai/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png deleted file mode 100644 index 8953cba09064..000000000000 Binary files a/packages/firebase_vertexai/firebase_vertexai/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png and /dev/null differ diff --git a/packages/firebase_vertexai/firebase_vertexai/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png b/packages/firebase_vertexai/firebase_vertexai/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png deleted file mode 100644 index 0467bf12aa4d..000000000000 Binary files a/packages/firebase_vertexai/firebase_vertexai/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png and /dev/null differ diff --git a/packages/firebase_vertexai/firebase_vertexai/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json b/packages/firebase_vertexai/firebase_vertexai/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json deleted file mode 100644 index 0bedcf2fd467..000000000000 --- a/packages/firebase_vertexai/firebase_vertexai/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "filename" : "LaunchImage.png", - "scale" : "1x" - }, - { - "idiom" : "universal", - "filename" : "LaunchImage@2x.png", - "scale" : "2x" - }, - { - "idiom" : "universal", - "filename" : "LaunchImage@3x.png", - "scale" : "3x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} diff --git a/packages/firebase_vertexai/firebase_vertexai/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png b/packages/firebase_vertexai/firebase_vertexai/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png deleted file mode 100644 index 9da19eacad3b..000000000000 Binary files a/packages/firebase_vertexai/firebase_vertexai/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png and /dev/null differ diff --git a/packages/firebase_vertexai/firebase_vertexai/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png b/packages/firebase_vertexai/firebase_vertexai/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png deleted file mode 100644 index 9da19eacad3b..000000000000 Binary files a/packages/firebase_vertexai/firebase_vertexai/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png and /dev/null differ diff --git a/packages/firebase_vertexai/firebase_vertexai/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png b/packages/firebase_vertexai/firebase_vertexai/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png deleted file mode 100644 index 9da19eacad3b..000000000000 Binary files a/packages/firebase_vertexai/firebase_vertexai/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png and /dev/null differ diff --git a/packages/firebase_vertexai/firebase_vertexai/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md b/packages/firebase_vertexai/firebase_vertexai/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md deleted file mode 100644 index 89c2725b70f1..000000000000 --- a/packages/firebase_vertexai/firebase_vertexai/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md +++ /dev/null @@ -1,5 +0,0 @@ -# Launch Screen Assets - -You can customize the launch screen with your own desired assets by replacing the image files in this directory. - -You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. \ No newline at end of file diff --git a/packages/firebase_vertexai/firebase_vertexai/example/ios/Runner/Base.lproj/LaunchScreen.storyboard b/packages/firebase_vertexai/firebase_vertexai/example/ios/Runner/Base.lproj/LaunchScreen.storyboard deleted file mode 100644 index f2e259c7c939..000000000000 --- a/packages/firebase_vertexai/firebase_vertexai/example/ios/Runner/Base.lproj/LaunchScreen.storyboard +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/packages/firebase_vertexai/firebase_vertexai/example/ios/Runner/Base.lproj/Main.storyboard b/packages/firebase_vertexai/firebase_vertexai/example/ios/Runner/Base.lproj/Main.storyboard deleted file mode 100644 index f3c28516fb38..000000000000 --- a/packages/firebase_vertexai/firebase_vertexai/example/ios/Runner/Base.lproj/Main.storyboard +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/packages/firebase_vertexai/firebase_vertexai/example/ios/Runner/Info.plist b/packages/firebase_vertexai/firebase_vertexai/example/ios/Runner/Info.plist deleted file mode 100644 index ce396f3af000..000000000000 --- a/packages/firebase_vertexai/firebase_vertexai/example/ios/Runner/Info.plist +++ /dev/null @@ -1,51 +0,0 @@ - - - - - CFBundleDevelopmentRegion - $(DEVELOPMENT_LANGUAGE) - CFBundleDisplayName - Vertex Ai Example - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - vertex_ai_example - CFBundlePackageType - APPL - CFBundleShortVersionString - $(FLUTTER_BUILD_NAME) - CFBundleSignature - ???? - CFBundleVersion - $(FLUTTER_BUILD_NUMBER) - LSRequiresIPhoneOS - - UILaunchStoryboardName - LaunchScreen - UIMainStoryboardFile - Main - UISupportedInterfaceOrientations - - UIInterfaceOrientationPortrait - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - UISupportedInterfaceOrientations~ipad - - UIInterfaceOrientationPortrait - UIInterfaceOrientationPortraitUpsideDown - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - CADisableMinimumFrameDurationOnPhone - - UIApplicationSupportsIndirectInputEvents - - NSMicrophoneUsageDescription - Need microphone to talk with Gemini - - diff --git a/packages/firebase_vertexai/firebase_vertexai/example/ios/Runner/Runner-Bridging-Header.h b/packages/firebase_vertexai/firebase_vertexai/example/ios/Runner/Runner-Bridging-Header.h deleted file mode 100644 index 308a2a560b42..000000000000 --- a/packages/firebase_vertexai/firebase_vertexai/example/ios/Runner/Runner-Bridging-Header.h +++ /dev/null @@ -1 +0,0 @@ -#import "GeneratedPluginRegistrant.h" diff --git a/packages/firebase_vertexai/firebase_vertexai/example/lib/main.dart b/packages/firebase_vertexai/firebase_vertexai/example/lib/main.dart deleted file mode 100644 index be06969a756d..000000000000 --- a/packages/firebase_vertexai/firebase_vertexai/example/lib/main.dart +++ /dev/null @@ -1,327 +0,0 @@ -// Copyright 2024 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import 'package:firebase_ai/firebase_ai.dart'; -import 'package:firebase_auth/firebase_auth.dart'; -import 'package:firebase_core/firebase_core.dart'; -import 'package:firebase_vertexai/firebase_vertexai.dart'; -import 'package:flutter/material.dart'; - -import 'pages/audio_page.dart'; -import 'pages/bidi_page.dart'; -// Import after file is generated through flutterfire_cli. -// import 'package:vertex_ai_example/firebase_options.dart'; - -import 'pages/chat_page.dart'; -import 'pages/document.dart'; -import 'pages/function_calling_page.dart'; -import 'pages/image_prompt_page.dart'; -import 'pages/imagen_page.dart'; -import 'pages/schema_page.dart'; -import 'pages/token_count_page.dart'; -import 'pages/video_page.dart'; - -void main() async { - WidgetsFlutterBinding.ensureInitialized(); - // Enable this line instead once have the firebase_options.dart generated and - // imported through flutterfire_cli. - // await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform); - await Firebase.initializeApp(); - await FirebaseAuth.instance.signInAnonymously(); - runApp(const GenerativeAISample()); -} - -class GenerativeAISample extends StatefulWidget { - const GenerativeAISample({super.key}); - - @override - State createState() => _GenerativeAISampleState(); -} - -class _GenerativeAISampleState extends State { - bool _useVertexBackend = false; - late GenerativeModel _currentModel; - late ImagenModel _currentImagenModel; - int _currentBottomNavIndex = 0; - - @override - void initState() { - super.initState(); - - _initializeModel(_useVertexBackend); - } - - void _initializeModel(bool useVertexBackend) { - var generationConfig = ImagenGenerationConfig( - negativePrompt: 'frog', - numberOfImages: 1, - aspectRatio: ImagenAspectRatio.square1x1, - imageFormat: ImagenFormat.jpeg(compressionQuality: 75), - ); - if (useVertexBackend) { - final vertexInstance = - // ignore: deprecated_member_use - FirebaseVertexAI.instanceFor(auth: FirebaseAuth.instance); - _currentModel = vertexInstance.generativeModel(model: 'gemini-1.5-flash'); - _currentImagenModel = vertexInstance.imagenModel( - model: 'imagen-3.0-generate-001', - generationConfig: generationConfig, - safetySettings: ImagenSafetySettings( - ImagenSafetyFilterLevel.blockLowAndAbove, - ImagenPersonFilterLevel.allowAdult, - ), - ); - } else { - final googleAI = FirebaseAI.googleAI(auth: FirebaseAuth.instance); - _currentModel = googleAI.generativeModel(model: 'gemini-2.0-flash'); - _currentImagenModel = googleAI.imagenModel( - model: 'imagen-3.0-generate-001', - generationConfig: generationConfig, - safetySettings: ImagenSafetySettings( - ImagenSafetyFilterLevel.blockLowAndAbove, - ImagenPersonFilterLevel.allowAdult, - ), - ); - } - } - - void _toggleBackend(bool value) { - setState(() { - _useVertexBackend = value; - }); - _initializeModel(_useVertexBackend); - } - - void _onBottomNavTapped(int index) { - setState(() { - _currentBottomNavIndex = index; - }); - } - - @override - Widget build(BuildContext context) { - return MaterialApp( - title: 'Flutter + ${_useVertexBackend ? 'Vertex AI' : 'Google AI'}', - debugShowCheckedModeBanner: false, - themeMode: ThemeMode.dark, - theme: ThemeData( - colorScheme: ColorScheme.fromSeed( - brightness: Brightness.dark, - seedColor: const Color.fromARGB(255, 171, 222, 244), - ), - useMaterial3: true, - ), - home: HomeScreen( - key: ValueKey( - '${_useVertexBackend}_${_currentModel.hashCode}', - ), - model: _currentModel, - imagenModel: _currentImagenModel, - useVertexBackend: _useVertexBackend, - onBackendChanged: _toggleBackend, - selectedIndex: _currentBottomNavIndex, - onSelectedIndexChanged: _onBottomNavTapped, - ), - ); - } -} - -class HomeScreen extends StatefulWidget { - final GenerativeModel model; - final ImagenModel imagenModel; - final bool useVertexBackend; - final ValueChanged onBackendChanged; - final int selectedIndex; - final ValueChanged onSelectedIndexChanged; - - const HomeScreen({ - super.key, - required this.model, - required this.imagenModel, - required this.useVertexBackend, - required this.onBackendChanged, - required this.selectedIndex, - required this.onSelectedIndexChanged, - }); - - @override - State createState() => _HomeScreenState(); -} - -class _HomeScreenState extends State { - void _onItemTapped(int index) { - widget.onSelectedIndexChanged(index); - } - -// Method to build the selected page on demand - Widget _buildSelectedPage( - int index, - GenerativeModel currentModel, - ImagenModel currentImagenModel, - bool useVertexBackend, - ) { - switch (index) { - case 0: - return ChatPage(title: 'Chat', model: currentModel); - case 1: - return AudioPage(title: 'Audio', model: currentModel); - case 2: - return TokenCountPage(title: 'Token Count', model: currentModel); - case 3: - // FunctionCallingPage initializes its own model as per original design - return FunctionCallingPage( - title: 'Function Calling', - useVertexBackend: useVertexBackend, - ); - case 4: - return ImagePromptPage(title: 'Image Prompt', model: currentModel); - case 5: - return ImagenPage(title: 'Imagen Model', model: currentImagenModel); - case 6: - return SchemaPromptPage(title: 'Schema Prompt', model: currentModel); - case 7: - return DocumentPage(title: 'Document Prompt', model: currentModel); - case 8: - return VideoPage(title: 'Video Prompt', model: currentModel); - case 9: - return BidiPage(title: 'Bidi Stream', model: currentModel); - default: - // Fallback to the first page in case of an unexpected index - return ChatPage(title: 'Chat', model: currentModel); - } - } - - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar( - title: Text( - 'Flutter + ${widget.useVertexBackend ? 'Vertex AI' : 'Google AI'}', - ), - actions: [ - Padding( - padding: const EdgeInsets.symmetric(horizontal: 16), - child: Row( - mainAxisSize: MainAxisSize.min, - children: [ - Text( - 'Google AI', - style: TextStyle( - fontSize: 12, - color: widget.useVertexBackend - ? Theme.of(context) - .colorScheme - .onSurface - .withValues(alpha: 0.7) - : Theme.of(context).colorScheme.primary, - ), - ), - Switch( - value: widget.useVertexBackend, - onChanged: widget.onBackendChanged, - activeTrackColor: Colors.green.withValues(alpha: 0.5), - inactiveTrackColor: Colors.blueGrey.withValues(alpha: 0.5), - activeThumbColor: Colors.green, - inactiveThumbColor: Colors.blueGrey, - ), - Text( - 'Vertex AI', - style: TextStyle( - fontSize: 12, - color: widget.useVertexBackend - ? Theme.of(context).colorScheme.primary - : Theme.of(context) - .colorScheme - .onSurface - .withValues(alpha: 0.7), - ), - ), - ], - ), - ), - ], - ), - body: Center( - child: _buildSelectedPage( - widget.selectedIndex, - widget.model, - widget.imagenModel, - widget.useVertexBackend, - ), - ), - bottomNavigationBar: BottomNavigationBar( - type: BottomNavigationBarType.fixed, - selectedFontSize: 10, - unselectedFontSize: 9, - selectedItemColor: Theme.of(context).colorScheme.primary, - unselectedItemColor: - Theme.of(context).colorScheme.onSurface.withValues(alpha: 0.7), - items: const [ - BottomNavigationBarItem( - icon: Icon(Icons.chat), - label: 'Chat', - tooltip: 'Chat', - ), - BottomNavigationBarItem( - icon: Icon(Icons.mic), - label: 'Audio', - tooltip: 'Audio Prompt', - ), - BottomNavigationBarItem( - icon: Icon(Icons.numbers), - label: 'Tokens', - tooltip: 'Token Count', - ), - BottomNavigationBarItem( - icon: Icon(Icons.functions), - label: 'Functions', - tooltip: 'Function Calling', - ), - BottomNavigationBarItem( - icon: Icon(Icons.image), - label: 'Image', - tooltip: 'Image Prompt', - ), - BottomNavigationBarItem( - icon: Icon(Icons.image_search), - label: 'Imagen', - tooltip: 'Imagen Model', - ), - BottomNavigationBarItem( - icon: Icon(Icons.schema), - label: 'Schema', - tooltip: 'Schema Prompt', - ), - BottomNavigationBarItem( - icon: Icon(Icons.edit_document), - label: 'Document', - tooltip: 'Document Prompt', - ), - BottomNavigationBarItem( - icon: Icon(Icons.video_collection), - label: 'Video', - tooltip: 'Video Prompt', - ), - BottomNavigationBarItem( - icon: Icon(Icons.stream), - label: 'Bidi', - tooltip: 'Bidi Stream', - ), - ], - currentIndex: widget.selectedIndex, - onTap: _onItemTapped, - ), - ); - } -} diff --git a/packages/firebase_vertexai/firebase_vertexai/example/lib/pages/audio_page.dart b/packages/firebase_vertexai/firebase_vertexai/example/lib/pages/audio_page.dart deleted file mode 100644 index 235022bf1338..000000000000 --- a/packages/firebase_vertexai/firebase_vertexai/example/lib/pages/audio_page.dart +++ /dev/null @@ -1,185 +0,0 @@ -// Copyright 2025 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import 'dart:io'; - -import 'package:flutter/material.dart'; -import 'package:firebase_vertexai/firebase_vertexai.dart'; -import '../widgets/message_widget.dart'; -import 'package:record/record.dart'; -import 'package:path_provider/path_provider.dart'; - -final record = AudioRecorder(); - -class AudioPage extends StatefulWidget { - const AudioPage({super.key, required this.title, required this.model}); - - final String title; - final GenerativeModel model; - - @override - State createState() => _AudioPageState(); -} - -class _AudioPageState extends State { - ChatSession? chat; - final ScrollController _scrollController = ScrollController(); - final List _messages = []; - bool _recording = false; - - @override - void initState() { - super.initState(); - chat = widget.model.startChat(); - } - - Future recordAudio() async { - if (!await record.hasPermission()) { - print('Audio recording permission denied'); - return; - } - - final dir = Directory( - '${(await getApplicationDocumentsDirectory()).path}/libs/recordings', - ); - - // ignore: avoid_slow_async_io - if (!await dir.exists()) { - await dir.create(recursive: true); - } - - String filePath = - '${dir.path}/recording_${DateTime.now().millisecondsSinceEpoch}.wav'; - - await record.start( - const RecordConfig( - encoder: AudioEncoder.wav, - ), - path: filePath, - ); - } - - Future stopRecord() async { - var path = await record.stop(); - - if (path == null) { - print('Failed to stop recording'); - return; - } - - debugPrint('Recording saved to: $path'); - - try { - File file = File(path); - final audio = await file.readAsBytes(); - debugPrint('Audio file size: ${audio.length} bytes'); - - final audioPart = InlineDataPart('audio/wav', audio); - - await _submitAudioToModel(audioPart); - - await file.delete(); - debugPrint('Recording deleted successfully.'); - } catch (e) { - debugPrint('Error processing recording: $e'); - } - } - - Future _submitAudioToModel(audioPart) async { - try { - const textPrompt = 'What is in the audio recording?'; - - setState(() { - _messages.add(MessageData(text: textPrompt, fromUser: true)); - }); - - final response = await widget.model.generateContent([ - Content.multi([const TextPart(textPrompt), audioPart]), - ]); - - setState(() { - _messages.add(MessageData(text: response.text, fromUser: false)); - }); - - debugPrint(response.text); - } catch (e) { - debugPrint('Error sending audio to model: $e'); - } - } - - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar( - title: Text(widget.title), - ), - body: Padding( - padding: const EdgeInsets.all(8), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Expanded( - child: ListView.builder( - controller: _scrollController, - itemBuilder: (context, idx) { - return MessageWidget( - text: _messages[idx].text, - image: _messages[idx].image, - isFromUser: _messages[idx].fromUser ?? false, - ); - }, - itemCount: _messages.length, - ), - ), - Padding( - padding: const EdgeInsets.symmetric( - vertical: 25, - horizontal: 15, - ), - child: Row( - children: [ - IconButton( - onPressed: () async { - setState(() { - _recording = !_recording; - }); - if (_recording) { - await recordAudio(); - } else { - await stopRecord(); - } - }, - icon: Icon( - Icons.mic, - color: _recording - ? Colors.blueGrey - : Theme.of(context).colorScheme.primary, - ), - ), - const SizedBox.square( - dimension: 15, - ), - const Text( - 'Tap the mic to record, tap again to submit', - ), - ], - ), - ), - ], - ), - ), - ); - } -} diff --git a/packages/firebase_vertexai/firebase_vertexai/example/lib/pages/bidi_page.dart b/packages/firebase_vertexai/firebase_vertexai/example/lib/pages/bidi_page.dart deleted file mode 100644 index 4d6cd0077c41..000000000000 --- a/packages/firebase_vertexai/firebase_vertexai/example/lib/pages/bidi_page.dart +++ /dev/null @@ -1,424 +0,0 @@ -// Copyright 2025 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -import 'dart:async'; -import 'dart:developer' as developer; - -import 'package:flutter/material.dart'; -import 'package:firebase_vertexai/firebase_vertexai.dart'; - -import '../utils/audio_input.dart'; -import '../utils/audio_output.dart'; -import '../widgets/message_widget.dart'; - -class BidiPage extends StatefulWidget { - const BidiPage({super.key, required this.title, required this.model}); - - final String title; - final GenerativeModel model; - - @override - State createState() => _BidiPageState(); -} - -class LightControl { - final int? brightness; - final String? colorTemperature; - - LightControl({this.brightness, this.colorTemperature}); -} - -class _BidiPageState extends State { - final ScrollController _scrollController = ScrollController(); - final TextEditingController _textController = TextEditingController(); - final FocusNode _textFieldFocus = FocusNode(); - final List _messages = []; - bool _loading = false; - bool _sessionOpening = false; - bool _recording = false; - late LiveGenerativeModel _liveModel; - late LiveSession _session; - StreamController _stopController = StreamController(); - final _audioOutput = AudioOutput(); - final _audioInput = AudioInput(); - - @override - void initState() { - super.initState(); - - final config = LiveGenerationConfig( - speechConfig: SpeechConfig(voiceName: 'Fenrir'), - responseModalities: [ - ResponseModalities.audio, - ], - ); - - // ignore: deprecated_member_use - _liveModel = FirebaseVertexAI.instance.liveGenerativeModel( - model: 'gemini-2.0-flash-exp', - liveGenerationConfig: config, - tools: [ - Tool.functionDeclarations([lightControlTool]), - ], - ); - _initAudio(); - } - - Future _initAudio() async { - await _audioOutput.init(); - await _audioInput.init(); - } - - void _scrollDown() { - WidgetsBinding.instance.addPostFrameCallback( - (_) => _scrollController.animateTo( - _scrollController.position.maxScrollExtent, - duration: const Duration( - milliseconds: 750, - ), - curve: Curves.easeOutCirc, - ), - ); - } - - @override - void dispose() { - if (_sessionOpening) { - _stopController.close(); - _sessionOpening = false; - _session.close(); - } - super.dispose(); - } - - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar( - title: Text(widget.title), - ), - body: Padding( - padding: const EdgeInsets.all(8), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Expanded( - child: ListView.builder( - controller: _scrollController, - itemBuilder: (context, idx) { - return MessageWidget( - text: _messages[idx].text, - image: _messages[idx].image, - isFromUser: _messages[idx].fromUser ?? false, - ); - }, - itemCount: _messages.length, - ), - ), - Padding( - padding: const EdgeInsets.symmetric( - vertical: 25, - horizontal: 15, - ), - child: Row( - children: [ - Expanded( - child: TextField( - autofocus: true, - focusNode: _textFieldFocus, - controller: _textController, - onSubmitted: _sendTextPrompt, - ), - ), - const SizedBox.square( - dimension: 15, - ), - IconButton( - tooltip: 'Start Streaming', - onPressed: !_loading - ? () async { - await _setupSession(); - } - : null, - icon: Icon( - Icons.network_wifi, - color: _sessionOpening - ? Theme.of(context).colorScheme.secondary - : Theme.of(context).colorScheme.primary, - ), - ), - IconButton( - tooltip: 'Send Stream Message', - onPressed: !_loading - ? () async { - if (_recording) { - await _stopRecording(); - } else { - await _startRecording(); - } - } - : null, - icon: Icon( - _recording ? Icons.stop : Icons.mic, - color: _loading - ? Theme.of(context).colorScheme.secondary - : Theme.of(context).colorScheme.primary, - ), - ), - if (!_loading) - IconButton( - onPressed: () async { - await _sendTextPrompt(_textController.text); - }, - icon: Icon( - Icons.send, - color: Theme.of(context).colorScheme.primary, - ), - ) - else - const CircularProgressIndicator(), - ], - ), - ), - ], - ), - ), - ); - } - - final lightControlTool = FunctionDeclaration( - 'setLightValues', - 'Set the brightness and color temperature of a room light.', - parameters: { - 'brightness': Schema.integer( - description: 'Light level from 0 to 100. ' - 'Zero is off and 100 is full brightness.', - ), - 'colorTemperature': Schema.string( - description: 'Color temperature of the light fixture, ' - 'which can be `daylight`, `cool` or `warm`.', - ), - }, - ); - - Future> _setLightValues({ - int? brightness, - String? colorTemperature, - }) async { - final apiResponse = { - 'colorTemprature': 'warm', - 'brightness': brightness, - }; - return apiResponse; - } - - Future _setupSession() async { - setState(() { - _loading = true; - }); - - if (!_sessionOpening) { - _session = await _liveModel.connect(); - _sessionOpening = true; - _stopController = StreamController(); - unawaited( - _processMessagesContinuously( - stopSignal: _stopController, - ), - ); - } else { - _stopController.add(true); - await _stopController.close(); - - await _session.close(); - _sessionOpening = false; - } - - setState(() { - _loading = false; - }); - } - - Future _startRecording() async { - setState(() { - _recording = true; - }); - try { - var inputStream = await _audioInput.startRecordingStream(); - await _audioOutput.playStream(); - // Map the Uint8List stream to InlineDataPart stream - if (inputStream != null) { - final inlineDataStream = inputStream.map((data) { - return InlineDataPart('audio/pcm', data); - }); - - await _session.sendMediaStream(inlineDataStream); - } - } catch (e) { - developer.log(e.toString()); - _showError(e.toString()); - } - } - - Future _stopRecording() async { - try { - await _audioInput.stopRecording(); - } catch (e) { - _showError(e.toString()); - } - - setState(() { - _recording = false; - }); - } - - Future _sendTextPrompt(String textPrompt) async { - setState(() { - _loading = true; - }); - try { - final prompt = Content.text(textPrompt); - await _session.send(input: prompt, turnComplete: true); - } catch (e) { - _showError(e.toString()); - } - - setState(() { - _loading = false; - }); - } - - Future _processMessagesContinuously({ - required StreamController stopSignal, - }) async { - bool shouldContinue = true; - - //listen to the stop signal stream - stopSignal.stream.listen((stop) { - if (stop) { - shouldContinue = false; - } - }); - - while (shouldContinue) { - try { - await for (final message in _session.receive()) { - // Process the received message - await _handleLiveServerMessage(message); - } - } catch (e) { - _showError(e.toString()); - break; - } - - // Optionally add a delay before restarting, if needed - await Future.delayed( - const Duration(milliseconds: 100), - ); // Small delay to prevent tight loops - } - } - - Future _handleLiveServerMessage(LiveServerResponse response) async { - final message = response.message; - - if (message is LiveServerContent) { - if (message.modelTurn != null) { - await _handleLiveServerContent(message); - } - if (message.interrupted != null && message.interrupted!) { - developer.log('Interrupted: $response'); - } - } else if (message is LiveServerToolCall && message.functionCalls != null) { - await _handleLiveServerToolCall(message); - } - } - - Future _handleLiveServerContent(LiveServerContent response) async { - final partList = response.modelTurn?.parts; - if (partList != null) { - for (final part in partList) { - if (part is TextPart) { - await _handleTextPart(part); - } else if (part is InlineDataPart) { - await _handleInlineDataPart(part); - } else { - developer.log('receive part with type ${part.runtimeType}'); - } - } - } - } - - Future _handleTextPart(TextPart part) async { - if (!_loading) { - setState(() { - _loading = true; - }); - } - _messages.add(MessageData(text: part.text, fromUser: false)); - setState(() { - _loading = false; - _scrollDown(); - }); - } - - Future _handleInlineDataPart(InlineDataPart part) async { - if (part.mimeType.startsWith('audio')) { - _audioOutput.addAudioStream(part.bytes); - } - } - - Future _handleLiveServerToolCall(LiveServerToolCall response) async { - final functionCalls = response.functionCalls!.toList(); - if (functionCalls.isNotEmpty) { - final functionCall = functionCalls.first; - if (functionCall.name == 'setLightValues') { - var color = functionCall.args['colorTemperature']! as String; - var brightness = functionCall.args['brightness']! as int; - final functionResult = await _setLightValues( - brightness: brightness, - colorTemperature: color, - ); - await _session.send( - input: Content.functionResponse(functionCall.name, functionResult), - ); - } else { - throw UnimplementedError( - 'Function not declared to the model: ${functionCall.name}', - ); - } - } - } - - void _showError(String message) { - showDialog( - context: context, - builder: (context) { - return AlertDialog( - title: const Text('Something went wrong'), - content: SingleChildScrollView( - child: SelectableText(message), - ), - actions: [ - TextButton( - onPressed: () { - Navigator.of(context).pop(); - }, - child: const Text('OK'), - ), - ], - ); - }, - ); - } -} diff --git a/packages/firebase_vertexai/firebase_vertexai/example/lib/pages/chat_page.dart b/packages/firebase_vertexai/firebase_vertexai/example/lib/pages/chat_page.dart deleted file mode 100644 index 489fccafa577..000000000000 --- a/packages/firebase_vertexai/firebase_vertexai/example/lib/pages/chat_page.dart +++ /dev/null @@ -1,239 +0,0 @@ -// Copyright 2025 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import 'package:flutter/material.dart'; -import 'package:firebase_vertexai/firebase_vertexai.dart'; -import '../widgets/message_widget.dart'; - -class ChatPage extends StatefulWidget { - const ChatPage({super.key, required this.title, required this.model}); - - final String title; - final GenerativeModel model; - - @override - State createState() => _ChatPageState(); -} - -class _ChatPageState extends State { - ChatSession? _chat; - final ScrollController _scrollController = ScrollController(); - final TextEditingController _textController = TextEditingController(); - final FocusNode _textFieldFocus = FocusNode(); - final List _messages = []; - bool _loading = false; - - @override - void initState() { - super.initState(); - _chat = widget.model.startChat(); - } - - void _scrollDown() { - WidgetsBinding.instance.addPostFrameCallback( - (_) => _scrollController.animateTo( - _scrollController.position.maxScrollExtent, - duration: const Duration( - milliseconds: 750, - ), - curve: Curves.easeOutCirc, - ), - ); - } - - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar( - title: Text(widget.title), - ), - body: Padding( - padding: const EdgeInsets.all(8), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Expanded( - child: ListView.builder( - controller: _scrollController, - itemBuilder: (context, idx) { - return MessageWidget( - text: _messages[idx].text, - image: _messages[idx].image, - isFromUser: _messages[idx].fromUser ?? false, - ); - }, - itemCount: _messages.length, - ), - ), - Padding( - padding: const EdgeInsets.symmetric( - vertical: 25, - horizontal: 15, - ), - child: Row( - children: [ - Expanded( - child: TextField( - autofocus: true, - focusNode: _textFieldFocus, - controller: _textController, - onSubmitted: _sendChatMessage, - ), - ), - const SizedBox.square( - dimension: 15, - ), - if (!_loading) - IconButton( - onPressed: () async { - await _imageResponse(_textController.text); - }, - icon: Icon( - Icons.image, - color: Theme.of(context).colorScheme.primary, - ), - tooltip: 'Image response', - ), - if (!_loading) - IconButton( - onPressed: () async { - await _sendChatMessage(_textController.text); - }, - icon: Icon( - Icons.send, - color: Theme.of(context).colorScheme.primary, - ), - ) - else - const CircularProgressIndicator(), - ], - ), - ), - ], - ), - ), - ); - } - - Future _sendChatMessage(String message) async { - setState(() { - _loading = true; - }); - - try { - _messages.add(MessageData(text: message, fromUser: true)); - var response = await _chat?.sendMessage( - Content.text(message), - ); - var text = response?.text; - _messages.add(MessageData(text: text, fromUser: false)); - - if (text == null) { - _showError('No response from API.'); - return; - } else { - setState(() { - _loading = false; - _scrollDown(); - }); - } - } catch (e) { - _showError(e.toString()); - setState(() { - _loading = false; - }); - } finally { - _textController.clear(); - setState(() { - _loading = false; - }); - _textFieldFocus.requestFocus(); - } - } - - Future _imageResponse(String message) async { - setState(() { - _loading = true; - }); - - try { - _messages.add(MessageData(text: message, fromUser: true)); - var response = await widget.model.generateContent( - [Content.text(message)], - generationConfig: GenerationConfig( - responseModalities: [ - ResponseModalities.text, - ResponseModalities.image, - ], - ), - ); - var inlineDatas = response.inlineDataParts.toList(); - - if (inlineDatas.isEmpty) { - _showError('No response from API.'); - return; - } else { - for (final inlineData in inlineDatas) { - if (inlineData.mimeType.contains('image')) { - _messages.add( - MessageData( - text: response.text, - image: Image.memory(inlineData.bytes), - fromUser: false, - ), - ); - } - } - setState(() { - _loading = false; - _scrollDown(); - }); - } - } catch (e) { - _showError(e.toString()); - setState(() { - _loading = false; - }); - } finally { - _textController.clear(); - setState(() { - _loading = false; - }); - _textFieldFocus.requestFocus(); - } - } - - void _showError(String message) { - showDialog( - context: context, - builder: (context) { - return AlertDialog( - title: const Text('Something went wrong'), - content: SingleChildScrollView( - child: SelectableText(message), - ), - actions: [ - TextButton( - onPressed: () { - Navigator.of(context).pop(); - }, - child: const Text('OK'), - ), - ], - ); - }, - ); - } -} diff --git a/packages/firebase_vertexai/firebase_vertexai/example/lib/pages/document.dart b/packages/firebase_vertexai/firebase_vertexai/example/lib/pages/document.dart deleted file mode 100644 index 65eceb62ed2e..000000000000 --- a/packages/firebase_vertexai/firebase_vertexai/example/lib/pages/document.dart +++ /dev/null @@ -1,115 +0,0 @@ -// Copyright 2025 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import 'package:flutter/material.dart'; -import 'package:firebase_vertexai/firebase_vertexai.dart'; -import 'package:flutter/services.dart'; -import '../widgets/message_widget.dart'; - -class DocumentPage extends StatefulWidget { - const DocumentPage({super.key, required this.title, required this.model}); - - final String title; - final GenerativeModel model; - - @override - State createState() => _DocumentPageState(); -} - -class _DocumentPageState extends State { - ChatSession? chat; - late final GenerativeModel model; - final List _messages = []; - bool _loading = false; - - @override - void initState() { - super.initState(); - chat = widget.model.startChat(); - } - - Future _testDocumentReading(model) async { - try { - ByteData docBytes = - await rootBundle.load('assets/documents/gemini_summary.pdf'); - - const _prompt = - 'Write me a summary in one sentence what this document is about.'; - - setState(() { - _messages.add(MessageData(text: _prompt, fromUser: true)); - }); - - final pdfPart = - InlineDataPart('application/pdf', docBytes.buffer.asUint8List()); - - final response = await widget.model.generateContent([ - Content.multi([const TextPart(_prompt), pdfPart]), - ]); - - setState(() { - _messages.add(MessageData(text: response.text, fromUser: false)); - }); - } catch (e) { - print('Error sending document to model: $e'); - } - } - - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar( - title: Text(widget.title), - ), - body: Padding( - padding: const EdgeInsets.all(8), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Expanded( - child: ListView.builder( - itemBuilder: (context, idx) { - return MessageWidget( - text: _messages[idx].text, - isFromUser: _messages[idx].fromUser ?? false, - ); - }, - itemCount: _messages.length, - ), - ), - Padding( - padding: const EdgeInsets.symmetric( - vertical: 25, - horizontal: 15, - ), - child: Center( - child: SizedBox( - child: ElevatedButton( - onPressed: !_loading - ? () async { - await _testDocumentReading(widget.model); - } - : null, - child: const Text('Test Document Reading'), - ), - ), - ), - ), - ], - ), - ), - ); - } -} diff --git a/packages/firebase_vertexai/firebase_vertexai/example/lib/pages/function_calling_page.dart b/packages/firebase_vertexai/firebase_vertexai/example/lib/pages/function_calling_page.dart deleted file mode 100644 index fe4f976c41ea..000000000000 --- a/packages/firebase_vertexai/firebase_vertexai/example/lib/pages/function_calling_page.dart +++ /dev/null @@ -1,203 +0,0 @@ -// Copyright 2025 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import 'package:flutter/material.dart'; -import 'package:firebase_ai/firebase_ai.dart'; -import 'package:firebase_vertexai/firebase_vertexai.dart'; -import 'package:firebase_auth/firebase_auth.dart'; - -import '../widgets/message_widget.dart'; - -class FunctionCallingPage extends StatefulWidget { - const FunctionCallingPage({ - super.key, - required this.title, - required this.useVertexBackend, - }); - - final String title; - final bool useVertexBackend; - - @override - State createState() => _FunctionCallingPageState(); -} - -class Location { - final String city; - final String state; - - Location(this.city, this.state); -} - -class _FunctionCallingPageState extends State { - late final GenerativeModel _functionCallModel; - final List _messages = []; - bool _loading = false; - - @override - void initState() { - super.initState(); - if (widget.useVertexBackend) { - // ignore: deprecated_member_use - var vertexAI = FirebaseVertexAI.instanceFor(auth: FirebaseAuth.instance); - _functionCallModel = vertexAI.generativeModel( - model: 'gemini-2.0-flash', - tools: [ - Tool.functionDeclarations([fetchWeatherTool]), - ], - ); - } else { - var googleAI = FirebaseAI.googleAI(auth: FirebaseAuth.instance); - _functionCallModel = googleAI.generativeModel( - model: 'gemini-2.0-flash', - tools: [ - Tool.functionDeclarations([fetchWeatherTool]), - ], - ); - } - } - - // This is a hypothetical API to return a fake weather data collection for - // certain location - Future> fetchWeather( - Location location, - String date, - ) async { - // TODO(developer): Call a real weather API. - // Mock response from the API. In developer live code this would call the - // external API and return what that API returns. - final apiResponse = { - 'temperature': 38, - 'chancePrecipitation': '56%', - 'cloudConditions': 'partly-cloudy', - }; - return apiResponse; - } - - /// Actual function to demonstrate the function calling feature. - final fetchWeatherTool = FunctionDeclaration( - 'fetchWeather', - 'Get the weather conditions for a specific city on a specific date.', - parameters: { - 'location': Schema.object( - description: 'The name of the city and its state for which to get ' - 'the weather. Only cities in the USA are supported.', - properties: { - 'city': Schema.string( - description: 'The city of the location.', - ), - 'state': Schema.string( - description: 'The state of the location.', - ), - }, - ), - 'date': Schema.string( - description: 'The date for which to get the weather. ' - 'Date must be in the format: YYYY-MM-DD.', - ), - }, - ); - - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar( - title: Text(widget.title), - ), - body: Padding( - padding: const EdgeInsets.all(8), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Expanded( - child: ListView.builder( - itemBuilder: (context, idx) { - return MessageWidget( - text: _messages[idx].text, - isFromUser: _messages[idx].fromUser ?? false, - ); - }, - itemCount: _messages.length, - ), - ), - Padding( - padding: const EdgeInsets.symmetric( - vertical: 25, - horizontal: 15, - ), - child: Row( - children: [ - Expanded( - child: ElevatedButton( - onPressed: !_loading - ? () async { - await _testFunctionCalling(); - } - : null, - child: const Text('Test Function Calling'), - ), - ), - ], - ), - ), - ], - ), - ), - ); - } - - Future _testFunctionCalling() async { - setState(() { - _loading = true; - }); - final functionCallChat = _functionCallModel.startChat(); - const prompt = 'What is the weather like in Boston on 10/02 in year 2024?'; - - // Send the message to the generative model. - var response = await functionCallChat.sendMessage( - Content.text(prompt), - ); - - final functionCalls = response.functionCalls.toList(); - // When the model response with a function call, invoke the function. - if (functionCalls.isNotEmpty) { - final functionCall = functionCalls.first; - if (functionCall.name == 'fetchWeather') { - Map location = - functionCall.args['location']! as Map; - var date = functionCall.args['date']! as String; - var city = location['city'] as String; - var state = location['state'] as String; - final functionResult = await fetchWeather(Location(city, state), date); - // Send the response to the model so that it can use the result to - // generate text for the user. - response = await functionCallChat.sendMessage( - Content.functionResponse(functionCall.name, functionResult), - ); - } else { - throw UnimplementedError( - 'Function not declared to the model: ${functionCall.name}', - ); - } - } - // When the model responds with non-null text content, print it. - if (response.text case final text?) { - _messages.add(MessageData(text: text)); - setState(() { - _loading = false; - }); - } - } -} diff --git a/packages/firebase_vertexai/firebase_vertexai/example/lib/pages/image_prompt_page.dart b/packages/firebase_vertexai/firebase_vertexai/example/lib/pages/image_prompt_page.dart deleted file mode 100644 index a34d55887553..000000000000 --- a/packages/firebase_vertexai/firebase_vertexai/example/lib/pages/image_prompt_page.dart +++ /dev/null @@ -1,243 +0,0 @@ -// Copyright 2025 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import 'package:flutter/material.dart'; -import 'package:firebase_vertexai/firebase_vertexai.dart'; -import 'package:flutter/services.dart'; -import '../widgets/message_widget.dart'; - -class ImagePromptPage extends StatefulWidget { - const ImagePromptPage({super.key, required this.title, required this.model}); - - final String title; - final GenerativeModel model; - - @override - State createState() => _ImagePromptPageState(); -} - -class _ImagePromptPageState extends State { - final ScrollController _scrollController = ScrollController(); - final TextEditingController _textController = TextEditingController(); - final FocusNode _textFieldFocus = FocusNode(); - final List _generatedContent = []; - bool _loading = false; - - void _scrollDown() { - WidgetsBinding.instance.addPostFrameCallback( - (_) => _scrollController.animateTo( - _scrollController.position.maxScrollExtent, - duration: const Duration( - milliseconds: 750, - ), - curve: Curves.easeOutCirc, - ), - ); - } - - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar( - title: Text(widget.title), - ), - body: Padding( - padding: const EdgeInsets.all(8), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Expanded( - child: ListView.builder( - controller: _scrollController, - itemBuilder: (context, idx) { - var content = _generatedContent[idx]; - return MessageWidget( - text: content.text, - image: content.image, - isFromUser: content.fromUser ?? false, - ); - }, - itemCount: _generatedContent.length, - ), - ), - Padding( - padding: const EdgeInsets.symmetric( - vertical: 25, - horizontal: 15, - ), - child: Row( - children: [ - Expanded( - child: TextField( - autofocus: true, - focusNode: _textFieldFocus, - controller: _textController, - ), - ), - const SizedBox.square( - dimension: 15, - ), - if (!_loading) - IconButton( - onPressed: () async { - await _sendImagePrompt(_textController.text); - }, - icon: Icon( - Icons.image, - color: Theme.of(context).colorScheme.primary, - ), - ), - if (!_loading) - IconButton( - onPressed: () async { - await _sendStorageUriPrompt(_textController.text); - }, - icon: Icon( - Icons.storage, - color: Theme.of(context).colorScheme.primary, - ), - ) - else - const CircularProgressIndicator(), - ], - ), - ), - ], - ), - ), - ); - } - - Future _sendImagePrompt(String message) async { - setState(() { - _loading = true; - }); - try { - ByteData catBytes = await rootBundle.load('assets/images/cat.jpg'); - ByteData sconeBytes = await rootBundle.load('assets/images/scones.jpg'); - final content = [ - Content.multi([ - TextPart(message), - // The only accepted mime types are image/*. - InlineDataPart('image/jpeg', catBytes.buffer.asUint8List()), - InlineDataPart('image/jpeg', sconeBytes.buffer.asUint8List()), - ]), - ]; - _generatedContent.add( - MessageData( - image: Image.asset('assets/images/cat.jpg'), - text: message, - fromUser: true, - ), - ); - _generatedContent.add( - MessageData( - image: Image.asset('assets/images/scones.jpg'), - fromUser: true, - ), - ); - - var response = await widget.model.generateContent(content); - var text = response.text; - _generatedContent.add(MessageData(text: text, fromUser: false)); - - if (text == null) { - _showError('No response from API.'); - return; - } else { - setState(() { - _loading = false; - _scrollDown(); - }); - } - } catch (e) { - _showError(e.toString()); - setState(() { - _loading = false; - }); - } finally { - _textController.clear(); - setState(() { - _loading = false; - }); - _textFieldFocus.requestFocus(); - } - } - - Future _sendStorageUriPrompt(String message) async { - setState(() { - _loading = true; - }); - try { - final content = [ - Content.multi([ - TextPart(message), - const FileData( - 'image/jpeg', - 'gs://vertex-ai-example-ef5a2.appspot.com/foodpic.jpg', - ), - ]), - ]; - _generatedContent.add(MessageData(text: message, fromUser: true)); - - var response = await widget.model.generateContent(content); - var text = response.text; - _generatedContent.add(MessageData(text: text, fromUser: false)); - - if (text == null) { - _showError('No response from API.'); - return; - } else { - setState(() { - _loading = false; - _scrollDown(); - }); - } - } catch (e) { - _showError(e.toString()); - setState(() { - _loading = false; - }); - } finally { - _textController.clear(); - setState(() { - _loading = false; - }); - _textFieldFocus.requestFocus(); - } - } - - void _showError(String message) { - showDialog( - context: context, - builder: (context) { - return AlertDialog( - title: const Text('Something went wrong'), - content: SingleChildScrollView( - child: SelectableText(message), - ), - actions: [ - TextButton( - onPressed: () { - Navigator.of(context).pop(); - }, - child: const Text('OK'), - ), - ], - ); - }, - ); - } -} diff --git a/packages/firebase_vertexai/firebase_vertexai/example/lib/pages/imagen_page.dart b/packages/firebase_vertexai/firebase_vertexai/example/lib/pages/imagen_page.dart deleted file mode 100644 index 0ab750b13fef..000000000000 --- a/packages/firebase_vertexai/firebase_vertexai/example/lib/pages/imagen_page.dart +++ /dev/null @@ -1,214 +0,0 @@ -// Copyright 2025 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import 'package:flutter/material.dart'; -import 'package:firebase_vertexai/firebase_vertexai.dart'; -//import 'package:firebase_storage/firebase_storage.dart'; -import '../widgets/message_widget.dart'; - -class ImagenPage extends StatefulWidget { - const ImagenPage({ - super.key, - required this.title, - required this.model, - }); - - final String title; - final ImagenModel model; - - @override - State createState() => _ImagenPageState(); -} - -class _ImagenPageState extends State { - final ScrollController _scrollController = ScrollController(); - final TextEditingController _textController = TextEditingController(); - final FocusNode _textFieldFocus = FocusNode(); - final List _generatedContent = []; - bool _loading = false; - - void _scrollDown() { - WidgetsBinding.instance.addPostFrameCallback( - (_) => _scrollController.animateTo( - _scrollController.position.maxScrollExtent, - duration: const Duration( - milliseconds: 750, - ), - curve: Curves.easeOutCirc, - ), - ); - } - - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar( - title: Text(widget.title), - ), - body: Padding( - padding: const EdgeInsets.all(8), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Expanded( - child: ListView.builder( - controller: _scrollController, - itemBuilder: (context, idx) { - return MessageWidget( - text: _generatedContent[idx].text, - image: _generatedContent[idx].image, - isFromUser: _generatedContent[idx].fromUser ?? false, - ); - }, - itemCount: _generatedContent.length, - ), - ), - Padding( - padding: const EdgeInsets.symmetric( - vertical: 25, - horizontal: 15, - ), - child: Row( - children: [ - Expanded( - child: TextField( - autofocus: true, - focusNode: _textFieldFocus, - controller: _textController, - ), - ), - const SizedBox.square( - dimension: 15, - ), - if (!_loading) - IconButton( - onPressed: () async { - await _testImagen(_textController.text); - }, - icon: Icon( - Icons.image_search, - color: Theme.of(context).colorScheme.primary, - ), - tooltip: 'Imagen raw data', - ) - else - const CircularProgressIndicator(), - // NOTE: Keep this API private until future release. - // if (!_loading) - // IconButton( - // onPressed: () async { - // await _testImagenGCS(_textController.text); - // }, - // icon: Icon( - // Icons.imagesearch_roller, - // color: Theme.of(context).colorScheme.primary, - // ), - // tooltip: 'Imagen GCS', - // ) - // else - // const CircularProgressIndicator(), - ], - ), - ), - ], - ), - ), - ); - } - - Future _testImagen(String prompt) async { - setState(() { - _loading = true; - }); - - try { - var response = await widget.model.generateImages(prompt); - - if (response.images.isNotEmpty) { - var imagenImage = response.images[0]; - - _generatedContent.add( - MessageData( - image: Image.memory(imagenImage.bytesBase64Encoded), - text: prompt, - fromUser: false, - ), - ); - } else { - // Handle the case where no images were generated - _showError('Error: No images were generated.'); - } - } catch (e) { - _showError(e.toString()); - } - - setState(() { - _loading = false; - _scrollDown(); - }); - } - // NOTE: Keep this API private until future release. - // Future _testImagenGCS(String prompt) async { - // setState(() { - // _loading = true; - // }); - // var gcsUrl = 'gs://vertex-ai-example-ef5a2.appspot.com/imagen'; - - // var response = await widget.model.generateImagesGCS(prompt, gcsUrl); - - // if (response.images.isNotEmpty) { - // var imagenImage = response.images[0]; - // final returnImageUri = imagenImage.gcsUri; - // final reference = FirebaseStorage.instance.refFromURL(returnImageUri); - // final downloadUrl = await reference.getDownloadURL(); - // // Process the image - // _generatedContent.add( - // MessageData( - // image: Image(image: NetworkImage(downloadUrl)), - // text: prompt, - // fromUser: false, - // ), - // ); - // } else { - // // Handle the case where no images were generated - // _showError('Error: No images were generated.'); - // } - // setState(() { - // _loading = false; - // }); - // } - - void _showError(String message) { - showDialog( - context: context, - builder: (context) { - return AlertDialog( - title: const Text('Something went wrong'), - content: SingleChildScrollView( - child: SelectableText(message), - ), - actions: [ - TextButton( - onPressed: () { - Navigator.of(context).pop(); - }, - child: const Text('OK'), - ), - ], - ); - }, - ); - } -} diff --git a/packages/firebase_vertexai/firebase_vertexai/example/lib/pages/schema_page.dart b/packages/firebase_vertexai/firebase_vertexai/example/lib/pages/schema_page.dart deleted file mode 100644 index 71fff4269b1e..000000000000 --- a/packages/firebase_vertexai/firebase_vertexai/example/lib/pages/schema_page.dart +++ /dev/null @@ -1,182 +0,0 @@ -// Copyright 2025 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import 'package:flutter/material.dart'; -import 'package:firebase_vertexai/firebase_vertexai.dart'; -import '../widgets/message_widget.dart'; - -class SchemaPromptPage extends StatefulWidget { - const SchemaPromptPage({super.key, required this.title, required this.model}); - - final String title; - final GenerativeModel model; - - @override - State createState() => _SchemaPromptPageState(); -} - -class _SchemaPromptPageState extends State { - final ScrollController _scrollController = ScrollController(); - final TextEditingController _textController = TextEditingController(); - final FocusNode _textFieldFocus = FocusNode(); - final List _messages = []; - bool _loading = false; - - void _scrollDown() { - WidgetsBinding.instance.addPostFrameCallback( - (_) => _scrollController.animateTo( - _scrollController.position.maxScrollExtent, - duration: const Duration( - milliseconds: 750, - ), - curve: Curves.easeOutCirc, - ), - ); - } - - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar( - title: Text(widget.title), - ), - body: Padding( - padding: const EdgeInsets.all(8), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Expanded( - child: ListView.builder( - controller: _scrollController, - itemBuilder: (context, idx) { - return MessageWidget( - text: _messages[idx].text, - isFromUser: _messages[idx].fromUser ?? false, - ); - }, - itemCount: _messages.length, - ), - ), - Padding( - padding: const EdgeInsets.symmetric( - vertical: 25, - horizontal: 15, - ), - child: Row( - children: [ - Expanded( - child: ElevatedButton( - onPressed: !_loading - ? () async { - await _promptSchemaTest(); - } - : null, - child: const Text('Schema Prompt'), - ), - ), - ], - ), - ), - ], - ), - ), - ); - } - - Future _promptSchemaTest() async { - setState(() { - _loading = true; - }); - try { - final content = [ - Content.text( - "For use in a children's card game, generate 10 animal-based " - 'characters.', - ), - ]; - - final jsonSchema = Schema.object( - properties: { - 'characters': Schema.array( - items: Schema.object( - properties: { - 'name': Schema.string(), - 'age': Schema.integer(), - 'species': Schema.string(), - 'accessory': - Schema.enumString(enumValues: ['hat', 'belt', 'shoes']), - }, - ), - ), - }, - optionalProperties: ['accessory'], - ); - - final response = await widget.model.generateContent( - content, - generationConfig: GenerationConfig( - responseMimeType: 'application/json', - responseSchema: jsonSchema, - ), - ); - - var text = response.text; - _messages.add(MessageData(text: text, fromUser: false)); - - if (text == null) { - _showError('No response from API.'); - return; - } else { - setState(() { - _loading = false; - _scrollDown(); - }); - } - } catch (e) { - _showError(e.toString()); - setState(() { - _loading = false; - }); - } finally { - _textController.clear(); - setState(() { - _loading = false; - }); - _textFieldFocus.requestFocus(); - } - } - - void _showError(String message) { - showDialog( - context: context, - builder: (context) { - return AlertDialog( - title: const Text('Something went wrong'), - content: SingleChildScrollView( - child: SelectableText(message), - ), - actions: [ - TextButton( - onPressed: () { - Navigator.of(context).pop(); - }, - child: const Text('OK'), - ), - ], - ); - }, - ); - } -} diff --git a/packages/firebase_vertexai/firebase_vertexai/example/lib/pages/token_count_page.dart b/packages/firebase_vertexai/firebase_vertexai/example/lib/pages/token_count_page.dart deleted file mode 100644 index 0b3b60f6c622..000000000000 --- a/packages/firebase_vertexai/firebase_vertexai/example/lib/pages/token_count_page.dart +++ /dev/null @@ -1,105 +0,0 @@ -// Copyright 2025 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import 'package:flutter/material.dart'; -import 'package:firebase_vertexai/firebase_vertexai.dart'; -import '../widgets/message_widget.dart'; - -class TokenCountPage extends StatefulWidget { - const TokenCountPage({super.key, required this.title, required this.model}); - - final String title; - final GenerativeModel model; - - @override - State createState() => _TokenCountPageState(); -} - -class _TokenCountPageState extends State { - final List _messages = []; - bool _loading = false; - - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar( - title: Text(widget.title), - ), - body: Padding( - padding: const EdgeInsets.all(8), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Expanded( - child: ListView.builder( - itemBuilder: (context, idx) { - return MessageWidget( - text: _messages[idx].text, - isFromUser: _messages[idx].fromUser ?? false, - ); - }, - itemCount: _messages.length, - ), - ), - Padding( - padding: const EdgeInsets.symmetric( - vertical: 25, - horizontal: 15, - ), - child: Row( - children: [ - Expanded( - child: ElevatedButton( - onPressed: !_loading - ? () async { - await _testCountToken(); - } - : null, - child: const Text('Count Tokens'), - ), - ), - ], - ), - ), - ], - ), - ), - ); - } - - Future _testCountToken() async { - setState(() { - _loading = true; - }); - - const prompt = 'tell a short story'; - final content = Content.text(prompt); - final tokenResponse = await widget.model.countTokens([content]); - final tokenResult = 'Count token: ${tokenResponse.totalTokens}'; - _messages.add(MessageData(text: tokenResult, fromUser: false)); - - final contentResponse = await widget.model.generateContent([content]); - final contentMetaData = 'result metadata, promptTokenCount:' - '${contentResponse.usageMetadata!.promptTokenCount}, ' - 'candidatesTokenCount:' - '${contentResponse.usageMetadata!.candidatesTokenCount}, ' - 'totalTokenCount:' - '${contentResponse.usageMetadata!.totalTokenCount}'; - _messages.add(MessageData(text: contentMetaData, fromUser: false)); - setState(() { - _loading = false; - }); - } -} diff --git a/packages/firebase_vertexai/firebase_vertexai/example/lib/pages/video_page.dart b/packages/firebase_vertexai/firebase_vertexai/example/lib/pages/video_page.dart deleted file mode 100644 index e214114d7ebc..000000000000 --- a/packages/firebase_vertexai/firebase_vertexai/example/lib/pages/video_page.dart +++ /dev/null @@ -1,114 +0,0 @@ -// Copyright 2025 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import 'package:flutter/material.dart'; -import 'package:firebase_vertexai/firebase_vertexai.dart'; -import 'package:flutter/services.dart'; -import '../widgets/message_widget.dart'; - -class VideoPage extends StatefulWidget { - const VideoPage({super.key, required this.title, required this.model}); - - final String title; - final GenerativeModel model; - - @override - State createState() => _VideoPageState(); -} - -class _VideoPageState extends State { - ChatSession? chat; - late final GenerativeModel model; - final List _messages = []; - bool _loading = false; - - @override - void initState() { - super.initState(); - chat = widget.model.startChat(); - } - - Future _testVideo(model) async { - try { - ByteData videoBytes = - await rootBundle.load('assets/videos/landscape.mp4'); - - const _prompt = 'Can you tell me what is in the video?'; - - setState(() { - _messages.add(MessageData(text: _prompt, fromUser: true)); - }); - - final videoPart = - InlineDataPart('video/mp4', videoBytes.buffer.asUint8List()); - - final response = await widget.model.generateContent([ - Content.multi([const TextPart(_prompt), videoPart]), - ]); - - setState(() { - _messages.add(MessageData(text: response.text, fromUser: false)); - }); - } catch (e) { - print('Error sending video to model: $e'); - } - } - - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar( - title: Text(widget.title), - ), - body: Padding( - padding: const EdgeInsets.all(8), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Expanded( - child: ListView.builder( - itemBuilder: (context, idx) { - return MessageWidget( - text: _messages[idx].text, - isFromUser: _messages[idx].fromUser ?? false, - ); - }, - itemCount: _messages.length, - ), - ), - Padding( - padding: const EdgeInsets.symmetric( - vertical: 25, - horizontal: 15, - ), - child: Center( - child: SizedBox( - child: ElevatedButton( - onPressed: !_loading - ? () async { - await _testVideo(widget.model); - } - : null, - child: const Text('Test Video Prompt'), - ), - ), - ), - ), - ], - ), - ), - ); - } -} diff --git a/packages/firebase_vertexai/firebase_vertexai/example/lib/utils/audio_input.dart b/packages/firebase_vertexai/firebase_vertexai/example/lib/utils/audio_input.dart deleted file mode 100644 index 869d4ee32781..000000000000 --- a/packages/firebase_vertexai/firebase_vertexai/example/lib/utils/audio_input.dart +++ /dev/null @@ -1,95 +0,0 @@ -// Copyright 2025 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import 'package:flutter/material.dart'; -import 'package:record/record.dart'; -import 'dart:typed_data'; - -class AudioInput extends ChangeNotifier { - final _recorder = AudioRecorder(); - final AudioEncoder _encoder = AudioEncoder.pcm16bits; - bool isRecording = false; - bool isPaused = false; - Stream? audioStream; - - Future init() async { - await _checkPermission(); - } - - @override - void dispose() { - _recorder.dispose(); - super.dispose(); - } - - Future _checkPermission() async { - final hasPermission = await _recorder.hasPermission(); - if (!hasPermission) { - throw MicrophonePermissionDeniedException( - 'App does not have mic permissions', - ); - } - } - - Future?> startRecordingStream() async { - var recordConfig = RecordConfig( - encoder: _encoder, - sampleRate: 24000, - numChannels: 1, - echoCancel: true, - noiseSuppress: true, - androidConfig: const AndroidRecordConfig( - audioSource: AndroidAudioSource.voiceCommunication, - ), - iosConfig: const IosRecordConfig(categoryOptions: []), - ); - await _recorder.listInputDevices(); - audioStream = await _recorder.startStream(recordConfig); - isRecording = true; - notifyListeners(); - return audioStream; - } - - Future stopRecording() async { - await _recorder.stop(); - isRecording = false; - notifyListeners(); - } - - Future togglePause() async { - if (isPaused) { - await _recorder.resume(); - isPaused = false; - } else { - await _recorder.pause(); - isPaused = true; - } - notifyListeners(); - return; - } -} - -/// An exception thrown when microphone permission is denied or not granted. -class MicrophonePermissionDeniedException implements Exception { - /// The optional message associated with the permission denial. - final String? message; - - /// Creates a new [MicrophonePermissionDeniedException] with an optional [message]. - MicrophonePermissionDeniedException([this.message]); - - @override - String toString() { - return 'MicrophonePermissionDeniedException: $message'; - } -} diff --git a/packages/firebase_vertexai/firebase_vertexai/example/lib/utils/audio_output.dart b/packages/firebase_vertexai/firebase_vertexai/example/lib/utils/audio_output.dart deleted file mode 100644 index b97ad3478f5b..000000000000 --- a/packages/firebase_vertexai/firebase_vertexai/example/lib/utils/audio_output.dart +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright 2025 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import 'dart:typed_data'; - -import 'package:flutter_soloud/flutter_soloud.dart'; - -class AudioOutput { - AudioSource? stream; - SoundHandle? handle; - - Future init() async { - // Initialize the player. - await SoLoud.instance.init(sampleRate: 24000, channels: Channels.mono); - await setupNewStream(); - } - - Future setupNewStream() async { - if (SoLoud.instance.isInitialized) { - // Stop and clear any previous playback handle if it's still valid - await stopStream(); // Ensure previous sound is stopped - - stream = SoLoud.instance.setBufferStream( - maxBufferSizeBytes: - 1024 * 1024 * 10, // 10MB of max buffer (not allocated) - bufferingType: BufferingType.released, - bufferingTimeNeeds: 0, - onBuffering: (isBuffering, handle, time) {}, - ); - // Reset handle to null until the stream is played again - handle = null; - } - } - - Future playStream() async { - handle = await SoLoud.instance.play(stream!); - return stream; - } - - Future stopStream() async { - if (stream != null && - handle != null && - SoLoud.instance.getIsValidVoiceHandle(handle!)) { - SoLoud.instance.setDataIsEnded(stream!); - await SoLoud.instance.stop(handle!); - - // Clear old stream, set up new session for next time. - await setupNewStream(); - } - } - - void addAudioStream(Uint8List audioChunk) { - SoLoud.instance.addAudioDataStream(stream!, audioChunk); - } -} diff --git a/packages/firebase_vertexai/firebase_vertexai/example/lib/widgets/message_widget.dart b/packages/firebase_vertexai/firebase_vertexai/example/lib/widgets/message_widget.dart deleted file mode 100644 index b8a0f23ce03b..000000000000 --- a/packages/firebase_vertexai/firebase_vertexai/example/lib/widgets/message_widget.dart +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright 2025 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import 'package:flutter/material.dart'; -import 'package:flutter_markdown/flutter_markdown.dart'; - -class MessageData { - MessageData({this.image, this.text, this.fromUser}); - final Image? image; - final String? text; - final bool? fromUser; -} - -class MessageWidget extends StatelessWidget { - final Image? image; - final String? text; - final bool isFromUser; - - const MessageWidget({ - super.key, - this.image, - this.text, - required this.isFromUser, - }); - - @override - Widget build(BuildContext context) { - return Row( - mainAxisAlignment: - isFromUser ? MainAxisAlignment.end : MainAxisAlignment.start, - children: [ - Flexible( - child: Container( - constraints: const BoxConstraints(maxWidth: 600), - decoration: BoxDecoration( - color: isFromUser - ? Theme.of(context).colorScheme.primaryContainer - : Theme.of(context).colorScheme.surfaceContainerHighest, - borderRadius: BorderRadius.circular(18), - ), - padding: const EdgeInsets.symmetric( - vertical: 15, - horizontal: 20, - ), - margin: const EdgeInsets.only(bottom: 8), - child: Column( - children: [ - if (text case final text?) MarkdownBody(data: text), - if (image case final image?) image, - ], - ), - ), - ), - ], - ); - } -} diff --git a/packages/firebase_vertexai/firebase_vertexai/example/macos/.gitignore b/packages/firebase_vertexai/firebase_vertexai/example/macos/.gitignore deleted file mode 100644 index 746adbb6b9e1..000000000000 --- a/packages/firebase_vertexai/firebase_vertexai/example/macos/.gitignore +++ /dev/null @@ -1,7 +0,0 @@ -# Flutter-related -**/Flutter/ephemeral/ -**/Pods/ - -# Xcode-related -**/dgph -**/xcuserdata/ diff --git a/packages/firebase_vertexai/firebase_vertexai/example/macos/Flutter/Flutter-Debug.xcconfig b/packages/firebase_vertexai/firebase_vertexai/example/macos/Flutter/Flutter-Debug.xcconfig deleted file mode 100644 index 4b81f9b2d200..000000000000 --- a/packages/firebase_vertexai/firebase_vertexai/example/macos/Flutter/Flutter-Debug.xcconfig +++ /dev/null @@ -1,2 +0,0 @@ -#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" -#include "ephemeral/Flutter-Generated.xcconfig" diff --git a/packages/firebase_vertexai/firebase_vertexai/example/macos/Flutter/Flutter-Release.xcconfig b/packages/firebase_vertexai/firebase_vertexai/example/macos/Flutter/Flutter-Release.xcconfig deleted file mode 100644 index 5caa9d1579e4..000000000000 --- a/packages/firebase_vertexai/firebase_vertexai/example/macos/Flutter/Flutter-Release.xcconfig +++ /dev/null @@ -1,2 +0,0 @@ -#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" -#include "ephemeral/Flutter-Generated.xcconfig" diff --git a/packages/firebase_vertexai/firebase_vertexai/example/macos/Podfile b/packages/firebase_vertexai/firebase_vertexai/example/macos/Podfile deleted file mode 100644 index b52666a10389..000000000000 --- a/packages/firebase_vertexai/firebase_vertexai/example/macos/Podfile +++ /dev/null @@ -1,43 +0,0 @@ -platform :osx, '10.15' - -# CocoaPods analytics sends network stats synchronously affecting flutter build latency. -ENV['COCOAPODS_DISABLE_STATS'] = 'true' - -project 'Runner', { - 'Debug' => :debug, - 'Profile' => :release, - 'Release' => :release, -} - -def flutter_root - generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'ephemeral', 'Flutter-Generated.xcconfig'), __FILE__) - unless File.exist?(generated_xcode_build_settings_path) - raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure \"flutter pub get\" is executed first" - end - - File.foreach(generated_xcode_build_settings_path) do |line| - matches = line.match(/FLUTTER_ROOT\=(.*)/) - return matches[1].strip if matches - end - raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Flutter-Generated.xcconfig, then run \"flutter pub get\"" -end - -require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) - -flutter_macos_podfile_setup - -target 'Runner' do - use_frameworks! - use_modular_headers! - - flutter_install_all_macos_pods File.dirname(File.realpath(__FILE__)) - target 'RunnerTests' do - inherit! :search_paths - end -end - -post_install do |installer| - installer.pods_project.targets.each do |target| - flutter_additional_macos_build_settings(target) - end -end diff --git a/packages/firebase_vertexai/firebase_vertexai/example/macos/Runner.xcodeproj/project.pbxproj b/packages/firebase_vertexai/firebase_vertexai/example/macos/Runner.xcodeproj/project.pbxproj deleted file mode 100644 index 47f1397e22f9..000000000000 --- a/packages/firebase_vertexai/firebase_vertexai/example/macos/Runner.xcodeproj/project.pbxproj +++ /dev/null @@ -1,807 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 54; - objects = { - -/* Begin PBXAggregateTarget section */ - 33CC111A2044C6BA0003C045 /* Flutter Assemble */ = { - isa = PBXAggregateTarget; - buildConfigurationList = 33CC111B2044C6BA0003C045 /* Build configuration list for PBXAggregateTarget "Flutter Assemble" */; - buildPhases = ( - 33CC111E2044C6BF0003C045 /* ShellScript */, - ); - dependencies = ( - ); - name = "Flutter Assemble"; - productName = FLX; - }; -/* End PBXAggregateTarget section */ - -/* Begin PBXBuildFile section */ - 1E1464098F5197FB1E35FDA1 /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0E05DB31CC6D204C7C78D127 /* Pods_RunnerTests.framework */; }; - 20C13FC2C906153EF4A40292 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 08B0491E23641E5BA5DD096C /* GoogleService-Info.plist */; }; - 331C80D8294CF71000263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C80D7294CF71000263BE5 /* RunnerTests.swift */; }; - 335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */ = {isa = PBXBuildFile; fileRef = 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */; }; - 33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC10F02044A3C60003C045 /* AppDelegate.swift */; }; - 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F22044A3C60003C045 /* Assets.xcassets */; }; - 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F42044A3C60003C045 /* MainMenu.xib */; }; - 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */; }; - 3D1CF19370CB8E26E5C667A5 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C4DAA18FE8B79A454BF3F8CB /* Pods_Runner.framework */; }; -/* End PBXBuildFile section */ - -/* Begin PBXContainerItemProxy section */ - 331C80D9294CF71000263BE5 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 33CC10E52044A3C60003C045 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 33CC10EC2044A3C60003C045; - remoteInfo = Runner; - }; - 33CC111F2044C79F0003C045 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 33CC10E52044A3C60003C045 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 33CC111A2044C6BA0003C045; - remoteInfo = FLX; - }; -/* End PBXContainerItemProxy section */ - -/* Begin PBXCopyFilesBuildPhase section */ - 33CC110E2044A8840003C045 /* Bundle Framework */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = ""; - dstSubfolderSpec = 10; - files = ( - ); - name = "Bundle Framework"; - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXCopyFilesBuildPhase section */ - -/* Begin PBXFileReference section */ - 08B0491E23641E5BA5DD096C /* GoogleService-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; name = "GoogleService-Info.plist"; path = "Runner/GoogleService-Info.plist"; sourceTree = ""; }; - 0E05DB31CC6D204C7C78D127 /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 331C80D5294CF71000263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; - 331C80D7294CF71000263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; }; - 333000ED22D3DE5D00554162 /* Warnings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Warnings.xcconfig; sourceTree = ""; }; - 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeneratedPluginRegistrant.swift; sourceTree = ""; }; - 33CC10ED2044A3C60003C045 /* example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = example.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 33CC10F02044A3C60003C045 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; - 33CC10F22044A3C60003C045 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = Runner/Assets.xcassets; sourceTree = ""; }; - 33CC10F52044A3C60003C045 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; - 33CC10F72044A3C60003C045 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = Info.plist; path = Runner/Info.plist; sourceTree = ""; }; - 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainFlutterWindow.swift; sourceTree = ""; }; - 33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Debug.xcconfig"; sourceTree = ""; }; - 33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Release.xcconfig"; sourceTree = ""; }; - 33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = "Flutter-Generated.xcconfig"; path = "ephemeral/Flutter-Generated.xcconfig"; sourceTree = ""; }; - 33E51913231747F40026EE4D /* DebugProfile.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DebugProfile.entitlements; sourceTree = ""; }; - 33E51914231749380026EE4D /* Release.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Release.entitlements; sourceTree = ""; }; - 33E5194F232828860026EE4D /* AppInfo.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppInfo.xcconfig; sourceTree = ""; }; - 3A40C9AE19ACEC6C433878E9 /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = ""; }; - 587C61AFC0E2B0BF5340F8E8 /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = ""; }; - 5C2B5E4F1CE100E1FA5D9DC5 /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = ""; }; - 766A2E414AFDFA56243527A6 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; - 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = ""; }; - 816B0EE72BF94FC5261D04E6 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; - 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = ""; }; - A2911B8EF91B3925874FDE6A /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; - C4DAA18FE8B79A454BF3F8CB /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 331C80D2294CF70F00263BE5 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 1E1464098F5197FB1E35FDA1 /* Pods_RunnerTests.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 33CC10EA2044A3C60003C045 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 3D1CF19370CB8E26E5C667A5 /* Pods_Runner.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 331C80D6294CF71000263BE5 /* RunnerTests */ = { - isa = PBXGroup; - children = ( - 331C80D7294CF71000263BE5 /* RunnerTests.swift */, - ); - path = RunnerTests; - sourceTree = ""; - }; - 33BA886A226E78AF003329D5 /* Configs */ = { - isa = PBXGroup; - children = ( - 33E5194F232828860026EE4D /* AppInfo.xcconfig */, - 9740EEB21CF90195004384FC /* Debug.xcconfig */, - 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, - 333000ED22D3DE5D00554162 /* Warnings.xcconfig */, - ); - path = Configs; - sourceTree = ""; - }; - 33CC10E42044A3C60003C045 = { - isa = PBXGroup; - children = ( - 33FAB671232836740065AC1E /* Runner */, - 33CEB47122A05771004F2AC0 /* Flutter */, - 331C80D6294CF71000263BE5 /* RunnerTests */, - 33CC10EE2044A3C60003C045 /* Products */, - D73912EC22F37F3D000D13A0 /* Frameworks */, - 08B0491E23641E5BA5DD096C /* GoogleService-Info.plist */, - BE277C424FC00920BE07E371 /* Pods */, - ); - sourceTree = ""; - }; - 33CC10EE2044A3C60003C045 /* Products */ = { - isa = PBXGroup; - children = ( - 33CC10ED2044A3C60003C045 /* example.app */, - 331C80D5294CF71000263BE5 /* RunnerTests.xctest */, - ); - name = Products; - sourceTree = ""; - }; - 33CC11242044D66E0003C045 /* Resources */ = { - isa = PBXGroup; - children = ( - 33CC10F22044A3C60003C045 /* Assets.xcassets */, - 33CC10F42044A3C60003C045 /* MainMenu.xib */, - 33CC10F72044A3C60003C045 /* Info.plist */, - ); - name = Resources; - path = ..; - sourceTree = ""; - }; - 33CEB47122A05771004F2AC0 /* Flutter */ = { - isa = PBXGroup; - children = ( - 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */, - 33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */, - 33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */, - 33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */, - ); - path = Flutter; - sourceTree = ""; - }; - 33FAB671232836740065AC1E /* Runner */ = { - isa = PBXGroup; - children = ( - 33CC10F02044A3C60003C045 /* AppDelegate.swift */, - 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */, - 33E51913231747F40026EE4D /* DebugProfile.entitlements */, - 33E51914231749380026EE4D /* Release.entitlements */, - 33CC11242044D66E0003C045 /* Resources */, - 33BA886A226E78AF003329D5 /* Configs */, - ); - path = Runner; - sourceTree = ""; - }; - BE277C424FC00920BE07E371 /* Pods */ = { - isa = PBXGroup; - children = ( - A2911B8EF91B3925874FDE6A /* Pods-Runner.debug.xcconfig */, - 816B0EE72BF94FC5261D04E6 /* Pods-Runner.release.xcconfig */, - 766A2E414AFDFA56243527A6 /* Pods-Runner.profile.xcconfig */, - 3A40C9AE19ACEC6C433878E9 /* Pods-RunnerTests.debug.xcconfig */, - 587C61AFC0E2B0BF5340F8E8 /* Pods-RunnerTests.release.xcconfig */, - 5C2B5E4F1CE100E1FA5D9DC5 /* Pods-RunnerTests.profile.xcconfig */, - ); - path = Pods; - sourceTree = ""; - }; - D73912EC22F37F3D000D13A0 /* Frameworks */ = { - isa = PBXGroup; - children = ( - C4DAA18FE8B79A454BF3F8CB /* Pods_Runner.framework */, - 0E05DB31CC6D204C7C78D127 /* Pods_RunnerTests.framework */, - ); - name = Frameworks; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 331C80D4294CF70F00263BE5 /* RunnerTests */ = { - isa = PBXNativeTarget; - buildConfigurationList = 331C80DE294CF71000263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */; - buildPhases = ( - 33B83C0D35C3606AED8215FE /* [CP] Check Pods Manifest.lock */, - 331C80D1294CF70F00263BE5 /* Sources */, - 331C80D2294CF70F00263BE5 /* Frameworks */, - 331C80D3294CF70F00263BE5 /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - 331C80DA294CF71000263BE5 /* PBXTargetDependency */, - ); - name = RunnerTests; - productName = RunnerTests; - productReference = 331C80D5294CF71000263BE5 /* RunnerTests.xctest */; - productType = "com.apple.product-type.bundle.unit-test"; - }; - 33CC10EC2044A3C60003C045 /* Runner */ = { - isa = PBXNativeTarget; - buildConfigurationList = 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */; - buildPhases = ( - E10F886575A4AF9F1D3D5C5B /* [CP] Check Pods Manifest.lock */, - 33CC10E92044A3C60003C045 /* Sources */, - 33CC10EA2044A3C60003C045 /* Frameworks */, - 33CC10EB2044A3C60003C045 /* Resources */, - 33CC110E2044A8840003C045 /* Bundle Framework */, - 3399D490228B24CF009A79C7 /* ShellScript */, - 1D3525FBE401B81EB0265948 /* [CP] Embed Pods Frameworks */, - ); - buildRules = ( - ); - dependencies = ( - 33CC11202044C79F0003C045 /* PBXTargetDependency */, - ); - name = Runner; - productName = Runner; - productReference = 33CC10ED2044A3C60003C045 /* example.app */; - productType = "com.apple.product-type.application"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 33CC10E52044A3C60003C045 /* Project object */ = { - isa = PBXProject; - attributes = { - BuildIndependentTargetsInParallel = YES; - LastSwiftUpdateCheck = 0920; - LastUpgradeCheck = 1510; - ORGANIZATIONNAME = ""; - TargetAttributes = { - 331C80D4294CF70F00263BE5 = { - CreatedOnToolsVersion = 14.0; - TestTargetID = 33CC10EC2044A3C60003C045; - }; - 33CC10EC2044A3C60003C045 = { - CreatedOnToolsVersion = 9.2; - LastSwiftMigration = 1100; - ProvisioningStyle = Automatic; - SystemCapabilities = { - com.apple.Sandbox = { - enabled = 1; - }; - }; - }; - 33CC111A2044C6BA0003C045 = { - CreatedOnToolsVersion = 9.2; - ProvisioningStyle = Manual; - }; - }; - }; - buildConfigurationList = 33CC10E82044A3C60003C045 /* Build configuration list for PBXProject "Runner" */; - compatibilityVersion = "Xcode 9.3"; - developmentRegion = en; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = 33CC10E42044A3C60003C045; - productRefGroup = 33CC10EE2044A3C60003C045 /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 33CC10EC2044A3C60003C045 /* Runner */, - 331C80D4294CF70F00263BE5 /* RunnerTests */, - 33CC111A2044C6BA0003C045 /* Flutter Assemble */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 331C80D3294CF70F00263BE5 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 33CC10EB2044A3C60003C045 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */, - 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */, - 20C13FC2C906153EF4A40292 /* GoogleService-Info.plist in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXShellScriptBuildPhase section */ - 1D3525FBE401B81EB0265948 /* [CP] Embed Pods Frameworks */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", - ); - name = "[CP] Embed Pods Frameworks"; - outputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; - showEnvVarsInLog = 0; - }; - 3399D490228B24CF009A79C7 /* ShellScript */ = { - isa = PBXShellScriptBuildPhase; - alwaysOutOfDate = 1; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - ); - inputPaths = ( - ); - outputFileListPaths = ( - ); - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "echo \"$PRODUCT_NAME.app\" > \"$PROJECT_DIR\"/Flutter/ephemeral/.app_filename && \"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh embed\n"; - }; - 33B83C0D35C3606AED8215FE /* [CP] Check Pods Manifest.lock */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - ); - inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", - ); - name = "[CP] Check Pods Manifest.lock"; - outputFileListPaths = ( - ); - outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-RunnerTests-checkManifestLockResult.txt", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; - showEnvVarsInLog = 0; - }; - 33CC111E2044C6BF0003C045 /* ShellScript */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - Flutter/ephemeral/FlutterInputs.xcfilelist, - ); - inputPaths = ( - Flutter/ephemeral/tripwire, - ); - outputFileListPaths = ( - Flutter/ephemeral/FlutterOutputs.xcfilelist, - ); - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh && touch Flutter/ephemeral/tripwire"; - }; - E10F886575A4AF9F1D3D5C5B /* [CP] Check Pods Manifest.lock */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - ); - inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", - ); - name = "[CP] Check Pods Manifest.lock"; - outputFileListPaths = ( - ); - outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; - showEnvVarsInLog = 0; - }; -/* End PBXShellScriptBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 331C80D1294CF70F00263BE5 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 331C80D8294CF71000263BE5 /* RunnerTests.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 33CC10E92044A3C60003C045 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */, - 33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */, - 335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXTargetDependency section */ - 331C80DA294CF71000263BE5 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 33CC10EC2044A3C60003C045 /* Runner */; - targetProxy = 331C80D9294CF71000263BE5 /* PBXContainerItemProxy */; - }; - 33CC11202044C79F0003C045 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 33CC111A2044C6BA0003C045 /* Flutter Assemble */; - targetProxy = 33CC111F2044C79F0003C045 /* PBXContainerItemProxy */; - }; -/* End PBXTargetDependency section */ - -/* Begin PBXVariantGroup section */ - 33CC10F42044A3C60003C045 /* MainMenu.xib */ = { - isa = PBXVariantGroup; - children = ( - 33CC10F52044A3C60003C045 /* Base */, - ); - name = MainMenu.xib; - path = Runner; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - -/* Begin XCBuildConfiguration section */ - 331C80DB294CF71000263BE5 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 3A40C9AE19ACEC6C433878E9 /* Pods-RunnerTests.debug.xcconfig */; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - CURRENT_PROJECT_VERSION = 1; - GENERATE_INFOPLIST_FILE = YES; - MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = com.example.example.RunnerTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 5.0; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/example.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/example"; - }; - name = Debug; - }; - 331C80DC294CF71000263BE5 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 587C61AFC0E2B0BF5340F8E8 /* Pods-RunnerTests.release.xcconfig */; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - CURRENT_PROJECT_VERSION = 1; - GENERATE_INFOPLIST_FILE = YES; - MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = com.example.example.RunnerTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 5.0; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/example.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/example"; - }; - name = Release; - }; - 331C80DD294CF71000263BE5 /* Profile */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 5C2B5E4F1CE100E1FA5D9DC5 /* Pods-RunnerTests.profile.xcconfig */; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - CURRENT_PROJECT_VERSION = 1; - GENERATE_INFOPLIST_FILE = YES; - MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = com.example.example.RunnerTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 5.0; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/example.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/example"; - }; - name = Profile; - }; - 338D0CE9231458BD00FA5F75 /* Profile */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CODE_SIGN_IDENTITY = "-"; - COPY_PHASE_STRIP = NO; - DEAD_CODE_STRIPPING = YES; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_USER_SCRIPT_SANDBOXING = NO; - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.15; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = macosx; - SWIFT_COMPILATION_MODE = wholemodule; - SWIFT_OPTIMIZATION_LEVEL = "-O"; - }; - name = Profile; - }; - 338D0CEA231458BD00FA5F75 /* Profile */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CLANG_ENABLE_MODULES = YES; - CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; - CODE_SIGN_STYLE = Automatic; - COMBINE_HIDPI_IMAGES = YES; - INFOPLIST_FILE = Runner/Info.plist; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/../Frameworks", - ); - PROVISIONING_PROFILE_SPECIFIER = ""; - STRIP_STYLE = "non-global"; - SWIFT_VERSION = 5.0; - }; - name = Profile; - }; - 338D0CEB231458BD00FA5F75 /* Profile */ = { - isa = XCBuildConfiguration; - buildSettings = { - CODE_SIGN_STYLE = Manual; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Profile; - }; - 33CC10F92044A3C60003C045 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CODE_SIGN_IDENTITY = "-"; - COPY_PHASE_STRIP = NO; - DEAD_CODE_STRIPPING = YES; - DEBUG_INFORMATION_FORMAT = dwarf; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; - ENABLE_USER_SCRIPT_SANDBOXING = NO; - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.15; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = macosx; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - }; - name = Debug; - }; - 33CC10FA2044A3C60003C045 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CODE_SIGN_IDENTITY = "-"; - COPY_PHASE_STRIP = NO; - DEAD_CODE_STRIPPING = YES; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_USER_SCRIPT_SANDBOXING = NO; - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.15; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = macosx; - SWIFT_COMPILATION_MODE = wholemodule; - SWIFT_OPTIMIZATION_LEVEL = "-O"; - }; - name = Release; - }; - 33CC10FC2044A3C60003C045 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CLANG_ENABLE_MODULES = YES; - CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; - CODE_SIGN_STYLE = Automatic; - COMBINE_HIDPI_IMAGES = YES; - INFOPLIST_FILE = Runner/Info.plist; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/../Frameworks", - ); - PROVISIONING_PROFILE_SPECIFIER = ""; - STRIP_STYLE = "non-global"; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 5.0; - }; - name = Debug; - }; - 33CC10FD2044A3C60003C045 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CLANG_ENABLE_MODULES = YES; - CODE_SIGN_ENTITLEMENTS = Runner/Release.entitlements; - CODE_SIGN_STYLE = Automatic; - COMBINE_HIDPI_IMAGES = YES; - INFOPLIST_FILE = Runner/Info.plist; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/../Frameworks", - ); - PROVISIONING_PROFILE_SPECIFIER = ""; - STRIP_STYLE = "non-global"; - SWIFT_VERSION = 5.0; - }; - name = Release; - }; - 33CC111C2044C6BA0003C045 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - CODE_SIGN_STYLE = Manual; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 33CC111D2044C6BA0003C045 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - CODE_SIGN_STYLE = Automatic; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 331C80DE294CF71000263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 331C80DB294CF71000263BE5 /* Debug */, - 331C80DC294CF71000263BE5 /* Release */, - 331C80DD294CF71000263BE5 /* Profile */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 33CC10E82044A3C60003C045 /* Build configuration list for PBXProject "Runner" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 33CC10F92044A3C60003C045 /* Debug */, - 33CC10FA2044A3C60003C045 /* Release */, - 338D0CE9231458BD00FA5F75 /* Profile */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 33CC10FC2044A3C60003C045 /* Debug */, - 33CC10FD2044A3C60003C045 /* Release */, - 338D0CEA231458BD00FA5F75 /* Profile */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 33CC111B2044C6BA0003C045 /* Build configuration list for PBXAggregateTarget "Flutter Assemble" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 33CC111C2044C6BA0003C045 /* Debug */, - 33CC111D2044C6BA0003C045 /* Release */, - 338D0CEB231458BD00FA5F75 /* Profile */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 33CC10E52044A3C60003C045 /* Project object */; -} diff --git a/packages/firebase_vertexai/firebase_vertexai/example/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/packages/firebase_vertexai/firebase_vertexai/example/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist deleted file mode 100644 index 18d981003d68..000000000000 --- a/packages/firebase_vertexai/firebase_vertexai/example/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +++ /dev/null @@ -1,8 +0,0 @@ - - - - - IDEDidComputeMac32BitWarning - - - diff --git a/packages/firebase_vertexai/firebase_vertexai/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/packages/firebase_vertexai/firebase_vertexai/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme deleted file mode 100644 index b0a82f087ad1..000000000000 --- a/packages/firebase_vertexai/firebase_vertexai/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ /dev/null @@ -1,105 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/packages/firebase_vertexai/firebase_vertexai/example/macos/Runner.xcworkspace/contents.xcworkspacedata b/packages/firebase_vertexai/firebase_vertexai/example/macos/Runner.xcworkspace/contents.xcworkspacedata deleted file mode 100644 index 21a3cc14c74e..000000000000 --- a/packages/firebase_vertexai/firebase_vertexai/example/macos/Runner.xcworkspace/contents.xcworkspacedata +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - diff --git a/packages/firebase_vertexai/firebase_vertexai/example/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/packages/firebase_vertexai/firebase_vertexai/example/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist deleted file mode 100644 index 18d981003d68..000000000000 --- a/packages/firebase_vertexai/firebase_vertexai/example/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +++ /dev/null @@ -1,8 +0,0 @@ - - - - - IDEDidComputeMac32BitWarning - - - diff --git a/packages/firebase_vertexai/firebase_vertexai/example/macos/Runner/AppDelegate.swift b/packages/firebase_vertexai/firebase_vertexai/example/macos/Runner/AppDelegate.swift deleted file mode 100644 index b3c176141221..000000000000 --- a/packages/firebase_vertexai/firebase_vertexai/example/macos/Runner/AppDelegate.swift +++ /dev/null @@ -1,13 +0,0 @@ -import Cocoa -import FlutterMacOS - -@main -class AppDelegate: FlutterAppDelegate { - override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool { - return true - } - - override func applicationSupportsSecureRestorableState(_ app: NSApplication) -> Bool { - return true - } -} diff --git a/packages/firebase_vertexai/firebase_vertexai/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/packages/firebase_vertexai/firebase_vertexai/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json deleted file mode 100644 index a2ec33f19f11..000000000000 --- a/packages/firebase_vertexai/firebase_vertexai/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json +++ /dev/null @@ -1,68 +0,0 @@ -{ - "images" : [ - { - "size" : "16x16", - "idiom" : "mac", - "filename" : "app_icon_16.png", - "scale" : "1x" - }, - { - "size" : "16x16", - "idiom" : "mac", - "filename" : "app_icon_32.png", - "scale" : "2x" - }, - { - "size" : "32x32", - "idiom" : "mac", - "filename" : "app_icon_32.png", - "scale" : "1x" - }, - { - "size" : "32x32", - "idiom" : "mac", - "filename" : "app_icon_64.png", - "scale" : "2x" - }, - { - "size" : "128x128", - "idiom" : "mac", - "filename" : "app_icon_128.png", - "scale" : "1x" - }, - { - "size" : "128x128", - "idiom" : "mac", - "filename" : "app_icon_256.png", - "scale" : "2x" - }, - { - "size" : "256x256", - "idiom" : "mac", - "filename" : "app_icon_256.png", - "scale" : "1x" - }, - { - "size" : "256x256", - "idiom" : "mac", - "filename" : "app_icon_512.png", - "scale" : "2x" - }, - { - "size" : "512x512", - "idiom" : "mac", - "filename" : "app_icon_512.png", - "scale" : "1x" - }, - { - "size" : "512x512", - "idiom" : "mac", - "filename" : "app_icon_1024.png", - "scale" : "2x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} diff --git a/packages/firebase_vertexai/firebase_vertexai/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png b/packages/firebase_vertexai/firebase_vertexai/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png deleted file mode 100644 index 82b6f9d9a33e..000000000000 Binary files a/packages/firebase_vertexai/firebase_vertexai/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png and /dev/null differ diff --git a/packages/firebase_vertexai/firebase_vertexai/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png b/packages/firebase_vertexai/firebase_vertexai/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png deleted file mode 100644 index 13b35eba55c6..000000000000 Binary files a/packages/firebase_vertexai/firebase_vertexai/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png and /dev/null differ diff --git a/packages/firebase_vertexai/firebase_vertexai/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png b/packages/firebase_vertexai/firebase_vertexai/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png deleted file mode 100644 index 0a3f5fa40fb3..000000000000 Binary files a/packages/firebase_vertexai/firebase_vertexai/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png and /dev/null differ diff --git a/packages/firebase_vertexai/firebase_vertexai/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png b/packages/firebase_vertexai/firebase_vertexai/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png deleted file mode 100644 index bdb57226d5f2..000000000000 Binary files a/packages/firebase_vertexai/firebase_vertexai/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png and /dev/null differ diff --git a/packages/firebase_vertexai/firebase_vertexai/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png b/packages/firebase_vertexai/firebase_vertexai/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png deleted file mode 100644 index f083318e09ca..000000000000 Binary files a/packages/firebase_vertexai/firebase_vertexai/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png and /dev/null differ diff --git a/packages/firebase_vertexai/firebase_vertexai/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png b/packages/firebase_vertexai/firebase_vertexai/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png deleted file mode 100644 index 326c0e72c9d8..000000000000 Binary files a/packages/firebase_vertexai/firebase_vertexai/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png and /dev/null differ diff --git a/packages/firebase_vertexai/firebase_vertexai/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png b/packages/firebase_vertexai/firebase_vertexai/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png deleted file mode 100644 index 2f1632cfddf3..000000000000 Binary files a/packages/firebase_vertexai/firebase_vertexai/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png and /dev/null differ diff --git a/packages/firebase_vertexai/firebase_vertexai/example/macos/Runner/Base.lproj/MainMenu.xib b/packages/firebase_vertexai/firebase_vertexai/example/macos/Runner/Base.lproj/MainMenu.xib deleted file mode 100644 index 80e867a4e06b..000000000000 --- a/packages/firebase_vertexai/firebase_vertexai/example/macos/Runner/Base.lproj/MainMenu.xib +++ /dev/null @@ -1,343 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/packages/firebase_vertexai/firebase_vertexai/example/macos/Runner/Configs/AppInfo.xcconfig b/packages/firebase_vertexai/firebase_vertexai/example/macos/Runner/Configs/AppInfo.xcconfig deleted file mode 100644 index 92fb3cd54e84..000000000000 --- a/packages/firebase_vertexai/firebase_vertexai/example/macos/Runner/Configs/AppInfo.xcconfig +++ /dev/null @@ -1,14 +0,0 @@ -// Application-level settings for the Runner target. -// -// This may be replaced with something auto-generated from metadata (e.g., pubspec.yaml) in the -// future. If not, the values below would default to using the project name when this becomes a -// 'flutter create' template. - -// The application's name. By default this is also the title of the Flutter window. -PRODUCT_NAME = example - -// The application's bundle identifier -PRODUCT_BUNDLE_IDENTIFIER = com.example.example - -// The copyright displayed in application information -PRODUCT_COPYRIGHT = Copyright © 2024 com.example. All rights reserved. diff --git a/packages/firebase_vertexai/firebase_vertexai/example/macos/Runner/Configs/Debug.xcconfig b/packages/firebase_vertexai/firebase_vertexai/example/macos/Runner/Configs/Debug.xcconfig deleted file mode 100644 index 36b0fd9464f4..000000000000 --- a/packages/firebase_vertexai/firebase_vertexai/example/macos/Runner/Configs/Debug.xcconfig +++ /dev/null @@ -1,2 +0,0 @@ -#include "../../Flutter/Flutter-Debug.xcconfig" -#include "Warnings.xcconfig" diff --git a/packages/firebase_vertexai/firebase_vertexai/example/macos/Runner/Configs/Release.xcconfig b/packages/firebase_vertexai/firebase_vertexai/example/macos/Runner/Configs/Release.xcconfig deleted file mode 100644 index dff4f49561c8..000000000000 --- a/packages/firebase_vertexai/firebase_vertexai/example/macos/Runner/Configs/Release.xcconfig +++ /dev/null @@ -1,2 +0,0 @@ -#include "../../Flutter/Flutter-Release.xcconfig" -#include "Warnings.xcconfig" diff --git a/packages/firebase_vertexai/firebase_vertexai/example/macos/Runner/Configs/Warnings.xcconfig b/packages/firebase_vertexai/firebase_vertexai/example/macos/Runner/Configs/Warnings.xcconfig deleted file mode 100644 index 42bcbf4780b1..000000000000 --- a/packages/firebase_vertexai/firebase_vertexai/example/macos/Runner/Configs/Warnings.xcconfig +++ /dev/null @@ -1,13 +0,0 @@ -WARNING_CFLAGS = -Wall -Wconditional-uninitialized -Wnullable-to-nonnull-conversion -Wmissing-method-return-type -Woverlength-strings -GCC_WARN_UNDECLARED_SELECTOR = YES -CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES -CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE -CLANG_WARN__DUPLICATE_METHOD_MATCH = YES -CLANG_WARN_PRAGMA_PACK = YES -CLANG_WARN_STRICT_PROTOTYPES = YES -CLANG_WARN_COMMA = YES -GCC_WARN_STRICT_SELECTOR_MATCH = YES -CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK = YES -CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES -GCC_WARN_SHADOW = YES -CLANG_WARN_UNREACHABLE_CODE = YES diff --git a/packages/firebase_vertexai/firebase_vertexai/example/macos/Runner/DebugProfile.entitlements b/packages/firebase_vertexai/firebase_vertexai/example/macos/Runner/DebugProfile.entitlements deleted file mode 100644 index d3eb4e3f2a11..000000000000 --- a/packages/firebase_vertexai/firebase_vertexai/example/macos/Runner/DebugProfile.entitlements +++ /dev/null @@ -1,20 +0,0 @@ - - - - - com.apple.security.app-sandbox - - com.apple.security.cs.allow-jit - - com.apple.security.files.downloads.read-write - - com.apple.security.network.client - - com.apple.security.network.server - - com.apple.security.device.audio-input - - com.apple.security.network.client - - - diff --git a/packages/firebase_vertexai/firebase_vertexai/example/macos/Runner/Info.plist b/packages/firebase_vertexai/firebase_vertexai/example/macos/Runner/Info.plist deleted file mode 100644 index a81b3fd0d617..000000000000 --- a/packages/firebase_vertexai/firebase_vertexai/example/macos/Runner/Info.plist +++ /dev/null @@ -1,34 +0,0 @@ - - - - - CFBundleDevelopmentRegion - $(DEVELOPMENT_LANGUAGE) - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIconFile - - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - APPL - CFBundleShortVersionString - $(FLUTTER_BUILD_NAME) - CFBundleVersion - $(FLUTTER_BUILD_NUMBER) - LSMinimumSystemVersion - $(MACOSX_DEPLOYMENT_TARGET) - NSHumanReadableCopyright - $(PRODUCT_COPYRIGHT) - NSMainNibFile - MainMenu - NSPrincipalClass - NSApplication - NSMicrophoneUsageDescription - Permission to Record audio - - diff --git a/packages/firebase_vertexai/firebase_vertexai/example/macos/Runner/MainFlutterWindow.swift b/packages/firebase_vertexai/firebase_vertexai/example/macos/Runner/MainFlutterWindow.swift deleted file mode 100644 index 3cc05eb23491..000000000000 --- a/packages/firebase_vertexai/firebase_vertexai/example/macos/Runner/MainFlutterWindow.swift +++ /dev/null @@ -1,15 +0,0 @@ -import Cocoa -import FlutterMacOS - -class MainFlutterWindow: NSWindow { - override func awakeFromNib() { - let flutterViewController = FlutterViewController() - let windowFrame = self.frame - self.contentViewController = flutterViewController - self.setFrame(windowFrame, display: true) - - RegisterGeneratedPlugins(registry: flutterViewController) - - super.awakeFromNib() - } -} diff --git a/packages/firebase_vertexai/firebase_vertexai/example/macos/Runner/Release.entitlements b/packages/firebase_vertexai/firebase_vertexai/example/macos/Runner/Release.entitlements deleted file mode 100644 index f18debee72ff..000000000000 --- a/packages/firebase_vertexai/firebase_vertexai/example/macos/Runner/Release.entitlements +++ /dev/null @@ -1,12 +0,0 @@ - - - - - com.apple.security.app-sandbox - - com.apple.security.files.downloads.read-write - - com.apple.security.network.client - - - diff --git a/packages/firebase_vertexai/firebase_vertexai/example/macos/firebase_app_id_file.json b/packages/firebase_vertexai/firebase_vertexai/example/macos/firebase_app_id_file.json deleted file mode 100644 index f4a21e85e553..000000000000 --- a/packages/firebase_vertexai/firebase_vertexai/example/macos/firebase_app_id_file.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "file_generated_by": "FlutterFire CLI", - "purpose": "FirebaseAppID & ProjectID for this Firebase app in this directory", - "GOOGLE_APP_ID": "1:651313571784:ios:722e4f9cad0b9e5db1c2fd", - "FIREBASE_PROJECT_ID": "vertex-ai-example-ef5a2", - "GCM_SENDER_ID": "651313571784" -} \ No newline at end of file diff --git a/packages/firebase_vertexai/firebase_vertexai/example/pubspec.yaml b/packages/firebase_vertexai/firebase_vertexai/example/pubspec.yaml deleted file mode 100644 index f4fd36cd95dc..000000000000 --- a/packages/firebase_vertexai/firebase_vertexai/example/pubspec.yaml +++ /dev/null @@ -1,47 +0,0 @@ -name: vertex_ai_example -description: "Example project to show how to use the Vertex AI SDK." -# The following line prevents the package from being accidentally published to -# pub.dev using `flutter pub publish`. This is preferred for private packages. -publish_to: 'none' # Remove this line if you wish to publish to pub.dev - -version: 1.0.0+1 - -environment: - sdk: '>=3.2.0 <4.0.0' - -# Dependencies specify other packages that your package needs in order to work. -# To automatically upgrade your package dependencies to the latest versions -# consider running `flutter pub upgrade --major-versions`. Alternatively, -# dependencies can be manually updated by changing the version numbers below to -# the latest version available on pub.dev. To see which dependencies have newer -# versions available, run `flutter pub outdated`. -dependencies: - # The following adds the Cupertino Icons font to your application. - # Use with the CupertinoIcons class for iOS style icons. - - cupertino_icons: ^1.0.6 - firebase_core: ^4.1.0 - firebase_storage: ^13.0.1 - firebase_vertexai: ^2.2.0 - flutter: - sdk: flutter - flutter_markdown: ^0.6.20 - flutter_soloud: ^3.1.6 - path_provider: ^2.1.5 - record: ^5.2.1 - -dev_dependencies: - flutter_lints: ^4.0.0 - flutter_test: - sdk: flutter - -flutter: - - # The following line ensures that the Material Icons font is - # included with your application, so that you can use the icons in - # the material Icons class. - uses-material-design: true - assets: - - assets/images/ - - assets/documents/ - - assets/videos/ diff --git a/packages/firebase_vertexai/firebase_vertexai/example/web/favicon.png b/packages/firebase_vertexai/firebase_vertexai/example/web/favicon.png deleted file mode 100644 index 8aaa46ac1ae2..000000000000 Binary files a/packages/firebase_vertexai/firebase_vertexai/example/web/favicon.png and /dev/null differ diff --git a/packages/firebase_vertexai/firebase_vertexai/example/web/icons/Icon-192.png b/packages/firebase_vertexai/firebase_vertexai/example/web/icons/Icon-192.png deleted file mode 100644 index b749bfef0747..000000000000 Binary files a/packages/firebase_vertexai/firebase_vertexai/example/web/icons/Icon-192.png and /dev/null differ diff --git a/packages/firebase_vertexai/firebase_vertexai/example/web/icons/Icon-512.png b/packages/firebase_vertexai/firebase_vertexai/example/web/icons/Icon-512.png deleted file mode 100644 index 88cfd48dff11..000000000000 Binary files a/packages/firebase_vertexai/firebase_vertexai/example/web/icons/Icon-512.png and /dev/null differ diff --git a/packages/firebase_vertexai/firebase_vertexai/example/web/icons/Icon-maskable-192.png b/packages/firebase_vertexai/firebase_vertexai/example/web/icons/Icon-maskable-192.png deleted file mode 100644 index eb9b4d76e525..000000000000 Binary files a/packages/firebase_vertexai/firebase_vertexai/example/web/icons/Icon-maskable-192.png and /dev/null differ diff --git a/packages/firebase_vertexai/firebase_vertexai/example/web/icons/Icon-maskable-512.png b/packages/firebase_vertexai/firebase_vertexai/example/web/icons/Icon-maskable-512.png deleted file mode 100644 index d69c56691fbd..000000000000 Binary files a/packages/firebase_vertexai/firebase_vertexai/example/web/icons/Icon-maskable-512.png and /dev/null differ diff --git a/packages/firebase_vertexai/firebase_vertexai/example/web/index.html b/packages/firebase_vertexai/firebase_vertexai/example/web/index.html deleted file mode 100644 index dcd929827260..000000000000 --- a/packages/firebase_vertexai/firebase_vertexai/example/web/index.html +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - flutterfire_vertexai - - - - - - - - - - \ No newline at end of file diff --git a/packages/firebase_vertexai/firebase_vertexai/example/web/manifest.json b/packages/firebase_vertexai/firebase_vertexai/example/web/manifest.json deleted file mode 100644 index ffebd446235c..000000000000 --- a/packages/firebase_vertexai/firebase_vertexai/example/web/manifest.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "name": "flutterfire_vertexai", - "short_name": "flutterfire_vertexai", - "start_url": ".", - "display": "standalone", - "background_color": "#0175C2", - "theme_color": "#0175C2", - "description": "A new Flutter project.", - "orientation": "portrait-primary", - "prefer_related_applications": false, - "icons": [ - { - "src": "icons/Icon-192.png", - "sizes": "192x192", - "type": "image/png" - }, - { - "src": "icons/Icon-512.png", - "sizes": "512x512", - "type": "image/png" - }, - { - "src": "icons/Icon-maskable-192.png", - "sizes": "192x192", - "type": "image/png", - "purpose": "maskable" - }, - { - "src": "icons/Icon-maskable-512.png", - "sizes": "512x512", - "type": "image/png", - "purpose": "maskable" - } - ] -} diff --git a/packages/firebase_vertexai/firebase_vertexai/example/windows/.gitignore b/packages/firebase_vertexai/firebase_vertexai/example/windows/.gitignore deleted file mode 100644 index d492d0d98c8f..000000000000 --- a/packages/firebase_vertexai/firebase_vertexai/example/windows/.gitignore +++ /dev/null @@ -1,17 +0,0 @@ -flutter/ephemeral/ - -# Visual Studio user-specific files. -*.suo -*.user -*.userosscache -*.sln.docstates - -# Visual Studio build-related files. -x64/ -x86/ - -# Visual Studio cache files -# files ending in .cache can be ignored -*.[Cc]ache -# but keep track of directories ending in .cache -!*.[Cc]ache/ diff --git a/packages/firebase_vertexai/firebase_vertexai/lib/firebase_vertexai.dart b/packages/firebase_vertexai/firebase_vertexai/lib/firebase_vertexai.dart deleted file mode 100644 index d0580c4928e5..000000000000 --- a/packages/firebase_vertexai/firebase_vertexai/lib/firebase_vertexai.dart +++ /dev/null @@ -1,84 +0,0 @@ -// Copyright 2024 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import 'package:firebase_ai/firebase_ai.dart' - show FirebaseAIException, FirebaseAISdkException; - -export 'package:firebase_ai/firebase_ai.dart' - show - BlockReason, - Candidate, - CitationMetadata, - Citation, - CountTokensResponse, - FinishReason, - GenerateContentResponse, - GenerationConfig, - HarmBlockThreshold, - HarmCategory, - HarmProbability, - HarmBlockMethod, - PromptFeedback, - ResponseModalities, - SafetyRating, - SafetySetting, - UsageMetadata, - GenerativeModel, - ImagenModel, - LiveGenerativeModel, - ChatSession, - StartChatExtension, - Content, - InlineDataPart, - FileData, - FunctionCall, - FunctionResponse, - Part, - TextPart, - InvalidApiKey, - ServerException, - UnsupportedUserLocation, - FunctionCallingConfig, - FunctionCallingMode, - FunctionDeclaration, - Tool, - ToolConfig, - ImagenSafetySettings, - ImagenFormat, - ImagenSafetyFilterLevel, - ImagenPersonFilterLevel, - ImagenGenerationConfig, - ImagenAspectRatio, - ImagenInlineImage, - LiveGenerationConfig, - SpeechConfig, - LiveServerMessage, - LiveServerContent, - LiveServerToolCall, - LiveServerToolCallCancellation, - LiveServerResponse, - LiveSession, - Schema, - SchemaType; -export 'src/firebase_vertexai.dart' show FirebaseVertexAI; - -/// Exception thrown when generating content fails. -typedef VertexAIException = FirebaseAIException; - -/// Exception indicating a stale package version or implementation bug. -/// -/// This exception indicates a likely problem with the SDK implementation such -/// as an inability to parse a new response format. Resolution paths may include -/// updating to a new version of the SDK, or filing an issue. -typedef VertexAISdkException = FirebaseAISdkException; diff --git a/packages/firebase_vertexai/firebase_vertexai/lib/src/firebase_vertexai.dart b/packages/firebase_vertexai/firebase_vertexai/lib/src/firebase_vertexai.dart deleted file mode 100644 index 9edd832302f6..000000000000 --- a/packages/firebase_vertexai/firebase_vertexai/lib/src/firebase_vertexai.dart +++ /dev/null @@ -1,187 +0,0 @@ -// Copyright 2024 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import 'package:firebase_ai/firebase_ai.dart'; -// ignore: implementation_imports -import 'package:firebase_ai/src/base_model.dart' - show createGenerativeModel, createLiveGenerativeModel, createImagenModel; -import 'package:firebase_app_check/firebase_app_check.dart'; -import 'package:firebase_auth/firebase_auth.dart'; -import 'package:firebase_core/firebase_core.dart'; -import 'package:firebase_core_platform_interface/firebase_core_platform_interface.dart' - show FirebasePluginPlatform; -import 'package:meta/meta.dart'; - -const _defaultLocation = 'us-central1'; - -/// The entrypoint for [FirebaseVertexAI]. -@Deprecated( - '`FirebaseVertexAI` library and `firebase_vertexai` package have been renamed ' - 'and replaced by the new Firebase AI SDK: `FirebaseAI` in `firebase_ai` package. ' - 'See details in the [migration guide](https://firebase.google.com/docs/vertex-ai/migrate-to-latest-sdk).', -) -class FirebaseVertexAI extends FirebasePluginPlatform { - FirebaseVertexAI._( - {required this.app, - required this.location, - required bool useVertexBackend, - this.appCheck, - this.auth}) - : _useVertexBackend = useVertexBackend, - super(app.name, 'plugins.flutter.io/firebase_vertexai'); - - /// The [FirebaseApp] for this current [FirebaseVertexAI] instance. - FirebaseApp app; - - /// The optional [FirebaseAppCheck] for this current [FirebaseVertexAI] instance. - /// https://firebase.google.com/docs/app-check - FirebaseAppCheck? appCheck; - - /// The optional [FirebaseAuth] for this current [FirebaseVertexAI] instance. - FirebaseAuth? auth; - - /// The service location for this [FirebaseVertexAI] instance. - String location; - - final bool _useVertexBackend; - - static final Map _cachedInstances = {}; - - /// Returns an instance using the default [FirebaseApp]. - static FirebaseVertexAI get instance { - return FirebaseVertexAI.instanceFor( - app: Firebase.app(), - ); - } - - /// Returns an instance using a specified [FirebaseApp]. - /// - /// If [app] is not provided, the default Firebase app will be used. - /// If pass in [appCheck], request session will get protected from abusing. - static FirebaseVertexAI instanceFor({ - FirebaseApp? app, - FirebaseAppCheck? appCheck, - FirebaseAuth? auth, - String? location, - }) => - _vertexAI(app: app, appCheck: appCheck, auth: auth, location: location); - - /// Returns an instance using a specified [FirebaseApp]. - /// - /// If [app] is not provided, the default Firebase app will be used. - /// If pass in [appCheck], request session will get protected from abusing. - static FirebaseVertexAI _vertexAI({ - FirebaseApp? app, - FirebaseAppCheck? appCheck, - FirebaseAuth? auth, - String? location, - }) { - app ??= Firebase.app(); - var instanceKey = '${app.name}::vertexai'; - - if (_cachedInstances.containsKey(instanceKey)) { - return _cachedInstances[instanceKey]!; - } - - location ??= _defaultLocation; - - FirebaseVertexAI newInstance = FirebaseVertexAI._( - app: app, - location: location, - appCheck: appCheck, - auth: auth, - useVertexBackend: true, - ); - _cachedInstances[instanceKey] = newInstance; - - return newInstance; - } - - /// Create a [GenerativeModel] backed by the generative model named [model]. - /// - /// The [model] argument can be a model name (such as `'gemini-pro'`) or a - /// model code (such as `'models/gemini-pro'`). - /// There is no creation time check for whether the `model` string identifies - /// a known and supported model. If not, attempts to generate content - /// will fail. - /// - /// The optional [safetySettings] and [generationConfig] can be used to - /// control and guide the generation. See [SafetySetting] and - /// [GenerationConfig] for details. - GenerativeModel generativeModel({ - required String model, - List? safetySettings, - GenerationConfig? generationConfig, - List? tools, - ToolConfig? toolConfig, - Content? systemInstruction, - }) { - return createGenerativeModel( - model: model, - app: app, - appCheck: appCheck, - useVertexBackend: _useVertexBackend, - auth: auth, - location: location, - safetySettings: safetySettings, - generationConfig: generationConfig, - tools: tools, - toolConfig: toolConfig, - systemInstruction: systemInstruction, - ); - } - - /// Create a [ImagenModel]. - /// - /// The optional [safetySettings] can be used to control and guide the - /// generation. See [ImagenSafetySettings] for details. - @experimental - ImagenModel imagenModel( - {required String model, - ImagenGenerationConfig? generationConfig, - ImagenSafetySettings? safetySettings}) { - return createImagenModel( - app: app, - location: location, - model: model, - useVertexBackend: _useVertexBackend, - generationConfig: generationConfig, - safetySettings: safetySettings, - appCheck: appCheck, - auth: auth); - } - - /// Create a [LiveGenerativeModel] for real-time interaction. - /// - /// The optional [liveGenerationConfig] can be used to control and guide the - /// generation. See [LiveGenerationConfig] for details. - LiveGenerativeModel liveGenerativeModel({ - required String model, - LiveGenerationConfig? liveGenerationConfig, - List? tools, - Content? systemInstruction, - }) { - return createLiveGenerativeModel( - app: app, - location: location, - model: model, - useVertexBackend: _useVertexBackend, - liveGenerationConfig: liveGenerationConfig, - tools: tools, - systemInstruction: systemInstruction, - appCheck: appCheck, - auth: auth, - ); - } -} diff --git a/packages/firebase_vertexai/firebase_vertexai/lib/src/vertex_version.dart b/packages/firebase_vertexai/firebase_vertexai/lib/src/vertex_version.dart deleted file mode 100644 index 4c27812bc27e..000000000000 --- a/packages/firebase_vertexai/firebase_vertexai/lib/src/vertex_version.dart +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2024 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/// generated version number for the package, do not manually edit -const packageVersion = '2.2.0'; diff --git a/packages/firebase_vertexai/firebase_vertexai/pubspec.yaml b/packages/firebase_vertexai/firebase_vertexai/pubspec.yaml deleted file mode 100644 index f59500fc23c8..000000000000 --- a/packages/firebase_vertexai/firebase_vertexai/pubspec.yaml +++ /dev/null @@ -1,40 +0,0 @@ -name: firebase_vertexai -description: "Firebase Vertex AI SDK." -version: 2.2.0 -homepage: https://firebase.google.com/docs/vertex-ai/get-started?platform=flutter -topics: - - firebase - - vertexai - - gemini - - generative-ai - -# Explicit about the supported platforms. -platforms: - android: - ios: - macos: - web: - -environment: - sdk: '>=3.2.0 <4.0.0' - flutter: ">=3.16.0" - -dependencies: - firebase_ai: ^3.2.0 - firebase_app_check: ^0.4.0+1 - firebase_auth: ^6.0.2 - firebase_core: ^4.1.0 - firebase_core_platform_interface: ^6.0.0 - flutter: - sdk: flutter - http: ^1.1.0 - meta: ^1.15.0 - web_socket_channel: ^3.0.1 - -dev_dependencies: - flutter_lints: ^4.0.0 - flutter_test: - sdk: flutter - matcher: ^0.12.16 - mockito: ^5.0.0 - plugin_platform_interface: ^2.1.3 diff --git a/packages/firebase_vertexai/firebase_vertexai/test/api_test.dart b/packages/firebase_vertexai/firebase_vertexai/test/api_test.dart deleted file mode 100644 index e11927ef3497..000000000000 --- a/packages/firebase_vertexai/firebase_vertexai/test/api_test.dart +++ /dev/null @@ -1,818 +0,0 @@ -// Copyright 2025 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import 'package:firebase_ai/firebase_ai.dart'; -import 'package:firebase_ai/src/api.dart'; - -import 'package:flutter_test/flutter_test.dart'; - -// --- Mock/Helper Implementations --- -// Minimal implementations or mocks for classes from imported files -// to make tests self-contained and focused on the target file's logic. - -void main() { - group('CountTokensResponse', () { - test('constructor initializes fields correctly', () { - final details = [ModalityTokenCount(ContentModality.text, 10)]; - final response = CountTokensResponse(100, promptTokensDetails: details); - expect(response.totalTokens, 100); - expect(response.promptTokensDetails, same(details)); - }); - - test('constructor with null optional fields', () { - final response = CountTokensResponse(100); - expect(response.totalTokens, 100); - expect(response.promptTokensDetails, isNull); - }); - }); - - group('GenerateContentResponse', () { - // Mock candidates - - final textContent = Content.text('Hello'); - - final candidateWithText = - Candidate(textContent, null, null, FinishReason.stop, null); - final candidateWithMultipleTextParts = Candidate( - Content('model', [const TextPart('Hello'), const TextPart(' World')]), - null, - null, - FinishReason.stop, - null); - - final candidateFinishedSafety = Candidate( - textContent, null, null, FinishReason.safety, 'Safety concern'); - final candidateFinishedRecitation = Candidate( - textContent, null, null, FinishReason.recitation, 'Recited content'); - - group('.text getter', () { - test('returns null if no candidates and no prompt feedback', () { - final response = GenerateContentResponse([], null); - expect(response.text, isNull); - }); - - test( - 'throws FirebaseAIException if prompt was blocked without message or reason', - () { - final feedback = PromptFeedback(BlockReason.safety, null, []); - final response = GenerateContentResponse([], feedback); - expect( - () => response.text, - throwsA(isA().having((e) => e.message, - 'message', 'Response was blocked due to safety'))); - }); - - test( - 'throws FirebaseAIException if prompt was blocked with reason and message', - () { - final feedback = - PromptFeedback(BlockReason.other, 'Custom block message', []); - final response = GenerateContentResponse([], feedback); - expect( - () => response.text, - throwsA(isA().having( - (e) => e.message, - 'message', - 'Response was blocked due to other: Custom block message'))); - }); - - test( - 'throws FirebaseAIException if first candidate finished due to safety', - () { - final response = - GenerateContentResponse([candidateFinishedSafety], null); - expect( - () => response.text, - throwsA(isA().having( - (e) => e.message, - 'message', - 'Candidate was blocked due to safety: Safety concern'))); - }); - test( - 'throws FirebaseAIException if first candidate finished due to safety without message', - () { - final candidateFinishedSafetyNoMsg = - Candidate(textContent, null, null, FinishReason.safety, ''); - final response = - GenerateContentResponse([candidateFinishedSafetyNoMsg], null); - expect( - () => response.text, - throwsA(isA().having((e) => e.message, - 'message', 'Candidate was blocked due to safety'))); - }); - - test( - 'throws FirebaseAIException if first candidate finished due to recitation', - () { - final response = - GenerateContentResponse([candidateFinishedRecitation], null); - expect( - () => response.text, - throwsA(isA().having( - (e) => e.message, - 'message', - 'Candidate was blocked due to recitation: Recited content'))); - }); - - test('returns text from single TextPart in first candidate', () { - final response = GenerateContentResponse([candidateWithText], null); - expect(response.text, 'Hello'); - }); - - test('concatenates text from multiple TextParts in first candidate', () { - final response = - GenerateContentResponse([candidateWithMultipleTextParts], null); - expect(response.text, 'Hello World'); - }); - }); - - group('.functionCalls getter', () { - test('returns empty list if no candidates', () { - final response = GenerateContentResponse([], null); - expect(response.functionCalls, isEmpty); - }); - - test('returns empty list if first candidate has no FunctionCall parts', - () { - final response = GenerateContentResponse([candidateWithText], null); - expect(response.functionCalls, isEmpty); - }); - }); - test('constructor initializes fields correctly', () { - final candidates = [candidateWithText]; - final feedback = PromptFeedback(null, null, []); - - final response = GenerateContentResponse( - candidates, - feedback, - ); - - expect(response.candidates, same(candidates)); - expect(response.promptFeedback, same(feedback)); - }); - }); - - group('PromptFeedback', () { - test('constructor initializes fields correctly', () { - final ratings = [ - SafetyRating(HarmCategory.dangerousContent, HarmProbability.high) - ]; - final feedback = PromptFeedback(BlockReason.safety, 'Blocked', ratings); - expect(feedback.blockReason, BlockReason.safety); - expect(feedback.blockReasonMessage, 'Blocked'); - expect(feedback.safetyRatings, same(ratings)); - }); - }); - - group('Candidate', () { - final textContent = Content.text('Test text'); - group('.text getter', () { - test('throws FirebaseAIException if finishReason is safety with message', - () { - final candidate = Candidate(textContent, null, null, - FinishReason.safety, 'Safety block message'); - expect( - () => candidate.text, - throwsA(isA().having( - (e) => e.message, - 'message', - 'Candidate was blocked due to safety: Safety block message'))); - }); - test( - 'throws FirebaseAIException if finishReason is safety without message', - () { - final candidate = Candidate( - textContent, null, null, FinishReason.safety, ''); // Empty message - expect( - () => candidate.text, - throwsA(isA().having((e) => e.message, - 'message', 'Candidate was blocked due to safety'))); - }); - - test( - 'throws FirebaseAIException if finishReason is recitation with message', - () { - final candidate = Candidate(textContent, null, null, - FinishReason.recitation, 'Recitation block message'); - expect( - () => candidate.text, - throwsA(isA().having( - (e) => e.message, - 'message', - 'Candidate was blocked due to recitation: Recitation block message'))); - }); - - test('returns text from single TextPart', () { - final candidate = - Candidate(textContent, null, null, FinishReason.stop, null); - expect(candidate.text, 'Test text'); - }); - - test('concatenates text from multiple TextParts', () { - final multiPartContent = Content( - 'model', - [ - const TextPart('Part 1'), - const TextPart('. Part 2'), - ], - ); - final candidate = - Candidate(multiPartContent, null, null, FinishReason.stop, null); - expect(candidate.text, 'Part 1. Part 2'); - }); - - test('returns text if finishReason is other non-blocking reason', () { - final candidate = - Candidate(textContent, null, null, FinishReason.maxTokens, null); - expect(candidate.text, 'Test text'); - }); - }); - test('constructor initializes fields correctly', () { - final content = Content.text('Hello'); - final ratings = [ - SafetyRating(HarmCategory.harassment, HarmProbability.low) - ]; - final citationMeta = CitationMetadata([]); - final candidate = Candidate( - content, ratings, citationMeta, FinishReason.stop, 'Finished'); - - expect(candidate.content, same(content)); - expect(candidate.safetyRatings, same(ratings)); - expect(candidate.citationMetadata, same(citationMeta)); - expect(candidate.finishReason, FinishReason.stop); - expect(candidate.finishMessage, 'Finished'); - }); - }); - - group('SafetyRating', () { - test('constructor initializes fields correctly', () { - final rating = SafetyRating( - HarmCategory.hateSpeech, HarmProbability.medium, - probabilityScore: 0.6, - isBlocked: true, - severity: HarmSeverity.high, - severityScore: 0.9); - expect(rating.category, HarmCategory.hateSpeech); - expect(rating.probability, HarmProbability.medium); - expect(rating.probabilityScore, 0.6); - expect(rating.isBlocked, true); - expect(rating.severity, HarmSeverity.high); - expect(rating.severityScore, 0.9); - }); - }); - - group('Enums', () { - test('BlockReason toJson and toString', () { - expect(BlockReason.unknown.toJson(), 'UNKNOWN'); - expect(BlockReason.safety.toJson(), 'SAFETY'); - expect(BlockReason.other.toJson(), 'OTHER'); - }); - - test('HarmCategory toJson and toString', () { - expect(HarmCategory.unknown.toJson(), 'UNKNOWN'); - expect(HarmCategory.harassment.toJson(), 'HARM_CATEGORY_HARASSMENT'); - expect(HarmCategory.hateSpeech.toJson(), 'HARM_CATEGORY_HATE_SPEECH'); - expect(HarmCategory.sexuallyExplicit.toJson(), - 'HARM_CATEGORY_SEXUALLY_EXPLICIT'); - expect(HarmCategory.dangerousContent.toJson(), - 'HARM_CATEGORY_DANGEROUS_CONTENT'); - }); - - test('HarmProbability toJson and toString', () { - expect(HarmProbability.unknown.toJson(), 'UNKNOWN'); - expect(HarmProbability.negligible.toJson(), 'NEGLIGIBLE'); - expect(HarmProbability.low.toJson(), 'LOW'); - expect(HarmProbability.medium.toJson(), 'MEDIUM'); - expect(HarmProbability.high.toJson(), 'HIGH'); - }); - - test('HarmSeverity toJson and toString', () { - expect(HarmSeverity.unknown.toJson(), 'UNKNOWN'); - expect(HarmSeverity.negligible.toJson(), 'NEGLIGIBLE'); - expect(HarmSeverity.low.toJson(), 'LOW'); - expect(HarmSeverity.medium.toJson(), 'MEDIUM'); - expect(HarmSeverity.high.toJson(), 'HIGH'); - }); - - test('FinishReason toJson and toString', () { - expect(FinishReason.unknown.toJson(), 'UNKNOWN'); - expect(FinishReason.stop.toJson(), 'STOP'); - expect(FinishReason.maxTokens.toJson(), 'MAX_TOKENS'); - expect(FinishReason.safety.toJson(), 'SAFETY'); - expect(FinishReason.recitation.toJson(), 'RECITATION'); - expect(FinishReason.other.toJson(), 'OTHER'); - }); - - test('ContentModality toJson and toString', () { - expect(ContentModality.unspecified.toJson(), 'MODALITY_UNSPECIFIED'); - expect(ContentModality.text.toJson(), 'TEXT'); - expect(ContentModality.image.toJson(), 'IMAGE'); - expect(ContentModality.video.toJson(), 'VIDEO'); - expect(ContentModality.audio.toJson(), 'AUDIO'); - expect(ContentModality.document.toJson(), 'DOCUMENT'); - }); - - test('HarmBlockThreshold toJson and toString', () { - expect(HarmBlockThreshold.low.toJson(), 'BLOCK_LOW_AND_ABOVE'); - expect(HarmBlockThreshold.medium.toJson(), 'BLOCK_MEDIUM_AND_ABOVE'); - expect(HarmBlockThreshold.high.toJson(), 'BLOCK_ONLY_HIGH'); - expect(HarmBlockThreshold.none.toJson(), 'BLOCK_NONE'); - expect(HarmBlockThreshold.off.toJson(), 'OFF'); - }); - - test('HarmBlockMethod toJson and toString', () { - expect(HarmBlockMethod.severity.toJson(), 'SEVERITY'); - expect(HarmBlockMethod.probability.toJson(), 'PROBABILITY'); - expect(HarmBlockMethod.unspecified.toJson(), - 'HARM_BLOCK_METHOD_UNSPECIFIED'); - }); - - test('TaskType toJson and toString', () { - expect(TaskType.unspecified.toJson(), 'TASK_TYPE_UNSPECIFIED'); - expect(TaskType.retrievalQuery.toJson(), 'RETRIEVAL_QUERY'); - expect(TaskType.retrievalDocument.toJson(), 'RETRIEVAL_DOCUMENT'); - expect(TaskType.semanticSimilarity.toJson(), 'SEMANTIC_SIMILARITY'); - expect(TaskType.classification.toJson(), 'CLASSIFICATION'); - expect(TaskType.clustering.toJson(), 'CLUSTERING'); - }); - }); - - group('CitationMetadata and Citation', () { - test('Citation constructor', () { - final uri = Uri.parse('http://example.com'); - final citation = Citation(0, 10, uri, 'Apache-2.0'); - expect(citation.startIndex, 0); - expect(citation.endIndex, 10); - expect(citation.uri, uri); - expect(citation.license, 'Apache-2.0'); - }); - test('CitationMetadata constructor', () { - final citation = Citation(0, 5, Uri.parse('a.com'), 'MIT'); - final metadata = CitationMetadata([citation]); - expect(metadata.citations, hasLength(1)); - expect(metadata.citations.first, same(citation)); - }); - }); - - group('ModalityTokenCount', () { - test('constructor initializes fields correctly', () { - final mtc = ModalityTokenCount(ContentModality.image, 150); - expect(mtc.modality, ContentModality.image); - expect(mtc.tokenCount, 150); - }); - }); - - group('SafetySetting', () { - test('toJson with all fields', () { - final setting = SafetySetting(HarmCategory.dangerousContent, - HarmBlockThreshold.medium, HarmBlockMethod.severity); - expect(setting.toJson(), { - 'category': 'HARM_CATEGORY_DANGEROUS_CONTENT', - 'threshold': 'BLOCK_MEDIUM_AND_ABOVE', - 'method': 'SEVERITY', - }); - }); - - test('toJson with method null (default to probability in spirit)', () { - // The toJson implementation will omit method if null - final setting = - SafetySetting(HarmCategory.harassment, HarmBlockThreshold.low, null); - expect(setting.toJson(), { - 'category': 'HARM_CATEGORY_HARASSMENT', - 'threshold': 'BLOCK_LOW_AND_ABOVE', - }); - }); - }); - - group('GenerationConfig & BaseGenerationConfig', () { - test('GenerationConfig toJson with all fields', () { - final schema = Schema.object(properties: {}); - final config = GenerationConfig( - candidateCount: 1, - stopSequences: ['\n', 'stop'], - maxOutputTokens: 200, - temperature: 0.7, - topP: 0.95, - topK: 50, - presencePenalty: 0.3, - frequencyPenalty: 0.4, - responseMimeType: 'application/json', - responseSchema: schema, - ); - expect(config.toJson(), { - 'candidateCount': 1, - 'maxOutputTokens': 200, - 'temperature': 0.7, - 'topP': 0.95, - 'topK': 50, - 'presencePenalty': 0.3, - 'frequencyPenalty': 0.4, - 'stopSequences': ['\n', 'stop'], - 'responseMimeType': 'application/json', - 'responseSchema': schema - .toJson(), // Schema itself not schema.toJson() in the provided code - }); - }); - - test('GenerationConfig toJson with empty stopSequences (omitted)', () { - final config = GenerationConfig(stopSequences: []); - expect(config.toJson(), {}); // Empty list for stopSequences is omitted - }); - - test('GenerationConfig toJson with some fields null', () { - final config = GenerationConfig( - temperature: 0.7, - responseMimeType: 'text/plain', - ); - expect(config.toJson(), { - 'temperature': 0.7, - 'responseMimeType': 'text/plain', - }); - }); - }); - - group('Parsing Functions', () { - group('parseCountTokensResponse', () { - test('parses valid full JSON correctly', () { - final json = { - 'totalTokens': 120, - 'promptTokensDetails': [ - { - 'modality': 'TEXT', - }, - {'modality': 'IMAGE', 'tokenCount': 20} - ] - }; - final response = VertexSerialization().parseCountTokensResponse(json); - expect(response.totalTokens, 120); - expect(response.promptTokensDetails, isNotNull); - expect(response.promptTokensDetails, hasLength(2)); - expect(response.promptTokensDetails![0].modality, ContentModality.text); - expect(response.promptTokensDetails![0].tokenCount, 0); - expect( - response.promptTokensDetails![1].modality, ContentModality.image); - expect(response.promptTokensDetails![1].tokenCount, 20); - }); - - test('parses valid JSON with minimal fields (only totalTokens)', () { - final json = {'totalTokens': 50}; - final response = VertexSerialization().parseCountTokensResponse(json); - expect(response.totalTokens, 50); - expect(response.promptTokensDetails, isNull); - }); - - test('throws FirebaseAIException if JSON contains error field', () { - final json = { - 'error': {'code': 400, 'message': 'Invalid request'} - }; - expect(() => VertexSerialization().parseCountTokensResponse(json), - throwsA(isA())); - }); - - test('throws FormatException for invalid JSON structure (not a Map)', () { - const json = 'not_a_map'; - expect( - () => VertexSerialization().parseCountTokensResponse(json), - throwsA(isA().having( - (e) => e.message, 'message', contains('CountTokensResponse')))); - }); - - test('throws if totalTokens is missing', () { - final json = {'totalBillableCharacters': 100}; - expect(() => VertexSerialization().parseCountTokensResponse(json), - throwsA(anything)); // More specific error expected - }); - }); - - group('parseGenerateContentResponse', () { - final basicCandidateJson = { - 'content': { - 'role': 'model', - 'parts': [ - {'text': 'Hello world'} - ] - }, - 'finishReason': 'STOP', - 'safetyRatings': [ - { - 'category': 'HARM_CATEGORY_SEXUALLY_EXPLICIT', - 'probability': 'NEGLIGIBLE' - } - ] - }; - - test('parses valid JSON with candidates and promptFeedback', () { - final json = { - 'candidates': [basicCandidateJson], - 'promptFeedback': { - 'blockReason': 'SAFETY', - 'blockReasonMessage': 'Prompt was too spicy.', - 'safetyRatings': [ - { - 'category': 'HARM_CATEGORY_DANGEROUS_CONTENT', - 'probability': 'HIGH', - 'blocked': true, - 'severity': 'HARM_SEVERITY_HIGH', - 'severityScore': 0.95 - } - ] - }, - 'usageMetadata': { - 'promptTokenCount': 10, - 'candidatesTokenCount': 20, - 'totalTokenCount': 30, - 'promptTokensDetails': [ - {'modality': 'TEXT', 'tokenCount': 10} - ], - 'candidatesTokensDetails': [ - {'modality': 'TEXT', 'tokenCount': 20} - ], - } - }; - final response = - VertexSerialization().parseGenerateContentResponse(json); - expect(response.candidates, hasLength(1)); - expect(response.candidates.first.text, 'Hello world'); - expect(response.candidates.first.finishReason, FinishReason.stop); - expect(response.candidates.first.safetyRatings, isNotNull); - expect(response.candidates.first.safetyRatings, hasLength(1)); - - expect(response.promptFeedback, isNotNull); - expect(response.promptFeedback!.blockReason, BlockReason.safety); - expect(response.promptFeedback!.blockReasonMessage, - 'Prompt was too spicy.'); - expect(response.promptFeedback!.safetyRatings, hasLength(1)); - expect(response.promptFeedback!.safetyRatings.first.category, - HarmCategory.dangerousContent); - expect(response.promptFeedback!.safetyRatings.first.probability, - HarmProbability.high); - expect(response.promptFeedback!.safetyRatings.first.isBlocked, true); - expect(response.promptFeedback!.safetyRatings.first.severity, - HarmSeverity.high); - expect( - response.promptFeedback!.safetyRatings.first.severityScore, 0.95); - - expect(response.usageMetadata, isNotNull); - expect(response.usageMetadata!.promptTokenCount, 10); - expect(response.usageMetadata!.candidatesTokenCount, 20); - expect(response.usageMetadata!.totalTokenCount, 30); - expect(response.usageMetadata!.promptTokensDetails, hasLength(1)); - expect(response.usageMetadata!.candidatesTokensDetails, hasLength(1)); - }); - - test('parses JSON with no candidates (empty list)', () { - final json = {'candidates': []}; - final response = - VertexSerialization().parseGenerateContentResponse(json); - expect(response.candidates, isEmpty); - expect(response.promptFeedback, isNull); - expect(response.usageMetadata, isNull); - }); - - test('parses JSON with null candidates (treated as empty)', () { - // The code defaults to [] if 'candidates' key is missing - final json = {'promptFeedback': null}; - final response = - VertexSerialization().parseGenerateContentResponse(json); - expect(response.candidates, isEmpty); - expect(response.promptFeedback, isNull); - }); - - test('parses JSON with missing optional fields in candidate', () { - final json = { - 'candidates': [ - { - 'content': { - 'parts': [ - {'text': 'Minimal'} - ] - } - // Missing finishReason, safetyRatings, citationMetadata, finishMessage - } - ] - }; - final response = - VertexSerialization().parseGenerateContentResponse(json); - expect(response.candidates, hasLength(1)); - expect(response.candidates.first.text, 'Minimal'); - expect(response.candidates.first.finishReason, isNull); - expect(response.candidates.first.safetyRatings, isNull); - expect(response.candidates.first.citationMetadata, isNull); - expect(response.candidates.first.finishMessage, isNull); - }); - - test('parses usageMetadata for no tokenCount', () { - final json = { - 'candidates': [basicCandidateJson], - 'usageMetadata': { - 'promptTokenCount': 10, - 'candidatesTokenCount': 20, - 'totalTokenCount': 30, - 'promptTokensDetails': [ - {'modality': 'TEXT', 'tokenCount': 10} - ], - 'candidatesTokensDetails': [ - { - 'modality': 'TEXT', - } - ], - } - }; - final response = - VertexSerialization().parseGenerateContentResponse(json); - expect(response.candidates, hasLength(1)); - expect(response.candidates.first.text, 'Hello world'); - expect(response.candidates.first.finishReason, FinishReason.stop); - expect(response.candidates.first.safetyRatings, isNotNull); - expect(response.candidates.first.safetyRatings, hasLength(1)); - - expect(response.usageMetadata, isNotNull); - expect(response.usageMetadata!.promptTokenCount, 10); - expect(response.usageMetadata!.candidatesTokenCount, 20); - expect(response.usageMetadata!.totalTokenCount, 30); - expect(response.usageMetadata!.promptTokensDetails, hasLength(1)); - expect(response.usageMetadata!.promptTokensDetails!.first.modality, - ContentModality.text); - expect( - response.usageMetadata!.promptTokensDetails!.first.tokenCount, 10); - expect(response.usageMetadata!.candidatesTokensDetails, hasLength(1)); - expect(response.usageMetadata!.candidatesTokensDetails!.first.modality, - ContentModality.text); - expect( - response.usageMetadata!.candidatesTokensDetails!.first.tokenCount, - 0); - }); - - test('parses citationMetadata with "citationSources"', () { - final json = { - 'candidates': [ - { - 'content': { - 'parts': [ - {'text': 'Cited text'} - ] - }, - 'citationMetadata': { - 'citationSources': [ - { - 'startIndex': 0, - 'endIndex': 5, - 'uri': 'http://example.com/source1', - 'license': 'CC-BY' - } - ] - } - } - ] - }; - final response = - VertexSerialization().parseGenerateContentResponse(json); - final candidate = response.candidates.first; - expect(candidate.citationMetadata, isNotNull); - expect(candidate.citationMetadata!.citations, hasLength(1)); - expect(candidate.citationMetadata!.citations.first.uri.toString(), - 'http://example.com/source1'); - }); - test('parses citationMetadata with "citations" (Vertex SDK format)', () { - final json = { - 'candidates': [ - { - 'content': { - 'parts': [ - {'text': 'Cited text'} - ] - }, - 'citationMetadata': { - 'citations': [ - // Vertex SDK uses 'citations' - { - 'startIndex': 0, - 'endIndex': 5, - 'uri': 'http://example.com/source2', - 'license': 'MIT' - } - ] - } - } - ] - }; - final response = - VertexSerialization().parseGenerateContentResponse(json); - final candidate = response.candidates.first; - expect(candidate.citationMetadata, isNotNull); - expect(candidate.citationMetadata!.citations, hasLength(1)); - expect(candidate.citationMetadata!.citations.first.uri.toString(), - 'http://example.com/source2'); - expect(candidate.citationMetadata!.citations.first.license, 'MIT'); - }); - - test('throws FirebaseAIException if JSON contains error field', () { - final json = { - 'error': {'code': 500, 'message': 'Internal server error'} - }; - expect(() => VertexSerialization().parseGenerateContentResponse(json), - throwsA(isA())); - }); - - test('handles missing content in candidate gracefully (empty content)', - () { - final json = { - 'candidates': [ - { - // No 'content' field - 'finishReason': 'STOP', - } - ] - }; - final response = - VertexSerialization().parseGenerateContentResponse(json); - expect(response.candidates, hasLength(1)); - expect(response.candidates.first.content.parts, isEmpty); - expect(response.candidates.first.text, isNull); - }); - test('throws FormatException for invalid candidate structure (not a Map)', - () { - final jsonResponse = { - 'candidates': ['not_a_map_candidate'] - }; - expect( - () => VertexSerialization() - .parseGenerateContentResponse(jsonResponse), - throwsA(isA() - .having((e) => e.message, 'message', contains('Candidate')))); - }); - - test('throws FormatException for invalid safety rating structure', () { - final jsonResponse = { - 'candidates': [ - { - 'content': {'parts': []}, - 'safetyRatings': ['not_a_map_rating'] - } - ] - }; - expect( - () => VertexSerialization() - .parseGenerateContentResponse(jsonResponse), - throwsA(isA().having( - (e) => e.message, 'message', contains('SafetyRating')))); - }); - test('throws FormatException for invalid citation metadata structure', - () { - final jsonResponse = { - 'candidates': [ - { - 'content': {'parts': []}, - 'citationMetadata': 'not_a_map_citation' - } - ] - }; - expect( - () => VertexSerialization() - .parseGenerateContentResponse(jsonResponse), - throwsA(isA().having( - (e) => e.message, 'message', contains('CitationMetadata')))); - }); - test('throws FormatException for invalid prompt feedback structure', () { - final jsonResponse = {'promptFeedback': 'not_a_map_feedback'}; - expect( - () => VertexSerialization() - .parseGenerateContentResponse(jsonResponse), - throwsA(isA().having( - (e) => e.message, 'message', contains('PromptFeedback')))); - }); - test('throws FormatException for invalid usage metadata structure', () { - final jsonResponse = {'usageMetadata': 'not_a_map_usage'}; - expect( - () => VertexSerialization() - .parseGenerateContentResponse(jsonResponse), - throwsA(isA().having( - (e) => e.message, 'message', contains('UsageMetadata')))); - }); - test('throws FormatException for invalid modality token count structure', - () { - final jsonResponse = { - 'usageMetadata': { - 'promptTokensDetails': ['not_a_map_modality'] - } - }; - expect( - () => VertexSerialization() - .parseGenerateContentResponse(jsonResponse), - throwsA(isA().having( - (e) => e.message, 'message', contains('ModalityTokenCount')))); - }); - }); - }); -} diff --git a/packages/firebase_vertexai/firebase_vertexai/test/chat_test.dart b/packages/firebase_vertexai/firebase_vertexai/test/chat_test.dart deleted file mode 100644 index 1222c079a8ac..000000000000 --- a/packages/firebase_vertexai/firebase_vertexai/test/chat_test.dart +++ /dev/null @@ -1,132 +0,0 @@ -// Copyright 2024 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import 'package:firebase_ai/src/base_model.dart'; -import 'package:firebase_core/firebase_core.dart'; -import 'package:firebase_vertexai/firebase_vertexai.dart'; -import 'package:flutter_test/flutter_test.dart'; - -import 'mock.dart'; -import 'utils/matchers.dart'; -import 'utils/stub_client.dart'; - -void main() { - setupFirebaseVertexAIMocks(); - // ignore: unused_local_variable - late FirebaseApp app; - - group('Chat', () { - const defaultModelName = 'some-model'; - setUpAll(() async { - // Initialize Firebase - app = await Firebase.initializeApp(); - }); - - (ClientController, GenerativeModel) createModel([ - String modelName = defaultModelName, - ]) { - final client = ClientController(); - final model = createModelWithClient( - app: app, - useVertexBackend: true, - model: modelName, - client: client.client, - location: 'us-central1'); - return (client, model); - } - - test('includes chat history in prompt', () async { - final (client, model) = createModel('models/$defaultModelName'); - final chat = model.startChat(history: [ - Content.text('Hi!'), - Content.model([const TextPart('Hello, how can I help you today?')]), - ]); - const prompt = 'Some prompt'; - final response = await client.checkRequest( - () => chat.sendMessage(Content.text(prompt)), - verifyRequest: (_, request) { - final contents = request['contents']; - expect(contents, hasLength(3)); - }, - response: arbitraryGenerateContentResponse, - ); - expect( - chat.history.last, - matchesContent(response.candidates.first.content), - ); - }); - - test('forwards safety settings', () async { - final (client, model) = createModel('models/$defaultModelName'); - final chat = model.startChat(safetySettings: [ - SafetySetting(HarmCategory.dangerousContent, HarmBlockThreshold.high, - HarmBlockMethod.severity), - ]); - const prompt = 'Some prompt'; - await client.checkRequest( - () => chat.sendMessage(Content.text(prompt)), - verifyRequest: (_, request) { - expect(request['safetySettings'], [ - { - 'category': 'HARM_CATEGORY_DANGEROUS_CONTENT', - 'threshold': 'BLOCK_ONLY_HIGH', - 'method': 'SEVERITY' - }, - ]); - }, - response: arbitraryGenerateContentResponse, - ); - }); - - test('forwards safety settings and config when streaming', () async { - final (client, model) = createModel('models/$defaultModelName'); - final chat = model.startChat(safetySettings: [ - SafetySetting(HarmCategory.dangerousContent, HarmBlockThreshold.high, - HarmBlockMethod.probability), - ], generationConfig: GenerationConfig(stopSequences: ['a'])); - const prompt = 'Some prompt'; - final responses = await client.checkStreamRequest( - () async => chat.sendMessageStream(Content.text(prompt)), - verifyRequest: (_, request) { - expect(request['safetySettings'], [ - { - 'category': 'HARM_CATEGORY_DANGEROUS_CONTENT', - 'threshold': 'BLOCK_ONLY_HIGH', - 'method': 'PROBABILITY', - }, - ]); - }, - responses: [arbitraryGenerateContentResponse], - ); - await responses.drain(); - }); - - test('forwards generation config', () async { - final (client, model) = createModel('models/$defaultModelName'); - final chat = model.startChat( - generationConfig: GenerationConfig(stopSequences: ['a']), - ); - const prompt = 'Some prompt'; - await client.checkRequest( - () => chat.sendMessage(Content.text(prompt)), - verifyRequest: (_, request) { - expect(request['generationConfig'], { - 'stopSequences': ['a'], - }); - }, - response: arbitraryGenerateContentResponse, - ); - }); - }); -} diff --git a/packages/firebase_vertexai/firebase_vertexai/test/content_test.dart b/packages/firebase_vertexai/firebase_vertexai/test/content_test.dart deleted file mode 100644 index 38c421a38ccd..000000000000 --- a/packages/firebase_vertexai/firebase_vertexai/test/content_test.dart +++ /dev/null @@ -1,226 +0,0 @@ -// Copyright 2024 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import 'dart:convert'; -import 'dart:typed_data'; - -import 'package:firebase_ai/src/content.dart'; -import 'package:flutter_test/flutter_test.dart'; - -// Mock google_ai classes (if needed) -// ... - -void main() { - group('Content tests', () { - test('constructor', () { - final content = Content('user', - [const TextPart('Test'), InlineDataPart('image/png', Uint8List(0))]); - expect(content.role, 'user'); - expect(content.parts[0], isA()); - expect((content.parts[0] as TextPart).text, 'Test'); - expect(content.parts[1], isA()); - expect((content.parts[1] as InlineDataPart).mimeType, 'image/png'); - expect((content.parts[1] as InlineDataPart).bytes.length, 0); - }); - - test('text()', () { - final content = Content('user', [const TextPart('Test')]); - expect(content.role, 'user'); - expect(content.parts[0], isA()); - }); - - test('data()', () { - final content = - Content('user', [InlineDataPart('image/png', Uint8List(0))]); - expect(content.parts[0], isA()); - }); - - test('multi()', () { - final content = Content('user', - [const TextPart('Test'), InlineDataPart('image/png', Uint8List(0))]); - expect(content.parts.length, 2); - expect(content.parts[0], isA()); - expect(content.parts[1], isA()); - }); - - test('toJson', () { - final content = Content('user', - [const TextPart('Test'), InlineDataPart('image/png', Uint8List(0))]); - final json = content.toJson(); - expect(json['role'], 'user'); - expect((json['parts']! as List).length, 2); - expect((json['parts']! as List)[0]['text'], 'Test'); - expect( - (json['parts']! as List)[1]['inlineData']['mimeType'], 'image/png'); - expect((json['parts']! as List)[1]['inlineData']['data'].length, 0); - }); - - test('parseContent', () { - final json = { - 'role': 'user', - 'parts': [ - {'text': 'Hello'}, - ] - }; - final content = parseContent(json); - expect(content.role, 'user'); - expect(content.parts.length, 1); - expect(content.parts[0], isA()); - expect(reason: 'TextPart', (content.parts[0] as TextPart).text, 'Hello'); - }); - }); - - group('Part tests', () { - test('TextPart toJson', () { - const part = TextPart('Test'); - final json = part.toJson(); - expect((json as Map)['text'], 'Test'); - }); - - test('DataPart toJson', () { - final part = InlineDataPart('image/png', Uint8List(0)); - final json = part.toJson(); - expect((json as Map)['inlineData']['mimeType'], 'image/png'); - expect(json['inlineData']['data'], ''); - }); - - test('FunctionCall toJson', () { - const part = FunctionCall( - 'myFunction', - { - 'arguments': [ - {'text': 'Test'} - ], - }, - id: 'myFunctionId'); - final json = part.toJson(); - expect((json as Map)['functionCall']['name'], 'myFunction'); - expect(json['functionCall']['args'].length, 1); - expect(json['functionCall']['args']['arguments'].length, 1); - expect(json['functionCall']['args']['arguments'][0]['text'], 'Test'); - expect(json['functionCall']['id'], 'myFunctionId'); - }); - - test('FunctionResponse toJson', () { - final part = FunctionResponse( - 'myFunction', - { - 'inlineData': { - 'mimeType': 'application/octet-stream', - 'data': Uint8List(0) - } - }, - id: 'myFunctionId'); - final json = part.toJson(); - expect((json as Map)['functionResponse']['name'], 'myFunction'); - expect(json['functionResponse']['response']['inlineData']['mimeType'], - 'application/octet-stream'); - expect(json['functionResponse']['response']['inlineData']['data'], - Uint8List(0)); - expect(json['functionResponse']['id'], 'myFunctionId'); - }); - - test('FileData toJson', () { - const part = FileData('image/png', 'gs://bucket-name/path'); - final json = part.toJson(); - expect((json as Map)['file_data']['mime_type'], 'image/png'); - expect(json['file_data']['file_uri'], 'gs://bucket-name/path'); - }); - }); - - group('parsePart', () { - test('parses TextPart correctly', () { - final json = {'text': 'Hello, world!'}; - final result = parsePart(json); - expect(result, isA()); - expect((result as TextPart).text, 'Hello, world!'); - }); - - test('parses FunctionCall correctly', () { - final json = { - 'functionCall': { - 'name': 'myFunction', - 'args': {'arg1': 1, 'arg2': 'value'}, - 'id': '123', - } - }; - final result = parsePart(json); - expect(result, isA()); - final functionCall = result as FunctionCall; - expect(functionCall.name, 'myFunction'); - expect(functionCall.args, {'arg1': 1, 'arg2': 'value'}); - expect(functionCall.id, '123'); - }); - - test('parses FileData correctly', () { - final json = { - 'file_data': { - 'file_uri': 'file:///path/to/file.txt', - 'mime_type': 'text/plain', - } - }; - final result = parsePart(json); - expect(result, isA()); - final fileData = result as FileData; - expect(fileData.fileUri, 'file:///path/to/file.txt'); - expect(fileData.mimeType, 'text/plain'); - }); - - test('parses InlineDataPart correctly', () { - final json = { - 'inlineData': { - 'mimeType': 'image/png', - 'data': base64Encode([1, 2, 3]) - } - }; - final result = parsePart(json); - expect(result, isA()); - final inlineData = result as InlineDataPart; - expect(inlineData.mimeType, 'image/png'); - expect(inlineData.bytes, const [1, 2, 3]); - }); - - test('returns UnknownPart for functionResponse', () { - final json = { - 'functionResponse': {'name': 'test', 'response': {}} - }; - final result = parsePart(json); - expect(result, isA()); - final unknownPart = result as UnknownPart; - expect(unknownPart.data, json); - }); - - test('returns UnknownPart for invalid JSON', () { - final json = {'invalid': 'data'}; - final result = parsePart(json); - expect(result, isA()); - final unknownPart = result as UnknownPart; - expect(unknownPart.data, json); - }); - - test('returns UnknownPart for null input', () { - final result = parsePart(null); - expect(result, isA()); - final unknownPart = result as UnknownPart; - expect(unknownPart.data, {'unhandled': null}); - }); - - test('returns UnknownPart for empty map', () { - final result = parsePart({}); - expect(result, isA()); - final unknownPart = result as UnknownPart; - expect(unknownPart.data, {'unhandled': {}}); - }); - }); -} diff --git a/packages/firebase_vertexai/firebase_vertexai/test/error_test.dart b/packages/firebase_vertexai/firebase_vertexai/test/error_test.dart deleted file mode 100644 index 0ee57af591b5..000000000000 --- a/packages/firebase_vertexai/firebase_vertexai/test/error_test.dart +++ /dev/null @@ -1,167 +0,0 @@ -// Copyright 2025 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import 'package:firebase_ai/src/error.dart'; -import 'package:firebase_vertexai/firebase_vertexai.dart' - show VertexAIException, VertexAISdkException; -import 'package:flutter_test/flutter_test.dart'; - -void main() { - group('VertexAI Exceptions', () { - test('VertexAIException toString', () { - final exception = VertexAIException('Test message'); - expect(exception.toString(), 'FirebaseAIException: Test message'); - }); - - test('InvalidApiKey toString', () { - final exception = InvalidApiKey('Invalid API key provided.'); - expect(exception.toString(), 'Invalid API key provided.'); - }); - - test('UnsupportedUserLocation message', () { - final exception = UnsupportedUserLocation(); - expect( - exception.message, 'User location is not supported for the API use.'); - }); - - test('ServiceApiNotEnabled message', () { - final exception = ServiceApiNotEnabled('projects/test-project'); - expect( - exception.message, - 'The Vertex AI in Firebase SDK requires the Vertex AI in Firebase API ' - '(`firebasevertexai.googleapis.com`) to be enabled in your Firebase project. Enable this API ' - 'by visiting the Firebase Console at ' - 'https://console.firebase.google.com/project/test-project/genai ' - 'and clicking "Get started". If you enabled this API recently, wait a few minutes for the ' - 'action to propagate to our systems and then retry.'); - }); - - test('QuotaExceeded toString', () { - final exception = QuotaExceeded('Quota for this API has been exceeded.'); - expect(exception.toString(), 'Quota for this API has been exceeded.'); - }); - - test('ServerException toString', () { - final exception = ServerException('Server error occurred.'); - expect(exception.toString(), 'Server error occurred.'); - }); - - test('FirebaseAISdkException toString', () { - final exception = VertexAISdkException('SDK failed to parse response.'); - expect( - exception.toString(), - 'SDK failed to parse response.\n' - 'This indicates a problem with the Firebase AI Logic SDK. ' - 'Try updating to the latest version ' - '(https://pub.dev/packages/firebase_ai/versions), ' - 'or file an issue at ' - 'https://github.com/firebase/flutterfire/issues.'); - }); - - test('ImagenImagesBlockedException toString', () { - final exception = - ImagenImagesBlockedException('All images were blocked.'); - expect(exception.toString(), 'All images were blocked.'); - }); - - test('LiveWebSocketClosedException toString - DEADLINE_EXCEEDED', () { - final exception = LiveWebSocketClosedException( - 'DEADLINE_EXCEEDED: Connection timed out.'); - expect(exception.toString(), - 'The current live session has expired. Please start a new session.'); - }); - - test('LiveWebSocketClosedException toString - RESOURCE_EXHAUSTED', () { - final exception = LiveWebSocketClosedException( - 'RESOURCE_EXHAUSTED: Too many connections.'); - expect( - exception.toString(), - 'You have exceeded the maximum number of concurrent sessions. ' - 'Please close other sessions and try again later.'); - }); - - test('LiveWebSocketClosedException toString - Other', () { - final exception = - LiveWebSocketClosedException('WebSocket connection closed.'); - expect(exception.toString(), 'WebSocket connection closed.'); - }); - - group('parseError', () { - test('parses API_KEY_INVALID', () { - final json = { - 'message': 'Invalid API key', - 'details': [ - {'reason': 'API_KEY_INVALID'} - ] - }; - final exception = parseError(json); - expect(exception, isInstanceOf()); - expect(exception.message, 'Invalid API key'); - }); - - test('parses UNSUPPORTED_USER_LOCATION', () { - final json = { - 'message': 'User location is not supported for the API use.' - }; - final exception = parseError(json); - expect(exception, isInstanceOf()); - }); - - test('parses QUOTA_EXCEEDED', () { - final json = {'message': 'Quota exceeded: Limit reached.'}; - final exception = parseError(json); - expect(exception, isInstanceOf()); - expect(exception.message, 'Quota exceeded: Limit reached.'); - }); - - test('parses SERVICE_API_NOT_ENABLED', () { - final json = { - 'message': 'API not enabled', - 'status': 'PERMISSION_DENIED', - 'details': [ - { - 'metadata': { - 'service': 'firebasevertexai.googleapis.com', - 'consumer': 'projects/my-project-id', - } - } - ] - }; - final exception = parseError(json); - expect(exception, isInstanceOf()); - expect( - (exception as ServiceApiNotEnabled).message, - 'The Vertex AI in Firebase SDK requires the Vertex AI in Firebase API ' - '(`firebasevertexai.googleapis.com`) to be enabled in your Firebase project. Enable this API ' - 'by visiting the Firebase Console at ' - 'https://console.firebase.google.com/project/my-project-id/genai ' - 'and clicking "Get started". If you enabled this API recently, wait a few minutes for the ' - 'action to propagate to our systems and then retry.'); - }); - - test('parses SERVER_ERROR', () { - final json = {'message': 'Internal server error.'}; - final exception = parseError(json); - expect(exception, isInstanceOf()); - expect(exception.message, 'Internal server error.'); - }); - - test('parses UNHANDLED_FORMAT', () { - final json = {'unexpected': 'format'}; - expect(() => parseError(json), - throwsA(isInstanceOf())); - }); - }); - }); -} diff --git a/packages/firebase_vertexai/firebase_vertexai/test/firebase_vertexai_test.dart b/packages/firebase_vertexai/firebase_vertexai/test/firebase_vertexai_test.dart deleted file mode 100644 index a9fa5d671d95..000000000000 --- a/packages/firebase_vertexai/firebase_vertexai/test/firebase_vertexai_test.dart +++ /dev/null @@ -1,81 +0,0 @@ -// Copyright 2024 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import 'package:firebase_app_check/firebase_app_check.dart'; -import 'package:firebase_core/firebase_core.dart'; -import 'package:firebase_vertexai/firebase_vertexai.dart'; -import 'package:flutter_test/flutter_test.dart'; - -import 'mock.dart'; - -void main() { - setupFirebaseVertexAIMocks(); - // ignore: unused_local_variable - late FirebaseApp app; - // ignore: unused_local_variable - late FirebaseAppCheck appCheck; - late FirebaseApp customApp; - late FirebaseAppCheck customAppCheck; - - group('FirebaseVertexAI Tests', () { - late FirebaseApp app; - - setUpAll(() async { - // Initialize Firebase - app = await Firebase.initializeApp(); - customApp = await Firebase.initializeApp( - name: 'custom-app', - options: Firebase.app().options, - ); - appCheck = FirebaseAppCheck.instance; - customAppCheck = FirebaseAppCheck.instanceFor(app: customApp); - }); - - test('Singleton behavior', () { - final instance1 = FirebaseVertexAI.instance; - final instance2 = FirebaseVertexAI.instanceFor(app: app); - expect(identical(instance1, instance2), isTrue); - }); - - test('Instance creation with defaults', () { - final vertexAI = FirebaseVertexAI.instanceFor(app: app); - expect(vertexAI.app, equals(app)); - expect(vertexAI.location, equals('us-central1')); - }); - - test('Instance creation with custom', () { - final vertexAI = FirebaseVertexAI.instanceFor( - app: customApp, - appCheck: customAppCheck, - location: 'custom-location'); - expect(vertexAI.app, equals(customApp)); - expect(vertexAI.appCheck, equals(customAppCheck)); - expect(vertexAI.location, equals('custom-location')); - }); - - test('generativeModel creation', () { - final vertexAI = FirebaseVertexAI.instance; - - final model = vertexAI.generativeModel( - model: 'gemini-pro', - generationConfig: GenerationConfig(maxOutputTokens: 1024), - systemInstruction: Content.system('You are a helpful assistant.'), - ); - - expect(model, isA()); - }); - - // ... other tests (e.g., with different parameters) - }); -} diff --git a/packages/firebase_vertexai/firebase_vertexai/test/google_ai_generative_model_test.dart b/packages/firebase_vertexai/firebase_vertexai/test/google_ai_generative_model_test.dart deleted file mode 100644 index b2e1968cea81..000000000000 --- a/packages/firebase_vertexai/firebase_vertexai/test/google_ai_generative_model_test.dart +++ /dev/null @@ -1,731 +0,0 @@ -// Copyright 2025 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import 'package:firebase_ai/src/base_model.dart'; -import 'package:firebase_core/firebase_core.dart'; -import 'package:firebase_vertexai/firebase_vertexai.dart'; -import 'package:flutter_test/flutter_test.dart'; - -import 'mock.dart'; -import 'utils/matchers.dart'; -import 'utils/stub_client.dart'; - -void main() { - setupFirebaseVertexAIMocks(); - late FirebaseApp app; - setUpAll(() async { - // Initialize Firebase - app = await Firebase.initializeApp(); - }); - group('GenerativeModel', () { - const defaultModelName = 'some-model'; - - (ClientController, GenerativeModel) createModel({ - String modelName = defaultModelName, - List? tools, - ToolConfig? toolConfig, - Content? systemInstruction, - }) { - final client = ClientController(); - final model = createModelWithClient( - useVertexBackend: false, - app: app, - model: modelName, - client: client.client, - tools: tools, - toolConfig: toolConfig, - systemInstruction: systemInstruction, - location: 'us-central1'); - return (client, model); - } - - test('strips leading "models/" from model name', () async { - final (client, model) = createModel( - modelName: 'models/$defaultModelName', - ); - const prompt = 'Some prompt'; - await client.checkRequest( - () => model.generateContent([Content.text(prompt)]), - response: arbitraryGenerateContentResponse, - verifyRequest: (uri, _) { - expect(uri.path, endsWith('/models/some-model:generateContent')); - }, - ); - }); - - test('allows specifying a tuned model', () async { - final (client, model) = createModel( - modelName: 'tunedModels/$defaultModelName', - ); - const prompt = 'Some prompt'; - await client.checkRequest( - () => model.generateContent([Content.text(prompt)]), - response: arbitraryGenerateContentResponse, - verifyRequest: (uri, _) { - expect(uri.path, endsWith('/tunedModels/some-model:generateContent')); - }, - ); - }); - - test('allows specifying an API version', () async { - final (client, model) = createModel( - // requestOptions: RequestOptions(apiVersion: 'override_version'), - ); - const prompt = 'Some prompt'; - await client.checkRequest( - () => model.generateContent([Content.text(prompt)]), - response: arbitraryGenerateContentResponse, - verifyRequest: (uri, _) { - expect(uri.path, startsWith('/override_version/')); - }, - ); - }, skip: 'No support for overriding API version'); - - group('generate unary content', () { - test('can make successful request', () async { - final (client, model) = createModel(); - const prompt = 'Some prompt'; - const result = 'Some response'; - final response = await client.checkRequest( - () => model.generateContent([Content.text(prompt)]), - verifyRequest: (uri, request) { - expect( - uri, - Uri.parse( - 'https://firebasevertexai.googleapis.com/v1beta/' - 'projects/123/' - 'models/some-model:generateContent', - ), - ); - expect(request, { - 'model': 'models/$defaultModelName', - 'contents': [ - { - 'role': 'user', - 'parts': [ - {'text': prompt}, - ], - }, - ], - }); - }, - response: { - 'candidates': [ - { - 'content': { - 'role': 'model', - 'parts': [ - {'text': result}, - ], - }, - }, - ], - }, - ); - expect( - response, - matchesGenerateContentResponse( - GenerateContentResponse([ - Candidate( - Content('model', [const TextPart(result)]), - null, - null, - null, - null, - ), - ], null), - ), - ); - }); - - test('can override safety settings', () async { - final (client, model) = createModel(); - const prompt = 'Some prompt'; - await client.checkRequest( - () => model.generateContent( - [Content.text(prompt)], - safetySettings: [ - SafetySetting( - HarmCategory.dangerousContent, - HarmBlockThreshold.high, - null, - ), - ], - ), - response: arbitraryGenerateContentResponse, - verifyRequest: (_, request) { - expect(request['safetySettings'], [ - { - 'category': 'HARM_CATEGORY_DANGEROUS_CONTENT', - 'threshold': 'BLOCK_ONLY_HIGH', - }, - ]); - }, - ); - }); - - test('can override generation config', () async { - final (client, model) = createModel(); - const prompt = 'Some prompt'; - await client.checkRequest( - () => model.generateContent([ - Content.text(prompt), - ], generationConfig: GenerationConfig(stopSequences: ['a'])), - verifyRequest: (_, request) { - expect(request['generationConfig'], { - 'stopSequences': ['a'], - }); - }, - response: arbitraryGenerateContentResponse, - ); - }); - - test('can pass system instructions', () async { - const instructions = 'Do a good job'; - final (client, model) = createModel( - systemInstruction: Content.system(instructions), - ); - const prompt = 'Some prompt'; - await client.checkRequest( - () => model.generateContent([Content.text(prompt)]), - verifyRequest: (_, request) { - expect(request['systemInstruction'], { - 'role': 'system', - 'parts': [ - {'text': instructions}, - ], - }); - }, - response: arbitraryGenerateContentResponse, - ); - }); - - test('can pass tools and function calling config', () async { - final (client, model) = createModel( - tools: [ - Tool.functionDeclarations([ - FunctionDeclaration( - 'someFunction', - 'Some cool function.', - parameters: { - 'schema1': Schema.string(description: 'Some parameter.'), - }, - ), - ]), - ], - toolConfig: ToolConfig( - functionCallingConfig: FunctionCallingConfig.any( - {'someFunction'}, - ), - ), - ); - const prompt = 'Some prompt'; - await client.checkRequest( - () => model.generateContent([Content.text(prompt)]), - verifyRequest: (_, request) { - expect(request['tools'], [ - { - 'functionDeclarations': [ - { - 'name': 'someFunction', - 'description': 'Some cool function.', - 'parameters': { - 'type': 'OBJECT', - 'properties': { - 'schema1': { - 'type': 'STRING', - 'description': 'Some parameter.' - } - }, - 'required': ['schema1'] - } - }, - ], - }, - ]); - expect(request['toolConfig'], { - 'functionCallingConfig': { - 'mode': 'ANY', - 'allowedFunctionNames': ['someFunction'], - }, - }); - }, - response: arbitraryGenerateContentResponse, - ); - }); - - test('can override tools and function calling config', () async { - final (client, model) = createModel(); - const prompt = 'Some prompt'; - await client.checkRequest( - () => model.generateContent( - [Content.text(prompt)], - tools: [ - Tool.functionDeclarations([ - FunctionDeclaration( - 'someFunction', - 'Some cool function.', - parameters: { - 'schema1': Schema.string(description: 'Some parameter.'), - }, - ), - ]), - ], - toolConfig: ToolConfig( - functionCallingConfig: FunctionCallingConfig.any( - {'someFunction'}, - ), - ), - ), - verifyRequest: (_, request) { - expect(request['tools'], [ - { - 'functionDeclarations': [ - { - 'name': 'someFunction', - 'description': 'Some cool function.', - 'parameters': { - 'type': 'OBJECT', - 'properties': { - 'schema1': { - 'type': 'STRING', - 'description': 'Some parameter.' - } - }, - 'required': ['schema1'] - } - }, - ], - }, - ]); - expect(request['toolConfig'], { - 'functionCallingConfig': { - 'mode': 'ANY', - 'allowedFunctionNames': ['someFunction'], - }, - }); - }, - response: arbitraryGenerateContentResponse, - ); - }); - - test('can enable code execution', () async { - final (client, model) = createModel(tools: [ - // Tool(codeExecution: CodeExecution()), - ]); - const prompt = 'Some prompt'; - await client.checkRequest( - () => model.generateContent([Content.text(prompt)]), - verifyRequest: (_, request) { - expect(request['tools'], [ - {'codeExecution': {}} - ]); - }, - response: arbitraryGenerateContentResponse, - ); - }, skip: 'No support for code execution'); - - test('can override code execution', () async { - final (client, model) = createModel(); - const prompt = 'Some prompt'; - await client.checkRequest( - () => model.generateContent([ - Content.text(prompt) - ], tools: [ - // Tool(codeExecution: CodeExecution()), - ]), - verifyRequest: (_, request) { - expect(request['tools'], [ - {'codeExecution': {}} - ]); - }, - response: arbitraryGenerateContentResponse, - ); - }, skip: 'No support for code execution'); - }); - - group('generate content stream', () { - test('can make successful request', () async { - final (client, model) = createModel(); - const prompt = 'Some prompt'; - final results = {'First response', 'Second Response'}; - final response = await client.checkStreamRequest( - () async => model.generateContentStream([Content.text(prompt)]), - verifyRequest: (uri, request) { - expect( - uri, - Uri.parse( - 'https://firebasevertexai.googleapis.com/v1beta/' - 'projects/123/' - 'models/some-model:streamGenerateContent', - ), - ); - expect(request, { - 'model': 'models/$defaultModelName', - 'contents': [ - { - 'role': 'user', - 'parts': [ - {'text': prompt}, - ], - }, - ], - }); - }, - responses: [ - for (final result in results) - { - 'candidates': [ - { - 'content': { - 'role': 'model', - 'parts': [ - {'text': result}, - ], - }, - }, - ], - }, - ], - ); - expect( - response, - emitsInOrder([ - for (final result in results) - matchesGenerateContentResponse( - GenerateContentResponse([ - Candidate( - Content('model', [TextPart(result)]), - null, - null, - null, - null, - ), - ], null), - ), - ]), - ); - }); - - test('can override safety settings', () async { - final (client, model) = createModel(); - const prompt = 'Some prompt'; - final responses = await client.checkStreamRequest( - () async => model.generateContentStream( - [Content.text(prompt)], - safetySettings: [ - SafetySetting( - HarmCategory.dangerousContent, - HarmBlockThreshold.high, - null, - ), - ], - ), - verifyRequest: (_, request) { - expect(request['safetySettings'], [ - { - 'category': 'HARM_CATEGORY_DANGEROUS_CONTENT', - 'threshold': 'BLOCK_ONLY_HIGH', - }, - ]); - }, - responses: [arbitraryGenerateContentResponse], - ); - await responses.drain(); - }); - - test('can override generation config', () async { - final (client, model) = createModel(); - const prompt = 'Some prompt'; - final responses = await client.checkStreamRequest( - () async => model.generateContentStream([ - Content.text(prompt), - ], generationConfig: GenerationConfig(stopSequences: ['a'])), - verifyRequest: (_, request) { - expect(request['generationConfig'], { - 'stopSequences': ['a'], - }); - }, - responses: [arbitraryGenerateContentResponse], - ); - await responses.drain(); - }); - }); - - group('count tokens', () { - test('can make successful request', () async { - final (client, model) = createModel(); - const prompt = 'Some prompt'; - final response = await client.checkRequest( - () => model.countTokens([Content.text(prompt)]), - verifyRequest: (uri, request) { - expect( - uri, - Uri.parse( - 'https://firebasevertexai.googleapis.com/v1beta/' - 'projects/123/' - 'models/some-model:countTokens', - ), - ); - expect(request, { - 'generateContentRequest': { - 'model': 'models/$defaultModelName', - 'contents': [ - { - 'role': 'user', - 'parts': [ - {'text': prompt}, - ], - }, - ], - } - }); - }, - response: {'totalTokens': 2}, - ); - expect(response, matchesCountTokensResponse(CountTokensResponse(2))); - }); - - test('can override GenerateContentRequest fields', () async { - final (client, model) = createModel(); - const prompt = 'Some prompt'; - await client.checkRequest( - response: {'totalTokens': 100}, - () => model.countTokens( - [Content.text(prompt)], - // safetySettings: [ - // SafetySetting( - // HarmCategory.dangerousContent, - // HarmBlockThreshold.high, - // null, - // ), - // ], - // generationConfig: GenerationConfig(stopSequences: ['a']), - // tools: [ - // Tool(functionDeclarations: [ - // FunctionDeclaration( - // 'someFunction', - // 'Some cool function.', - // Schema(SchemaType.string, description: 'Some parameter.'), - // ), - // ]), - // ], - // toolConfig: ToolConfig( - // functionCallingConfig: FunctionCallingConfig( - // mode: FunctionCallingMode.any, - // allowedFunctionNames: {'someFunction'}, - // ), - // ), - ), - verifyRequest: (_, countTokensRequest) { - expect(countTokensRequest, isNotNull); - final request = countTokensRequest['generateContentRequest']! - as Map; - expect(request['safetySettings'], [ - { - 'category': 'HARM_CATEGORY_DANGEROUS_CONTENT', - 'threshold': 'BLOCK_ONLY_HIGH', - }, - ]); - expect(request['generationConfig'], { - 'stopSequences': ['a'], - }); - expect(request['tools'], [ - { - 'functionDeclarations': [ - { - 'name': 'someFunction', - 'description': 'Some cool function.', - 'parameters': { - 'type': 'STRING', - 'description': 'Some parameter.', - }, - }, - ], - }, - ]); - expect(request['toolConfig'], { - 'functionCallingConfig': { - 'mode': 'ANY', - 'allowedFunctionNames': ['someFunction'], - }, - }); - }, - ); - }, skip: 'Only content argument supported for countTokens'); - }); - - group('embed content', () { - test('can make successful request', () async { - final (client, model) = createModel(); - const prompt = 'Some prompt'; - final response = await client.checkRequest( - () async { - // await model.embedContent(Content.text(prompt)); - }, - verifyRequest: (uri, request) { - expect( - uri, - Uri.parse( - 'https://firebasevertexai.googleapis.com/v1beta/' - 'projects/123/' - 'models/some-model:embedContent', - ), - ); - expect(request, { - 'content': { - 'role': 'user', - 'parts': [ - {'text': prompt}, - ], - }, - }); - }, - response: { - 'embedding': { - 'values': [0.1, 0.2, 0.3], - }, - }, - ); - expect( - response, - // matchesEmbedContentResponse( - // EmbedContentResponse(ContentEmbedding([0.1, 0.2, 0.3])), - // ), - isNotNull, - ); - }); - - test('embed content with reduced output dimensionality', () async { - final (client, model) = createModel(); - const content = 'Some content'; - const outputDimensionality = 1; - final embeddingValues = [0.1]; - - await client.checkRequest(() async { - Content.text(content); - // await model.embedContent( - // Content.text(content), - // outputDimensionality: outputDimensionality, - // ); - }, verifyRequest: (_, request) { - expect(request, - containsPair('outputDimensionality', outputDimensionality)); - }, response: { - 'embedding': {'values': embeddingValues}, - }); - }); - }, skip: 'No support for embedding content'); - - group('batch embed contents', () { - test('can make successful request', () async { - final (client, model) = createModel(); - const prompt1 = 'Some prompt'; - const prompt2 = 'Another prompt'; - final embedding1 = [0.1, 0.2, 0.3]; - final embedding2 = [0.4, 0.5, 1.6]; - final response = await client.checkRequest( - () async { - // await model.batchEmbedContents([ - // EmbedContentRequest(Content.text(prompt1)), - // EmbedContentRequest(Content.text(prompt2)), - // ]); - }, - verifyRequest: (uri, request) { - expect( - uri, - Uri.parse( - 'https://firebasevertexai.googleapis.com/v1beta/' - 'projects/123/' - 'models/some-model:batchEmbedContents', - ), - ); - expect(request, { - 'requests': [ - { - 'content': { - 'role': 'user', - 'parts': [ - {'text': prompt1}, - ], - }, - 'model': 'models/$defaultModelName', - }, - { - 'content': { - 'role': 'user', - 'parts': [ - {'text': prompt2}, - ], - }, - 'model': 'models/$defaultModelName', - }, - ], - }); - }, - response: { - 'embeddings': [ - {'values': embedding1}, - {'values': embedding2}, - ], - }, - ); - expect( - response, - isNotNull, - // matchesBatchEmbedContentsResponse( - // BatchEmbedContentsResponse([ - // ContentEmbedding(embedding1), - // ContentEmbedding(embedding2), - // ]), - // ), - ); - }); - - test('batch embed contents with reduced output dimensionality', () async { - final (client, model) = createModel(); - const content1 = 'Some content 1'; - const content2 = 'Some content 2'; - const outputDimensionality = 1; - final embeddingValues1 = [0.1]; - final embeddingValues2 = [0.4]; - - await client.checkRequest(() async { - Content.text(content1); - Content.text(content2); - // await model.batchEmbedContents([ - // EmbedContentRequest( - // Content.text(content1), - // outputDimensionality: outputDimensionality, - // ), - // EmbedContentRequest( - // Content.text(content2), - // outputDimensionality: outputDimensionality, - // ), - // ]); - }, verifyRequest: (_, request) { - expect(request['requests'], [ - containsPair('outputDimensionality', outputDimensionality), - containsPair('outputDimensionality', outputDimensionality), - ]); - }, response: { - 'embeddings': [ - {'values': embeddingValues1}, - {'values': embeddingValues2}, - ], - }); - }); - }, skip: 'No support for embed content'); - }); -} diff --git a/packages/firebase_vertexai/firebase_vertexai/test/google_ai_response_parsing_test.dart b/packages/firebase_vertexai/firebase_vertexai/test/google_ai_response_parsing_test.dart deleted file mode 100644 index ba6277444ea0..000000000000 --- a/packages/firebase_vertexai/firebase_vertexai/test/google_ai_response_parsing_test.dart +++ /dev/null @@ -1,770 +0,0 @@ -// Copyright 2025 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import 'dart:convert'; - -import 'package:firebase_ai/src/developer/api.dart'; -import 'package:firebase_vertexai/firebase_vertexai.dart'; -import 'package:flutter_test/flutter_test.dart'; - -import 'utils/matchers.dart'; - -void main() { - group('throws errors for invalid GenerateContentResponse', () { - test('with empty content', () { - const response = ''' -{ - "candidates": [ - { - "content": {}, - "index": 0 - } - ], - "promptFeedback": { - "safetyRatings": [ - { - "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HATE_SPEECH", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HARASSMENT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_DANGEROUS_CONTENT", - "probability": "NEGLIGIBLE" - } - ] - } -} -'''; - final decoded = jsonDecode(response) as Object; - expect( - () => DeveloperSerialization().parseGenerateContentResponse(decoded), - throwsA( - isA().having( - (e) => e.message, - 'message', - startsWith('Unhandled format for Content:'), - ), - ), - ); - }); - - test('with a blocked prompt', () { - const response = ''' -{ - "promptFeedback": { - "blockReason": "SAFETY", - "safetyRatings": [ - { - "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HATE_SPEECH", - "probability": "HIGH" - }, - { - "category": "HARM_CATEGORY_HARASSMENT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_DANGEROUS_CONTENT", - "probability": "NEGLIGIBLE" - } - ] - } -} -'''; - final decoded = jsonDecode(response) as Object; - final generateContentResponse = - DeveloperSerialization().parseGenerateContentResponse(decoded); - expect( - generateContentResponse, - matchesGenerateContentResponse( - GenerateContentResponse( - [], - PromptFeedback(BlockReason.safety, null, [ - SafetyRating( - HarmCategory.sexuallyExplicit, - HarmProbability.negligible, - ), - SafetyRating(HarmCategory.hateSpeech, HarmProbability.high), - SafetyRating(HarmCategory.harassment, HarmProbability.negligible), - SafetyRating( - HarmCategory.dangerousContent, - HarmProbability.negligible, - ), - ]), - ), - ), - ); - expect( - () => generateContentResponse.text, - throwsA( - isA().having( - (e) => e.message, - 'message', - startsWith('Response was blocked due to safety'), - ), - ), - ); - }); - }); - - group('parses successful GenerateContentResponse', () { - test('with a basic reply', () async { - const response = ''' -{ - "candidates": [ - { - "content": { - "parts": [ - { - "text": "Mountain View, California, United States" - } - ], - "role": "model" - }, - "finishReason": "STOP", - "index": 0, - "safetyRatings": [ - { - "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HATE_SPEECH", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HARASSMENT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_DANGEROUS_CONTENT", - "probability": "NEGLIGIBLE" - } - ] - } - ], - "promptFeedback": { - "safetyRatings": [ - { - "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HATE_SPEECH", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HARASSMENT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_DANGEROUS_CONTENT", - "probability": "NEGLIGIBLE" - } - ] - } -} -'''; - final decoded = jsonDecode(response) as Object; - final generateContentResponse = - DeveloperSerialization().parseGenerateContentResponse(decoded); - expect( - generateContentResponse, - matchesGenerateContentResponse( - GenerateContentResponse( - [ - Candidate( - Content.model([ - const TextPart('Mountain View, California, United States'), - ]), - [ - SafetyRating( - HarmCategory.sexuallyExplicit, - HarmProbability.negligible, - ), - SafetyRating( - HarmCategory.hateSpeech, - HarmProbability.negligible, - ), - SafetyRating( - HarmCategory.harassment, - HarmProbability.negligible, - ), - SafetyRating( - HarmCategory.dangerousContent, - HarmProbability.negligible, - ), - ], - null, - FinishReason.stop, - null, - ), - ], - PromptFeedback(null, null, [ - SafetyRating( - HarmCategory.sexuallyExplicit, - HarmProbability.negligible, - ), - SafetyRating(HarmCategory.hateSpeech, HarmProbability.negligible), - SafetyRating(HarmCategory.harassment, HarmProbability.negligible), - SafetyRating( - HarmCategory.dangerousContent, - HarmProbability.negligible, - ), - ]), - ), - ), - ); - }); - - test('with a citation', () async { - const response = ''' -{ - "candidates": [ - { - "content": { - "parts": [ - { - "text": "placeholder" - } - ], - "role": "model" - }, - "finishReason": "STOP", - "index": 0, - "safetyRatings": [ - { - "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HATE_SPEECH", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HARASSMENT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_DANGEROUS_CONTENT", - "probability": "NEGLIGIBLE" - } - ], - "citationMetadata": { - "citationSources": [ - { - "startIndex": 574, - "endIndex": 705, - "uri": "https://example.com/", - "license": "" - }, - { - "startIndex": 899, - "endIndex": 1026, - "uri": "https://example.com/", - "license": "" - }, - { - "startIndex": 899, - "endIndex": 1026 - }, - { - "uri": "https://example.com/", - "license": "" - }, - {} - ] - } - } - ], - "promptFeedback": { - "safetyRatings": [ - { - "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HATE_SPEECH", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HARASSMENT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_DANGEROUS_CONTENT", - "probability": "NEGLIGIBLE" - } - ] - } -} -'''; - final decoded = jsonDecode(response) as Object; - final generateContentResponse = - DeveloperSerialization().parseGenerateContentResponse(decoded); - expect( - generateContentResponse, - matchesGenerateContentResponse( - GenerateContentResponse( - [ - Candidate( - Content.model([const TextPart('placeholder')]), - [ - SafetyRating( - HarmCategory.sexuallyExplicit, - HarmProbability.negligible, - ), - SafetyRating( - HarmCategory.hateSpeech, - HarmProbability.negligible, - ), - SafetyRating( - HarmCategory.harassment, - HarmProbability.negligible, - ), - SafetyRating( - HarmCategory.dangerousContent, - HarmProbability.negligible, - ), - ], - CitationMetadata([ - Citation(574, 705, Uri.https('example.com'), ''), - Citation(899, 1026, Uri.https('example.com'), ''), - ]), - FinishReason.stop, - null, - ), - ], - PromptFeedback(null, null, [ - SafetyRating( - HarmCategory.sexuallyExplicit, - HarmProbability.negligible, - ), - SafetyRating(HarmCategory.hateSpeech, HarmProbability.negligible), - SafetyRating(HarmCategory.harassment, HarmProbability.negligible), - SafetyRating( - HarmCategory.dangerousContent, - HarmProbability.negligible, - ), - ]), - ), - ), - ); - }); - - test('with a vertex formatted citation', () async { - const response = ''' -{ - "candidates": [ - { - "content": { - "parts": [ - { - "text": "placeholder" - } - ], - "role": "model" - }, - "finishReason": "STOP", - "index": 0, - "safetyRatings": [ - { - "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HATE_SPEECH", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HARASSMENT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_DANGEROUS_CONTENT", - "probability": "NEGLIGIBLE" - } - ], - "citationMetadata": { - "citations": [ - { - "startIndex": 574, - "endIndex": 705, - "uri": "https://example.com/", - "license": "" - }, - { - "startIndex": 899, - "endIndex": 1026, - "uri": "https://example.com/", - "license": "" - }, - { - "startIndex": 899, - "endIndex": 1026 - }, - { - "uri": "https://example.com/", - "license": "" - }, - {} - ] - } - } - ], - "promptFeedback": { - "safetyRatings": [ - { - "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HATE_SPEECH", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HARASSMENT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_DANGEROUS_CONTENT", - "probability": "NEGLIGIBLE" - } - ] - } -} -'''; - final decoded = jsonDecode(response) as Object; - final generateContentResponse = - DeveloperSerialization().parseGenerateContentResponse(decoded); - expect( - generateContentResponse, - matchesGenerateContentResponse( - GenerateContentResponse( - [ - Candidate( - Content.model([const TextPart('placeholder')]), - [ - SafetyRating( - HarmCategory.sexuallyExplicit, - HarmProbability.negligible, - ), - SafetyRating( - HarmCategory.hateSpeech, - HarmProbability.negligible, - ), - SafetyRating( - HarmCategory.harassment, - HarmProbability.negligible, - ), - SafetyRating( - HarmCategory.dangerousContent, - HarmProbability.negligible, - ), - ], - CitationMetadata([ - Citation(574, 705, Uri.https('example.com'), ''), - Citation(899, 1026, Uri.https('example.com'), ''), - ]), - FinishReason.stop, - null, - ), - ], - PromptFeedback(null, null, [ - SafetyRating( - HarmCategory.sexuallyExplicit, - HarmProbability.negligible, - ), - SafetyRating(HarmCategory.hateSpeech, HarmProbability.negligible), - SafetyRating(HarmCategory.harassment, HarmProbability.negligible), - SafetyRating( - HarmCategory.dangerousContent, - HarmProbability.negligible, - ), - ]), - ), - ), - ); - }); - - test('with code execution', () async { - const response = ''' -{ - "candidates": [ - { - "content": { - "parts": [ - { - "executableCode": { - "language": "PYTHON", - "code": "print('hello world')" - } - }, - { - "codeExecutionResult": { - "outcome": "OUTCOME_OK", - "output": "hello world" - } - }, - { - "text": "hello world" - } - ], - "role": "model" - }, - "finishReason": "STOP", - "index": 0 - } - ] -} -'''; - final decoded = jsonDecode(response) as Object; - final generateContentResponse = - DeveloperSerialization().parseGenerateContentResponse(decoded); - expect( - generateContentResponse, - matchesGenerateContentResponse( - GenerateContentResponse( - [ - Candidate( - Content.model([ - // ExecutableCode(Language.python, 'print(\'hello world\')'), - // CodeExecutionResult(Outcome.ok, 'hello world'), - const TextPart('hello world') - ]), - [], - null, - FinishReason.stop, - null, - ), - ], - null, - ), - ), - ); - }, skip: 'Code Execution Unsupported'); - - test('allows missing content', () async { - const response = ''' -{ - "candidates": [ - { - "finishReason": "SAFETY", - "index": 0, - "safetyRatings": [ - { - "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HATE_SPEECH", - "probability": "LOW" - }, - { - "category": "HARM_CATEGORY_HARASSMENT", - "probability": "MEDIUM" - }, - { - "category": "HARM_CATEGORY_DANGEROUS_CONTENT", - "probability": "NEGLIGIBLE" - } - ] - } - ] -} -'''; - final decoded = jsonDecode(response) as Object; - final generateContentResponse = - DeveloperSerialization().parseGenerateContentResponse(decoded); - expect( - generateContentResponse, - matchesGenerateContentResponse( - GenerateContentResponse([ - Candidate( - Content(null, []), - [ - SafetyRating( - HarmCategory.sexuallyExplicit, - HarmProbability.negligible, - ), - SafetyRating( - HarmCategory.hateSpeech, HarmProbability.negligible), - SafetyRating( - HarmCategory.harassment, HarmProbability.negligible), - SafetyRating( - HarmCategory.dangerousContent, - HarmProbability.negligible, - ), - ], - CitationMetadata([]), - FinishReason.safety, - null), - ], null), - ), - ); - }); - - test('text getter joins content', () async { - const response = ''' -{ - "candidates": [ - { - "content": { - "parts": [ - { - "text": "Initial text" - }, - { - "functionCall": {"name": "someFunction", "args": {}} - }, - { - "text": " And more text" - } - ], - "role": "model" - }, - "finishReason": "STOP", - "index": 0 - } - ] -} -'''; - final decoded = jsonDecode(response) as Object; - final generateContentResponse = - DeveloperSerialization().parseGenerateContentResponse(decoded); - expect(generateContentResponse.text, 'Initial text And more text'); - expect(generateContentResponse.candidates.single.text, - 'Initial text And more text'); - }); - }); - - group('parses and throws error responses', () { - test('for invalid API key', () async { - const response = ''' -{ - "error": { - "code": 400, - "message": "API key not valid. Please pass a valid API key.", - "status": "INVALID_ARGUMENT", - "details": [ - { - "@type": "type.googleapis.com/google.rpc.ErrorInfo", - "reason": "API_KEY_INVALID", - "domain": "googleapis.com", - "metadata": { - "service": "generativelanguage.googleapis.com" - } - }, - { - "@type": "type.googleapis.com/google.rpc.DebugInfo", - "detail": "Invalid API key: AIzv00G7VmUCUeC-5OglO3hcXM" - } - ] - } -} -'''; - final decoded = jsonDecode(response) as Object; - final expectedThrow = throwsA( - isA().having( - (e) => e.message, - 'message', - 'API key not valid. Please pass a valid API key.', - ), - ); - expect( - () => DeveloperSerialization().parseGenerateContentResponse(decoded), - expectedThrow); - expect(() => DeveloperSerialization().parseCountTokensResponse(decoded), - expectedThrow); - // expect(() => parseEmbedContentResponse(decoded), expectedThrow); - }); - - test('for unsupported user location', () async { - const response = r''' -{ - "error": { - "code": 400, - "message": "User location is not supported for the API use.", - "status": "FAILED_PRECONDITION", - "details": [ - { - "@type": "type.googleapis.com/google.rpc.DebugInfo", - "detail": "[ORIGINAL ERROR] generic::failed_precondition: User location is not supported for the API use. [google.rpc.error_details_ext] { message: \"User location is not supported for the API use.\" }" - } - ] - } -} -'''; - final decoded = jsonDecode(response) as Object; - final expectedThrow = throwsA( - isA().having( - (e) => e.message, - 'message', - 'User location is not supported for the API use.', - ), - ); - expect( - () => DeveloperSerialization().parseGenerateContentResponse(decoded), - expectedThrow); - expect(() => DeveloperSerialization().parseCountTokensResponse(decoded), - expectedThrow); - // expect(() => parseEmbedContentResponse(decoded), expectedThrow); - }); - - test('for general server errors', () async { - const response = r''' -{ - "error": { - "code": 404, - "message": "models/unknown is not found for API version v1, or is not supported for GenerateContent. Call ListModels to see the list of available models and their supported methods.", - "status": "NOT_FOUND", - "details": [ - { - "@type": "type.googleapis.com/google.rpc.DebugInfo", - "detail": "[ORIGINAL ERROR] generic::not_found: models/unknown is not found for API version v1, or is not supported for GenerateContent. Call ListModels to see the list of available models and their supported methods. [google.rpc.error_details_ext] { message: \"models/unknown is not found for API version v1, or is not supported for GenerateContent. Call ListModels to see the list of available models and their supported methods.\" }" - } - ] - } -} -'''; - final decoded = jsonDecode(response) as Object; - final expectedThrow = throwsA( - isA().having( - (e) => e.message, - 'message', - startsWith( - 'models/unknown is not found for API version v1, ' - 'or is not supported for GenerateContent.', - ), - ), - ); - expect( - () => DeveloperSerialization().parseGenerateContentResponse(decoded), - expectedThrow); - expect(() => DeveloperSerialization().parseCountTokensResponse(decoded), - expectedThrow); - // expect(() => parseEmbedContentResponse(decoded), expectedThrow); - }); - }); -} diff --git a/packages/firebase_vertexai/firebase_vertexai/test/imagen_test.dart b/packages/firebase_vertexai/firebase_vertexai/test/imagen_test.dart deleted file mode 100644 index d1544818126d..000000000000 --- a/packages/firebase_vertexai/firebase_vertexai/test/imagen_test.dart +++ /dev/null @@ -1,241 +0,0 @@ -// Copyright 2025 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import 'dart:convert'; -import 'dart:typed_data'; - -import 'package:firebase_ai/src/error.dart'; -import 'package:firebase_ai/src/imagen/imagen_content.dart'; -import 'package:flutter_test/flutter_test.dart'; - -void main() { - group('ImagenInlineImage', () { - test('fromJson with valid base64', () { - final json = { - 'mimeType': 'image/png', - 'bytesBase64Encoded': - 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII=' - }; - final image = ImagenInlineImage.fromJson(json); - expect(image.mimeType, 'image/png'); - expect(image.bytesBase64Encoded, isA()); - expect(image.bytesBase64Encoded, isNotEmpty); - }); - - test('fromJson with invalid base64', () { - final json = { - 'mimeType': 'image/png', - 'bytesBase64Encoded': 'invalid_base64_string' - }; - // Expect that the constructor throws an exception. - expect(() => ImagenInlineImage.fromJson(json), throwsFormatException); - }); - - test('toJson', () { - final image = ImagenInlineImage( - mimeType: 'image/png', - bytesBase64Encoded: Uint8List.fromList(utf8.encode('Hello, world!')), - ); - final json = image.toJson(); - expect(json, { - 'mimeType': 'image/png', - 'bytesBase64Encoded': 'SGVsbG8sIHdvcmxkIQ==', - }); - }); - }); - - group('ImagenGCSImage', () { - test('fromJson', () { - final json = { - 'mimeType': 'image/jpeg', - 'gcsUri': - 'gs://test-project-id-1234.firebasestorage.app/images/1234567890123/sample_0.jpg' - }; - final image = ImagenGCSImage.fromJson(json); - expect(image.mimeType, 'image/jpeg'); - expect(image.gcsUri, - 'gs://test-project-id-1234.firebasestorage.app/images/1234567890123/sample_0.jpg'); - }); - - test('toJson', () { - final image = ImagenGCSImage( - mimeType: 'image/jpeg', - gcsUri: - 'gs://test-project-id-1234.firebasestorage.app/images/1234567890123/sample_0.jpg', - ); - final json = image.toJson(); - expect(json, { - 'mimeType': 'image/jpeg', - 'gcsUri': - 'gs://test-project-id-1234.firebasestorage.app/images/1234567890123/sample_0.jpg', - }); - }); - }); - - group('ImagenGenerationResponse', () { - test('fromJson with gcsUri', () { - final json = { - 'predictions': [ - { - 'mimeType': 'image/jpeg', - 'gcsUri': - 'gs://test-project-id-1234.firebasestorage.app/images/1234567890123/sample_0.jpg' - }, - { - 'mimeType': 'image/jpeg', - 'gcsUri': - 'gs://test-project-id-1234.firebasestorage.app/images/1234567890123/sample_1.jpg' - }, - { - 'mimeType': 'image/jpeg', - 'gcsUri': - 'gs://test-project-id-1234.firebasestorage.app/images/1234567890123/sample_2.jpg' - }, - { - 'mimeType': 'image/jpeg', - 'gcsUri': - 'gs://test-project-id-1234.firebasestorage.app/images/1234567890123/sample_3.jpg' - } - ] - }; - final response = ImagenGenerationResponse.fromJson(json); - expect(response.images, isA>()); - expect(response.images.length, 4); - expect(response.filteredReason, isNull); - }); - - test('fromJson with bytesBase64Encoded', () { - final json = { - 'predictions': [ - { - 'mimeType': 'image/jpeg', - 'bytesBase64Encoded': 'SGVsbG8sIHdvcmxkIQ==' - }, - { - 'mimeType': 'image/jpeg', - 'bytesBase64Encoded': 'SGVsbG8sIHdvcmxkIQ==' - }, - { - 'mimeType': 'image/jpeg', - 'bytesBase64Encoded': 'SGVsbG8sIHdvcmxkIQ==' - }, - { - 'mimeType': 'image/jpeg', - 'bytesBase64Encoded': 'SGVsbG8sIHdvcmxkIQ==' - } - ] - }; - final response = - ImagenGenerationResponse.fromJson(json); - expect(response.images, isA>()); - expect(response.images.length, 4); - expect(response.filteredReason, isNull); - }); - - test('fromJson with bytesBase64Encoded and raiFilteredReason', () { - final json = { - 'predictions': [ - { - 'mimeType': 'image/png', - 'bytesBase64Encoded': - 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII=' - }, - { - 'mimeType': 'image/png', - 'bytesBase64Encoded': - 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII=' - }, - { - 'raiFilteredReason': - 'Your current safety filter threshold filtered out 2 generated images. You will not be charged for blocked images. Try rephrasing the prompt. If you think this was an error, send feedback.' - } - ] - }; - final response = - ImagenGenerationResponse.fromJson(json); - expect(response.images, isA>()); - expect(response.images.length, 2); - expect(response.filteredReason, - 'Your current safety filter threshold filtered out 2 generated images. You will not be charged for blocked images. Try rephrasing the prompt. If you think this was an error, send feedback.'); - }); - - test('fromJson with only raiFilteredReason', () { - final json = { - 'predictions': [ - { - 'raiFilteredReason': - "Unable to show generated images. All images were filtered out because they violated Vertex AI's usage guidelines. You will not be charged for blocked images. Try rephrasing the prompt. If you think this was an error, send feedback. Support codes: 39322892, 29310472" - } - ] - }; - // Expect that the constructor throws an exception. - expect(() => ImagenGenerationResponse.fromJson(json), - throwsA(isA())); - }); - - test('fromJson with empty predictions', () { - final json = {'predictions': {}}; - // Expect that the constructor throws an exception. - expect(() => ImagenGenerationResponse.fromJson(json), - throwsA(isA())); - }); - - test('fromJson with unsupported type', () { - final json = { - 'predictions': [ - { - 'mimeType': 'image/jpeg', - 'gcsUri': - 'gs://test-project-id-1234.firebasestorage.app/images/1234567890123/sample_0.jpg' - }, - ] - }; - // Expect that the constructor throws an exception. - expect(() => ImagenGenerationResponse.fromJson(json), - throwsA(isA())); - }); - }); - - group('parseImagenGenerationResponse', () { - test('with valid response', () { - final json = { - 'predictions': [ - { - 'mimeType': 'image/jpeg', - 'gcsUri': - 'gs://test-project-id-1234.firebasestorage.app/images/1234567890123/sample_0.jpg' - }, - ] - }; - final response = parseImagenGenerationResponse(json); - expect(response.images, isA>()); - expect(response.images.length, 1); - expect(response.filteredReason, isNull); - }); - - test('with error', () { - final json = { - 'error': { - 'code': 400, - 'message': - "Image generation failed with the following error: The prompt could not be submitted. This prompt contains sensitive words that violate Google's Responsible AI practices. Try rephrasing the prompt. If you think this was an error, send feedback. Support codes: 42876398", - 'status': 'INVALID_ARGUMENT' - } - }; - // Expect that the function throws an exception. - expect(() => parseImagenGenerationResponse(json), - throwsA(isA())); - }); - }); -} diff --git a/packages/firebase_vertexai/firebase_vertexai/test/live_test.dart b/packages/firebase_vertexai/firebase_vertexai/test/live_test.dart deleted file mode 100644 index 526cb19a77de..000000000000 --- a/packages/firebase_vertexai/firebase_vertexai/test/live_test.dart +++ /dev/null @@ -1,241 +0,0 @@ -// Copyright 2025 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -import 'dart:typed_data'; - -import 'package:firebase_ai/src/api.dart'; -import 'package:firebase_ai/src/content.dart'; -import 'package:firebase_ai/src/live_api.dart'; -import 'package:firebase_vertexai/firebase_vertexai.dart' - show VertexAISdkException; -import 'package:flutter_test/flutter_test.dart'; - -void main() { - group('LiveAPI Tests', () { - test('SpeechConfig toJson() returns correct JSON', () { - final speechConfigWithVoice = SpeechConfig(voiceName: 'Aoede'); - expect(speechConfigWithVoice.toJson(), { - 'voice_config': { - 'prebuilt_voice_config': {'voice_name': 'Aoede'} - } - }); - - final speechConfigWithoutVoice = SpeechConfig(); - expect(speechConfigWithoutVoice.toJson(), {}); - }); - - test('ResponseModalities enum toJson() returns correct value', () { - expect(ResponseModalities.text.toJson(), 'TEXT'); - expect(ResponseModalities.image.toJson(), 'IMAGE'); - expect(ResponseModalities.audio.toJson(), 'AUDIO'); - }); - - test('LiveGenerationConfig toJson() returns correct JSON', () { - final liveGenerationConfig = LiveGenerationConfig( - speechConfig: SpeechConfig(voiceName: 'Charon'), - responseModalities: [ResponseModalities.text, ResponseModalities.audio], - maxOutputTokens: 100, - temperature: 0.8, - topP: 0.95, - topK: 40, - ); - - expect(liveGenerationConfig.toJson(), { - 'maxOutputTokens': 100, - 'temperature': 0.8, - 'topP': 0.95, - 'topK': 40, - 'speechConfig': { - 'voice_config': { - 'prebuilt_voice_config': {'voice_name': 'Charon'} - } - }, - 'responseModalities': ['TEXT', 'AUDIO'], - }); - - final liveGenerationConfigWithoutOptionals = LiveGenerationConfig(); - expect(liveGenerationConfigWithoutOptionals.toJson(), {}); - }); - - test('LiveServerContent constructor and properties', () { - final content = Content.text('Hello, world!'); - final message = LiveServerContent( - modelTurn: content, - turnComplete: true, - interrupted: false, - ); - expect(message.modelTurn, content); - expect(message.turnComplete, true); - expect(message.interrupted, false); - - final message2 = LiveServerContent(); - expect(message2.modelTurn, null); - expect(message2.turnComplete, null); - expect(message2.interrupted, null); - }); - - test('LiveServerToolCall constructor and properties', () { - const functionCall = FunctionCall('test', {}); - final message = LiveServerToolCall(functionCalls: [functionCall]); - expect(message.functionCalls, [functionCall]); - - final message2 = LiveServerToolCall(); - expect(message2.functionCalls, null); - }); - - test('LiveServerToolCallCancellation constructor and properties', () { - final message = LiveServerToolCallCancellation(functionIds: ['1', '2']); - expect(message.functionIds, ['1', '2']); - - final message2 = LiveServerToolCallCancellation(); - expect(message2.functionIds, null); - }); - - test('LiveClientRealtimeInput toJson() returns correct JSON', () { - final part = InlineDataPart('audio/pcm', Uint8List.fromList([1, 2, 3])); - final message = LiveClientRealtimeInput(mediaChunks: [part]); - expect(message.toJson(), { - 'realtime_input': { - 'media_chunks': [ - { - 'mimeType': 'audio/pcm', - 'data': 'AQID', - } - ], - }, - }); - - final message2 = LiveClientRealtimeInput(); - expect(message2.toJson(), { - 'realtime_input': { - 'media_chunks': null, - }, - }); - }); - - test('LiveClientContent toJson() returns correct JSON', () { - final content = Content.text('some test input'); - final message = LiveClientContent(turns: [content], turnComplete: true); - expect(message.toJson(), { - 'client_content': { - 'turns': [ - { - 'role': 'user', - 'parts': [ - {'text': 'some test input'} - ] - } - ], - 'turn_complete': true, - } - }); - - final message2 = LiveClientContent(); - expect(message2.toJson(), { - 'client_content': { - 'turns': null, - 'turn_complete': null, - } - }); - }); - - test('LiveClientToolResponse toJson() returns correct JSON', () { - const response = FunctionResponse('test', {}); - final message = LiveClientToolResponse(functionResponses: [response]); - expect(message.toJson(), { - 'toolResponse': { - 'functionResponses': [ - {'name': 'test', 'response': {}} - ] - } - }); - - final message2 = LiveClientToolResponse(); - expect(message2.toJson(), { - 'toolResponse': {'functionResponses': null} - }); - }); - - test('parseServerMessage parses serverContent message correctly', () { - final jsonObject = { - 'serverContent': { - 'modelTurn': { - 'parts': [ - {'text': 'Hello, world!'} - ] - }, - 'turnComplete': true, - } - }; - final response = parseServerResponse(jsonObject); - expect(response.message, isA()); - final contentMessage = response.message as LiveServerContent; - expect(contentMessage.turnComplete, true); - expect(contentMessage.modelTurn, isA()); - }); - - test('parseServerMessage parses toolCall message correctly', () { - final jsonObject = { - 'toolCall': { - 'functionCalls': [ - { - 'name': 'test1', - 'args': {'foo1': 'bar1'} - }, - { - 'name': 'test2', - 'args': {'foo2': 'bar2'} - } - ] - } - }; - final response = parseServerResponse(jsonObject); - expect(response.message, isA()); - final toolCallMessage = response.message as LiveServerToolCall; - expect(toolCallMessage.functionCalls, isA>()); - }); - - test('parseServerMessage parses toolCallCancellation message correctly', - () { - final jsonObject = { - 'toolCallCancellation': { - 'ids': ['1', '2'] - } - }; - final response = parseServerResponse(jsonObject); - expect(response.message, isA()); - final cancellationMessage = - response.message as LiveServerToolCallCancellation; - expect(cancellationMessage.functionIds, ['1', '2']); - }); - - test('parseServerMessage parses setupComplete message correctly', () { - final jsonObject = {'setupComplete': {}}; - final response = parseServerResponse(jsonObject); - expect(response.message, isA()); - }); - - test('parseServerMessage throws VertexAIException for error message', () { - final jsonObject = {'error': {}}; - expect(() => parseServerResponse(jsonObject), - throwsA(isA())); - }); - - test('parseServerMessage throws VertexAISdkException for unhandled format', - () { - final jsonObject = {'unknown': {}}; - expect(() => parseServerResponse(jsonObject), - throwsA(isA())); - }); - }); -} diff --git a/packages/firebase_vertexai/firebase_vertexai/test/mock.dart b/packages/firebase_vertexai/firebase_vertexai/test/mock.dart deleted file mode 100644 index d6be1c501cea..000000000000 --- a/packages/firebase_vertexai/firebase_vertexai/test/mock.dart +++ /dev/null @@ -1,73 +0,0 @@ -// Copyright 2024 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import 'package:firebase_core_platform_interface/firebase_core_platform_interface.dart'; -import 'package:firebase_core_platform_interface/test.dart'; -import 'package:flutter_test/flutter_test.dart'; -import 'package:mockito/mockito.dart'; -import 'package:plugin_platform_interface/plugin_platform_interface.dart'; - -class MockFirebaseAppVertexAI implements TestFirebaseCoreHostApi { - @override - Future initializeApp( - String appName, - CoreFirebaseOptions initializeAppRequest, - ) async { - return CoreInitializeResponse( - name: appName, - options: initializeAppRequest, - pluginConstants: {}, - ); - } - - @override - Future> initializeCore() async { - return [ - CoreInitializeResponse( - name: defaultFirebaseAppName, - options: CoreFirebaseOptions( - apiKey: '123', - projectId: '123', - appId: '123', - messagingSenderId: '123', - ), - pluginConstants: {}, - ) - ]; - } - - @override - Future optionsFromResource() async { - return CoreFirebaseOptions( - apiKey: '123', - projectId: '123', - appId: '123', - messagingSenderId: '123', - ); - } -} - -void setupFirebaseVertexAIMocks() { - TestWidgetsFlutterBinding.ensureInitialized(); - - TestFirebaseCoreHostApi.setUp(MockFirebaseAppVertexAI()); -} - -// FirebaseVertexAIPlatform Mock -class MockFirebaseVertexAI extends Mock - with - // ignore: prefer_mixin, plugin_platform_interface needs to migrate to use `mixin` - MockPlatformInterfaceMixin { - MockFirebaseVertexAI(); -} diff --git a/packages/firebase_vertexai/firebase_vertexai/test/model_test.dart b/packages/firebase_vertexai/firebase_vertexai/test/model_test.dart deleted file mode 100644 index 1079e00cbbed..000000000000 --- a/packages/firebase_vertexai/firebase_vertexai/test/model_test.dart +++ /dev/null @@ -1,464 +0,0 @@ -// Copyright 2024 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import 'package:firebase_ai/src/base_model.dart'; -import 'package:firebase_core/firebase_core.dart'; -import 'package:firebase_vertexai/firebase_vertexai.dart'; -import 'package:flutter_test/flutter_test.dart'; - -import 'mock.dart'; -import 'utils/matchers.dart'; -import 'utils/stub_client.dart'; - -void main() { - setupFirebaseVertexAIMocks(); - // ignore: unused_local_variable - late FirebaseApp app; - setUpAll(() async { - // Initialize Firebase - app = await Firebase.initializeApp(); - }); - group('GenerativeModel', () { - const defaultModelName = 'some-model'; - - (ClientController, GenerativeModel) createModel({ - String modelName = defaultModelName, - List? tools, - ToolConfig? toolConfig, - Content? systemInstruction, - }) { - final client = ClientController(); - final model = createModelWithClient( - useVertexBackend: true, - app: app, - model: modelName, - client: client.client, - tools: tools, - toolConfig: toolConfig, - systemInstruction: systemInstruction, - location: 'us-central1'); - return (client, model); - } - - test('strips leading "models/" from model name', () async { - final (client, model) = createModel( - modelName: 'models/$defaultModelName', - ); - const prompt = 'Some prompt'; - await client.checkRequest( - () => model.generateContent([Content.text(prompt)]), - response: arbitraryGenerateContentResponse, - verifyRequest: (uri, _) { - expect(uri.path, endsWith('/models/some-model:generateContent')); - }, - ); - }); - - test('allows specifying a tuned model', () async { - final (client, model) = createModel( - modelName: 'tunedModels/$defaultModelName', - ); - const prompt = 'Some prompt'; - await client.checkRequest( - () => model.generateContent([Content.text(prompt)]), - response: arbitraryGenerateContentResponse, - verifyRequest: (uri, _) { - expect(uri.path, endsWith('/tunedModels/some-model:generateContent')); - }, - ); - }); - - group('generate unary content', () { - test('can make successful request', () async { - final (client, model) = createModel(); - const prompt = 'Some prompt'; - const result = 'Some response'; - final response = await client.checkRequest( - () => model.generateContent([Content.text(prompt)]), - verifyRequest: (uri, request) { - expect( - uri, - Uri.parse( - 'https://firebasevertexai.googleapis.com/v1beta/projects/123/locations/us-central1/publishers/google/models/some-model:generateContent', - ), - ); - expect(request, { - 'model': 'models/$defaultModelName', - 'contents': [ - { - 'role': 'user', - 'parts': [ - {'text': prompt}, - ], - }, - ], - }); - }, - response: { - 'candidates': [ - { - 'content': { - 'role': 'model', - 'parts': [ - {'text': result}, - ], - }, - }, - ], - }, - ); - expect( - response, - matchesGenerateContentResponse( - GenerateContentResponse([ - Candidate( - Content('model', [const TextPart(result)]), - null, - null, - null, - null, - ), - ], null), - ), - ); - }); - - test('can override safety settings', () async { - final (client, model) = createModel(); - const prompt = 'Some prompt'; - await client.checkRequest( - () => model.generateContent( - [Content.text(prompt)], - safetySettings: [ - SafetySetting( - HarmCategory.dangerousContent, - HarmBlockThreshold.high, - HarmBlockMethod.probability, - ), - ], - ), - response: arbitraryGenerateContentResponse, - verifyRequest: (_, request) { - expect(request['safetySettings'], [ - { - 'category': 'HARM_CATEGORY_DANGEROUS_CONTENT', - 'threshold': 'BLOCK_ONLY_HIGH', - 'method': 'PROBABILITY', - }, - ]); - }, - ); - }); - - test('can override generation config', () async { - final (client, model) = createModel(); - const prompt = 'Some prompt'; - await client.checkRequest( - () => model.generateContent([ - Content.text(prompt), - ], generationConfig: GenerationConfig(stopSequences: ['a'])), - verifyRequest: (_, request) { - expect(request['generationConfig'], { - 'stopSequences': ['a'], - }); - }, - response: arbitraryGenerateContentResponse, - ); - }); - - test('can override GenerationConfig repetition penalties', () async { - final (client, model) = createModel(); - const prompt = 'Some prompt'; - await client.checkRequest( - () => model.generateContent([Content.text(prompt)], - generationConfig: GenerationConfig( - presencePenalty: 0.5, frequencyPenalty: 0.2)), - verifyRequest: (_, request) { - expect(request['generationConfig'], { - 'presencePenalty': 0.5, - 'frequencyPenalty': 0.2, - }); - }, - response: arbitraryGenerateContentResponse, - ); - }); - - test('can pass system instructions', () async { - const instructions = 'Do a good job'; - final (client, model) = createModel( - systemInstruction: Content.system(instructions), - ); - const prompt = 'Some prompt'; - await client.checkRequest( - () => model.generateContent([Content.text(prompt)]), - verifyRequest: (_, request) { - expect(request['systemInstruction'], { - 'role': 'system', - 'parts': [ - {'text': instructions}, - ], - }); - }, - response: arbitraryGenerateContentResponse, - ); - }); - - test('can pass tools and function calling config', () async { - final (client, model) = createModel( - tools: [ - Tool.functionDeclarations([ - FunctionDeclaration( - 'someFunction', - 'Some cool function.', - parameters: { - 'schema1': Schema.string(description: 'Some parameter.') - }, - ), - ]), - ], - toolConfig: ToolConfig( - functionCallingConfig: FunctionCallingConfig.any( - {'someFunction'}, - ), - ), - ); - const prompt = 'Some prompt'; - await client.checkRequest( - () => model.generateContent([Content.text(prompt)]), - verifyRequest: (_, request) { - expect(request['tools'], [ - { - 'functionDeclarations': [ - { - 'name': 'someFunction', - 'description': 'Some cool function.', - 'parameters': { - 'type': 'OBJECT', - 'properties': { - 'schema1': { - 'type': 'STRING', - 'description': 'Some parameter.' - } - }, - 'required': ['schema1'] - } - }, - ], - }, - ]); - expect(request['toolConfig'], { - 'functionCallingConfig': { - 'mode': 'ANY', - 'allowedFunctionNames': ['someFunction'], - }, - }); - }, - response: arbitraryGenerateContentResponse, - ); - }); - - test('can override tools and function calling config', () async { - final (client, model) = createModel(); - const prompt = 'Some prompt'; - await client.checkRequest( - () => model.generateContent( - [Content.text(prompt)], - tools: [ - Tool.functionDeclarations([ - FunctionDeclaration( - 'someFunction', - 'Some cool function.', - parameters: { - 'schema1': Schema.string(description: 'Some parameter.') - }, - ), - ]), - ], - toolConfig: ToolConfig( - functionCallingConfig: FunctionCallingConfig.any( - {'someFunction'}, - ), - ), - ), - verifyRequest: (_, request) { - expect(request['tools'], [ - { - 'functionDeclarations': [ - { - 'name': 'someFunction', - 'description': 'Some cool function.', - 'parameters': { - 'type': 'OBJECT', - 'properties': { - 'schema1': { - 'type': 'STRING', - 'description': 'Some parameter.' - } - }, - 'required': ['schema1'] - } - }, - ], - }, - ]); - expect(request['toolConfig'], { - 'functionCallingConfig': { - 'mode': 'ANY', - 'allowedFunctionNames': ['someFunction'], - }, - }); - }, - response: arbitraryGenerateContentResponse, - ); - }); - }); - - group('generate content stream', () { - test('can make successful request', () async { - final (client, model) = createModel(); - const prompt = 'Some prompt'; - final results = {'First response', 'Second Response'}; - final response = await client.checkStreamRequest( - () async => model.generateContentStream([Content.text(prompt)]), - verifyRequest: (uri, request) { - expect( - uri, - Uri.parse( - 'https://firebasevertexai.googleapis.com/v1beta/projects/123/locations/us-central1/publishers/google/models/some-model:streamGenerateContent', - ), - ); - expect(request, { - 'model': 'models/$defaultModelName', - 'contents': [ - { - 'role': 'user', - 'parts': [ - {'text': prompt}, - ], - }, - ], - }); - }, - responses: [ - for (final result in results) - { - 'candidates': [ - { - 'content': { - 'role': 'model', - 'parts': [ - {'text': result}, - ], - }, - }, - ], - }, - ], - ); - expect( - response, - emitsInOrder([ - for (final result in results) - matchesGenerateContentResponse( - GenerateContentResponse([ - Candidate( - Content('model', [TextPart(result)]), - null, - null, - null, - null, - ), - ], null), - ), - ]), - ); - }); - - test('can override safety settings', () async { - final (client, model) = createModel(); - const prompt = 'Some prompt'; - final responses = await client.checkStreamRequest( - () async => model.generateContentStream( - [Content.text(prompt)], - safetySettings: [ - SafetySetting( - HarmCategory.dangerousContent, - HarmBlockThreshold.high, - HarmBlockMethod.severity, - ), - ], - ), - verifyRequest: (_, request) { - expect(request['safetySettings'], [ - { - 'category': 'HARM_CATEGORY_DANGEROUS_CONTENT', - 'threshold': 'BLOCK_ONLY_HIGH', - 'method': 'SEVERITY', - }, - ]); - }, - responses: [arbitraryGenerateContentResponse], - ); - await responses.drain(); - }); - - test('can override generation config', () async { - final (client, model) = createModel(); - const prompt = 'Some prompt'; - final responses = await client.checkStreamRequest( - () async => model.generateContentStream([ - Content.text(prompt), - ], generationConfig: GenerationConfig(stopSequences: ['a'])), - verifyRequest: (_, request) { - expect(request['generationConfig'], { - 'stopSequences': ['a'], - }); - }, - responses: [arbitraryGenerateContentResponse], - ); - await responses.drain(); - }); - }); - - group('count tokens', () { - test('can make successful request', () async { - final (client, model) = createModel(); - const prompt = 'Some prompt'; - final response = await client.checkRequest( - () => model.countTokens([Content.text(prompt)]), - verifyRequest: (uri, request) { - expect( - uri, - Uri.parse( - 'https://firebasevertexai.googleapis.com/v1beta/projects/123/locations/us-central1/publishers/google/models/some-model:countTokens', - ), - ); - expect(request, { - 'contents': [ - { - 'role': 'user', - 'parts': [ - {'text': prompt}, - ], - }, - ], - }); - }, - response: {'totalTokens': 2}, - ); - expect(response, matchesCountTokensResponse(CountTokensResponse(2))); - }); - }); - }); -} diff --git a/packages/firebase_vertexai/firebase_vertexai/test/response_parsing_test.dart b/packages/firebase_vertexai/firebase_vertexai/test/response_parsing_test.dart deleted file mode 100644 index 7af47214b881..000000000000 --- a/packages/firebase_vertexai/firebase_vertexai/test/response_parsing_test.dart +++ /dev/null @@ -1,875 +0,0 @@ -// Copyright 2024 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import 'dart:convert'; - -import 'package:firebase_ai/src/api.dart'; -import 'package:firebase_ai/src/error.dart'; -import 'package:firebase_vertexai/firebase_vertexai.dart'; -import 'package:flutter_test/flutter_test.dart'; - -import 'utils/matchers.dart'; - -void main() { - group('throws errors for invalid GenerateContentResponse', () { - test('with empty content', () { - const response = ''' -{ - "candidates": [ - { - "content": {}, - "index": 0 - } - ], - "promptFeedback": { - "safetyRatings": [ - { - "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HATE_SPEECH", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HARASSMENT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_DANGEROUS_CONTENT", - "probability": "NEGLIGIBLE" - } - ] - } -} -'''; - final decoded = jsonDecode(response) as Object; - expect( - () => VertexSerialization().parseGenerateContentResponse(decoded), - throwsA( - isA().having( - (e) => e.message, - 'message', - startsWith('Unhandled format for Content:'), - ), - ), - ); - }); - - test('with a blocked prompt', () { - const response = ''' -{ - "promptFeedback": { - "blockReason": "SAFETY", - "safetyRatings": [ - { - "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HATE_SPEECH", - "probability": "HIGH" - }, - { - "category": "HARM_CATEGORY_HARASSMENT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_DANGEROUS_CONTENT", - "probability": "NEGLIGIBLE" - } - ] - } -} -'''; - final decoded = jsonDecode(response) as Object; - final generateContentResponse = - VertexSerialization().parseGenerateContentResponse(decoded); - expect( - generateContentResponse, - matchesGenerateContentResponse( - GenerateContentResponse( - [], - PromptFeedback(BlockReason.safety, null, [ - SafetyRating( - HarmCategory.sexuallyExplicit, - HarmProbability.negligible, - ), - SafetyRating(HarmCategory.hateSpeech, HarmProbability.high), - SafetyRating(HarmCategory.harassment, HarmProbability.negligible), - SafetyRating( - HarmCategory.dangerousContent, - HarmProbability.negligible, - ), - ]), - ), - ), - ); - expect( - () => generateContentResponse.text, - throwsA( - isA().having( - (e) => e.message, - 'message', - startsWith('Response was blocked due to safety'), - ), - ), - ); - }); - test('with service api not enabled', () { - const response = ''' -{ - "error": { - "code": 403, - "message": "Vertex AI in Firebase API has not been used in project test-project-id-1234 before or it is disabled. Enable it by visiting https://console.developers.google.com/apis/api/firebasevertexai.googleapis.com/overview?project=test-project-id-1234 then retry. If you enabled this API recently, wait a few minutes for the action to propagate to our systems and retry.", - "status": "PERMISSION_DENIED", - "details": [ - { - "@type": "type.googleapis.com/google.rpc.Help", - "links": [ - { - "description": "Google developers console API activation", - "url": "https://console.developers.google.com/apis/api/firebasevertexai.googleapis.com/overview?project=test-project-id-1234" - } - ] - }, - { - "@type": "type.googleapis.com/google.rpc.ErrorInfo", - "reason": "SERVICE_DISABLED", - "domain": "googleapis.com", - "metadata": { - "service": "firebasevertexai.googleapis.com", - "consumer": "projects/test-project-id-1234" - } - } - ] - } -} -'''; - final decoded = jsonDecode(response) as Object; - expect( - () => VertexSerialization().parseGenerateContentResponse(decoded), - throwsA( - isA().having( - (e) => e.message, - 'message', - startsWith( - 'The Vertex AI in Firebase SDK requires the Vertex AI in Firebase API'), - ), - ), - ); - }); - - test('with quota exceed', () { - const response = ''' -{ - "error": { - "code": 429, - "message": "Quota exceeded for quota metric 'Generate Content API requests per minute' and limit 'GenerateContent request limit per minute for a region' of service 'generativelanguage.googleapis.com' for consumer 'project_number:348715329010'.", - "status": "RESOURCE_EXHAUSTED", - "details": [ - { - "@type": "type.googleapis.com/google.rpc.ErrorInfo", - "reason": "RATE_LIMIT_EXCEEDED", - "domain": "googleapis.com", - "metadata": { - "service": "generativelanguage.googleapis.com", - "consumer": "projects/348715329010", - "quota_limit_value": "0", - "quota_limit": "GenerateContentRequestsPerMinutePerProjectPerRegion", - "quota_location": "us-east2", - "quota_metric": "generativelanguage.googleapis.com/generate_content_requests" - } - }, - { - "@type": "type.googleapis.com/google.rpc.Help", - "links": [ - { - "description": "Request a higher quota limit.", - "url": "https://cloud.google.com/docs/quota#requesting_higher_quota" - } - ] - } - ] - } -} -'''; - final decoded = jsonDecode(response) as Object; - expect( - () => VertexSerialization().parseGenerateContentResponse(decoded), - throwsA( - isA().having( - (e) => e.message, - 'message', - startsWith('Quota exceeded for quota metric'), - ), - ), - ); - }); - }); - - group('parses successful GenerateContentResponse', () { - test('with a basic reply', () async { - const response = ''' -{ - "candidates": [ - { - "content": { - "parts": [ - { - "text": "Mountain View, California, United States" - } - ], - "role": "model" - }, - "finishReason": "STOP", - "index": 0, - "safetyRatings": [ - { - "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HATE_SPEECH", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HARASSMENT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_DANGEROUS_CONTENT", - "probability": "NEGLIGIBLE" - } - ] - } - ], - "promptFeedback": { - "safetyRatings": [ - { - "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HATE_SPEECH", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HARASSMENT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_DANGEROUS_CONTENT", - "probability": "NEGLIGIBLE" - } - ] - } -} -'''; - final decoded = jsonDecode(response) as Object; - final generateContentResponse = - VertexSerialization().parseGenerateContentResponse(decoded); - expect( - generateContentResponse, - matchesGenerateContentResponse( - GenerateContentResponse( - [ - Candidate( - Content.model([ - const TextPart('Mountain View, California, United States'), - ]), - [ - SafetyRating( - HarmCategory.sexuallyExplicit, - HarmProbability.negligible, - ), - SafetyRating( - HarmCategory.hateSpeech, - HarmProbability.negligible, - ), - SafetyRating( - HarmCategory.harassment, - HarmProbability.negligible, - ), - SafetyRating( - HarmCategory.dangerousContent, - HarmProbability.negligible, - ), - ], - null, - FinishReason.stop, - null, - ), - ], - PromptFeedback(null, null, [ - SafetyRating( - HarmCategory.sexuallyExplicit, - HarmProbability.negligible, - ), - SafetyRating(HarmCategory.hateSpeech, HarmProbability.negligible), - SafetyRating(HarmCategory.harassment, HarmProbability.negligible), - SafetyRating( - HarmCategory.dangerousContent, - HarmProbability.negligible, - ), - ]), - ), - ), - ); - }); - - test('with a citation', () async { - const response = ''' -{ - "candidates": [ - { - "content": { - "parts": [ - { - "text": "placeholder" - } - ], - "role": "model" - }, - "finishReason": "STOP", - "index": 0, - "safetyRatings": [ - { - "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HATE_SPEECH", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HARASSMENT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_DANGEROUS_CONTENT", - "probability": "NEGLIGIBLE" - } - ], - "citationMetadata": { - "citationSources": [ - { - "startIndex": 574, - "endIndex": 705, - "uri": "https://example.com/", - "license": "" - }, - { - "startIndex": 899, - "endIndex": 1026, - "uri": "https://example.com/", - "license": "" - }, - { - "startIndex": 899, - "endIndex": 1026 - }, - { - "uri": "https://example.com/", - "license": "" - }, - {} - ] - } - } - ], - "promptFeedback": { - "safetyRatings": [ - { - "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HATE_SPEECH", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HARASSMENT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_DANGEROUS_CONTENT", - "probability": "NEGLIGIBLE" - } - ] - } -} -'''; - final decoded = jsonDecode(response) as Object; - final generateContentResponse = - VertexSerialization().parseGenerateContentResponse(decoded); - expect( - generateContentResponse, - matchesGenerateContentResponse( - GenerateContentResponse( - [ - Candidate( - Content.model([const TextPart('placeholder')]), - [ - SafetyRating( - HarmCategory.sexuallyExplicit, - HarmProbability.negligible, - ), - SafetyRating( - HarmCategory.hateSpeech, - HarmProbability.negligible, - ), - SafetyRating( - HarmCategory.harassment, - HarmProbability.negligible, - ), - SafetyRating( - HarmCategory.dangerousContent, - HarmProbability.negligible, - ), - ], - CitationMetadata([ - Citation(574, 705, Uri.https('example.com'), ''), - Citation(899, 1026, Uri.https('example.com'), ''), - ]), - FinishReason.stop, - null, - ), - ], - PromptFeedback(null, null, [ - SafetyRating( - HarmCategory.sexuallyExplicit, - HarmProbability.negligible, - ), - SafetyRating(HarmCategory.hateSpeech, HarmProbability.negligible), - SafetyRating(HarmCategory.harassment, HarmProbability.negligible), - SafetyRating( - HarmCategory.dangerousContent, - HarmProbability.negligible, - ), - ]), - ), - ), - ); - }); - - test('with a vertex formatted citation', () async { - const response = ''' -{ - "candidates": [ - { - "content": { - "parts": [ - { - "text": "placeholder" - } - ], - "role": "model" - }, - "finishReason": "STOP", - "index": 0, - "safetyRatings": [ - { - "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HATE_SPEECH", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HARASSMENT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_DANGEROUS_CONTENT", - "probability": "NEGLIGIBLE" - } - ], - "citationMetadata": { - "citations": [ - { - "startIndex": 574, - "endIndex": 705, - "uri": "https://example.com/", - "license": "" - }, - { - "startIndex": 899, - "endIndex": 1026, - "uri": "https://example.com/", - "license": "" - }, - { - "startIndex": 899, - "endIndex": 1026 - }, - { - "uri": "https://example.com/", - "license": "" - }, - {} - ] - } - } - ], - "promptFeedback": { - "safetyRatings": [ - { - "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HATE_SPEECH", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HARASSMENT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_DANGEROUS_CONTENT", - "probability": "NEGLIGIBLE" - } - ] - } -} -'''; - final decoded = jsonDecode(response) as Object; - final generateContentResponse = - VertexSerialization().parseGenerateContentResponse(decoded); - expect( - generateContentResponse, - matchesGenerateContentResponse( - GenerateContentResponse( - [ - Candidate( - Content.model([const TextPart('placeholder')]), - [ - SafetyRating( - HarmCategory.sexuallyExplicit, - HarmProbability.negligible, - ), - SafetyRating( - HarmCategory.hateSpeech, - HarmProbability.negligible, - ), - SafetyRating( - HarmCategory.harassment, - HarmProbability.negligible, - ), - SafetyRating( - HarmCategory.dangerousContent, - HarmProbability.negligible, - ), - ], - CitationMetadata([ - Citation(574, 705, Uri.https('example.com'), ''), - Citation(899, 1026, Uri.https('example.com'), ''), - ]), - FinishReason.stop, - null, - ), - ], - PromptFeedback(null, null, [ - SafetyRating( - HarmCategory.sexuallyExplicit, - HarmProbability.negligible, - ), - SafetyRating(HarmCategory.hateSpeech, HarmProbability.negligible), - SafetyRating(HarmCategory.harassment, HarmProbability.negligible), - SafetyRating( - HarmCategory.dangerousContent, - HarmProbability.negligible, - ), - ]), - ), - ), - ); - }); - - test('allows missing content', () async { - const response = ''' -{ - "candidates": [ - { - "finishReason": "SAFETY", - "index": 0, - "safetyRatings": [ - { - "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HATE_SPEECH", - "probability": "LOW" - }, - { - "category": "HARM_CATEGORY_HARASSMENT", - "probability": "MEDIUM" - }, - { - "category": "HARM_CATEGORY_DANGEROUS_CONTENT", - "probability": "NEGLIGIBLE" - } - ] - } - ] -} -'''; - final decoded = jsonDecode(response) as Object; - final generateContentResponse = - VertexSerialization().parseGenerateContentResponse(decoded); - expect( - generateContentResponse, - matchesGenerateContentResponse( - GenerateContentResponse([ - Candidate( - Content(null, []), - [ - SafetyRating( - HarmCategory.sexuallyExplicit, - HarmProbability.negligible, - ), - SafetyRating( - HarmCategory.hateSpeech, HarmProbability.negligible), - SafetyRating( - HarmCategory.harassment, HarmProbability.negligible), - SafetyRating( - HarmCategory.dangerousContent, - HarmProbability.negligible, - ), - ], - CitationMetadata([]), - FinishReason.safety, - null), - ], null), - ), - ); - }); - - test('response including usage metadata', () async { - const response = ''' -{ - "candidates": [{ - "content": { - "role": "model", - "parts": [{ - "text": "Here is a description of the image:" - }] - }, - "finishReason": "STOP" - }], - "usageMetadata": { - "promptTokenCount": 1837, - "candidatesTokenCount": 76, - "totalTokenCount": 1913, - "promptTokensDetails": [{ - "modality": "TEXT", - "tokenCount": 76 - }, { - "modality": "IMAGE", - "tokenCount": 1806 - }], - "candidatesTokensDetails": [{ - "modality": "TEXT", - "tokenCount": 76 - }] - } -} - '''; - final decoded = jsonDecode(response) as Object; - final generateContentResponse = - VertexSerialization().parseGenerateContentResponse(decoded); - expect( - generateContentResponse.text, 'Here is a description of the image:'); - expect(generateContentResponse.usageMetadata?.totalTokenCount, 1913); - expect( - generateContentResponse - .usageMetadata?.promptTokensDetails?[1].modality, - ContentModality.image); - expect( - generateContentResponse - .usageMetadata?.promptTokensDetails?[1].tokenCount, - 1806); - expect( - generateContentResponse - .usageMetadata?.candidatesTokensDetails?.first.modality, - ContentModality.text); - expect( - generateContentResponse - .usageMetadata?.candidatesTokensDetails?.first.tokenCount, - 76); - }); - - test('countTokens with modality fields returned', () async { - const response = ''' -{ - "totalTokens": 1837, - "totalBillableCharacters": 117, - "promptTokensDetails": [{ - "modality": "IMAGE", - "tokenCount": 1806 - }, { - "modality": "TEXT", - "tokenCount": 31 - }] -} - '''; - final decoded = jsonDecode(response) as Object; - final countTokensResponse = - VertexSerialization().parseCountTokensResponse(decoded); - expect(countTokensResponse.totalTokens, 1837); - expect(countTokensResponse.promptTokensDetails?.first.modality, - ContentModality.image); - expect(countTokensResponse.promptTokensDetails?.first.tokenCount, 1806); - }); - - test('text getter joins content', () async { - const response = ''' -{ - "candidates": [ - { - "content": { - "parts": [ - { - "text": "Initial text" - }, - { - "functionCall": {"name": "someFunction", "args": {}} - }, - { - "text": " And more text" - } - ], - "role": "model" - }, - "finishReason": "STOP", - "index": 0 - } - ] -} -'''; - final decoded = jsonDecode(response) as Object; - final generateContentResponse = - VertexSerialization().parseGenerateContentResponse(decoded); - expect(generateContentResponse.text, 'Initial text And more text'); - expect(generateContentResponse.candidates.single.text, - 'Initial text And more text'); - }); - }); - - group('parses and throws error responses', () { - test('for invalid API key', () async { - const response = ''' -{ - "error": { - "code": 400, - "message": "API key not valid. Please pass a valid API key.", - "status": "INVALID_ARGUMENT", - "details": [ - { - "@type": "type.googleapis.com/google.rpc.ErrorInfo", - "reason": "API_KEY_INVALID", - "domain": "googleapis.com", - "metadata": { - "service": "generativelanguage.googleapis.com" - } - }, - { - "@type": "type.googleapis.com/google.rpc.DebugInfo", - "detail": "Invalid API key: AIzv00G7VmUCUeC-5OglO3hcXM" - } - ] - } -} -'''; - final decoded = jsonDecode(response) as Object; - final expectedThrow = throwsA( - isA().having( - (e) => e.message, - 'message', - 'API key not valid. Please pass a valid API key.', - ), - ); - expect(() => VertexSerialization().parseGenerateContentResponse(decoded), - expectedThrow); - expect(() => VertexSerialization().parseCountTokensResponse(decoded), - expectedThrow); - }); - - test('for unsupported user location', () async { - const response = r''' -{ - "error": { - "code": 400, - "message": "User location is not supported for the API use.", - "status": "FAILED_PRECONDITION", - "details": [ - { - "@type": "type.googleapis.com/google.rpc.DebugInfo", - "detail": "[ORIGINAL ERROR] generic::failed_precondition: User location is not supported for the API use. [google.rpc.error_details_ext] { message: \"User location is not supported for the API use.\" }" - } - ] - } -} -'''; - final decoded = jsonDecode(response) as Object; - final expectedThrow = throwsA( - isA().having( - (e) => e.message, - 'message', - 'User location is not supported for the API use.', - ), - ); - expect(() => VertexSerialization().parseGenerateContentResponse(decoded), - expectedThrow); - expect(() => VertexSerialization().parseCountTokensResponse(decoded), - expectedThrow); - }); - - test('for general server errors', () async { - const response = r''' -{ - "error": { - "code": 404, - "message": "models/unknown is not found for API version v1, or is not supported for GenerateContent. Call ListModels to see the list of available models and their supported methods.", - "status": "NOT_FOUND", - "details": [ - { - "@type": "type.googleapis.com/google.rpc.DebugInfo", - "detail": "[ORIGINAL ERROR] generic::not_found: models/unknown is not found for API version v1, or is not supported for GenerateContent. Call ListModels to see the list of available models and their supported methods. [google.rpc.error_details_ext] { message: \"models/unknown is not found for API version v1, or is not supported for GenerateContent. Call ListModels to see the list of available models and their supported methods.\" }" - } - ] - } -} -'''; - final decoded = jsonDecode(response) as Object; - final expectedThrow = throwsA( - isA().having( - (e) => e.message, - 'message', - startsWith( - 'models/unknown is not found for API version v1, ' - 'or is not supported for GenerateContent.', - ), - ), - ); - expect(() => VertexSerialization().parseGenerateContentResponse(decoded), - expectedThrow); - expect(() => VertexSerialization().parseCountTokensResponse(decoded), - expectedThrow); - }); - }); -} diff --git a/packages/firebase_vertexai/firebase_vertexai/test/schema_test.dart b/packages/firebase_vertexai/firebase_vertexai/test/schema_test.dart deleted file mode 100644 index e4b47be4be94..000000000000 --- a/packages/firebase_vertexai/firebase_vertexai/test/schema_test.dart +++ /dev/null @@ -1,297 +0,0 @@ -// Copyright 2024 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import 'package:firebase_ai/src/schema.dart'; -import 'package:flutter_test/flutter_test.dart'; - -void main() { - group('Schema Tests', () { - // Test basic constructors and toJson() for primitive types - test('Schema.boolean', () { - final schema = Schema.boolean( - description: 'A boolean value', nullable: true, title: 'Is Active'); - expect(schema.type, SchemaType.boolean); - expect(schema.description, 'A boolean value'); - expect(schema.nullable, true); - expect(schema.title, 'Is Active'); - expect(schema.toJson(), { - 'type': 'BOOLEAN', - 'description': 'A boolean value', - 'nullable': true, - 'title': 'Is Active', - }); - }); - - test('Schema.integer', () { - final schema = Schema.integer( - format: 'int32', minimum: 0, maximum: 100, title: 'Count'); - expect(schema.type, SchemaType.integer); - expect(schema.format, 'int32'); - expect(schema.minimum, 0); - expect(schema.maximum, 100); - expect(schema.title, 'Count'); - expect(schema.toJson(), { - 'type': 'INTEGER', - 'format': 'int32', - 'minimum': 0.0, // Ensure double conversion - 'maximum': 100.0, // Ensure double conversion - 'title': 'Count', - }); - }); - - test('Schema.number', () { - final schema = Schema.number( - format: 'double', - nullable: false, - minimum: 0.5, - maximum: 99.5, - title: 'Percentage'); - expect(schema.type, SchemaType.number); - expect(schema.format, 'double'); - expect(schema.nullable, false); - expect(schema.minimum, 0.5); - expect(schema.maximum, 99.5); - expect(schema.title, 'Percentage'); - expect(schema.toJson(), { - 'type': 'NUMBER', - 'format': 'double', - 'nullable': false, - 'minimum': 0.5, - 'maximum': 99.5, - 'title': 'Percentage', - }); - }); - - test('Schema.string', () { - final schema = Schema.string(title: 'User Name'); - expect(schema.type, SchemaType.string); - expect(schema.title, 'User Name'); - expect(schema.toJson(), {'type': 'STRING', 'title': 'User Name'}); - }); - - test('Schema.enumString', () { - final schema = - Schema.enumString(enumValues: ['value1', 'value2'], title: 'Status'); - expect(schema.type, SchemaType.string); - expect(schema.format, 'enum'); - expect(schema.enumValues, ['value1', 'value2']); - expect(schema.title, 'Status'); - expect(schema.toJson(), { - 'type': 'STRING', - 'format': 'enum', - 'enum': ['value1', 'value2'], - 'title': 'Status', - }); - }); - - // Test constructors and toJson() for complex types - test('Schema.array', () { - final itemSchema = Schema.string(); - final schema = Schema.array( - items: itemSchema, minItems: 1, maxItems: 5, title: 'Tags'); - expect(schema.type, SchemaType.array); - expect(schema.items, itemSchema); - expect(schema.minItems, 1); - expect(schema.maxItems, 5); - expect(schema.title, 'Tags'); - expect(schema.toJson(), { - 'type': 'ARRAY', - 'items': {'type': 'STRING'}, - 'minItems': 1, - 'maxItems': 5, - 'title': 'Tags', - }); - }); - - test('Schema.object', () { - final properties = { - 'name': Schema.string(), - 'age': Schema.integer(), - 'city': Schema.string(description: 'City of residence'), - }; - final schema = Schema.object( - properties: properties, - optionalProperties: ['age'], - propertyOrdering: ['name', 'city', 'age'], - title: 'User Profile', - description: 'Represents a user profile', - ); - expect(schema.type, SchemaType.object); - expect(schema.properties, properties); - expect(schema.optionalProperties, ['age']); - expect(schema.propertyOrdering, ['name', 'city', 'age']); - expect(schema.title, 'User Profile'); - expect(schema.description, 'Represents a user profile'); - expect(schema.toJson(), { - 'type': 'OBJECT', - 'properties': { - 'name': {'type': 'STRING'}, - 'age': {'type': 'INTEGER'}, - 'city': {'type': 'STRING', 'description': 'City of residence'}, - }, - 'required': ['name', 'city'], - 'propertyOrdering': ['name', 'city', 'age'], - 'title': 'User Profile', - 'description': 'Represents a user profile', - }); - }); - - test('Schema.object with empty optionalProperties', () { - final properties = { - 'name': Schema.string(), - 'age': Schema.integer(), - }; - final schema = Schema.object( - properties: properties, - // No optionalProperties, so all are required - ); - expect(schema.type, SchemaType.object); - expect(schema.properties, properties); - expect(schema.toJson(), { - 'type': 'OBJECT', - 'properties': { - 'name': {'type': 'STRING'}, - 'age': {'type': 'INTEGER'}, - }, - 'required': ['name', 'age'], // All keys from properties - }); - }); - - test('Schema.object with all properties optional', () { - final properties = { - 'name': Schema.string(), - 'age': Schema.integer(), - }; - final schema = Schema.object( - properties: properties, - optionalProperties: ['name', 'age'], - ); - expect(schema.type, SchemaType.object); - expect(schema.properties, properties); - expect(schema.optionalProperties, ['name', 'age']); - expect(schema.toJson(), { - 'type': 'OBJECT', - 'properties': { - 'name': {'type': 'STRING'}, - 'age': {'type': 'INTEGER'}, - }, - 'required': [], // Empty list as all are optional - }); - }); - - // Test Schema.anyOf - test('Schema.anyOf', () { - final schema1 = Schema.string(description: 'A string value'); - final schema2 = Schema.integer(description: 'An integer value'); - final schema = Schema.anyOf(schemas: [schema1, schema2]); - - // The type field is SchemaType.anyOf internally for dispatching toJson - // but it should not be present in the final JSON for `anyOf`. - expect(schema.type, SchemaType.anyOf); - expect(schema.anyOf, [schema1, schema2]); - expect(schema.toJson(), { - 'anyOf': [ - {'type': 'STRING', 'description': 'A string value'}, - {'type': 'INTEGER', 'description': 'An integer value'}, - ], - }); - }); - - test('Schema.anyOf with complex types', () { - final userSchema = Schema.object(properties: { - 'id': Schema.integer(), - 'username': Schema.string(), - }, optionalProperties: [ - 'username' - ]); - final errorSchema = Schema.object(properties: { - 'errorCode': Schema.integer(), - 'errorMessage': Schema.string(), - }); - final schema = Schema.anyOf(schemas: [userSchema, errorSchema]); - - expect(schema.type, SchemaType.anyOf); - expect(schema.anyOf?.length, 2); - expect(schema.toJson(), { - 'anyOf': [ - { - 'type': 'OBJECT', - 'properties': { - 'id': {'type': 'INTEGER'}, - 'username': {'type': 'STRING'}, - }, - 'required': ['id'], - }, - { - 'type': 'OBJECT', - 'properties': { - 'errorCode': {'type': 'INTEGER'}, - 'errorMessage': {'type': 'STRING'}, - }, - 'required': ['errorCode', 'errorMessage'], - }, - ], - }); - }); - - // Test SchemaType.toJson() - test('SchemaType.toJson', () { - expect(SchemaType.string.toJson(), 'STRING'); - expect(SchemaType.number.toJson(), 'NUMBER'); - expect(SchemaType.integer.toJson(), 'INTEGER'); - expect(SchemaType.boolean.toJson(), 'BOOLEAN'); - expect(SchemaType.array.toJson(), 'ARRAY'); - expect(SchemaType.object.toJson(), 'OBJECT'); - expect(SchemaType.anyOf.toJson(), - 'null'); // As per implementation, 'null' string for anyOf - }); - - // Test edge cases - test('Schema.object with no properties', () { - final schema = Schema.object(properties: {}); - expect(schema.type, SchemaType.object); - expect(schema.properties, {}); - expect(schema.toJson(), { - 'type': 'OBJECT', - 'properties': {}, - 'required': [], - }); - }); - - test('Schema.array with no items (should not happen with constructor)', () { - // This is more of a theoretical test as the constructor requires `items`. - // We construct it manually to test `toJson` robustness. - final schema = Schema(SchemaType.array); - expect(schema.type, SchemaType.array); - expect(schema.toJson(), { - 'type': 'ARRAY', - // 'items' field should be absent if items is null - }); - }); - - test('Schema with all optional fields null', () { - final schema = Schema(SchemaType.string); // Only type is provided - expect(schema.type, SchemaType.string); - expect(schema.format, isNull); - expect(schema.description, isNull); - expect(schema.nullable, isNull); - expect(schema.enumValues, isNull); - expect(schema.items, isNull); - expect(schema.properties, isNull); - expect(schema.optionalProperties, isNull); - expect(schema.anyOf, isNull); - expect(schema.toJson(), {'type': 'STRING'}); - }); - }); -} diff --git a/packages/firebase_vertexai/firebase_vertexai/test/utils/matchers.dart b/packages/firebase_vertexai/firebase_vertexai/test/utils/matchers.dart deleted file mode 100644 index 8daf0b12abf8..000000000000 --- a/packages/firebase_vertexai/firebase_vertexai/test/utils/matchers.dart +++ /dev/null @@ -1,103 +0,0 @@ -// Copyright 2024 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -import 'package:firebase_ai/src/content.dart'; -import 'package:firebase_vertexai/firebase_vertexai.dart'; -import 'package:http/http.dart' as http; -import 'package:matcher/matcher.dart'; - -Matcher matchesPart(Part part) => switch (part) { - TextPart(text: final text) => - isA().having((p) => p.text, 'text', text), - InlineDataPart(mimeType: final mimeType, bytes: final bytes) => - isA() - .having((p) => p.mimeType, 'mimeType', mimeType) - .having((p) => p.bytes, 'bytes', bytes), - FileData(mimeType: final mimeType, fileUri: final fileUri) => - isA() - .having((p) => p.mimeType, 'mimeType', mimeType) - .having((p) => p.fileUri, 'fileUri', fileUri), - FunctionCall(name: final name, args: final args) => isA() - .having((p) => p.name, 'name', name) - .having((p) => p.args, 'args', args), - FunctionResponse(name: final name, response: final response) => - isA() - .having((p) => p.name, 'name', name) - .having((p) => p.response, 'args', response), - UnknownPart(data: final data) => - isA().having((p) => p.data, 'data', data), - }; - -Matcher matchesContent(Content content) => isA() - .having((c) => c.role, 'role', content.role) - .having((c) => c.parts, 'parts', content.parts.map(matchesPart).toList()); - -Matcher matchesCandidate(Candidate candidate) => isA().having( - (c) => c.content, - 'content', - matchesContent(candidate.content), - ); - -Matcher matchesGenerateContentResponse(GenerateContentResponse response) => - isA() - .having( - (r) => r.candidates, - 'candidates', - response.candidates.map(matchesCandidate).toList(), - ) - .having( - (r) => r.promptFeedback, - 'promptFeedback', - response.promptFeedback == null - ? isNull - : matchesPromptFeedback(response.promptFeedback!), - ); - -Matcher matchesPromptFeedback( - PromptFeedback promptFeedback, -) => - isA() - .having((p) => p.blockReason, 'blockReason', promptFeedback.blockReason) - .having( - (p) => p.blockReasonMessage, - 'blockReasonMessage', - promptFeedback.blockReasonMessage, - ) - .having( - (p) => p.safetyRatings, - 'safetyRatings', - unorderedMatches( - promptFeedback.safetyRatings.map(matchesSafetyRating)), - ); - -Matcher matchesSafetyRating(SafetyRating safetyRating) => isA() - .having((s) => s.category, 'category', safetyRating.category) - .having((s) => s.probability, 'probability', safetyRating.probability); - -Matcher matchesCountTokensResponse(CountTokensResponse response) => - isA().having( - (r) => r.totalTokens, - 'totalTokens', - response.totalTokens, - ); - -Matcher matchesRequest(http.Request request) => isA() - .having((r) => r.headers, 'headers', request.headers) - .having((r) => r.method, 'method', request.method) - .having((r) => r.bodyBytes, 'bodyBytes', request.bodyBytes) - .having((r) => r.url, 'url', request.url); - -Matcher matchesBaseRequest(http.BaseRequest request) => isA() - .having((r) => r.headers, 'headers', request.headers) - .having((r) => r.method, 'method', request.method) - .having((r) => r.url, 'url', request.url); diff --git a/packages/firebase_vertexai/firebase_vertexai/test/utils/stub_client.dart b/packages/firebase_vertexai/firebase_vertexai/test/utils/stub_client.dart deleted file mode 100644 index fa0704316574..000000000000 --- a/packages/firebase_vertexai/firebase_vertexai/test/utils/stub_client.dart +++ /dev/null @@ -1,93 +0,0 @@ -// Copyright 2024 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import 'dart:collection'; - -import 'package:firebase_ai/src/client.dart'; - -class ClientController { - final _client = _ControlledClient(); - ApiClient get client => _client; - - /// Run [body] and return [response] for a single call to - /// [ApiClient.streamRequest]. - /// - /// Check expectations for the request URI and JSON payload with the - /// [verifyRequest] callback. - Future checkRequest( - Future Function() body, { - required Map response, - void Function(Uri, Map)? verifyRequest, - }) async { - _client._requestExpectations.addLast(verifyRequest); - _client._responses.addLast([response]); - final result = await body(); - assert(_client._responses.isEmpty); - return result; - } - - /// Run [body] and return [responses] for a single call to - /// [ApiClient.streamRequest]. - /// - /// Check expectations for the request URI and JSON payload with the - /// [verifyRequest] callback. - Future checkStreamRequest( - Future Function() body, { - required Iterable> responses, - void Function(Uri, Map)? verifyRequest, - }) async { - _client._requestExpectations.addLast(verifyRequest); - _client._responses.addLast(responses.toList()); - final result = await body(); - assert(_client._responses.isEmpty); - return result; - } -} - -final class _ControlledClient implements ApiClient { - final _requestExpectations = - Queue)?>(); - final _responses = Queue>>(); - - @override - Future> makeRequest( - Uri uri, - Map body, - ) async { - _requestExpectations.removeFirst()?.call(uri, body); - return _responses.removeFirst().single; - } - - @override - Stream> streamRequest( - Uri uri, - Map body, - ) { - _requestExpectations.removeFirst()?.call(uri, body); - return Stream.fromIterable(_responses.removeFirst()); - } -} - -const Map arbitraryGenerateContentResponse = { - 'candidates': [ - { - 'content': { - 'role': 'model', - 'parts': [ - {'text': 'Some Response'}, - ], - }, - }, - ], -};