Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .pubignore
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ AGENTS.md

# Dev-only docs
doc/RELEASE_CHECKLIST.md
doc/superpowers/
docs/

# Environment and secrets
.env
Expand Down
29 changes: 29 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,32 @@
## 0.0.12

* Add `GenuiXTransport.ollama()` factory — thin wrapper around
`GenuiXTransport.openai()` configured for Ollama's OpenAI-compatible
endpoint. Defaults to `http://localhost:11434` and `llama3.2`. No API key
required (a placeholder bearer token is sent so the OpenAI-compat layer
accepts the request). Disables retries by default (`maxRetries: 0`) since
local servers don't rate-limit.
* Add `example/lib/ollama_main.dart` — runnable local-Ollama chat demo
with `enforceJsonMode: true` for stricter A2UI compliance from local
models. Supports `OLLAMA_BASE_URL` and `OLLAMA_MODEL` `--dart-define`s.
* README overhaul for discoverability — new tagline, provider matrix table
(Anthropic / OpenAI / Gemini / Ollama / custom proxy at a glance), CI
badge, demo-GIF placeholder block, Ollama backend section, and Ollama
example run instructions.
* `pubspec.yaml` — add `homepage` and `documentation` URLs, refresh
`topics` to `[genui, llm, claude, gemini, openai]` (drop redundant
`flutter` and broad `ai`), and stage a commented-out `screenshots:`
block for the demo GIF.
* Upgrade dependency to `genui: ^0.9.2` in both the package and example app.
* Upgrade transport dependency to `http: ^1.6.0`.
* Refresh docs and agent notes to reference `genui ^0.9.2` instead of `^0.8.0`.
* Exclude dev-only docs (`doc/superpowers/`, `docs/`) from pub publish via
`.pubignore` so package publish surface stays clean.
* Validate compatibility with `flutter analyze --fatal-infos` and `flutter test`
in both the root package and `example/` app.
* No public API removals or signature changes; existing call sites for
`.anthropic()`, `.openai()`, and `.gemini()` are byte-identical.

## 0.0.11

