├── .gitattributes ├── .github ├── dependabot.yaml ├── labeler.yml └── workflows │ ├── flutter_sample.yml │ ├── google_generative_ai.yml │ └── samples.yml ├── .gitignore ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── pkgs └── google_generative_ai │ ├── CHANGELOG.md │ ├── LICENSE │ ├── README.md │ ├── analysis_options.yaml │ ├── lib │ ├── google_generative_ai.dart │ └── src │ │ ├── api.dart │ │ ├── chat.dart │ │ ├── client.dart │ │ ├── content.dart │ │ ├── error.dart │ │ ├── function_calling.dart │ │ ├── model.dart │ │ ├── utils │ │ └── mutex.dart │ │ ├── version.dart │ │ └── vertex_hooks.dart │ ├── pubspec.yaml │ ├── test │ ├── chat_test.dart │ ├── generative_model_test.dart │ ├── http_api_client_test.dart │ ├── response_parsing_test.dart │ └── utils │ │ ├── matchers.dart │ │ └── stub_client.dart │ └── tool │ └── validate_version.dart └── samples ├── dart ├── README.md ├── analysis_options.yaml ├── bin │ ├── advanced_chat.dart │ ├── advanced_text.dart │ ├── advanced_text_and_image.dart │ ├── chat.dart │ ├── code_execution.dart │ ├── configure_model_parameters.dart │ ├── controlled_generation.dart │ ├── count_tokens.dart │ ├── function_calling.dart │ ├── guessing_game.dart │ ├── safety_settings.dart │ ├── simple_chat.dart │ ├── simple_config.dart │ ├── simple_embedding.dart │ ├── simple_text.dart │ ├── simple_text_and_image.dart │ ├── system_instructions.dart │ ├── text_generation.dart │ └── util │ │ └── resource.dart ├── pubspec.yaml └── resources │ ├── cat.jpg │ ├── firefighter.jpg │ ├── jetpack.jpg │ ├── organ.jpg │ ├── piranha.jpg │ └── scones.jpg └── flutter_app ├── .gitignore ├── .metadata ├── README.md ├── analysis_options.yaml ├── android ├── .gitignore ├── app │ ├── build.gradle │ └── src │ │ ├── debug │ │ └── AndroidManifest.xml │ │ ├── main │ │ ├── AndroidManifest.xml │ │ ├── kotlin │ │ │ └── com │ │ │ │ └── example │ │ │ │ └── flutter_app │ │ │ │ └── MainActivity.kt │ │ └── res │ │ │ ├── drawable-v21 │ │ │ └── launch_background.xml │ │ │ ├── drawable │ │ │ └── launch_background.xml │ │ │ ├── mipmap-hdpi │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-mdpi │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-xhdpi │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-xxhdpi │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-xxxhdpi │ │ │ └── ic_launcher.png │ │ │ ├── values-night │ │ │ └── styles.xml │ │ │ └── values │ │ │ └── styles.xml │ │ └── profile │ │ └── AndroidManifest.xml ├── build.gradle ├── gradle.properties ├── gradle │ └── wrapper │ │ └── gradle-wrapper.properties └── settings.gradle ├── assets └── images │ ├── cat.jpg │ └── scones.jpg ├── ios ├── .gitignore ├── Flutter │ ├── AppFrameworkInfo.plist │ ├── Debug.xcconfig │ └── Release.xcconfig ├── Runner.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ ├── IDEWorkspaceChecks.plist │ │ │ └── WorkspaceSettings.xcsettings │ └── xcshareddata │ │ └── xcschemes │ │ └── Runner.xcscheme ├── Runner.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ ├── IDEWorkspaceChecks.plist │ │ └── WorkspaceSettings.xcsettings ├── Runner │ ├── AppDelegate.swift │ ├── Assets.xcassets │ │ ├── AppIcon.appiconset │ │ │ ├── Contents.json │ │ │ ├── Icon-App-1024x1024@1x.png │ │ │ ├── Icon-App-20x20@1x.png │ │ │ ├── Icon-App-20x20@2x.png │ │ │ ├── Icon-App-20x20@3x.png │ │ │ ├── Icon-App-29x29@1x.png │ │ │ ├── Icon-App-29x29@2x.png │ │ │ ├── Icon-App-29x29@3x.png │ │ │ ├── Icon-App-40x40@1x.png │ │ │ ├── Icon-App-40x40@2x.png │ │ │ ├── Icon-App-40x40@3x.png │ │ │ ├── Icon-App-60x60@2x.png │ │ │ ├── Icon-App-60x60@3x.png │ │ │ ├── Icon-App-76x76@1x.png │ │ │ ├── Icon-App-76x76@2x.png │ │ │ └── Icon-App-83.5x83.5@2x.png │ │ └── LaunchImage.imageset │ │ │ ├── Contents.json │ │ │ ├── LaunchImage.png │ │ │ ├── LaunchImage@2x.png │ │ │ ├── LaunchImage@3x.png │ │ │ └── README.md │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ ├── Info.plist │ └── Runner-Bridging-Header.h └── RunnerTests │ └── RunnerTests.swift ├── lib └── main.dart ├── macos ├── .gitignore ├── Flutter │ ├── Flutter-Debug.xcconfig │ ├── Flutter-Release.xcconfig │ └── GeneratedPluginRegistrant.swift ├── Runner.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ └── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ └── xcshareddata │ │ └── xcschemes │ │ └── Runner.xcscheme ├── Runner.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist ├── Runner │ ├── AppDelegate.swift │ ├── Assets.xcassets │ │ └── AppIcon.appiconset │ │ │ ├── Contents.json │ │ │ ├── app_icon_1024.png │ │ │ ├── app_icon_128.png │ │ │ ├── app_icon_16.png │ │ │ ├── app_icon_256.png │ │ │ ├── app_icon_32.png │ │ │ ├── app_icon_512.png │ │ │ └── app_icon_64.png │ ├── Base.lproj │ │ └── MainMenu.xib │ ├── Configs │ │ ├── AppInfo.xcconfig │ │ ├── Debug.xcconfig │ │ ├── Release.xcconfig │ │ └── Warnings.xcconfig │ ├── DebugProfile.entitlements │ ├── Info.plist │ ├── MainFlutterWindow.swift │ └── Release.entitlements └── RunnerTests │ └── RunnerTests.swift ├── pubspec.yaml ├── web ├── favicon.png ├── icons │ ├── Icon-192.png │ ├── Icon-512.png │ ├── Icon-maskable-192.png │ └── Icon-maskable-512.png ├── index.html └── manifest.json └── windows ├── .gitignore ├── CMakeLists.txt ├── flutter └── CMakeLists.txt └── runner ├── CMakeLists.txt ├── Runner.rc ├── flutter_window.cpp ├── flutter_window.h ├── main.cpp ├── resource.h ├── resources └── app_icon.ico ├── runner.exe.manifest ├── utils.cpp ├── utils.h ├── win32_window.cpp └── win32_window.h /.gitattributes: -------------------------------------------------------------------------------- 1 | samples/*/.metadata linguist-generated=true 2 | samples/**/Flutter/GeneratedPluginRegistrant.swift linguist-generated=true 3 | samples/**/Runner.xcodeproj/ linguist-generated=true 4 | samples/**/Runner.xcworkspace/ linguist-generated=true 5 | samples/**/flutter/CMakeLists.txt linguist-generated=true 6 | samples/**/flutter/generated_* linguist-generated=true 7 | -------------------------------------------------------------------------------- /.github/dependabot.yaml: -------------------------------------------------------------------------------- 1 | # Dependabot configuration file; see 2 | # https://docs.github.com/en/code-security/dependabot/dependabot-version-updates 3 | 4 | version: 2 5 | 6 | updates: 7 | - package-ecosystem: github-actions 8 | directory: / 9 | schedule: 10 | interval: monthly 11 | -------------------------------------------------------------------------------- /.github/labeler.yml: -------------------------------------------------------------------------------- 1 | # Configuration for .github/workflows/pull_request_label.yml. 2 | 3 | 'type-infra': 4 | - '.github/**' 5 | 6 | 'package:google_generative_ai': 7 | - 'pkgs/google_generative_ai/**' 8 | -------------------------------------------------------------------------------- /.github/workflows/flutter_sample.yml: -------------------------------------------------------------------------------- 1 | name: samples_flutter 2 | 3 | permissions: read-all 4 | 5 | on: 6 | push: 7 | branches: [ main ] 8 | paths: 9 | - '.github/workflows/flutter_sample.yml' 10 | - 'pkgs/google_generative_ai/**' 11 | - 'samples/flutter_app/**' 12 | pull_request: 13 | branches: [ main ] 14 | paths: 15 | - '.github/workflows/flutter_sample.yml' 16 | - 'pkgs/google_generative_ai/**' 17 | - 'samples/flutter_app/**' 18 | schedule: 19 | - cron: '0 0 * * 0' # weekly 20 | 21 | jobs: 22 | validate: 23 | runs-on: ubuntu-latest 24 | defaults: 25 | run: 26 | working-directory: samples/flutter_app/ 27 | steps: 28 | - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 29 | - uses: subosito/flutter-action@44ac965b96f18d999802d4b807e3256d5a3f9fa1 30 | with: 31 | channel: stable 32 | - run: flutter pub get 33 | - run: flutter analyze --fatal-infos 34 | - run: dart format --set-exit-if-changed . 35 | -------------------------------------------------------------------------------- /.github/workflows/google_generative_ai.yml: -------------------------------------------------------------------------------- 1 | name: package:google_generative_ai 2 | 3 | permissions: read-all 4 | 5 | on: 6 | pull_request: 7 | branches: [ main ] 8 | paths: 9 | - '.github/workflows/google_generative_ai.yml' 10 | - 'pkgs/google_generative_ai/**' 11 | push: 12 | branches: [ main ] 13 | paths: 14 | - '.github/workflows/google_generative_ai.yml' 15 | - 'pkgs/google_generative_ai/**' 16 | schedule: 17 | - cron: '0 0 * * 0' # weekly 18 | 19 | jobs: 20 | build: 21 | runs-on: ubuntu-latest 22 | defaults: 23 | run: 24 | working-directory: pkgs/google_generative_ai 25 | strategy: 26 | fail-fast: false 27 | matrix: 28 | sdk: ['3.1', stable, dev] 29 | include: 30 | - sdk: stable 31 | run-tests: true 32 | steps: 33 | - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 34 | - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 35 | with: 36 | sdk: ${{ matrix.sdk }} 37 | 38 | - run: dart pub get 39 | 40 | - run: dart analyze --fatal-infos 41 | 42 | # Make sure that the package version in lib/src/version.dart is kept up-to-date. 43 | - run: dart tool/validate_version.dart 44 | 45 | - run: dart format --output=none --set-exit-if-changed . 46 | if: ${{matrix.run-tests}} 47 | 48 | - run: dart test 49 | if: ${{matrix.run-tests}} 50 | 51 | - run: dart test --platform chrome 52 | if: ${{matrix.run-tests}} 53 | -------------------------------------------------------------------------------- /.github/workflows/samples.yml: -------------------------------------------------------------------------------- 1 | name: samples_dart 2 | 3 | permissions: read-all 4 | 5 | on: 6 | pull_request: 7 | branches: [ main ] 8 | paths: 9 | - '.github/workflows/samples.yml' 10 | - 'pkgs/google_generative_ai/**' 11 | - 'samples/dart/**' 12 | push: 13 | branches: [ main ] 14 | paths: 15 | - '.github/workflows/samples.yml' 16 | - 'pkgs/google_generative_ai/**' 17 | - 'samples/dart/**' 18 | schedule: 19 | - cron: '0 0 * * 0' # weekly 20 | 21 | jobs: 22 | build: 23 | runs-on: ubuntu-latest 24 | defaults: 25 | run: 26 | working-directory: samples/dart 27 | strategy: 28 | fail-fast: false 29 | matrix: 30 | sdk: [stable, dev] 31 | include: 32 | - sdk: stable 33 | check-formatting: true 34 | steps: 35 | - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 36 | - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 37 | with: 38 | sdk: ${{ matrix.sdk }} 39 | 40 | - run: dart pub get 41 | 42 | - run: dart analyze --fatal-infos 43 | 44 | - run: dart format --output=none --set-exit-if-changed . 45 | if: ${{matrix.check-formatting}} 46 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .atom/ 3 | .idea/ 4 | .vscode/* 5 | 6 | # Dart project 7 | **/doc/api/ 8 | .dart_tool/ 9 | build/ 10 | pubspec.lock 11 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # How to Contribute 2 | 3 | We would love to accept your patches and contributions to this project. 4 | 5 | ## Before you begin 6 | 7 | ### Sign our Contributor License Agreement 8 | 9 | Contributions to this project must be accompanied by a 10 | [Contributor License Agreement](https://cla.developers.google.com/about) (CLA). 11 | You (or your employer) retain the copyright to your contribution; this simply 12 | gives us permission to use and redistribute your contributions as part of the 13 | project. 14 | 15 | If you or your current employer have already signed the Google CLA (even if it 16 | was for a different project), you probably don't need to do it again. 17 | 18 | Visit to see your current agreements or to 19 | sign a new one. 20 | 21 | ### Review our Community Guidelines 22 | 23 | This project follows [Google's Open Source Community 24 | Guidelines](https://opensource.google/conduct/). 25 | 26 | ## Contribution process 27 | 28 | ### Code Reviews 29 | 30 | All submissions, including submissions by project members, require review. We 31 | use [GitHub pull requests](https://docs.github.com/articles/about-pull-requests) 32 | for this purpose. 33 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # [Deprecated] Google AI Dart SDK for the Gemini API 2 | 3 | With Gemini 2.0, we took the chance to create a unified SDK for mobile 4 | developers who want to use Google's GenAI models (Gemini, Veo, Imagen, etc). As 5 | part of that process, we took all of the feedback from this SDK and what 6 | developers like about other SDKs in the ecosystem to directly work with the 7 | [Firebase SDK](https://firebase.google.com/docs/vertex-ai). We don't plan to add 8 | anything to this SDK or make any further changes. We know how disruptive an SDK 9 | change can be and don't take this change lightly, but our goal is to create an 10 | extremely simple and clear path for developers to build with our models so it 11 | felt necessary to make this change. 12 | 13 | Thank you for building with Gemini and 14 | [let us know](https://discuss.ai.google.dev/c/gemini-api/4) if you need any 15 | help! 16 | -------------------------------------------------------------------------------- /pkgs/google_generative_ai/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## 0.4.7 2 | 3 | - Update the README.md to indicate that this package is deprecated; using the 4 | [Firebase SDK](https://firebase.google.com/docs/vertex-ai) is the preferred 5 | path forward. 6 | 7 | ## 0.4.6 8 | 9 | - Throw a more relevant exception for server error HTTP responses. 10 | 11 | ## 0.4.5 12 | 13 | - Add support for model side Code Execution. Enable code execution by 14 | configuring `Tools` with a `codeExecution` argument. 15 | - Use a default role `'model'` when a chat response comes back with no role. 16 | 17 | ## 0.4.4 18 | 19 | - Allow the Vertex format for citation metadata - read either `citationSources` 20 | or `citations` keys, whichever exists. Fixes a `FormatException` when parsing 21 | vertex results with citations. 22 | 23 | ## 0.4.3 24 | 25 | - Internal changes to enable reuse in the Vertex SDK. No user visible changes. 26 | 27 | ## 0.4.2 28 | 29 | - Add support for `GenerationConfig.responseSchema` for constraining JSON mime 30 | type output formats. 31 | - Require Dart 3.1. 32 | 33 | ## 0.4.1 34 | 35 | - Concatenate multiple `TextPart` into the `text` String in case the model 36 | replies with more than one part. 37 | - Fix handling of `format` argument to `Schema.number` and `Schema.integer`. 38 | - Export `UsageMetadata`. 39 | - Include the full `GenerateContentRequest` (previously omitted 40 | `safetySettings`, `generationConfig`, `tools`, `toolConfig`, and 41 | `systemInstruction`) in `countTokens` requests. This aligns the token count 42 | with the token count the backend will see in practice for a 43 | `generateContent` request. 44 | - Add a `text` getter on `Candidate` to make it easer to retrieve the text from 45 | candidates other than the first in a response. 46 | 47 | ## 0.4.0 48 | 49 | - Add support for parsing Vertex AI specific fields in `CountTokensResponse`. 50 | - Add named constructors on `Schema` for each value type. 51 | - Add `GenerationConfig.responseMimeType` which supports setting 52 | `'application/json'` to force the model to reply with JSON parseable output. 53 | - Add `outputDimensionality` argument support for `embedContent` and 54 | `batchEmbedContent`. 55 | - Add `Content.functionResponses` utility to reply to multiple function calls in 56 | parallel. 57 | - **Breaking** The `Part` class is no longer `sealed`. Exhaustive switches over 58 | a `Part` instance will need to add a wildcard case. 59 | 60 | ## 0.3.3 61 | 62 | - Add support for parsing the `usageMetadata` field in `GenerateContentResponse` 63 | messages. 64 | 65 | ## 0.3.2 66 | 67 | - Use API version `v1beta` by default. 68 | - Add note to README warning about leaking API keys. 69 | 70 | ## 0.3.1 71 | 72 | - Add support on content generating methods for overriding "tools" passed when 73 | the generative model was instantiated. 74 | - Add support for forcing the model to use or not use function calls to generate 75 | content. 76 | 77 | ## 0.3.0 78 | 79 | - Allow specifying an API version in a `requestOptions` argument when 80 | constructing a model. 81 | - Add support for referring to uploaded files in request contents. 82 | - Add support for passing tools with functions the model may call while 83 | generating responses. 84 | - Add support for passing a system instruction when creating the model. 85 | - **Breaking** Added new subclasses `FilePart`, `FunctionCall`, and 86 | `FunctionResponse` of the sealed class `Part`. 87 | 88 | ## 0.2.3 89 | 90 | - Update the package version that is sent with the HTTP client name. 91 | - Throw more actionable error objects than `FormatException` for errors. Errors 92 | were previously only correctly parsed in `generateContent` calls. 93 | - Add support for tuned models. 94 | - Add support for `batchEmbedContents` calls. 95 | 96 | ## 0.2.2 97 | 98 | - Remove usage of new SDK features - support older SDKs 3.0 and above. 99 | 100 | ## 0.2.1 101 | 102 | - Fix an issue parsing `generateContent()` responses that do not include content 103 | (this can occur for some `finishReason`s). 104 | - Fix an issue parsing `generateContent()` responses that include citation 105 | sources with unpopulated fields 106 | - Add link to ai.google.dev docs. 107 | 108 | ## 0.2.0 109 | 110 | - **Breaking** `HarmCategory.unknown` renamed to `unspecified`. Removed unused 111 | `unknown` values in the `HarmProbability` and `FinishReason` enums. 112 | - Add additional API documentation. 113 | - Update the getting started instructions in the readme. 114 | 115 | ## 0.1.0 116 | 117 | - Initial release. 118 | -------------------------------------------------------------------------------- /pkgs/google_generative_ai/README.md: -------------------------------------------------------------------------------- 1 | # [Deprecated] Google AI Dart SDK for the Gemini API 2 | 3 | With Gemini 2.0, we took the chance to create a unified SDK for mobile 4 | developers who want to use Google's GenAI models (Gemini, Veo, Imagen, etc). As 5 | part of that process, we took all of the feedback from this SDK and what 6 | developers like about other SDKs in the ecosystem to directly work with the 7 | [Firebase SDK](https://firebase.google.com/docs/vertex-ai). We don't plan to add 8 | anything to this SDK or make any further changes. We know how disruptive an SDK 9 | change can be and don't take this change lightly, but our goal is to create an 10 | extremely simple and clear path for developers to build with our models so it 11 | felt necessary to make this change. 12 | 13 | Thank you for building with Gemini and 14 | [let us know](https://discuss.ai.google.dev/c/gemini-api/4) if you need any 15 | help! 16 | -------------------------------------------------------------------------------- /pkgs/google_generative_ai/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:lints/recommended.yaml 2 | 3 | analyzer: 4 | language: 5 | strict-casts: true 6 | strict-inference: true 7 | strict-raw-types: true 8 | 9 | linter: 10 | rules: 11 | # consistency 12 | - directives_ordering 13 | - omit_local_variable_types 14 | - prefer_final_locals 15 | - prefer_final_in_for_each 16 | - prefer_relative_imports 17 | - prefer_single_quotes 18 | - sort_pub_dependencies 19 | - unnecessary_library_directive 20 | 21 | # correctness 22 | - always_declare_return_types 23 | - avoid_catching_errors 24 | - avoid_dynamic_calls 25 | - only_throw_errors 26 | - test_types_in_equals 27 | - throw_in_finally 28 | - type_annotate_public_apis 29 | - unawaited_futures 30 | 31 | # documentation related 32 | - comment_references 33 | -------------------------------------------------------------------------------- /pkgs/google_generative_ai/lib/google_generative_ai.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2024 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | /// Google generative AI SDK API bindings for Dart. 16 | /// 17 | /// The Google Generative AI SDK for Dart allows developers to use 18 | /// state-of-the-art Large Language Models (LLMs) to build applications. 19 | /// 20 | /// Most uses of this library will be through a [GenerativeModel]. 21 | /// Here's a simple example of using this API: 22 | /// 23 | /// ```dart 24 | /// const apiKey = ...; 25 | /// 26 | /// void main() async { 27 | /// final model = GenerativeModel( 28 | /// model: 'gemini-1.5-flash-latest', 29 | /// apiKey: apiKey, 30 | /// ); 31 | /// 32 | /// final prompt = 'Write a story about a magic backpack.'; 33 | /// final content = [Content.text(prompt)]; 34 | /// final response = await model.generateContent(content); 35 | /// 36 | /// print(response.text); 37 | /// }; 38 | /// ``` 39 | library; 40 | 41 | import 'src/model.dart'; 42 | 43 | export 'src/api.dart' 44 | show 45 | BatchEmbedContentsResponse, 46 | BlockReason, 47 | Candidate, 48 | CitationMetadata, 49 | CitationSource, 50 | ContentEmbedding, 51 | CountTokensResponse, 52 | EmbedContentRequest, 53 | EmbedContentResponse, 54 | FinishReason, 55 | GenerateContentResponse, 56 | GenerationConfig, 57 | HarmBlockThreshold, 58 | HarmCategory, 59 | HarmProbability, 60 | PromptFeedback, 61 | SafetyRating, 62 | SafetySetting, 63 | TaskType, 64 | UsageMetadata; 65 | export 'src/chat.dart' show ChatSession, StartChatExtension; 66 | export 'src/content.dart' 67 | show 68 | CodeExecutionResult, 69 | Content, 70 | DataPart, 71 | ExecutableCode, 72 | FilePart, 73 | FunctionCall, 74 | FunctionResponse, 75 | Language, 76 | Outcome, 77 | Part, 78 | TextPart; 79 | export 'src/error.dart' 80 | show 81 | GenerativeAIException, 82 | GenerativeAISdkException, 83 | InvalidApiKey, 84 | ServerException, 85 | UnsupportedUserLocation; 86 | export 'src/function_calling.dart' 87 | show 88 | CodeExecution, 89 | FunctionCallingConfig, 90 | FunctionCallingMode, 91 | FunctionDeclaration, 92 | Schema, 93 | SchemaType, 94 | Tool, 95 | ToolConfig; 96 | export 'src/model.dart' show GenerativeModel, RequestOptions; 97 | -------------------------------------------------------------------------------- /pkgs/google_generative_ai/lib/src/chat.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2024 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | import 'dart:async'; 16 | 17 | import 'api.dart'; 18 | import 'content.dart'; 19 | import 'model.dart'; 20 | import 'utils/mutex.dart'; 21 | 22 | /// A back-and-forth chat with a generative model. 23 | /// 24 | /// Records messages sent and received in [history]. The history will always 25 | /// record the content from the first candidate in the 26 | /// [GenerateContentResponse], other candidates may be available on the returned 27 | /// response. 28 | final class ChatSession { 29 | final Future Function(Iterable content, 30 | {List? safetySettings, 31 | GenerationConfig? generationConfig}) _generateContent; 32 | final Stream Function(Iterable content, 33 | {List? safetySettings, 34 | GenerationConfig? generationConfig}) _generateContentStream; 35 | 36 | final _mutex = Mutex(); 37 | 38 | final List _history; 39 | final List? _safetySettings; 40 | final GenerationConfig? _generationConfig; 41 | 42 | ChatSession._(this._generateContent, this._generateContentStream, 43 | this._history, this._safetySettings, this._generationConfig); 44 | 45 | /// The content that has been successfully sent to, or received from, the 46 | /// generative model. 47 | /// 48 | /// If there are outstanding requests from calls to [sendMessage] or 49 | /// [sendMessageStream], these will not be reflected in the history. 50 | /// Messages without a candidate in the response are not recorded in history, 51 | /// including the message sent to the model. 52 | Iterable get history => _history.skip(0); 53 | 54 | /// Sends [message] to the model as a continuation of the chat [history]. 55 | /// 56 | /// Prepends the history to the request and uses the provided model to 57 | /// generate new content. 58 | /// 59 | /// When there are no candidates in the response, the [message] and response 60 | /// are ignored and will not be recorded in the [history]. 61 | /// 62 | /// Waits for any ongoing or pending requests to [sendMessage] or 63 | /// [sendMessageStream] to complete before generating new content. 64 | /// Successful messages and responses for ongoing or pending requests will 65 | /// be reflected in the history sent for this message. 66 | Future sendMessage(Content message) async { 67 | final lock = await _mutex.acquire(); 68 | try { 69 | final response = await _generateContent(_history.followedBy([message]), 70 | safetySettings: _safetySettings, generationConfig: _generationConfig); 71 | if (response.candidates case [final candidate, ...]) { 72 | _history.add(message); 73 | final normalizedContent = candidate.content.role == null 74 | ? Content('model', candidate.content.parts) 75 | : candidate.content; 76 | _history.add(normalizedContent); 77 | } 78 | return response; 79 | } finally { 80 | lock.release(); 81 | } 82 | } 83 | 84 | /// Continues the chat with a new [message]. 85 | /// 86 | /// Sends [message] to the model as a continuation of the chat [history] and 87 | /// reads the response in a stream. 88 | /// Prepends the history to the request and uses the provided model to 89 | /// generate new content. 90 | /// 91 | /// When there are no candidates in any response in the stream, the [message] 92 | /// and responses are ignored and will not be recorded in the [history]. 93 | /// 94 | /// Waits for any ongoing or pending requests to [sendMessage] or 95 | /// [sendMessageStream] to complete before generating new content. 96 | /// Successful messages and responses for ongoing or pending requests will 97 | /// be reflected in the history sent for this message. 98 | /// 99 | /// Waits to read the entire streamed response before recording the message 100 | /// and response and allowing pending messages to be sent. 101 | Stream sendMessageStream(Content message) { 102 | final controller = StreamController(sync: true); 103 | _mutex.acquire().then((lock) async { 104 | try { 105 | final responses = _generateContentStream(_history.followedBy([message]), 106 | safetySettings: _safetySettings, 107 | generationConfig: _generationConfig); 108 | final content = []; 109 | await for (final response in responses) { 110 | if (response.candidates case [final candidate, ...]) { 111 | content.add(candidate.content); 112 | } 113 | controller.add(response); 114 | } 115 | if (content.isNotEmpty) { 116 | _history.add(message); 117 | _history.add(_aggregate(content)); 118 | } 119 | } catch (e, s) { 120 | controller.addError(e, s); 121 | } 122 | lock.release(); 123 | unawaited(controller.close()); 124 | }); 125 | return controller.stream; 126 | } 127 | 128 | /// Aggregates a list of [Content] responses into a single [Content]. 129 | /// 130 | /// Includes all the [Content.parts] of every element of [contents], 131 | /// and concatenates adjacent [TextPart]s into a single [TextPart], 132 | /// even across adjacent [Content]s. 133 | Content _aggregate(List contents) { 134 | assert(contents.isNotEmpty); 135 | final role = contents.first.role ?? 'model'; 136 | final textBuffer = StringBuffer(); 137 | // If non-null, only a single text part has been seen. 138 | TextPart? previousText; 139 | final parts = []; 140 | void addBufferedText() { 141 | if (textBuffer.isEmpty) return; 142 | if (previousText case final singleText?) { 143 | parts.add(singleText); 144 | previousText = null; 145 | } else { 146 | parts.add(TextPart(textBuffer.toString())); 147 | } 148 | textBuffer.clear(); 149 | } 150 | 151 | for (final content in contents) { 152 | for (final part in content.parts) { 153 | if (part case TextPart(:final text)) { 154 | if (text.isNotEmpty) { 155 | previousText = textBuffer.isEmpty ? part : null; 156 | textBuffer.write(text); 157 | } 158 | } else { 159 | addBufferedText(); 160 | parts.add(part); 161 | } 162 | } 163 | } 164 | addBufferedText(); 165 | return Content(role, parts); 166 | } 167 | } 168 | 169 | extension StartChatExtension on GenerativeModel { 170 | /// Starts a [ChatSession] that will use this model to respond to messages. 171 | /// 172 | /// ```dart 173 | /// final chat = model.startChat(); 174 | /// final response = await chat.sendMessage(Content.text('Hello there.')); 175 | /// print(response.text); 176 | /// ``` 177 | ChatSession startChat( 178 | {List? history, 179 | List? safetySettings, 180 | GenerationConfig? generationConfig}) => 181 | ChatSession._(generateContent, generateContentStream, history ?? [], 182 | safetySettings, generationConfig); 183 | } 184 | -------------------------------------------------------------------------------- /pkgs/google_generative_ai/lib/src/client.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2024 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | import 'dart:async'; 16 | import 'dart:convert'; 17 | 18 | import 'package:http/http.dart' as http; 19 | 20 | import 'error.dart'; 21 | import 'version.dart'; 22 | 23 | const clientName = 'genai-dart/$packageVersion'; 24 | 25 | abstract interface class ApiClient { 26 | Future> makeRequest(Uri uri, Map body); 27 | Stream> streamRequest( 28 | Uri uri, Map body); 29 | } 30 | 31 | // Encodes first by `json.encode`, then `utf8.encode`. 32 | // Decodes first by `utf8.decode`, then `json.decode`. 33 | final _utf8Json = json.fuse(utf8); 34 | 35 | final class HttpApiClient implements ApiClient { 36 | final String _apiKey; 37 | final http.Client? _httpClient; 38 | 39 | final FutureOr> Function()? _requestHeaders; 40 | 41 | HttpApiClient( 42 | {required String apiKey, 43 | http.Client? httpClient, 44 | FutureOr> Function()? requestHeaders}) 45 | : _apiKey = apiKey, 46 | _httpClient = httpClient, 47 | _requestHeaders = requestHeaders; 48 | 49 | Future> _headers() async => { 50 | 'x-goog-api-key': _apiKey, 51 | 'x-goog-api-client': clientName, 52 | 'Content-Type': 'application/json', 53 | if (_requestHeaders case final requestHeaders?) 54 | ...(await requestHeaders()), 55 | }; 56 | 57 | @override 58 | Future> makeRequest( 59 | Uri uri, Map body) async { 60 | final response = await (_httpClient?.post ?? http.post)( 61 | uri, 62 | headers: await _headers(), 63 | body: _utf8Json.encode(body), 64 | ); 65 | if (response.statusCode >= 500) { 66 | throw GenerativeAIException( 67 | 'Server Error [${response.statusCode}]: ${response.body}'); 68 | } 69 | 70 | return _utf8Json.decode(response.bodyBytes) as Map; 71 | } 72 | 73 | @override 74 | Stream> streamRequest( 75 | Uri uri, Map body) async* { 76 | uri = uri.replace(queryParameters: {'alt': 'sse'}); 77 | final request = http.Request('POST', uri) 78 | ..bodyBytes = _utf8Json.encode(body) 79 | ..headers.addAll(await _headers()); 80 | final response = await (_httpClient?.send(request) ?? request.send()); 81 | if (response.statusCode != 200) { 82 | final body = await response.stream.bytesToString(); 83 | // Yeild a potential error object like a normal result for consistency 84 | // with `makeRequest`. 85 | yield jsonDecode(body) as Map; 86 | return; 87 | } 88 | final lines = 89 | response.stream.toStringStream().transform(const LineSplitter()); 90 | await for (final line in lines) { 91 | const dataPrefix = 'data: '; 92 | if (line.startsWith(dataPrefix)) { 93 | final jsonText = line.substring(dataPrefix.length); 94 | yield jsonDecode(jsonText) as Map; 95 | } 96 | } 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /pkgs/google_generative_ai/lib/src/error.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2024 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | /// Exception thrown when generating content fails. 16 | /// 17 | /// The [message] may explain the cause of the failure. 18 | final class GenerativeAIException implements Exception { 19 | final String message; 20 | 21 | GenerativeAIException(this.message); 22 | 23 | @override 24 | String toString() => 'GenerativeAIException: $message'; 25 | } 26 | 27 | /// Exception thrown when the server rejects the API key. 28 | final class InvalidApiKey implements GenerativeAIException { 29 | @override 30 | final String message; 31 | 32 | InvalidApiKey(this.message); 33 | 34 | @override 35 | String toString() => message; 36 | } 37 | 38 | /// Exception thrown when the user location is unsupported. 39 | final class UnsupportedUserLocation implements GenerativeAIException { 40 | static const _message = 'User location is not supported for the API use.'; 41 | @override 42 | String get message => _message; 43 | } 44 | 45 | /// Exception thrown when the server failed to generate content. 46 | final class ServerException implements GenerativeAIException { 47 | @override 48 | final String message; 49 | 50 | ServerException(this.message); 51 | 52 | @override 53 | String toString() => message; 54 | } 55 | 56 | /// Exception indicating a stale package version or implementation bug. 57 | /// 58 | /// This exception indicates a likely problem with the SDK implementation such 59 | /// as an inability to parse a new response format. Resolution paths may include 60 | /// updating to a new version of the SDK, or filing an issue. 61 | final class GenerativeAISdkException implements Exception { 62 | final String message; 63 | 64 | GenerativeAISdkException(this.message); 65 | 66 | @override 67 | String toString() => '$message\n' 68 | 'This indicates a problem with the Google Generative AI SDK. ' 69 | 'Try updating to the latest version ' 70 | '(https://pub.dev/packages/google_generative_ai/versions), ' 71 | 'or file an issue at ' 72 | 'https://github.com/google-gemini/generative-ai-dart/issues.'; 73 | } 74 | 75 | GenerativeAIException parseError(Object jsonObject) { 76 | return switch (jsonObject) { 77 | { 78 | 'message': final String message, 79 | 'details': [{'reason': 'API_KEY_INVALID'}, ...] 80 | } => 81 | InvalidApiKey(message), 82 | {'message': UnsupportedUserLocation._message} => UnsupportedUserLocation(), 83 | {'message': final String message} => ServerException(message), 84 | _ => throw unhandledFormat('server error', jsonObject) 85 | }; 86 | } 87 | 88 | Exception unhandledFormat(String name, Object? jsonObject) => 89 | GenerativeAISdkException('Unhandled format for $name: $jsonObject'); 90 | -------------------------------------------------------------------------------- /pkgs/google_generative_ai/lib/src/utils/mutex.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2024 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | import 'dart:async'; 16 | import 'dart:collection' show Queue; 17 | 18 | /// Simple object to restrict simultaneous accesses to a resource. 19 | /// 20 | /// Cooperating code should acquire a lock on the mutex using [acquire], 21 | /// and only use a guarded resource while they have that lock (from the 22 | /// returned future completing with a [Lock] to calling [Lock.release] 23 | /// on that lock.) 24 | /// 25 | /// At most one active [Lock] object can exist for each [Mutex] at any time. 26 | class Mutex { 27 | /// Queue of pending lock acquisitions, and the current active lock. 28 | /// 29 | /// The already completed completer of the currently active lock 30 | /// is reatined at the head of the queue, and is removed when the 31 | /// lock is released. 32 | final Queue> _pending = Queue(); 33 | 34 | /// Acquire a lock on the mutex. 35 | /// 36 | /// The future will complete with an active [Lock] object 37 | /// after all prior calls to `acquire` have completed with an acquired lock, 38 | /// and [Lock.release] has been called on each of those locks. 39 | Future acquire() { 40 | final completer = Completer(); 41 | _pending.add(completer); 42 | if (_pending.length == 1) { 43 | // Is next in line to acquire lock. 44 | completer.complete(Lock._(this)); 45 | } 46 | return completer.future; 47 | } 48 | 49 | void _release() { 50 | assert(_pending.isNotEmpty); 51 | assert(_pending.first.isCompleted); 52 | _pending.removeFirst(); 53 | if (_pending.isNotEmpty) { 54 | _pending.first.complete(Lock._(this)); 55 | } 56 | } 57 | } 58 | 59 | /// A lock acquired against a [Mutex]. 60 | /// 61 | /// Can be released *once*. 62 | class Lock { 63 | Mutex? _mutex; 64 | Lock._(this._mutex); 65 | 66 | /// Release the lock on the mutex. 67 | /// 68 | /// The lock object no longer holds a lock on the mutex. 69 | void release() { 70 | final mutex = _mutex; 71 | if (mutex == null) throw StateError('Already released'); 72 | _mutex = null; 73 | mutex._release(); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /pkgs/google_generative_ai/lib/src/version.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2024 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | const packageVersion = '0.4.7'; 16 | -------------------------------------------------------------------------------- /pkgs/google_generative_ai/lib/src/vertex_hooks.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2024 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | /// Extra APIs to impelement the Vertex AI SDK. 16 | /// 17 | /// These APIs should not be exposed through the public libraries. 18 | library; 19 | 20 | export 'api.dart' 21 | show 22 | countTokensResponseFields, 23 | createCountTokensResponse, 24 | parseBatchEmbedContentsResponse, 25 | parseCountTokensResponse, 26 | parseEmbedContentResponse, 27 | parseGenerateContentResponse; 28 | export 'model.dart' show Task, VertexExtensions, createModelWithBaseUri; 29 | -------------------------------------------------------------------------------- /pkgs/google_generative_ai/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: google_generative_ai 2 | # Update `lib/version.dart` when changing version. 3 | version: 0.4.7 4 | description: >- 5 | The Google AI Dart SDK enables developers to use Google's state-of-the-art 6 | generative AI models (like Gemini). 7 | repository: https://github.com/google-gemini/generative-ai-dart/tree/main/pkgs/google_generative_ai 8 | 9 | environment: 10 | sdk: ^3.1.0 11 | 12 | dependencies: 13 | http: ^1.1.0 14 | 15 | dev_dependencies: 16 | lints: ^4.0.0 17 | matcher: ^0.12.16 18 | test: ^1.24.0 19 | yaml: ^3.1.0 20 | -------------------------------------------------------------------------------- /pkgs/google_generative_ai/test/chat_test.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2024 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | import 'package:google_generative_ai/google_generative_ai.dart'; 16 | import 'package:google_generative_ai/src/model.dart'; 17 | import 'package:test/test.dart'; 18 | 19 | import 'utils/matchers.dart'; 20 | import 'utils/stub_client.dart'; 21 | 22 | void main() { 23 | group('Chat', () { 24 | const defaultModelName = 'some-model'; 25 | 26 | (ClientController, GenerativeModel) createModel([ 27 | String modelName = defaultModelName, 28 | ]) { 29 | final client = ClientController(); 30 | final model = createModelWithClient( 31 | model: modelName, 32 | client: client.client, 33 | ); 34 | return (client, model); 35 | } 36 | 37 | test('includes chat history in prompt', () async { 38 | final (client, model) = createModel('models/$defaultModelName'); 39 | final chat = model.startChat(history: [ 40 | Content.text('Hi!'), 41 | Content.model([TextPart('Hello, how can I help you today?')]), 42 | ]); 43 | final prompt = 'Some prompt'; 44 | final response = await client.checkRequest( 45 | () => chat.sendMessage(Content.text(prompt)), 46 | verifyRequest: (_, request) { 47 | final contents = request['contents']; 48 | expect(contents, hasLength(3)); 49 | }, 50 | response: arbitraryGenerateContentResponse, 51 | ); 52 | expect( 53 | chat.history.last, 54 | matchesContent(response.candidates.first.content), 55 | ); 56 | }); 57 | 58 | test('forwards safety settings', () async { 59 | final (client, model) = createModel('models/$defaultModelName'); 60 | final chat = model.startChat(safetySettings: [ 61 | SafetySetting(HarmCategory.dangerousContent, HarmBlockThreshold.high), 62 | ]); 63 | final prompt = 'Some prompt'; 64 | await client.checkRequest( 65 | () => chat.sendMessage(Content.text(prompt)), 66 | verifyRequest: (_, request) { 67 | expect(request['safetySettings'], [ 68 | { 69 | 'category': 'HARM_CATEGORY_DANGEROUS_CONTENT', 70 | 'threshold': 'BLOCK_ONLY_HIGH', 71 | }, 72 | ]); 73 | }, 74 | response: arbitraryGenerateContentResponse, 75 | ); 76 | }); 77 | 78 | test('forwards safety settings and config when streaming', () async { 79 | final (client, model) = createModel('models/$defaultModelName'); 80 | final chat = model.startChat(safetySettings: [ 81 | SafetySetting(HarmCategory.dangerousContent, HarmBlockThreshold.high), 82 | ], generationConfig: GenerationConfig(stopSequences: ['a'])); 83 | final prompt = 'Some prompt'; 84 | final responses = await client.checkStreamRequest( 85 | () async => chat.sendMessageStream(Content.text(prompt)), 86 | verifyRequest: (_, request) { 87 | expect(request['safetySettings'], [ 88 | { 89 | 'category': 'HARM_CATEGORY_DANGEROUS_CONTENT', 90 | 'threshold': 'BLOCK_ONLY_HIGH', 91 | }, 92 | ]); 93 | }, 94 | responses: [arbitraryGenerateContentResponse], 95 | ); 96 | await responses.drain(); 97 | }); 98 | 99 | test('forwards generation config', () async { 100 | final (client, model) = createModel('models/$defaultModelName'); 101 | final chat = model.startChat( 102 | generationConfig: GenerationConfig(stopSequences: ['a']), 103 | ); 104 | final prompt = 'Some prompt'; 105 | await client.checkRequest( 106 | () => chat.sendMessage(Content.text(prompt)), 107 | verifyRequest: (_, request) { 108 | expect(request['generationConfig'], { 109 | 'stopSequences': ['a'], 110 | }); 111 | }, 112 | response: arbitraryGenerateContentResponse, 113 | ); 114 | }); 115 | }); 116 | } 117 | -------------------------------------------------------------------------------- /pkgs/google_generative_ai/test/http_api_client_test.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2024 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | import 'dart:convert'; 16 | 17 | import 'package:google_generative_ai/src/client.dart'; 18 | import 'package:http/http.dart' as http; 19 | import 'package:http/testing.dart'; 20 | import 'package:test/test.dart'; 21 | 22 | import 'utils/matchers.dart'; 23 | 24 | void main() { 25 | group('HttpApiClient', () { 26 | test('can make unary request with default client', () async { 27 | final url = Uri.parse('https://someurl.com'); 28 | final body = {'some': 'body'}; 29 | final apiKey = 'apiKey'; 30 | final expectedResponse = {'result': 'OK'}; 31 | await http.runWithClient( 32 | () async { 33 | final client = HttpApiClient(apiKey: apiKey); 34 | final response = await client.makeRequest(url, body); 35 | expect(response, expectedResponse); 36 | }, 37 | () => MockClient((request) async { 38 | expect( 39 | request, 40 | matchesRequest( 41 | http.Request('POST', url) 42 | ..headers.addAll({ 43 | 'x-goog-api-key': apiKey, 44 | 'x-goog-api-client': clientName, 45 | 'Content-Type': 'application/json', 46 | }) 47 | ..bodyBytes = utf8.encode(jsonEncode(body)), 48 | ), 49 | ); 50 | return http.Response.bytes( 51 | utf8.encode(jsonEncode(expectedResponse)), 52 | 200, 53 | ); 54 | }), 55 | ); 56 | }); 57 | 58 | test('can make unary request with custom client', () async { 59 | final url = Uri.parse('https://someurl.com'); 60 | final body = {'some': 'body'}; 61 | final apiKey = 'apiKey'; 62 | final expectedResponse = {'result': 'OK'}; 63 | final httpClient = MockClient((request) async { 64 | expect( 65 | request, 66 | matchesRequest( 67 | http.Request('POST', url) 68 | ..headers.addAll({ 69 | 'x-goog-api-key': apiKey, 70 | 'x-goog-api-client': clientName, 71 | 'Content-Type': 'application/json', 72 | }) 73 | ..bodyBytes = utf8.encode(jsonEncode(body)), 74 | ), 75 | ); 76 | return http.Response.bytes( 77 | utf8.encode(jsonEncode(expectedResponse)), 78 | 200, 79 | ); 80 | }); 81 | final client = HttpApiClient(apiKey: apiKey, httpClient: httpClient); 82 | final response = await client.makeRequest(url, body); 83 | expect(response, expectedResponse); 84 | }); 85 | 86 | test('can make streaming request with default client', () async { 87 | final url = Uri.parse('https://someurl.com'); 88 | final streamingUrl = Uri.parse('https://someurl.com?alt=sse'); 89 | final body = {'some': 'body'}; 90 | final apiKey = 'apiKey'; 91 | final expectedResponses = [ 92 | {'first': 'OK'}, 93 | {'second': 'OK'}, 94 | ]; 95 | await http.runWithClient( 96 | () async { 97 | final client = HttpApiClient(apiKey: apiKey); 98 | final response = client.streamRequest(url, body); 99 | await expectLater( 100 | response, 101 | emitsInOrder([...expectedResponses, emitsDone]), 102 | ); 103 | }, 104 | () => MockClient.streaming((request, requestStream) async { 105 | expect( 106 | request, 107 | matchesBaseRequest( 108 | http.Request('POST', streamingUrl) 109 | ..headers.addAll({ 110 | 'x-goog-api-key': apiKey, 111 | 'x-goog-api-client': clientName, 112 | 'Content-Type': 'application/json', 113 | }), 114 | ), 115 | ); 116 | expect( 117 | requestStream, 118 | emitsInOrder([utf8.encode(jsonEncode(body)), emitsDone]), 119 | ); 120 | return http.StreamedResponse( 121 | Stream.fromIterable( 122 | expectedResponses, 123 | ).map((r) => utf8.encode('data: ${jsonEncode(r)}\n')), 124 | 200, 125 | ); 126 | }), 127 | ); 128 | }); 129 | 130 | test('can make streaming request with custom client', () async { 131 | final url = Uri.parse('https://someurl.com'); 132 | final streamingUrl = Uri.parse('https://someurl.com?alt=sse'); 133 | final body = {'some': 'body'}; 134 | final apiKey = 'apiKey'; 135 | final expectedResponses = [ 136 | {'first': 'OK'}, 137 | {'second': 'OK'}, 138 | ]; 139 | final httpClient = MockClient.streaming((request, requestStream) async { 140 | expect( 141 | request, 142 | matchesBaseRequest( 143 | http.Request('POST', streamingUrl) 144 | ..headers.addAll({ 145 | 'x-goog-api-key': apiKey, 146 | 'x-goog-api-client': clientName, 147 | 'Content-Type': 'application/json', 148 | }), 149 | ), 150 | ); 151 | expect( 152 | requestStream, 153 | emitsInOrder([utf8.encode(jsonEncode(body)), emitsDone]), 154 | ); 155 | return http.StreamedResponse( 156 | Stream.fromIterable( 157 | expectedResponses, 158 | ).map((r) => utf8.encode('data: ${jsonEncode(r)}\n')), 159 | 200, 160 | ); 161 | }); 162 | final client = HttpApiClient(apiKey: apiKey, httpClient: httpClient); 163 | final response = client.streamRequest(url, body); 164 | await expectLater( 165 | response, 166 | emitsInOrder([...expectedResponses, emitsDone]), 167 | ); 168 | }); 169 | 170 | test('parses non-SSE JSON error object at the top level', () async { 171 | final url = Uri.parse('https://someurl.com'); 172 | final streamingUrl = Uri.parse('https://someurl.com?alt=sse'); 173 | final body = {'some': 'body'}; 174 | final apiKey = 'apiKey'; 175 | final expectedError = { 176 | 'error': {'message': 'User location is not supported for the API use.'}, 177 | }; 178 | await http.runWithClient( 179 | () async { 180 | final client = HttpApiClient(apiKey: apiKey); 181 | final response = client.streamRequest(url, body); 182 | await expectLater(response, emitsInOrder([expectedError, emitsDone])); 183 | }, 184 | () => MockClient.streaming((request, requestStream) async { 185 | expect( 186 | request, 187 | matchesBaseRequest( 188 | http.Request('POST', streamingUrl) 189 | ..headers.addAll({ 190 | 'x-goog-api-key': apiKey, 191 | 'x-goog-api-client': clientName, 192 | 'Content-Type': 'application/json', 193 | }), 194 | ), 195 | ); 196 | return http.StreamedResponse( 197 | // No "data: " prefix 198 | Stream.value(utf8.encode(jsonEncode(expectedError))), 199 | 400, 200 | ); 201 | }), 202 | ); 203 | }); 204 | }); 205 | } 206 | -------------------------------------------------------------------------------- /pkgs/google_generative_ai/test/utils/matchers.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2024 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | import 'package:google_generative_ai/google_generative_ai.dart'; 16 | import 'package:http/http.dart' as http; 17 | import 'package:matcher/matcher.dart'; 18 | 19 | Matcher matchesPart(Part part) => switch (part) { 20 | TextPart(text: final text) => 21 | isA().having((p) => p.text, 'text', text), 22 | DataPart(mimeType: final mimeType, bytes: final bytes) => isA() 23 | .having((p) => p.mimeType, 'mimeType', mimeType) 24 | .having((p) => p.bytes, 'bytes', bytes), 25 | FilePart(uri: final uri) => 26 | isA().having((p) => p.uri, 'uri', uri), 27 | FunctionCall(name: final name, args: final args) => isA() 28 | .having((p) => p.name, 'name', name) 29 | .having((p) => p.args, 'args', args), 30 | FunctionResponse(name: final name, response: final response) => 31 | isA() 32 | .having((p) => p.name, 'name', name) 33 | .having((p) => p.response, 'args', response), 34 | ExecutableCode(language: final language, code: final code) => 35 | isA() 36 | .having((p) => p.language, 'language', language) 37 | .having((p) => p.code, 'code', code), 38 | CodeExecutionResult(outcome: final outcome, output: final output) => 39 | isA() 40 | .having((p) => p.outcome, 'outcome', outcome) 41 | .having((p) => p.output, 'output', output), 42 | _ => throw StateError('Unhandled Part type.'), 43 | }; 44 | 45 | Matcher matchesContent(Content content) => isA() 46 | .having((c) => c.role, 'role', content.role) 47 | .having((c) => c.parts, 'parts', content.parts.map(matchesPart).toList()); 48 | 49 | Matcher matchesCandidate(Candidate candidate) => isA().having( 50 | (c) => c.content, 51 | 'content', 52 | matchesContent(candidate.content), 53 | ); 54 | 55 | Matcher matchesGenerateContentResponse(GenerateContentResponse response) => 56 | isA() 57 | .having( 58 | (r) => r.candidates, 59 | 'candidates', 60 | response.candidates.map(matchesCandidate).toList(), 61 | ) 62 | .having( 63 | (r) => r.promptFeedback, 64 | 'promptFeedback', 65 | response.promptFeedback == null 66 | ? isNull 67 | : matchesPromptFeedback(response.promptFeedback!), 68 | ); 69 | 70 | Matcher matchesPromptFeedback( 71 | PromptFeedback promptFeedback, 72 | ) => 73 | isA() 74 | .having((p) => p.blockReason, 'blockReason', promptFeedback.blockReason) 75 | .having( 76 | (p) => p.blockReasonMessage, 77 | 'blockReasonMessage', 78 | promptFeedback.blockReasonMessage, 79 | ) 80 | .having( 81 | (p) => p.safetyRatings, 82 | 'safetyRatings', 83 | unorderedMatches( 84 | promptFeedback.safetyRatings.map(matchesSafetyRating)), 85 | ); 86 | 87 | Matcher matchesSafetyRating(SafetyRating safetyRating) => isA() 88 | .having((s) => s.category, 'category', safetyRating.category) 89 | .having((s) => s.probability, 'probability', safetyRating.probability); 90 | 91 | Matcher matchesEmbedding(ContentEmbedding embedding) => 92 | isA().having((e) => e.values, 'values', embedding.values); 93 | 94 | Matcher matchesEmbedContentResponse(EmbedContentResponse response) => 95 | isA().having( 96 | (r) => r.embedding, 97 | 'embedding', 98 | matchesEmbedding(response.embedding), 99 | ); 100 | 101 | Matcher matchesBatchEmbedContentsResponse( 102 | BatchEmbedContentsResponse response, 103 | ) => 104 | isA().having( 105 | (r) => r.embeddings, 106 | 'embeddings', 107 | response.embeddings.map(matchesEmbedding), 108 | ); 109 | 110 | Matcher matchesCountTokensResponse(CountTokensResponse response) => 111 | isA().having( 112 | (r) => r.totalTokens, 113 | 'totalTokens', 114 | response.totalTokens, 115 | ); 116 | 117 | Matcher matchesRequest(http.Request request) => isA() 118 | .having((r) => r.headers, 'headers', request.headers) 119 | .having((r) => r.method, 'method', request.method) 120 | .having((r) => r.bodyBytes, 'bodyBytes', request.bodyBytes) 121 | .having((r) => r.url, 'url', request.url); 122 | 123 | Matcher matchesBaseRequest(http.BaseRequest request) => isA() 124 | .having((r) => r.headers, 'headers', request.headers) 125 | .having((r) => r.method, 'method', request.method) 126 | .having((r) => r.url, 'url', request.url); 127 | -------------------------------------------------------------------------------- /pkgs/google_generative_ai/test/utils/stub_client.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2024 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | import 'dart:collection'; 16 | 17 | import 'package:google_generative_ai/src/client.dart'; 18 | 19 | class ClientController { 20 | final _client = _ControlledClient(); 21 | ApiClient get client => _client; 22 | 23 | /// Run [body] and return [response] for a single call to 24 | /// [ApiClient.streamRequest]. 25 | /// 26 | /// Check expectations for the request URI and JSON payload with the 27 | /// [verifyRequest] callback. 28 | Future checkRequest( 29 | Future Function() body, { 30 | required Map response, 31 | void Function(Uri, Map)? verifyRequest, 32 | }) async { 33 | _client._requestExpectations.addLast(verifyRequest); 34 | _client._responses.addLast([response]); 35 | final result = await body(); 36 | assert(_client._responses.isEmpty); 37 | return result; 38 | } 39 | 40 | /// Run [body] and return [responses] for a single call to 41 | /// [ApiClient.streamRequest]. 42 | /// 43 | /// Check expectations for the request URI and JSON payload with the 44 | /// [verifyRequest] callback. 45 | Future checkStreamRequest( 46 | Future Function() body, { 47 | required Iterable> responses, 48 | void Function(Uri, Map)? verifyRequest, 49 | }) async { 50 | _client._requestExpectations.addLast(verifyRequest); 51 | _client._responses.addLast(responses.toList()); 52 | final result = await body(); 53 | assert(_client._responses.isEmpty); 54 | return result; 55 | } 56 | } 57 | 58 | final class _ControlledClient implements ApiClient { 59 | final _requestExpectations = 60 | Queue)?>(); 61 | final _responses = Queue>>(); 62 | 63 | @override 64 | Future> makeRequest( 65 | Uri uri, 66 | Map body, 67 | ) async { 68 | _requestExpectations.removeFirst()?.call(uri, body); 69 | return _responses.removeFirst().single; 70 | } 71 | 72 | @override 73 | Stream> streamRequest( 74 | Uri uri, 75 | Map body, 76 | ) { 77 | _requestExpectations.removeFirst()?.call(uri, body); 78 | return Stream.fromIterable(_responses.removeFirst()); 79 | } 80 | } 81 | 82 | const Map arbitraryGenerateContentResponse = { 83 | 'candidates': [ 84 | { 85 | 'content': { 86 | 'role': 'model', 87 | 'parts': [ 88 | {'text': 'Some Response'}, 89 | ], 90 | }, 91 | }, 92 | ], 93 | }; 94 | -------------------------------------------------------------------------------- /pkgs/google_generative_ai/tool/validate_version.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2024 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | import 'dart:io'; 16 | 17 | import 'package:google_generative_ai/src/version.dart'; 18 | import 'package:yaml/yaml.dart' as yaml; 19 | 20 | void main(List args) { 21 | final pubspecVersion = _parsePubspecVersion(); 22 | final sourceCodeVersion = packageVersion; 23 | 24 | if (pubspecVersion == sourceCodeVersion) { 25 | stdout.writeln( 26 | 'pubspec.yaml version and lib/src/version.dart version agree.'); 27 | } else { 28 | stderr.writeln( 29 | "pubspec.yaml version and lib/src/version.dart version don't agree."); 30 | stderr.writeln(); 31 | stderr.writeln('pubspec.yaml: $pubspecVersion'); 32 | stderr.writeln('lib/src/version.dart: $sourceCodeVersion'); 33 | stderr.writeln(); 34 | stderr.writeln('When updating the pubspec version, please also update ' 35 | 'the version string in lib/src/version.dart.'); 36 | exit(1); 37 | } 38 | } 39 | 40 | String _parsePubspecVersion() { 41 | final pubspec = File('pubspec.yaml'); 42 | final contents = yaml.loadYaml(pubspec.readAsStringSync()); 43 | return (contents as Map)['version'] as String; 44 | } 45 | -------------------------------------------------------------------------------- /samples/dart/README.md: -------------------------------------------------------------------------------- 1 | [![samples](https://github.com/google/generative-ai-dart/actions/workflows/samples.yml/badge.svg)](https://github.com/google/generative-ai-dart/actions/workflows/samples.yml) 2 | 3 | ## Getting started 4 | 5 | To try these samples out, follow these steps: 6 | 7 | - To use the Gemini API, you'll need an API key. If you don't already have one, 8 | create a key in Google AI Studio: https://aistudio.google.com/app/apikey. 9 | - Export a `$GEMINI_API_KEY` environment variable with an API key with access to 10 | the Gemini generative models, or run the below commands with an environment 11 | containing this variable. 12 | - Run any sample from the `bin` directory (e.g., `dart bin/simple_text.dart`). 13 | 14 | ## Contents 15 | 16 | | File | Description | 17 | |----------------------------------------------------------------| ----------- | 18 | | [chat.dart](bin/chat.dart) | Multi-turn chat conversations | 19 | | [code_execution.dart](bin/code_execution.dart) | Executing code | 20 | | [controlled_generation.dart](bin/controlled_generation.dart) | Generating content with output constraints (e.g. JSON mode) | 21 | | [count_tokens.dart](bin/count_tokens.dart) | Counting input and output tokens | 22 | | [function_calling.dart](bin/function_calling.dart) | Using function calling | 23 | | [safety_settings.dart](bin/safety_settings.dart) | Setting and using safety controls | 24 | | [system_instruction.dart](bin/system_instruction.dart) | Setting system instructions | 25 | | [text_generation.dart](bin/text_generation.dart) | Generating text | 26 | -------------------------------------------------------------------------------- /samples/dart/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:lints/recommended.yaml 2 | -------------------------------------------------------------------------------- /samples/dart/bin/advanced_chat.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2024 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | import 'dart:io'; 16 | 17 | import 'package:google_generative_ai/google_generative_ai.dart'; 18 | 19 | Future main() async { 20 | final apiKey = Platform.environment['GEMINI_API_KEY']; 21 | if (apiKey == null) { 22 | stderr.writeln(r'No $GEMINI_API_KEY environment variable'); 23 | exit(1); 24 | } 25 | final model = GenerativeModel( 26 | model: 'gemini-1.5-flash-latest', 27 | apiKey: apiKey, 28 | generationConfig: GenerationConfig(maxOutputTokens: 100), 29 | ); 30 | final chat = model.startChat(history: [ 31 | Content.text('Hello, I have 2 dogs in my house.'), 32 | Content.model([TextPart('Great to meet you. What would you like to know?')]) 33 | ]); 34 | var message = 'How many paws are in my house?'; 35 | print('Message: $message'); 36 | var content = Content.text(message); 37 | var CountTokensResponse(:totalTokens) = 38 | await model.countTokens([...chat.history, content]); 39 | print('Token count: $totalTokens'); 40 | var response = await chat.sendMessage(content); 41 | print('Response: ${response.text}'); 42 | 43 | content = Content.text('How many noses (including mine)?'); 44 | CountTokensResponse(:totalTokens) = 45 | await model.countTokens([...chat.history, content]); 46 | print('Token count: $totalTokens'); 47 | response = await chat.sendMessage(content); 48 | print('Response: ${response.text}'); 49 | 50 | print('Chat history:'); 51 | for (final content in chat.history) { 52 | print('${content.role}:'); 53 | for (final part in content.parts) { 54 | switch (part) { 55 | case TextPart(:final text): 56 | print(text); 57 | case _: 58 | print('Non text content'); 59 | } 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /samples/dart/bin/advanced_text.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2024 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | import 'dart:io'; 16 | 17 | import 'package:google_generative_ai/google_generative_ai.dart'; 18 | 19 | void main() async { 20 | final apiKey = Platform.environment['GEMINI_API_KEY']; 21 | if (apiKey == null) { 22 | stderr.writeln(r'No $GEMINI_API_KEY environment variable'); 23 | exit(1); 24 | } 25 | final model = GenerativeModel( 26 | model: 'gemini-1.5-flash-latest', 27 | apiKey: apiKey, 28 | safetySettings: [ 29 | SafetySetting(HarmCategory.sexuallyExplicit, HarmBlockThreshold.none) 30 | ]); 31 | final prompt = 'Please describe in detail the movie "Eyes wide shut"'; 32 | print('Prompt: $prompt'); 33 | final content = [Content.text(prompt)]; 34 | final tokenCount = await model.countTokens(content); 35 | print('Token count: ${tokenCount.totalTokens}'); 36 | 37 | final responses = model.generateContentStream(content); 38 | await for (final response in responses) { 39 | if (response.usageMetadata case final usageMetadata?) { 40 | stdout.writeln('(Usage: prompt - ${usageMetadata.promptTokenCount}), ' 41 | 'candidates - ${usageMetadata.candidatesTokenCount}, ' 42 | 'total - ${usageMetadata.totalTokenCount}'); 43 | } 44 | stdout.write(response.text); 45 | } 46 | stdout.writeln(); 47 | } 48 | -------------------------------------------------------------------------------- /samples/dart/bin/advanced_text_and_image.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2024 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | import 'dart:io'; 16 | 17 | import 'package:google_generative_ai/google_generative_ai.dart'; 18 | 19 | import 'util/resource.dart'; 20 | 21 | void main() async { 22 | final apiKey = Platform.environment['GEMINI_API_KEY']; 23 | if (apiKey == null) { 24 | stderr.writeln(r'No $GEMINI_API_KEY environment variable'); 25 | exit(1); 26 | } 27 | final model = GenerativeModel( 28 | model: 'gemini-1.5-flash-latest', 29 | apiKey: apiKey, 30 | generationConfig: GenerationConfig(temperature: 0)); 31 | final prompt = 32 | 'What do you see? Use lists. Start with a headline for each image.'; 33 | print('Prompt: $prompt'); 34 | 35 | final (catBytes, sconeBytes) = await ( 36 | readResource('cat.jpg'), 37 | readResource('scones.jpg'), 38 | ).wait; 39 | final content = [ 40 | Content.multi([ 41 | TextPart(prompt), 42 | // The only accepted mime types are image/*. 43 | DataPart('image/jpeg', catBytes), 44 | DataPart('image/jpeg', sconeBytes), 45 | ]) 46 | ]; 47 | // final tokenCount = await model.countTokens(content); 48 | // print('Token count: ${tokenCount.totalTokens}'); 49 | 50 | final responses = model.generateContentStream(content); 51 | await for (final response in responses) { 52 | stdout.write(response.text); 53 | } 54 | stdout.writeln(); 55 | } 56 | -------------------------------------------------------------------------------- /samples/dart/bin/chat.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2024 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | import 'dart:io'; 16 | 17 | import 'package:google_generative_ai/google_generative_ai.dart'; 18 | 19 | final apiKey = () { 20 | final apiKey = Platform.environment['GEMINI_API_KEY']; 21 | if (apiKey == null) { 22 | stderr.writeln(r'No $GEMINI_API_KEY environment variable'); 23 | exit(1); 24 | } 25 | return apiKey; 26 | }(); 27 | 28 | Future chat() async { 29 | // [START chat] 30 | // Make sure to include this import: 31 | // import 'package:google_generative_ai/google_generative_ai.dart'; 32 | final model = GenerativeModel( 33 | model: 'gemini-1.5-flash', 34 | apiKey: apiKey, 35 | ); 36 | final chat = model.startChat(history: [ 37 | Content.text('hello'), 38 | Content.model([TextPart('Great to meet you. What would you like to know?')]) 39 | ]); 40 | var response = 41 | await chat.sendMessage(Content.text('I have 2 dogs in my house.')); 42 | print(response.text); 43 | response = 44 | await chat.sendMessage(Content.text('How many paws are in my house?')); 45 | print(response.text); 46 | // [END chat] 47 | } 48 | 49 | Future chatStreaming() async { 50 | // [START chat_streaming] 51 | // Make sure to include this import: 52 | // import 'package:google_generative_ai/google_generative_ai.dart'; 53 | final model = GenerativeModel( 54 | model: 'gemini-1.5-flash', 55 | apiKey: apiKey, 56 | ); 57 | final chat = model.startChat(history: [ 58 | Content.text('hello'), 59 | Content.model([TextPart('Great to meet you. What would you like to know?')]) 60 | ]); 61 | var responses = 62 | chat.sendMessageStream(Content.text('I have 2 dogs in my house.')); 63 | await for (final response in responses) { 64 | print(response.text); 65 | print('_' * 80); 66 | } 67 | responses = 68 | chat.sendMessageStream(Content.text('How many paws are in my house?')); 69 | await for (final response in responses) { 70 | print(response.text); 71 | print('_' * 80); 72 | } 73 | // [END chat_streaming] 74 | } 75 | 76 | Future chatStreamingWithImages() async { 77 | // [START chat_streaming_with_images] 78 | // Make sure to include this import: 79 | // import 'package:google_generative_ai/google_generative_ai.dart'; 80 | final model = GenerativeModel( 81 | model: 'gemini-1.5-flash', 82 | apiKey: apiKey, 83 | ); 84 | Future fileToPart(String mimeType, String path) async { 85 | return DataPart(mimeType, await File(path).readAsBytes()); 86 | } 87 | 88 | final chat = model.startChat(); 89 | var responses = chat.sendMessageStream(Content.text( 90 | "Hello, I'm interested in learning about musical instruments. " 91 | 'Can I show you one?')); 92 | await for (final response in responses) { 93 | print(response.text); 94 | print('_' * 80); 95 | } 96 | final prompt = 'What family of instruments does this belong to?'; 97 | final image = await fileToPart('image/jpeg', 'resources/organ.jpg'); 98 | responses = chat.sendMessageStream(Content.multi([TextPart(prompt), image])); 99 | await for (final response in responses) { 100 | print(response.text); 101 | print('_' * 80); 102 | } 103 | // [END chat_streaming_with_images] 104 | } 105 | 106 | void main() async { 107 | await chat(); 108 | await chatStreaming(); 109 | await chatStreamingWithImages(); 110 | } 111 | -------------------------------------------------------------------------------- /samples/dart/bin/code_execution.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2024 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | import 'dart:io'; 16 | 17 | import 'package:google_generative_ai/google_generative_ai.dart'; 18 | 19 | // Set up your API Key 20 | // 21 | // To use the Gemini API, you'll need an API key. 22 | // To learn more, see the "Set up your API Key" section in the Gemini API 23 | // quickstart: 24 | // https://ai.google.dev/gemini-api/docs/quickstart?lang=swift#set-up-api-key 25 | final apiKey = () { 26 | final apiKey = Platform.environment['GEMINI_API_KEY']; 27 | if (apiKey == null) { 28 | stderr.writeln(r'No $GEMINI_API_KEY environment variable'); 29 | exit(1); 30 | } 31 | return apiKey; 32 | }(); 33 | 34 | Future codeExecutionBasic() async { 35 | // [START code_execution_basic] 36 | // Make sure to include this import: 37 | // import 'package:google_generative_ai/google_generative_ai.dart'; 38 | final model = GenerativeModel( 39 | // Specify a Gemini model appropriate for your use case 40 | model: 'gemini-1.5-flash', 41 | apiKey: apiKey, 42 | tools: [Tool(codeExecution: CodeExecution())], 43 | ); 44 | final prompt = 'What is the sum of the first 50 prime numbers? ' 45 | 'Generate and run code for the calculation, and make sure you get ' 46 | 'all 50.'; 47 | 48 | final response = await model.generateContent([Content.text(prompt)]); 49 | print(response.text); 50 | // [END code_execution_basic] 51 | } 52 | 53 | Future codeExecutionChat() async { 54 | // [START code_execution_chat] 55 | // Make sure to include this import: 56 | // import 'package:google_generative_ai/google_generative_ai.dart'; 57 | final model = GenerativeModel( 58 | // Specify a Gemini model appropriate for your use case 59 | model: 'gemini-1.5-flash', 60 | apiKey: apiKey, 61 | tools: [Tool(codeExecution: CodeExecution())], 62 | ); 63 | final chat = model.startChat(); 64 | final prompt = 'What is the sum of the first 50 prime numbers? ' 65 | 'Generate and run code for the calculation, and make sure you get ' 66 | 'all 50.'; 67 | 68 | final response = await chat.sendMessage(Content.text(prompt)); 69 | print(response.text); 70 | // [END code_execution_chat] 71 | } 72 | 73 | void main() async { 74 | codeExecutionBasic(); 75 | codeExecutionChat(); 76 | } 77 | -------------------------------------------------------------------------------- /samples/dart/bin/configure_model_parameters.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2024 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | import 'dart:io'; 16 | 17 | import 'package:google_generative_ai/google_generative_ai.dart'; 18 | 19 | final apiKey = () { 20 | final apiKey = Platform.environment['GEMINI_API_KEY']; 21 | if (apiKey == null) { 22 | stderr.writeln(r'No $GEMINI_API_KEY environment variable'); 23 | exit(1); 24 | } 25 | return apiKey; 26 | }(); 27 | 28 | Future configureModelParameters() async { 29 | // [START configure_model_parameters] 30 | final model = GenerativeModel( 31 | model: 'gemini-1.5-flash', 32 | apiKey: apiKey, 33 | ); 34 | final prompt = 'Tell me a story about a magic backpack.'; 35 | 36 | final response = await model.generateContent( 37 | [Content.text(prompt)], 38 | generationConfig: GenerationConfig( 39 | candidateCount: 1, 40 | stopSequences: ['x'], 41 | maxOutputTokens: 20, 42 | temperature: 1.0, 43 | ), 44 | ); 45 | print(response.text); 46 | // [END configure_model_parameters] 47 | } 48 | 49 | void main() async { 50 | await configureModelParameters(); 51 | } 52 | -------------------------------------------------------------------------------- /samples/dart/bin/controlled_generation.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2024 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | import 'dart:io'; 16 | 17 | import 'package:google_generative_ai/google_generative_ai.dart'; 18 | 19 | final apiKey = () { 20 | final apiKey = Platform.environment['GEMINI_API_KEY']; 21 | if (apiKey == null) { 22 | stderr.writeln(r'No $GEMINI_API_KEY environment variable'); 23 | exit(1); 24 | } 25 | return apiKey; 26 | }(); 27 | 28 | Future jsonControlledGeneration() async { 29 | // [START json_controlled_generation] 30 | // Make sure to include this import: 31 | // import 'package:google_generative_ai/google_generative_ai.dart'; 32 | final schema = Schema.array( 33 | description: 'List of recipes', 34 | items: Schema.object(properties: { 35 | 'recipeName': 36 | Schema.string(description: 'Name of the recipe.', nullable: false) 37 | }, requiredProperties: [ 38 | 'recipeName' 39 | ])); 40 | 41 | final model = GenerativeModel( 42 | model: 'gemini-1.5-pro', 43 | apiKey: apiKey, 44 | generationConfig: GenerationConfig( 45 | responseMimeType: 'application/json', responseSchema: schema)); 46 | 47 | final prompt = 'List a few popular cookie recipes.'; 48 | final response = await model.generateContent([Content.text(prompt)]); 49 | print(response.text); 50 | // [END json_controlled_generation] 51 | } 52 | 53 | Future jsonNoSchema() async { 54 | // [START json_no_schema] 55 | // Make sure to include this import: 56 | // import 'package:google_generative_ai/google_generative_ai.dart'; 57 | final model = GenerativeModel( 58 | model: 'gemini-1.5-pro', 59 | apiKey: apiKey, 60 | generationConfig: GenerationConfig(responseMimeType: 'application/json')); 61 | 62 | final prompt = 'List a few popular cookie recipes using this JSON schema:\n\n' 63 | 'Recipe = {"recipeName": string}\n' 64 | 'Return: Array'; 65 | final response = await model.generateContent([Content.text(prompt)]); 66 | print(response.text); 67 | // [END json_no_schema] 68 | } 69 | 70 | void main() async { 71 | await jsonControlledGeneration(); 72 | await jsonNoSchema(); 73 | } 74 | -------------------------------------------------------------------------------- /samples/dart/bin/count_tokens.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2024 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | import 'dart:io'; 16 | 17 | import 'package:google_generative_ai/google_generative_ai.dart'; 18 | 19 | final apiKey = () { 20 | final apiKey = Platform.environment['GEMINI_API_KEY']; 21 | if (apiKey == null) { 22 | stderr.writeln(r'No $GEMINI_API_KEY environment variable'); 23 | exit(1); 24 | } 25 | return apiKey; 26 | }(); 27 | 28 | Future tokensTextOnly() async { 29 | // [START tokens_text_only] 30 | // Make sure to include this import: 31 | // import 'package:google_generative_ai/google_generative_ai.dart'; 32 | final model = GenerativeModel( 33 | model: 'gemini-1.5-flash', 34 | apiKey: apiKey, 35 | ); 36 | final prompt = 'The quick brown fox jumps over the lazy dog.'; 37 | final tokenCount = await model.countTokens([Content.text(prompt)]); 38 | print('Total tokens: ${tokenCount.totalTokens}'); 39 | // [END tokens_text_only] 40 | } 41 | 42 | Future tokensChat() async { 43 | // [START tokens_chat] 44 | // Make sure to include this import: 45 | // import 'package:google_generative_ai/google_generative_ai.dart'; 46 | final model = GenerativeModel( 47 | model: 'gemini-1.5-flash', 48 | apiKey: apiKey, 49 | ); 50 | final chat = model.startChat(history: [ 51 | Content.text('Hi my name is Bob'), 52 | Content.model([TextPart('Hi Bob!')]) 53 | ]); 54 | var tokenCount = await model.countTokens(chat.history); 55 | print('Total tokens: ${tokenCount.totalTokens}'); 56 | 57 | final response = await chat.sendMessage(Content.text( 58 | 'In one sentence, explain how a computer works to a young child.')); 59 | if (response.usageMetadata case final usage?) { 60 | print('Prompt: ${usage.promptTokenCount}, ' 61 | 'Candidates: ${usage.candidatesTokenCount}, ' 62 | 'Total: ${usage.totalTokenCount}'); 63 | } 64 | 65 | tokenCount = await model.countTokens( 66 | [...chat.history, Content.text('What is the meaning of life?')]); 67 | print('Total tokens: ${tokenCount.totalTokens}'); 68 | // [END tokens_chat] 69 | } 70 | 71 | Future tokensMultimodalImageInline() async { 72 | // [START tokens_multimodal_image_inline] 73 | // Make sure to include this import: 74 | // import 'package:google_generative_ai/google_generative_ai.dart'; 75 | final model = GenerativeModel( 76 | model: 'gemini-1.5-flash', 77 | apiKey: apiKey, 78 | ); 79 | 80 | Future fileToPart(String mimeType, String path) async { 81 | return DataPart(mimeType, await File(path).readAsBytes()); 82 | } 83 | 84 | final prompt = 'Tell me about this image'; 85 | final image = await fileToPart('image/jpeg', 'resources/organ.jpg'); 86 | final content = Content.multi([TextPart(prompt), image]); 87 | 88 | // An image's display size does not affet its token count. 89 | // Optionally, you can call `countTokens` for the prompt and file separately. 90 | final tokenCount = await model.countTokens([content]); 91 | print('Total tokens: ${tokenCount.totalTokens}'); 92 | 93 | final response = await model.generateContent([content]); 94 | if (response.usageMetadata case final usage?) { 95 | print('Prompt: ${usage.promptTokenCount}, ' 96 | 'Candidates: ${usage.candidatesTokenCount}, ' 97 | 'Total: ${usage.totalTokenCount}'); 98 | } 99 | // [END tokens_multimodal_image_inline] 100 | } 101 | 102 | Future tokensSystemInstructions() async { 103 | // [START tokens_system_instruction] 104 | // Make sure to include this import: 105 | // import 'package:google_generative_ai/google_generative_ai.dart'; 106 | var model = GenerativeModel( 107 | model: 'gemini-1.5-flash', 108 | apiKey: apiKey, 109 | ); 110 | final prompt = 'The quick brown fox jumps over the lazy dog.'; 111 | 112 | // The total token count includes everything sent in the `generateContent` 113 | // request. 114 | var tokenCount = await model.countTokens([Content.text(prompt)]); 115 | print('Total tokens: ${tokenCount.totalTokens}'); 116 | model = GenerativeModel( 117 | model: 'gemini-1.5-flash', 118 | apiKey: apiKey, 119 | systemInstruction: Content.system('You are a cat. Your name is Neko.'), 120 | ); 121 | tokenCount = await model.countTokens([Content.text(prompt)]); 122 | print('Total tokens: ${tokenCount.totalTokens}'); 123 | // [END tokens_system_instruction] 124 | } 125 | 126 | Future tokensTools() async { 127 | // [START tokens_tools] 128 | // Make sure to include this import: 129 | // import 'package:google_generative_ai/google_generative_ai.dart'; 130 | var model = GenerativeModel( 131 | model: 'gemini-1.5-flash', 132 | apiKey: apiKey, 133 | ); 134 | final prompt = 'I have 57 cats, each owns 44 mittens, ' 135 | 'how many mittens is that in total?'; 136 | 137 | // The total token count includes everything sent in the `generateContent` 138 | // request. 139 | var tokenCount = await model.countTokens([Content.text(prompt)]); 140 | print('Total tokens: ${tokenCount.totalTokens}'); 141 | final binaryFunction = Schema.object( 142 | properties: { 143 | 'a': Schema.number(nullable: false), 144 | 'b': Schema.number(nullable: false) 145 | }, 146 | requiredProperties: ['a', 'b'], 147 | ); 148 | 149 | model = GenerativeModel( 150 | model: 'gemini-1.5-flash', 151 | apiKey: apiKey, 152 | tools: [ 153 | Tool(functionDeclarations: [ 154 | FunctionDeclaration('add', 'returns a + b', binaryFunction), 155 | FunctionDeclaration('subtract', 'returns a - b', binaryFunction), 156 | FunctionDeclaration('multipley', 'returns a * b', binaryFunction), 157 | FunctionDeclaration('divide', 'returns a / b', binaryFunction) 158 | ]) 159 | ], 160 | ); 161 | tokenCount = await model.countTokens([Content.text(prompt)]); 162 | print('Total tokens: ${tokenCount.totalTokens}'); 163 | // [END tokens_tools] 164 | } 165 | 166 | void main() async { 167 | await tokensTextOnly(); 168 | await tokensChat(); 169 | await tokensMultimodalImageInline(); 170 | await tokensSystemInstructions(); 171 | await tokensTools(); 172 | } 173 | -------------------------------------------------------------------------------- /samples/dart/bin/function_calling.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2024 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | import 'dart:io'; 16 | 17 | import 'package:google_generative_ai/google_generative_ai.dart'; 18 | 19 | final apiKey = () { 20 | final apiKey = Platform.environment['GEMINI_API_KEY']; 21 | if (apiKey == null) { 22 | stderr.writeln(r'No $GEMINI_API_KEY environment variable'); 23 | exit(1); 24 | } 25 | return apiKey; 26 | }(); 27 | 28 | Future functionCalling() async { 29 | // [START function_calling] 30 | // Make sure to include this import: 31 | // import 'package:google_generative_ai/google_generative_ai.dart'; 32 | Map setLightValues(Map args) { 33 | return args; 34 | } 35 | 36 | final controlLightFunction = FunctionDeclaration( 37 | 'controlLight', 38 | 'Set the brightness and color temperature of a room light.', 39 | Schema.object(properties: { 40 | 'brightness': Schema.number( 41 | description: 42 | 'Light level from 0 to 100. Zero is off and 100 is full brightness.', 43 | nullable: false), 44 | 'colorTemperatur': Schema.string( 45 | description: 46 | 'Color temperature of the light fixture which can be `daylight`, `cool`, or `warm`', 47 | nullable: false), 48 | })); 49 | 50 | final functions = {controlLightFunction.name: setLightValues}; 51 | FunctionResponse dispatchFunctionCall(FunctionCall call) { 52 | final function = functions[call.name]!; 53 | final result = function(call.args); 54 | return FunctionResponse(call.name, result); 55 | } 56 | 57 | final model = GenerativeModel( 58 | model: 'gemini-1.5-pro', 59 | apiKey: apiKey, 60 | tools: [ 61 | Tool(functionDeclarations: [controlLightFunction]) 62 | ], 63 | ); 64 | 65 | final prompt = 'Dim the lights so the room feels cozy and warm.'; 66 | final content = [Content.text(prompt)]; 67 | var response = await model.generateContent(content); 68 | 69 | List functionCalls; 70 | while ((functionCalls = response.functionCalls.toList()).isNotEmpty) { 71 | var responses = [ 72 | for (final functionCall in functionCalls) 73 | dispatchFunctionCall(functionCall) 74 | ]; 75 | content 76 | ..add(response.candidates.first.content) 77 | ..add(Content.functionResponses(responses)); 78 | response = await model.generateContent(content); 79 | } 80 | print('Response: ${response.text}'); 81 | // [END function_calling] 82 | } 83 | 84 | void main() async { 85 | await functionCalling(); 86 | } 87 | -------------------------------------------------------------------------------- /samples/dart/bin/guessing_game.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2024 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | import 'dart:convert'; 16 | import 'dart:io'; 17 | 18 | import 'package:args/args.dart'; 19 | import 'package:google_generative_ai/google_generative_ai.dart'; 20 | 21 | Future> _generateWords(String apiKey, String subject) async { 22 | final config = GenerationConfig(candidateCount: 1, temperature: 1.0); 23 | final model = GenerativeModel( 24 | model: 'gemini-1.5-pro-latest', 25 | apiKey: apiKey, 26 | generationConfig: config, 27 | requestOptions: RequestOptions(apiVersion: 'v1beta'), 28 | ); 29 | final content = [Content.text('Create a list of 20 $subject.')]; 30 | 31 | final response = await model.generateContent( 32 | content, 33 | generationConfig: GenerationConfig( 34 | responseMimeType: 'application/json', 35 | responseSchema: Schema.array( 36 | items: Schema.string( 37 | description: 'A single word that a player will need to guess.', 38 | ), 39 | ), 40 | ), 41 | ); 42 | final words = jsonDecode(response.text!) as List; 43 | return [for (final word in words) word]; 44 | } 45 | 46 | Future> _generateHints( 47 | String apiKey, 48 | List words, 49 | ) async { 50 | final config = GenerationConfig(candidateCount: 1, temperature: 0.5); 51 | final model = GenerativeModel( 52 | model: 'gemini-1.5-pro-latest', 53 | apiKey: apiKey, 54 | generationConfig: config, 55 | requestOptions: RequestOptions(apiVersion: 'v1beta'), 56 | ); 57 | final content = [ 58 | Content.text( 59 | 'Create a list of descriptions for these words: $words. ' 60 | 'The descriptions should be in the same order as the words. ' 61 | 'The descriptions cannot use the word itself. ' 62 | 'The descriptions should make it easy to guess the word. ' 63 | 'Each description should be 3 words long.', 64 | ), 65 | ]; 66 | 67 | final response = await model.generateContent( 68 | content, 69 | generationConfig: GenerationConfig( 70 | responseMimeType: 'application/json', 71 | responseSchema: Schema.array( 72 | items: Schema.string( 73 | description: 'A 3 word description of some other hidden word.', 74 | ), 75 | ), 76 | ), 77 | ); 78 | final hints = jsonDecode(response.text!) as List; 79 | return [for (int i = 0; i < hints.length; ++i) (words[i], hints[i])]; 80 | } 81 | 82 | bool guessWord(String word, String hint) { 83 | stdout.writeln(hint); 84 | stdout.write('What am I? '); 85 | 86 | while (true) { 87 | final guess = stdin.readLineSync(); 88 | if (guess == null) { 89 | stdout.writeln('You missed me, I am $word'); 90 | exit(0); 91 | } 92 | if (guess.trim().toUpperCase() == word.toUpperCase()) { 93 | return true; 94 | } 95 | if (guess.isEmpty) { 96 | stdout.writeln('You missed me, I am $word'); 97 | return false; 98 | } 99 | stdout.write('Nope! What am I? '); 100 | } 101 | } 102 | 103 | Future main(List args) async { 104 | final apiKey = Platform.environment['GEMINI_API_KEY']; 105 | if (apiKey == null) { 106 | stderr.writeln(r'No $GEMINI_API_KEY environment variable'); 107 | exit(1); 108 | } 109 | 110 | final parser = ArgParser(); 111 | parser.addOption('subject', 112 | defaultsTo: 'common nouns', help: 'the theme of the quiz'); 113 | final parsedArgs = parser.parse(args); 114 | 115 | final words = await _generateWords(apiKey, parsedArgs['subject']); 116 | words.shuffle(); 117 | final hints = await _generateHints(apiKey, words); 118 | 119 | final start = DateTime.now(); 120 | var got = 0; 121 | while (hints.isNotEmpty) { 122 | final (word, prompt) = hints.removeLast(); 123 | if (guessWord(word, prompt)) got += 1; 124 | } 125 | final end = DateTime.now(); 126 | stdout.writeln('Got $got of ${words.length} in ' 127 | '${end.difference(start).inSeconds} seconds'); 128 | } 129 | -------------------------------------------------------------------------------- /samples/dart/bin/safety_settings.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2024 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | import 'dart:io'; 16 | 17 | import 'package:google_generative_ai/google_generative_ai.dart'; 18 | 19 | final apiKey = () { 20 | final apiKey = Platform.environment['GEMINI_API_KEY']; 21 | if (apiKey == null) { 22 | stderr.writeln(r'No $GEMINI_API_KEY environment variable'); 23 | exit(1); 24 | } 25 | return apiKey; 26 | }(); 27 | 28 | Future safetySettings() async { 29 | // [START safety_settings] 30 | // Make sure to include this import: 31 | // import 'package:google_generative_ai/google_generative_ai.dart'; 32 | final model = GenerativeModel( 33 | model: 'gemini-1.5-flash', 34 | apiKey: apiKey, 35 | ); 36 | final prompt = 'I support Martians Soccer Club and I think ' 37 | 'Jupiterians Football Club sucks! Write an ironic phrase telling ' 38 | 'them how I feel about them.'; 39 | 40 | final response = await model.generateContent( 41 | [Content.text(prompt)], 42 | safetySettings: [ 43 | SafetySetting(HarmCategory.harassment, HarmBlockThreshold.low) 44 | ], 45 | ); 46 | try { 47 | print(response.text); 48 | } catch (e) { 49 | print(e); 50 | for (final SafetyRating(:category, :probability) 51 | in response.candidates.first.safetyRatings!) { 52 | print('Safety Rating: $category - $probability'); 53 | } 54 | } 55 | // [END safety_settings] 56 | } 57 | 58 | Future safetySettingsMulti() async { 59 | // [START safety_settings_multi] 60 | // Make sure to include this import: 61 | // import 'package:google_generative_ai/google_generative_ai.dart'; 62 | final model = GenerativeModel( 63 | model: 'gemini-1.5-flash', 64 | apiKey: apiKey, 65 | ); 66 | final prompt = 'I support Martians Soccer Club and I think ' 67 | 'Jupiterians Football Club sucks! Write an ironic phrase telling ' 68 | 'them how I feel about them.'; 69 | 70 | final response = await model.generateContent( 71 | [Content.text(prompt)], 72 | safetySettings: [ 73 | SafetySetting(HarmCategory.harassment, HarmBlockThreshold.medium), 74 | SafetySetting(HarmCategory.hateSpeech, HarmBlockThreshold.low), 75 | ], 76 | ); 77 | try { 78 | print(response.text); 79 | } catch (e) { 80 | print(e); 81 | for (final SafetyRating(:category, :probability) 82 | in response.candidates.first.safetyRatings!) { 83 | print('Safety Rating: $category - $probability'); 84 | } 85 | } 86 | // [END safety_settings_multi] 87 | } 88 | 89 | void main() async { 90 | await safetySettings(); 91 | await safetySettingsMulti(); 92 | } 93 | -------------------------------------------------------------------------------- /samples/dart/bin/simple_chat.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2024 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | import 'dart:io'; 16 | 17 | import 'package:google_generative_ai/google_generative_ai.dart'; 18 | 19 | Future main() async { 20 | final apiKey = Platform.environment['GEMINI_API_KEY']; 21 | if (apiKey == null) { 22 | stderr.writeln(r'No $GEMINI_API_KEY environment variable'); 23 | exit(1); 24 | } 25 | final model = 26 | GenerativeModel(model: 'gemini-1.5-flash-latest', apiKey: apiKey); 27 | final chat = model.startChat(); 28 | final message = 'Hello! How are you?'; 29 | final content = Content.text(message); 30 | 31 | final response = await chat.sendMessage(content); 32 | print(response.text); 33 | } 34 | -------------------------------------------------------------------------------- /samples/dart/bin/simple_config.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2024 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | import 'dart:convert'; 16 | import 'dart:io'; 17 | 18 | import 'package:google_generative_ai/google_generative_ai.dart'; 19 | 20 | Future generate(GenerationConfig? generationConfig, String apiKey) async { 21 | final model = GenerativeModel( 22 | model: 'gemini-1.5-flash-latest', 23 | apiKey: apiKey, 24 | generationConfig: generationConfig); 25 | final prompt = 'One, two, three, '; 26 | print('Prompt: $prompt'); 27 | final content = [Content.text(prompt)]; 28 | 29 | print('Options: ${jsonEncode(generationConfig?.toJson())}'); 30 | 31 | final response = await model.generateContent(content); 32 | print('Response:'); 33 | print(response.text); 34 | } 35 | 36 | Future main() async { 37 | final apiKey = Platform.environment['GEMINI_API_KEY']; 38 | if (apiKey == null) { 39 | stderr.writeln(r'No $GEMINI_API_KEY environment variable'); 40 | exit(1); 41 | } 42 | await generate(null, apiKey); 43 | await generate(GenerationConfig(maxOutputTokens: 3), apiKey); 44 | await generate(GenerationConfig(stopSequences: ['seven']), apiKey); 45 | await generate(GenerationConfig(temperature: 0), apiKey); 46 | } 47 | -------------------------------------------------------------------------------- /samples/dart/bin/simple_embedding.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2024 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | import 'dart:io'; 16 | 17 | import 'package:google_generative_ai/google_generative_ai.dart'; 18 | 19 | void main() async { 20 | final apiKey = Platform.environment['GEMINI_API_KEY']; 21 | if (apiKey == null) { 22 | stderr.writeln(r'No $GEMINI_API_KEY environment variable'); 23 | exit(1); 24 | } 25 | final model = GenerativeModel(model: 'embedding-001', apiKey: apiKey); 26 | final prompt = 'The quick brown fox jumps over the lazy dog.'; 27 | print('Content: $prompt'); 28 | final content = Content.text(prompt); 29 | 30 | final result = await model.embedContent(content); 31 | print('Embedding:'); 32 | print(result.embedding.values); 33 | } 34 | -------------------------------------------------------------------------------- /samples/dart/bin/simple_text.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2024 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | import 'dart:io'; 16 | 17 | import 'package:google_generative_ai/google_generative_ai.dart'; 18 | 19 | void main() async { 20 | final apiKey = Platform.environment['GEMINI_API_KEY']; 21 | if (apiKey == null) { 22 | stderr.writeln(r'No $GEMINI_API_KEY environment variable'); 23 | exit(1); 24 | } 25 | final model = GenerativeModel( 26 | model: 'gemini-1.5-flash-latest', 27 | apiKey: apiKey, 28 | safetySettings: [ 29 | SafetySetting(HarmCategory.dangerousContent, HarmBlockThreshold.high) 30 | ], 31 | generationConfig: GenerationConfig(maxOutputTokens: 200)); 32 | final prompt = 'Write a story about a magic backpack.'; 33 | print('Prompt: $prompt'); 34 | final content = [Content.text(prompt)]; 35 | final tokenCount = await model.countTokens(content); 36 | print('Token count: ${tokenCount.totalTokens}'); 37 | 38 | final response = await model.generateContent(content); 39 | print('Response:'); 40 | print(response.text); 41 | } 42 | -------------------------------------------------------------------------------- /samples/dart/bin/simple_text_and_image.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2024 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | import 'dart:io'; 16 | 17 | import 'package:google_generative_ai/google_generative_ai.dart'; 18 | 19 | import 'util/resource.dart'; 20 | 21 | void main() async { 22 | final apiKey = Platform.environment['GEMINI_API_KEY']; 23 | if (apiKey == null) { 24 | stderr.writeln(r'No $GEMINI_API_KEY environment variable'); 25 | exit(1); 26 | } 27 | final model = GenerativeModel( 28 | model: 'gemini-1.5-flash-latest', 29 | apiKey: apiKey, 30 | ); 31 | final prompt = 'What do you see?'; 32 | print('Prompt: $prompt'); 33 | 34 | final (catBytes, sconeBytes) = await ( 35 | readResource('cat.jpg'), 36 | readResource('scones.jpg'), 37 | ).wait; 38 | final content = [ 39 | Content.multi([ 40 | TextPart(prompt), 41 | // The only accepted mime types are image/*. 42 | DataPart('image/jpeg', catBytes), 43 | DataPart('image/jpeg', sconeBytes), 44 | ]) 45 | ]; 46 | 47 | final response = await model.generateContent(content); 48 | print('Response:'); 49 | print(response.text); 50 | } 51 | -------------------------------------------------------------------------------- /samples/dart/bin/system_instructions.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2024 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | import 'dart:io'; 16 | 17 | import 'package:google_generative_ai/google_generative_ai.dart'; 18 | 19 | final apiKey = () { 20 | final apiKey = Platform.environment['GEMINI_API_KEY']; 21 | if (apiKey == null) { 22 | stderr.writeln(r'No $GEMINI_API_KEY environment variable'); 23 | exit(1); 24 | } 25 | return apiKey; 26 | }(); 27 | 28 | Future systemInstructions() async { 29 | // [START system_instructions] 30 | // Make sure to include this import: 31 | // import 'package:google_generative_ai/google_generative_ai.dart'; 32 | final model = GenerativeModel( 33 | model: 'gemini-1.5-flash', 34 | apiKey: apiKey, 35 | systemInstruction: Content.system('You are a cat. Your name is Neko.'), 36 | ); 37 | final prompt = 'Good morning! How are you?'; 38 | 39 | final response = await model.generateContent([Content.text(prompt)]); 40 | print(response.text); 41 | // [END system_instructions] 42 | } 43 | 44 | void main() async { 45 | await systemInstructions(); 46 | } 47 | -------------------------------------------------------------------------------- /samples/dart/bin/text_generation.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2024 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | import 'dart:io'; 16 | 17 | import 'package:google_generative_ai/google_generative_ai.dart'; 18 | 19 | final apiKey = () { 20 | final apiKey = Platform.environment['GEMINI_API_KEY']; 21 | if (apiKey == null) { 22 | stderr.writeln(r'No $GEMINI_API_KEY environment variable'); 23 | exit(1); 24 | } 25 | return apiKey; 26 | }(); 27 | 28 | Future textGenTextOnlyPrompt() async { 29 | // [START text_gen_text_only_prompt] 30 | // Make sure to include this import: 31 | // import 'package:google_generative_ai/google_generative_ai.dart'; 32 | final model = GenerativeModel( 33 | model: 'gemini-1.5-flash', 34 | apiKey: apiKey, 35 | ); 36 | final prompt = 'Write a story about a magic backpack.'; 37 | 38 | final response = await model.generateContent([Content.text(prompt)]); 39 | print(response.text); 40 | // [END text_gen_text_only_prompt] 41 | } 42 | 43 | Future textGenTextOnlyPromptStreaming() async { 44 | // [START text_gen_text_only_prompt_streaming] 45 | // Make sure to include this import: 46 | // import 'package:google_generative_ai/google_generative_ai.dart'; 47 | final model = GenerativeModel( 48 | model: 'gemini-1.5-flash', 49 | apiKey: apiKey, 50 | ); 51 | final prompt = 'Write a story about a magic backpack.'; 52 | 53 | final responses = model.generateContentStream([Content.text(prompt)]); 54 | await for (final response in responses) { 55 | print(response.text); 56 | } 57 | // [END text_gen_text_only_prompt_streaming] 58 | } 59 | 60 | Future textGenMultimodalOneImagePrompt() async { 61 | // [START text_gen_multimodal_one_image_prompt] 62 | // Make sure to include this import: 63 | // import 'package:google_generative_ai/google_generative_ai.dart'; 64 | final model = GenerativeModel( 65 | model: 'gemini-1.5-flash', 66 | apiKey: apiKey, 67 | ); 68 | 69 | Future fileToPart(String mimeType, String path) async { 70 | return DataPart(mimeType, await File(path).readAsBytes()); 71 | } 72 | 73 | final prompt = 'Describe how this product might be manufactured.'; 74 | final image = await fileToPart('image/jpeg', 'resources/jetpack.jpg'); 75 | 76 | final response = await model.generateContent([ 77 | Content.multi([TextPart(prompt), image]) 78 | ]); 79 | print(response.text); 80 | // [END text_gen_multimodal_one_image_prompt] 81 | } 82 | 83 | Future textGenMultimodalOneImagePromptStreaming() async { 84 | // [START text_gen_multimodal_one_image_prompt_streaming] 85 | // Make sure to include this import: 86 | // import 'package:google_generative_ai/google_generative_ai.dart'; 87 | final model = GenerativeModel( 88 | model: 'gemini-1.5-flash', 89 | apiKey: apiKey, 90 | ); 91 | 92 | Future fileToPart(String mimeType, String path) async { 93 | return DataPart(mimeType, await File(path).readAsBytes()); 94 | } 95 | 96 | final prompt = 'Describe how this product might be manufactured.'; 97 | final image = await fileToPart('image/jpeg', 'resources/jetpack.jpg'); 98 | 99 | final responses = model.generateContentStream([ 100 | Content.multi([TextPart(prompt), image]) 101 | ]); 102 | await for (final response in responses) { 103 | print(response.text); 104 | } 105 | // [END text_gen_multimodal_one_image_prompt_streaming] 106 | } 107 | 108 | Future textGenMultimodalMultiImagePrompt() async { 109 | // [START text_gen_multimodal_multi_image_prompt] 110 | // Make sure to include this import: 111 | // import 'package:google_generative_ai/google_generative_ai.dart'; 112 | final model = GenerativeModel( 113 | model: 'gemini-1.5-flash', 114 | apiKey: apiKey, 115 | ); 116 | 117 | Future fileToPart(String mimeType, String path) async { 118 | return DataPart(mimeType, await File(path).readAsBytes()); 119 | } 120 | 121 | final prompt = 'Write an advertising jingle showing how the product in the' 122 | ' first image could solve the problems shown in the second two images.'; 123 | final images = await [ 124 | fileToPart('image/jpeg', 'resources/jetpack.jpg'), 125 | fileToPart('image/jpeg', 'resources/piranha.jpg'), 126 | fileToPart('image/jpeg', 'resources/firefighter.jpg'), 127 | ].wait; 128 | 129 | final response = await model.generateContent([ 130 | Content.multi([TextPart(prompt), ...images]) 131 | ]); 132 | print(response.text); 133 | // [END text_gen_multimodal_multi_image_prompt] 134 | } 135 | 136 | Future textGenMultimodalMultiImagePromptStreaming() async { 137 | // [START text_gen_multimodal_multi_image_prompt_streaming] 138 | // Make sure to include this import: 139 | // import 'package:google_generative_ai/google_generative_ai.dart'; 140 | final model = GenerativeModel( 141 | model: 'gemini-1.5-flash', 142 | apiKey: apiKey, 143 | ); 144 | 145 | Future fileToPart(String mimeType, String path) async { 146 | return DataPart(mimeType, await File(path).readAsBytes()); 147 | } 148 | 149 | final prompt = 'Write an advertising jingle showing how the product in the' 150 | ' first image could solve the problems shown in the second two images.'; 151 | final images = await [ 152 | fileToPart('image/jpeg', 'resources/jetpack.jpg'), 153 | fileToPart('image/jpeg', 'resources/piranha.jpg'), 154 | fileToPart('image/jpeg', 'resources/firefighter.jpg'), 155 | ].wait; 156 | 157 | final responses = model.generateContentStream([ 158 | Content.multi([TextPart(prompt), ...images]) 159 | ]); 160 | await for (final response in responses) { 161 | print(response.text); 162 | } 163 | // [END text_gen_multimodal_multi_image_prompt_streaming] 164 | } 165 | 166 | void main() async { 167 | await textGenTextOnlyPrompt(); 168 | await textGenTextOnlyPromptStreaming(); 169 | await textGenMultimodalOneImagePrompt(); 170 | await textGenMultimodalOneImagePromptStreaming(); 171 | await textGenMultimodalMultiImagePrompt(); 172 | await textGenMultimodalMultiImagePromptStreaming(); 173 | } 174 | -------------------------------------------------------------------------------- /samples/dart/bin/util/resource.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2024 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | import 'dart:io'; 16 | import 'dart:typed_data'; 17 | 18 | import 'package:path/path.dart' as path; 19 | 20 | /// Reads a file from the `resources/` directory of this Pub package root 21 | /// directory. 22 | /// 23 | /// The [name] is the entire file name, including extension. 24 | /// 25 | /// Assumes the script is run from the `bin/` directory or another immediate 26 | /// subdirectory of the package root directory. 27 | Future readResource(String name) { 28 | return File(path.join(_resourceDirectory.path, name)).readAsBytes(); 29 | } 30 | 31 | final _resourceDirectory = 32 | Directory.fromUri(Platform.script.resolve('../resources/')); 33 | -------------------------------------------------------------------------------- /samples/dart/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: generative_ai_samples 2 | 3 | publish_to: none 4 | 5 | environment: 6 | sdk: ^3.0.0 7 | 8 | dependencies: 9 | args: ^2.4.2 10 | path: ^1.9.0 11 | # Note: best practice here is to use a caret version constraint. We use `any` 12 | # here just for the purpose of the samples. 13 | google_generative_ai: any 14 | 15 | dev_dependencies: 16 | lints: ^3.0.0 17 | 18 | # Note: this section is only used in order to resolve google_generative_ai to 19 | # the same repo as the samples. 20 | dependency_overrides: 21 | google_generative_ai: 22 | path: ../../pkgs/google_generative_ai 23 | -------------------------------------------------------------------------------- /samples/dart/resources/cat.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google-gemini/deprecated-generative-ai-dart/19c1d6018b253ebfcd6a35eed7bc556cf6ff4d8e/samples/dart/resources/cat.jpg -------------------------------------------------------------------------------- /samples/dart/resources/firefighter.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google-gemini/deprecated-generative-ai-dart/19c1d6018b253ebfcd6a35eed7bc556cf6ff4d8e/samples/dart/resources/firefighter.jpg -------------------------------------------------------------------------------- /samples/dart/resources/jetpack.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google-gemini/deprecated-generative-ai-dart/19c1d6018b253ebfcd6a35eed7bc556cf6ff4d8e/samples/dart/resources/jetpack.jpg -------------------------------------------------------------------------------- /samples/dart/resources/organ.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google-gemini/deprecated-generative-ai-dart/19c1d6018b253ebfcd6a35eed7bc556cf6ff4d8e/samples/dart/resources/organ.jpg -------------------------------------------------------------------------------- /samples/dart/resources/piranha.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google-gemini/deprecated-generative-ai-dart/19c1d6018b253ebfcd6a35eed7bc556cf6ff4d8e/samples/dart/resources/piranha.jpg -------------------------------------------------------------------------------- /samples/dart/resources/scones.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google-gemini/deprecated-generative-ai-dart/19c1d6018b253ebfcd6a35eed7bc556cf6ff4d8e/samples/dart/resources/scones.jpg -------------------------------------------------------------------------------- /samples/flutter_app/.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.log 4 | *.pyc 5 | *.swp 6 | .DS_Store 7 | .atom/ 8 | .buildlog/ 9 | .history 10 | .svn/ 11 | migrate_working_dir/ 12 | 13 | # IntelliJ related 14 | *.iml 15 | *.ipr 16 | *.iws 17 | .idea/ 18 | 19 | # The .vscode folder contains launch configuration and tasks you configure in 20 | # VS Code which you may wish to be included in version control, so this line 21 | # is commented out by default. 22 | #.vscode/ 23 | 24 | # Flutter/Dart/Pub related 25 | **/doc/api/ 26 | **/ios/Flutter/.last_build_id 27 | .dart_tool/ 28 | .flutter-plugins 29 | .flutter-plugins-dependencies 30 | .pub-cache/ 31 | .pub/ 32 | /build/ 33 | 34 | # Symbolication related 35 | app.*.symbols 36 | 37 | # Obfuscation related 38 | app.*.map.json 39 | 40 | # Android Studio will place build artifacts here 41 | /android/app/debug 42 | /android/app/profile 43 | /android/app/release 44 | -------------------------------------------------------------------------------- /samples/flutter_app/.metadata: -------------------------------------------------------------------------------- 1 | # This file tracks properties of this Flutter project. 2 | # Used by Flutter tool to assess capabilities and perform upgrades etc. 3 | # 4 | # This file should be version controlled and should not be manually edited. 5 | 6 | version: 7 | revision: "41456452f29d64e8deb623a3c927524bcf9f111b" 8 | channel: "stable" 9 | 10 | project_type: app 11 | 12 | # Tracks metadata for the flutter migrate command 13 | migration: 14 | platforms: 15 | - platform: root 16 | create_revision: 41456452f29d64e8deb623a3c927524bcf9f111b 17 | base_revision: 41456452f29d64e8deb623a3c927524bcf9f111b 18 | - platform: ios 19 | create_revision: 41456452f29d64e8deb623a3c927524bcf9f111b 20 | base_revision: 41456452f29d64e8deb623a3c927524bcf9f111b 21 | 22 | # User provided section 23 | 24 | # List of Local paths (relative to this file) that should be 25 | # ignored by the migrate tool. 26 | # 27 | # Files that are not part of the templates will be ignored by default. 28 | unmanaged_files: 29 | - 'lib/main.dart' 30 | - 'ios/Runner.xcodeproj/project.pbxproj' 31 | -------------------------------------------------------------------------------- /samples/flutter_app/README.md: -------------------------------------------------------------------------------- 1 | [![flutter_sample](https://github.com/google/generative-ai-dart/actions/workflows/flutter_sample.yml/badge.svg)](https://github.com/google/generative-ai-dart/actions/workflows/flutter_sample.yml) 2 | 3 | # Flutter generative AI sample 4 | 5 | A Flutter chat application that uses the `google_generative_ai` package. 6 | 7 | ## Getting started 8 | 9 | To use the Gemini API, you'll need an API key. If you don't already have one, 10 | create a key in Google AI Studio: https://aistudio.google.com/app/apikey. 11 | 12 | When running the app, include your API key using the `--dart-define` flag: 13 | 14 | ```bash 15 | flutter run --dart-define=API_KEY=$GEMINI_API_KEY 16 | ``` 17 | 18 | If you use VSCode, you can [specify `--dart-define` 19 | variables](https://dartcode.org/docs/using-dart-define-in-flutter/) in your 20 | launch.json file. 21 | 22 | If you use Android Studio or IntelliJ you can use run / debug configurations 23 | (https://www.jetbrains.com/help/idea/run-debug-configuration.html). 24 | -------------------------------------------------------------------------------- /samples/flutter_app/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:flutter_lints/flutter.yaml 2 | -------------------------------------------------------------------------------- /samples/flutter_app/android/.gitignore: -------------------------------------------------------------------------------- 1 | gradle-wrapper.jar 2 | /.gradle 3 | /captures/ 4 | /gradlew 5 | /gradlew.bat 6 | /local.properties 7 | GeneratedPluginRegistrant.java 8 | 9 | # Remember to never publicly share your keystore. 10 | # See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app 11 | key.properties 12 | **/*.keystore 13 | **/*.jks 14 | -------------------------------------------------------------------------------- /samples/flutter_app/android/app/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id "com.android.application" 3 | id "kotlin-android" 4 | id "dev.flutter.flutter-gradle-plugin" 5 | } 6 | 7 | def localProperties = new Properties() 8 | def localPropertiesFile = rootProject.file('local.properties') 9 | if (localPropertiesFile.exists()) { 10 | localPropertiesFile.withReader('UTF-8') { reader -> 11 | localProperties.load(reader) 12 | } 13 | } 14 | 15 | def flutterVersionCode = localProperties.getProperty('flutter.versionCode') 16 | if (flutterVersionCode == null) { 17 | flutterVersionCode = '1' 18 | } 19 | 20 | def flutterVersionName = localProperties.getProperty('flutter.versionName') 21 | if (flutterVersionName == null) { 22 | flutterVersionName = '1.0' 23 | } 24 | 25 | android { 26 | namespace "com.example.flutter_app" 27 | compileSdkVersion flutter.compileSdkVersion 28 | ndkVersion flutter.ndkVersion 29 | 30 | compileOptions { 31 | sourceCompatibility JavaVersion.VERSION_1_8 32 | targetCompatibility JavaVersion.VERSION_1_8 33 | } 34 | 35 | kotlinOptions { 36 | jvmTarget = '1.8' 37 | } 38 | 39 | sourceSets { 40 | main.java.srcDirs += 'src/main/kotlin' 41 | } 42 | 43 | defaultConfig { 44 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). 45 | applicationId "com.example.flutter_app" 46 | // You can update the following values to match your application needs. 47 | // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration. 48 | minSdkVersion flutter.minSdkVersion 49 | targetSdkVersion flutter.targetSdkVersion 50 | versionCode flutterVersionCode.toInteger() 51 | versionName flutterVersionName 52 | } 53 | 54 | buildTypes { 55 | release { 56 | // TODO: Add your own signing config for the release build. 57 | // Signing with the debug keys for now, so `flutter run --release` works. 58 | signingConfig signingConfigs.debug 59 | } 60 | } 61 | } 62 | 63 | flutter { 64 | source '../..' 65 | } 66 | 67 | dependencies {} 68 | -------------------------------------------------------------------------------- /samples/flutter_app/android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /samples/flutter_app/android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 14 | 18 | 22 | 23 | 24 | 25 | 26 | 27 | 29 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /samples/flutter_app/android/app/src/main/kotlin/com/example/flutter_app/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package com.example.flutter_app 2 | 3 | import io.flutter.embedding.android.FlutterActivity 4 | 5 | class MainActivity: FlutterActivity() { 6 | } 7 | -------------------------------------------------------------------------------- /samples/flutter_app/android/app/src/main/res/drawable-v21/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /samples/flutter_app/android/app/src/main/res/drawable/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /samples/flutter_app/android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google-gemini/deprecated-generative-ai-dart/19c1d6018b253ebfcd6a35eed7bc556cf6ff4d8e/samples/flutter_app/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /samples/flutter_app/android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google-gemini/deprecated-generative-ai-dart/19c1d6018b253ebfcd6a35eed7bc556cf6ff4d8e/samples/flutter_app/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /samples/flutter_app/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google-gemini/deprecated-generative-ai-dart/19c1d6018b253ebfcd6a35eed7bc556cf6ff4d8e/samples/flutter_app/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /samples/flutter_app/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google-gemini/deprecated-generative-ai-dart/19c1d6018b253ebfcd6a35eed7bc556cf6ff4d8e/samples/flutter_app/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /samples/flutter_app/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google-gemini/deprecated-generative-ai-dart/19c1d6018b253ebfcd6a35eed7bc556cf6ff4d8e/samples/flutter_app/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /samples/flutter_app/android/app/src/main/res/values-night/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 15 | 18 | 19 | -------------------------------------------------------------------------------- /samples/flutter_app/android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 15 | 18 | 19 | -------------------------------------------------------------------------------- /samples/flutter_app/android/app/src/profile/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /samples/flutter_app/android/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | ext.kotlin_version = '1.7.10' 3 | repositories { 4 | google() 5 | mavenCentral() 6 | } 7 | 8 | dependencies { 9 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" 10 | } 11 | } 12 | 13 | allprojects { 14 | repositories { 15 | google() 16 | mavenCentral() 17 | } 18 | } 19 | 20 | rootProject.buildDir = '../build' 21 | subprojects { 22 | project.buildDir = "${rootProject.buildDir}/${project.name}" 23 | } 24 | subprojects { 25 | project.evaluationDependsOn(':app') 26 | } 27 | 28 | tasks.register("clean", Delete) { 29 | delete rootProject.buildDir 30 | } 31 | -------------------------------------------------------------------------------- /samples/flutter_app/android/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx4G 2 | android.useAndroidX=true 3 | android.enableJetifier=true 4 | -------------------------------------------------------------------------------- /samples/flutter_app/android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | zipStoreBase=GRADLE_USER_HOME 4 | zipStorePath=wrapper/dists 5 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-all.zip 6 | -------------------------------------------------------------------------------- /samples/flutter_app/android/settings.gradle: -------------------------------------------------------------------------------- 1 | pluginManagement { 2 | def flutterSdkPath = { 3 | def properties = new Properties() 4 | file("local.properties").withInputStream { properties.load(it) } 5 | def flutterSdkPath = properties.getProperty("flutter.sdk") 6 | assert flutterSdkPath != null, "flutter.sdk not set in local.properties" 7 | return flutterSdkPath 8 | } 9 | settings.ext.flutterSdkPath = flutterSdkPath() 10 | 11 | includeBuild("${settings.ext.flutterSdkPath}/packages/flutter_tools/gradle") 12 | 13 | repositories { 14 | google() 15 | mavenCentral() 16 | gradlePluginPortal() 17 | } 18 | 19 | plugins { 20 | id "dev.flutter.flutter-gradle-plugin" version "1.0.0" apply false 21 | } 22 | } 23 | 24 | plugins { 25 | id "dev.flutter.flutter-plugin-loader" version "1.0.0" 26 | id "com.android.application" version "7.3.0" apply false 27 | } 28 | 29 | include ":app" 30 | -------------------------------------------------------------------------------- /samples/flutter_app/assets/images/cat.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google-gemini/deprecated-generative-ai-dart/19c1d6018b253ebfcd6a35eed7bc556cf6ff4d8e/samples/flutter_app/assets/images/cat.jpg -------------------------------------------------------------------------------- /samples/flutter_app/assets/images/scones.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google-gemini/deprecated-generative-ai-dart/19c1d6018b253ebfcd6a35eed7bc556cf6ff4d8e/samples/flutter_app/assets/images/scones.jpg -------------------------------------------------------------------------------- /samples/flutter_app/ios/.gitignore: -------------------------------------------------------------------------------- 1 | **/dgph 2 | *.mode1v3 3 | *.mode2v3 4 | *.moved-aside 5 | *.pbxuser 6 | *.perspectivev3 7 | **/*sync/ 8 | .sconsign.dblite 9 | .tags* 10 | **/.vagrant/ 11 | **/DerivedData/ 12 | Icon? 13 | **/Pods/ 14 | **/.symlinks/ 15 | profile 16 | xcuserdata 17 | **/.generated/ 18 | Flutter/App.framework 19 | Flutter/Flutter.framework 20 | Flutter/Flutter.podspec 21 | Flutter/Generated.xcconfig 22 | Flutter/ephemeral/ 23 | Flutter/app.flx 24 | Flutter/app.zip 25 | Flutter/flutter_assets/ 26 | Flutter/flutter_export_environment.sh 27 | ServiceDefinitions.json 28 | Runner/GeneratedPluginRegistrant.* 29 | 30 | # Exceptions to above rules. 31 | !default.mode1v3 32 | !default.mode2v3 33 | !default.pbxuser 34 | !default.perspectivev3 35 | -------------------------------------------------------------------------------- /samples/flutter_app/ios/Flutter/AppFrameworkInfo.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | App 9 | CFBundleIdentifier 10 | io.flutter.flutter.app 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | App 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1.0 23 | MinimumOSVersion 24 | 12.0 25 | 26 | 27 | -------------------------------------------------------------------------------- /samples/flutter_app/ios/Flutter/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /samples/flutter_app/ios/Flutter/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /samples/flutter_app/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /samples/flutter_app/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /samples/flutter_app/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /samples/flutter_app/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 37 | 38 | 39 | 40 | 43 | 49 | 50 | 51 | 52 | 53 | 63 | 65 | 71 | 72 | 73 | 74 | 80 | 82 | 88 | 89 | 90 | 91 | 93 | 94 | 97 | 98 | 99 | -------------------------------------------------------------------------------- /samples/flutter_app/ios/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /samples/flutter_app/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /samples/flutter_app/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /samples/flutter_app/ios/Runner/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | import Flutter 3 | 4 | @UIApplicationMain 5 | @objc class AppDelegate: FlutterAppDelegate { 6 | override func application( 7 | _ application: UIApplication, 8 | didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? 9 | ) -> Bool { 10 | GeneratedPluginRegistrant.register(with: self) 11 | return super.application(application, didFinishLaunchingWithOptions: launchOptions) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /samples/flutter_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "20x20", 5 | "idiom" : "iphone", 6 | "filename" : "Icon-App-20x20@2x.png", 7 | "scale" : "2x" 8 | }, 9 | { 10 | "size" : "20x20", 11 | "idiom" : "iphone", 12 | "filename" : "Icon-App-20x20@3x.png", 13 | "scale" : "3x" 14 | }, 15 | { 16 | "size" : "29x29", 17 | "idiom" : "iphone", 18 | "filename" : "Icon-App-29x29@1x.png", 19 | "scale" : "1x" 20 | }, 21 | { 22 | "size" : "29x29", 23 | "idiom" : "iphone", 24 | "filename" : "Icon-App-29x29@2x.png", 25 | "scale" : "2x" 26 | }, 27 | { 28 | "size" : "29x29", 29 | "idiom" : "iphone", 30 | "filename" : "Icon-App-29x29@3x.png", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "size" : "40x40", 35 | "idiom" : "iphone", 36 | "filename" : "Icon-App-40x40@2x.png", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "size" : "40x40", 41 | "idiom" : "iphone", 42 | "filename" : "Icon-App-40x40@3x.png", 43 | "scale" : "3x" 44 | }, 45 | { 46 | "size" : "60x60", 47 | "idiom" : "iphone", 48 | "filename" : "Icon-App-60x60@2x.png", 49 | "scale" : "2x" 50 | }, 51 | { 52 | "size" : "60x60", 53 | "idiom" : "iphone", 54 | "filename" : "Icon-App-60x60@3x.png", 55 | "scale" : "3x" 56 | }, 57 | { 58 | "size" : "20x20", 59 | "idiom" : "ipad", 60 | "filename" : "Icon-App-20x20@1x.png", 61 | "scale" : "1x" 62 | }, 63 | { 64 | "size" : "20x20", 65 | "idiom" : "ipad", 66 | "filename" : "Icon-App-20x20@2x.png", 67 | "scale" : "2x" 68 | }, 69 | { 70 | "size" : "29x29", 71 | "idiom" : "ipad", 72 | "filename" : "Icon-App-29x29@1x.png", 73 | "scale" : "1x" 74 | }, 75 | { 76 | "size" : "29x29", 77 | "idiom" : "ipad", 78 | "filename" : "Icon-App-29x29@2x.png", 79 | "scale" : "2x" 80 | }, 81 | { 82 | "size" : "40x40", 83 | "idiom" : "ipad", 84 | "filename" : "Icon-App-40x40@1x.png", 85 | "scale" : "1x" 86 | }, 87 | { 88 | "size" : "40x40", 89 | "idiom" : "ipad", 90 | "filename" : "Icon-App-40x40@2x.png", 91 | "scale" : "2x" 92 | }, 93 | { 94 | "size" : "76x76", 95 | "idiom" : "ipad", 96 | "filename" : "Icon-App-76x76@1x.png", 97 | "scale" : "1x" 98 | }, 99 | { 100 | "size" : "76x76", 101 | "idiom" : "ipad", 102 | "filename" : "Icon-App-76x76@2x.png", 103 | "scale" : "2x" 104 | }, 105 | { 106 | "size" : "83.5x83.5", 107 | "idiom" : "ipad", 108 | "filename" : "Icon-App-83.5x83.5@2x.png", 109 | "scale" : "2x" 110 | }, 111 | { 112 | "size" : "1024x1024", 113 | "idiom" : "ios-marketing", 114 | "filename" : "Icon-App-1024x1024@1x.png", 115 | "scale" : "1x" 116 | } 117 | ], 118 | "info" : { 119 | "version" : 1, 120 | "author" : "xcode" 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /samples/flutter_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google-gemini/deprecated-generative-ai-dart/19c1d6018b253ebfcd6a35eed7bc556cf6ff4d8e/samples/flutter_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png -------------------------------------------------------------------------------- /samples/flutter_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google-gemini/deprecated-generative-ai-dart/19c1d6018b253ebfcd6a35eed7bc556cf6ff4d8e/samples/flutter_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png -------------------------------------------------------------------------------- /samples/flutter_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google-gemini/deprecated-generative-ai-dart/19c1d6018b253ebfcd6a35eed7bc556cf6ff4d8e/samples/flutter_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png -------------------------------------------------------------------------------- /samples/flutter_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google-gemini/deprecated-generative-ai-dart/19c1d6018b253ebfcd6a35eed7bc556cf6ff4d8e/samples/flutter_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png -------------------------------------------------------------------------------- /samples/flutter_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google-gemini/deprecated-generative-ai-dart/19c1d6018b253ebfcd6a35eed7bc556cf6ff4d8e/samples/flutter_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png -------------------------------------------------------------------------------- /samples/flutter_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google-gemini/deprecated-generative-ai-dart/19c1d6018b253ebfcd6a35eed7bc556cf6ff4d8e/samples/flutter_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png -------------------------------------------------------------------------------- /samples/flutter_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google-gemini/deprecated-generative-ai-dart/19c1d6018b253ebfcd6a35eed7bc556cf6ff4d8e/samples/flutter_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png -------------------------------------------------------------------------------- /samples/flutter_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google-gemini/deprecated-generative-ai-dart/19c1d6018b253ebfcd6a35eed7bc556cf6ff4d8e/samples/flutter_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png -------------------------------------------------------------------------------- /samples/flutter_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google-gemini/deprecated-generative-ai-dart/19c1d6018b253ebfcd6a35eed7bc556cf6ff4d8e/samples/flutter_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png -------------------------------------------------------------------------------- /samples/flutter_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google-gemini/deprecated-generative-ai-dart/19c1d6018b253ebfcd6a35eed7bc556cf6ff4d8e/samples/flutter_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png -------------------------------------------------------------------------------- /samples/flutter_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google-gemini/deprecated-generative-ai-dart/19c1d6018b253ebfcd6a35eed7bc556cf6ff4d8e/samples/flutter_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png -------------------------------------------------------------------------------- /samples/flutter_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google-gemini/deprecated-generative-ai-dart/19c1d6018b253ebfcd6a35eed7bc556cf6ff4d8e/samples/flutter_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png -------------------------------------------------------------------------------- /samples/flutter_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google-gemini/deprecated-generative-ai-dart/19c1d6018b253ebfcd6a35eed7bc556cf6ff4d8e/samples/flutter_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png -------------------------------------------------------------------------------- /samples/flutter_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google-gemini/deprecated-generative-ai-dart/19c1d6018b253ebfcd6a35eed7bc556cf6ff4d8e/samples/flutter_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png -------------------------------------------------------------------------------- /samples/flutter_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google-gemini/deprecated-generative-ai-dart/19c1d6018b253ebfcd6a35eed7bc556cf6ff4d8e/samples/flutter_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png -------------------------------------------------------------------------------- /samples/flutter_app/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "LaunchImage.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "LaunchImage@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "LaunchImage@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /samples/flutter_app/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google-gemini/deprecated-generative-ai-dart/19c1d6018b253ebfcd6a35eed7bc556cf6ff4d8e/samples/flutter_app/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png -------------------------------------------------------------------------------- /samples/flutter_app/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google-gemini/deprecated-generative-ai-dart/19c1d6018b253ebfcd6a35eed7bc556cf6ff4d8e/samples/flutter_app/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png -------------------------------------------------------------------------------- /samples/flutter_app/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google-gemini/deprecated-generative-ai-dart/19c1d6018b253ebfcd6a35eed7bc556cf6ff4d8e/samples/flutter_app/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png -------------------------------------------------------------------------------- /samples/flutter_app/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md: -------------------------------------------------------------------------------- 1 | # Launch Screen Assets 2 | 3 | You can customize the launch screen with your own desired assets by replacing the image files in this directory. 4 | 5 | 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. -------------------------------------------------------------------------------- /samples/flutter_app/ios/Runner/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /samples/flutter_app/ios/Runner/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /samples/flutter_app/ios/Runner/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleDisplayName 8 | Flutter App 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | flutter_app 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | $(FLUTTER_BUILD_NAME) 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | $(FLUTTER_BUILD_NUMBER) 25 | LSRequiresIPhoneOS 26 | 27 | UILaunchStoryboardName 28 | LaunchScreen 29 | UIMainStoryboardFile 30 | Main 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | UISupportedInterfaceOrientations~ipad 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationPortraitUpsideDown 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | CADisableMinimumFrameDurationOnPhone 45 | 46 | UIApplicationSupportsIndirectInputEvents 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /samples/flutter_app/ios/Runner/Runner-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | #import "GeneratedPluginRegistrant.h" 2 | -------------------------------------------------------------------------------- /samples/flutter_app/ios/RunnerTests/RunnerTests.swift: -------------------------------------------------------------------------------- 1 | import Flutter 2 | import UIKit 3 | import XCTest 4 | 5 | class RunnerTests: XCTestCase { 6 | 7 | func testExample() { 8 | // If you add code to the Runner application, consider adding tests here. 9 | // See https://developer.apple.com/documentation/xctest for more information about using XCTest. 10 | } 11 | 12 | } 13 | -------------------------------------------------------------------------------- /samples/flutter_app/macos/.gitignore: -------------------------------------------------------------------------------- 1 | # Flutter-related 2 | **/Flutter/ephemeral/ 3 | **/Pods/ 4 | 5 | # Xcode-related 6 | **/dgph 7 | **/xcuserdata/ 8 | -------------------------------------------------------------------------------- /samples/flutter_app/macos/Flutter/Flutter-Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include "ephemeral/Flutter-Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /samples/flutter_app/macos/Flutter/Flutter-Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include "ephemeral/Flutter-Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /samples/flutter_app/macos/Flutter/GeneratedPluginRegistrant.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Generated file. Do not edit. 3 | // 4 | 5 | import FlutterMacOS 6 | import Foundation 7 | 8 | 9 | func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { 10 | } 11 | -------------------------------------------------------------------------------- /samples/flutter_app/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /samples/flutter_app/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 37 | 38 | 39 | 40 | 43 | 49 | 50 | 51 | 52 | 53 | 63 | 65 | 71 | 72 | 73 | 74 | 80 | 82 | 88 | 89 | 90 | 91 | 93 | 94 | 97 | 98 | 99 | -------------------------------------------------------------------------------- /samples/flutter_app/macos/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /samples/flutter_app/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /samples/flutter_app/macos/Runner/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | import Cocoa 2 | import FlutterMacOS 3 | 4 | @NSApplicationMain 5 | class AppDelegate: FlutterAppDelegate { 6 | override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool { 7 | return true 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /samples/flutter_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "16x16", 5 | "idiom" : "mac", 6 | "filename" : "app_icon_16.png", 7 | "scale" : "1x" 8 | }, 9 | { 10 | "size" : "16x16", 11 | "idiom" : "mac", 12 | "filename" : "app_icon_32.png", 13 | "scale" : "2x" 14 | }, 15 | { 16 | "size" : "32x32", 17 | "idiom" : "mac", 18 | "filename" : "app_icon_32.png", 19 | "scale" : "1x" 20 | }, 21 | { 22 | "size" : "32x32", 23 | "idiom" : "mac", 24 | "filename" : "app_icon_64.png", 25 | "scale" : "2x" 26 | }, 27 | { 28 | "size" : "128x128", 29 | "idiom" : "mac", 30 | "filename" : "app_icon_128.png", 31 | "scale" : "1x" 32 | }, 33 | { 34 | "size" : "128x128", 35 | "idiom" : "mac", 36 | "filename" : "app_icon_256.png", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "size" : "256x256", 41 | "idiom" : "mac", 42 | "filename" : "app_icon_256.png", 43 | "scale" : "1x" 44 | }, 45 | { 46 | "size" : "256x256", 47 | "idiom" : "mac", 48 | "filename" : "app_icon_512.png", 49 | "scale" : "2x" 50 | }, 51 | { 52 | "size" : "512x512", 53 | "idiom" : "mac", 54 | "filename" : "app_icon_512.png", 55 | "scale" : "1x" 56 | }, 57 | { 58 | "size" : "512x512", 59 | "idiom" : "mac", 60 | "filename" : "app_icon_1024.png", 61 | "scale" : "2x" 62 | } 63 | ], 64 | "info" : { 65 | "version" : 1, 66 | "author" : "xcode" 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /samples/flutter_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google-gemini/deprecated-generative-ai-dart/19c1d6018b253ebfcd6a35eed7bc556cf6ff4d8e/samples/flutter_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png -------------------------------------------------------------------------------- /samples/flutter_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google-gemini/deprecated-generative-ai-dart/19c1d6018b253ebfcd6a35eed7bc556cf6ff4d8e/samples/flutter_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png -------------------------------------------------------------------------------- /samples/flutter_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google-gemini/deprecated-generative-ai-dart/19c1d6018b253ebfcd6a35eed7bc556cf6ff4d8e/samples/flutter_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png -------------------------------------------------------------------------------- /samples/flutter_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google-gemini/deprecated-generative-ai-dart/19c1d6018b253ebfcd6a35eed7bc556cf6ff4d8e/samples/flutter_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png -------------------------------------------------------------------------------- /samples/flutter_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google-gemini/deprecated-generative-ai-dart/19c1d6018b253ebfcd6a35eed7bc556cf6ff4d8e/samples/flutter_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png -------------------------------------------------------------------------------- /samples/flutter_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google-gemini/deprecated-generative-ai-dart/19c1d6018b253ebfcd6a35eed7bc556cf6ff4d8e/samples/flutter_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png -------------------------------------------------------------------------------- /samples/flutter_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google-gemini/deprecated-generative-ai-dart/19c1d6018b253ebfcd6a35eed7bc556cf6ff4d8e/samples/flutter_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png -------------------------------------------------------------------------------- /samples/flutter_app/macos/Runner/Configs/AppInfo.xcconfig: -------------------------------------------------------------------------------- 1 | // Application-level settings for the Runner target. 2 | // 3 | // This may be replaced with something auto-generated from metadata (e.g., pubspec.yaml) in the 4 | // future. If not, the values below would default to using the project name when this becomes a 5 | // 'flutter create' template. 6 | 7 | // The application's name. By default this is also the title of the Flutter window. 8 | PRODUCT_NAME = flutter_app 9 | 10 | // The application's bundle identifier 11 | PRODUCT_BUNDLE_IDENTIFIER = com.example.flutterApp 12 | 13 | // The copyright displayed in application information 14 | PRODUCT_COPYRIGHT = Copyright © 2024 com.example. All rights reserved. 15 | -------------------------------------------------------------------------------- /samples/flutter_app/macos/Runner/Configs/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include "../../Flutter/Flutter-Debug.xcconfig" 2 | #include "Warnings.xcconfig" 3 | -------------------------------------------------------------------------------- /samples/flutter_app/macos/Runner/Configs/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include "../../Flutter/Flutter-Release.xcconfig" 2 | #include "Warnings.xcconfig" 3 | -------------------------------------------------------------------------------- /samples/flutter_app/macos/Runner/Configs/Warnings.xcconfig: -------------------------------------------------------------------------------- 1 | WARNING_CFLAGS = -Wall -Wconditional-uninitialized -Wnullable-to-nonnull-conversion -Wmissing-method-return-type -Woverlength-strings 2 | GCC_WARN_UNDECLARED_SELECTOR = YES 3 | CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES 4 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE 5 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES 6 | CLANG_WARN_PRAGMA_PACK = YES 7 | CLANG_WARN_STRICT_PROTOTYPES = YES 8 | CLANG_WARN_COMMA = YES 9 | GCC_WARN_STRICT_SELECTOR_MATCH = YES 10 | CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK = YES 11 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES 12 | GCC_WARN_SHADOW = YES 13 | CLANG_WARN_UNREACHABLE_CODE = YES 14 | -------------------------------------------------------------------------------- /samples/flutter_app/macos/Runner/DebugProfile.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.app-sandbox 6 | 7 | com.apple.security.cs.allow-jit 8 | 9 | com.apple.security.network.server 10 | 11 | com.apple.security.network.client 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /samples/flutter_app/macos/Runner/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIconFile 10 | 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | $(FLUTTER_BUILD_NAME) 21 | CFBundleVersion 22 | $(FLUTTER_BUILD_NUMBER) 23 | LSMinimumSystemVersion 24 | $(MACOSX_DEPLOYMENT_TARGET) 25 | NSHumanReadableCopyright 26 | $(PRODUCT_COPYRIGHT) 27 | NSMainNibFile 28 | MainMenu 29 | NSPrincipalClass 30 | NSApplication 31 | 32 | 33 | -------------------------------------------------------------------------------- /samples/flutter_app/macos/Runner/MainFlutterWindow.swift: -------------------------------------------------------------------------------- 1 | import Cocoa 2 | import FlutterMacOS 3 | 4 | class MainFlutterWindow: NSWindow { 5 | override func awakeFromNib() { 6 | let flutterViewController = FlutterViewController() 7 | let windowFrame = self.frame 8 | self.contentViewController = flutterViewController 9 | self.setFrame(windowFrame, display: true) 10 | 11 | RegisterGeneratedPlugins(registry: flutterViewController) 12 | 13 | super.awakeFromNib() 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /samples/flutter_app/macos/Runner/Release.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.app-sandbox 6 | 7 | com.apple.security.network.client 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /samples/flutter_app/macos/RunnerTests/RunnerTests.swift: -------------------------------------------------------------------------------- 1 | import FlutterMacOS 2 | import Cocoa 3 | import XCTest 4 | 5 | class RunnerTests: XCTestCase { 6 | 7 | func testExample() { 8 | // If you add code to the Runner application, consider adding tests here. 9 | // See https://developer.apple.com/documentation/xctest for more information about using XCTest. 10 | } 11 | 12 | } 13 | -------------------------------------------------------------------------------- /samples/flutter_app/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: generative_ai_flutter 2 | description: "Sample app for the google_generative_ai package" 3 | 4 | publish_to: none 5 | 6 | environment: 7 | sdk: ^3.2.0 8 | 9 | dependencies: 10 | flutter: 11 | sdk: flutter 12 | cupertino_icons: ^1.0.6 13 | flutter_markdown: any 14 | # Note: best practice here is to use a caret version constraint. We use `any` 15 | # here just for the purpose of the sample. 16 | google_generative_ai: any 17 | 18 | dev_dependencies: 19 | flutter_test: 20 | sdk: flutter 21 | flutter_lints: ^3.0.0 22 | 23 | flutter: 24 | uses-material-design: true 25 | assets: 26 | - assets/images/ 27 | 28 | # Note: this section is only used in order to resolve google_generative_ai to 29 | # the same repo as the sample. 30 | dependency_overrides: 31 | google_generative_ai: 32 | path: ../../pkgs/google_generative_ai 33 | -------------------------------------------------------------------------------- /samples/flutter_app/web/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google-gemini/deprecated-generative-ai-dart/19c1d6018b253ebfcd6a35eed7bc556cf6ff4d8e/samples/flutter_app/web/favicon.png -------------------------------------------------------------------------------- /samples/flutter_app/web/icons/Icon-192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google-gemini/deprecated-generative-ai-dart/19c1d6018b253ebfcd6a35eed7bc556cf6ff4d8e/samples/flutter_app/web/icons/Icon-192.png -------------------------------------------------------------------------------- /samples/flutter_app/web/icons/Icon-512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google-gemini/deprecated-generative-ai-dart/19c1d6018b253ebfcd6a35eed7bc556cf6ff4d8e/samples/flutter_app/web/icons/Icon-512.png -------------------------------------------------------------------------------- /samples/flutter_app/web/icons/Icon-maskable-192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google-gemini/deprecated-generative-ai-dart/19c1d6018b253ebfcd6a35eed7bc556cf6ff4d8e/samples/flutter_app/web/icons/Icon-maskable-192.png -------------------------------------------------------------------------------- /samples/flutter_app/web/icons/Icon-maskable-512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google-gemini/deprecated-generative-ai-dart/19c1d6018b253ebfcd6a35eed7bc556cf6ff4d8e/samples/flutter_app/web/icons/Icon-maskable-512.png -------------------------------------------------------------------------------- /samples/flutter_app/web/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | flutter_app 33 | 34 | 35 | 39 | 40 | 41 | 42 | 43 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /samples/flutter_app/web/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "flutter_app", 3 | "short_name": "flutter_app", 4 | "start_url": ".", 5 | "display": "standalone", 6 | "background_color": "#0175C2", 7 | "theme_color": "#0175C2", 8 | "description": "A new Flutter project.", 9 | "orientation": "portrait-primary", 10 | "prefer_related_applications": false, 11 | "icons": [ 12 | { 13 | "src": "icons/Icon-192.png", 14 | "sizes": "192x192", 15 | "type": "image/png" 16 | }, 17 | { 18 | "src": "icons/Icon-512.png", 19 | "sizes": "512x512", 20 | "type": "image/png" 21 | }, 22 | { 23 | "src": "icons/Icon-maskable-192.png", 24 | "sizes": "192x192", 25 | "type": "image/png", 26 | "purpose": "maskable" 27 | }, 28 | { 29 | "src": "icons/Icon-maskable-512.png", 30 | "sizes": "512x512", 31 | "type": "image/png", 32 | "purpose": "maskable" 33 | } 34 | ] 35 | } 36 | -------------------------------------------------------------------------------- /samples/flutter_app/windows/.gitignore: -------------------------------------------------------------------------------- 1 | flutter/ephemeral/ 2 | 3 | # Visual Studio user-specific files. 4 | *.suo 5 | *.user 6 | *.userosscache 7 | *.sln.docstates 8 | 9 | # Visual Studio build-related files. 10 | x64/ 11 | x86/ 12 | 13 | # Visual Studio cache files 14 | # files ending in .cache can be ignored 15 | *.[Cc]ache 16 | # but keep track of directories ending in .cache 17 | !*.[Cc]ache/ 18 | -------------------------------------------------------------------------------- /samples/flutter_app/windows/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Project-level configuration. 2 | cmake_minimum_required(VERSION 3.14) 3 | project(flutter_app LANGUAGES CXX) 4 | 5 | # The name of the executable created for the application. Change this to change 6 | # the on-disk name of your application. 7 | set(BINARY_NAME "flutter_app") 8 | 9 | # Explicitly opt in to modern CMake behaviors to avoid warnings with recent 10 | # versions of CMake. 11 | cmake_policy(VERSION 3.14...3.25) 12 | 13 | # Define build configuration option. 14 | get_property(IS_MULTICONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) 15 | if(IS_MULTICONFIG) 16 | set(CMAKE_CONFIGURATION_TYPES "Debug;Profile;Release" 17 | CACHE STRING "" FORCE) 18 | else() 19 | if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) 20 | set(CMAKE_BUILD_TYPE "Debug" CACHE 21 | STRING "Flutter build mode" FORCE) 22 | set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS 23 | "Debug" "Profile" "Release") 24 | endif() 25 | endif() 26 | # Define settings for the Profile build mode. 27 | set(CMAKE_EXE_LINKER_FLAGS_PROFILE "${CMAKE_EXE_LINKER_FLAGS_RELEASE}") 28 | set(CMAKE_SHARED_LINKER_FLAGS_PROFILE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE}") 29 | set(CMAKE_C_FLAGS_PROFILE "${CMAKE_C_FLAGS_RELEASE}") 30 | set(CMAKE_CXX_FLAGS_PROFILE "${CMAKE_CXX_FLAGS_RELEASE}") 31 | 32 | # Use Unicode for all projects. 33 | add_definitions(-DUNICODE -D_UNICODE) 34 | 35 | # Compilation settings that should be applied to most targets. 36 | # 37 | # Be cautious about adding new options here, as plugins use this function by 38 | # default. In most cases, you should add new options to specific targets instead 39 | # of modifying this function. 40 | function(APPLY_STANDARD_SETTINGS TARGET) 41 | target_compile_features(${TARGET} PUBLIC cxx_std_17) 42 | target_compile_options(${TARGET} PRIVATE /W4 /WX /wd"4100") 43 | target_compile_options(${TARGET} PRIVATE /EHsc) 44 | target_compile_definitions(${TARGET} PRIVATE "_HAS_EXCEPTIONS=0") 45 | target_compile_definitions(${TARGET} PRIVATE "$<$:_DEBUG>") 46 | endfunction() 47 | 48 | # Flutter library and tool build rules. 49 | set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") 50 | add_subdirectory(${FLUTTER_MANAGED_DIR}) 51 | 52 | # Application build; see runner/CMakeLists.txt. 53 | add_subdirectory("runner") 54 | 55 | 56 | # Generated plugin build rules, which manage building the plugins and adding 57 | # them to the application. 58 | include(flutter/generated_plugins.cmake) 59 | 60 | 61 | # === Installation === 62 | # Support files are copied into place next to the executable, so that it can 63 | # run in place. This is done instead of making a separate bundle (as on Linux) 64 | # so that building and running from within Visual Studio will work. 65 | set(BUILD_BUNDLE_DIR "$") 66 | # Make the "install" step default, as it's required to run. 67 | set(CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD 1) 68 | if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) 69 | set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) 70 | endif() 71 | 72 | set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") 73 | set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}") 74 | 75 | install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" 76 | COMPONENT Runtime) 77 | 78 | install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" 79 | COMPONENT Runtime) 80 | 81 | install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" 82 | COMPONENT Runtime) 83 | 84 | if(PLUGIN_BUNDLED_LIBRARIES) 85 | install(FILES "${PLUGIN_BUNDLED_LIBRARIES}" 86 | DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" 87 | COMPONENT Runtime) 88 | endif() 89 | 90 | # Copy the native assets provided by the build.dart from all packages. 91 | set(NATIVE_ASSETS_DIR "${PROJECT_BUILD_DIR}native_assets/windows/") 92 | install(DIRECTORY "${NATIVE_ASSETS_DIR}" 93 | DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" 94 | COMPONENT Runtime) 95 | 96 | # Fully re-copy the assets directory on each build to avoid having stale files 97 | # from a previous install. 98 | set(FLUTTER_ASSET_DIR_NAME "flutter_assets") 99 | install(CODE " 100 | file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") 101 | " COMPONENT Runtime) 102 | install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" 103 | DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) 104 | 105 | # Install the AOT library on non-Debug builds only. 106 | install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" 107 | CONFIGURATIONS Profile;Release 108 | COMPONENT Runtime) 109 | -------------------------------------------------------------------------------- /samples/flutter_app/windows/flutter/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # This file controls Flutter-level build steps. It should not be edited. 2 | cmake_minimum_required(VERSION 3.14) 3 | 4 | set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral") 5 | 6 | # Configuration provided via flutter tool. 7 | include(${EPHEMERAL_DIR}/generated_config.cmake) 8 | 9 | # TODO: Move the rest of this into files in ephemeral. See 10 | # https://github.com/flutter/flutter/issues/57146. 11 | set(WRAPPER_ROOT "${EPHEMERAL_DIR}/cpp_client_wrapper") 12 | 13 | # Set fallback configurations for older versions of the flutter tool. 14 | if (NOT DEFINED FLUTTER_TARGET_PLATFORM) 15 | set(FLUTTER_TARGET_PLATFORM "windows-x64") 16 | endif() 17 | 18 | # === Flutter Library === 19 | set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/flutter_windows.dll") 20 | 21 | # Published to parent scope for install step. 22 | set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE) 23 | set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE) 24 | set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) 25 | set(AOT_LIBRARY "${PROJECT_DIR}/build/windows/app.so" PARENT_SCOPE) 26 | 27 | list(APPEND FLUTTER_LIBRARY_HEADERS 28 | "flutter_export.h" 29 | "flutter_windows.h" 30 | "flutter_messenger.h" 31 | "flutter_plugin_registrar.h" 32 | "flutter_texture_registrar.h" 33 | ) 34 | list(TRANSFORM FLUTTER_LIBRARY_HEADERS PREPEND "${EPHEMERAL_DIR}/") 35 | add_library(flutter INTERFACE) 36 | target_include_directories(flutter INTERFACE 37 | "${EPHEMERAL_DIR}" 38 | ) 39 | target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}.lib") 40 | add_dependencies(flutter flutter_assemble) 41 | 42 | # === Wrapper === 43 | list(APPEND CPP_WRAPPER_SOURCES_CORE 44 | "core_implementations.cc" 45 | "standard_codec.cc" 46 | ) 47 | list(TRANSFORM CPP_WRAPPER_SOURCES_CORE PREPEND "${WRAPPER_ROOT}/") 48 | list(APPEND CPP_WRAPPER_SOURCES_PLUGIN 49 | "plugin_registrar.cc" 50 | ) 51 | list(TRANSFORM CPP_WRAPPER_SOURCES_PLUGIN PREPEND "${WRAPPER_ROOT}/") 52 | list(APPEND CPP_WRAPPER_SOURCES_APP 53 | "flutter_engine.cc" 54 | "flutter_view_controller.cc" 55 | ) 56 | list(TRANSFORM CPP_WRAPPER_SOURCES_APP PREPEND "${WRAPPER_ROOT}/") 57 | 58 | # Wrapper sources needed for a plugin. 59 | add_library(flutter_wrapper_plugin STATIC 60 | ${CPP_WRAPPER_SOURCES_CORE} 61 | ${CPP_WRAPPER_SOURCES_PLUGIN} 62 | ) 63 | apply_standard_settings(flutter_wrapper_plugin) 64 | set_target_properties(flutter_wrapper_plugin PROPERTIES 65 | POSITION_INDEPENDENT_CODE ON) 66 | set_target_properties(flutter_wrapper_plugin PROPERTIES 67 | CXX_VISIBILITY_PRESET hidden) 68 | target_link_libraries(flutter_wrapper_plugin PUBLIC flutter) 69 | target_include_directories(flutter_wrapper_plugin PUBLIC 70 | "${WRAPPER_ROOT}/include" 71 | ) 72 | add_dependencies(flutter_wrapper_plugin flutter_assemble) 73 | 74 | # Wrapper sources needed for the runner. 75 | add_library(flutter_wrapper_app STATIC 76 | ${CPP_WRAPPER_SOURCES_CORE} 77 | ${CPP_WRAPPER_SOURCES_APP} 78 | ) 79 | apply_standard_settings(flutter_wrapper_app) 80 | target_link_libraries(flutter_wrapper_app PUBLIC flutter) 81 | target_include_directories(flutter_wrapper_app PUBLIC 82 | "${WRAPPER_ROOT}/include" 83 | ) 84 | add_dependencies(flutter_wrapper_app flutter_assemble) 85 | 86 | # === Flutter tool backend === 87 | # _phony_ is a non-existent file to force this command to run every time, 88 | # since currently there's no way to get a full input/output list from the 89 | # flutter tool. 90 | set(PHONY_OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/_phony_") 91 | set_source_files_properties("${PHONY_OUTPUT}" PROPERTIES SYMBOLIC TRUE) 92 | add_custom_command( 93 | OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} 94 | ${CPP_WRAPPER_SOURCES_CORE} ${CPP_WRAPPER_SOURCES_PLUGIN} 95 | ${CPP_WRAPPER_SOURCES_APP} 96 | ${PHONY_OUTPUT} 97 | COMMAND ${CMAKE_COMMAND} -E env 98 | ${FLUTTER_TOOL_ENVIRONMENT} 99 | "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.bat" 100 | ${FLUTTER_TARGET_PLATFORM} $ 101 | VERBATIM 102 | ) 103 | add_custom_target(flutter_assemble DEPENDS 104 | "${FLUTTER_LIBRARY}" 105 | ${FLUTTER_LIBRARY_HEADERS} 106 | ${CPP_WRAPPER_SOURCES_CORE} 107 | ${CPP_WRAPPER_SOURCES_PLUGIN} 108 | ${CPP_WRAPPER_SOURCES_APP} 109 | ) 110 | -------------------------------------------------------------------------------- /samples/flutter_app/windows/runner/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.14) 2 | project(runner LANGUAGES CXX) 3 | 4 | # Define the application target. To change its name, change BINARY_NAME in the 5 | # top-level CMakeLists.txt, not the value here, or `flutter run` will no longer 6 | # work. 7 | # 8 | # Any new source files that you add to the application should be added here. 9 | add_executable(${BINARY_NAME} WIN32 10 | "flutter_window.cpp" 11 | "main.cpp" 12 | "utils.cpp" 13 | "win32_window.cpp" 14 | "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" 15 | "Runner.rc" 16 | "runner.exe.manifest" 17 | ) 18 | 19 | # Apply the standard set of build settings. This can be removed for applications 20 | # that need different build settings. 21 | apply_standard_settings(${BINARY_NAME}) 22 | 23 | # Add preprocessor definitions for the build version. 24 | target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION=\"${FLUTTER_VERSION}\"") 25 | target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_MAJOR=${FLUTTER_VERSION_MAJOR}") 26 | target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_MINOR=${FLUTTER_VERSION_MINOR}") 27 | target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_PATCH=${FLUTTER_VERSION_PATCH}") 28 | target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_BUILD=${FLUTTER_VERSION_BUILD}") 29 | 30 | # Disable Windows macros that collide with C++ standard library functions. 31 | target_compile_definitions(${BINARY_NAME} PRIVATE "NOMINMAX") 32 | 33 | # Add dependency libraries and include directories. Add any application-specific 34 | # dependencies here. 35 | target_link_libraries(${BINARY_NAME} PRIVATE flutter flutter_wrapper_app) 36 | target_link_libraries(${BINARY_NAME} PRIVATE "dwmapi.lib") 37 | target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}") 38 | 39 | # Run the Flutter tool portions of the build. This must not be removed. 40 | add_dependencies(${BINARY_NAME} flutter_assemble) 41 | -------------------------------------------------------------------------------- /samples/flutter_app/windows/runner/Runner.rc: -------------------------------------------------------------------------------- 1 | // Microsoft Visual C++ generated resource script. 2 | // 3 | #pragma code_page(65001) 4 | #include "resource.h" 5 | 6 | #define APSTUDIO_READONLY_SYMBOLS 7 | ///////////////////////////////////////////////////////////////////////////// 8 | // 9 | // Generated from the TEXTINCLUDE 2 resource. 10 | // 11 | #include "winres.h" 12 | 13 | ///////////////////////////////////////////////////////////////////////////// 14 | #undef APSTUDIO_READONLY_SYMBOLS 15 | 16 | ///////////////////////////////////////////////////////////////////////////// 17 | // English (United States) resources 18 | 19 | #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) 20 | LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US 21 | 22 | #ifdef APSTUDIO_INVOKED 23 | ///////////////////////////////////////////////////////////////////////////// 24 | // 25 | // TEXTINCLUDE 26 | // 27 | 28 | 1 TEXTINCLUDE 29 | BEGIN 30 | "resource.h\0" 31 | END 32 | 33 | 2 TEXTINCLUDE 34 | BEGIN 35 | "#include ""winres.h""\r\n" 36 | "\0" 37 | END 38 | 39 | 3 TEXTINCLUDE 40 | BEGIN 41 | "\r\n" 42 | "\0" 43 | END 44 | 45 | #endif // APSTUDIO_INVOKED 46 | 47 | 48 | ///////////////////////////////////////////////////////////////////////////// 49 | // 50 | // Icon 51 | // 52 | 53 | // Icon with lowest ID value placed first to ensure application icon 54 | // remains consistent on all systems. 55 | IDI_APP_ICON ICON "resources\\app_icon.ico" 56 | 57 | 58 | ///////////////////////////////////////////////////////////////////////////// 59 | // 60 | // Version 61 | // 62 | 63 | #if defined(FLUTTER_VERSION_MAJOR) && defined(FLUTTER_VERSION_MINOR) && defined(FLUTTER_VERSION_PATCH) && defined(FLUTTER_VERSION_BUILD) 64 | #define VERSION_AS_NUMBER FLUTTER_VERSION_MAJOR,FLUTTER_VERSION_MINOR,FLUTTER_VERSION_PATCH,FLUTTER_VERSION_BUILD 65 | #else 66 | #define VERSION_AS_NUMBER 1,0,0,0 67 | #endif 68 | 69 | #if defined(FLUTTER_VERSION) 70 | #define VERSION_AS_STRING FLUTTER_VERSION 71 | #else 72 | #define VERSION_AS_STRING "1.0.0" 73 | #endif 74 | 75 | VS_VERSION_INFO VERSIONINFO 76 | FILEVERSION VERSION_AS_NUMBER 77 | PRODUCTVERSION VERSION_AS_NUMBER 78 | FILEFLAGSMASK VS_FFI_FILEFLAGSMASK 79 | #ifdef _DEBUG 80 | FILEFLAGS VS_FF_DEBUG 81 | #else 82 | FILEFLAGS 0x0L 83 | #endif 84 | FILEOS VOS__WINDOWS32 85 | FILETYPE VFT_APP 86 | FILESUBTYPE 0x0L 87 | BEGIN 88 | BLOCK "StringFileInfo" 89 | BEGIN 90 | BLOCK "040904e4" 91 | BEGIN 92 | VALUE "CompanyName", "com.example" "\0" 93 | VALUE "FileDescription", "flutter_app" "\0" 94 | VALUE "FileVersion", VERSION_AS_STRING "\0" 95 | VALUE "InternalName", "flutter_app" "\0" 96 | VALUE "LegalCopyright", "Copyright (C) 2024 com.example. All rights reserved." "\0" 97 | VALUE "OriginalFilename", "flutter_app.exe" "\0" 98 | VALUE "ProductName", "flutter_app" "\0" 99 | VALUE "ProductVersion", VERSION_AS_STRING "\0" 100 | END 101 | END 102 | BLOCK "VarFileInfo" 103 | BEGIN 104 | VALUE "Translation", 0x409, 1252 105 | END 106 | END 107 | 108 | #endif // English (United States) resources 109 | ///////////////////////////////////////////////////////////////////////////// 110 | 111 | 112 | 113 | #ifndef APSTUDIO_INVOKED 114 | ///////////////////////////////////////////////////////////////////////////// 115 | // 116 | // Generated from the TEXTINCLUDE 3 resource. 117 | // 118 | 119 | 120 | ///////////////////////////////////////////////////////////////////////////// 121 | #endif // not APSTUDIO_INVOKED 122 | -------------------------------------------------------------------------------- /samples/flutter_app/windows/runner/flutter_window.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2024 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include "flutter_window.h" 16 | 17 | #include 18 | 19 | #include "flutter/generated_plugin_registrant.h" 20 | 21 | FlutterWindow::FlutterWindow(const flutter::DartProject& project) 22 | : project_(project) {} 23 | 24 | FlutterWindow::~FlutterWindow() {} 25 | 26 | bool FlutterWindow::OnCreate() { 27 | if (!Win32Window::OnCreate()) { 28 | return false; 29 | } 30 | 31 | RECT frame = GetClientArea(); 32 | 33 | // The size here must match the window dimensions to avoid unnecessary surface 34 | // creation / destruction in the startup path. 35 | flutter_controller_ = std::make_unique( 36 | frame.right - frame.left, frame.bottom - frame.top, project_); 37 | // Ensure that basic setup of the controller was successful. 38 | if (!flutter_controller_->engine() || !flutter_controller_->view()) { 39 | return false; 40 | } 41 | RegisterPlugins(flutter_controller_->engine()); 42 | SetChildContent(flutter_controller_->view()->GetNativeWindow()); 43 | 44 | flutter_controller_->engine()->SetNextFrameCallback([&]() { 45 | this->Show(); 46 | }); 47 | 48 | // Flutter can complete the first frame before the "show window" callback is 49 | // registered. The following call ensures a frame is pending to ensure the 50 | // window is shown. It is a no-op if the first frame hasn't completed yet. 51 | flutter_controller_->ForceRedraw(); 52 | 53 | return true; 54 | } 55 | 56 | void FlutterWindow::OnDestroy() { 57 | if (flutter_controller_) { 58 | flutter_controller_ = nullptr; 59 | } 60 | 61 | Win32Window::OnDestroy(); 62 | } 63 | 64 | LRESULT 65 | FlutterWindow::MessageHandler(HWND hwnd, UINT const message, 66 | WPARAM const wparam, 67 | LPARAM const lparam) noexcept { 68 | // Give Flutter, including plugins, an opportunity to handle window messages. 69 | if (flutter_controller_) { 70 | std::optional result = 71 | flutter_controller_->HandleTopLevelWindowProc(hwnd, message, wparam, 72 | lparam); 73 | if (result) { 74 | return *result; 75 | } 76 | } 77 | 78 | switch (message) { 79 | case WM_FONTCHANGE: 80 | flutter_controller_->engine()->ReloadSystemFonts(); 81 | break; 82 | } 83 | 84 | return Win32Window::MessageHandler(hwnd, message, wparam, lparam); 85 | } 86 | -------------------------------------------------------------------------------- /samples/flutter_app/windows/runner/flutter_window.h: -------------------------------------------------------------------------------- 1 | // Copyright 2024 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifndef RUNNER_FLUTTER_WINDOW_H_ 16 | #define RUNNER_FLUTTER_WINDOW_H_ 17 | 18 | #include 19 | #include 20 | 21 | #include 22 | 23 | #include "win32_window.h" 24 | 25 | // A window that does nothing but host a Flutter view. 26 | class FlutterWindow : public Win32Window { 27 | public: 28 | // Creates a new FlutterWindow hosting a Flutter view running |project|. 29 | explicit FlutterWindow(const flutter::DartProject& project); 30 | virtual ~FlutterWindow(); 31 | 32 | protected: 33 | // Win32Window: 34 | bool OnCreate() override; 35 | void OnDestroy() override; 36 | LRESULT MessageHandler(HWND window, UINT const message, WPARAM const wparam, 37 | LPARAM const lparam) noexcept override; 38 | 39 | private: 40 | // The project to run. 41 | flutter::DartProject project_; 42 | 43 | // The Flutter instance hosted by this window. 44 | std::unique_ptr flutter_controller_; 45 | }; 46 | 47 | #endif // RUNNER_FLUTTER_WINDOW_H_ 48 | -------------------------------------------------------------------------------- /samples/flutter_app/windows/runner/main.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2024 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include 16 | #include 17 | #include 18 | 19 | #include "flutter_window.h" 20 | #include "utils.h" 21 | 22 | int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev, 23 | _In_ wchar_t *command_line, _In_ int show_command) { 24 | // Attach to console when present (e.g., 'flutter run') or create a 25 | // new console when running with a debugger. 26 | if (!::AttachConsole(ATTACH_PARENT_PROCESS) && ::IsDebuggerPresent()) { 27 | CreateAndAttachConsole(); 28 | } 29 | 30 | // Initialize COM, so that it is available for use in the library and/or 31 | // plugins. 32 | ::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED); 33 | 34 | flutter::DartProject project(L"data"); 35 | 36 | std::vector command_line_arguments = 37 | GetCommandLineArguments(); 38 | 39 | project.set_dart_entrypoint_arguments(std::move(command_line_arguments)); 40 | 41 | FlutterWindow window(project); 42 | Win32Window::Point origin(10, 10); 43 | Win32Window::Size size(1280, 720); 44 | if (!window.Create(L"flutter_app", origin, size)) { 45 | return EXIT_FAILURE; 46 | } 47 | window.SetQuitOnClose(true); 48 | 49 | ::MSG msg; 50 | while (::GetMessage(&msg, nullptr, 0, 0)) { 51 | ::TranslateMessage(&msg); 52 | ::DispatchMessage(&msg); 53 | } 54 | 55 | ::CoUninitialize(); 56 | return EXIT_SUCCESS; 57 | } 58 | -------------------------------------------------------------------------------- /samples/flutter_app/windows/runner/resource.h: -------------------------------------------------------------------------------- 1 | // Copyright 2024 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | //{{NO_DEPENDENCIES}} 16 | // Microsoft Visual C++ generated include file. 17 | // Used by Runner.rc 18 | // 19 | #define IDI_APP_ICON 101 20 | 21 | // Next default values for new objects 22 | // 23 | #ifdef APSTUDIO_INVOKED 24 | #ifndef APSTUDIO_READONLY_SYMBOLS 25 | #define _APS_NEXT_RESOURCE_VALUE 102 26 | #define _APS_NEXT_COMMAND_VALUE 40001 27 | #define _APS_NEXT_CONTROL_VALUE 1001 28 | #define _APS_NEXT_SYMED_VALUE 101 29 | #endif 30 | #endif 31 | -------------------------------------------------------------------------------- /samples/flutter_app/windows/runner/resources/app_icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google-gemini/deprecated-generative-ai-dart/19c1d6018b253ebfcd6a35eed7bc556cf6ff4d8e/samples/flutter_app/windows/runner/resources/app_icon.ico -------------------------------------------------------------------------------- /samples/flutter_app/windows/runner/runner.exe.manifest: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PerMonitorV2 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /samples/flutter_app/windows/runner/utils.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2024 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include "utils.h" 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | #include 23 | 24 | void CreateAndAttachConsole() { 25 | if (::AllocConsole()) { 26 | FILE *unused; 27 | if (freopen_s(&unused, "CONOUT$", "w", stdout)) { 28 | _dup2(_fileno(stdout), 1); 29 | } 30 | if (freopen_s(&unused, "CONOUT$", "w", stderr)) { 31 | _dup2(_fileno(stdout), 2); 32 | } 33 | std::ios::sync_with_stdio(); 34 | FlutterDesktopResyncOutputStreams(); 35 | } 36 | } 37 | 38 | std::vector GetCommandLineArguments() { 39 | // Convert the UTF-16 command line arguments to UTF-8 for the Engine to use. 40 | int argc; 41 | wchar_t** argv = ::CommandLineToArgvW(::GetCommandLineW(), &argc); 42 | if (argv == nullptr) { 43 | return std::vector(); 44 | } 45 | 46 | std::vector command_line_arguments; 47 | 48 | // Skip the first argument as it's the binary name. 49 | for (int i = 1; i < argc; i++) { 50 | command_line_arguments.push_back(Utf8FromUtf16(argv[i])); 51 | } 52 | 53 | ::LocalFree(argv); 54 | 55 | return command_line_arguments; 56 | } 57 | 58 | std::string Utf8FromUtf16(const wchar_t* utf16_string) { 59 | if (utf16_string == nullptr) { 60 | return std::string(); 61 | } 62 | int target_length = ::WideCharToMultiByte( 63 | CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, 64 | -1, nullptr, 0, nullptr, nullptr) 65 | -1; // remove the trailing null character 66 | int input_length = (int)wcslen(utf16_string); 67 | std::string utf8_string; 68 | if (target_length <= 0 || target_length > utf8_string.max_size()) { 69 | return utf8_string; 70 | } 71 | utf8_string.resize(target_length); 72 | int converted_length = ::WideCharToMultiByte( 73 | CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, 74 | input_length, utf8_string.data(), target_length, nullptr, nullptr); 75 | if (converted_length == 0) { 76 | return std::string(); 77 | } 78 | return utf8_string; 79 | } 80 | -------------------------------------------------------------------------------- /samples/flutter_app/windows/runner/utils.h: -------------------------------------------------------------------------------- 1 | // Copyright 2024 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifndef RUNNER_UTILS_H_ 16 | #define RUNNER_UTILS_H_ 17 | 18 | #include 19 | #include 20 | 21 | // Creates a console for the process, and redirects stdout and stderr to 22 | // it for both the runner and the Flutter library. 23 | void CreateAndAttachConsole(); 24 | 25 | // Takes a null-terminated wchar_t* encoded in UTF-16 and returns a std::string 26 | // encoded in UTF-8. Returns an empty std::string on failure. 27 | std::string Utf8FromUtf16(const wchar_t* utf16_string); 28 | 29 | // Gets the command line arguments passed in as a std::vector, 30 | // encoded in UTF-8. Returns an empty std::vector on failure. 31 | std::vector GetCommandLineArguments(); 32 | 33 | #endif // RUNNER_UTILS_H_ 34 | -------------------------------------------------------------------------------- /samples/flutter_app/windows/runner/win32_window.h: -------------------------------------------------------------------------------- 1 | // Copyright 2024 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifndef RUNNER_WIN32_WINDOW_H_ 16 | #define RUNNER_WIN32_WINDOW_H_ 17 | 18 | #include 19 | 20 | #include 21 | #include 22 | #include 23 | 24 | // A class abstraction for a high DPI-aware Win32 Window. Intended to be 25 | // inherited from by classes that wish to specialize with custom 26 | // rendering and input handling 27 | class Win32Window { 28 | public: 29 | struct Point { 30 | unsigned int x; 31 | unsigned int y; 32 | Point(unsigned int x, unsigned int y) : x(x), y(y) {} 33 | }; 34 | 35 | struct Size { 36 | unsigned int width; 37 | unsigned int height; 38 | Size(unsigned int width, unsigned int height) 39 | : width(width), height(height) {} 40 | }; 41 | 42 | Win32Window(); 43 | virtual ~Win32Window(); 44 | 45 | // Creates a win32 window with |title| that is positioned and sized using 46 | // |origin| and |size|. New windows are created on the default monitor. Window 47 | // sizes are specified to the OS in physical pixels, hence to ensure a 48 | // consistent size this function will scale the inputted width and height as 49 | // as appropriate for the default monitor. The window is invisible until 50 | // |Show| is called. Returns true if the window was created successfully. 51 | bool Create(const std::wstring& title, const Point& origin, const Size& size); 52 | 53 | // Show the current window. Returns true if the window was successfully shown. 54 | bool Show(); 55 | 56 | // Release OS resources associated with window. 57 | void Destroy(); 58 | 59 | // Inserts |content| into the window tree. 60 | void SetChildContent(HWND content); 61 | 62 | // Returns the backing Window handle to enable clients to set icon and other 63 | // window properties. Returns nullptr if the window has been destroyed. 64 | HWND GetHandle(); 65 | 66 | // If true, closing this window will quit the application. 67 | void SetQuitOnClose(bool quit_on_close); 68 | 69 | // Return a RECT representing the bounds of the current client area. 70 | RECT GetClientArea(); 71 | 72 | protected: 73 | // Processes and route salient window messages for mouse handling, 74 | // size change and DPI. Delegates handling of these to member overloads that 75 | // inheriting classes can handle. 76 | virtual LRESULT MessageHandler(HWND window, 77 | UINT const message, 78 | WPARAM const wparam, 79 | LPARAM const lparam) noexcept; 80 | 81 | // Called when CreateAndShow is called, allowing subclass window-related 82 | // setup. Subclasses should return false if setup fails. 83 | virtual bool OnCreate(); 84 | 85 | // Called when Destroy is called. 86 | virtual void OnDestroy(); 87 | 88 | private: 89 | friend class WindowClassRegistrar; 90 | 91 | // OS callback called by message pump. Handles the WM_NCCREATE message which 92 | // is passed when the non-client area is being created and enables automatic 93 | // non-client DPI scaling so that the non-client area automatically 94 | // responds to changes in DPI. All other messages are handled by 95 | // MessageHandler. 96 | static LRESULT CALLBACK WndProc(HWND const window, 97 | UINT const message, 98 | WPARAM const wparam, 99 | LPARAM const lparam) noexcept; 100 | 101 | // Retrieves a class instance pointer for |window| 102 | static Win32Window* GetThisFromHandle(HWND const window) noexcept; 103 | 104 | // Update the window frame's theme to match the system theme. 105 | static void UpdateTheme(HWND const window); 106 | 107 | bool quit_on_close_ = false; 108 | 109 | // window handle for top level window. 110 | HWND window_handle_ = nullptr; 111 | 112 | // window handle for hosted content. 113 | HWND child_content_ = nullptr; 114 | }; 115 | 116 | #endif // RUNNER_WIN32_WINDOW_H_ 117 | --------------------------------------------------------------------------------