vrex-flow-engine 0.2.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. vrex_flow_engine-0.2.0/PKG-INFO +62 -0
  2. vrex_flow_engine-0.2.0/PYPI_README.md +38 -0
  3. vrex_flow_engine-0.2.0/README.md +259 -0
  4. vrex_flow_engine-0.2.0/flow_engine/__init__.py +4 -0
  5. vrex_flow_engine-0.2.0/flow_engine/bridge/__init__.py +6 -0
  6. vrex_flow_engine-0.2.0/flow_engine/bridge/flow_client.py +444 -0
  7. vrex_flow_engine-0.2.0/flow_engine/bridge/flow_sdk.py +1743 -0
  8. vrex_flow_engine-0.2.0/flow_engine/bridge/ws_server.py +84 -0
  9. vrex_flow_engine-0.2.0/flow_engine/catalog.py +332 -0
  10. vrex_flow_engine-0.2.0/flow_engine/cli/__init__.py +1 -0
  11. vrex_flow_engine-0.2.0/flow_engine/cli/app.py +149 -0
  12. vrex_flow_engine-0.2.0/flow_engine/cli/config.py +81 -0
  13. vrex_flow_engine-0.2.0/flow_engine/cli/dashboard.py +125 -0
  14. vrex_flow_engine-0.2.0/flow_engine/cli/health.py +40 -0
  15. vrex_flow_engine-0.2.0/flow_engine/cli/processes.py +109 -0
  16. vrex_flow_engine-0.2.0/flow_engine/cli/supervisor.py +184 -0
  17. vrex_flow_engine-0.2.0/flow_engine/config.py +43 -0
  18. vrex_flow_engine-0.2.0/flow_engine/ingest.py +172 -0
  19. vrex_flow_engine-0.2.0/flow_engine/job_store.py +28 -0
  20. vrex_flow_engine-0.2.0/flow_engine/jobs.py +245 -0
  21. vrex_flow_engine-0.2.0/flow_engine/main.py +187 -0
  22. vrex_flow_engine-0.2.0/flow_engine/media.py +227 -0
  23. vrex_flow_engine-0.2.0/flow_engine/media_store.py +202 -0
  24. vrex_flow_engine-0.2.0/flow_engine/openai/__init__.py +1 -0
  25. vrex_flow_engine-0.2.0/flow_engine/openai/_util.py +59 -0
  26. vrex_flow_engine-0.2.0/flow_engine/openai/images.py +134 -0
  27. vrex_flow_engine-0.2.0/flow_engine/openai/models.py +38 -0
  28. vrex_flow_engine-0.2.0/flow_engine/openai/uploads.py +70 -0
  29. vrex_flow_engine-0.2.0/flow_engine/openai/videos.py +289 -0
  30. vrex_flow_engine-0.2.0/flow_engine/pool.py +138 -0
  31. vrex_flow_engine-0.2.0/flow_engine/posthog_client.py +117 -0
  32. vrex_flow_engine-0.2.0/flow_engine/session.py +89 -0
  33. vrex_flow_engine-0.2.0/flow_engine/video_context.py +77 -0
  34. vrex_flow_engine-0.2.0/flow_engine/video_context_store.py +49 -0
  35. vrex_flow_engine-0.2.0/pyproject.toml +43 -0
  36. vrex_flow_engine-0.2.0/setup.cfg +4 -0
  37. vrex_flow_engine-0.2.0/vrex_flow_engine.egg-info/PKG-INFO +62 -0
  38. vrex_flow_engine-0.2.0/vrex_flow_engine.egg-info/SOURCES.txt +40 -0
  39. vrex_flow_engine-0.2.0/vrex_flow_engine.egg-info/dependency_links.txt +1 -0
  40. vrex_flow_engine-0.2.0/vrex_flow_engine.egg-info/entry_points.txt +3 -0
  41. vrex_flow_engine-0.2.0/vrex_flow_engine.egg-info/requires.txt +8 -0
  42. vrex_flow_engine-0.2.0/vrex_flow_engine.egg-info/top_level.txt +1 -0