* Add `GenuiXTransport.gemini()` factory — pre-configures Google's Generative
Expand Down
61 changes: 57 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,38 @@
[![pub package](https://img.shields.io/pub/v/genui_x.svg)](https://pub.dev/packages/genui_x)
[![pub points](https://img.shields.io/pub/points/genui_x.svg)](https://pub.dev/packages/genui_x/score)
[![likes](https://img.shields.io/pub/likes/genui_x.svg)](https://pub.dev/packages/genui_x/score)
[![CI](https://github.com/thurakhant/genui_x/actions/workflows/ci.yml/badge.svg)](https://github.com/thurakhant/genui_x/actions/workflows/ci.yml)

A lightweight AI backend adapter for Google's [genui](https://pub.dev/packages/genui) (Generative UI) framework.
> **The missing backend for [Google's genui](https://pub.dev/packages/genui) framework.** One `Transport`, every major LLM — Anthropic Claude, OpenAI, Google Gemini, local Ollama, or any OpenAI-compatible proxy.

Connect any AI backend — Anthropic Claude, OpenAI, OpenRouter, LiteLLM, or your own proxy — to genui with a single class.
<!--
Demo GIF placeholder — record ~15 s of `example/lib/travel_main.dart`
(prompt → streamed widget) and drop the file at `screenshots/demo.gif`,
then uncomment the line below.

![genui_x demo](screenshots/demo.gif)
-->

```dart
final transport = GenuiXTransport.anthropic( // or .openai() / .gemini() / .ollama()
apiKey: const String.fromEnvironment('CLAUDE_API_KEY'),
catalog: myCatalog,
);
```

`genui` defines *what* the AI can render. `genui_x` connects it to *who* generates it.

## Provider matrix

| Provider | Factory | Streaming | JSON mode | Auth header | Default model |
|---|---|:-:|:-:|---|---|
| Anthropic Claude | `GenuiXTransport.anthropic()` | ✅ | n/a (Claude is JSON-friendly) | `x-api-key` | `claude-haiku-4-5-20251001` |
| OpenAI / OpenRouter / LiteLLM | `GenuiXTransport.openai()` | ✅ | ✅ via `enforceJsonMode` | `Authorization: Bearer` | `gpt-4o-mini` |
| Google Gemini | `GenuiXTransport.gemini()` | ✅ | n/a (uses `systemInstruction`) | `x-goog-api-key` | `gemini-2.5-flash` |
| Ollama (local) | `GenuiXTransport.ollama()` | ✅ | ✅ via `enforceJsonMode` | `Authorization: Bearer` (placeholder) | `llama3.2` |
| Custom proxy | `GenuiXTransport(...)` | ✅ | via `requestBodyOverrides` | configurable | configurable |

All providers share the same retry-on-429, cancel, `clearHistory`, `isLoading`, and `debug` controls.

---

Expand Down Expand Up @@ -37,8 +65,8 @@ Your App
```yaml
# pubspec.yaml
dependencies:
genui: ^0.8.0
genui_x: ^0.0.11
genui: ^0.9.2
genui_x: ^0.0.12
```

### 2. Create your catalog
Expand Down Expand Up @@ -152,6 +180,22 @@ Sends `x-goog-api-key`, posts to
`candidates[*].content.parts[*].text` SSE stream. Override `baseUrl` to
point at a Vertex AI gateway or your own proxy.

### Ollama (local models)

```dart
final transport = GenuiXTransport.ollama(
catalog: myCatalog,
// model: 'llama3.2', // optional — default
// baseUrl: 'http://localhost:11434', // optional — default
// enforceJsonMode: true, // recommended for stricter A2UI output
);
```

Wraps `GenuiXTransport.openai()` against Ollama's OpenAI-compatible
endpoint. No API key is required by Ollama, but a placeholder bearer token
(`ollama`) is sent so the OpenAI-compat layer accepts the request. Pull
the model first with `ollama pull llama3.2`.

### OpenRouter / LiteLLM / custom proxy

```dart
Expand Down Expand Up @@ -264,6 +308,8 @@ final transport = GenuiXTransport(
| OpenAI | `gpt-4o` | Higher quality |
| Gemini | `gemini-2.5-flash` | Default for `.gemini()` — fast, low cost |
| Gemini | `gemini-2.5-pro` | Higher quality |
| Ollama | `llama3.2` | Default for `.ollama()` — local |
| Ollama | any local model slug | e.g. `qwen2.5-coder`, `mistral` |
| OpenRouter | any model slug | via `GenuiXTransport.openai(baseUrl: ...)` |

---
Expand All @@ -289,6 +335,13 @@ flutter run -t lib/proxy_main.dart \
# Google Gemini
flutter run -t lib/gemini_main.dart \
--dart-define=GEMINI_API_KEY=your-google-api-key

# Ollama (local — no API key)
flutter run -t lib/ollama_main.dart
# or with overrides:
flutter run -t lib/ollama_main.dart \
--dart-define=OLLAMA_BASE_URL=http://192.168.1.50:11434 \
--dart-define=OLLAMA_MODEL=qwen2.5-coder
```

---
Expand Down
34 changes: 33 additions & 1 deletion example/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# genui_x examples

Three runnable entry points — pick the one that matches your setup.
Five runnable entry points — pick the one that matches your setup.

---

Expand Down Expand Up @@ -36,3 +36,35 @@ flutter run -t lib/proxy_main.dart \
```

Shows `GenuiXStreamFormat.openai`, `authorization` header, and `Bearer ` prefix.

---

## Gemini — Google's Generative Language API

```bash
flutter run -t lib/gemini_main.dart \
--dart-define=GEMINI_API_KEY=your-google-api-key
```

Uses `GenuiXTransport.gemini()`, the `x-goog-api-key` header, and the
`streamGenerateContent?alt=sse` endpoint.

---

## Ollama — local model, no API key

```bash
# 1. Pull a model first (one-time):
ollama pull llama3.2

# 2. Run the example:
flutter run -t lib/ollama_main.dart

# Optional overrides:
flutter run -t lib/ollama_main.dart \
--dart-define=OLLAMA_BASE_URL=http://192.168.1.50:11434 \
--dart-define=OLLAMA_MODEL=qwen2.5-coder
```

Uses `GenuiXTransport.ollama()` against Ollama's OpenAI-compatible
endpoint with `enforceJsonMode: true` for stricter A2UI output.
6 changes: 4 additions & 2 deletions example/lib/AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
# example/lib/

## Purpose
Four Flutter entry points demonstrating different complexity levels and backend choices for `genui_x` integration. Each file is a complete runnable app including its own `Catalog`, `CatalogItem`, `widgetBuilder`, and chat UI.
Five Flutter entry points demonstrating different complexity levels and backend choices for `genui_x` integration. Each file is a complete runnable app including its own `Catalog`, `CatalogItem`, `widgetBuilder`, and chat UI.

## Key Files

Expand All @@ -14,6 +14,8 @@ Four Flutter entry points demonstrating different complexity levels and backend
| `main.dart` | Full-featured demo — `WeatherWidget` catalog with proxy/model overrides via `--dart-define`, text input chat |
| `travel_main.dart` | Travel demo — custom `TravelPlanWidget` catalog, shows `data`-wrapped component properties and list props |
| `gemini_main.dart` | Gemini-backend demo — uses `GenuiXTransport.gemini()` against the Generative Language API |
| `ollama_main.dart` | Local Ollama demo — uses `GenuiXTransport.ollama()`, no API key required, `enforceJsonMode: true` |
| `proxy_main.dart` | Generic OpenAI-compatible proxy demo (LiteLLM, OpenRouter, etc.) configured via `--dart-define` |

## For AI Agents

Expand Down Expand Up @@ -60,7 +62,7 @@ cd example && flutter test # widget smoke tests
- `../AGENTS.md` — example-wide conventions

### External
- `package:genui_x` — `GenuiXTransport` (with `.openai()`, `.anthropic()`, `.gemini()` factories), `GenuiXConfig`, `GenuiXStreamFormat`
- `package:genui_x` — `GenuiXTransport` (with `.openai()`, `.anthropic()`, `.gemini()`, `.ollama()` factories), `GenuiXConfig`, `GenuiXStreamFormat`
- `package:genui` — `Catalog`, `CatalogItem`, `SurfaceController`, `Conversation`, `Surface`, `ChatMessage`, `PromptBuilder`
- `package:json_schema_builder` — `S.object()`, `S.string()`, etc.

Expand Down
Loading
Loading