From 738329a4717378ea71719d7750d5d5783e1dba35 Mon Sep 17 00:00:00 2001 From: Divyang Panchasara Date: Sat, 16 Aug 2025 14:51:44 +0530 Subject: [PATCH 1/5] Docs/readme ci fix (#1) * docs: rewrite README; add MIT LICENSE * ci: add dev branch pipeline + branch-aware prerelease versioning --- .github/workflows/ci.yml | 25 +++++-- LICENSE | 20 ++++++ README.md | 149 +++++++++++++++++++++------------------ 3 files changed, 120 insertions(+), 74 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2de845c..98768a5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -2,7 +2,7 @@ name: CI on: push: - branches: [ main ] + branches: [ main, dev ] pull_request: branches: [ main ] workflow_dispatch: @@ -42,8 +42,10 @@ jobs: env: GEMINI_API_KEY: ${{ secrets.GEMINI_API_KEY }} run: dotnet test Nayvid.Gemini.slnx --configuration Release --no-build --verbosity normal + - name: Determine changed projects id: changed + shell: bash run: | git fetch origin main --depth=1 || true BASE="origin/main" @@ -68,8 +70,7 @@ jobs: done fi done - # Always include core if any project changed - if [[ ${#PROJECTS[@]} -gt 0 ]]; then PROJECTS+=("Nayvid.Gemini.Core/Nayvid.Gemini.Core.csproj"); fi + # (Core auto-include removed – adjust if a shared core project is added later) # Unique UNIQUE=$(printf '%s\n' "${PROJECTS[@]}" | sort -u) echo "Projects to pack:\n$UNIQUE" @@ -77,6 +78,7 @@ jobs: echo "pack_list=$LIST" >> $GITHUB_OUTPUT - name: Derive version id: version + shell: bash run: | # Derive version from workflow input, commit message (release: x.y.z) or fallback to 0.1.0+ INPUT_VER="${{ github.event.inputs.release_version }}" @@ -86,7 +88,15 @@ jobs: VER="${BASH_REMATCH[1]}" else SHORT=$(git rev-parse --short HEAD) - VER="0.1.0-$SHORT" + # Branch-aware prerelease tagging: dev -> -dev., other branches -> -beta.. + if [[ "$GITHUB_REF_NAME" == "dev" ]]; then + VER="0.1.0-dev.$SHORT" + elif [[ "$GITHUB_REF_TYPE" == "branch" && "$GITHUB_REF_NAME" != "main" ]]; then + SAFE_BRANCH=$(echo "$GITHUB_REF_NAME" | tr '/' '-') + VER="0.1.0-beta.$SAFE_BRANCH.$SHORT" + else + VER="0.1.0-$SHORT" + fi fi fi echo "Using version: $VER" @@ -94,6 +104,7 @@ jobs: - name: Pack changed projects if: steps.changed.outputs.pack_list != '' + shell: bash run: | IFS=',' read -ra ARR <<< "${{ steps.changed.outputs.pack_list }}" mkdir -p artifacts @@ -125,6 +136,7 @@ jobs: - name: Create/Update freeze branch if: ${{ github.event.inputs.create_release == 'true' || startsWith(github.event.head_commit.message, 'release:') }} + shell: bash run: | VER="${{ needs.build-test-pack.outputs.derived_version }}" git config --global user.name "github-actions" @@ -143,6 +155,7 @@ jobs: env: NUGET_API_KEY: ${{ secrets.NUGET_API_KEY }} if: secrets.NUGET_API_KEY != '' + shell: bash run: | for f in artifacts/*.nupkg; do echo "Pushing $f" @@ -153,6 +166,7 @@ jobs: if: github.repository_owner != '' env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + shell: bash run: | OWNER=${{ github.repository_owner }} for f in artifacts/*.nupkg; do @@ -160,5 +174,4 @@ jobs: dotnet nuget push "$f" --api-key "$GITHUB_TOKEN" --source https://nuget.pkg.github.com/$OWNER/index.json --skip-duplicate done - - name: Publish packages - if: false # legacy step disabled + # Removed invalid empty step placeholder that caused workflow lint error diff --git a/LICENSE b/LICENSE index 7042835..f8aa7f7 100644 --- a/LICENSE +++ b/LICENSE @@ -1,5 +1,25 @@ MIT License +Copyright (c) 2025 Nayvid + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE.MIT License + Copyright (c) 2025 Nayvid Technology LLP Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/README.md b/README.md index 338637f..5b3c50c 100644 --- a/README.md +++ b/README.md @@ -1,86 +1,99 @@ -# ngemini / Nayvid Gemini SDK (Multi-domain) +# ngemini – Nayvid Gemini SDK (Multi‑domain) -This repository provides a modular .NET SDK surface for interacting with Google Gemini style capabilities (video, image, music, embeddings, speech, long-context utilities, structured output). Current implementations are placeholder/fake for rapid iteration – they demonstrate patterns, shapes and testing strategy. +> Status: Experimental / pre-release. Core shapes are stabilizing; transports and real HTTP integrations are still stubs. -## Projects -- Core: shared primitives (Operation, GeminiError, RetryHelper, options, transport abstraction) -- Video, Image, Music, Embeddings, Speech, LongContext, StructuredOutput domain libraries -- Test projects per domain (xUnit) -- Sample console app demonstrating multi-domain usage +![CI](https://github.com/nayvidtechnology/ngemini/actions/workflows/ci.yml/badge.svg) -## Getting Started -Install the packages (once published to NuGet): -``` +This repository provides a modular .NET 9 SDK surface for interacting with Google Gemini style capabilities: + +Domains: Video, Image, Music, Embeddings, Speech, Long‑Context utilities, Structured Output. + +Current implementations simulate responses (no real network) except the dedicated real samples which call public endpoints directly. This lets you explore client patterns, retry logic shaping, long‑running operation polling, and test strategy ahead of wiring real REST calls. + +## Project Layout +| Folder | Purpose | +|--------|---------| +| `Nayvid.Gemini.Core` | Core primitives (Operation, exceptions, JSON helpers, transport abstraction) | +| `Nayvid.Gemini.*` | Domain clients (video, image, speech, music, embeddings, structured, long context) | +| `*.Tests` | xUnit unit tests per domain | +| `samples/` | End‑to‑end sample apps (console, API, Blazor, MAUI, real video/API) | +| `.github/workflows/ci.yml` | Build, test, selective pack workflow | + +## Quick Start +Add packages (after publishing): +```powershell dotnet add package Nayvid.Gemini.Core - dotnet add package Nayvid.Gemini.Video -# etc. +dotnet add package Nayvid.Gemini.Video +# etc ``` -### API Key Configuration -Set an environment variable before running: +Set your API key (PowerShell): +```powershell +$Env:GEMINI_API_KEY = 'your_real_key' ``` -set GEMINI_API_KEY=your_key_here # Windows PowerShell: $Env:GEMINI_API_KEY = 'your_key_here' +Or Bash: +```bash +export GEMINI_API_KEY=your_real_key +``` + +Run a sample: +```powershell +dotnet run --project samples/Nayvid.ConsoleDemo/ConsoleDemo.csproj ``` -The console sample reads `GEMINI_API_KEY` and falls back to a placeholder. Avoid hard-coding secrets in source. Consider using `dotnet user-secrets` for local dev. -### Retry Guidance -`RetryHelper` centralizes exponential backoff with jitter. Usage pattern for HTTP calls (pseudo): +## Samples Matrix +| Sample | Description | Command | +|--------|-------------|---------| +| ConsoleDemo | Sequential multi‑domain demo (mock transport fallback) | `dotnet run --project samples/Nayvid.ConsoleDemo/ConsoleDemo.csproj` | +| AspNetSample | Minimal API (Swagger + video/image/speech/music endpoints) | `dotnet run --project samples/Nayvid.AspNetSample/Nayvid.AspNetSample.csproj` → browse `/swagger` | +| BlazorSample | WASM UI calling domain clients in-browser | `dotnet run --project samples/Nayvid.BlazorSample/Nayvid.BlazorSample.csproj` | +| MauiSample | Cross‑platform (Windows/Android/iOS) UI | `dotnet build samples/Nayvid.MauiSample/Nayvid.MauiSample.csproj` | +| RealApiSample | Uses real API key path for image/speech (placeholder logic inside) | `dotnet run --project samples/Nayvid.RealApiSample/Nayvid.RealApiSample.csproj` | +| RealVideoSample | Direct long‑running video generation via `veo-3.0-generate-preview` REST | `dotnet run --project samples/Nayvid.RealVideoSample/Nayvid.RealVideoSample.csproj -- "Prompt"` | + +## Long‑Running Operations +Video (and some image/music scenarios) return an `Operation`. Poll with `WaitForCompletionAsync` or explicit GET loop. Sample pattern: +```csharp +await foreach (var op in client.WaitForCompletionAsync(operationName, TimeSpan.FromSeconds(2))) { + if (op.Status == "DONE") { /* use op.Result */ } +} ``` -for attempt in 1..maxAttempts: - response = await transport.SendAsync() - if success: break - if !RetryHelper.ShouldRetry(status): throw - await Task.Delay(RetryHelper.ComputeBackoff(attempt, baseDelay, maxDelay)) + +## Retry Strategy (Planned) +Transient 5xx / 429 responses will use exponential backoff w/ jitter. Pseudocode: +```text +for attempt in 1..N + send + if success break + if !ShouldRetry(status) throw + await Delay(ComputeBackoff(attempt)) ``` -Future real HTTP implementations should wrap transient (5xx, 429) failures with this logic and surface final errors via `GeminiApiException`. -### Long-running Operations -Video/Image/Music generation return an `Operation`. Use `WaitForCompletionAsync` (pattern demonstrated in video client) or poll manually. `Operation.IsDone` / `IsFailed` convenience flags assist flow control. +## Development Workflow +1. Create feature branch +2. Implement + add/update unit tests +3. `dotnet test` (all green) & run samples +4. Submit PR – CI builds, runs tests, identifies changed projects, packs only what changed -### Samples -Samples provided: +## Selective Packing +The CI script diffs against `origin/main` to compute affected project list and always adds `Core` if any domain changed. Packed `.nupkg` files are uploaded as artifacts; publishing requires environment approval + API keys. -| Sample | Description | Run Command | -|--------|-------------|-------------| -| ConsoleDemo | Multi-domain sequential demo | `dotnet run --project samples/Nayvid.ConsoleDemo/ConsoleDemo.csproj` | -| AspNetSample | Minimal API with video/image/speech/music endpoints + Swagger | `dotnet run --project samples/Nayvid.AspNetSample/Nayvid.AspNetSample.csproj` then browse `/swagger` | -| BlazorSample | WebAssembly UI for prompts (video/image/speech) | (Serve with a static host: `dotnet run --project samples/Nayvid.BlazorSample/Nayvid.BlazorSample.csproj`) | -| MauiSample | Cross-platform UI (video/image/speech/music) | `dotnet build samples/Nayvid.MauiSample/Nayvid.MauiSample.csproj` then deploy via platform tooling | +## Real Video Sample +`samples/Nayvid.RealVideoSample` illustrates direct calling of the `predictLongRunning` endpoint for model `veo-3.0-generate-preview` and polls until `done` then downloads the MP4. -Set environment variable first (PowerShell): -``` -$Env:GEMINI_API_KEY = 'your_key' -``` -Or Bash: -``` -export GEMINI_API_KEY=your_key -``` +## Roadmap +- Implement real HTTP transport + auth (bearer / API key) per domain +- Streaming generation APIs +- Structured schema enforcement (STJ source generators) +- Cancellation/timeouts wrapping each call +- NuGet meta-package aggregator +- Rich telemetry (OpenTelemetry instrumentation hooks) -### Roadmap -- Replace fake stub logic with real REST calls (Video upload/resumable already partially patterned) -- Add streaming APIs for text / media where supported -- Add cancellation + timeout wrappers per operation -- Introduce structured schema enforcement (System.Text.Json source generators or reflection-based validation) -- Provide a meta-package aggregator - -### Contributing -1. Fork & create a feature branch -2. Add or update tests (all domains) – fast unit tests required -3. Run CI (build, test, pack) locally before PR -4. Submit PR with concise description - -## CI / Packaging Strategy -The GitHub workflow will be enhanced to: -- Detect changed project directories vs main branch -- Only `dotnet pack` those changed domains (plus Core if shared code changed) -- On tagged release or version bump commit, push packages to NuGet - -Planned detection script outline (pseudo): -``` -changed = git diff --name-only origin/main...HEAD -projects = changed paths mapped to csproj roots -pack list = closure including Core when any domain changes -``` +## Security / Keys +Never commit real API keys. Use environment variables or `dotnet user-secrets`. CI expects `GEMINI_API_KEY` only for integration tests (optional paths skip if absent). + +## Contributing +PRs welcome after opening an issue for large changes. Keep tests fast & deterministic. ## License -MIT (add LICENSE file). +MIT (LICENSE to be added). From de619dfa2b5bc1b98e92113bb506bbb7c4e540c4 Mon Sep 17 00:00:00 2001 From: Divyang Panchasara Date: Sat, 16 Aug 2025 14:54:56 +0530 Subject: [PATCH 2/5] ci: remove invalid if expression on secrets.NUGET_API_KEY --- .github/workflows/ci.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 98768a5..9d26162 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -154,9 +154,12 @@ jobs: - name: Publish to NuGet (manual approval gated env) env: NUGET_API_KEY: ${{ secrets.NUGET_API_KEY }} - if: secrets.NUGET_API_KEY != '' shell: bash run: | + if [ -z "$NUGET_API_KEY" ]; then + echo "NUGET_API_KEY not set; skipping NuGet publish." + exit 0 + fi for f in artifacts/*.nupkg; do echo "Pushing $f" dotnet nuget push "$f" --api-key "$NUGET_API_KEY" --source https://api.nuget.org/v3/index.json --skip-duplicate From 9e902019c3ced6ccd39f06cb633aa7b7b3699a94 Mon Sep 17 00:00:00 2001 From: Divyang Panchasara Date: Sat, 16 Aug 2025 14:55:36 +0530 Subject: [PATCH 3/5] update vs code setting --- .vscode/launch.json | 69 +++++++++++++++++++++++++++++++++++++++++++ .vscode/settings.json | 3 ++ .vscode/tasks.json | 40 +++++++++++++++++++++++++ 3 files changed, 112 insertions(+) create mode 100644 .vscode/launch.json create mode 100644 .vscode/settings.json create mode 100644 .vscode/tasks.json diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..400378b --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,69 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "name": "Run Console Demo", + "type": "coreclr", + "request": "launch", + "program": "${workspaceFolder}/samples/Nayvid.ConsoleDemo/bin/Debug/net9.0/ConsoleDemo.dll", + "preLaunchTask": "build ConsoleDemo", + "cwd": "${workspaceFolder}", + // GEMINI_API_KEY taken from shell environment. Set before F5: $Env:GEMINI_API_KEY = 'real_key' + "env": {}, + "console": "integratedTerminal" + }, + { + "name": "Run ASP.NET Sample", + "type": "coreclr", + "request": "launch", + "program": "${workspaceFolder}/samples/Nayvid.AspNetSample/bin/Debug/net9.0/Nayvid.AspNetSample.dll", + "preLaunchTask": "build AspNetSample", + "cwd": "${workspaceFolder}/samples/Nayvid.AspNetSample", + "env": { "ASPNETCORE_URLS": "http://localhost:5000" }, + "serverReadyAction": { + "action": "openExternally", + "pattern": "Now listening on: (https?://\\S+)" + } + }, + { + "name": "Run Blazor Sample (WASM)", + "type": "coreclr", + "request": "launch", + "program": "${workspaceFolder}/samples/Nayvid.BlazorSample/bin/Debug/net9.0/Nayvid.BlazorSample.dll", + "preLaunchTask": "build BlazorSample", + "cwd": "${workspaceFolder}/samples/Nayvid.BlazorSample", + "env": {}, + "serverReadyAction": { + "action": "openExternally", + "pattern": "Now listening on: (https?://\\S+)" + } + }, + { + "name": "Run Real API Sample", + "type": "coreclr", + "request": "launch", + "program": "${workspaceFolder}/samples/Nayvid.RealApiSample/bin/Debug/net9.0/Nayvid.RealApiSample.dll", + "preLaunchTask": "build RealApiSample", + "cwd": "${workspaceFolder}", + "env": {}, + "console": "integratedTerminal" + }, + { + "name": "Run Real Video Sample", + "type": "coreclr", + "request": "launch", + "program": "${workspaceFolder}/samples/Nayvid.RealVideoSample/bin/Debug/net9.0/Nayvid.RealVideoSample.dll", + "preLaunchTask": "build RealVideoSample", + "cwd": "${workspaceFolder}", + "env": {}, + "args": ["A close up cinematic shot of ocean waves glistening at sunrise"], + "console": "integratedTerminal" + } + ], + "compounds": [ + { + "name": "API + Blazor", + "configurations": ["Run ASP.NET Sample", "Run Blazor Sample (WASM)"] + } + ] +} diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..67c2240 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "FSharp.suggestGitignore": false +} \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 0000000..fb9fe22 --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,40 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "label": "build ConsoleDemo", + "type": "shell", + "command": "dotnet build samples/Nayvid.ConsoleDemo/ConsoleDemo.csproj", + "problemMatcher": "$msCompile", + "group": "build" + }, + { + "label": "build AspNetSample", + "type": "shell", + "command": "dotnet build samples/Nayvid.AspNetSample/Nayvid.AspNetSample.csproj", + "problemMatcher": "$msCompile", + "group": "build" + }, + { + "label": "build BlazorSample", + "type": "shell", + "command": "dotnet build samples/Nayvid.BlazorSample/Nayvid.BlazorSample.csproj", + "problemMatcher": "$msCompile", + "group": "build" + }, + { + "label": "build RealApiSample", + "type": "shell", + "command": "dotnet build samples/Nayvid.RealApiSample/Nayvid.RealApiSample.csproj", + "problemMatcher": "$msCompile", + "group": "build" + }, + { + "label": "build RealVideoSample", + "type": "shell", + "command": "dotnet build samples/Nayvid.RealVideoSample/Nayvid.RealVideoSample.csproj", + "problemMatcher": "$msCompile", + "group": "build" + } + ] +} From 791a073a95fb18e5120bbdd392a538e130a53139 Mon Sep 17 00:00:00 2001 From: Divyang Panchasara Date: Sat, 16 Aug 2025 14:57:11 +0530 Subject: [PATCH 4/5] ci: robust changed project detection when no merge base (unrelated histories) --- .github/workflows/ci.yml | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9d26162..025cb27 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -51,7 +51,17 @@ jobs: BASE="origin/main" if ! git rev-parse --verify origin/main; then BASE=$(git rev-list --max-parents=0 HEAD | tail -n1); fi echo "Base ref: $BASE" - CHANGED=$(git diff --name-only "$BASE"...HEAD) + # Try triple-dot diff (merge-base). If no merge base (unrelated history), fall back to two-dot or full file list. + if git merge-base "$BASE" HEAD >/dev/null 2>&1; then + CHANGED=$(git diff --name-only "$BASE"...HEAD) + else + echo "No merge base with $BASE; using direct range diff." + CHANGED=$(git diff --name-only "$BASE" HEAD || true) + if [[ -z $CHANGED ]]; then + echo "Range diff empty; falling back to listing all tracked files." + CHANGED=$(git ls-files) + fi + fi echo "Changed files:\n$CHANGED" # Map to project directories PROJECTS=() From 6fb6aff09e0d0f69c048ad0b814e56b38ed9da7d Mon Sep 17 00:00:00 2001 From: Divyang Panchasara Date: Thu, 21 Aug 2025 00:54:12 +0530 Subject: [PATCH 5/5] feat(video): add video client, upload/session models and tests --- Acme.Gemini.Core/Acme.Gemini.Core.csproj | 0 Acme.Gemini.Core/GeminiApiException.cs | 0 Acme.Gemini.Core/GeminiLogger.cs | 0 Acme.Gemini.Core/IAccessTokenProvider.cs | 0 Acme.Gemini.Core/IHttpTransport.cs | 0 Acme.Gemini.Embeddings/Acme.Gemini.Embeddings.csproj | 0 Acme.Gemini.Image/Acme.Gemini.Image.csproj | 0 Acme.Gemini.LongContext/Acme.Gemini.LongContext.csproj | 0 Acme.Gemini.Music/Acme.Gemini.Music.csproj | 0 Acme.Gemini.Speech/Acme.Gemini.Speech.csproj | 0 Acme.Gemini.StructuredOutput/Acme.Gemini.StructuredOutput.csproj | 0 Acme.Gemini.Video/Acme.Gemini.Video.csproj | 0 Acme.Gemini.Video/GeminiVideoClient.cs | 0 Acme.Gemini.Video/GeminiVideoClientOptions.cs | 0 Acme.Gemini.Video/IGeminiVideoClient.cs | 0 Acme.Gemini.Video/Models/GeminiError.cs | 0 Acme.Gemini.Video/Models/GenerateChunk.cs | 0 Acme.Gemini.Video/Models/GenerateFromVideoRequest.cs | 0 Acme.Gemini.Video/Models/Operation.cs | 0 Acme.Gemini.Video/Models/SmallUploadRequest.cs | 0 Acme.Gemini.Video/Models/StartUploadRequest.cs | 0 Acme.Gemini.Video/Models/UploadProgress.cs | 0 Acme.Gemini.Video/Models/UploadSession.cs | 0 Acme.Gemini.Video/Models/UploadedMedia.cs | 0 Acme.Gemini.Video/Models/VideoPart.cs | 0 Acme.Gemini.Video/README.md | 0 Ngemini/GeminiApiException.cs | 0 Ngemini/GeminiVideoClient.Analyzers.props | 0 Ngemini/GeminiVideoClient.cs | 0 Ngemini/GeminiVideoClient.xml | 0 Ngemini/GeminiVideoClientOptions.cs | 0 Ngemini/IGeminiVideoClient.cs | 0 Ngemini/Internal/GeminiLogger.cs | 0 Ngemini/Models/GeminiError.cs | 0 Ngemini/Models/GenerateChunk.cs | 0 Ngemini/Models/GenerateFromVideoRequest.cs | 0 Ngemini/Models/Operation.cs | 0 Ngemini/Models/SmallUploadRequest.cs | 0 Ngemini/Models/StartUploadRequest.cs | 0 Ngemini/Models/UploadProgress.cs | 0 Ngemini/Models/UploadSession.cs | 0 Ngemini/Models/UploadedMedia.cs | 0 Ngemini/Models/VideoPart.cs | 0 Ngemini/Tests/GeminiVideoClientTests.cs | 0 44 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 Acme.Gemini.Core/Acme.Gemini.Core.csproj create mode 100644 Acme.Gemini.Core/GeminiApiException.cs create mode 100644 Acme.Gemini.Core/GeminiLogger.cs create mode 100644 Acme.Gemini.Core/IAccessTokenProvider.cs create mode 100644 Acme.Gemini.Core/IHttpTransport.cs create mode 100644 Acme.Gemini.Embeddings/Acme.Gemini.Embeddings.csproj create mode 100644 Acme.Gemini.Image/Acme.Gemini.Image.csproj create mode 100644 Acme.Gemini.LongContext/Acme.Gemini.LongContext.csproj create mode 100644 Acme.Gemini.Music/Acme.Gemini.Music.csproj create mode 100644 Acme.Gemini.Speech/Acme.Gemini.Speech.csproj create mode 100644 Acme.Gemini.StructuredOutput/Acme.Gemini.StructuredOutput.csproj create mode 100644 Acme.Gemini.Video/Acme.Gemini.Video.csproj create mode 100644 Acme.Gemini.Video/GeminiVideoClient.cs create mode 100644 Acme.Gemini.Video/GeminiVideoClientOptions.cs create mode 100644 Acme.Gemini.Video/IGeminiVideoClient.cs create mode 100644 Acme.Gemini.Video/Models/GeminiError.cs create mode 100644 Acme.Gemini.Video/Models/GenerateChunk.cs create mode 100644 Acme.Gemini.Video/Models/GenerateFromVideoRequest.cs create mode 100644 Acme.Gemini.Video/Models/Operation.cs create mode 100644 Acme.Gemini.Video/Models/SmallUploadRequest.cs create mode 100644 Acme.Gemini.Video/Models/StartUploadRequest.cs create mode 100644 Acme.Gemini.Video/Models/UploadProgress.cs create mode 100644 Acme.Gemini.Video/Models/UploadSession.cs create mode 100644 Acme.Gemini.Video/Models/UploadedMedia.cs create mode 100644 Acme.Gemini.Video/Models/VideoPart.cs create mode 100644 Acme.Gemini.Video/README.md create mode 100644 Ngemini/GeminiApiException.cs create mode 100644 Ngemini/GeminiVideoClient.Analyzers.props create mode 100644 Ngemini/GeminiVideoClient.cs create mode 100644 Ngemini/GeminiVideoClient.xml create mode 100644 Ngemini/GeminiVideoClientOptions.cs create mode 100644 Ngemini/IGeminiVideoClient.cs create mode 100644 Ngemini/Internal/GeminiLogger.cs create mode 100644 Ngemini/Models/GeminiError.cs create mode 100644 Ngemini/Models/GenerateChunk.cs create mode 100644 Ngemini/Models/GenerateFromVideoRequest.cs create mode 100644 Ngemini/Models/Operation.cs create mode 100644 Ngemini/Models/SmallUploadRequest.cs create mode 100644 Ngemini/Models/StartUploadRequest.cs create mode 100644 Ngemini/Models/UploadProgress.cs create mode 100644 Ngemini/Models/UploadSession.cs create mode 100644 Ngemini/Models/UploadedMedia.cs create mode 100644 Ngemini/Models/VideoPart.cs create mode 100644 Ngemini/Tests/GeminiVideoClientTests.cs diff --git a/Acme.Gemini.Core/Acme.Gemini.Core.csproj b/Acme.Gemini.Core/Acme.Gemini.Core.csproj new file mode 100644 index 0000000..e69de29 diff --git a/Acme.Gemini.Core/GeminiApiException.cs b/Acme.Gemini.Core/GeminiApiException.cs new file mode 100644 index 0000000..e69de29 diff --git a/Acme.Gemini.Core/GeminiLogger.cs b/Acme.Gemini.Core/GeminiLogger.cs new file mode 100644 index 0000000..e69de29 diff --git a/Acme.Gemini.Core/IAccessTokenProvider.cs b/Acme.Gemini.Core/IAccessTokenProvider.cs new file mode 100644 index 0000000..e69de29 diff --git a/Acme.Gemini.Core/IHttpTransport.cs b/Acme.Gemini.Core/IHttpTransport.cs new file mode 100644 index 0000000..e69de29 diff --git a/Acme.Gemini.Embeddings/Acme.Gemini.Embeddings.csproj b/Acme.Gemini.Embeddings/Acme.Gemini.Embeddings.csproj new file mode 100644 index 0000000..e69de29 diff --git a/Acme.Gemini.Image/Acme.Gemini.Image.csproj b/Acme.Gemini.Image/Acme.Gemini.Image.csproj new file mode 100644 index 0000000..e69de29 diff --git a/Acme.Gemini.LongContext/Acme.Gemini.LongContext.csproj b/Acme.Gemini.LongContext/Acme.Gemini.LongContext.csproj new file mode 100644 index 0000000..e69de29 diff --git a/Acme.Gemini.Music/Acme.Gemini.Music.csproj b/Acme.Gemini.Music/Acme.Gemini.Music.csproj new file mode 100644 index 0000000..e69de29 diff --git a/Acme.Gemini.Speech/Acme.Gemini.Speech.csproj b/Acme.Gemini.Speech/Acme.Gemini.Speech.csproj new file mode 100644 index 0000000..e69de29 diff --git a/Acme.Gemini.StructuredOutput/Acme.Gemini.StructuredOutput.csproj b/Acme.Gemini.StructuredOutput/Acme.Gemini.StructuredOutput.csproj new file mode 100644 index 0000000..e69de29 diff --git a/Acme.Gemini.Video/Acme.Gemini.Video.csproj b/Acme.Gemini.Video/Acme.Gemini.Video.csproj new file mode 100644 index 0000000..e69de29 diff --git a/Acme.Gemini.Video/GeminiVideoClient.cs b/Acme.Gemini.Video/GeminiVideoClient.cs new file mode 100644 index 0000000..e69de29 diff --git a/Acme.Gemini.Video/GeminiVideoClientOptions.cs b/Acme.Gemini.Video/GeminiVideoClientOptions.cs new file mode 100644 index 0000000..e69de29 diff --git a/Acme.Gemini.Video/IGeminiVideoClient.cs b/Acme.Gemini.Video/IGeminiVideoClient.cs new file mode 100644 index 0000000..e69de29 diff --git a/Acme.Gemini.Video/Models/GeminiError.cs b/Acme.Gemini.Video/Models/GeminiError.cs new file mode 100644 index 0000000..e69de29 diff --git a/Acme.Gemini.Video/Models/GenerateChunk.cs b/Acme.Gemini.Video/Models/GenerateChunk.cs new file mode 100644 index 0000000..e69de29 diff --git a/Acme.Gemini.Video/Models/GenerateFromVideoRequest.cs b/Acme.Gemini.Video/Models/GenerateFromVideoRequest.cs new file mode 100644 index 0000000..e69de29 diff --git a/Acme.Gemini.Video/Models/Operation.cs b/Acme.Gemini.Video/Models/Operation.cs new file mode 100644 index 0000000..e69de29 diff --git a/Acme.Gemini.Video/Models/SmallUploadRequest.cs b/Acme.Gemini.Video/Models/SmallUploadRequest.cs new file mode 100644 index 0000000..e69de29 diff --git a/Acme.Gemini.Video/Models/StartUploadRequest.cs b/Acme.Gemini.Video/Models/StartUploadRequest.cs new file mode 100644 index 0000000..e69de29 diff --git a/Acme.Gemini.Video/Models/UploadProgress.cs b/Acme.Gemini.Video/Models/UploadProgress.cs new file mode 100644 index 0000000..e69de29 diff --git a/Acme.Gemini.Video/Models/UploadSession.cs b/Acme.Gemini.Video/Models/UploadSession.cs new file mode 100644 index 0000000..e69de29 diff --git a/Acme.Gemini.Video/Models/UploadedMedia.cs b/Acme.Gemini.Video/Models/UploadedMedia.cs new file mode 100644 index 0000000..e69de29 diff --git a/Acme.Gemini.Video/Models/VideoPart.cs b/Acme.Gemini.Video/Models/VideoPart.cs new file mode 100644 index 0000000..e69de29 diff --git a/Acme.Gemini.Video/README.md b/Acme.Gemini.Video/README.md new file mode 100644 index 0000000..e69de29 diff --git a/Ngemini/GeminiApiException.cs b/Ngemini/GeminiApiException.cs new file mode 100644 index 0000000..e69de29 diff --git a/Ngemini/GeminiVideoClient.Analyzers.props b/Ngemini/GeminiVideoClient.Analyzers.props new file mode 100644 index 0000000..e69de29 diff --git a/Ngemini/GeminiVideoClient.cs b/Ngemini/GeminiVideoClient.cs new file mode 100644 index 0000000..e69de29 diff --git a/Ngemini/GeminiVideoClient.xml b/Ngemini/GeminiVideoClient.xml new file mode 100644 index 0000000..e69de29 diff --git a/Ngemini/GeminiVideoClientOptions.cs b/Ngemini/GeminiVideoClientOptions.cs new file mode 100644 index 0000000..e69de29 diff --git a/Ngemini/IGeminiVideoClient.cs b/Ngemini/IGeminiVideoClient.cs new file mode 100644 index 0000000..e69de29 diff --git a/Ngemini/Internal/GeminiLogger.cs b/Ngemini/Internal/GeminiLogger.cs new file mode 100644 index 0000000..e69de29 diff --git a/Ngemini/Models/GeminiError.cs b/Ngemini/Models/GeminiError.cs new file mode 100644 index 0000000..e69de29 diff --git a/Ngemini/Models/GenerateChunk.cs b/Ngemini/Models/GenerateChunk.cs new file mode 100644 index 0000000..e69de29 diff --git a/Ngemini/Models/GenerateFromVideoRequest.cs b/Ngemini/Models/GenerateFromVideoRequest.cs new file mode 100644 index 0000000..e69de29 diff --git a/Ngemini/Models/Operation.cs b/Ngemini/Models/Operation.cs new file mode 100644 index 0000000..e69de29 diff --git a/Ngemini/Models/SmallUploadRequest.cs b/Ngemini/Models/SmallUploadRequest.cs new file mode 100644 index 0000000..e69de29 diff --git a/Ngemini/Models/StartUploadRequest.cs b/Ngemini/Models/StartUploadRequest.cs new file mode 100644 index 0000000..e69de29 diff --git a/Ngemini/Models/UploadProgress.cs b/Ngemini/Models/UploadProgress.cs new file mode 100644 index 0000000..e69de29 diff --git a/Ngemini/Models/UploadSession.cs b/Ngemini/Models/UploadSession.cs new file mode 100644 index 0000000..e69de29 diff --git a/Ngemini/Models/UploadedMedia.cs b/Ngemini/Models/UploadedMedia.cs new file mode 100644 index 0000000..e69de29 diff --git a/Ngemini/Models/VideoPart.cs b/Ngemini/Models/VideoPart.cs new file mode 100644 index 0000000..e69de29 diff --git a/Ngemini/Tests/GeminiVideoClientTests.cs b/Ngemini/Tests/GeminiVideoClientTests.cs new file mode 100644 index 0000000..e69de29