@@ -0,0 +1,62 @@
1
+ Metadata-Version: 2.4
2
+ Name: vrex-flow-engine
3
+ Version: 0.2.0
4
+ Summary: Launcher + supervisor and OpenAI-compatible image/video generation service (Vrex Flow Engine).
5
+ Author: Vrex
6
+ License: Proprietary
7
+ Project-URL: Homepage, https://getvrex.com
8
+ Keywords: vrex,flow-engine,cli,supervisor,image-generation,video-generation
9
+ Classifier: Programming Language :: Python :: 3
10
+ Classifier: Environment :: Console
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: Operating System :: POSIX
13
+ Classifier: Topic :: Multimedia :: Video
14
+ Requires-Python: >=3.10
15
+ Description-Content-Type: text/markdown
16
+ Requires-Dist: fastapi>=0.110
17
+ Requires-Dist: uvicorn[standard]>=0.27
18
+ Requires-Dist: httpx>=0.27
19
+ Requires-Dist: websockets>=12.0
20
+ Requires-Dist: pydantic>=2.5
21
+ Requires-Dist: python-multipart>=0.0.9
22
+ Requires-Dist: posthog>=3.8
23
+ Requires-Dist: rich>=13.7
24
+
25
+ # vrex-flow-engine
26
+
27
+ One-command launcher + supervisor for the **Vrex Flow Engine** — a self-hosted
28
+ service that exposes OpenAI-compatible image/video generation endpoints.
29
+
30
+ `vrex-flow-engine start` stores your engine key + Cloudflare tunnel token,
31
+ launches the engine and the tunnel as supervised child processes (with
32
+ crash-restart), and renders a live status dashboard.
33
+
34
+ ## Quickstart
35
+
36
+ ```bash
37
+ uvx vrex-flow-engine start
38
+ ```
39
+
40
+ First run prompts for the engine API key and the Cloudflare tunnel token (saved
41
+ to `~/.vrex-flow/config.json`, chmod 600), then brings up the engine + tunnel.
42
+ Ctrl-C stops both cleanly.
43
+
44
+ ## Commands
45
+
46
+ | Command | What it does |
47
+ |---|---|
48
+ | `vrex-flow-engine start` | Run engine + tunnel with a live dashboard. `--no-tunnel` runs the engine only. |
49
+ | `vrex-flow-engine setup` | Store the engine key + tunnel token. |
50
+ | `vrex-flow-engine doctor` | Check prerequisites and probe a running engine. |
51
+ | `vrex-flow-engine serve` | Run just the engine in the foreground. |
52
+
53
+ The short alias `flow-engine` is installed for the same commands.
54
+
55
+ ## Requirements
56
+
57
+ - Python 3.10+
58
+ - [`cloudflared`](https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/downloads/)
59
+ (for the tunnel; `--no-tunnel` skips it)
60
+ - Access to a Vrex Flow Engine deployment.
61
+
62
+ Internal Vrex tooling.
@@ -0,0 +1,38 @@
1
+ # vrex-flow-engine
2
+
3
+ One-command launcher + supervisor for the **Vrex Flow Engine** — a self-hosted
4
+ service that exposes OpenAI-compatible image/video generation endpoints.
5
+
6
+ `vrex-flow-engine start` stores your engine key + Cloudflare tunnel token,
7
+ launches the engine and the tunnel as supervised child processes (with
8
+ crash-restart), and renders a live status dashboard.
9
+
10
+ ## Quickstart
11
+
12
+ ```bash
13
+ uvx vrex-flow-engine start
14
+ ```
15
+
16
+ First run prompts for the engine API key and the Cloudflare tunnel token (saved
17
+ to `~/.vrex-flow/config.json`, chmod 600), then brings up the engine + tunnel.
18
+ Ctrl-C stops both cleanly.
19
+
20
+ ## Commands
21
+
22
+ | Command | What it does |
23
+ |---|---|
24
+ | `vrex-flow-engine start` | Run engine + tunnel with a live dashboard. `--no-tunnel` runs the engine only. |
25
+ | `vrex-flow-engine setup` | Store the engine key + tunnel token. |
26
+ | `vrex-flow-engine doctor` | Check prerequisites and probe a running engine. |
27
+ | `vrex-flow-engine serve` | Run just the engine in the foreground. |
28
+
29
+ The short alias `flow-engine` is installed for the same commands.
30
+
31
+ ## Requirements
32
+
33
+ - Python 3.10+
34
+ - [`cloudflared`](https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/downloads/)
35
+ (for the tunnel; `--no-tunnel` skips it)
36
+ - Access to a Vrex Flow Engine deployment.
37
+
38
+ Internal Vrex tooling.
@@ -0,0 +1,259 @@
1
+ # flow-engine
2
+
3
+ Host a **Google Flow browser-extension instance** and expose **OpenAI-compatible
4
+ image/video generation endpoints** backed by Google Flow (labs.google).
5
+
6
+ flow-engine drives a Chrome extension that borrows your authenticated Flow
7
+ session (token + cookies + reCAPTCHA solving) and proxies Flow's private
8
+ `aisandbox-pa.googleapis.com` calls, mapping the results onto familiar OpenAI
9
+ request/response shapes. Python package `flow-engine`, import module
10
+ `flow_engine`, console command `flow-engine` (subcommands: `start`, `serve`,
11
+ `setup`, `doctor`).
12
+
13
+ ```
14
+ OpenAI client ──HTTP :8101──> flow-engine ──WS :9223──> Chrome extension ──fetch──> Google Flow
15
+ (this repo) (extension/, in your browser)
16
+ ```
17
+
18
+ In production the HTTP surface is published at `https://flow.getvrex.com`
19
+ (a `cloudflared` tunnel → `127.0.0.1:8101`); the Next.js app reaches it via
20
+ `FLOW_ENGINE_URL`. See "Expose to production" below.
21
+
22
+ ## Endpoints
23
+
24
+ - `POST /v1/images/generations` — synchronous image (Nano Banana 2).
25
+ - `POST /v1/videos/generations` + `GET /v1/videos/{id}` — async video job + poll (Veo 3.1 lite).
26
+ - `GET /v1/videos/{id}/debug` — raw `{dispatch, last_poll}` Google payloads for a job (troubleshooting).
27
+ - `POST /v1/flow/uploads` — image **or video** bytes → Flow media id (routes by mime).
28
+ - `GET /v1/models` — model catalog (cached on disk, refresh with `?refresh=1`).
29
+ - `GET /media/{id}` — cached generated bytes at a stable URL.
30
+ - `GET /api/health` — liveness + extension-connected status (ungated).
31
+
32
+ `/v1/*` and `/api/pool/status` require `Authorization: Bearer <FLOW_ENGINE_API_KEY>`.
33
+ `/api/health` and `/media/{id}` are ungated.
34
+
35
+ ## Requirements
36
+
37
+ - Python 3.10+
38
+ - Google Chrome signed in to **labs.google** with a Flow tab open, and the
39
+ extension in `extension/` loaded (chrome://extensions → Load unpacked).
40
+ - A Flow account (Pro or Ultra — the paygate tier is read from your session).
41
+ - `cloudflared` (only for exposing to production).
42
+
43
+ > The extension's `background.js` hardcodes `ws://127.0.0.1:9223` and
44
+ > `http://127.0.0.1:8101/api/ext/callback`, so flow-engine defaults to those
45
+ > ports. It therefore **cannot run alongside the legacy flowboard agent on
46
+ > defaults** — change both the env vars and the extension URLs to run both.
47
+
48
+ ## Quickstart — one command
49
+
50
+ `flow-engine start` is a supervisor: it stores your secrets, launches the engine
51
+ **and** the Cloudflare tunnel as child processes, restarts either on crash, and
52
+ renders a live status dashboard. Run it with [uv](https://docs.astral.sh/uv/)
53
+ (the Python equivalent of `npx` — no manual venv):
54
+
55
+ ```bash
56
+ # from the monorepo (until published to PyPI):
57
+ uvx --from 'git+ssh://git@github.com/getvrex/multimodal.git#subdirectory=flow-engine' flow-engine start
58
+
59
+ # once published: uvx flow-engine start
60
+ ```
61
+
62
+ First run prompts for the **engine API key** (must match the value the Next.js
63
+ app sends — `FLOW_ENGINE_API_KEY` on Vrex Multimodal / `.env.prd`) and the
64
+ **Cloudflare tunnel token** (dashboard → Zero Trust → Networks → Tunnels → your
65
+ tunnel → "run a connector"). Both are saved to `~/.vrex-flow/config.json` (0600)
66
+ so later runs need no input. Then it brings up the engine + tunnel and shows:
67
+
68
+ ```
69
+ 🎬 Vrex Flow Engine ● running uptime 3m02s
70
+ ┌ engine ──────────────┐ ┌ tunnel ───────────────┐
71
+ │ status ● UP │ │ status ● connected │
72
+ │ extension ● connected│ │ public flow.getvrex.com│
73
+ │ instances 1 │ │ → 127.0.0.1:8101 │
74
+ └──────────────────────┘ └───────────────────────┘
75
+ ```
76
+
77
+ The one thing the CLI can't automate: open a `labs.google/fx/tools/flow` tab in
78
+ Chrome with the `extension/` loaded and signed into a Flow Pro/Ultra account.
79
+ Until you do, the dashboard shows `extension ● OPEN A FLOW TAB`. Ctrl-C stops
80
+ both processes cleanly.
81
+
82
+ ### CLI commands
83
+
84
+ | Command | What it does |
85
+ |---|---|
86
+ | `flow-engine start` | Supervise engine + tunnel + live dashboard (the one-liner). `--no-tunnel` runs the engine only; `--non-interactive` fails instead of prompting. |
87
+ | `flow-engine setup` | (Re)store the engine key + tunnel token in `~/.vrex-flow/config.json`. |
88
+ | `flow-engine doctor` | Check prerequisites (python, cloudflared, config) and probe a running engine. |
89
+ | `flow-engine serve` | Run just the engine in the foreground (for systemd / your own supervisor). |
90
+
91
+ Secrets can also come from env (`FLOW_ENGINE_API_KEY`, `CLOUDFLARE_TUNNEL_TOKEN`)
92
+ or flags (`--engine-key`, `--tunnel-token`) — flags > env > stored config.
93
+
94
+ ## Run manually (without the CLI)
95
+
96
+ The engine reads config from the environment directly — **no `.env` auto-load**.
97
+ `FLOW_ENGINE_API_KEY` is **required**; the server refuses to boot without it.
98
+
99
+ ```bash
100
+ cd flow-engine
101
+ python -m venv .venv && source .venv/bin/activate
102
+ pip install -e .
103
+ export FLOW_ENGINE_API_KEY=<shared-secret> # must match the caller's key
104
+ flow-engine serve # serves :8101 (HTTP) + :9223 (WS)
105
+ # equivalent: python -m flow_engine.main
106
+ ```
107
+
108
+ Load `extension/` in Chrome, open a `labs.google/fx/tools/flow` tab, then check:
109
+
110
+ ```bash
111
+ curl localhost:8101/api/health
112
+ # {"ok":true,"extension_connected":true,"instances":1}
113
+ ```
114
+
115
+ `extension_connected:false` means no Flow tab/extension is bridged yet — open
116
+ the tab and reload the extension.
117
+
118
+ ## Expose to production (Cloudflare Tunnel)
119
+
120
+ The public origin `https://flow.getvrex.com` is a `cloudflared` tunnel to the
121
+ local `:8101`. **`flow-engine start` runs this tunnel for you** (via the stored
122
+ token), so normally you don't touch `cloudflared` directly. To run it standalone
123
+ — e.g. the `serve` path — start the tunnel as a separate process on the same
124
+ machine:
125
+
126
+ ```bash
127
+ cloudflared tunnel run --token <your-tunnel-token> # flow.getvrex.com → 127.0.0.1:8101
128
+ # or, with a named-tunnel config file:
129
+ cloudflared tunnel run --config cloudflared.yml
130
+ ```
131
+
132
+ If `https://flow.getvrex.com` returns **HTTP 530 / `error code: 1033`**, the
133
+ tunnel is down (Cloudflare has no active connection to the origin) — restart it
134
+ (or `flow-engine start`). A `502`/`1016` instead means the tunnel is up but the
135
+ engine on `:8101` is not — restart the engine.
136
+
137
+ ## Examples
138
+
139
+ Image (`model` must be `NANO_BANANA_2`, or omit to force it):
140
+
141
+ ```bash
142
+ curl localhost:8101/v1/images/generations \
143
+ -H "authorization: Bearer $FLOW_ENGINE_API_KEY" \
144
+ -H 'content-type: application/json' -d '{
145
+ "prompt": "a studio portrait, soft light", "n": 2,
146
+ "size": "1024x1024", "model": "NANO_BANANA_2"
147
+ }'
148
+ # {"created":..., "data":[{"url":"http://127.0.0.1:8101/media/<uuid>"}, ...]}
149
+ ```
150
+
151
+ Video (`model` must be `veo_3_1_lite_low_priority`). Text-to-video:
152
+
153
+ ```bash
154
+ JOB=$(curl -s localhost:8101/v1/videos/generations \
155
+ -H "authorization: Bearer $FLOW_ENGINE_API_KEY" \
156
+ -H 'content-type: application/json' -d '{
157
+ "prompt": "slow dolly in over a city at dusk",
158
+ "model": "veo_3_1_lite_low_priority", "seconds": 8, "size": "1280x720"
159
+ }' | jq -r .id)
160
+ curl -s localhost:8101/v1/videos/$JOB \
161
+ -H "authorization: Bearer $FLOW_ENGINE_API_KEY" # poll until status == "completed"
162
+ ```
163
+
164
+ Image-to-video — pass the start frame inline; flow-engine uploads it for you:
165
+
166
+ ```bash
167
+ curl localhost:8101/v1/videos/generations \
168
+ -H "authorization: Bearer $FLOW_ENGINE_API_KEY" \
169
+ -H 'content-type: application/json' -d "{
170
+ \"prompt\": \"the subject turns to camera\", \"model\": \"veo_3_1_lite_low_priority\",
171
+ \"start_images\": [\"$(base64 < frame.png)\"], \"size\": \"1280x720\"
172
+ }"
173
+ ```
174
+
175
+ `start_images` / `ref_images` accept a data URL, an `http(s)` URL, or bare
176
+ base64. Already have a Flow media id (e.g. from `/v1/flow/uploads`)? Pass it in
177
+ `start_media_ids` / `ref_media_ids` instead — the two forms merge. Uploading a
178
+ reference **video** (for v2v/edit/extend) works the same way via
179
+ `/v1/flow/uploads -F file=@clip.mp4`, which returns a `"kind":"video"` media id.
180
+
181
+ Extend or edit a clip you already generated — pass back the `media_id` you got
182
+ and flow-engine resolves the rest (scene / workflow / frame count) from what it
183
+ remembered this run:
184
+
185
+ ```bash
186
+ # extend (continue a Veo clip — only Veo-generated videos can be extended)
187
+ curl localhost:8101/v1/videos/generations \
188
+ -H "authorization: Bearer $FLOW_ENGINE_API_KEY" \
189
+ -H 'content-type: application/json' -d '{
190
+ "prompt": "a dog joins in", "mode": "extend",
191
+ "model": "veo_3_1_lite_low_priority", "source_media_id": "<prev media_id>"
192
+ }'
193
+
194
+ # edit (video-to-video rewrite)
195
+ curl localhost:8101/v1/videos/generations \
196
+ -H "authorization: Bearer $FLOW_ENGINE_API_KEY" \
197
+ -H 'content-type: application/json' -d '{
198
+ "prompt": "add a green ball", "mode": "edit",
199
+ "model": "veo_3_1_lite_low_priority", "source_media_id": "<prev media_id>",
200
+ "source_seconds": 8
201
+ }'
202
+ ```
203
+
204
+ For a source flow-engine didn't generate this run (e.g. after a restart), pass
205
+ `workflow_id` explicitly (extend resolves the scene from it; edit uses it
206
+ directly) — plus `source_seconds` for edit so the frame range matches. The
207
+ generation-context registry is in-memory, so it resets when the server restarts.
208
+
209
+ ## Configuration
210
+
211
+ These configure the **engine** process (read from its environment). The
212
+ `flow-engine start` launcher injects `FLOW_ENGINE_API_KEY` + ports for you from
213
+ `~/.vrex-flow/config.json`; set these directly only for the manual `serve` path.
214
+ All optional except the API key. Port/host/storage vars keep the `FLOWPROXY_`
215
+ prefix for extension compatibility; the API key and pool size use the
216
+ `FLOW_ENGINE_` / `FLOW_POOL_` names.
217
+
218
+ | Env var | Default | Purpose |
219
+ |---|---|---|
220
+ | `FLOW_ENGINE_API_KEY` | — (**required**) | Bearer key gating `/v1/*`. Legacy `FLOWPROXY_API_KEY` still accepted. |
221
+ | `FLOWPROXY_HTTP_PORT` | `8101` | HTTP surface (OpenAI endpoints + `/media` + callback). |
222
+ | `FLOWPROXY_WS_HOST` | `127.0.0.1` | Extension WS bind — **must be loopback** (unauthenticated by design). |
223
+ | `FLOWPROXY_EXT_WS_PORT` | `9223` | Extension WebSocket port. |
224
+ | `FLOWPROXY_PUBLIC_BASE_URL` | `http://127.0.0.1:8101` | Base used to build absolute `/media` URLs returned to clients. |
225
+ | `FLOW_POOL_CONCURRENCY` | `4` | Max concurrent in-flight Flow calls per instance (back-pressure, no 503). |
226
+ | `FLOWPROXY_STORAGE` | `./storage` | Local byte cache dir. |
227
+ | `FLOWPROXY_CATALOG_TTL` | `86400` | Model-catalog cache TTL (seconds). |
228
+ | `VIDEO_POLL_MAX_CYCLES` / `VIDEO_POLL_INTERVAL_S` | `72` / `10` | Video poll budget (default 12 min). |
229
+
230
+ ## Layout
231
+
232
+ ```
233
+ extension/ Chrome MV3 bridge (open a labs.google/fx/tools/flow tab)
234
+ flow_engine/
235
+ bridge/ WS server + flow_client + flow_sdk (Flow API port)
236
+ media.py DB-free media cache (registry + on-disk bytes)
237
+ jobs.py in-memory job store + async video poller
238
+ session.py readiness gate + default project + pool seam
239
+ catalog.py model catalog (flow.projectInitialData), disk-cached
240
+ openai/ /v1/images, /v1/videos, /v1/flow/uploads, /v1/models
241
+ main.py FastAPI app, /api/ext/callback, /media/{id}, lifespan
242
+ cli/ launcher: app (argparse), supervisor, dashboard,
243
+ processes, health, config (~/.vrex-flow)
244
+ ```
245
+
246
+ ## Notes & caveats
247
+
248
+ - **Single account.** One extension instance = one Google account = one tier.
249
+ Multi-tenant needs a browser-instance pool routed by API key — the
250
+ `session.get_bridge(api_key)` indirection is where that goes.
251
+ - **Live Flow tab required.** Every dispatch solves an enterprise reCAPTCHA in
252
+ an open Flow tab; hosting needs a headful/virtual-display Chrome kept warm.
253
+ - **Signed URLs expire.** flow-engine caches bytes locally and serves stable
254
+ `/media/{id}` URLs; workflow-mode video arrives as inline base64 MP4.
255
+ - **Localhost WS is unauthenticated** by design — never bind it to a network
256
+ interface. Gate the HTTP `/v1/*` surface with `FLOW_ENGINE_API_KEY` when exposed.
257
+ - **No `.env` auto-load.** The process reads `os.environ` directly — export vars
258
+ in the shell (or a wrapper/launchd unit), don't rely on a `.env` file.
259
+ ```
@@ -0,0 +1,4 @@
1
+ """flow_engine — host a Flowboard browser-extension instance and expose
2
+ OpenAI-compatible image/video generation endpoints over Google Flow."""
3
+
4
+ __version__ = "0.0.1"
@@ -0,0 +1,6 @@
1
+ """The extension bridge: WS server + Flow client + Flow SDK.
2
+
3
+ These three modules are lifted near-verbatim from flowboard's agent. They are
4
+ intentionally free of any database / board dependency so they drop straight
5
+ into a standalone proxy. The only edits vs. the originals are the import paths.
6
+ """